#include <DHTTestApp.h>
A simple test application that does random put and get calls on the DHT layer
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 | |
UnderlayConfigurator * | underlayConfigurator |
pointer to UnderlayConfigurator in this node | |
BootstrapOracle * | bootstrapOracle |
pointer to BootstrapOracle in this node | |
GlobalStatistics * | globalStatistics |
pointer to GlobalStatistics module in this node | |
GlobalDhtTestMap * | globalDhtTestMap |
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... |
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 }
void DHTTestApp::initializeApp | ( | int | stage | ) | [private, virtual] |
initializes derived class-attributes
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
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
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
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.
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.
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 }
pointer to UnderlayConfigurator in this node
Reimplemented from BaseApp.
Referenced by handleTimerEvent(), and initializeApp().
BootstrapOracle* DHTTestApp::bootstrapOracle [private] |
GlobalStatistics* DHTTestApp::globalStatistics [private] |
pointer to GlobalStatistics module in this node
Reimplemented from BaseApp.
Referenced by finishApp(), handleGetResponse(), handlePutResponse(), handleTimerEvent(), handleTraceMessage(), and initializeApp().
GlobalDhtTestMap* DHTTestApp::globalDhtTestMap [private] |
pointer to the GlobalDhtTestMap module
Referenced by handleGetResponse(), handlePutResponse(), handleTimerEvent(), and initializeApp().
bool DHTTestApp::debugOutput [private] |
double DHTTestApp::mean [private] |
mean time interval between sending test messages
Referenced by handleTimerEvent(), and initializeApp().
double DHTTestApp::deviation [private] |
double DHTTestApp::ttl [private] |
ttl for stored DHT records
Referenced by handlePutResponse(), handleTimerEvent(), handleTraceMessage(), and initializeApp().
bool DHTTestApp::activeNetwInitPhase [private] |
int DHTTestApp::numSent [private] |
number of sent packets
Referenced by finishApp(), handleTimerEvent(), handleTraceMessage(), and initializeApp().
int DHTTestApp::numGetSent [private] |
number of get sent
Referenced by finishApp(), handleTimerEvent(), handleTraceMessage(), and initializeApp().
int DHTTestApp::numGetError [private] |
int DHTTestApp::numGetSuccess [private] |
int DHTTestApp::numPutSent [private] |
number of put sent
Referenced by finishApp(), handleTimerEvent(), handleTraceMessage(), and initializeApp().
int DHTTestApp::numPutError [private] |
number of error in put responses
Referenced by finishApp(), handlePutResponse(), and initializeApp().
int DHTTestApp::numPutSuccess [private] |
number of success in put responses
Referenced by finishApp(), handlePutResponse(), and initializeApp().
cMessage* DHTTestApp::dhttestput_timer [private] |
Referenced by DHTTestApp(), initializeApp(), and ~DHTTestApp().
cMessage * DHTTestApp::dhttestget_timer [private] |
Referenced by DHTTestApp(), initializeApp(), and ~DHTTestApp().
cMessage * DHTTestApp::dhttestmod_timer [private] |
Referenced by DHTTestApp(), initializeApp(), and ~DHTTestApp().
bool DHTTestApp::nodeIsLeavingSoon [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().