<commit_before>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Nest Labs, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *          Contains non-inline method definitions for the
 *          GenericPlatformManagerImpl<> template.
 */

#ifndef GENERIC_PLATFORM_MANAGER_IMPL_CPP
#define GENERIC_PLATFORM_MANAGER_IMPL_CPP

#include <inttypes.h>
#include <new>
#include <platform/PlatformManager.h>
#include <platform/internal/BLEManager.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <platform/internal/EventLogging.h>
#include <platform/internal/GenericPlatformManagerImpl.h>

#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace DeviceLayer {

namespace Internal {

extern CHIP_ERROR InitEntropy();

template <class ImplClass>
CHIP_ERROR GenericPlatformManagerImpl<ImplClass>::_InitChipStack()
{
    CHIP_ERROR err;

    mMsgLayerWasActive = false;

    // Arrange for CHIP core errors to be translated to text
    RegisterCHIPLayerErrorFormatter();

    // Arrange for Device Layer errors to be translated to text.
    RegisterDeviceLayerErrorFormatter();

    err = InitEntropy();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Entropy initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    err = ConfigurationMgr().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Configuration Manager initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the CHIP system layer.
    err = SystemLayer().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "SystemLayer initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the CHIP Inet layer.
    err = InetLayer().Init(SystemLayer(), nullptr);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "InetLayer initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // TODO Perform dynamic configuration of the core CHIP objects based on stored settings.

    // Initialize the CHIP BLE manager.
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
    err = BLEMgr().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "BLEManager initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);
#endif

    // Initialize the Connectivity Manager object.
    err = ConnectivityMgr().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Connectivity Manager initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the NFC Manager.
#if CHIP_DEVICE_CONFIG_ENABLE_NFC
    err = NFCMgr().Init();
    VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "NFC Manager initialization failed: %s", ErrorStr(err)));
#endif

    // TODO Initialize CHIP Event Logging.

    // TODO Initialize the Time Sync Manager object.

    SuccessOrExit(err);

    // TODO Initialize the Software Update Manager object.

exit:
    return err;
}

template <class ImplClass>
CHIP_ERROR GenericPlatformManagerImpl<ImplClass>::_Shutdown()
{
    CHIP_ERROR err;
    ChipLogError(DeviceLayer, "Inet Layer shutdown");
    err = InetLayer().Shutdown();

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
    ChipLogError(DeviceLayer, "BLE layer shutdown");
    err = BLEMgr().GetBleLayer()->Shutdown();
#endif

    ChipLogError(DeviceLayer, "System Layer shutdown");
    err = SystemLayer().Shutdown();

    return err;
}

template <class ImplClass>
CHIP_ERROR GenericPlatformManagerImpl<ImplClass>::_AddEventHandler(PlatformManager::EventHandlerFunct handler, intptr_t arg)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    AppEventHandler * eventHandler;

    // Do nothing if the event handler is already registered.
    for (eventHandler = mAppEventHandlerList; eventHandler != nullptr; eventHandler = eventHandler->Next)
    {
        if (eventHandler->Handler == handler && eventHandler->Arg == arg)
        {
            ExitNow();
        }
    }

    eventHandler = (AppEventHandler *) chip::Platform::MemoryAlloc(sizeof(AppEventHandler));
    VerifyOrExit(eventHandler != nullptr, err = CHIP_ERROR_NO_MEMORY);

    eventHandler->Next    = mAppEventHandlerList;
    eventHandler->Handler = handler;
    eventHandler->Arg     = arg;

    mAppEventHandlerList = eventHandler;

