Classes | Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes

DHTTestApp Class Reference

A simple test application for the DHT layer. More...

#include <DHTTestApp.h>

Inheritance diagram for DHTTestApp:
BaseApp BaseRpc BaseTcpSupport RpcListener

List of all members.

Classes

class  DHTStatsContext
 A container used by the DHTTestApp to store context information for statistics. More...

Public Member Functions

 DHTTestApp ()
virtual ~DHTTestApp ()
 virtual destructor

Private Member Functions

void initializeApp (int stage)
 initializes derived class-attributes
OverlayKey getRandomKey ()
 Get a random key of the hashmap.
BinaryValue generateRandomValue ()
 generate a random human readable binary value
void finishApp ()
 collects statistical data of derived app
virtual void handleGetResponse (DHTgetCAPIResponse *msg, DHTStatsContext *context)
 processes get responses
virtual void handlePutResponse (DHTputCAPIResponse *msg, DHTStatsContext *context)
 processes put responses
virtual void handleTimerEvent (cMessage *msg)
 processes self-messages
virtual void handleTraceMessage (cMessage *msg)
 handleTraceMessage gets called of handleMessage(cMessage* msg) if a message arrives at trace_in.
virtual void handleNodeLeaveNotification ()
 This method gets call **.gracefulLeaveDelay seconds before it is killed.
void handleRpcResponse (BaseResponseMessage *msg, const RpcState &state, simtime_t rtt)

Private Attributes

UnderlayConfiguratorunderlayConfigurator
 pointer to UnderlayConfigurator in this node
GlobalNodeListglobalNodeList
 pointer to GlobalNodeList in this node
GlobalStatisticsglobalStatistics
 pointer to GlobalStatistics module in this node
GlobalDhtTestMapglobalDhtTestMap
 pointer to the GlobalDhtTestMap module
bool debugOutput
 debug output yes/no?
double mean
 mean time interval between sending test messages
double deviation
 deviation of time interval
int ttl
 ttl for stored DHT records
bool p2pnsTraffic
 model p2pns application traffic */
bool activeNetwInitPhase
 is app active in network init phase?
int numSent
 number of sent packets
int numGetSent
 number of get sent
int numGetError
 number of false get responses
int numGetSuccess
 number of false get responses
int numPutSent
 number of put sent
int numPutError
 number of error in put responses
int numPutSuccess
 number of success in put responses
cMessage * dhttestput_timer
cMessage * dhttestget_timer
cMessage * dhttestmod_timer
bool nodeIsLeavingSoon
 true if the node is going to be killed shortly

Static Private Attributes

static const int DHTTESTAPP_VALUE_LEN = 20

Detailed Description

A simple test application for the DHT layer.

A simple test application that does random put and get calls on the DHT layer

Author:
Ingmar Baumgart

Definition at line 50 of file DHTTestApp.h.


Constructor & Destructor Documentation

DHTTestApp::DHTTestApp (  ) 

Definition at line 46 of file DHTTestApp.cc.

DHTTestApp::~DHTTestApp (  )  [virtual]

virtual destructor

Definition at line 39 of file DHTTestApp.cc.

{
    cancelAndDelete(dhttestput_timer);
    cancelAndDelete(dhttestget_timer);
    cancelAndDelete(dhttestmod_timer);
}


Member Function Documentation

void DHTTestApp::finishApp (  )  [private, virtual]

collects statistical data of derived app

Reimplemented from BaseApp.

Definition at line 436 of file DHTTestApp.cc.

{
    simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);

    if (time >= GlobalStatistics::MIN_MEASURED) {
        // record scalar data
        globalStatistics->addStdDev("DHTTestApp: Sent Total Messages/s",
                                    numSent / time);
        globalStatistics->addStdDev("DHTTestApp: Sent GET Messages/s",
                                    numGetSent / time);
        globalStatistics->addStdDev("DHTTestApp: Failed GET Requests/s",
                                    numGetError / time);
        globalStatistics->addStdDev("DHTTestApp: Successful GET Requests/s",
                                    numGetSuccess / time);

        globalStatistics->addStdDev("DHTTestApp: Sent PUT Messages/s",
                                    numPutSent / time);
        globalStatistics->addStdDev("DHTTestApp: Failed PUT Requests/s",
                                    numPutError / time);
        globalStatistics->addStdDev("DHTTestApp: Successful PUT Requests/s",
                                    numPutSuccess / time);

        if ((numGetSuccess + numGetError) > 0) {
            globalStatistics->addStdDev("DHTTestApp: GET Success Ratio",
                                        (double) numGetSuccess
                                        / (double) (numGetSuccess + numGetError));
        }
    }
}

