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 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
00080 numSent = 0;
00081 numGetSent = 0;
00082 numGetError = 0;
00083 numGetSuccess = 0;
00084 numPutSent = 0;
00085 numPutError = 0;
00086 numPutSuccess = 0;
00087
00088
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
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 }
00115
00116 void DHTTestApp::handleRpcResponse(BaseResponseMessage* msg,
00117 cPolymorphic* context, int rpcId,
00118 simtime_t rtt)
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 }
00142
00143 void DHTTestApp::handlePutResponse(DHTputCAPIResponse* msg,
00144 DHTStatsContext* context)
00145 {
00146 if (!(msg->getIsSuccess())) {
00147 if (context->measurementPhase == false) {
00148
00149
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
00164
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 }
00175
00176 void DHTTestApp::handleGetResponse(DHTgetCAPIResponse* msg,
00177 DHTStatsContext* context)
00178 {
00179 if (context->measurementPhase == false) {
00180
00181
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
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
00200 RECORD_STATS(numGetError++);
00201
00202 delete context;
00203 return;
00204 }
00205
00206 if (simTime() > entry->endtime) {
00207
00208
00209 globalDhtTestMap->eraseEntry(context->key);
00210 delete context;
00211
00212 if (msg->getResultArraySize() > 0) {
00213 RECORD_STATS(numGetError++);
00214
00215 return;
00216 } else {
00217 RECORD_STATS(numGetSuccess++);
00218
00219 return;
00220 }
00221 } else {
00222 delete context;
00223 if ((msg->getResultArraySize() > 0) && (msg->getResult(0).getValue() != entry->value)) {
00224 RECORD_STATS(numGetError++);
00225
00226
00227 return;
00228 } else {
00229 RECORD_STATS(numGetSuccess++);
00230
00231 return;
00232 }
00233 }
00234
00235 }
00236
00237 void DHTTestApp::handleTraceMessage(cMessage* msg)
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
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
00263 buf++;
00264
00265
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
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 }
00294
00295 void DHTTestApp::handleTimerEvent(cMessage* msg)
00296 {
00297 if (msg->isName("dhttest_put_timer")) {
00298
00299 scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00300
00301
00302 if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00303 || underlayConfigurator->isSimulationEndingSoon()
00304 || nodeIsLeavingSoon)
00305 return;
00306
00307
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
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
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 }
00373
00374
00375 BinaryValue DHTTestApp::generateRandomValue()
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 }
00386
00387 void DHTTestApp::handleNodeLeaveNotification()
00388 {
00389 nodeIsLeavingSoon = true;
00390 }
00391
00392 void DHTTestApp::finishApp()
00393 {
00394 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00395
00396 if (time >= GlobalStatistics::MIN_MEASURED) {
00397
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 }
00421