DHTTestApp Class Reference

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

#include <DHTTestApp.h>

Inheritance diagram for DHTTestApp:

BaseApp BaseRpc 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, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.

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 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.

00047 {
00048     dhttestput_timer = NULL;
00049     dhttestget_timer = NULL;
00050     dhttestmod_timer = NULL;
00051 }

DHTTestApp::~DHTTestApp (  )  [virtual]

virtual destructor

Definition at line 39 of file DHTTestApp.cc.

00040 {
00041     cancelAndDelete(dhttestput_timer);
00042     cancelAndDelete(dhttestget_timer);
00043     cancelAndDelete(dhttestmod_timer);
00044 }


Member Function Documentation

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

collects statistical data of derived app

Reimplemented from BaseApp.

Definition at line 392 of file DHTTestApp.cc.

00393 {
00394     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00395 
00396     if (time >= GlobalStatistics::MIN_MEASURED) {
00397         // record scalar data
00398         globalStatistics->addStdDev("DHTTestApp: Sent Total Messages/s",
00399                                     numSent / time);
00400         globalStatistics->addStdDev("DHTTestApp: Sent GET Messages/s",
00401                                     numGetSent / time);
00402         globalStatistics->addStdDev("DHTTestApp: Failed GET Requests/s",
00403                                     numGetError / time);
00404         globalStatistics->addStdDev("DHTTestApp: Successful GET Requests/s",
00405                                     numGetSuccess / time);
00406 
00407         globalStatistics->addStdDev("DHTTestApp: Sent PUT Messages/s",
00408                                     numPutSent / time);
00409         globalStatistics->addStdDev("DHTTestApp: Failed PUT Requests/s",
00410                                     numPutError / time);
00411         globalStatistics->addStdDev("DHTTestApp: Successful PUT Requests/s",
00412                                     numPutSuccess / time);
00413 
00414         if (numGetSent > 0) {
00415             globalStatistics->addStdDev("DHTTestApp: GET Success Ratio",
00416                                         (double) numGetSuccess
00417                                         / (double) numGetSent);
00418         }
00419     }
00420 }

BinaryValue DHTTestApp::generateRandomValue (  )  [private]

generate a random human readable binary value

Definition at line 375 of file DHTTestApp.cc.

Referenced by handleTimerEvent().

00376 {
00377     char value[DHTTESTAPP_VALUE_LEN + 1];
00378 
00379     for (int i = 0; i < DHTTESTAPP_VALUE_LEN; i++) {
00380         value[i] = intuniform(0, 25) + 'a';
00381     }
00382 
00383     value[DHTTESTAPP_VALUE_LEN] = '\0';
00384     return BinaryValue(value);
00385 }

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 176 of file DHTTestApp.cc.

Referenced by handleRpcResponse().

00178 {
00179     if (context->measurementPhase == false) {
00180         // don't count response, if the request was not sent
00181         // in the measurement phase
00182         delete context;
00183         return;
00184     }
00185 
00186     RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: GET delay (s)",
00187                                              SIMTIME_DBL(simTime() - context->requestTime)));
00188 
00189     if (!(msg->getIsSuccess())) {
00190         //cout << "DHTTestApp: success == false" << endl;
00191         RECORD_STATS(numGetError++);
00192         delete context;
00193         return;
00194     }
00195 
00196     const DHTEntry* entry = globalDhtTestMap->findEntry(context->key);
00197 
00198     if (entry == NULL) {
00199         //unexpected key
00200         RECORD_STATS(numGetError++);
00201         //cout << "DHTTestApp: unexpected key" << endl;
00202         delete context;
00203         return;
00204     }
00205 
00206     if (simTime() > entry->endtime) {
00207         //this key doesn't exist anymore in the DHT, delete it in our hashtable
00208 
00209         globalDhtTestMap->eraseEntry(context->key);
00210         delete context;
00211 
00212         if (msg->getResultArraySize() > 0) {
00213             RECORD_STATS(numGetError++);
00214             //cout << "DHTTestApp: deleted key still available" << endl;
00215             return;
00216         } else {
00217             RECORD_STATS(numGetSuccess++);
00218             //cout << "DHTTestApp: success (1)" << endl;
00219             return;
00220         }
00221     } else {
00222         delete context;
00223         if ((msg->getResultArraySize() > 0) && (msg->getResult(0).getValue() != entry->value)) {
00224             RECORD_STATS(numGetError++);
00225             //cout << "DHTTestApp: wrong value" << endl;
00226             //cout << "size: " << msg->getResult(0).getValue().size() << endl;
00227             return;
00228         } else {
00229             RECORD_STATS(numGetSuccess++);
00230             //cout << "DHTTestApp: success (2)" << endl;
00231             return;
00232         }
00233     }
00234 
00235 }

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

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