BinaryValue DHTTestApp::generateRandomValue (  )  [private]

generate a random human readable binary value

Definition at line 419 of file DHTTestApp.cc.

Referenced by handleTimerEvent().

{
    char value[DHTTESTAPP_VALUE_LEN + 1];

    for (int i = 0; i < DHTTESTAPP_VALUE_LEN; i++) {
        value[i] = intuniform(0, 25) + 'a';
    }

    value[DHTTESTAPP_VALUE_LEN] = '\0';
    return BinaryValue(value);
}

OverlayKey DHTTestApp::getRandomKey (  )  [private]

Get a random key of the hashmap.

void DHTTestApp::handleGetResponse ( DHTgetCAPIResponse msg,
DHTStatsContext context 
) [private, virtual]

processes get responses

method to handle get responses should be overwritten in derived application if needed

Parameters:
msg get response message
context context object used for collecting statistics

Definition at line 172 of file DHTTestApp.cc.

Referenced by handleRpcResponse().

{
    if (context->measurementPhase == false) {
        // don't count response, if the request was not sent
        // in the measurement phase
        delete context;
        return;
    }

    RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: GET Latency (s)",
                               SIMTIME_DBL(simTime() - context->requestTime)));

    if (!(msg->getIsSuccess())) {
        //cout << "DHTTestApp: success == false" << endl;
        RECORD_STATS(numGetError++);
        delete context;
        return;
    }

    const DHTEntry* entry = globalDhtTestMap->findEntry(context->key);

    if (entry == NULL) {
        //unexpected key
        RECORD_STATS(numGetError++);
        //cout << "DHTTestApp: unexpected key" << endl;
        delete context;
        return;
    }

    if (simTime() > entry->endtime) {
        //this key doesn't exist anymore in the DHT, delete it in our hashtable

        globalDhtTestMap->eraseEntry(context->key);
        delete context;

        if (msg->getResultArraySize() > 0) {
            RECORD_STATS(numGetError++);
            //cout << "DHTTestApp: deleted key still available" << endl;
            return;
        } else {
            RECORD_STATS(numGetSuccess++);
            //cout << "DHTTestApp: success (1)" << endl;
            return;
        }
    } else {
        delete context;
        if ((msg->getResultArraySize() > 0) && (msg->getResult(0).getValue() != entry->value)) {
            RECORD_STATS(numGetError++);
            //cout << "DHTTestApp: wrong value" << endl;
            //cout << "value: " << msg->getResult(0).getValue() << endl;
            return;
        } else {
            RECORD_STATS(numGetSuccess++);
            //cout << "DHTTestApp: success (2)" << endl;
            return;
        }
    }

}

void DHTTestApp::handleNodeLeaveNotification (  )  [private, virtual]

This method gets call **.gracefulLeaveDelay seconds before it is killed.

Reimplemented from BaseApp.

Definition at line 431 of file DHTTestApp.cc.

{
    nodeIsLeavingSoon = true;
}

void DHTTestApp::handlePutResponse ( DHTputCAPIResponse msg,
DHTStatsContext context 
) [private, virtual]

processes put responses

method to handle put responses should be overwritten in derived application if needed

Parameters:
msg put response message
context context object used for collecting statistics

Definition at line 147 of file DHTTestApp.cc.

Referenced by handleRpcResponse().

{
    DHTEntry entry = {context->value, simTime() + ttl};

    globalDhtTestMap->insertEntry(context->key, entry);

    if (context->measurementPhase == false) {
        // don't count response, if the request was not sent
        // in the measurement phase
        delete context;
        return;
    }

    if (msg->getIsSuccess()) {
        RECORD_STATS(numPutSuccess++);
        RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: PUT Latency (s)",
                               SIMTIME_DBL(simTime() - context->requestTime)));
    } else {
        RECORD_STATS(numPutError++);
    }

    delete context;
}

void DHTTestApp::handleRpcResponse ( BaseResponseMessage msg,
const RpcState state,
simtime_t  rtt 
) [private]

Definition at line 121 of file DHTTestApp.cc.