exit:
    return err;
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::_RemoveEventHandler(PlatformManager::EventHandlerFunct handler, intptr_t arg)
{
    AppEventHandler ** eventHandlerIndirectPtr;

    for (eventHandlerIndirectPtr = &mAppEventHandlerList; *eventHandlerIndirectPtr != nullptr;)
    {
        AppEventHandler * eventHandler = (*eventHandlerIndirectPtr);

        if (eventHandler->Handler == handler && eventHandler->Arg == arg)
        {
            *eventHandlerIndirectPtr = eventHandler->Next;
            chip::Platform::MemoryFree(eventHandler);
        }
        else
        {
            eventHandlerIndirectPtr = &eventHandler->Next;
        }
    }
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::_ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg)
{
    ChipDeviceEvent event;
    event.Type                    = DeviceEventType::kCallWorkFunct;
    event.CallWorkFunct.WorkFunct = workFunct;
    event.CallWorkFunct.Arg       = arg;

    CHIP_ERROR status = Impl()->PostEvent(&event);
    if (status != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to schedule work: %" CHIP_ERROR_FORMAT, status.Format());
    }
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::_DispatchEvent(const ChipDeviceEvent * event)
{
#if CHIP_PROGRESS_LOGGING
    System::Clock::Timestamp start = System::SystemClock().GetMonotonicTimestamp();
#endif // CHIP_PROGRESS_LOGGING

    switch (event->Type)
    {
    case DeviceEventType::kNoOp:
        // Do nothing for no-op events.
        break;

    case DeviceEventType::kChipSystemLayerEvent:
        // If the event is a CHIP System or Inet Layer event, deliver it to the System::Layer event handler.
        Impl()->DispatchEventToSystemLayer(event);
        break;

    case DeviceEventType::kChipLambdaEvent:
        event->LambdaEvent.LambdaProxy(static_cast<const void *>(event->LambdaEvent.LambdaBody));
        break;

    case DeviceEventType::kCallWorkFunct:
        // If the event is a "call work function" event, call the specified function.
        event->CallWorkFunct.WorkFunct(event->CallWorkFunct.Arg);
        break;

    default:
        // For all other events, deliver the event to each of the components in the Device Layer.
        Impl()->DispatchEventToDeviceLayer(event);

        // If the event is not an internal event, also deliver it to the application's registered
        // event handlers.
        if (!event->IsInternal())
        {
            Impl()->DispatchEventToApplication(event);
        }

        break;
    }

    // TODO: make this configurable
#if CHIP_PROGRESS_LOGGING
    uint32_t deltaMs = System::Clock::Milliseconds32(System::SystemClock().GetMonotonicTimestamp() - start).count();
    if (deltaMs > 100)
    {
        ChipLogError(DeviceLayer, "Long dispatch time: %" PRIu32 " ms, for event type %d", deltaMs, event->Type);
    }
#endif // CHIP_PROGRESS_LOGGING
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::DispatchEventToSystemLayer(const ChipDeviceEvent * event)
{
    // TODO(#788): remove ifdef LWIP once System::Layer event APIs are generally available
#if CHIP_SYSTEM_CONFIG_USE_LWIP
    CHIP_ERROR err = CHIP_NO_ERROR;

    // Invoke the System Layer's event handler function.
    err = static_cast<System::LayerImplLwIP &>(SystemLayer())
              .HandleEvent(*event->ChipSystemLayerEvent.Target, event->ChipSystemLayerEvent.Type,
                           event->ChipSystemLayerEvent.Argument);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Error handling CHIP System Layer event (type %d): %s", event->Type, ErrorStr(err));
    }
#endif
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::DispatchEventToDeviceLayer(const ChipDeviceEvent * event)
{
    // Dispatch the event to all the components in the Device Layer.
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
    BLEMgr().OnPlatformEvent(event);
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
    ThreadStackMgr().OnPlatformEvent(event);
#endif
    ConnectivityMgr().OnPlatformEvent(event);
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::DispatchEventToApplication(const ChipDeviceEvent * event)
{
    // Dispatch the event to each of the registered application event handlers.
    for (AppEventHandler * eventHandler = mAppEventHandlerList; eventHandler != nullptr; eventHandler = eventHandler->Next)
    {
        eventHandler->Handler(event, eventHandler->Arg);
    }
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::HandleMessageLayerActivityChanged(bool messageLayerIsActive)
{
    GenericPlatformManagerImpl<ImplClass> & self = PlatformMgrImpl();

    if (messageLayerIsActive != self.mMsgLayerWasActive)
    {
        self.mMsgLayerWasActive = messageLayerIsActive;

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
        ThreadStackMgr().OnMessageLayerActivityChanged(messageLayerIsActive);
#endif
    }
}

// Fully instantiate the generic implementation class in whatever compilation unit includes this file.
template class GenericPlatformManagerImpl<PlatformManagerImpl>;

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip

#endif // GENERIC_PLATFORM_MANAGER_IMPL_CPP
<commit_msg>Fix _InitChipStack() initialization order. (#11374)<commit_after>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Nest Labs, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *          Contains non-inline method definitions for the
 *          GenericPlatformManagerImpl<> template.
 */

#ifndef GENERIC_PLATFORM_MANAGER_IMPL_CPP
#define GENERIC_PLATFORM_MANAGER_IMPL_CPP

#include <inttypes.h>
#include <new>
#include <platform/PlatformManager.h>
#include <platform/internal/BLEManager.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <platform/internal/EventLogging.h>
#include <platform/internal/GenericPlatformManagerImpl.h>

#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace DeviceLayer {

namespace Internal {

extern CHIP_ERROR InitEntropy();

template <class ImplClass>
CHIP_ERROR GenericPlatformManagerImpl<ImplClass>::_InitChipStack()
{
    CHIP_ERROR err;

    mMsgLayerWasActive = false;

    // Arrange for CHIP core errors to be translated to text
    RegisterCHIPLayerErrorFormatter();

    // Arrange for Device Layer errors to be translated to text.
    RegisterDeviceLayerErrorFormatter();

    err = InitEntropy();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Entropy initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the CHIP system layer.
    err = SystemLayer().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "SystemLayer initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the Configuration Manager.
    err = ConfigurationMgr().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Configuration Manager initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the CHIP Inet layer.
    err = InetLayer().Init(SystemLayer(), nullptr);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "InetLayer initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // TODO Perform dynamic configuration of the core CHIP objects based on stored settings.

    // Initialize the CHIP BLE manager.
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
    err = BLEMgr().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "BLEManager initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);
#endif

    // Initialize the Connectivity Manager object.
    err = ConnectivityMgr().Init();
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Connectivity Manager initialization failed: %s", ErrorStr(err));
    }
    SuccessOrExit(err);

    // Initialize the NFC Manager.
#if CHIP_DEVICE_CONFIG_ENABLE_NFC
    err = NFCMgr().Init();
    VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "NFC Manager initialization failed: %s", ErrorStr(err)));
#endif

    // TODO Initialize CHIP Event Logging.

    // TODO Initialize the Time Sync Manager object.

    SuccessOrExit(err);

    // TODO Initialize the Software Update Manager object.

exit:
    return err;
}

template <class ImplClass>
CHIP_ERROR GenericPlatformManagerImpl<ImplClass>::_Shutdown()
{
    CHIP_ERROR err;
    ChipLogError(DeviceLayer, "Inet Layer shutdown");
    err = InetLayer().Shutdown();

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
    ChipLogError(DeviceLayer, "BLE layer shutdown");
    err = BLEMgr().GetBleLayer()->Shutdown();
#endif

    ChipLogError(DeviceLayer, "System Layer shutdown");
    err = SystemLayer().Shutdown();

    return err;
}

template <class ImplClass>
CHIP_ERROR GenericPlatformManagerImpl<ImplClass>::_AddEventHandler(PlatformManager::EventHandlerFunct handler, intptr_t arg)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    AppEventHandler * eventHandler;

    // Do nothing if the event handler is already registered.
    for (eventHandler = mAppEventHandlerList; eventHandler != nullptr; eventHandler = eventHandler->Next)
    {
        if (eventHandler->Handler == handler && eventHandler->Arg == arg)
        {
            ExitNow();
        }
    }

    eventHandler = (AppEventHandler *) chip::Platform::MemoryAlloc(sizeof(AppEventHandler));
    VerifyOrExit(eventHandler != nullptr, err = CHIP_ERROR_NO_MEMORY);

    eventHandler->Next    = mAppEventHandlerList;
    eventHandler->Handler = handler;
    eventHandler->Arg     = arg;

    mAppEventHandlerList = eventHandler;

exit:
    return err;
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::_RemoveEventHandler(PlatformManager::EventHandlerFunct handler, intptr_t arg)
{
    AppEventHandler ** eventHandlerIndirectPtr;

    for (eventHandlerIndirectPtr = &mAppEventHandlerList; *eventHandlerIndirectPtr != nullptr;)
    {
        AppEventHandler * eventHandler = (*eventHandlerIndirectPtr);

        if (eventHandler->Handler == handler && eventHandler->Arg == arg)
        {
            *eventHandlerIndirectPtr = eventHandler->Next;
            chip::Platform::MemoryFree(eventHandler);
        }
        else
        {
            eventHandlerIndirectPtr = &eventHandler->Next;
        }
    }
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::_ScheduleWork(AsyncWorkFunct workFunct, intptr_t arg)
{
    ChipDeviceEvent event;
    event.Type                    = DeviceEventType::kCallWorkFunct;
    event.CallWorkFunct.WorkFunct = workFunct;
    event.CallWorkFunct.Arg       = arg;

    CHIP_ERROR status = Impl()->PostEvent(&event);
    if (status != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to schedule work: %" CHIP_ERROR_FORMAT, status.Format());
    }
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::_DispatchEvent(const ChipDeviceEvent * event)
{
#if CHIP_PROGRESS_LOGGING
    System::Clock::Timestamp start = System::SystemClock().GetMonotonicTimestamp();
#endif // CHIP_PROGRESS_LOGGING

    switch (event->Type)
    {
    case DeviceEventType::kNoOp:
        // Do nothing for no-op events.
        break;

    case DeviceEventType::kChipSystemLayerEvent:
        // If the event is a CHIP System or Inet Layer event, deliver it to the System::Layer event handler.
        Impl()->DispatchEventToSystemLayer(event);
        break;

    case DeviceEventType::kChipLambdaEvent:
        event->LambdaEvent.LambdaProxy(static_cast<const void *>(event->LambdaEvent.LambdaBody));
        break;

    case DeviceEventType::kCallWorkFunct:
        // If the event is a "call work function" event, call the specified function.
        event->CallWorkFunct.WorkFunct(event->CallWorkFunct.Arg);
        break;

    default:
        // For all other events, deliver the event to each of the components in the Device Layer.
        Impl()->DispatchEventToDeviceLayer(event);

        // If the event is not an internal event, also deliver it to the application's registered
        // event handlers.
        if (!event->IsInternal())
        {
            Impl()->DispatchEventToApplication(event);
        }

        break;
    }

    // TODO: make this configurable
#if CHIP_PROGRESS_LOGGING
    uint32_t deltaMs = System::Clock::Milliseconds32(System::SystemClock().GetMonotonicTimestamp() - start).count();
    if (deltaMs > 100)
    {
        ChipLogError(DeviceLayer, "Long dispatch time: %" PRIu32 " ms, for event type %d", deltaMs, event->Type);
    }
#endif // CHIP_PROGRESS_LOGGING
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::DispatchEventToSystemLayer(const ChipDeviceEvent * event)
{
    // TODO(#788): remove ifdef LWIP once System::Layer event APIs are generally available
#if CHIP_SYSTEM_CONFIG_USE_LWIP
    CHIP_ERROR err = CHIP_NO_ERROR;

    // Invoke the System Layer's event handler function.
    err = static_cast<System::LayerImplLwIP &>(SystemLayer())
              .HandleEvent(*event->ChipSystemLayerEvent.Target, event->ChipSystemLayerEvent.Type,
                           event->ChipSystemLayerEvent.Argument);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Error handling CHIP System Layer event (type %d): %s", event->Type, ErrorStr(err));
    }
#endif
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::DispatchEventToDeviceLayer(const ChipDeviceEvent * event)
{
    // Dispatch the event to all the components in the Device Layer.
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
    BLEMgr().OnPlatformEvent(event);
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
    ThreadStackMgr().OnPlatformEvent(event);
#endif
    ConnectivityMgr().OnPlatformEvent(event);
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::DispatchEventToApplication(const ChipDeviceEvent * event)
{
    // Dispatch the event to each of the registered application event handlers.
    for (AppEventHandler * eventHandler = mAppEventHandlerList; eventHandler != nullptr; eventHandler = eventHandler->Next)
    {
        eventHandler->Handler(event, eventHandler->Arg);
    }
}

template <class ImplClass>
void GenericPlatformManagerImpl<ImplClass>::HandleMessageLayerActivityChanged(bool messageLayerIsActive)
{
    GenericPlatformManagerImpl<ImplClass> & self = PlatformMgrImpl();

    if (messageLayerIsActive != self.mMsgLayerWasActive)
    {
        self.mMsgLayerWasActive = messageLayerIsActive;

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
        ThreadStackMgr().OnMessageLayerActivityChanged(messageLayerIsActive);
#endif
    }
}

// Fully instantiate the generic implementation class in whatever compilation unit includes this file.
template class GenericPlatformManagerImpl<PlatformManagerImpl>;

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip

#endif // GENERIC_PLATFORM_MANAGER_IMPL_CPP
<|endoftext|>


<commit_before>/*
 * This file is part of the libefgy project.
*/

/*
 * Copyright (c) 2012-2013, ef.gy Project Members
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

#include <iostream>

#include <ef.gy/fractions.h>
#include <ef.gy/continued-fractions.h>
#include <cstdlib>

using namespace efgy::math;

numeric::continuedFractional<number> apply
    (const numeric::continuedFractional<number> &cf,
     const char &op,
     const number &n)
{
    switch (op)
    {
        case 0:
            return n;
        case '+':
            return cf+n;
        case '-':
            return cf-n;
        case '*':
            return cf*n;
        case '/':
            return cf/n;
        case ',':
            return (cf,n);
        default:
            throw std::exception();
    }
}

int main (int argc, char* argv[])
{
    try
    {
        for (int i = 1; i < argc; i++)
        {
            numeric::continuedFractional<number> res;
            std::string arg;
            number n;
            char op = 0;

            for (int j = 0; argv[i][j]; j++)
            {
                switch (argv[i][j])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        arg += std::string(1, argv[i][j]);
                        break;
                    case '-':
                    case '+':
                        if (arg.size() == 0)
                        {
                            arg += std::string(1, argv[i][j]);
                            break;
                        }
                    case '*':
                    case '/':
                    case ',':
                        op = argv[i][j];
                        n = std::atoi(arg.c_str());
                        arg = std::string();
                        res = apply (res, op, n);
                        break;
                }
            }

            if (arg.size() > 0)
            {
                n = std::atoi(arg.c_str());
                arg = std::string();
                res = apply (res, op, n);
            }

            std::cerr << std::string(res) << " = " << std::string(numeric::fractional<number>(res)) << "\n";
        }
    }
    catch (std::exception &e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }
    catch (...)
    {
        std::cerr << "Unknown Exception\n";
    }

    return 0;
}
<commit_msg>properly test basic arithmetic with continued fractions<commit_after>/*
 * This file is part of the libefgy project.
*/

/*
 * Copyright (c) 2012-2013, ef.gy Project Members
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

#include <iostream>

#include <ef.gy/fractions.h>
#include <ef.gy/continued-fractions.h>

using namespace efgy::math;
using namespace std;

int main (int argc, char **argv)
{
    try
    {
        numeric::fractional<number> af(6,11), bf(4,5), rf;
        numeric::continuedFractional<number> a(af), b(bf), r;

        rf = af + bf;
        cerr << string(af) << " + " << string(bf) << " = " << string(rf) << "\n";

        r = a + b;
        rf = r;
        cerr << string(a)  << " + " << string(b)  << " = " << string(r)  << " = " << string(rf) << "\n";

        if (rf != r)
        {
            return 1;
        }

        rf = af - bf;
        cerr << string(af) << " - " << string(bf) << " = " << string(rf) << "\n";

        r = a - b;
        rf = r;
        cerr << string(a)  << " - " << string(b)  << " = " << string(r)  << " = " << string(rf) << "\n";

        if (rf != r)
        {
            return 2;
        }

        rf = af * bf;
        cerr << string(af) << " * " << string(bf) << " = " << string(rf) << "\n";

        r = a * b;
        rf = r;
        cerr << string(a)  << " * " << string(b)  << " = " << string(r)  << " = " << string(rf) << "\n";

        if (rf != r)
        {
            return 3;
        }

        rf = af / bf;
        cerr << string(af) << " / " << string(bf) << " = " << string(rf) << "\n";

        r = a + b;
        rf = r;
        cerr << string(a)  << " / " << string(b)  << " = " << string(r)  << " = " << string(rf) << "\n";

        if (rf != r)
        {
            return 4;
        }
    }
    catch (exception &e)
    {
        cerr << "Exception: " << e.what() << "\n";
        return -1;
    }
    catch (...)
    {
        cerr << "Unknown Exception\n";
        return -1;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){

	// init logs
	ofSetLogLevel(OF_LOG_VERBOSE);
	ofLogVerbose() << "setup started";

	// init scene objects
	timeElapsed = 0;
	currentIndex = 1;

    for (int i = 0; i < SEGMENTS_STORED; ++i) {
        ceilHeights[i] = floorHeights[i] = 0;
		earthline[i] = skyline[i] = ofRectangle(0,0,0,0);
    }

	gameField = paddingTop = paddingBottom =
		ofRectangle(0,0,0,0);

	viewPort = ofGetCurrentViewport();

	// init vertical sync and some graphics
	ofSetVerticalSync(true);
	ofSetCircleResolution(80);
	ofBackground(47, 52, 64);

	// init audio
	soundStream.listDevices();

	fft = ofxFft::create(AUDIO_BUFFER_SIZE);

	left.assign(AUDIO_BUFFER_SIZE, 0.0);
	right.assign(AUDIO_BUFFER_SIZE, 0.0);

	soundStream.setup(this, 0, 2, 44100, AUDIO_BUFFER_SIZE, 4);
	audioInput = new float[AUDIO_BUFFER_SIZE];
	fftOutput = new float[fft->getBinSize()];
	ifftOutput = new float[AUDIO_BUFFER_SIZE];

	// seed random
	ofSeedRandom();

	ofLogVerbose() << "setup finished";
}

//--------------------------------------------------------------
void testApp::update(){
    unsigned long long now = ofGetElapsedTimeMillis();
	float dt = (now - timeElapsed) / 1000.0f;
	timeElapsed = now;

	// update scene

	//offset in segments
	float beginOffset = MOVEMENT_SPEED * timeElapsed / 1000.0f;

	if (viewPort.width == 0 || viewPort.height == 0) {
		return;
	}

	gameField = viewPort;

	gameField.height = viewPort.width / VIEWPORT_ASPECT;
	gameField.y = (viewPort.height - gameField.height) / 2;
	float segmentWidth = ceil(gameField.width / SEGMENTS_PER_VIEWPORT);

	if (paddingTop.width == 0) {
		paddingTop = ofRectangle(0, 0, viewPort.width, gameField.y);
	}
	if (paddingBottom.width == 0) {
		paddingBottom = ofRectangle(0, viewPort.height - gameField.y, viewPort.width, gameField.y);
	}

	float maxSegmentHeight = gameField.height * SEGMENT_MAX_HEIGHT_PART;
	float minSegmentHeight = maxSegmentHeight / 2;

	// current offset in segments
	float offset = beginOffset - currentIndex;

	for (int i = 0; i < SEGMENTS_STORED; ++i) {
	    if (ceilHeights[i] == 0) {// generate hights
            ceilHeights[i] = ofRandom(minSegmentHeight, maxSegmentHeight);
            floorHeights[i] = ofRandom(minSegmentHeight, maxSegmentHeight);
	    }

		if (skyline[i].width == 0) { // generate rectangles
            float startX = i==0 ? 0 : skyline[i-1].x + segmentWidth;

            skyline[i] = ofRectangle(startX, gameField.y, segmentWidth, ceilHeights[i]);
            earthline[i] = ofRectangle(startX, gameField.y + gameField.height - floorHeights[i],
                                       segmentWidth, floorHeights[i]);
		}
	    else {
			earthline[i].x = skyline[i].x = (i - offset) * segmentWidth ;

            if (skyline[i].x < -segmentWidth) {
                moveSegments(i);
            }
	    }
	}

	moveSegments(floor(beginOffset) - currentIndex);
	currentIndex = floor(beginOffset);
}

//--------------------------------------------------------------
void testApp::moveSegments(int count) {

	if (count <= 0) {
		return;
	}

	for (int i = 0; i < SEGMENTS_STORED - count; ++i) {
		ceilHeights[i] = ceilHeights[i + count];
		floorHeights[i] = floorHeights[i + count];

		skyline[i] = skyline[i + count];
		earthline[i] = earthline[i + count];
	}

	for (int i = SEGMENTS_STORED - count; i < SEGMENTS_STORED; i++)
	{
		floorHeights[i] = ceilHeights[i] = 0;
		earthline[i] = skyline[i] = ofRectangle(0,0,0,0);
	}
}

//--------------------------------------------------------------
void testApp::draw(){
	drawScene();

	plotFft();
}

//--------------------------------------------------------------
void testApp::drawScene() {

	ofSetColor(63, 83, 140);
    ofFill();

	ofRect(paddingTop);
	ofRect(paddingBottom);

	for (int i = 0; i < SEGMENTS_STORED; ++i) {
		ofRect(skyline[i]);
		ofRect(earthline[i]);
	}

	ofSetColor(255, 85, 84);
    ofFill();
	ofCircle(viewPort.width * 0.3, viewPort.height * 0.5, viewPort.width * 0.03);
}

//--------------------------------------------------------------
void testApp::plotFft() {
	ofRectangle area = ofRectangle(0,0, gameField.width, gameField.y);
	int count = fft->getBinSize();
	int lineHeight = 3;

	ofSetColor(221, 221, 227);
	ofSetLineWidth(lineHeight);

	for (int i = 0; i < count; i++)
	{
		float height = fftOutput[i] * 10000;
		float x = i * lineHeight * 2 + lineHeight;
		ofLine(x, 0, x, height);
	}
}

//--------------------------------------------------------------
void testApp::audioIn(float * input, int bufferSize, int nChannels){

	//lets go through each sample and calculate the root mean square which is a rough way to calculate volume
	for (int i = 0; i < bufferSize; i++){
		left[i]		= input[i*2]*0.5;
		right[i]	= input[i*2+1]*0.5;
	}

	memcpy(audioInput, input, sizeof(float) * bufferSize);

	fft->setSignal(audioInput);
	memcpy(fftOutput, fft->getAmplitude(), sizeof(float) * fft->getBinSize());

	float maxAmp = 0.0f;
	for (int i = 0; i < fft->getBinSize()-1; i++)
	{
		maxAmp = max(maxAmp, fftOutput[i]);
	}

	/*for (int i = 0; i < fft->getBinSize()-1; i++)
	{
		fftOutput[i] /= maxAmp;
	}*/

	fft->clampSignal();
	memcpy(ifftOutput, fft->getSignal(), sizeof(float) * fft->getSignalSize());
}

//--------------------------------------------------------------
void testApp::keyPressed  (int key){
	if( key == 's' ){
		soundStream.start();
	}

	if( key == 'e' ){
		soundStream.stop();
	}
}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
	for (int i = 0; i < SEGMENTS_STORED; ++i) {
		skyline[i] = ofRectangle(0,0,0,0);
		earthline[i] = ofRectangle(0,0,0,0);
	}

	paddingTop = paddingBottom = ofRectangle(0,0,0,0);

	viewPort.width = w;
	viewPort.height = h;
}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>Refinements<commit_after>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){

	// init logs
	ofSetLogLevel(OF_LOG_VERBOSE);
	ofLogVerbose() << "setup started";

	// init scene objects
	timeElapsed = 0;
	currentIndex = 1;

    for (int i = 0; i < SEGMENTS_STORED; ++i) {
        ceilHeights[i] = floorHeights[i] = 0;
		earthline[i] = skyline[i] = ofRectangle(0,0,0,0);
    }

	gameField = paddingTop = paddingBottom =
		ofRectangle(0,0,0,0);

	viewPort = ofGetCurrentViewport();

	// init vertical sync and some graphics
	ofSetVerticalSync(true);
	ofSetCircleResolution(80);
	ofBackground(47, 52, 64);

	// init audio
	soundStream.listDevices();

	fft = ofxFft::create(AUDIO_BUFFER_SIZE);

	left.assign(AUDIO_BUFFER_SIZE, 0.0);
	right.assign(AUDIO_BUFFER_SIZE, 0.0);

	soundStream.setup(this, 0, 2, 44100, AUDIO_BUFFER_SIZE, 4);
	audioInput = new float[AUDIO_BUFFER_SIZE];
	fftOutput = new float[fft->getBinSize()];
	ifftOutput = new float[AUDIO_BUFFER_SIZE];

	// seed random
	ofSeedRandom();

	ofLogVerbose() << "setup finished";
}

//--------------------------------------------------------------
void testApp::update(){
    unsigned long long now = ofGetElapsedTimeMillis();
	float dt = (now - timeElapsed) / 1000.0f;
	timeElapsed = now;

	// update scene

	//offset in segments
	float beginOffset = MOVEMENT_SPEED * timeElapsed / 1000.0f;

	if (viewPort.width == 0 || viewPort.height == 0) {
		return;
	}

	gameField = viewPort;

	gameField.height = viewPort.width / VIEWPORT_ASPECT;
	gameField.y = (viewPort.height - gameField.height) / 2;
	float segmentWidth = ceil(gameField.width / SEGMENTS_PER_VIEWPORT);

	if (paddingTop.width == 0) {
		paddingTop = ofRectangle(0, 0, viewPort.width, gameField.y);
	}
	if (paddingBottom.width == 0) {
		paddingBottom = ofRectangle(0, viewPort.height - gameField.y, viewPort.width, gameField.y);
	}

	float maxSegmentHeight = gameField.height * SEGMENT_MAX_HEIGHT_PART;
	float minSegmentHeight = maxSegmentHeight / 2;

	// current offset in segments
	float offset = beginOffset - currentIndex;

	for (int i = 0; i < SEGMENTS_STORED; ++i) {
	    if (ceilHeights[i] == 0) {// generate hights
            ceilHeights[i] = ofRandom(minSegmentHeight, maxSegmentHeight);
            floorHeights[i] = ofRandom(minSegmentHeight, maxSegmentHeight);
	    }

		if (skyline[i].width == 0) { // generate rectangles
            float startX = i==0 ? 0 : skyline[i-1].x + segmentWidth;

            skyline[i] = ofRectangle(startX, gameField.y, segmentWidth, ceilHeights[i]);
            earthline[i] = ofRectangle(startX, gameField.y + gameField.height - floorHeights[i],
                                       segmentWidth, floorHeights[i]);
		}
	    else {
			earthline[i].x = skyline[i].x = (i - offset) * segmentWidth ;

            if (skyline[i].x < -segmentWidth) {
                moveSegments(i);
            }
	    }
	}

	moveSegments(floor(beginOffset) - currentIndex);
	currentIndex = floor(beginOffset);
}

//--------------------------------------------------------------
void testApp::moveSegments(int count) {

	if (count <= 0) {
		return;
	}

	for (int i = 0; i < SEGMENTS_STORED - count; ++i) {
		ceilHeights[i] = ceilHeights[i + count];
		floorHeights[i] = floorHeights[i + count];

		skyline[i] = skyline[i + count];
		earthline[i] = earthline[i + count];
	}

	for (int i = SEGMENTS_STORED - count; i < SEGMENTS_STORED; i++)
	{
		floorHeights[i] = ceilHeights[i] = 0;
		earthline[i] = skyline[i] = ofRectangle(0,0,0,0);
	}
}

//--------------------------------------------------------------
void testApp::draw(){
	drawScene();

	plotFft();
}

//--------------------------------------------------------------
void testApp::drawScene() {

	ofSetColor(63, 83, 140);
    ofFill();

	ofRect(paddingTop);
	ofRect(paddingBottom);

	for (int i = 0; i < SEGMENTS_STORED; ++i) {
		ofRect(skyline[i]);
		ofRect(earthline[i]);
	}

	ofSetColor(255, 85, 84);
    ofFill();
	ofCircle(viewPort.width * 0.3, viewPort.height * 0.5, viewPort.width * 0.03);
}

//--------------------------------------------------------------
void testApp::plotFft() {
	ofRectangle area = ofRectangle(0,0, gameField.width, gameField.y);
	int count = fft->getBinSize();
	int lineHeight = 2;

	ofSetColor(221, 221, 227);
	ofSetLineWidth(lineHeight);

	float maxAmp = 0.0f;
	int maxIndex = -1;
	for (int i = 0; i < count; i++)
	{
		if (maxAmp >= fftOutput[i])
			continue;

		maxAmp = fftOutput[i];
		maxIndex = i;
	}

	for (int i = 0; i < count; i++)
	{
		float gated = max(0.0f, fftOutput[i] - maxAmp * 0.2f);
		float height = gated * 10000;
		float x = i * lineHeight * 2 + lineHeight;
		ofLine(x, 0, x, height);
	}

	ofSetColor(255, 85, 84);
	ofDrawBitmapString(ofToString(maxAmp) + " at " + ofToString(maxIndex), 10, viewPort.height - 10);
}

//--------------------------------------------------------------
void testApp::audioIn(float * input, int bufferSize, int nChannels){

	for (int i = 0; i < bufferSize; i++){
		left[i]		= input[i*2];
		right[i]	= input[i*2+1];
	}

	memcpy(audioInput, left.data(), sizeof(float) * bufferSize);

	fft->setSignal(audioInput);
	memcpy(fftOutput, fft->getAmplitude(), sizeof(float) * fft->getBinSize());

	fft->clampSignal();
	memcpy(ifftOutput, fft->getSignal(), sizeof(float) * fft->getSignalSize());
}

//--------------------------------------------------------------
void testApp::keyPressed  (int key){
	if( key == 's' ){
		soundStream.start();
	}

	if( key == 'e' ){
		soundStream.stop();
	}
}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
	for (int i = 0; i < SEGMENTS_STORED; ++i) {
		skyline[i] = ofRectangle(0,0,0,0);
		earthline[i] = ofRectangle(0,0,0,0);
	}

	paddingTop = paddingBottom = ofRectangle(0,0,0,0);

	viewPort.width = w;
	viewPort.height = h;
}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
    ofBackground(0,0,0);
    ofSetBackgroundAuto(false);
    isFullScreen = false;
    ofSetFrameRate(30);

    masterCounter = 0;
    direction = 1; //count up

    // OSC STUFF
    receiver.setup(PORT);
    mainMix = 0;
    chan01, chan02, chan03, chan04, chan05, chan06, chan07 = 0;
}

//--------------------------------------------------------------
void testApp::update(){

	// check for waiting messages
	while(receiver.hasWaitingMessages()){
		// get the next message
		ofxOscMessage m;
		receiver.getNextMessage(&m);

		// check for mouse moved message
		if(m.getAddress() == "/main/mix"){
			// both the arguments are int32's
			mainMix = m.getArgAsFloat(0);
            ofLogNotice("mainMix: "+ofToString(m.getArgAsFloat(0)));
		}
        else if (m.getAddress() == "/main/chan/one") {
            chan01 = m.getArgAsFloat(0);
            if (chan01 < 1) { //stop the weird numbers
                ofLogNotice("chan/one: "+ofToString(chan01));
            }
        }
        else if (m.getAddress() == "/main/chan/two") {
            chan02 = m.getArgAsFloat(0);
            ofLogNotice("two "+ofToString(chan02));
        }
        else if (m.getAddress() == "/main/chan/three") {
            chan03 = m.getArgAsFloat(0);
            ofLogNotice("tthree "+ofToString(chan03));
        }
        else if (m.getAddress() == "/main/chan/four") {
            chan04 = m.getArgAsFloat(0);
            ofLogNotice("four: "+ofToString(chan04));
        }
        else if (m.getAddress() == "/main/chan/five") {
            chan05 = m.getArgAsFloat(0);
            ofLogNotice("five: "+ofToString(chan05));
        }
        else if (m.getAddress() == "/main/chan/six") {
            chan06 = m.getArgAsFloat(0);
            ofLogNotice("six"+ofToString(chan06));
        }
        else if (m.getAddress() == "/main/chan/seven") {
            chan07 = m.getArgAsFloat(0);
            ofLogNotice("tseven "+ofToString(chan07));
        }
	}

    // FUN STUFF
    masterCounter+=direction;
    if (masterCounter > 2000) {
        direction = -1;
    }
    if (masterCounter < -2000) {
        direction = 1;
    }

}

//--------------------------------------------------------------
void testApp::draw(){
    //normalize mouse (within the window space...
    float daMouseX = float(mouseX)/float(ofGetWidth());
    float daMouseY = float(mouseY)/ofGetHeight();
   // ofLogNotice(ofToString(daMouseX));

    //Abstract line stuff
    for (int i = 0; i < ofGetWidth(); i++) {

        // set the color for each line
        int r = daMouseX*sin(masterCounter)/4;
        int g = i/4;
        int b = daMouseX*daMouseY*i/4;

        // line start and destination
        int xStart = i;
        int yStart = ofGetHeight()/2;
        int xDest = i*sin(i)*mouseY;
        int yDest = i*cos(i)*masterCounter*mainMix;

        //shake the signal
        if (masterCounter%2 == 0) {
            yStart += mainMix*10;
            xDest += xDest*mainMix;
            yDest += yDest*mainMix;
        }
        else {
           yStart -= mainMix*10;
            xDest -= xDest*mainMix;
            yDest -= yDest*mainMix;

        }

        ofSetColor(r, g, b); //Replace this with pixel colors from feed
         ofLine(xStart, yStart, xDest, yDest);    }

}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if (key == 'f' || 'F') {
        isFullScreen = !isFullScreen;
        ofSetFullscreen(isFullScreen);
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>xDest -> hardcoded to 400 instead of mouseY<commit_after>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
    ofBackground(0,0,0);
    ofSetBackgroundAuto(false);
    isFullScreen = false;
    ofSetFrameRate(30);

    masterCounter = 0;
    direction = 1; //count up

    // OSC STUFF
    receiver.setup(PORT);
    mainMix = 0;
    chan01, chan02, chan03, chan04, chan05, chan06, chan07 = 0;
}

//--------------------------------------------------------------
void testApp::update(){

	// check for waiting messages
	while(receiver.hasWaitingMessages()){
		// get the next message
		ofxOscMessage m;
		receiver.getNextMessage(&m);

		// check for mouse moved message
		if(m.getAddress() == "/main/mix"){
			// both the arguments are int32's
			mainMix = m.getArgAsFloat(0);
            ofLogNotice("mainMix: "+ofToString(m.getArgAsFloat(0)));
		}
        else if (m.getAddress() == "/main/chan/one") {
            chan01 = m.getArgAsFloat(0);
            if (chan01 < 1) { //stop the weird numbers
                ofLogNotice("chan/one: "+ofToString(chan01));
            }
        }
        else if (m.getAddress() == "/main/chan/two") {
            chan02 = m.getArgAsFloat(0);
            ofLogNotice("two "+ofToString(chan02));
        }
        else if (m.getAddress() == "/main/chan/three") {
            chan03 = m.getArgAsFloat(0);
            ofLogNotice("tthree "+ofToString(chan03));
        }
        else if (m.getAddress() == "/main/chan/four") {
            chan04 = m.getArgAsFloat(0);
            ofLogNotice("four: "+ofToString(chan04));
        }
        else if (m.getAddress() == "/main/chan/five") {
            chan05 = m.getArgAsFloat(0);
            ofLogNotice("five: "+ofToString(chan05));
        }
        else if (m.getAddress() == "/main/chan/six") {
            chan06 = m.getArgAsFloat(0);
            ofLogNotice("six"+ofToString(chan06));
        }
        else if (m.getAddress() == "/main/chan/seven") {
            chan07 = m.getArgAsFloat(0);
            ofLogNotice("tseven "+ofToString(chan07));
        }
	}

    // FUN STUFF
    masterCounter+=direction;
    if (masterCounter > 2000) {
        direction = -1;
    }
    if (masterCounter < -2000) {
        direction = 1;
    }

}

//--------------------------------------------------------------
void testApp::draw(){
    //normalize mouse (within the window space...
    float daMouseX = float(mouseX)/float(ofGetWidth());
    float daMouseY = float(mouseY)/float(ofGetHeight());
   // ofLogNotice(ofToString(daMouseX));

    //Abstract line stuff
    for (int i = 0; i < ofGetWidth(); i++) {

        // set the color for each line
        int r = daMouseX*sin(masterCounter)/4;
        int g = i/4;
        int b = daMouseX*daMouseY*i/4;

        // line start and destination
        int xStart = i;
        int yStart = ofGetHeight()/2;
        int xDest = i*sin(i)*400; //400 is arbitrary.
        int yDest = i*cos(i)*masterCounter*mainMix;

        //shake the signal
        if (masterCounter%2 == 0) {
            yStart += mainMix*10;
            xDest += xDest*mainMix;
            yDest += yDest*mainMix;
        }
        else {
           yStart -= mainMix*10;
            xDest -= xDest*mainMix;
            yDest -= yDest*mainMix;

        }

        ofSetColor(r, g, b); //Replace this with pixel colors from feed
         ofLine(xStart, yStart, xDest, yDest);    }

}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if (key == 'f' || 'F') {
        isFullScreen = !isFullScreen;
        ofSetFullscreen(isFullScreen);
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>/*
 * Copyright 2013-2016 Christian Lockley
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
#define _DEFAULT_SOURCE
#include <libgen.h>
#include "watchdogd.hpp"
#include "sub.hpp"
#include <dirent.h>
#include <semaphore.h>
#include "testdir.hpp"
#include "exe.hpp"
#include "repair.hpp"
#include <sys/eventfd.h>
#include "threadpool.hpp"
#include "futex.hpp"
#include "logutils.hpp"
#include <sys/ipc.h>
#include <sys/shm.h>

static std::atomic_int sem = {0};
unsigned long numberOfRepairScripts = 0;

static void DeleteDuplicates(ProcessList * p)
{
	if (!p)
		return;

	if (list_is_empty(&p->head))
		return;

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		repaircmd_t *b = NULL;
		repaircmd_t *next2 = NULL;
		++numberOfRepairScripts;
		if (c->legacy) {
			list_for_each_entry(b, next2, &p->head, entry) {
				if (!b->legacy) {
					if (strcmp(c->path, b->path) == 0) {
						--numberOfRepairScripts;
						Logmsg(LOG_INFO, "Using configuration info for %s script", b->path);
						list_del(&c->entry);
						free((void *)c->path);
						free((void *)c);
					}
				}
			}
		}
	}
}

int CreateLinkedListOfExes(char *repairScriptFolder, ProcessList * p,
			   struct cfgoptions *const config)
{
	assert(p != NULL);
	assert(repairScriptFolder != NULL);

	struct stat buffer;
	struct dirent *ent = NULL;

	list_init(&p->head);

	int fd = open(repairScriptFolder, O_DIRECTORY | O_RDONLY);

	if (fd == -1) {
		if (!(IDENTIFY & config->options)) {
			fprintf(stderr, "watchdogd: %s: %s\n", repairScriptFolder,
				MyStrerror(errno));
		}

		if (config->options & FORCE || config->options & SOFTBOOT || config->haveConfigFile == false) {
			return 0;
		}

		return 1;
	}

	DIR *dir = fdopendir(fd);

	if (dir == NULL) {
		Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
		close(fd);
		return -1;
	}

	errno = 0;

	while ((ent = readdir(dir)) != NULL) {

		int statfd = dirfd(dir);

		if (statfd == -1) {
			goto error;
		}

		if (strchr(".", ent->d_name[0]) != NULL && !(config->options & FORCE)) {
			continue;
		}

		if (fstatat(statfd, ent->d_name, &buffer, 0) < 0)
			continue;

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}

			if (!(buffer.st_mode & S_IXUSR))
				continue;

			if (!(buffer.st_mode & S_IRUSR))
				continue;
		} else {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}
		}

		repaircmd_t *cmd = (repaircmd_t *) calloc(1, sizeof(*cmd));

		if (cmd == NULL) {
			goto error;
		}

		for (size_t i = 0; i < strlen(repairScriptFolder); i += 1) {
			if (repairScriptFolder[i] == '/' && i < strlen(repairScriptFolder)
			    && repairScriptFolder[i+1] == '\0') {
				repairScriptFolder[i] = '\0';
			}
		}

		Wasprintf((char **)&cmd->path, "%s/%s", repairScriptFolder, ent->d_name);

		if (cmd->path == NULL) {
			assert(cmd != NULL);
			free(cmd);
			goto error;
		}

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			cmd->legacy = true;
		} else {
			//For V3 repair scripts cmd->path refers to the pathname of the repair script config file
			if (LoadRepairScriptLink
			    (&cmd->spawnattr, (char *)cmd->path) == false) {
				free((void *)cmd->path);
				free(cmd);
				continue;
			}

			cmd->spawnattr.repairFilePathname = strdup(cmd->path);
			free((void *)cmd->path);
			cmd->path = NULL;
			cmd->path = cmd->spawnattr.execStart;

			char * rel = basename(strdup(cmd->path));

			if (strcmp(rel, cmd->path) == 0) {
				free((void*)rel);
				Wasprintf((char **)&rel, "%s/%s", repairScriptFolder, cmd->path);
				free((void*)cmd->path);
				cmd->path = cmd->spawnattr.execStart = rel;
			}

			if (cmd->path == NULL) {
				fprintf(stderr,
					"Ignoring malformed repair file: %s\n",
					ent->d_name);
				free(cmd);
				continue;
			}

			if (fd < 0) {
				fprintf(stderr, "unable to open file %s:\n",
					MyStrerror(errno));
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			if (IsExe(cmd->path, false) < 0) {
				fprintf(stderr, "%s is not an executable\n",
					cmd->path);
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			cmd->legacy = false;
		}

		list_add(&cmd->entry, &p->head);
	}

	assert(fd != -1);

	close(fd);
	closedir(dir);
	DeleteDuplicates(p);
	return 0;

 error:
	assert(fd != -1);
	close(fd);
	Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
	closedir(dir);

	return -1;
}

void FreeExeList(ProcessList * p)
{
	assert(p != NULL);

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		list_del(&c->entry);
		free((void *)c->path);
		if (c->legacy == false) {
			free((void *)c->spawnattr.user);
			free((void *)c->spawnattr.group);
			free((void *)c->spawnattr.workingDirectory);
			free((void *)c->spawnattr.repairFilePathname);
			free((void *)c->spawnattr.noNewPrivileges);
		}
		free(c);
	}
}

static void * __ExecScriptWorkerThread(void *a)
{
	assert(a != NULL);

	__sync_synchronize();

	Container *container = (Container *) a;
	repaircmd_t *c = container->cmd;
	container->workerThreadCount += 1;
	sem = 1;
	FutexWake(&sem);
	__sync_synchronize();

	if (c->legacy == false) {
		if (c->retString[0] == '\0') {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair",
				      NULL);
		} else {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair", c->retString,
				      NULL);
		}
	} else {
		spawnattr_t attr = {
				.workingDirectory = NULL, .repairFilePathname = NULL,
	        		.execStart = NULL, .user = NULL, .group = NULL,
				.timeout = container->config->repairBinTimeout, .nice = 0, .umask = 0,
				.noNewPrivileges = false, .hasUmask = false
		};

		if (c->retString[0] == '\0') {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->path, NULL);
			}
		} else {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->retString, c->path, NULL);
			}
		}
	}

	c->retString[0] = '\0';

	container->workerThreadCount -= 1;

	__sync_synchronize();
	return NULL;
}

static void __WaitForWorkers(Container const *container)
{
	while (container->workerThreadCount != 0) {
		sleep(1);
	}
}

static int __ExecuteRepairScripts(void *a)
{
	struct executeScriptsStruct *arg = (struct executeScriptsStruct *)a;
	ProcessList *p = arg->list;
	struct cfgoptions *s = arg->config;

	Container container = {{0}, s, NULL};

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		container.cmd = c;
		container.cmd->mode = TEST;

		c->retString[0] = '\0';
		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	c = NULL;
	next = NULL;

	__WaitForWorkers(&container);

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret == 0) {
			continue;
		}

		container.cmd = c;
		portable_snprintf(container.cmd->retString, sizeof(container.cmd->retString), "%i", c->ret);

		container.cmd->mode = REPAIR;

		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	__WaitForWorkers(&container);

	c = NULL;
	next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret != 0) {
			Logmsg(LOG_ERR, "repair %s script failed",
				c->legacy == false ? c->spawnattr.repairFilePathname : c->path);
			return 1;
		}
	}

	return 0;
}

struct repairscriptTranctions *rst = NULL;

bool ExecuteRepairScriptsPreFork(ProcessList * p, struct cfgoptions *s)
{
	if (list_is_empty(&p->head)) {
		return true;
	}

	int shmid = shmget(IPC_PRIVATE, sysconf(_SC_PAGESIZE), (IPC_CREAT|IPC_EXCL|SHM_NORESERVE|0600));
	rst = (repairscriptTranctions*)shmat(shmid, NULL, 0);
	struct shmid_ds buf = {0};
	shmctl(shmid, IPC_RMID, &buf);

	pid_t pid = fork();

	if (pid == -1) {
		Logmsg(LOG_ERR, "%s\n", MyStrerror(errno));
		return false;
	} else if (pid == 0) {
		unsetenv("NOTIFY_SOCKET");
		unsetenv("LD_PRELOAD");

		ThreadPoolNew();

		while (true) {
			FutexWait(&rst->sem, 0);

			struct executeScriptsStruct ess;
			ess.list = p;
			ess.config = s;
			rst->ret = __ExecuteRepairScripts(&ess);
		}
		quick_exit(0);
	}

	return true;
}

int ExecuteRepairScripts(void)
{
	if (rst == NULL) {
		pthread_exit(NULL);
	}

	FutexWake(&rst->sem);

	if (rst->ret != 0) {
		return -1;
	}

	return 0;
}
<commit_msg>don't unset LD_PRELOAD<commit_after>/*
 * Copyright 2013-2016 Christian Lockley
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
#define _DEFAULT_SOURCE
#include <libgen.h>
#include "watchdogd.hpp"
#include "sub.hpp"
#include <dirent.h>
#include <semaphore.h>
#include "testdir.hpp"
#include "exe.hpp"
#include "repair.hpp"
#include <sys/eventfd.h>
#include "threadpool.hpp"
#include "futex.hpp"
#include "logutils.hpp"
#include <sys/ipc.h>
#include <sys/shm.h>

static std::atomic_int sem = {0};
unsigned long numberOfRepairScripts = 0;

static void DeleteDuplicates(ProcessList * p)
{
	if (!p)
		return;

	if (list_is_empty(&p->head))
		return;

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		repaircmd_t *b = NULL;
		repaircmd_t *next2 = NULL;
		++numberOfRepairScripts;
		if (c->legacy) {
			list_for_each_entry(b, next2, &p->head, entry) {
				if (!b->legacy) {
					if (strcmp(c->path, b->path) == 0) {
						--numberOfRepairScripts;
						Logmsg(LOG_INFO, "Using configuration info for %s script", b->path);
						list_del(&c->entry);
						free((void *)c->path);
						free((void *)c);
					}
				}
			}
		}
	}
}

int CreateLinkedListOfExes(char *repairScriptFolder, ProcessList * p,
			   struct cfgoptions *const config)
{
	assert(p != NULL);
	assert(repairScriptFolder != NULL);

	struct stat buffer;
	struct dirent *ent = NULL;

	list_init(&p->head);

	int fd = open(repairScriptFolder, O_DIRECTORY | O_RDONLY);

	if (fd == -1) {
		if (!(IDENTIFY & config->options)) {
			fprintf(stderr, "watchdogd: %s: %s\n", repairScriptFolder,
				MyStrerror(errno));
		}

		if (config->options & FORCE || config->options & SOFTBOOT || config->haveConfigFile == false) {
			return 0;
		}

		return 1;
	}

	DIR *dir = fdopendir(fd);

	if (dir == NULL) {
		Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
		close(fd);
		return -1;
	}

	errno = 0;

	while ((ent = readdir(dir)) != NULL) {

		int statfd = dirfd(dir);

		if (statfd == -1) {
			goto error;
		}

		if (strchr(".", ent->d_name[0]) != NULL && !(config->options & FORCE)) {
			continue;
		}

		if (fstatat(statfd, ent->d_name, &buffer, 0) < 0)
			continue;

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}

			if (!(buffer.st_mode & S_IXUSR))
				continue;

			if (!(buffer.st_mode & S_IRUSR))
				continue;
		} else {
			if (S_ISREG(buffer.st_mode) == 0) {
				continue;
			}
		}

		repaircmd_t *cmd = (repaircmd_t *) calloc(1, sizeof(*cmd));

		if (cmd == NULL) {
			goto error;
		}

		for (size_t i = 0; i < strlen(repairScriptFolder); i += 1) {
			if (repairScriptFolder[i] == '/' && i < strlen(repairScriptFolder)
			    && repairScriptFolder[i+1] == '\0') {
				repairScriptFolder[i] = '\0';
			}
		}

		Wasprintf((char **)&cmd->path, "%s/%s", repairScriptFolder, ent->d_name);

		if (cmd->path == NULL) {
			assert(cmd != NULL);
			free(cmd);
			goto error;
		}

		if (IsRepairScriptConfig(ent->d_name) == 0) {
			cmd->legacy = true;
		} else {
			//For V3 repair scripts cmd->path refers to the pathname of the repair script config file
			if (LoadRepairScriptLink
			    (&cmd->spawnattr, (char *)cmd->path) == false) {
				free((void *)cmd->path);
				free(cmd);
				continue;
			}

			cmd->spawnattr.repairFilePathname = strdup(cmd->path);
			free((void *)cmd->path);
			cmd->path = NULL;
			cmd->path = cmd->spawnattr.execStart;

			char * rel = basename(strdup(cmd->path));

			if (strcmp(rel, cmd->path) == 0) {
				free((void*)rel);
				Wasprintf((char **)&rel, "%s/%s", repairScriptFolder, cmd->path);
				free((void*)cmd->path);
				cmd->path = cmd->spawnattr.execStart = rel;
			}

			if (cmd->path == NULL) {
				fprintf(stderr,
					"Ignoring malformed repair file: %s\n",
					ent->d_name);
				free(cmd);
				continue;
			}

			if (fd < 0) {
				fprintf(stderr, "unable to open file %s:\n",
					MyStrerror(errno));
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			if (IsExe(cmd->path, false) < 0) {
				fprintf(stderr, "%s is not an executable\n",
					cmd->path);
				free((void *)cmd->path);
				free((void *)cmd);
				continue;
			}

			cmd->legacy = false;
		}

		list_add(&cmd->entry, &p->head);
	}

	assert(fd != -1);

	close(fd);
	closedir(dir);
	DeleteDuplicates(p);
	return 0;

 error:
	assert(fd != -1);
	close(fd);
	Logmsg(LOG_ERR, "watchdogd: %s", MyStrerror(errno));
	closedir(dir);

	return -1;
}

void FreeExeList(ProcessList * p)
{
	assert(p != NULL);

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		list_del(&c->entry);
		free((void *)c->path);
		if (c->legacy == false) {
			free((void *)c->spawnattr.user);
			free((void *)c->spawnattr.group);
			free((void *)c->spawnattr.workingDirectory);
			free((void *)c->spawnattr.repairFilePathname);
			free((void *)c->spawnattr.noNewPrivileges);
		}
		free(c);
	}
}

static void * __ExecScriptWorkerThread(void *a)
{
	assert(a != NULL);

	__sync_synchronize();

	Container *container = (Container *) a;
	repaircmd_t *c = container->cmd;
	container->workerThreadCount += 1;
	sem = 1;
	FutexWake(&sem);
	__sync_synchronize();

	if (c->legacy == false) {
		if (c->retString[0] == '\0') {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair",
				      NULL);
		} else {
			c->ret =
			    SpawnAttr(&c->spawnattr, c->path, c->path, c->mode == TEST ? "test": "repair", c->retString,
				      NULL);
		}
	} else {
		spawnattr_t attr = {
				.workingDirectory = NULL, .repairFilePathname = NULL,
	        		.execStart = NULL, .user = NULL, .group = NULL,
				.timeout = container->config->repairBinTimeout, .nice = 0, .umask = 0,
				.noNewPrivileges = false, .hasUmask = false
		};

		if (c->retString[0] == '\0') {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->path, NULL);
			}
		} else {
			if (c->mode == TEST) {
				c->ret = SpawnAttr(&attr, c->path, c->path, "test", NULL);
			} else {
				c->ret = SpawnAttr(&attr, c->path, c->path, "repair", c->retString, c->path, NULL);
			}
		}
	}

	c->retString[0] = '\0';

	container->workerThreadCount -= 1;

	__sync_synchronize();
	return NULL;
}

static void __WaitForWorkers(Container const *container)
{
	while (container->workerThreadCount != 0) {
		sleep(1);
	}
}

static int __ExecuteRepairScripts(void *a)
{
	struct executeScriptsStruct *arg = (struct executeScriptsStruct *)a;
	ProcessList *p = arg->list;
	struct cfgoptions *s = arg->config;

	Container container = {{0}, s, NULL};

	repaircmd_t *c = NULL;
	repaircmd_t *next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		container.cmd = c;
		container.cmd->mode = TEST;

		c->retString[0] = '\0';
		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	c = NULL;
	next = NULL;

	__WaitForWorkers(&container);

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret == 0) {
			continue;
		}

		container.cmd = c;
		portable_snprintf(container.cmd->retString, sizeof(container.cmd->retString), "%i", c->ret);

		container.cmd->mode = REPAIR;

		ThreadPoolAddTask(__ExecScriptWorkerThread, &container, true);
		__sync_synchronize();
		FutexWait(&sem, 0);
		sem = 0;
	}

	__WaitForWorkers(&container);

	c = NULL;
	next = NULL;

	list_for_each_entry(c, next, &p->head, entry) {
		if (c->ret != 0) {
			Logmsg(LOG_ERR, "repair %s script failed",
				c->legacy == false ? c->spawnattr.repairFilePathname : c->path);
			return 1;
		}
	}

	return 0;
}

struct repairscriptTranctions *rst = NULL;

bool ExecuteRepairScriptsPreFork(ProcessList * p, struct cfgoptions *s)
{
	if (list_is_empty(&p->head)) {
		return true;
	}

	int shmid = shmget(IPC_PRIVATE, sysconf(_SC_PAGESIZE), (IPC_CREAT|IPC_EXCL|SHM_NORESERVE|0600));
	rst = (repairscriptTranctions*)shmat(shmid, NULL, 0);
	struct shmid_ds buf = {0};
	shmctl(shmid, IPC_RMID, &buf);

	pid_t pid = fork();

	if (pid == -1) {
		Logmsg(LOG_ERR, "%s\n", MyStrerror(errno));
		return false;
	} else if (pid == 0) {
		unsetenv("NOTIFY_SOCKET");

		ThreadPoolNew();

		while (true) {
			FutexWait(&rst->sem, 0);

			struct executeScriptsStruct ess;
			ess.list = p;
			ess.config = s;
			rst->ret = __ExecuteRepairScripts(&ess);
		}
		quick_exit(0);
	}

	return true;
}

int ExecuteRepairScripts(void)
{
	if (rst == NULL) {
		pthread_exit(NULL);
	}

	FutexWake(&rst->sem);

	if (rst->ret != 0) {
		return -1;
	}

	return 0;
}
<|endoftext|>


<commit_before>/*-------------simple.cpp-----------------------------------------------------//
*
* Purpose: This file is a simple example of how we can simulate the defomation
*          of balls with a newton-solver algorithm. I have referred to RK4 a
*          few tiems and may implement it if this ends up becoming too slow in
*          the future, but I think it should be fine.
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>

/*----------------------------------------------------------------------------//
* STRUCTURES AND FUNCTIONS
*-----------------------------------------------------------------------------*/
using namespace std;

// Structure to point to the closest points in each direction
// I might actually use pointer later, but not for now.
struct closest{
    int up,down,forw,back,left,right;
};

// Class to hold all values of particles.
class point{
    public:
        int step_num;                                  // Time-step number.
        double x, y, z;                                // Position in x, y, z
        double v_x, v_y, v_z;                          // Velocity in x, y, z
        closest next;                                  // Closest points
};

// Class for all the parameters for hooke's law
class hook_param{
    public:
        double timestep, spring_const, rest_l, mass;
};

vector <double> hookes(double dist, double velocity, hook_param params);
void test(hook_param params);
vector <point> create_sphere(double radius, double rest_length,
                             double init_v_x, double init_v_y,
                             double init_v_z);
vector <point> simulate(vector <point> curr_sphere, hook_param params);
void write_file(vector<point> points);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/
int main(){

    hook_param params;
    params.timestep     = 0.0001;
    params.mass         = 0.001;
    params.spring_const = 1;
    params.rest_l       = 10;

    test(params);

    double radius = 5.0;
    double rest_length = 0.5 * radius;
    double init_v_x, init_v_z, init_v_y;
    vector <point> points;

    init_v_x = 0; init_v_y = 0; init_v_z = 0;
    points = create_sphere(radius, rest_length, init_v_x, init_v_y, init_v_z);
    points = simulate( points, params);
    write_file(points);

}

/*----------------------------------------------------------------------------//
* SUBROUTINES / FUNCTIONS
*-----------------------------------------------------------------------------*/

// Simple solver for Hooke's law. I could use RK4, but this'll do for now.
vector<double> hookes(double dist, double velocity, hook_param params){

    vector<double> both;

    dist += (velocity * params.timestep)
            + params.timestep * params.timestep
            *(0.5 * params.spring_const * (params.rest_l - dist) / params.mass);
    velocity += params.timestep*(params.spring_const *
                                (params.rest_l - dist) / params.mass);

    both.push_back(dist); both.push_back(velocity);

    return both;
}

// Test for Hooke's function... and potentially RK4 in a bit.
void test(hook_param params){

    vector<double> solution;
    double distance = 9.0,velocity = 0;

    solution.push_back(distance);
    solution.push_back(velocity);
    for (int i = 0; i < 100; i++){
        solution = hookes(solution[0],solution[1],params);
        cout << solution[0] << '\t' << solution[1] << endl;

    }
}

// Populate sphere of points. Brutish, sure... but it'll do.
// Note: make reat_length a multiple of radius. That makes things easier.
// Also: Checked
vector <point> create_sphere(double radius, double rest_length,
                             double init_v_x, double init_v_y,
                             double init_v_z){

    // The idea here is simple. We will start at the corner of our sphere and
    // create points in x, then y, then z that are each rest_length atart from
    // one another. Whenever any of these parameters are
    // outside of the radius of our sphere, we move to the next parameter.
    // The end result should be a vector of points, moving at our initial vel.

    vector<point> points;                               // All points
    point dummy;                                        // Dummy point
    int count = 0;                                      // Just a count

    cout << "Populating sphere..." << endl;

    for (double ix = -radius; ix <= (radius); ix = ix+ rest_length){
        for (double iy = -radius; iy <= (radius); iy = iy + rest_length){
            for (double iz = -radius; iz <= (radius); iz = iz + rest_length){

                if (((ix * ix) + (iy * iy) + (iz * iz)) <= radius*radius){
                    dummy.step_num = count;
                    dummy.x = ix;
                    dummy.y = iy;
                    dummy.z = iz;
                    dummy.v_x = init_v_x;
                    dummy.v_y = init_v_y;
                    dummy.v_z = init_v_z;
                    points.push_back(dummy);
                    count++;
                }

            }

        }

    }

    // Now I need to figure out which ones are closest to each other.
    // Note: if I want to use this code later, I can easily break this f(x)
    //       in half.

    cout << "Finding closest particles..." << endl;

    double x, y, z;

    for (int i = 0; i < points.size(); i++){
        x = points[i].x;
        y = points[i].y;
        z = points[i].z;

        // Let's find the maximum count number (fcount)
        double count_up, count_down;
        int fcount;

        count_up = radius*radius - (x+rest_length)*(x+rest_length);
        count_down = radius*radius - (x-rest_length)*(x-rest_length);

        if (count_down > count_up){
            fcount = count_down;
        }
        else{
            fcount = count_up;
        }

        for (int ii = 0; ii < fcount; ii++){

            // UP
            if ( points[i].z == points[i + ii].z){
                points[i].next.up = points[i+ii].z;
            }

            // RIGHT
            if ( points[i].y == points[i + ii].y){
                points[i].next.right = points[i+ii].y;
            }

            // FORW
            if ( points[i].x == points[i + ii].x){
                points[i].next.forw = points[i+ii].x;
            }

            if ( i >= ii){

                // DOWN
                if ( points[i].z == points[i - ii].z){
                    points[i].next.down = points[i-ii].z;
                }

                // LEFT
                if ( points[i].y == points[i - ii].y){
                    points[i].next.left = points[i+ii].y;
                }

                // BACK
                if ( points[i].x == points[i - ii].x){
                    points[i].next.back = points[i+ii].x;
                }

            }

        }

    }
    return points;
}

// Now I need to prepare each point so that it reads into my Hooke's law f(x).
vector <point> simulate(vector <point> curr_sphere, hook_param params){

    int dir;
    double del_x, del_y, del_z, theta_xy, theta_zy, del_tot;

    // I need to get the velocities from each component in the spring direction
    double del_vx, del_vy, del_vz, vel_fx, vel_fy, vel_fz, vel_tot;

    vector <double> solution;

    solution.push_back(1.000);     solution.push_back(1.000);

    for (int i = 0; i < curr_sphere.size(); i++){
        for (int ii = 0; ii < 6; ii++){

            // Setting which direction to check
            if (ii = 0){dir = curr_sphere[i].next.up;}
            if (ii = 1){dir = curr_sphere[i].next.down;}
            if (ii = 2){dir = curr_sphere[i].next.left;}
            if (ii = 3){dir = curr_sphere[i].next.right;}
            if (ii = 4){dir = curr_sphere[i].next.forw;}
            if (ii = 5){dir = curr_sphere[i].next.back;}

            // Finding all necessary parameters between two points
            del_x = curr_sphere[i].x - curr_sphere[dir].x;
            del_y = curr_sphere[i].y - curr_sphere[dir].y;
            del_z = curr_sphere[i].z - curr_sphere[dir].z;
            theta_xy = atan( del_y / del_x);
            theta_zy = atan( del_y / del_z);

            del_tot = del_x*del_x + del_y*del_y + del_z*del_z;

            del_vx = curr_sphere[i].v_x - curr_sphere[dir].v_x;
            del_vy = curr_sphere[i].v_y - curr_sphere[dir].v_y;
            del_vz = curr_sphere[i].v_z - curr_sphere[dir].v_z;

            vel_fz = del_vz / cos(theta_zy);
            vel_fy = del_vy / sin(theta_xy);
            vel_fx = del_vx / cos(theta_xy);

            vel_tot = vel_fx + vel_fy + vel_fz;

            // Now solving Hooke's Law
            solution[0] = del_tot;     solution[1] = vel_tot;

            solution = hookes(solution[0], solution[1], params);

            // Intereting solution
            del_x = solution[0] * cos(theta_xy);
            del_y = solution[0] * sin(theta_xy);
            del_z = solution[0] * cos(theta_zy);
            del_vx = solution[1] * cos(theta_xy);
            del_vy = solution[1] * sin(theta_xy);
            del_vz = solution[1] * cos(theta_zy);

            // Adding the change in distance...
            curr_sphere[i].x += (0.5 * del_x);
            curr_sphere[i].y += (0.5 * del_y);
            curr_sphere[i].z += (0.5 * del_z);
            curr_sphere[dir].x += (0.5 * del_x);
            curr_sphere[dir].y += (0.5 * del_y);
            curr_sphere[dir].z += (0.5 * del_z);

            // Adding the change in velocity...
            curr_sphere[i].v_x += (0.5 * del_vx);
            curr_sphere[i].v_y += (0.5 * del_vy);
            curr_sphere[i].v_z += (0.5 * del_vz);
            curr_sphere[dir].v_x += (0.5 * del_vx);
            curr_sphere[dir].v_y += (0.5 * del_vy);
            curr_sphere[dir].v_z += (0.5 * del_vz);

        }

        // Adding the change in distance due to overall velocity of point
        curr_sphere[i].x += params.timestep * curr_sphere[i].v_x;
        curr_sphere[i].y += params.timestep * curr_sphere[i].v_y;
        curr_sphere[i].z += params.timestep * curr_sphere[i].v_z;

    }

return curr_sphere;
}

// Now I need a function to write everything to a file.
void write_file(vector<point> points){

    ofstream output("out.dat");
    if (output.is_open()){
        for (int i = 0; i < points.size(); i++){
            output << points[i].x << '\t' << points[i].y << '\t'
                   << points[i].z << '\t' << points[i].v_x << '\t'
                   << points[i].v_y << '\t' << points[i].v_z
                   << endl;
        }

        output.close();
    }
    else cout << "Cannot open output file. Sorry. =/" << endl;

}
<commit_msg>well, now they are allnan's. That's good, right?<commit_after>/*-------------simple.cpp-----------------------------------------------------//
*
* Purpose: This file is a simple example of how we can simulate the defomation
*          of balls with a newton-solver algorithm. I have referred to RK4 a
*          few tiems and may implement it if this ends up becoming too slow in
*          the future, but I think it should be fine.
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>

/*----------------------------------------------------------------------------//
* STRUCTURES AND FUNCTIONS
*-----------------------------------------------------------------------------*/
using namespace std;

// Structure to point to the closest points in each direction
// I might actually use pointer later, but not for now.
struct closest{
    int up,down,forw,back,left,right;
};

// Class to hold all values of particles.
class point{
    public:
        int step_num;                                  // Time-step number.
        double x, y, z;                                // Position in x, y, z
        double v_x, v_y, v_z;                          // Velocity in x, y, z
        closest next;                                  // Closest points
};

// Class for all the parameters for hooke's law
class hook_param{
    public:
        double timestep, spring_const, rest_l, mass;
};

vector <double> hookes(double dist, double velocity, hook_param params);
void test(hook_param params);
vector <point> create_sphere(double radius, double rest_length,
                             double init_v_x, double init_v_y,
                             double init_v_z);
vector <point> simulate(vector <point> curr_sphere, hook_param params);
void write_file(vector<point> points);
void clear_output();

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/
int main(){

    clear_output();
    hook_param params;
    params.timestep     = 0.0001;
    params.mass         = 0.001;
    params.spring_const = 1;
    params.rest_l       = 10;

//    test(params);

    double radius = 5.0;
    double rest_length = 0.5 * radius;
    double init_v_x, init_v_z, init_v_y;
    vector <point> points;

    init_v_x = 0; init_v_y = 0; init_v_z = 0;
    points = create_sphere(radius, rest_length, init_v_x, init_v_y, init_v_z);
    write_file(points);

    // ERROR... I think we get a lot of NaN's because there is no value in that
    // direction...
    points = simulate( points, params);
    write_file(points);

}

/*----------------------------------------------------------------------------//
* SUBROUTINES / FUNCTIONS
*-----------------------------------------------------------------------------*/

// Simple solver for Hooke's law. I could use RK4, but this'll do for now.
vector<double> hookes(double dist, double velocity, hook_param params){

    vector<double> both;

    dist += (velocity * params.timestep)
            + params.timestep * params.timestep
            *(0.5 * params.spring_const * (params.rest_l - dist) / params.mass);
    velocity += params.timestep*(params.spring_const *
                                (params.rest_l - dist) / params.mass);

    both.push_back(dist); both.push_back(velocity);

    return both;
}

// Test for Hooke's function... and potentially RK4 in a bit.
void test(hook_param params){

    vector<double> solution;
    double distance = 9.0,velocity = 0;

    solution.push_back(distance);
    solution.push_back(velocity);
    for (int i = 0; i < 100; i++){
        solution = hookes(solution[0],solution[1],params);
        cout << solution[0] << '\t' << solution[1] << endl;

    }
}

// Populate sphere of points. Brutish, sure... but it'll do.
// Note: make reat_length a multiple of radius. That makes things easier.
// Also: Checked
vector <point> create_sphere(double radius, double rest_length,
                             double init_v_x, double init_v_y,
                             double init_v_z){

    // The idea here is simple. We will start at the corner of our sphere and
    // create points in x, then y, then z that are each rest_length atart from
    // one another. Whenever any of these parameters are
    // outside of the radius of our sphere, we move to the next parameter.
    // The end result should be a vector of points, moving at our initial vel.

    vector<point> points;                               // All points
    point dummy;                                        // Dummy point
    int count = 0;                                      // Just a count

    cout << "Populating sphere..." << endl;

    for (double ix = -radius; ix <= (radius); ix = ix+ rest_length){
        for (double iy = -radius; iy <= (radius); iy = iy + rest_length){
            for (double iz = -radius; iz <= (radius); iz = iz + rest_length){

                if (((ix * ix) + (iy * iy) + (iz * iz)) <= radius*radius){
                    dummy.step_num = count;
                    dummy.x = ix;
                    dummy.y = iy;
                    dummy.z = iz;
                    dummy.v_x = init_v_x;
                    dummy.v_y = init_v_y;
                    dummy.v_z = init_v_z;
                    points.push_back(dummy);
                    count++;
                }

            }

        }

    }

    // Now I need to figure out which ones are closest to each other.
    // Note: if I want to use this code later, I can easily break this f(x)
    //       in half.

    cout << "Finding closest particles..." << endl;

    double x, y, z;

    for (int i = 0; i < points.size(); i++){
        x = points[i].x;
        y = points[i].y;
        z = points[i].z;

        // Let's find the maximum count number (fcount)
        double count_up, count_down;
        int fcount;

        count_up = radius*radius - (x+rest_length)*(x+rest_length);
        count_down = radius*radius - (x-rest_length)*(x-rest_length);

        if (count_down > count_up){
            fcount = count_down;
        }
        else{
            fcount = count_up;
        }

        for (int ii = 0; ii < fcount; ii++){

            // UP
            if ( points[i].z == points[i + ii].z){
                points[i].next.up = points[i+ii].z;
            }

            // RIGHT
            if ( points[i].y == points[i + ii].y){
                points[i].next.right = points[i+ii].y;
            }

            // FORW
            if ( points[i].x == points[i + ii].x){
                points[i].next.forw = points[i+ii].x;
            }

            if ( i >= ii){

                // DOWN
                if ( points[i].z == points[i - ii].z){
                    points[i].next.down = points[i-ii].z;
                }

                // LEFT
                if ( points[i].y == points[i - ii].y){
                    points[i].next.left = points[i+ii].y;
                }

                // BACK
                if ( points[i].x == points[i - ii].x){
                    points[i].next.back = points[i+ii].x;
                }

            }

        }

    }
    return points;
}

// Now I need to prepare each point so that it reads into my Hooke's law f(x).
vector <point> simulate(vector <point> curr_sphere, hook_param params){

    int dir;
    double del_x, del_y, del_z, theta_xy, theta_zy, del_tot;

    // I need to get the velocities from each component in the spring direction
    double del_vx, del_vy, del_vz, vel_fx, vel_fy, vel_fz, vel_tot;

    vector <double> solution;

    solution.push_back(1.000);     solution.push_back(1.000);

    for (int i = 0; i < curr_sphere.size(); i++){
        for (int ii = 0; ii < 6; ii++){

            // Setting which direction to check
            if (ii = 0){
                if (curr_sphere[i].next.up >= 0){
                    dir = curr_sphere[i].next.up;
                }
            }

            if (ii = 1){
                if (curr_sphere[i].next.down >= 0){
                    dir = curr_sphere[i].next.down;
                }
            }

            if (ii = 2){
                if (curr_sphere[i].next.left >= 0){
                    dir = curr_sphere[i].next.left;
                }
            }

            if (ii = 3){
                if (curr_sphere[i].next.right >= 0){
                    dir = curr_sphere[i].next.right;
                }
            }

            if (ii = 4){
                if (curr_sphere[i].next.forw >= 0){
                    dir = curr_sphere[i].next.forw;
                }
            }

            if (ii = 5){
                if (curr_sphere[i].next.back >= 0){
                    dir = curr_sphere[i].next.back;
                }
            }

            // Finding all necessary parameters between two points
            del_x = curr_sphere[i].x - curr_sphere[dir].x;
            del_y = curr_sphere[i].y - curr_sphere[dir].y;
            del_z = curr_sphere[i].z - curr_sphere[dir].z;
            theta_xy = atan( del_y / del_x);
            theta_zy = atan( del_y / del_z);

            del_tot = del_x*del_x + del_y*del_y + del_z*del_z;

            del_vx = curr_sphere[i].v_x - curr_sphere[dir].v_x;
            del_vy = curr_sphere[i].v_y - curr_sphere[dir].v_y;
            del_vz = curr_sphere[i].v_z - curr_sphere[dir].v_z;

            vel_fz = del_vz / cos(theta_zy);
            vel_fy = del_vy / sin(theta_xy);
            vel_fx = del_vx / cos(theta_xy);

            vel_tot = vel_fx + vel_fy + vel_fz;

            // Now solving Hooke's Law
            solution[0] = del_tot;     solution[1] = vel_tot;

            solution = hookes(solution[0], solution[1], params);

            // Intereting solution
            del_x = solution[0] * cos(theta_xy);
            del_y = solution[0] * sin(theta_xy);
            del_z = solution[0] * cos(theta_zy);
            del_vx = solution[1] * cos(theta_xy);
            del_vy = solution[1] * sin(theta_xy);
            del_vz = solution[1] * cos(theta_zy);

            // Adding the change in distance...
            curr_sphere[i].x += (0.5 * del_x);
            curr_sphere[i].y += (0.5 * del_y);
            curr_sphere[i].z += (0.5 * del_z);
            curr_sphere[dir].x += (0.5 * del_x);
            curr_sphere[dir].y += (0.5 * del_y);
            curr_sphere[dir].z += (0.5 * del_z);

            // Adding the change in velocity...
            curr_sphere[i].v_x += (0.5 * del_vx);
            curr_sphere[i].v_y += (0.5 * del_vy);
            curr_sphere[i].v_z += (0.5 * del_vz);
            curr_sphere[dir].v_x += (0.5 * del_vx);
            curr_sphere[dir].v_y += (0.5 * del_vy);
            curr_sphere[dir].v_z += (0.5 * del_vz);

        }

        // Adding the change in distance due to overall velocity of point
        curr_sphere[i].x += params.timestep * curr_sphere[i].v_x;
        curr_sphere[i].y += params.timestep * curr_sphere[i].v_y;
        curr_sphere[i].z += params.timestep * curr_sphere[i].v_z;

    }

return curr_sphere;
}

// Now I need a function to write everything to a file.
void write_file(vector<point> points){

    ofstream output("out.dat", std::ofstream::out | std::ofstream::app);
    if (output.is_open()){
        for (int i = 0; i < points.size(); i++){
            output << points[i].x << '\t' << points[i].y << '\t'
                   << points[i].z << '\t' << points[i].v_x << '\t'
                   << points[i].v_y << '\t' << points[i].v_z
                   << endl;
        }

        output.close();
    }
    else cout << "Cannot open output file. Sorry. =/" << endl;

}

// I may need to clear the output at the start of each run...
void clear_output(){
    ofstream output("out.dat");
    if (output.is_open()){
        output.clear();
        output.close();
    }
    else cout << "Cannot open output file. Sorry. =/" << endl;

}
<|endoftext|>