Reimplemented from BaseApp.

Definition at line 387 of file DHTTestApp.cc.

00388 {
00389     nodeIsLeavingSoon = true;
00390 }

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 143 of file DHTTestApp.cc.

Referenced by handleRpcResponse().

00145 {
00146     if (!(msg->getIsSuccess())) {
00147         if (context->measurementPhase == false) {
00148             // don't count response, if the request was not sent
00149             // in the measurement phase
00150             RECORD_STATS(numPutError++);
00151         }
00152         delete context;
00153         return;
00154     }
00155 
00156     OverlayKey key = msg->getKey();
00157     DHTEntry entry = {BinaryValue(msg->getValue()),
00158             simTime() + ttl};
00159 
00160     globalDhtTestMap->insertEntry(msg->getKey(), entry);
00161 
00162     if (context->measurementPhase == false) {
00163         // don't count response, if the request was not sent
00164         // in the measurement phase
00165         delete context;
00166         return;
00167     }
00168 
00169     RECORD_STATS(numPutSuccess++);
00170 
00171     RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: PUT delay (s)",
00172                                              SIMTIME_DBL(simTime() - context->requestTime)));
00173     delete context;
00174 }

void DHTTestApp::handleRpcResponse ( BaseResponseMessage msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [private, virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

Definition at line 116 of file DHTTestApp.cc.

00119 {
00120     RPC_SWITCH_START(msg)
00121     RPC_ON_RESPONSE( DHTputCAPI ) {
00122         handlePutResponse(_DHTputCAPIResponse,
00123                           check_and_cast<DHTStatsContext*>(context));
00124         EV << "[DHTTestApp::handleRpcResponse()]\n"
00125            << "    DHT Put RPC Response received: id=" << rpcId
00126            << " msg=" << *_DHTputCAPIResponse << " rtt=" << rtt
00127            << endl;
00128         break;
00129     }
00130     RPC_ON_RESPONSE(DHTgetCAPI)
00131     {
00132         handleGetResponse(_DHTgetCAPIResponse,
00133                           check_and_cast<DHTStatsContext*>(context));
00134         EV << "[DHTTestApp::handleRpcResponse()]\n"
00135            << "    DHT Get RPC Response received: id=" << rpcId
00136            << " msg=" << *_DHTgetCAPIResponse << " rtt=" << rtt
00137            << endl;
00138         break;
00139     }
00140     RPC_SWITCH_END()
00141 }

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

Reimplemented from BaseRpc.

Definition at line 295 of file DHTTestApp.cc.

00296 {
00297     if (msg->isName("dhttest_put_timer")) {
00298         // schedule next timer event
00299         scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00300 
00301         // do nothing if the network is still in the initialization phase
00302         if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00303                 || underlayConfigurator->isSimulationEndingSoon()
00304                 || nodeIsLeavingSoon)
00305             return;
00306 
00307         // create a put test message with random destination key
00308         OverlayKey destKey = OverlayKey::random();
00309         DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00310         dhtPutMsg->setKey(destKey);
00311         dhtPutMsg->setValue(generateRandomValue());
00312         dhtPutMsg->setTtl(ttl);
00313         dhtPutMsg->setIsModifiable(true);
00314 
00315         RECORD_STATS(numSent++; numPutSent++);
00316         sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00317                 new DHTStatsContext(globalStatistics->isMeasuring(),
00318                                     simTime(), destKey));
00319     } else if (msg->isName("dhttest_get_timer")) {
00320         scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00321 
00322         // do nothing if the network is still in the initialization phase
00323         if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00324                 || underlayConfigurator->isSimulationEndingSoon()
00325                 || nodeIsLeavingSoon) {
00326             return;
00327         }
00328 
00329         const OverlayKey& key = globalDhtTestMap->getRandomKey();
00330 
00331         if (key.isUnspecified()) {
00332             EV << "[DHTTestApp::handleTimerEvent() @ " << thisNode.getAddress()
00333                << " (" << thisNode.getKey().toString(16) << ")]\n"
00334                << "    Error: No key available in global DHT test map!"
00335                << endl;
00336             return;
00337         }
00338 
00339         DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00340         dhtGetMsg->setKey(key);
00341         RECORD_STATS(numSent++; numGetSent++);
00342 
00343         sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
00344                 new DHTStatsContext(globalStatistics->isMeasuring(),
00345                                     simTime(), key));
00346     } else if (msg->isName("dhttest_mod_timer")) {
00347         scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00348 
00349         // do nothing if the network is still in the initialization phase
00350         if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00351                 || underlayConfigurator->isSimulationEndingSoon()
00352                 || nodeIsLeavingSoon) {
00353             return;
00354         }
00355 
00356         const OverlayKey& key = globalDhtTestMap->getRandomKey();
00357 
00358         if (key.isUnspecified())
00359             return;
00360 
00361         DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00362         dhtPutMsg->setKey(key);
00363         dhtPutMsg->setValue(generateRandomValue());
00364         dhtPutMsg->setTtl(ttl);
00365         dhtPutMsg->setIsModifiable(true);
00366 
00367         RECORD_STATS(numSent++; numPutSent++);
00368         sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00369                 new DHTStatsContext(globalStatistics->isMeasuring(),
00370                                     simTime(), key));
00371     }
00372 }

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 237 of file DHTTestApp.cc.