{
    RPC_SWITCH_START(msg)
    RPC_ON_RESPONSE( DHTputCAPI ) {
        handlePutResponse(_DHTputCAPIResponse,
                          check_and_cast<DHTStatsContext*>(state.getContext()));
        EV << "[DHTTestApp::handleRpcResponse()]\n"
           << "    DHT Put RPC Response received: id=" << state.getId()
           << " msg=" << *_DHTputCAPIResponse << " rtt=" << rtt
           << endl;
        break;
    }
    RPC_ON_RESPONSE(DHTgetCAPI)
    {
        handleGetResponse(_DHTgetCAPIResponse,
                          check_and_cast<DHTStatsContext*>(state.getContext()));
        EV << "[DHTTestApp::handleRpcResponse()]\n"
           << "    DHT Get RPC Response received: id=" << state.getId()
           << " msg=" << *_DHTgetCAPIResponse << " rtt=" << rtt
           << endl;
        break;
    }
    RPC_SWITCH_END()
}

void DHTTestApp::handleTimerEvent ( cMessage *  msg  )  [private, virtual]

processes self-messages

method to handle self-messages should be overwritten in derived application if needed

Parameters:
msg self-message

Definition at line 291 of file DHTTestApp.cc.

{
    if (msg->isName("dhttest_put_timer")) {
        // schedule next timer event
        scheduleAt(simTime() + truncnormal(mean, deviation), msg);

        // do nothing if the network is still in the initialization phase
        if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
                || underlayConfigurator->isSimulationEndingSoon()
                || nodeIsLeavingSoon)
            return;

        if (p2pnsTraffic) {
            if (globalDhtTestMap->p2pnsNameCount < 4*globalNodeList->getNumNodes()) {
                for (int i = 0; i < 4; i++) {
                    // create a put test message with random destination key
                    OverlayKey destKey = OverlayKey::random();
                    DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
                    dhtPutMsg->setKey(destKey);
                    dhtPutMsg->setValue(generateRandomValue());
                    dhtPutMsg->setTtl(ttl);
                    dhtPutMsg->setIsModifiable(true);

                    RECORD_STATS(numSent++; numPutSent++);
                    sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
                            new DHTStatsContext(globalStatistics->isMeasuring(),
                                                simTime(), destKey, dhtPutMsg->getValue()));
                    globalDhtTestMap->p2pnsNameCount++;
                }
            }
            cancelEvent(msg);
            return;
        }

        // create a put test message with random destination key
        OverlayKey destKey = OverlayKey::random();
        DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
        dhtPutMsg->setKey(destKey);
        dhtPutMsg->setValue(generateRandomValue());
        dhtPutMsg->setTtl(ttl);
        dhtPutMsg->setIsModifiable(true);

        RECORD_STATS(numSent++; numPutSent++);
        sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
                new DHTStatsContext(globalStatistics->isMeasuring(),
                                    simTime(), destKey, dhtPutMsg->getValue()));
    } else if (msg->isName("dhttest_get_timer")) {
        scheduleAt(simTime() + truncnormal(mean, deviation), msg);

        // do nothing if the network is still in the initialization phase
        if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
                || underlayConfigurator->isSimulationEndingSoon()
                || nodeIsLeavingSoon) {
            return;
        }

        if (p2pnsTraffic && (uniform(0, 1) > ((double)mean/1800.0))) {
            return;
        }

        const OverlayKey& key = globalDhtTestMap->getRandomKey();

        if (key.isUnspecified()) {
            EV << "[DHTTestApp::handleTimerEvent() @ " << thisNode.getIp()
               << " (" << thisNode.getKey().toString(16) << ")]\n"
               << "    Error: No key available in global DHT test map!"
               << endl;
            return;
        }

        DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
        dhtGetMsg->setKey(key);
        RECORD_STATS(numSent++; numGetSent++);

        sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
                new DHTStatsContext(globalStatistics->isMeasuring(),
                                    simTime(), key));
    } else if (msg->isName("dhttest_mod_timer")) {
        scheduleAt(simTime() + truncnormal(mean, deviation), msg);

        // do nothing if the network is still in the initialization phase
        if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
                || underlayConfigurator->isSimulationEndingSoon()
                || nodeIsLeavingSoon) {
            return;
        }

        if (p2pnsTraffic) {
            if (globalDhtTestMap->p2pnsNameCount >= 4*globalNodeList->getNumNodes()) {
                const OverlayKey& key = globalDhtTestMap->getRandomKey();

                if (key.isUnspecified())
                    return;

                DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
                dhtPutMsg->setKey(key);
                dhtPutMsg->setValue(generateRandomValue());
                dhtPutMsg->setTtl(ttl);
                dhtPutMsg->setIsModifiable(true);

                RECORD_STATS(numSent++; numPutSent++);
                sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
                        new DHTStatsContext(globalStatistics->isMeasuring(),
                                            simTime(), key, dhtPutMsg->getValue()));
            }
            cancelEvent(msg);
            return;
        }

        const OverlayKey& key = globalDhtTestMap->getRandomKey();

        if (key.isUnspecified())
            return;

        DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
        dhtPutMsg->setKey(key);
        dhtPutMsg->setValue(generateRandomValue());
        dhtPutMsg->setTtl(ttl);
        dhtPutMsg->setIsModifiable(true);

        RECORD_STATS(numSent++; numPutSent++);
        sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
                new DHTStatsContext(globalStatistics->isMeasuring(),
                                    simTime(), key, dhtPutMsg->getValue()));
    }
}

