<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 ARM Limited
 *
 * 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.
 */

#include "mbed.h"
#include "ble/BLE.h"
#include "ble-blocktransfer/BlockTransferService.h"
#include "voytalk/Voytalk.h"

/*****************************************************************************/
/* Configuration                                                             */
/*****************************************************************************/

// set device name
const char DEVICE_NAME[] = "mbed Provisioning";

// set TX power
#ifndef CFG_BLE_TX_POWER_LEVEL
#define CFG_BLE_TX_POWER_LEVEL 0
#endif

// control debug output
#if 1
#define DEBUGOUT(...) { printf(__VA_ARGS__); }
#else
#define DEBUGOUT(...) /* nothing */
#endif // DEBUGOUT

#define VERBOSE_DEBUG_OUT 1

/*****************************************************************************/

/* Voytalk short UUID */
const UUID uuid(0xFE8E);

/* Voytalk states */
typedef enum {
    FLAG_CONNECTED      = 0x01,
    FLAG_PROVISIONED    = 0x02,
} flags_t;

static volatile uint8_t state;

/*****************************************************************************/
/* Global variables used by the test app                                     */
/*****************************************************************************/

// BLE_API ble device
BLE ble;

// Transfer large blocks of data on platforms without Fragmentation-And-Recombination
BlockTransferService bts;

// variables for sending and receiving data
uint8_t readBuffer[1000];
SharedPointer<Block> readBlock(new BlockStatic(readBuffer, sizeof(readBuffer)));
SharedPointer<Block> writeBlock;

// wifi parameters
std::string ssid_string;
std::string key_string;

// Compatibility function
void signalReady();

void onResponseFinished(const VTResponse& res)
{
    DEBUGOUT("main: output buffer usage: %lu of %lu\r\n", readBlock->getLength(), readBlock->getMaxLength());
    (void) res;

    // signal response is ready to be read
    signalReady();

    // free reference counted block
    writeBlock = SharedPointer<Block>();
}

// Voytalk handling
VoytalkRouter router(DEVICE_NAME, onResponseFinished);

/*****************************************************************************/
/* Functions for handling debug output                                       */
/*****************************************************************************/

/*
    Functions called when BLE device connects and disconnects.
*/
void whenConnected(const Gap::ConnectionCallbackParams_t* params)
{
    (void) params;
    DEBUGOUT("main: Connected: %d %d %d\r\n", params->connectionParams->minConnectionInterval,
                                              params->connectionParams->maxConnectionInterval,
                                              params->connectionParams->slaveLatency);

    // change state in main application
    state |= FLAG_CONNECTED;

    // change state inside Voytalk hub
    router.setStateMask(state);
}

void whenDisconnected(const Gap::DisconnectionCallbackParams_t*)
{
    DEBUGOUT("main: Disconnected!\r\n");
    DEBUGOUT("main: Restarting the advertising process\r\n");

    ble.gap().startAdvertising();

    // change state in main application
    state &= ~FLAG_CONNECTED;

    // change state inside Voytalk hub
    router.setStateMask(state);
}

/*****************************************************************************/
/* BlockTransfer callbacks for sending and receiving data                    */
/*****************************************************************************/

/*
    Function called when signaling client that new data is ready to be read.
*/
void blockServerSendNotification()
{
    DEBUGOUT("main: notify read updated\r\n");
    bts.updateCharacteristicValue((uint8_t*)"", 0);
}

/*
    Function called when device receives a read request over BLE.
*/
SharedPointer<Block> blockServerReadHandler(uint32_t offset)
{
    DEBUGOUT("main: block read: %lu\r\n", readBlock->getLength());
    (void) offset;

#if VERBOSE_DEBUG_OUT
    /* print generated output */
    if (readBlock->getLength() > 0)
    {
        for (size_t idx = 0; idx < readBlock->getLength(); idx++)
        {
            DEBUGOUT("%02X", readBlock->at(idx));
        }
        DEBUGOUT("\r\n\r\n");
    }
#endif

    return readBlock;
}

/*
    Function called when data has been written over BLE.
*/
void blockServerWriteHandler(SharedPointer<Block> block)
{
    DEBUGOUT("main: block write\r\n");

#if VERBOSE_DEBUG_OUT
    DEBUGOUT("main write:\r\n");
    for (size_t idx = 0; idx < block->getLength(); idx++)
    {
        DEBUGOUT("%02X", block->at(idx));
    }
    DEBUGOUT("\r\n\r\n");
#endif

    /*
        Process received data, assuming it is CBOR encoded.
        Any output generated will be written to the readBlock.
    */

    DEBUGOUT("main: input buffer usage: %lu of %lu\r\n", block->getLength(), block->getMaxLength());

    router.processCBOR((BlockStatic*) block.get(), (BlockStatic*) readBlock.get());

    // save block until we are done processing this request
    writeBlock = block;
}

/*****************************************************************************/
/* Voytalk Wifi example                                                      */
/*****************************************************************************/

/*
    Callback function for constructing wifi intent.
*/
void wifiIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: wifi intent construction\r\n");
    (void) req;

    /* create intent using generated endpoint and constraint set */
    VTIntent intent("com.arm.connectivity.wifi");
    intent.knownParameters("/networks")
        .endpoint("/wifi");

    res.write(intent);
}

/*****************************************************************************/
/* Reset device example                                                      */
/*****************************************************************************/

void resetIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: reset intent construction\r\n");
    (void) req;

    /* create intent using generated endpoint and constraint set */
    VTIntent intent("com.arm.reset");
    intent.endpoint("/reset");
    res.write(intent);
}

/*****************************************************************************/
/* Voytalk complex example                                                   */
/*****************************************************************************/

/*
    Callback functions for the example intent.
*/
void exampleIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: complex example intent construction\r\n");
    (void) req;

    /* create intent */
    VTIntent intent("com.arm.examples.complex");
    intent.endpoint("/examples/complex");

    res.write(intent);
}

/*****************************************************************************/
/* Voytalk custom example                                                    */
/*****************************************************************************/

void customIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: custom intent construction\r\n");
    (void) req;

    /* create intent using generated endpoint and constraint set */
    VTIntent intent("com.arm.examples.custom");
    intent.endpoint("/custom")
        .constraints()
            .title("Hello!")
            .description("This is the description")
            .addProperty("test",
                VTConstraint(VTConstraint::TypeString)
                    .title("Test")
                    .defaultValue("default goes here")
            )
            .addProperty("test2",
                VTConstraint(VTConstraint::TypeString)
                    .title("Other test")
                    .defaultValue("default goes here")
            );
    res.write(intent);
}

/*****************************************************************************/
/* Middleware for actually doing stuff                                       */
/*****************************************************************************/

VTRequest* demoCallbackRequest = NULL;
VTResponse* demoCallbackResponse = NULL;
VoytalkRouter::next_t demoCallbackHandle;

void demoCallbackTask()
{
    demoCallbackHandle();
}

void printInvocation(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    (void) req;
    (void) res;

    VTIntentInvocation invocation(req.getBody());
    invocation.getParameters().print();

    // save parameters so callback can be called asynchronously
    demoCallbackRequest = &req;
    demoCallbackResponse = &res;
    demoCallbackHandle = next;

    // post call to function to demo asynchronous callback
    minar::Scheduler::postCallback(demoCallbackTask);
}

void saveWifi(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: saving wifi details\r\n");
    (void) req;
    (void) res;

    VTIntentInvocation invocation(req.getBody());

    invocation.getParameters().find("ssid").getString(ssid_string);
    invocation.getParameters().find("key").getString(key_string);

    // change state in main application
    state |= FLAG_PROVISIONED;

    // change state inside Voytalk hub
    router.setStateMask(state);

    next();
}

void resetDevice(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: reset device\r\n");
    (void) req;
    (void) res;

    ssid_string = "";
    key_string = "";

    // change state in main application
    state &= ~FLAG_PROVISIONED;

    // change state inside Voytalk hub
    router.setStateMask(state);

    next();
}

void sendSuccess(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: sending success coda\r\n");
    (void) req;

    VTIntentInvocation invocation(req.getBody());
    VTCoda coda(invocation.getID());
    coda.success(true);
    res.write(coda);
    next(200);
}

void networkList(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: listing network resources");
    (void) req;
    (void) res;

    VoytalkKnownParameters parameters(res);

    parameters.begin();

    parameters.parameter("com.arm.connectivity.wifi", 50)
        .map()
            .key("ssid").value("miWifi")
        .end();

    parameters.parameter("com.arm.connectivity.wifi", 20)
        .map()
            .key("ssid").value("yoWifi")
        .end();

    parameters.end();

    next(200);
}

/*****************************************************************************/
/* main                                                                      */
/*****************************************************************************/