00238 {
00239     char* cmd = new char[strlen(msg->getName()) + 1];
00240     strcpy(cmd, msg->getName());
00241 
00242     if (strlen(msg->getName()) < 5) {
00243         delete[] cmd;
00244         delete msg;
00245         return;
00246     }
00247 
00248     if (strncmp(cmd, "PUT ", 4) == 0) {
00249         // Generate key
00250         char* buf = cmd + 4;
00251 
00252         while (!isspace(buf[0])) {
00253             if (buf[0] == '\0')
00254                 throw cRuntimeError("Error parsing PUT command");
00255             buf++;
00256         }
00257 
00258         buf[0] = '\0';
00259         BinaryValue b(cmd + 4);
00260         OverlayKey destKey(OverlayKey::sha1(b));
00261 
00262         // get value
00263         buf++;
00264 
00265         // build putMsg
00266         DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00267         dhtPutMsg->setKey(destKey);
00268         dhtPutMsg->setValue(buf);
00269         dhtPutMsg->setTtl(ttl);
00270         dhtPutMsg->setIsModifiable(true);
00271         RECORD_STATS(numSent++; numPutSent++);
00272         sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00273                 new DHTStatsContext(globalStatistics->isMeasuring(),
00274                                     simTime(), destKey));
00275     } else if (strncmp(cmd, "GET ", 4) == 0) {
00276         // Get key
00277         BinaryValue b(cmd + 4);
00278         OverlayKey key(OverlayKey::sha1(b));
00279 
00280         DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00281         dhtGetMsg->setKey(key);
00282         RECORD_STATS(numSent++; numGetSent++);
00283         sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
00284                 new DHTStatsContext(globalStatistics->isMeasuring(),
00285                                     simTime(), key));
00286     } else {
00287         throw cRuntimeError("Unknown trace command; "
00288                                 "only GET and PUT are allowed");
00289     }
00290 
00291     delete[] cmd;
00292     delete msg;
00293 }

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.

