00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <IPAddressResolver.h>
00025 #include <GlobalNodeListAccess.h>
00026 #include <GlobalStatisticsAccess.h>
00027 #include <UnderlayConfiguratorAccess.h>
00028 #include <RpcMacros.h>
00029 #include "CommonMessages_m.h"
00030
00031 #include <GlobalDhtTestMap.h>
00032
00033 #include "DHTTestApp.h"
00034
00035 Define_Module(DHTTestApp);
00036
00037 using namespace std;
00038
00039 DHTTestApp::~DHTTestApp()
00040 {
00041 cancelAndDelete(dhttestput_timer);
00042 cancelAndDelete(dhttestget_timer);
00043 cancelAndDelete(dhttestmod_timer);
00044 }
00045
00046 DHTTestApp::DHTTestApp()
00047 {
00048 dhttestput_timer = NULL;
00049 dhttestget_timer = NULL;
00050 dhttestmod_timer = NULL;
00051 }
00052
00053 void DHTTestApp::initializeApp(int stage)
00054 {
00055 if (stage != MIN_STAGE_APP)
00056 return;
00057
00058
00059 debugOutput = par("debugOutput");
00060 activeNetwInitPhase = par("activeNetwInitPhase");
00061
00062 mean = par("testInterval");
00063 p2pnsTraffic = par("p2pnsTraffic");
00064 deviation = mean / 10;
00065
00066 if (p2pnsTraffic) {
00067 ttl = 3600*24*365;
00068 } else {
00069 ttl = par("testTtl");
00070 }
00071
00072 globalNodeList = GlobalNodeListAccess().get();
00073 underlayConfigurator = UnderlayConfiguratorAccess().get();
00074 globalStatistics = GlobalStatisticsAccess().get();
00075
00076 globalDhtTestMap = dynamic_cast<GlobalDhtTestMap*>(simulation.getModuleByPath(
00077 "globalObserver.globalFunctions[0].function"));
00078
00079 if (globalDhtTestMap == NULL) {
00080 throw cRuntimeError("DHTTestApp::initializeApp(): "
00081 "GlobalDhtTestMap module not found!");
00082 }
00083
00084
00085 numSent = 0;
00086 numGetSent = 0;
00087 numGetError = 0;
00088 numGetSuccess = 0;
00089 numPutSent = 0;
00090 numPutError = 0;
00091 numPutSuccess = 0;
00092
00093
00094 WATCH(numSent);
00095 WATCH(numGetSent);
00096 WATCH(numGetError);
00097 WATCH(numGetSuccess);
00098 WATCH(numPutSent);
00099 WATCH(numPutError);
00100 WATCH(numPutSuccess);
00101
00102 nodeIsLeavingSoon = false;
00103
00104
00105 dhttestput_timer = new cMessage("dhttest_put_timer");
00106 dhttestget_timer = new cMessage("dhttest_get_timer");
00107 dhttestmod_timer = new cMessage("dhttest_mod_timer");
00108
00109 if (mean > 0) {
00110 scheduleAt(simTime() + truncnormal(mean, deviation),
00111 dhttestput_timer);
00112 scheduleAt(simTime() + truncnormal(mean + mean / 3,
00113 deviation),
00114 dhttestget_timer);
00115 scheduleAt(simTime() + truncnormal(mean + 2 * mean / 3,
00116 deviation),
00117 dhttestmod_timer);
00118 }
00119 }
00120
00121 void DHTTestApp::handleRpcResponse(BaseResponseMessage* msg,
00122 const RpcState& state, simtime_t rtt)
00123 {
00124 RPC_SWITCH_START(msg)
00125 RPC_ON_RESPONSE( DHTputCAPI ) {
00126 handlePutResponse(_DHTputCAPIResponse,
00127 check_and_cast<DHTStatsContext*>(state.getContext()));
00128 EV << "[DHTTestApp::handleRpcResponse()]\n"
00129 << " DHT Put RPC Response received: id=" << state.getId()
00130 << " msg=" << *_DHTputCAPIResponse << " rtt=" << rtt
00131 << endl;
00132 break;
00133 }
00134 RPC_ON_RESPONSE(DHTgetCAPI)
00135 {
00136 handleGetResponse(_DHTgetCAPIResponse,
00137 check_and_cast<DHTStatsContext*>(state.getContext()));
00138 EV << "[DHTTestApp::handleRpcResponse()]\n"
00139 << " DHT Get RPC Response received: id=" << state.getId()
00140 << " msg=" << *_DHTgetCAPIResponse << " rtt=" << rtt
00141 << endl;
00142 break;
00143 }
00144 RPC_SWITCH_END()
00145 }
00146
00147 void DHTTestApp::handlePutResponse(DHTputCAPIResponse* msg,
00148 DHTStatsContext* context)
00149 {
00150 DHTEntry entry = {context->value, simTime() + ttl};
00151
00152 globalDhtTestMap->insertEntry(context->key, entry);
00153
00154 if (context->measurementPhase == false) {
00155
00156
00157 delete context;
00158 return;
00159 }
00160
00161 if (msg->getIsSuccess()) {
00162 RECORD_STATS(numPutSuccess++);
00163 RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: PUT Latency (s)",
00164 SIMTIME_DBL(simTime() - context->requestTime)));
00165 } else {
00166 RECORD_STATS(numPutError++);
00167 }
00168
00169 delete context;
00170 }
00171
00172 void DHTTestApp::handleGetResponse(DHTgetCAPIResponse* msg,
00173 DHTStatsContext* context)
00174 {
00175 if (context->measurementPhase == false) {
00176
00177
00178 delete context;
00179 return;
00180 }
00181
00182 RECORD_STATS(globalStatistics->addStdDev("DHTTestApp: GET Latency (s)",
00183 SIMTIME_DBL(simTime() - context->requestTime)));
00184
00185 if (!(msg->getIsSuccess())) {
00186 cout << "DHTTestApp: success == false" << endl;
00187 RECORD_STATS(numGetError++);
00188 delete context;
00189 return;
00190 }
00191
00192 const DHTEntry* entry = globalDhtTestMap->findEntry(context->key);
00193
00194 if (entry == NULL) {
00195
00196 RECORD_STATS(numGetError++);
00197 cout << "DHTTestApp: unexpected key" << endl;
00198 delete context;
00199 return;
00200 }
00201
00202 if (simTime() > entry->endtime) {
00203
00204
00205 globalDhtTestMap->eraseEntry(context->key);
00206 delete context;
00207
00208 if (msg->getResultArraySize() > 0) {
00209 RECORD_STATS(numGetError++);
00210 cout << "DHTTestApp: deleted key still available" << endl;
00211 return;
00212 } else {
00213 RECORD_STATS(numGetSuccess++);
00214
00215 return;
00216 }
00217 } else {
00218 delete context;
00219 if ((msg->getResultArraySize() > 0) && (msg->getResult(0).getValue() != entry->value)) {
00220 RECORD_STATS(numGetError++);
00221 cout << "DHTTestApp: wrong value" << endl;
00222 cout << "value: " << msg->getResult(0).getValue() << endl;
00223 return;
00224 } else {
00225 RECORD_STATS(numGetSuccess++);
00226
00227 return;
00228 }
00229 }
00230
00231 }
00232
00233 void DHTTestApp::handleTraceMessage(cMessage* msg)
00234 {
00235 char* cmd = new char[strlen(msg->getName()) + 1];
00236 strcpy(cmd, msg->getName());
00237
00238 if (strlen(msg->getName()) < 5) {
00239 delete[] cmd;
00240 delete msg;
00241 return;
00242 }
00243
00244 if (strncmp(cmd, "PUT ", 4) == 0) {
00245
00246 char* buf = cmd + 4;
00247
00248 while (!isspace(buf[0])) {
00249 if (buf[0] == '\0')
00250 throw cRuntimeError("Error parsing PUT command");
00251 buf++;
00252 }
00253
00254 buf[0] = '\0';
00255 BinaryValue b(cmd + 4);
00256 OverlayKey destKey(OverlayKey::sha1(b));
00257
00258
00259 buf++;
00260
00261
00262 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00263 dhtPutMsg->setKey(destKey);
00264 dhtPutMsg->setValue(buf);
00265 dhtPutMsg->setTtl(ttl);
00266 dhtPutMsg->setIsModifiable(true);
00267 RECORD_STATS(numSent++; numPutSent++);
00268 sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00269 new DHTStatsContext(globalStatistics->isMeasuring(),
00270 simTime(), destKey));
00271 } else if (strncmp(cmd, "GET ", 4) == 0) {
00272
00273 BinaryValue b(cmd + 4);
00274 OverlayKey key(OverlayKey::sha1(b));
00275
00276 DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00277 dhtGetMsg->setKey(key);
00278 RECORD_STATS(numSent++; numGetSent++);
00279 sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
00280 new DHTStatsContext(globalStatistics->isMeasuring(),
00281 simTime(), key));
00282 } else {
00283 throw cRuntimeError("Unknown trace command; "
00284 "only GET and PUT are allowed");
00285 }
00286
00287 delete[] cmd;
00288 delete msg;
00289 }
00290
00291 void DHTTestApp::handleTimerEvent(cMessage* msg)
00292 {
00293 if (msg->isName("dhttest_put_timer")) {
00294
00295 scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00296
00297
00298 if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00299 || underlayConfigurator->isSimulationEndingSoon()
00300 || nodeIsLeavingSoon)
00301 return;
00302
00303 if (p2pnsTraffic) {
00304 if (globalDhtTestMap->p2pnsNameCount < 4*globalNodeList->getNumNodes()) {
00305 for (int i = 0; i < 4; i++) {
00306
00307 OverlayKey destKey = OverlayKey::random();
00308 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00309 dhtPutMsg->setKey(destKey);
00310 dhtPutMsg->setValue(generateRandomValue());
00311 dhtPutMsg->setTtl(ttl);
00312 dhtPutMsg->setIsModifiable(true);
00313
00314 RECORD_STATS(numSent++; numPutSent++);
00315 sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00316 new DHTStatsContext(globalStatistics->isMeasuring(),
00317 simTime(), destKey, dhtPutMsg->getValue()));
00318 globalDhtTestMap->p2pnsNameCount++;
00319 }
00320 }
00321 cancelEvent(msg);
00322 return;
00323 }
00324
00325
00326 OverlayKey destKey = OverlayKey::random();
00327 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00328 dhtPutMsg->setKey(destKey);
00329 dhtPutMsg->setValue(generateRandomValue());
00330 dhtPutMsg->setTtl(ttl);
00331 dhtPutMsg->setIsModifiable(true);
00332
00333 RECORD_STATS(numSent++; numPutSent++);
00334 sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00335 new DHTStatsContext(globalStatistics->isMeasuring(),
00336 simTime(), destKey, dhtPutMsg->getValue()));
00337 } else if (msg->isName("dhttest_get_timer")) {
00338 scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00339
00340
00341 if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00342 || underlayConfigurator->isSimulationEndingSoon()
00343 || nodeIsLeavingSoon) {
00344 return;
00345 }
00346
00347 if (p2pnsTraffic && (uniform(0, 1) > ((double)mean/1800.0))) {
00348 return;
00349 }
00350
00351 const OverlayKey& key = globalDhtTestMap->getRandomKey();
00352
00353 if (key.isUnspecified()) {
00354 EV << "[DHTTestApp::handleTimerEvent() @ " << thisNode.getAddress()
00355 << " (" << thisNode.getKey().toString(16) << ")]\n"
00356 << " Error: No key available in global DHT test map!"
00357 << endl;
00358 return;
00359 }
00360
00361 DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00362 dhtGetMsg->setKey(key);
00363 RECORD_STATS(numSent++; numGetSent++);
00364
00365 sendInternalRpcCall(TIER1_COMP, dhtGetMsg,
00366 new DHTStatsContext(globalStatistics->isMeasuring(),
00367 simTime(), key));
00368 } else if (msg->isName("dhttest_mod_timer")) {
00369 scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00370
00371
00372 if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00373 || underlayConfigurator->isSimulationEndingSoon()
00374 || nodeIsLeavingSoon) {
00375 return;
00376 }
00377
00378 if (p2pnsTraffic) {
00379 if (globalDhtTestMap->p2pnsNameCount >= 4*globalNodeList->getNumNodes()) {
00380 const OverlayKey& key = globalDhtTestMap->getRandomKey();
00381
00382 if (key.isUnspecified())
00383 return;
00384
00385 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00386 dhtPutMsg->setKey(key);
00387 dhtPutMsg->setValue(generateRandomValue());
00388 dhtPutMsg->setTtl(ttl);
00389 dhtPutMsg->setIsModifiable(true);
00390
00391 RECORD_STATS(numSent++; numPutSent++);
00392 sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00393 new DHTStatsContext(globalStatistics->isMeasuring(),
00394 simTime(), key, dhtPutMsg->getValue()));
00395 }
00396 cancelEvent(msg);
00397 return;
00398 }
00399
00400 const OverlayKey& key = globalDhtTestMap->getRandomKey();
00401
00402 if (key.isUnspecified())
00403 return;
00404
00405 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00406 dhtPutMsg->setKey(key);
00407 dhtPutMsg->setValue(generateRandomValue());
00408 dhtPutMsg->setTtl(ttl);
00409 dhtPutMsg->setIsModifiable(true);
00410
00411 RECORD_STATS(numSent++; numPutSent++);
00412 sendInternalRpcCall(TIER1_COMP, dhtPutMsg,
00413 new DHTStatsContext(globalStatistics->isMeasuring(),
00414 simTime(), key, dhtPutMsg->getValue()));
00415 }
00416 }
00417
00418
00419 BinaryValue DHTTestApp::generateRandomValue()
00420 {
00421 char value[DHTTESTAPP_VALUE_LEN + 1];
00422
00423 for (int i = 0; i < DHTTESTAPP_VALUE_LEN; i++) {
00424 value[i] = intuniform(0, 25) + 'a';
00425 }
00426
00427 value[DHTTESTAPP_VALUE_LEN] = '\0';
00428 return BinaryValue(value);
00429 }
00430
00431 void DHTTestApp::handleNodeLeaveNotification()
00432 {
00433 nodeIsLeavingSoon = true;
00434 }
00435
00436 void DHTTestApp::finishApp()
00437 {
00438 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00439
00440 if (time >= GlobalStatistics::MIN_MEASURED) {
00441
00442 globalStatistics->addStdDev("DHTTestApp: Sent Total Messages/s",
00443 numSent / time);
00444 globalStatistics->addStdDev("DHTTestApp: Sent GET Messages/s",
00445 numGetSent / time);
00446 globalStatistics->addStdDev("DHTTestApp: Failed GET Requests/s",
00447 numGetError / time);
00448 globalStatistics->addStdDev("DHTTestApp: Successful GET Requests/s",
00449 numGetSuccess / time);
00450
00451 globalStatistics->addStdDev("DHTTestApp: Sent PUT Messages/s",
00452 numPutSent / time);
00453 globalStatistics->addStdDev("DHTTestApp: Failed PUT Requests/s",
00454 numPutError / time);
00455 globalStatistics->addStdDev("DHTTestApp: Successful PUT Requests/s",
00456 numPutSuccess / time);
00457
00458 if ((numGetSuccess + numGetError) > 0) {
00459 globalStatistics->addStdDev("DHTTestApp: GET Success Ratio",
00460 (double) numGetSuccess
00461 / (double) (numGetSuccess + numGetError));
00462 }
00463 }
00464 }
00465