void app_start(int, char *[])
{
    /*
        Register Voytalk intents in the hub.

        First parameter is the callback function for intent generation.
        Second parameter is a bitmap for grouping intents together.
    */

    // Wifi provisioning intent
    router.registerIntent(wifiIntentConstruction,
                          FLAG_CONNECTED | FLAG_PROVISIONED);

    // reset intent
    router.registerIntent(resetIntentConstruction,
                          FLAG_PROVISIONED);

    // custom intent
    //router.registerIntent(customIntentConstruction,
    //                     FLAG_CONNECTED | FLAG_PROVISIONED);

    // example intent
    router.registerIntent(exampleIntentConstruction,
                         FLAG_CONNECTED | FLAG_PROVISIONED);

    /*
        Set the current state mask.

        Mask is AND'ed with each intent's bitmap and only intents with non-zero
        results are displayed and can be invoked.
    */
    router.setStateMask(0);

    /*
        Define some resource callbacks
    */

    router.get("/networks",          networkList,                               NULL);
    router.post("/wifi",             printInvocation, saveWifi,    sendSuccess, NULL);
    router.post("/reset",            printInvocation, resetDevice, sendSuccess, NULL);
    router.post("/custom",           printInvocation,              sendSuccess, NULL);
    router.post("/examples/complex", printInvocation,              sendSuccess, NULL);

    /*************************************************************************/
    /*************************************************************************/
    /* bluetooth le */
    ble.init();

    // status callback functions
    ble.gap().onConnection(whenConnected);
    ble.gap().onDisconnection(whenDisconnected);

    /* construct advertising beacon */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED|GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, uuid.getBaseUUID(), uuid.getLen());
    ble.gap().accumulateAdvertisingPayloadTxPower(CFG_BLE_TX_POWER_LEVEL);

    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1s; in multiples of 0.625ms. */

    // set TX power
    ble.gap().setTxPower(CFG_BLE_TX_POWER_LEVEL);

    // Apple uses device name instead of beacon name
    ble.gap().setDeviceName((const uint8_t*) DEVICE_NAME);

    /*************************************************************************/
    /*************************************************************************/
    // setup block transfer service

    // add service using ble device, responding to uuid, and without encryption
    bts.init(uuid, SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK);

    // set callback functions for the BlockTransfer service
    bts.setWriteAuthorizationCallback(blockServerWriteHandler);
    bts.setReadAuthorizationCallback(blockServerReadHandler);

    // ble setup complete - start advertising
    ble.gap().startAdvertising();

    printf("Voytalk Test: %s %s\r\n", __DATE__, __TIME__);
}

/*****************************************************************************/
/* Compatibility                                                             */
/*****************************************************************************/

#if defined(YOTTA_MINAR_VERSION_STRING)
/*********************************************************/
/* Build for mbed OS                                     */
/*********************************************************/

void signalReady()
{
    minar::Scheduler::postCallback(blockServerSendNotification);
}

#else
/*********************************************************/
/* Build for mbed Classic                                */
/*********************************************************/

volatile bool sendNotification = false;

void signalReady()
{
    sendNotification = true;
}

int main(void)
{
    app_start(0, NULL);

    for(;;)
    {
        // send notification outside of interrupt context
        if (sendNotification)
        {
            sendNotification = false;
            blockServerSendNotification();
        }

        ble.waitForEvent();
    }
}
#endif

<commit_msg>use more appropriate wifi priorities<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 ARM Limited
 *
 * 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.
 */

#include "mbed.h"
#include "ble/BLE.h"
#include "ble-blocktransfer/BlockTransferService.h"
#include "voytalk/Voytalk.h"

/*****************************************************************************/
/* Configuration                                                             */
/*****************************************************************************/

// set device name
const char DEVICE_NAME[] = "mbed Provisioning";

// set TX power
#ifndef CFG_BLE_TX_POWER_LEVEL
#define CFG_BLE_TX_POWER_LEVEL 0
#endif

// control debug output
#if 1
#define DEBUGOUT(...) { printf(__VA_ARGS__); }
#else
#define DEBUGOUT(...) /* nothing */
#endif // DEBUGOUT

#define VERBOSE_DEBUG_OUT 1

/*****************************************************************************/

/* Voytalk short UUID */
const UUID uuid(0xFE8E);

/* Voytalk states */
typedef enum {
    FLAG_CONNECTED      = 0x01,
    FLAG_PROVISIONED    = 0x02,
} flags_t;

static volatile uint8_t state;

/*****************************************************************************/
/* Global variables used by the test app                                     */
/*****************************************************************************/

// BLE_API ble device
BLE ble;

// Transfer large blocks of data on platforms without Fragmentation-And-Recombination
BlockTransferService bts;

// variables for sending and receiving data
uint8_t readBuffer[1000];
SharedPointer<Block> readBlock(new BlockStatic(readBuffer, sizeof(readBuffer)));
SharedPointer<Block> writeBlock;

// wifi parameters
std::string ssid_string;
std::string key_string;

// Compatibility function
void signalReady();

void onResponseFinished(const VTResponse& res)
{
    DEBUGOUT("main: output buffer usage: %lu of %lu\r\n", readBlock->getLength(), readBlock->getMaxLength());
    (void) res;

    // signal response is ready to be read
    signalReady();

    // free reference counted block
    writeBlock = SharedPointer<Block>();
}

// Voytalk handling
VoytalkRouter router(DEVICE_NAME, onResponseFinished);

/*****************************************************************************/
/* Functions for handling debug output                                       */
/*****************************************************************************/

/*
    Functions called when BLE device connects and disconnects.
*/
void whenConnected(const Gap::ConnectionCallbackParams_t* params)
{
    (void) params;
    DEBUGOUT("main: Connected: %d %d %d\r\n", params->connectionParams->minConnectionInterval,
                                              params->connectionParams->maxConnectionInterval,
                                              params->connectionParams->slaveLatency);

    // change state in main application
    state |= FLAG_CONNECTED;

    // change state inside Voytalk hub
    router.setStateMask(state);
}

void whenDisconnected(const Gap::DisconnectionCallbackParams_t*)
{
    DEBUGOUT("main: Disconnected!\r\n");
    DEBUGOUT("main: Restarting the advertising process\r\n");

    ble.gap().startAdvertising();

    // change state in main application
    state &= ~FLAG_CONNECTED;

    // change state inside Voytalk hub
    router.setStateMask(state);
}

/*****************************************************************************/
/* BlockTransfer callbacks for sending and receiving data                    */
/*****************************************************************************/

/*
    Function called when signaling client that new data is ready to be read.
*/
void blockServerSendNotification()
{
    DEBUGOUT("main: notify read updated\r\n");
    bts.updateCharacteristicValue((uint8_t*)"", 0);
}

/*
    Function called when device receives a read request over BLE.
*/
SharedPointer<Block> blockServerReadHandler(uint32_t offset)
{
    DEBUGOUT("main: block read: %lu\r\n", readBlock->getLength());
    (void) offset;

#if VERBOSE_DEBUG_OUT
    /* print generated output */
    if (readBlock->getLength() > 0)
    {
        for (size_t idx = 0; idx < readBlock->getLength(); idx++)
        {
            DEBUGOUT("%02X", readBlock->at(idx));
        }
        DEBUGOUT("\r\n\r\n");
    }
#endif

    return readBlock;
}

/*
    Function called when data has been written over BLE.
*/
void blockServerWriteHandler(SharedPointer<Block> block)
{
    DEBUGOUT("main: block write\r\n");

#if VERBOSE_DEBUG_OUT
    DEBUGOUT("main write:\r\n");
    for (size_t idx = 0; idx < block->getLength(); idx++)
    {
        DEBUGOUT("%02X", block->at(idx));
    }
    DEBUGOUT("\r\n\r\n");
#endif

    /*
        Process received data, assuming it is CBOR encoded.
        Any output generated will be written to the readBlock.
    */

    DEBUGOUT("main: input buffer usage: %lu of %lu\r\n", block->getLength(), block->getMaxLength());

    router.processCBOR((BlockStatic*) block.get(), (BlockStatic*) readBlock.get());

    // save block until we are done processing this request
    writeBlock = block;
}

/*****************************************************************************/
/* Voytalk Wifi example                                                      */
/*****************************************************************************/

/*
    Callback function for constructing wifi intent.
*/
void wifiIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: wifi intent construction\r\n");
    (void) req;

    /* create intent using generated endpoint and constraint set */
    VTIntent intent("com.arm.connectivity.wifi");
    intent.knownParameters("/networks")
        .endpoint("/wifi");

    res.write(intent);
}

/*****************************************************************************/
/* Reset device example                                                      */
/*****************************************************************************/

void resetIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: reset intent construction\r\n");
    (void) req;

    /* create intent using generated endpoint and constraint set */
    VTIntent intent("com.arm.reset");
    intent.endpoint("/reset");
    res.write(intent);
}

/*****************************************************************************/
/* Voytalk complex example                                                   */
/*****************************************************************************/

/*
    Callback functions for the example intent.
*/
void exampleIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: complex example intent construction\r\n");
    (void) req;

    /* create intent */
    VTIntent intent("com.arm.examples.complex");
    intent.endpoint("/examples/complex");

    res.write(intent);
}

/*****************************************************************************/
/* Voytalk custom example                                                    */
/*****************************************************************************/

void customIntentConstruction(VTRequest& req, VTResponse& res)
{
    DEBUGOUT("main: custom intent construction\r\n");
    (void) req;

    /* create intent using generated endpoint and constraint set */
    VTIntent intent("com.arm.examples.custom");
    intent.endpoint("/custom")
        .constraints()
            .title("Hello!")
            .description("This is the description")
            .addProperty("test",
                VTConstraint(VTConstraint::TypeString)
                    .title("Test")
                    .defaultValue("default goes here")
            )
            .addProperty("test2",
                VTConstraint(VTConstraint::TypeString)
                    .title("Other test")
                    .defaultValue("default goes here")
            );
    res.write(intent);
}

/*****************************************************************************/
/* Middleware for actually doing stuff                                       */
/*****************************************************************************/

VTRequest* demoCallbackRequest = NULL;
VTResponse* demoCallbackResponse = NULL;
VoytalkRouter::next_t demoCallbackHandle;

void demoCallbackTask()
{
    demoCallbackHandle();
}

void printInvocation(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    (void) req;
    (void) res;

    VTIntentInvocation invocation(req.getBody());
    invocation.getParameters().print();

    // save parameters so callback can be called asynchronously
    demoCallbackRequest = &req;
    demoCallbackResponse = &res;
    demoCallbackHandle = next;

    // post call to function to demo asynchronous callback
    minar::Scheduler::postCallback(demoCallbackTask);
}

void saveWifi(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: saving wifi details\r\n");
    (void) req;
    (void) res;

    VTIntentInvocation invocation(req.getBody());

    invocation.getParameters().find("ssid").getString(ssid_string);
    invocation.getParameters().find("key").getString(key_string);

    // change state in main application
    state |= FLAG_PROVISIONED;

    // change state inside Voytalk hub
    router.setStateMask(state);

    next();
}

