DHTTestApp.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2007 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     // fetch parameters
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     // statistics
00085     numSent = 0;
00086     numGetSent = 0;
00087     numGetError = 0;
00088     numGetSuccess = 0;
00089     numPutSent = 0;
00090     numPutError = 0;
00091     numPutSuccess = 0;
00092 
00093     //initRpcs();
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     // initiate test message transmission
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         // don't count response, if the request was not sent
00156         // in the measurement phase
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         // don't count response, if the request was not sent
00177         // in the measurement phase
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         //unexpected key
00196         RECORD_STATS(numGetError++);
00197         cout << "DHTTestApp: unexpected key" << endl;
00198         delete context;
00199         return;
00200     }
00201 
00202     if (simTime() > entry->endtime) {
00203         //this key doesn't exist anymore in the DHT, delete it in our hashtable
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             //cout << "DHTTestApp: success (1)" << endl;
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             //cout << "DHTTestApp: success (2)" << endl;
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         // Generate key
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         // get value
00259         buf++;
00260 
00261         // build putMsg
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         // Get key
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         // schedule next timer event
00295         scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00296 
00297         // do nothing if the network is still in the initialization phase
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                     // create a put test message with random destination key
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         // create a put test message with random destination key
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         // do nothing if the network is still in the initialization phase
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         // do nothing if the network is still in the initialization phase
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         // record scalar data
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 
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3