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     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     // 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(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             // don't count response, if the request was not sent
00149             // in the measurement phase
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         // don't count response, if the request was not sent
00164         // in the measurement phase
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         // don't count response, if the request was not sent
00181         // in the measurement phase
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         //cout << "DHTTestApp: success == false" << endl;
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         //unexpected key
00200         RECORD_STATS(numGetError++);
00201         //cout << "DHTTestApp: unexpected key" << endl;
00202         delete context;
00203         return;
00204     }
00205 
00206     if (simTime() > entry->endtime) {
00207         //this key doesn't exist anymore in the DHT, delete it in our hashtable
00208 
00209         globalDhtTestMap->eraseEntry(context->key);
00210         delete context;
00211 
00212         if (msg->getResultArraySize() > 0) {
00213             RECORD_STATS(numGetError++);
00214             //cout << "DHTTestApp: deleted key still available" << endl;
00215             return;
00216         } else {
00217             RECORD_STATS(numGetSuccess++);
00218             //cout << "DHTTestApp: success (1)" << endl;
00219             return;
00220         }
00221     } else {
00222         delete context;
00223         if ((msg->getResultArraySize() > 0) && (msg->getResult(0).getValue() != entry->value)) {
00224             RECORD_STATS(numGetError++);
00225             //cout << "DHTTestApp: wrong value" << endl;
00226             //cout << "size: " << msg->getResult(0).getValue().size() << endl;
00227             return;
00228         } else {
00229             RECORD_STATS(numGetSuccess++);
00230             //cout << "DHTTestApp: success (2)" << endl;
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         // Generate key
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         // get value
00263         buf++;
00264 
00265         // build putMsg
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         // Get key
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         // schedule next timer event
00299         scheduleAt(simTime() + truncnormal(mean, deviation), msg);
00300 
00301         // do nothing if the network is still in the initialization phase
00302         if (((!activeNetwInitPhase) && (underlayConfigurator->isInInitPhase()))
00303                 || underlayConfigurator->isSimulationEndingSoon()
00304                 || nodeIsLeavingSoon)
00305             return;
00306 
00307         // create a put test message with random destination key
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         // do nothing if the network is still in the initialization phase
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         // do nothing if the network is still in the initialization phase
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         // record scalar data
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 

Generated on Tue Sep 8 17:26:52 2009 for OverSim by  doxygen 1.5.8