void resetDevice(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: reset device\r\n");
    (void) req;
    (void) res;

    ssid_string = "";
    key_string = "";

    // change state in main application
    state &= ~FLAG_PROVISIONED;

    // change state inside Voytalk hub
    router.setStateMask(state);

    next();
}

void sendSuccess(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: sending success coda\r\n");
    (void) req;

    VTIntentInvocation invocation(req.getBody());
    VTCoda coda(invocation.getID());
    coda.success(true);
    res.write(coda);
    next(200);
}

void networkList(VTRequest& req, VTResponse& res, VoytalkRouter::next_t& next)
{
    DEBUGOUT("main: listing network resources");
    (void) req;
    (void) res;

    VoytalkKnownParameters parameters(res);

    parameters.begin();

    parameters.parameter("com.arm.connectivity.wifi", 255)
        .map()
            .key("ssid").value("miWifi")
        .end();

    parameters.parameter("com.arm.connectivity.wifi", 125)
        .map()
            .key("ssid").value("yoWifi")
        .end();

    parameters.end();

    next(200);
}

/*****************************************************************************/
/* main                                                                      */
/*****************************************************************************/

void app_start(int, char *[])
{
    /*
        Register Voytalk intents in the hub.

        First parameter is the callback function for intent generation.
        Second parameter is a bitmap for grouping intents together.
    */

    // Wifi provisioning intent
    router.registerIntent(wifiIntentConstruction,
                          FLAG_CONNECTED | FLAG_PROVISIONED);

    // reset intent
    router.registerIntent(resetIntentConstruction,
                          FLAG_PROVISIONED);

    // custom intent
    //router.registerIntent(customIntentConstruction,
    //                     FLAG_CONNECTED | FLAG_PROVISIONED);

    // example intent
    router.registerIntent(exampleIntentConstruction,
                         FLAG_CONNECTED | FLAG_PROVISIONED);

    /*
        Set the current state mask.

        Mask is AND'ed with each intent's bitmap and only intents with non-zero
        results are displayed and can be invoked.
    */
    router.setStateMask(0);

    /*
        Define some resource callbacks
    */

    router.get("/networks",          networkList,                               NULL);
    router.post("/wifi",             printInvocation, saveWifi,    sendSuccess, NULL);
    router.post("/reset",            printInvocation, resetDevice, sendSuccess, NULL);
    router.post("/custom",           printInvocation,              sendSuccess, NULL);
    router.post("/examples/complex", printInvocation,              sendSuccess, NULL);

    /*************************************************************************/
    /*************************************************************************/
    /* bluetooth le */
    ble.init();

    // status callback functions
    ble.gap().onConnection(whenConnected);
    ble.gap().onDisconnection(whenDisconnected);

    /* construct advertising beacon */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED|GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, uuid.getBaseUUID(), uuid.getLen());
    ble.gap().accumulateAdvertisingPayloadTxPower(CFG_BLE_TX_POWER_LEVEL);

    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1s; in multiples of 0.625ms. */

    // set TX power
    ble.gap().setTxPower(CFG_BLE_TX_POWER_LEVEL);

    // Apple uses device name instead of beacon name
    ble.gap().setDeviceName((const uint8_t*) DEVICE_NAME);

    /*************************************************************************/
    /*************************************************************************/
    // setup block transfer service

    // add service using ble device, responding to uuid, and without encryption
    bts.init(uuid, SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK);

    // set callback functions for the BlockTransfer service
    bts.setWriteAuthorizationCallback(blockServerWriteHandler);
    bts.setReadAuthorizationCallback(blockServerReadHandler);

    // ble setup complete - start advertising
    ble.gap().startAdvertising();

    printf("Voytalk Test: %s %s\r\n", __DATE__, __TIME__);
}

/*****************************************************************************/
/* Compatibility                                                             */
/*****************************************************************************/

#if defined(YOTTA_MINAR_VERSION_STRING)
/*********************************************************/
/* Build for mbed OS                                     */
/*********************************************************/

void signalReady()
{
    minar::Scheduler::postCallback(blockServerSendNotification);
}

#else
/*********************************************************/
/* Build for mbed Classic                                */
/*********************************************************/

volatile bool sendNotification = false;

void signalReady()
{
    sendNotification = true;
}

int main(void)
{
    app_start(0, NULL);

    for(;;)
    {
        // send notification outside of interrupt context
        if (sendNotification)
        {
            sendNotification = false;
            blockServerSendNotification();
        }

        ble.waitForEvent();
    }
}
#endif

<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */

#include "mbed-drivers/mbed.h"
#include "ble/BLE.h"
#include "EddystoneService.h"

BLE ble;
EddystoneService *eddyServicePtr;

/* Duration after power-on that config service is available. */
static const int CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS = 30;

DigitalOut led(LED1, 1);

/**
 * Callback triggered upon a disconnection event.
 */
static void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
{
    (void) cbParams;
    ble.gap().startAdvertising();
}

/**
 * Callback triggered some time after application started to switch to beacon mode.
 */
static void timeout(void)
{
    Gap::GapState_t state;
    state = ble.getGapState();
    if (!state.connected) { /* don't switch if we're in a connected state. */
        EddystoneService::EddystoneParams_t eddyParams;
        eddyServicePtr->startBeaconService(5, 5, 5);
    } else {
        minar::Scheduler::postCallback(timeout).delay(minar::milliseconds(CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS * 1000));
    }
}

static void blinky(void)
{
    led = !led;
}

static void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext)
{
    /* Initialization error handling goes here... */
    (void) initContext;
}

static void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext)
{
    BLE         &ble  = initContext->ble;
    ble_error_t error = initContext->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(initContext);
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);

    /* Set UID and TLM frame data */
    const EddystoneService::UIDNamespaceID_t uidNamespaceID = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
    const EddystoneService::UIDInstanceID_t  uidInstanceID = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
    uint8_t tlmVersion = 0x00;

    /* Initialize a EddystoneBeaconConfig service providing config params, default URI, and power levels. */
    static const EddystoneService::PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13}; // Values for ADV packets related to firmware levels, calibrated based on measured values at 1m
    static const EddystoneService::PowerLevels_t radioPowerLevels      = {-30, -16, -4, 4};    // Values for radio power levels, provided by manufacturer.

    /* Set everything to defaults */
    eddyServicePtr = new EddystoneService(ble, defaultAdvPowerLevels, radioPowerLevels, 500);

    /* Set default URL, UID and TLM frame data if not initialized through the config service */
    eddyServicePtr->setURLData("http://mbed.org");
    eddyServicePtr->setUIDData(&uidNamespaceID, &uidInstanceID);
    eddyServicePtr->setTLMData(tlmVersion);

    /* Start Eddystone in config mode */
    eddyServicePtr->startConfigService();

    minar::Scheduler::postCallback(timeout).delay(minar::milliseconds(CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS * 1000));
}

void app_start(int, char *[])
{
    /* Tell standard C library to not allocate large buffers for these streams */
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
    setbuf(stdin, NULL);

    minar::Scheduler::postCallback(blinky).period(minar::milliseconds(500));

    ble.init(bleInitComplete);
}
<commit_msg>Remove unused variable from Eddystone example<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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.
 */

#include "mbed-drivers/mbed.h"
#include "ble/BLE.h"
#include "EddystoneService.h"

BLE ble;
EddystoneService *eddyServicePtr;

/* Duration after power-on that config service is available. */
static const int CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS = 30;

DigitalOut led(LED1, 1);

/**
 * Callback triggered upon a disconnection event.
 */
static void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
{
    (void) cbParams;
    ble.gap().startAdvertising();
}

/**
 * Callback triggered some time after application started to switch to beacon mode.
 */
static void timeout(void)
{
    Gap::GapState_t state;
    state = ble.getGapState();
    if (!state.connected) { /* don't switch if we're in a connected state. */
        eddyServicePtr->startBeaconService(5, 5, 5);
    } else {
        minar::Scheduler::postCallback(timeout).delay(minar::milliseconds(CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS * 1000));
    }
}

static void blinky(void)
{
    led = !led;
}

static void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext)
{
    /* Initialization error handling goes here... */
    (void) initContext;
}

static void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext)
{
    BLE         &ble  = initContext->ble;
    ble_error_t error = initContext->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(initContext);
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);

    /* Set UID and TLM frame data */
    const EddystoneService::UIDNamespaceID_t uidNamespaceID = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
    const EddystoneService::UIDInstanceID_t  uidInstanceID = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
    uint8_t tlmVersion = 0x00;

    /* Initialize a EddystoneBeaconConfig service providing config params, default URI, and power levels. */
    static const EddystoneService::PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13}; // Values for ADV packets related to firmware levels, calibrated based on measured values at 1m
    static const EddystoneService::PowerLevels_t radioPowerLevels      = {-30, -16, -4, 4};    // Values for radio power levels, provided by manufacturer.

    /* Set everything to defaults */
    eddyServicePtr = new EddystoneService(ble, defaultAdvPowerLevels, radioPowerLevels, 500);

    /* Set default URL, UID and TLM frame data if not initialized through the config service */
    eddyServicePtr->setURLData("http://mbed.org");
    eddyServicePtr->setUIDData(&uidNamespaceID, &uidInstanceID);
    eddyServicePtr->setTLMData(tlmVersion);

    /* Start Eddystone in config mode */
    eddyServicePtr->startConfigService();

    minar::Scheduler::postCallback(timeout).delay(minar::milliseconds(CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS * 1000));
}

void app_start(int, char *[])
{
    /* Tell standard C library to not allocate large buffers for these streams */
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
    setbuf(stdin, NULL);

    minar::Scheduler::postCallback(blinky).period(minar::milliseconds(500));

    ble.init(bleInitComplete);
}
<|endoftext|>


<commit_before>#include <iostream>