void DHTTestApp::handleTraceMessage ( cMessage *  msg  )  [private, virtual]

handleTraceMessage gets called of handleMessage(cMessage* msg) if a message arrives at trace_in.

The command included in this message should be parsed and handled.

Parameters:
msg the command message to handle

Reimplemented from BaseApp.

Definition at line 233 of file DHTTestApp.cc.

{
    char* cmd = new char[strlen(msg->getName()) + 1];
    strcpy(cmd, msg->getName());

    if (strlen(msg->getName()) < 5) {
        delete[] cmd;
        delete msg;
        return;
    }

    if (strncmp(cmd, "PUT ", 4) == 0) {
        // Generate key
        char* buf = cmd + 4;

        while (!isspace(buf[0])) {
            if (buf[0] == '\0')
                throw cRuntimeError("Error parsing PUT command");
            buf++;
        }

        buf[0] = '\0';
        BinaryValue b(cmd + 4);
        OverlayKey destKey(OverlayKey::sha1(b));

        // get value
        buf++;

        // build putMsg
        DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
        dhtPutMsg->setKey(destKey);
        dhtPutMsg->setValue(buf);
        dhtPutMsg->setTtl(ttl);
        dhtPutMsg->setIsModifiable(true);
        RECORD_STATS(numSent++; numPutSent++);
        sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
                new DHTStatsContext(globalStatistics->isMeasuring(),
                                    simTime(), destKey));
    } else if (strncmp(cmd, "GET ", 4) == 0) {
        // Get key
        BinaryValue b(cmd + 4);
        OverlayKey key(OverlayKey::sha1(b));

        DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
        dhtGetMsg->setKey(key);
        RECORD_STATS(numSent++; numGetSent++);
        sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
                new DHTStatsContext(globalStatistics->isMeasuring(),
                                    simTime(), key));
    } else {
        throw cRuntimeError("Unknown trace command; "
                                "only GET and PUT are allowed");
    }

    delete[] cmd;
    delete msg;
}

void DHTTestApp::initializeApp ( int  stage  )  [private, virtual]

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

Definition at line 53 of file DHTTestApp.cc.

{
    if (stage != MIN_STAGE_APP)
        return;

    // fetch parameters
    debugOutput = par("debugOutput");
    activeNetwInitPhase = par("activeNetwInitPhase");

    mean = par("testInterval");
    p2pnsTraffic = par("p2pnsTraffic");
    deviation = mean / 10;

    if (p2pnsTraffic) {
        ttl = 3600*24*365;
    } else {
        ttl = par("testTtl");
    }

    globalNodeList = GlobalNodeListAccess().get();
    underlayConfigurator = UnderlayConfiguratorAccess().get();
    globalStatistics = GlobalStatisticsAccess().get();

    globalDhtTestMap = dynamic_cast<GlobalDhtTestMap*>(simulation.getModuleByPath(
            "globalObserver.globalFunctions[0].function"));

    if (globalDhtTestMap == NULL) {
        throw cRuntimeError("DHTTestApp::initializeApp(): "
                                "GlobalDhtTestMap module not found!");
    }

    // statistics
    numSent = 0;
    numGetSent = 0;
    numGetError = 0;
    numGetSuccess = 0;
    numPutSent = 0;
    numPutError = 0;
    numPutSuccess = 0;

    //initRpcs();
    WATCH(numSent);
    WATCH(numGetSent);
    WATCH(numGetError);
    WATCH(numGetSuccess);
    WATCH(numPutSent);
    WATCH(numPutError);
    WATCH(numPutSuccess);

    nodeIsLeavingSoon = false;

    // initiate test message transmission
    dhttestput_timer = new cMessage("dhttest_put_timer");
    dhttestget_timer = new cMessage("dhttest_get_timer");
    dhttestmod_timer = new cMessage("dhttest_mod_timer");

    if (mean > 0) {
        scheduleAt(simTime() + truncnormal(mean, deviation),
                   dhttestput_timer);
        scheduleAt(simTime() + truncnormal(mean + mean / 3,
                                                      deviation),
                                                      dhttestget_timer);
        scheduleAt(simTime() + truncnormal(mean + 2 * mean / 3,
                                                      deviation),
                                                      dhttestmod_timer);
    }
}