00054 {
00055     if (stage != MIN_STAGE_APP)
00056         return;
00057 
00058     // fetch parameters
00059     debugOutput = par("debugOutput");
00060     activeNetwInitPhase = par("activeNetwInitPhase");
00061 
00062     mean = par("testInterval");
00063     deviation = mean / 10;
00064 
00065     ttl = par("testTtl");
00066 
00067     globalNodeList = GlobalNodeListAccess().get();
00068     underlayConfigurator = UnderlayConfiguratorAccess().get();
00069     globalStatistics = GlobalStatisticsAccess().get();
00070 
00071     globalDhtTestMap = dynamic_cast<GlobalDhtTestMap*>(simulation.getModuleByPath(
00072             "globalObserver.globalFunctions[0].function"));
00073 
00074     if (globalDhtTestMap == NULL) {
00075         throw cRuntimeError("DHTTestApp::initializeApp(): "
00076                                 "GlobalDhtTestMap module not found!");
00077     }
00078 
00079     // statistics
00080     numSent = 0;
00081     numGetSent = 0;
00082     numGetError = 0;
00083     numGetSuccess = 0;
00084     numPutSent = 0;
00085     numPutError = 0;
00086     numPutSuccess = 0;
00087 
00088     //initRpcs();
00089     WATCH(numSent);
00090     WATCH(numGetSent);
00091     WATCH(numGetError);
00092     WATCH(numGetSuccess);
00093     WATCH(numPutSent);
00094     WATCH(numPutError);
00095     WATCH(numPutSuccess);
00096 
00097     nodeIsLeavingSoon = false;
00098 
00099     // initiate test message transmission
00100     dhttestput_timer = new cMessage("dhttest_put_timer");
00101     dhttestget_timer = new cMessage("dhttest_get_timer");
00102     dhttestmod_timer = new cMessage("dhttest_mod_timer");
00103 
00104     if (mean > 0) {
00105         scheduleAt(simTime() + truncnormal(mean, deviation),
00106                    dhttestput_timer);
00107         scheduleAt(simTime() + truncnormal(mean + mean / 3,
00108                                                       deviation),
00109                                                       dhttestget_timer);
00110         scheduleAt(simTime() + truncnormal(mean + 2 * mean / 3,
00111                                                       deviation),
00112                                                       dhttestmod_timer);
00113     }
00114 }


Member Data Documentation

is app active in network init phase?

Definition at line 146 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

bool DHTTestApp::debugOutput [private]

debug output yes/no?

Reimplemented from BaseApp.

Definition at line 142 of file DHTTestApp.h.

Referenced by initializeApp().

double DHTTestApp::deviation [private]

deviation of time interval

Definition at line 144 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

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

Definition at line 160 of file DHTTestApp.h.

Referenced by generateRandomValue().

cMessage * DHTTestApp::dhttestget_timer [private]

Definition at line 157 of file DHTTestApp.h.

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

cMessage * DHTTestApp::dhttestmod_timer [private]

Definition at line 157 of file DHTTestApp.h.

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

cMessage* DHTTestApp::dhttestput_timer [private]

Definition at line 157 of file DHTTestApp.h.

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

pointer to the GlobalDhtTestMap module

Definition at line 139 of file DHTTestApp.h.

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

pointer to GlobalNodeList in this node

Reimplemented from BaseApp.

Definition at line 136 of file DHTTestApp.h.

Referenced by initializeApp().

pointer to GlobalStatistics module in this node

Reimplemented from BaseApp.

Definition at line 138 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 143 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().

true if the node is going to be killed shortly

Definition at line 158 of file DHTTestApp.h.

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

int DHTTestApp::numGetError [private]

number of false get responses

Definition at line 151 of file DHTTestApp.h.

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

int DHTTestApp::numGetSent [private]

number of get sent

Definition at line 150 of file DHTTestApp.h.

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

number of false get responses

Definition at line 152 of file DHTTestApp.h.

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

int DHTTestApp::numPutError [private]

number of error in put responses

Definition at line 154 of file DHTTestApp.h.

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

int DHTTestApp::numPutSent [private]

number of put sent

Definition at line 153 of file DHTTestApp.h.

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

number of success in put responses

Definition at line 155 of file DHTTestApp.h.

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

int DHTTestApp::numSent [private]

number of sent packets

Definition at line 149 of file DHTTestApp.h.

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

int DHTTestApp::ttl [private]

ttl for stored DHT records

Definition at line 145 of file DHTTestApp.h.

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

pointer to UnderlayConfigurator in this node

Reimplemented from BaseApp.

Definition at line 134 of file DHTTestApp.h.

Referenced by handleTimerEvent(), and initializeApp().


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

Generated on Tue Sep 8 17:26:58 2009 for OverSim by  doxygen 1.5.8