#include "computeparity.h"
#include "unittest.h"
#include "testsuite.h"
#include "narytree.h"
#include "convertbase.h"
#include "queens.h"
#include "listcycle.h"
#include "pairsum.h"
#include "maxstack.h"
#include "binarytree.h"
#include "binarysearch.h"
#include "hashletter.h"
#include "dynamicprogramming.h"
#include "sorting.h"
#include "heapmerge.h"
#include "powerset.h"

using namespace std;

/*!
 * Main entry point for code.
 * Executes all tests.
 */
int main(int argc, char *argv[])
{
	bool verbose = false;

    // Initialize test suite
    TestSuite tests;

    // Test 1
    ComputeParity parity;
    tests.addTest(&parity);

    // Test 2
    NaryTree tree;
    tests.addTest(&tree);

    // Test 3
    ConvertBase base;
    tests.addTest(&base);

    // Test 4
    Queens queens(verbose);
    tests.addTest(&queens);

    // Test 5
    ListCycle cycle;
    tests.addTest(&cycle);

    // Test 6
    PairSum pair;
    tests.addTest(&pair);

    // Test 7
    MaxStack stack;
    tests.addTest(&stack);

    // Test 8
    BinaryTree binary;
    tests.addTest(&binary);

    // Test 9
    HeapMerge heap;
    tests.addTest(&heap);

    // Test 10
    BinarySearch search;
    tests.addTest(&search);

    // Test 11
    HashLetter hash;
    tests.addTest(&hash);

    // Test 12
    PowerSet set;
    tests.addTest(&set);

    // Test 13
    DynamicProgramming dyno;
    tests.addTest(&dyno);

    // Test 14
    Sorting sorting;
    tests.addTest(&sorting);

    // Run Tests
    tests.test();

	return 0;
}
<commit_msg>Spaces not tabs<commit_after>#include <iostream>

#include "computeparity.h"
#include "unittest.h"
#include "testsuite.h"
#include "narytree.h"
#include "convertbase.h"
#include "queens.h"
#include "listcycle.h"
#include "pairsum.h"
#include "maxstack.h"
#include "binarytree.h"
#include "binarysearch.h"
#include "hashletter.h"
#include "dynamicprogramming.h"
#include "sorting.h"
#include "heapmerge.h"
#include "powerset.h"

using namespace std;

/*!
 * Main entry point for code.
 * Executes all tests.
 */
int main(int argc, char *argv[])
{
    bool verbose = false;

    // Initialize test suite
    TestSuite tests;

    // Test 1
    ComputeParity parity;
    tests.addTest(&parity);

    // Test 2
    NaryTree tree;
    tests.addTest(&tree);

    // Test 3
    ConvertBase base;
    tests.addTest(&base);

    // Test 4
    Queens queens(verbose);
    tests.addTest(&queens);

    // Test 5
    ListCycle cycle;
    tests.addTest(&cycle);

    // Test 6
    PairSum pair;
    tests.addTest(&pair);

    // Test 7
    MaxStack stack;
    tests.addTest(&stack);

    // Test 8
    BinaryTree binary;
    tests.addTest(&binary);

    // Test 9
    HeapMerge heap;
    tests.addTest(&heap);

    // Test 10
    BinarySearch search;
    tests.addTest(&search);

    // Test 11
    HashLetter hash;
    tests.addTest(&hash);

    // Test 12
    PowerSet set;
    tests.addTest(&set);

    // Test 13
    DynamicProgramming dyno;
    tests.addTest(&dyno);

    // Test 14
    Sorting sorting;
    tests.addTest(&sorting);

    // Run Tests
    tests.test();

    return 0;
}
<|endoftext|>


<commit_before>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    cout << "Hello World!";
}

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

}

//--------------------------------------------------------------
void ofApp::draw(){

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    switch (key){

        case 'f':
        case 'F':
            ofToggleFullscreen();
            break;

        default:
            break;
    }

}

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

}

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

}

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

}

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

}

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

}

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

}

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

}

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

}
<commit_msg>namespace declarations<commit_after>#include "ofApp.h"

using namespace ofxCv;
using namespace cv;

//--------------------------------------------------------------
void ofApp::setup(){
    cout << "Hello World!";
}

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

}

//--------------------------------------------------------------
void ofApp::draw(){

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    switch (key){

        case 'f':
        case 'F':
            ofToggleFullscreen();
            break;

        default:
            break;
    }

}

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

}

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

}

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

}

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

}

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

}

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

}

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

}

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

}
<|endoftext|>


<commit_before>
#include "precompiled.h"

void ofApp::setup() {
  // load json
  ofxJSON json;
  json.open("game.json");

  sceneMgr_ = ofxSceneManager::instance();

  // シーンを追加
  sceneMgr_->addScene(new GameTitle(), TITLE);
  sceneMgr_->addScene(new GameMain(),  GAME);
  sceneMgr_->addScene(new Sandbox(),   SANDBOX);

  // 指定したデフォルトのシーンへ遷移
  int ds = json["defaultScene"].asInt();
  sceneMgr_->goToScene(ds, false, false);

  // 遷移のフェード時間を設定
  float dt = json["fade"]["dropTime"].asFloat();
  float dr = json["fade"]["riseTime"].asFloat();
  sceneMgr_->setCurtainDropTime(dt);
  sceneMgr_->setCurtainRiseTime(dr);

  acc_ = json["acceleration"].asFloat();

  gui_.setup();
}

void ofApp::update() {
  float dt = ofGetLastFrameTime() * acc_;
  sceneMgr_->update(dt);
}

void ofApp::draw() {
  sceneMgr_->draw();

  // guiの描画
  gui_.begin();
   ImGui::Begin("Root");
    ImGui::Text("%s", string("width  :" + ofToString(ofGetWidth())).c_str());
    ImGui::Text("%s", string("height :" + ofToString(ofGetHeight())).c_str());
    ImGui::Text("%s", string("FPS :" + ofToString(ofGetFrameRate() , 1)).c_str());

    ImGui::SliderFloat("Acceleration", &acc_, 0, 3);

    if (ImGui::Button("scene change to GameTitle")) { sceneMgr_->goToScene(TITLE);   }
    if (ImGui::Button("scene change to GameMain"))  { sceneMgr_->goToScene(GAME);    }
    if (ImGui::Button("scene change to Sandbox"))   { sceneMgr_->goToScene(SANDBOX); }
   ImGui::End();
  gui_.end();
}
<commit_msg>各sceneからImGuiが使えるようにした<commit_after>
#include "precompiled.h"

void ofApp::setup() {
  // load json
  ofxJSON json;
  json.open("game.json");

  sceneMgr_ = ofxSceneManager::instance();

  // シーンを追加
  sceneMgr_->addScene(new GameTitle(), TITLE);
  sceneMgr_->addScene(new GameMain(),  GAME);
  sceneMgr_->addScene(new Sandbox(),   SANDBOX);

  // 指定したデフォルトのシーンへ遷移
  int ds = json["defaultScene"].asInt();
  sceneMgr_->goToScene(ds, false, false);

  // 遷移のフェード時間を設定
  float dt = json["fade"]["dropTime"].asFloat();
  float dr = json["fade"]["riseTime"].asFloat();
  sceneMgr_->setCurtainDropTime(dt);
  sceneMgr_->setCurtainRiseTime(dr);

  acc_ = json["acceleration"].asFloat();

  gui_.setup();
}

void ofApp::update() {
  float dt = ofGetLastFrameTime() * acc_;
  sceneMgr_->update(dt);
}

void ofApp::draw() {
  gui_.begin();

   sceneMgr_->draw();

   ImGui::Begin("Root");
    ImGui::Text("%s", string("width  :" + ofToString(ofGetWidth())).c_str());
    ImGui::Text("%s", string("height :" + ofToString(ofGetHeight())).c_str());
    ImGui::Text("%s", string("FPS :" + ofToString(ofGetFrameRate() , 1)).c_str());

    ImGui::SliderFloat("Acceleration", &acc_, 0, 3);

    if (ImGui::Button("scene change to GameTitle")) { sceneMgr_->goToScene(TITLE);   }
    if (ImGui::Button("scene change to GameMain"))  { sceneMgr_->goToScene(GAME);    }
    if (ImGui::Button("scene change to Sandbox"))   { sceneMgr_->goToScene(SANDBOX); }
   ImGui::End();

  gui_.end();
}
<|endoftext|>


<commit_before>// BEGIN_COPYRIGHT
// END_COPYRIGHT
#ifndef HADOOP_PIPES_HPP
#define HADOOP_PIPES_HPP

// Python 2.6 macro. Needed when compiling with older versions.
#ifndef Py_REFCNT
#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
#endif

#include <string>

#include <hadoop/SerialUtils.hh>
#include "pipes_context.hpp"
#include "exceptions.hpp"

namespace hu = HadoopUtils;
namespace hp = HadoopPipes;

struct cxx_capsule {

  cxx_capsule() {
    in_cxx_land = false;
  };

  void entering_cxx_land(bool flag=true) {
    in_cxx_land = flag;
  }

  bool in_cxx_land;

};

#define DESTROY_PYTHON_TOO(wobj_t)                                   \
    if (in_cxx_land) {                                               \
      bp::reference_existing_object::apply<wobj_t*>::type converter; \
      PyObject* self = converter(this);                              \
      while (Py_REFCNT(self) > 0){Py_DECREF(self);}                  \
    }

struct wrap_mapper: hp::Mapper, bp::wrapper<hp::Mapper>, cxx_capsule {

  void map(hp::MapContext& ctx) {
    bp::reference_existing_object::apply<hp::MapContext&>::type converter;
    PyObject* obj = converter(ctx);
    bp::object po = bp::object(bp::handle<>(bp::borrowed(obj)));
    this->get_override("map")(po);
  }
  virtual ~wrap_mapper() {
    DESTROY_PYTHON_TOO(wrap_mapper);
  }
};