Member Data Documentation

is app active in network init phase?

Definition at line 148 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

bool DHTTestApp::debugOutput [private]

debug output yes/no?

Reimplemented from BaseApp.

Definition at line 143 of file DHTTestApp.h.

Referenced by initializeApp().

double DHTTestApp::deviation [private]

deviation of time interval

Definition at line 145 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

const int DHTTestApp::DHTTESTAPP_VALUE_LEN = 20 [static, private]

Definition at line 162 of file DHTTestApp.h.

Referenced by generateRandomValue().

cMessage * DHTTestApp::dhttestget_timer [private]

Definition at line 159 of file DHTTestApp.h.

Referenced by DHTTestApp(), initializeApp(), and ~DHTTestApp().

cMessage * DHTTestApp::dhttestmod_timer [private]

Definition at line 159 of file DHTTestApp.h.

Referenced by DHTTestApp(), initializeApp(), and ~DHTTestApp().

cMessage* DHTTestApp::dhttestput_timer [private]

Definition at line 159 of file DHTTestApp.h.

Referenced by DHTTestApp(), initializeApp(), and ~DHTTestApp().

pointer to GlobalNodeList in this node

Reimplemented from BaseApp.

Definition at line 137 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

pointer to GlobalStatistics module in this node

Reimplemented from BaseApp.

Definition at line 139 of file DHTTestApp.h.

Referenced by finishApp(), handleGetResponse(), handlePutResponse(), handleTimerEvent(), handleTraceMessage(), and initializeApp().

double DHTTestApp::mean [private]

mean time interval between sending test messages

Definition at line 144 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

true if the node is going to be killed shortly

Definition at line 160 of file DHTTestApp.h.

Referenced by handleNodeLeaveNotification(), handleTimerEvent(), and initializeApp().

int DHTTestApp::numGetError [private]

number of false get responses

Definition at line 153 of file DHTTestApp.h.

Referenced by finishApp(), handleGetResponse(), and initializeApp().

int DHTTestApp::numGetSent [private]

number of get sent

Definition at line 152 of file DHTTestApp.h.

Referenced by finishApp(), handleTimerEvent(), handleTraceMessage(), and initializeApp().

number of false get responses

Definition at line 154 of file DHTTestApp.h.

Referenced by finishApp(), handleGetResponse(), and initializeApp().

int DHTTestApp::numPutError [private]

number of error in put responses

Definition at line 156 of file DHTTestApp.h.

Referenced by finishApp(), handlePutResponse(), and initializeApp().

int DHTTestApp::numPutSent [private]

number of put sent

Definition at line 155 of file DHTTestApp.h.

Referenced by finishApp(), handleTimerEvent(), handleTraceMessage(), and initializeApp().

number of success in put responses

Definition at line 157 of file DHTTestApp.h.

Referenced by finishApp(), handlePutResponse(), and initializeApp().

int DHTTestApp::numSent [private]

number of sent packets

Definition at line 151 of file DHTTestApp.h.

Referenced by finishApp(), handleTimerEvent(), handleTraceMessage(), and initializeApp().

bool DHTTestApp::p2pnsTraffic [private]

model p2pns application traffic */

Definition at line 147 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

int DHTTestApp::ttl [private]

ttl for stored DHT records

Definition at line 146 of file DHTTestApp.h.

Referenced by handlePutResponse(), handleTimerEvent(), handleTraceMessage(), and initializeApp().

pointer to UnderlayConfigurator in this node

Reimplemented from BaseApp.

Definition at line 135 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().


The documentation for this class was generated from the following files: