DHTTestApp Class Reference

#include <DHTTestApp.h>

Inheritance diagram for DHTTestApp:

BaseApp BaseRpc RpcListener

List of all members.


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

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
BootstrapOraclebootstrapOracle
 pointer to BootstrapOracle 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
double 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

Classes

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

Constructor & Destructor Documentation

DHTTestApp::DHTTestApp (  ) 

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

DHTTestApp::~DHTTestApp (  )  [virtual]

virtual destructor

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


Member Function Documentation

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

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

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     bootstrapOracle = BootstrapOracleAccess().get();
00068     underlayConfigurator = UnderlayConfiguratorAccess().get();
00069     globalStatistics = GlobalStatisticsAccess().get();
00070 
00071     globalDhtTestMap = dynamic_cast<GlobalDhtTestMap*>(simulation.moduleByPath(
00072             "globalObserver.globalFunctions[0]"));
00073 
00074     if (globalDhtTestMap == NULL) {
00075         throw new 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(simulation.simTime() + truncnormal(mean, deviation),
00106                    dhttestput_timer);
00107         scheduleAt(simulation.simTime() + truncnormal(mean + mean / 3,
00108                                                       deviation),
00109                                                       dhttestget_timer);
00110         scheduleAt(simulation.simTime() + truncnormal(mean + 2 * mean / 3,
00111                                                       deviation),
00112                                                       dhttestmod_timer);
00113     }
00114 }

OverlayKey DHTTestApp::getRandomKey (  )  [private]

Get a random key of the hashmap.

BinaryValue DHTTestApp::generateRandomValue (  )  [private]

generate a random human readable binary value

Referenced by handleTimerEvent().

00357 {
00358     char value[DHTTESTAPP_VALUE_LEN + 1];
00359 
00360     for (int i = 0; i < DHTTESTAPP_VALUE_LEN; i++) {
00361         value[i] = intuniform(0, 25) + 'a';
00362     }
00363 
00364     value[DHTTESTAPP_VALUE_LEN] = '\0';
00365     return BinaryValue(value);
00366 }

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

collects statistical data of derived app

Reimplemented from BaseApp.

00374 {
00375     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00376 
00377     // record scalar data
00378     globalStatistics->addStdDev("DHTTestApp: Sent Total Messages/s",
00379                                 numSent / time);
00380     globalStatistics->addStdDev("DHTTestApp: Sent GET Messages/s",
00381                                 numGetSent / time);
00382     globalStatistics->addStdDev("DHTTestApp: Failed GET Requests/s",
00383                                 numGetError / time);
00384     globalStatistics->addStdDev("DHTTestApp: Successful GET Requests/s",
00385                                 numGetSuccess / time);
00386 
00387     globalStatistics->addStdDev("DHTTestApp: Sent PUT Messages/s",
00388                                 numPutSent / time);
00389     globalStatistics->addStdDev("DHTTestApp: Failed PUT Requests/s",
00390                                 numPutError / time);
00391     globalStatistics->addStdDev("DHTTestApp: Successful PUT Requests/s",
00392                                 numPutSuccess / time);
00393 
00394     if (numGetSent > 0) {
00395             globalStatistics->addStdDev("DHTTestApp: GET Success Ratio",
00396                                         (double) numGetSuccess
00397                                         / (double) numGetSent);
00398     }
00399 }

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

Referenced by handleRpcResponse().

00171 {
00172     if (context->measurementPhase == false) {
00173         // don't count response, if the request was not sent
00174         // in the measurement phase
00175         return;
00176     }
00177 
00178     RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: GET delay (s)",
00179                                              simTime() - context->requestTime));
00180 
00181     if (!(msg->getIsSuccess())) {
00182         //cout << "DHTTestApp: success == false" << endl;
00183         RECORD_STATS(numGetError++);
00184         return;
00185     }
00186 
00187     const DHTEntry* entry = globalDhtTestMap->findEntry(msg->getKey());
00188 
00189     if (entry == NULL) {
00190         //unexpected key
00191         RECORD_STATS(numGetError++);
00192         //cout << "DHTTestApp: unexpected key" << endl;
00193         return;
00194     }
00195 
00196     if (simulation.simTime() > entry->endtime) {
00197         //this key doesn't exist anymore in the DHT, delete it in our hashtable
00198 
00199         globalDhtTestMap->eraseEntry(msg->getKey());
00200 
00201         if (!(msg->getValue().isUnspecified())) {
00202             RECORD_STATS(numGetError++);
00203             //cout << "DHTTestApp: deleted key still available" << endl;
00204             return;
00205         } else {
00206             RECORD_STATS(numGetSuccess++);
00207             return;
00208         }
00209     } else {
00210         if (msg->getValue() != entry->value) {
00211             RECORD_STATS(numGetError++);
00212             //cout << "DHTTestApp: wrong value" << endl;
00213             //cout << "size: " << msg->getValue().size() << endl;
00214             return;
00215         } else {
00216             RECORD_STATS(numGetSuccess++);
00217             return;
00218         }
00219     }
00220 
00221 }

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

Referenced by handleRpcResponse().

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

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

00282 {
00283     if (msg->isName("dhttest_put_timer")) {
00284         // schedule next timer event
00285         scheduleAt(simulation.simTime() + truncnormal(mean, deviation), msg);
00286 
00287         // do nothing if the network is still in the initialization phase
00288         if ((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase())
00289                 || underlayConfigurator->isSimulationEndingSoon()
00290                 || nodeIsLeavingSoon)
00291             return;
00292 
00293         // create a put test message with random destination key
00294         OverlayKey destKey = OverlayKey::random();
00295         DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00296         dhtPutMsg->setKey(destKey);
00297         dhtPutMsg->setValue(generateRandomValue());
00298         dhtPutMsg->setTtl(ttl);
00299         dhtPutMsg->setIsModifiable(true);
00300 
00301         RECORD_STATS(numSent++; numPutSent++);
00302         sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00303                 new DHTStatsContext(globalStatistics->isMeasuring(),
00304                                     simTime()));
00305     } else if (msg->isName("dhttest_get_timer")) {
00306         scheduleAt(simulation.simTime() + truncnormal(mean, deviation), msg);
00307 
00308         // do nothing if the network is still in the initialization phase
00309         if ((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase())
00310                 || underlayConfigurator->isSimulationEndingSoon()
00311                 || nodeIsLeavingSoon) {
00312             return;
00313         }
00314 
00315         const OverlayKey& key = globalDhtTestMap->getRandomKey();
00316 
00317         if (key.isUnspecified())
00318             return;
00319 
00320         DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00321         dhtGetMsg->setKey(key);
00322         RECORD_STATS(numSent++; numGetSent++);
00323 
00324         sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
00325                 new DHTStatsContext(globalStatistics->isMeasuring(),
00326                                     simTime()));
00327     } else if (msg->isName("dhttest_mod_timer")) {
00328         scheduleAt(simulation.simTime() + truncnormal(mean, deviation), msg);
00329 
00330         // do nothing if the network is still in the initialization phase
00331         if ((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase())
00332                 || underlayConfigurator->isSimulationEndingSoon()
00333                 || nodeIsLeavingSoon) {
00334             return;
00335         }
00336 
00337         const OverlayKey& key = globalDhtTestMap->getRandomKey();
00338 
00339         if (key.isUnspecified())
00340             return;
00341 
00342         DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00343         dhtPutMsg->setKey(key);
00344         dhtPutMsg->setValue(generateRandomValue());
00345         dhtPutMsg->setTtl(ttl);
00346         dhtPutMsg->setIsModifiable(true);
00347 
00348         RECORD_STATS(numSent++; numPutSent++);
00349         sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00350                 new DHTStatsContext(globalStatistics->isMeasuring(),
00351                                     simTime()));
00352     }
00353 }

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.

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

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

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

Reimplemented from BaseApp.

00369 {
00370     nodeIsLeavingSoon = true;
00371 }

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.

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


Member Data Documentation

pointer to UnderlayConfigurator in this node

Reimplemented from BaseApp.

Referenced by handleTimerEvent(), and initializeApp().

pointer to BootstrapOracle in this node

Reimplemented from BaseApp.

Referenced by initializeApp().

pointer to GlobalStatistics module in this node

Reimplemented from BaseApp.

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

bool DHTTestApp::debugOutput [private]

debug output yes/no?

Reimplemented from BaseApp.

Referenced by initializeApp().

double DHTTestApp::mean [private]

mean time interval between sending test messages

Referenced by handleTimerEvent(), and initializeApp().

double DHTTestApp::deviation [private]

deviation of time interval

Referenced by handleTimerEvent(), and initializeApp().

double DHTTestApp::ttl [private]

ttl for stored DHT records

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

is app active in network init phase?

Referenced by handleTimerEvent(), and initializeApp().

int DHTTestApp::numSent [private]

number of sent packets

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

int DHTTestApp::numGetSent [private]

int DHTTestApp::numGetError [private]

number of false get responses

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

number of false get responses

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

int DHTTestApp::numPutSent [private]

int DHTTestApp::numPutError [private]

number of error in put responses

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

number of success in put responses

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

cMessage* DHTTestApp::dhttestput_timer [private]

cMessage * DHTTestApp::dhttestget_timer [private]

cMessage * DHTTestApp::dhttestmod_timer [private]

true if the node is going to be killed shortly

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

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

Referenced by generateRandomValue().


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

Generated on Fri Sep 19 13:05:06 2008 for ITM OverSim by  doxygen 1.5.5