struct wrap_reducer: hp::Reducer, bp::wrapper<hp::Reducer>, cxx_capsule {
  void reduce(hp::ReduceContext& ctx) {
    bp::reference_existing_object::apply<hp::ReduceContext&>::type converter;
    PyObject* obj = converter(ctx);
    bp::object po = bp::object(bp::handle<>(bp::borrowed(obj)));
    this->get_override("reduce")(po);
  }
  virtual ~wrap_reducer() {
    DESTROY_PYTHON_TOO(wrap_reducer);
  }
};

struct wrap_partitioner: hp::Partitioner, bp::wrapper<hp::Partitioner>, cxx_capsule {
  int partition(const std::string& key, int numOfReduces) {
    return this->get_override("partition")(key, numOfReduces);
  }
  virtual ~wrap_partitioner() {
    DESTROY_PYTHON_TOO(wrap_partitioner);
  }
};

struct wrap_record_reader: hp::RecordReader, bp::wrapper<hp::RecordReader>, cxx_capsule {
  bool next(std::string& key, std::string& value) {
    // t = (bool got_record, str key, str value)
    bp::tuple t = this->get_override("next")();
    if (!t[0]) {
      return false;
    }
    bp::extract<std::string> k(t[1]);
    if (k.check()) {
      key = k;
    } else {
      throw pipes_exception("RecordReader:: overloaded method is not returning a proper key.");
    }
    bp::extract<std::string> v(t[2]);
    if (v.check()) {
      value = v;
    } else {
      throw pipes_exception("RecordReader:: overloaded method is not returning a proper value.");
    }
    return true;
  }
  float getProgress() {
    return this->get_override("getProgress")();
  }
  virtual ~wrap_record_reader() {
    DESTROY_PYTHON_TOO(wrap_record_reader);
  }
};

struct wrap_record_writer: hp::RecordWriter, bp::wrapper<hp::RecordWriter>, cxx_capsule {
  void emit(const std::string& key, const std::string& value) {
    this->get_override("emit")(key, value);
  }
  virtual ~wrap_record_writer() {
    DESTROY_PYTHON_TOO(wrap_record_writer);
  }
};

#define CREATE_AND_RETURN_OBJECT(wobj_t, obj_t, ctx_t, method_name, ctx) \
    bp::reference_existing_object::apply<ctx_t&>::type converter;\
    PyObject* po_ctx = converter(ctx);\
    bp::object o_ctx = bp::object(bp::handle<>(bp::borrowed(po_ctx)));\
    bp::override f = this->get_override(#method_name);\
    if (f) {\
      bp::object res = f(o_ctx);\
      std::auto_ptr<wobj_t> ap = bp::extract<std::auto_ptr<wobj_t> >(res);\
      PyObject* obj = res.ptr();\
      Py_INCREF(obj);\
      wobj_t* o = ap.get();\
      ap.release();\
      o->entering_cxx_land();\
      return o;\
    } else {\
      return NULL;\
    }

struct wrap_factory: hp::Factory, bp::wrapper<hp::Factory> {

  hp::Mapper* createMapper(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_mapper, hp::Mapper, hp::MapContext,
			     createMapper, ctx);
  }

  hp::Reducer* createReducer(hp::ReduceContext& ctx) const{
    CREATE_AND_RETURN_OBJECT(wrap_reducer, hp::Reducer, hp::ReduceContext,
			     createReducer, ctx);
  }

  hp::RecordReader* createRecordReader(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_record_reader, hp::RecordReader,
			     hp::MapContext, createRecordReader, ctx);
  }

  hp::Reducer* createCombiner(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_reducer, hp::Reducer, hp::MapContext,
			     createCombiner, ctx);
  }

  hp::Partitioner* createPartitioner(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_partitioner, hp::Partitioner, hp::MapContext,
			     createPartitioner, ctx);
  }

  hp::RecordWriter* createRecordWriter(hp::ReduceContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_record_writer, hp::RecordWriter,
			     hp::ReduceContext, createRecordWriter, ctx);
  }

};

#endif // HADOOP_PIPES_HPP
<commit_msg>memory leaks leaking<commit_after>// BEGIN_COPYRIGHT
// END_COPYRIGHT
#ifndef HADOOP_PIPES_HPP
#define HADOOP_PIPES_HPP

// Python 2.6 macro. Needed when compiling with older versions.
#ifndef Py_REFCNT
#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
#endif

#include <string>

#include <hadoop/SerialUtils.hh>
#include "pipes_context.hpp"
#include "exceptions.hpp"

namespace hu = HadoopUtils;
namespace hp = HadoopPipes;

struct cxx_capsule {

  cxx_capsule() {
    in_cxx_land = false;
  };

  void entering_cxx_land(bool flag=true) {
    in_cxx_land = flag;
  }

  bool in_cxx_land;

};

#define DESTROY_PYTHON_TOO(wobj_t)                                   \
    if (in_cxx_land) {                                               \
      bp::reference_existing_object::apply<wobj_t*>::type converter; \
      PyObject* self = converter(this);                              \
      while (Py_REFCNT(self) > 0){Py_DECREF(self);}                  \
    }

struct wrap_mapper: hp::Mapper, bp::wrapper<hp::Mapper>, cxx_capsule {

  void map(hp::MapContext& ctx) {
#if 0
    bp::reference_existing_object::apply<hp::MapContext&>::type converter;
    PyObject* obj = converter(ctx);
    bp::object po = bp::object(bp::handle<>(bp::borrowed(obj)));
    this->get_override("map")(po);
#else
    bp::reference_existing_object::apply<hp::MapContext&>::type converter;
    PyObject* obj = converter(ctx);
    bp::object po = bp::object(bp::handle<>(obj))
    this->get_override("map")(po);
    while (Py_REFCNT(obj) > 0){Py_DECREF(obj);}
    //bp::decref(obj);
#endif
  }
  virtual ~wrap_mapper() {
    DESTROY_PYTHON_TOO(wrap_mapper);
  }
};

struct wrap_reducer: hp::Reducer, bp::wrapper<hp::Reducer>, cxx_capsule {
  void reduce(hp::ReduceContext& ctx) {
#if 0
    bp::reference_existing_object::apply<hp::ReduceContext&>::type converter;
    PyObject* obj = converter(ctx);
    bp::object po = bp::object(bp::handle<>(bp::borrowed(obj)));
    this->get_override("reduce")(po);
#else
    bp::reference_existing_object::apply<hp::ReduceContext&>::type converter;
    PyObject* obj = converter(ctx);
    bp::object po = bp::object(bp::handle<>(obj));
    this->get_override("reduce")(po);
    while (Py_REFCNT(obj) > 0){Py_DECREF(obj);}
    //bp::decref(obj);
#endif
  }
  virtual ~wrap_reducer() {
    DESTROY_PYTHON_TOO(wrap_reducer);
  }
};

struct wrap_partitioner: hp::Partitioner, bp::wrapper<hp::Partitioner>, cxx_capsule {
  int partition(const std::string& key, int numOfReduces) {
    return this->get_override("partition")(key, numOfReduces);
  }
  virtual ~wrap_partitioner() {
    DESTROY_PYTHON_TOO(wrap_partitioner);
  }
};

struct wrap_record_reader: hp::RecordReader, bp::wrapper<hp::RecordReader>, cxx_capsule {
  bool next(std::string& key, std::string& value) {
    // t = (bool got_record, str key, str value)
    bp::tuple t = this->get_override("next")();
    if (!t[0]) {
      return false;
    }
    bp::extract<std::string> k(t[1]);
    if (k.check()) {
      key = k;
    } else {
      throw pipes_exception("RecordReader:: overloaded method is not returning a proper key.");
    }
    bp::extract<std::string> v(t[2]);
    if (v.check()) {
      value = v;
    } else {
      throw pipes_exception("RecordReader:: overloaded method is not returning a proper value.");
    }
    return true;
  }
  float getProgress() {
    return this->get_override("getProgress")();
  }
  virtual ~wrap_record_reader() {
    DESTROY_PYTHON_TOO(wrap_record_reader);
  }
};

struct wrap_record_writer: hp::RecordWriter, bp::wrapper<hp::RecordWriter>, cxx_capsule {
  void emit(const std::string& key, const std::string& value) {
    this->get_override("emit")(key, value);
  }
  virtual ~wrap_record_writer() {
    DESTROY_PYTHON_TOO(wrap_record_writer);
  }
};

#define CREATE_AND_RETURN_OBJECT(wobj_t, obj_t, ctx_t, method_name, ctx) \
    bp::reference_existing_object::apply<ctx_t&>::type converter;\
    PyObject* po_ctx = converter(ctx);\
    bp::object o_ctx = bp::object(bp::handle<>(bp::borrowed(po_ctx)));\
    bp::override f = this->get_override(#method_name);\
    if (f) {\
      bp::object res = f(o_ctx);\
      std::auto_ptr<wobj_t> ap = bp::extract<std::auto_ptr<wobj_t> >(res);\
      PyObject* obj = res.ptr();\
      Py_INCREF(obj);\
      wobj_t* o = ap.get();\
      ap.release();\
      o->entering_cxx_land();\
      return o;\
    } else {\
      return NULL;\
    }

struct wrap_factory: hp::Factory, bp::wrapper<hp::Factory> {

  hp::Mapper* createMapper(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_mapper, hp::Mapper, hp::MapContext,
			     createMapper, ctx);
  }

  hp::Reducer* createReducer(hp::ReduceContext& ctx) const{
    CREATE_AND_RETURN_OBJECT(wrap_reducer, hp::Reducer, hp::ReduceContext,
			     createReducer, ctx);
  }

  hp::RecordReader* createRecordReader(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_record_reader, hp::RecordReader,
			     hp::MapContext, createRecordReader, ctx);
  }

  hp::Reducer* createCombiner(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_reducer, hp::Reducer, hp::MapContext,
			     createCombiner, ctx);
  }

  hp::Partitioner* createPartitioner(hp::MapContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_partitioner, hp::Partitioner, hp::MapContext,
			     createPartitioner, ctx);
  }

  hp::RecordWriter* createRecordWriter(hp::ReduceContext& ctx) const {
    CREATE_AND_RETURN_OBJECT(wrap_record_writer, hp::RecordWriter,
			     hp::ReduceContext, createRecordWriter, ctx);
  }

};

#endif // HADOOP_PIPES_HPP
<|endoftext|>


<commit_before>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef RDB_PROTOCOL_CHANGEFEED_HPP_
#define RDB_PROTOCOL_CHANGEFEED_HPP_

#include <deque>
#include <exception>
#include <map>
#include <string>

#include "errors.hpp"
#include <boost/variant.hpp>

#include "concurrency/rwlock.hpp"
#include "containers/counted.hpp"
#include "containers/scoped.hpp"
#include "protocol_api.hpp"
#include "rdb_protocol/counted_term.hpp"
#include "region/region.hpp"
#include "region/region.hpp"
#include "repli_timestamp.hpp"
#include "rpc/connectivity/peer_id.hpp"
#include "rpc/mailbox/typed.hpp"
#include "rpc/serialize_macros.hpp"

class auto_drainer_t;
class namespace_interface_access_t;
class mailbox_manager_t;
struct rdb_modification_report_t;

namespace ql {

class base_exc_t;
class batcher_t;
class datum_stream_t;
class datum_t;
class env_t;
class table_t;

namespace changefeed {

struct msg_t {
    struct change_t {
        change_t();
        explicit change_t(counted_t<const datum_t> _old_val,
                          counted_t<const datum_t> _new_val);
        ~change_t();
        counted_t<const datum_t> old_val, new_val;
        RDB_DECLARE_ME_SERIALIZABLE;
    };
    struct stop_t {
    };

    msg_t() { }
    msg_t(msg_t &&msg);
    explicit msg_t(stop_t &&op);
    explicit msg_t(change_t &&op);

    // We need to define the copy constructor.  GCC 4.4 doesn't let use use `=
    // default`, and SRH is uncomfortable violating the rule of 3, so we define
    // the destructor and assignment operator as well.
    msg_t(const msg_t &msg) : op(msg.op) { }
    ~msg_t() { }
    const msg_t &operator=(const msg_t &msg) {
        op = msg.op;
        return *this;
    }

    // Starts with STOP to avoid doing work for default initialization.
    boost::variant<stop_t, change_t> op;
};

RDB_SERIALIZE_OUTSIDE(msg_t::change_t);
RDB_DECLARE_SERIALIZABLE(msg_t::stop_t);
RDB_DECLARE_SERIALIZABLE(msg_t);

class feed_t;
struct stamped_msg_t;

typedef mailbox_addr_t<void(stamped_msg_t)> client_addr_t;

struct keyspec_t {
    struct all_t { };
    struct point_t {
        point_t() { }
        explicit point_t(counted_t<const datum_t> _key) : key(std::move(_key)) { }
        counted_t<const datum_t> key;
    };

    keyspec_t(keyspec_t &&keyspec) = default;
    explicit keyspec_t(all_t &&all) : spec(std::move(all)) { }
    explicit keyspec_t(point_t &&point) : spec(std::move(point)) { }

    // This needs to be copyable and assignable because it goes inside a
    // `changefeed_stamp_t`, which goes inside a variant.
    keyspec_t(const keyspec_t &keyspec) = default;
    keyspec_t &operator=(const keyspec_t &) = default;

    boost::variant<all_t, point_t> spec;
private:
    keyspec_t() { }
};
region_t keyspec_to_region(const keyspec_t &keyspec);

RDB_DECLARE_SERIALIZABLE(keyspec_t::all_t);
RDB_DECLARE_SERIALIZABLE(keyspec_t::point_t);
RDB_DECLARE_SERIALIZABLE(keyspec_t);

// The `client_t` exists on the machine handling the changefeed query, in the
// `rdb_context_t`.  When a query subscribes to the changes on a table, it
// should call `new_feed`.  The `client_t` will give it back a stream of rows.
// The `client_t` does this by maintaining an internal map from table UUIDs to
// `feed_t`s.  (It does this so that there is at most one `feed_t` per <table,
// client> pair, to prevent redundant cluster messages.)  The actual logic for
// subscribing to a changefeed server and distributing writes to streams can be
// found in the `feed_t` class.
class client_t : public home_thread_mixin_t {
public:
    typedef client_addr_t addr_t;
    client_t(
        mailbox_manager_t *_manager,
        const std::function<
            namespace_interface_access_t(
                const namespace_id_t &,
                signal_t *)
            > &_namespace_source
        );
    ~client_t();
    // Throws QL exceptions.
    counted_t<datum_stream_t> new_feed(env_t *env, const namespace_id_t &table,
        const protob_t<const Backtrace> &bt, const std::string &table_name,
        const std::string &pkey, keyspec_t &&keyspec);
    void maybe_remove_feed(const namespace_id_t &uuid);
    scoped_ptr_t<feed_t> detach_feed(const namespace_id_t &uuid);
private:
    friend class subscription_t;
    mailbox_manager_t *const manager;
    std::function<
        namespace_interface_access_t(
            const namespace_id_t &,
            signal_t *)
        > const namespace_source;
    std::map<namespace_id_t, scoped_ptr_t<feed_t> > feeds;
    // This lock manages access to the `feeds` map.  The `feeds` map needs to be
    // read whenever `new_feed` is called, and needs to be written to whenever
    // `new_feed` is called with a table not already in the `feeds` map, or
    // whenever `maybe_remove_feed` or `detach_feed` is called.
    //
    // This lock is held for a long time when `new_feed` is called with a table
    // not already in the `feeds` map (in fact, it's held long enough to do a
    // cluster read).  This should only be a problem if the number of tables
    // (*not* the number of feeds) is large relative to read throughput, because
    // otherwise most of the calls to `new_feed` that block will see the table
    // as soon as they're woken up and won't have to do a second read.
    rwlock_t feeds_lock;
    auto_drainer_t drainer;
};

typedef mailbox_addr_t<void(client_addr_t)> server_addr_t;

// There is one `server_t` per `store_t`, and it is used to send changes that
// occur on that `store_t` to any subscribed `feed_t`s contained in a
// `client_t`.
class server_t {
public:
    typedef server_addr_t addr_t;
    explicit server_t(mailbox_manager_t *_manager);
    ~server_t();
    void add_client(const client_t::addr_t &addr, region_t region);
    // `key` should be non-NULL if there is a key associated with the message.
    void send_all(msg_t msg, const store_key_t *key);
    void stop_all();
    addr_t get_stop_addr();
    uint64_t get_stamp(const client_t::addr_t &addr);
    uuid_u get_uuid();
private:
    void send_all_with_lock(const auto_drainer_t::lock_t &lock,
                            msg_t msg, const store_key_t *key);
    void stop_mailbox_cb(client_t::addr_t addr);
    void add_client_cb(signal_t *stopped, client_t::addr_t addr);

    // The UUID of the server, used so that `feed_t`s can enforce on ordering on
    // changefeed messages on a per-server basis (and drop changefeed messages
    // from before their own creation timestamp on a per-server basis).
    const uuid_u uuid;
    mailbox_manager_t *const manager;

    struct client_info_t {
        scoped_ptr_t<cond_t> cond;
        uint64_t stamp;
        std::vector<region_t> regions;
    };
    std::map<client_t::addr_t, client_info_t> clients;
    // Controls access to `clients`.  A `server_t` needs to read `clients` when:
    // * `send_all` is called
    // * `get_stamp` is called
    // And needs to write to clients when:
    // * `add_client` is called
    // * `clear` is called
    // * A message is received at `stop_mailbox` unsubscribing a client
    // A lock is needed because e.g. `send_all` calls `send`, which can block,
    // while looping over `clients`, and we need to make sure the map doesn't
    // change under it.
    rwlock_t clients_lock;

    // Clients send a message to this mailbox with their address when they want
    // to unsubscribe.
    mailbox_t<void(client_t::addr_t)> stop_mailbox;
    auto_drainer_t drainer;
};

} // namespace changefeed
} // namespace ql

#endif // RDB_PROTOCOL_CHANGEFEED_HPP_

<commit_msg>Removed duplicate header.<commit_after>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef RDB_PROTOCOL_CHANGEFEED_HPP_
#define RDB_PROTOCOL_CHANGEFEED_HPP_

#include <deque>
#include <exception>
#include <map>
#include <string>

#include "errors.hpp"
#include <boost/variant.hpp>

#include "concurrency/rwlock.hpp"
#include "containers/counted.hpp"
#include "containers/scoped.hpp"
#include "protocol_api.hpp"
#include "rdb_protocol/counted_term.hpp"
#include "region/region.hpp"
#include "repli_timestamp.hpp"
#include "rpc/connectivity/peer_id.hpp"
#include "rpc/mailbox/typed.hpp"
#include "rpc/serialize_macros.hpp"

class auto_drainer_t;
class namespace_interface_access_t;
class mailbox_manager_t;
struct rdb_modification_report_t;

namespace ql {

class base_exc_t;
class batcher_t;
class datum_stream_t;
class datum_t;
class env_t;
class table_t;

namespace changefeed {

struct msg_t {
    struct change_t {
        change_t();
        explicit change_t(counted_t<const datum_t> _old_val,
                          counted_t<const datum_t> _new_val);
        ~change_t();
        counted_t<const datum_t> old_val, new_val;
        RDB_DECLARE_ME_SERIALIZABLE;
    };
    struct stop_t {
    };

    msg_t() { }
    msg_t(msg_t &&msg);
    explicit msg_t(stop_t &&op);
    explicit msg_t(change_t &&op);

    // We need to define the copy constructor.  GCC 4.4 doesn't let use use `=
    // default`, and SRH is uncomfortable violating the rule of 3, so we define
    // the destructor and assignment operator as well.
    msg_t(const msg_t &msg) : op(msg.op) { }
    ~msg_t() { }
    const msg_t &operator=(const msg_t &msg) {
        op = msg.op;
        return *this;
    }

    // Starts with STOP to avoid doing work for default initialization.
    boost::variant<stop_t, change_t> op;
};

RDB_SERIALIZE_OUTSIDE(msg_t::change_t);
RDB_DECLARE_SERIALIZABLE(msg_t::stop_t);
RDB_DECLARE_SERIALIZABLE(msg_t);

class feed_t;
struct stamped_msg_t;

typedef mailbox_addr_t<void(stamped_msg_t)> client_addr_t;

struct keyspec_t {
    struct all_t { };
    struct point_t {
        point_t() { }
        explicit point_t(counted_t<const datum_t> _key) : key(std::move(_key)) { }
        counted_t<const datum_t> key;
    };

    keyspec_t(keyspec_t &&keyspec) = default;
    explicit keyspec_t(all_t &&all) : spec(std::move(all)) { }
    explicit keyspec_t(point_t &&point) : spec(std::move(point)) { }

    // This needs to be copyable and assignable because it goes inside a
    // `changefeed_stamp_t`, which goes inside a variant.
    keyspec_t(const keyspec_t &keyspec) = default;
    keyspec_t &operator=(const keyspec_t &) = default;

    boost::variant<all_t, point_t> spec;
private:
    keyspec_t() { }
};
region_t keyspec_to_region(const keyspec_t &keyspec);

RDB_DECLARE_SERIALIZABLE(keyspec_t::all_t);
RDB_DECLARE_SERIALIZABLE(keyspec_t::point_t);
RDB_DECLARE_SERIALIZABLE(keyspec_t);

// The `client_t` exists on the machine handling the changefeed query, in the
// `rdb_context_t`.  When a query subscribes to the changes on a table, it
// should call `new_feed`.  The `client_t` will give it back a stream of rows.
// The `client_t` does this by maintaining an internal map from table UUIDs to
// `feed_t`s.  (It does this so that there is at most one `feed_t` per <table,
// client> pair, to prevent redundant cluster messages.)  The actual logic for
// subscribing to a changefeed server and distributing writes to streams can be
// found in the `feed_t` class.
class client_t : public home_thread_mixin_t {
public:
    typedef client_addr_t addr_t;
    client_t(
        mailbox_manager_t *_manager,
        const std::function<
            namespace_interface_access_t(
                const namespace_id_t &,
                signal_t *)
            > &_namespace_source
        );
    ~client_t();
    // Throws QL exceptions.
    counted_t<datum_stream_t> new_feed(env_t *env, const namespace_id_t &table,
        const protob_t<const Backtrace> &bt, const std::string &table_name,
        const std::string &pkey, keyspec_t &&keyspec);
    void maybe_remove_feed(const namespace_id_t &uuid);
    scoped_ptr_t<feed_t> detach_feed(const namespace_id_t &uuid);
private:
    friend class subscription_t;
    mailbox_manager_t *const manager;
    std::function<
        namespace_interface_access_t(
            const namespace_id_t &,
            signal_t *)
        > const namespace_source;
    std::map<namespace_id_t, scoped_ptr_t<feed_t> > feeds;
    // This lock manages access to the `feeds` map.  The `feeds` map needs to be
    // read whenever `new_feed` is called, and needs to be written to whenever
    // `new_feed` is called with a table not already in the `feeds` map, or
    // whenever `maybe_remove_feed` or `detach_feed` is called.
    //
    // This lock is held for a long time when `new_feed` is called with a table
    // not already in the `feeds` map (in fact, it's held long enough to do a
    // cluster read).  This should only be a problem if the number of tables
    // (*not* the number of feeds) is large relative to read throughput, because
    // otherwise most of the calls to `new_feed` that block will see the table
    // as soon as they're woken up and won't have to do a second read.
    rwlock_t feeds_lock;
    auto_drainer_t drainer;
};

typedef mailbox_addr_t<void(client_addr_t)> server_addr_t;

// There is one `server_t` per `store_t`, and it is used to send changes that
// occur on that `store_t` to any subscribed `feed_t`s contained in a
// `client_t`.
class server_t {
public:
    typedef server_addr_t addr_t;
    explicit server_t(mailbox_manager_t *_manager);
    ~server_t();
    void add_client(const client_t::addr_t &addr, region_t region);
    // `key` should be non-NULL if there is a key associated with the message.
    void send_all(msg_t msg, const store_key_t *key);
    void stop_all();
    addr_t get_stop_addr();
    uint64_t get_stamp(const client_t::addr_t &addr);
    uuid_u get_uuid();
private:
    void send_all_with_lock(const auto_drainer_t::lock_t &lock,
                            msg_t msg, const store_key_t *key);
    void stop_mailbox_cb(client_t::addr_t addr);
    void add_client_cb(signal_t *stopped, client_t::addr_t addr);

    // The UUID of the server, used so that `feed_t`s can enforce on ordering on
    // changefeed messages on a per-server basis (and drop changefeed messages
    // from before their own creation timestamp on a per-server basis).
    const uuid_u uuid;
    mailbox_manager_t *const manager;

    struct client_info_t {
        scoped_ptr_t<cond_t> cond;
        uint64_t stamp;
        std::vector<region_t> regions;
    };
    std::map<client_t::addr_t, client_info_t> clients;
    // Controls access to `clients`.  A `server_t` needs to read `clients` when:
    // * `send_all` is called
    // * `get_stamp` is called
    // And needs to write to clients when:
    // * `add_client` is called
    // * `clear` is called
    // * A message is received at `stop_mailbox` unsubscribing a client
    // A lock is needed because e.g. `send_all` calls `send`, which can block,
    // while looping over `clients`, and we need to make sure the map doesn't
    // change under it.
    rwlock_t clients_lock;

    // Clients send a message to this mailbox with their address when they want
    // to unsubscribe.
    mailbox_t<void(client_t::addr_t)> stop_mailbox;
    auto_drainer_t drainer;
};

} // namespace changefeed
} // namespace ql

#endif // RDB_PROTOCOL_CHANGEFEED_HPP_

<|endoftext|>


<commit_before>#pragma once

#include <algorithm>
#include <cstddef>
#include <functional>
#include <queue>
#include <set>
#include <vector>

template<typename T>
class Vertex {
public:
    Vertex() : idx_(-1), data_() {}
    explicit Vertex(int idx) : idx_(idx), data_() {}
    Vertex(int idx, const T &data) : idx_(idx), data_(data) {}
    virtual ~Vertex() = default;

    int idx() const { return idx_; }
    T data() const { return data_; }

    bool operator<(const Vertex<T> &vertex) const {
        return idx_ < vertex.idx_;
    }

private:
    int idx_;
    T data_;
};

template<typename T>
class Edge {
public:
    Edge(int idx1, int idx2) : idx1_(idx1), idx2_(idx2) {}
    virtual ~Edge() = default;
    int idx1() const { return idx1_; }
    int idx2() const { return idx2_; }

private:
    int idx1_;
    int idx2_;
};

template<typename V, typename E>
class GraphI {
public:
    virtual ~GraphI() = default;

    virtual int add_vertex(const Vertex<V> &vertex) = 0;
    virtual int set_vertex(const Vertex<V> &vertex) = 0;
    virtual void rm_vertex(const Vertex<V> &vertex) = 0;
    virtual const std::set<int> &adjacent_vertices(int idx) const = 0;

    virtual const Vertex<V> &vertex(int idx) const = 0;
    virtual int vertex_num() const = 0;

    virtual int add_edge(const Edge<E> &edge) = 0;
    virtual int rm_edge(const Edge<E> &edge) = 0;

    virtual bool bfs(int start_idx, std::function<bool(V)> &pred, std::vector<int> *path) const;
    virtual bool astar(int start_idx, int goal_idx, std::function<float(int, int)> &heuristic, std::vector<int> *path) const;
};

template<typename V, typename E>
bool GraphI<V, E>::bfs(int start_idx, std::function<bool(V)> &pred, std::vector<int> *path) const
{
    int vnum = vertex_num();
    if (start_idx > vnum) {
        return false;
    }

    std::vector<bool> visited(vnum, false);
    std::vector<int> prev(vnum, -1);
    std::vector<int> dist(vnum, vnum + 1);
    std::queue<int> queue;

    bool vertex_found = false;

    queue.push(start_idx);
    dist[start_idx] = 0;
    int end_idx = -1;

    while (!vertex_found && !queue.empty()) {
        int u = queue.front();
        queue.pop();
        if (visited[u]) {
            continue;
        }

        visited[u] = true;

        std::set<int> vertices = adjacent_vertices(u);

        for (auto v : vertices) {
            if (!visited[v]) {
                int alt = dist[u] + 1;
                if (alt < dist[v]) {
                    dist[v] = alt;
                    prev[v] = u;
                }

                queue.push(v);
                if (pred(vertex(v).data())) {
                    vertex_found = true;
                    end_idx = v;
                    break;
                }
            }
        }
    }

    if (vertex_found) {
        int v = end_idx;
        do {
            path->push_back(v);
            v = prev[v];
        } while (v != -1);
        // FIXME
        std::reverse(path->begin(), path->end());
    }

    return vertex_found;
}

int min_idx(const std::set<int> &opened, const std::vector<float> &f_score)
{
    int min_idx = -1;
    float min = std::numeric_limits<float>::max();
    for (auto idx : opened) {
        if ((f_score[idx] < min) || (min_idx == -1)) {
            min_idx = idx;
            min = f_score[idx];
        }
    }
    return min_idx;
}

template<typename V, typename E>
bool GraphI<V, E>::astar(int start_idx, int goal_idx, std::function<float(int, int)> &heuristic, std::vector<int> *path) const
{
    int vnum = vertex_num();

    std::set<int> closed;
    std::set<int> opened;
    std::vector<int> came_from(vnum, -1);
    std::vector<float> g_score(vnum, std::numeric_limits<float>::max());
    std::vector<float> f_score(vnum, std::numeric_limits<float>::max());

    opened.insert(start_idx);

    bool vertex_found = false;
    while (!vertex_found && !opened.empty()) {
        int current = min_idx(opened, f_score);
        if (current == goal_idx) {
            vertex_found = true;
            break;
        }
        opened.erase(current);
        closed.insert(current);

        std::set<int> neighbours = adjacent_vertices(current);
        for (auto neighbour : neighbours) {
            if (closed.count(neighbour) > 0) {
                continue;
            }

            float tentative_score = g_score[current] + 1;
            if (opened.count(neighbour) == 0) {
                opened.insert(neighbour);
            }
            else if (tentative_score >= g_score[neighbour]) {
                continue;
            }

            came_from[neighbour] = current;
            g_score[neighbour] = tentative_score;
            f_score[neighbour] = g_score[neighbour] + heuristic(neighbour, goal_idx);
        }
    }

    if (vertex_found) {
        int idx = goal_idx;
        do {
            path->push_back(idx);
            idx = came_from[idx];
        } while (idx != -1);
        std::reverse(path->begin(), path->end());
    }

    return vertex_found;
}
<commit_msg>Split long lines<commit_after>#pragma once

#include <algorithm>
#include <cstddef>
#include <functional>
#include <queue>
#include <set>
#include <vector>

template<typename T>
class Vertex {
public:
    Vertex() : idx_(-1), data_() {}
    explicit Vertex(int idx) : idx_(idx), data_() {}
    Vertex(int idx, const T &data) : idx_(idx), data_(data) {}
    virtual ~Vertex() = default;

    int idx() const { return idx_; }
    T data() const { return data_; }

    bool operator<(const Vertex<T> &vertex) const {
        return idx_ < vertex.idx_;
    }

private:
    int idx_;
    T data_;
};

template<typename T>
class Edge {
public:
    Edge(int idx1, int idx2) : idx1_(idx1), idx2_(idx2) {}
    virtual ~Edge() = default;
    int idx1() const { return idx1_; }
    int idx2() const { return idx2_; }

private:
    int idx1_;
    int idx2_;
};

template<typename V, typename E>
class GraphI {
public:
    virtual ~GraphI() = default;

    virtual int add_vertex(const Vertex<V> &vertex) = 0;
    virtual int set_vertex(const Vertex<V> &vertex) = 0;
    virtual void rm_vertex(const Vertex<V> &vertex) = 0;
    virtual const std::set<int> &adjacent_vertices(int idx) const = 0;

    virtual const Vertex<V> &vertex(int idx) const = 0;
    virtual int vertex_num() const = 0;

    virtual int add_edge(const Edge<E> &edge) = 0;
    virtual int rm_edge(const Edge<E> &edge) = 0;

    virtual bool bfs(int start_idx, std::function<bool(V)> &pred, std::vector<int> *path) const;
    virtual bool astar(int start_idx, int goal_idx,
            std::function<float(int, int)> &heuristic, std::vector<int> *path) const;
};

template<typename V, typename E>
bool GraphI<V, E>::bfs(int start_idx, std::function<bool(V)> &pred, std::vector<int> *path) const
{
    int vnum = vertex_num();
    if (start_idx > vnum) {
        return false;
    }

    std::vector<bool> visited(vnum, false);
    std::vector<int> prev(vnum, -1);
    std::vector<int> dist(vnum, vnum + 1);
    std::queue<int> queue;

    bool vertex_found = false;

    queue.push(start_idx);
    dist[start_idx] = 0;
    int end_idx = -1;

    while (!vertex_found && !queue.empty()) {
        int u = queue.front();
        queue.pop();
        if (visited[u]) {
            continue;
        }

        visited[u] = true;

        std::set<int> vertices = adjacent_vertices(u);

        for (auto v : vertices) {
            if (!visited[v]) {
                int alt = dist[u] + 1;
                if (alt < dist[v]) {
                    dist[v] = alt;
                    prev[v] = u;
                }

                queue.push(v);
                if (pred(vertex(v).data())) {
                    vertex_found = true;
                    end_idx = v;
                    break;
                }
            }
        }
    }

    if (vertex_found) {
        int v = end_idx;
        do {
            path->push_back(v);
            v = prev[v];
        } while (v != -1);
        // FIXME
        std::reverse(path->begin(), path->end());
    }

    return vertex_found;
}

int min_idx(const std::set<int> &opened, const std::vector<float> &f_score)
{
    int min_idx = -1;
    float min = std::numeric_limits<float>::max();
    for (auto idx : opened) {
        if ((f_score[idx] < min) || (min_idx == -1)) {
            min_idx = idx;
            min = f_score[idx];
        }
    }
    return min_idx;
}

template<typename V, typename E>
bool GraphI<V, E>::astar(int start_idx, int goal_idx,
        std::function<float(int, int)> &heuristic, std::vector<int> *path) const
{
    int vnum = vertex_num();

    std::set<int> closed;
    std::set<int> opened;
    std::vector<int> came_from(vnum, -1);
    std::vector<float> g_score(vnum, std::numeric_limits<float>::max());
    std::vector<float> f_score(vnum, std::numeric_limits<float>::max());

    opened.insert(start_idx);

    bool vertex_found = false;
    while (!vertex_found && !opened.empty()) {
        int current = min_idx(opened, f_score);
        if (current == goal_idx) {
            vertex_found = true;
            break;
        }
        opened.erase(current);
        closed.insert(current);

        std::set<int> neighbours = adjacent_vertices(current);
        for (auto neighbour : neighbours) {
            if (closed.count(neighbour) > 0) {
                continue;
            }

            float tentative_score = g_score[current] + 1;
            if (opened.count(neighbour) == 0) {
                opened.insert(neighbour);
            }
            else if (tentative_score >= g_score[neighbour]) {
                continue;
            }

            came_from[neighbour] = current;
            g_score[neighbour] = tentative_score;
            f_score[neighbour] = g_score[neighbour] + heuristic(neighbour, goal_idx);
        }
    }

    if (vertex_found) {
        int idx = goal_idx;
        do {
            path->push_back(idx);
            idx = came_from[idx];
        } while (idx != -1);
        std::reverse(path->begin(), path->end());
    }

    return vertex_found;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2009, Markus Rickert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#include <chrono>

#include "GaussianSampler.h"
#include "SimpleModel.h"

namespace rl
{
	namespace plan
	{
		GaussianSampler::GaussianSampler() :
			UniformSampler(),
			sigma(nullptr),
			gaussDistribution(0, 1),
			gaussEngine(::std::random_device()())
		{
		}

		GaussianSampler::~GaussianSampler()
		{
		}

		::std::normal_distribution< ::rl::math::Real>::result_type
		GaussianSampler::gauss()
		{
			return this->gaussDistribution(this->gaussEngine);
		}

		::rl::math::Vector
		GaussianSampler::generateCollisionFree()
		{
			::rl::math::Vector q2(this->model->getDof());

			while (true)
			{
				::rl::math::Vector q = this->generate();

				::rl::math::Vector gauss(this->model->getDof());

				for (::std::size_t i = 0; i < this->model->getDof(); ++i)
				{
					gauss(i) = this->gauss();
				}

				q2 = this->model->generatePositionGaussian(gauss, q, *this->sigma);

				this->model->setPosition(q);
				this->model->updateFrames();

				if (!this->model->isColliding())
				{
					this->model->setPosition(q2);
					this->model->updateFrames();

					if (this->model->isColliding())
					{
						return q;
					}
				}
				else
				{
					this->model->setPosition(q2);
					this->model->updateFrames();

					if (!this->model->isColliding())
					{
						q = q2;
						return q;
					}
				}
			}
		}

		void
		GaussianSampler::seed(const ::std::mt19937::result_type& value)
		{
			this->gaussEngine.seed(value);
			this->randEngine.seed(value);
		}
	}
}
<commit_msg>Update GaussianSampler<commit_after>//
// Copyright (c) 2009, Markus Rickert
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#include <chrono>

#include "GaussianSampler.h"
#include "SimpleModel.h"

namespace rl
{
	namespace plan
	{
		GaussianSampler::GaussianSampler() :
			UniformSampler(),
			sigma(nullptr),
			gaussDistribution(0, 1),
			gaussEngine(::std::random_device()())
		{
		}

		GaussianSampler::~GaussianSampler()
		{
		}

		::std::normal_distribution< ::rl::math::Real>::result_type
		GaussianSampler::gauss()
		{
			return this->gaussDistribution(this->gaussEngine);
		}

		::rl::math::Vector
		GaussianSampler::generateCollisionFree()
		{
			::rl::math::Vector gauss(this->model->getDof());

			while (true)
			{
				::rl::math::Vector q = this->generate();

				for (::std::size_t i = 0; i < this->model->getDof(); ++i)
				{
					gauss(i) = this->gauss();
				}

				::rl::math::Vector q2 = this->model->generatePositionGaussian(gauss, q, *this->sigma);

				this->model->setPosition(q);
				this->model->updateFrames();

				if (!this->model->isColliding())
				{
					this->model->setPosition(q2);
					this->model->updateFrames();

					if (this->model->isColliding())
					{
						return q;
					}
				}
				else
				{
					this->model->setPosition(q2);
					this->model->updateFrames();

					if (!this->model->isColliding())
					{
						return q2;
					}
				}
			}
		}

		void
		GaussianSampler::seed(const ::std::mt19937::result_type& value)
		{
			this->gaussEngine.seed(value);
			this->randEngine.seed(value);
		}
	}
}
<|endoftext|>