00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <sstream>
00025
00026 #include <IPAddressResolver.h>
00027 #include <IPvXAddress.h>
00028 #include <IInterfaceTable.h>
00029 #include <IPv4InterfaceData.h>
00030 #include <RpcMacros.h>
00031 #include <InitStages.h>
00032 #include <NeighborCache.h>
00033 #include <GlobalStatistics.h>
00034 #include <BootstrapList.h>
00035 #include <assert.h>
00036
00037 #include "BasePastry.h"
00038
00039
00040 void BasePastry::purgeVectors(void)
00041 {
00042
00043 if (!stReceived.empty()) {
00044 for (std::vector<PastryStateMsgHandle>::iterator it =
00045 stReceived.begin(); it != stReceived.end(); it++) {
00046
00047 if (it->msg == stateCache.msg) {
00048 stateCache.msg = NULL;
00049 stateCache.prox = NULL;
00050 }
00051 delete it->msg;
00052 delete it->prox;
00053 }
00054 stReceived.clear();
00055 stReceivedPos = stReceived.end();
00056 }
00057
00058
00059 notifyList.clear();
00060
00061
00062 for (std::map<TransportAddress, BaseRouteMessage*>::iterator i =
00063 recFwdQueue.begin(); i != recFwdQueue.end(); i++) {
00064 delete i->second;
00065 }
00066 recFwdQueue.clear();
00067
00068
00069 while (! stateCacheQueue.empty()) {
00070 delete stateCacheQueue.front().msg;
00071 stateCacheQueue.pop();
00072 }
00073
00074
00075 if (stateCache.msg) {
00076 delete stateCache.msg;
00077 stateCache.msg = NULL;
00078 delete stateCache.prox;
00079 stateCache.prox = NULL;
00080 }
00081
00082
00083 if (! sendStateWait.empty()) {
00084 for (std::vector<PastrySendState*>::iterator it =
00085 sendStateWait.begin(); it != sendStateWait.end(); it++) {
00086 if ( (*it)->isScheduled() ) cancelEvent(*it);
00087 delete *it;
00088 }
00089 sendStateWait.clear();
00090 }
00091 }
00092
00093 void BasePastry::baseInit()
00094 {
00095 bitsPerDigit = par("bitsPerDigit");
00096 numberOfLeaves = par("numberOfLeaves");
00097 numberOfNeighbors = par("numberOfNeighbors");
00098 joinTimeoutAmount = par("joinTimeout");
00099 repairTimeout = par("repairTimeout");
00100 enableNewLeafs = par("enableNewLeafs");
00101 optimizeLookup = par("optimizeLookup");
00102 optimisticForward = par("optimisticForward");
00103 avoidDuplicates = par("avoidDuplicates");
00104 sendStateWaitAmount = par("sendStateWaitAmount");
00105 timeoutPing = par("pingTimeout");
00106 pingRetries = par("pingRetries");
00107 useRegularNextHop = par("useRegularNextHop");
00108 alwaysSendUpdate = par("alwaysSendUpdate");
00109
00110 useDiscovery = false;
00111
00112 if (!neighborCache->isEnabled()) {
00113 throw cRuntimeError("NeighborCache is disabled, which is mandatory "
00114 "for Pastry/Bamboo. Activate it by setting "
00115 "\"**.neighborCache.enableNeighborCache "
00116 "= true\" in your omnetpp.ini!");
00117 }
00118
00119 if (numberOfLeaves % 2) {
00120 EV << "[BasePastry::baseInit() @ " << thisNode.getAddress()
00121 << " (" << thisNode.getKey().toString(16) << ")]\n"
00122 << " Warning: numberOfLeaves must be even - adding 1."
00123 << endl;
00124 numberOfLeaves++;
00125 }
00126
00127 routingTable = check_and_cast<PastryRoutingTable*>
00128 (getParentModule()->getSubmodule("pastryRoutingTable"));
00129 leafSet = check_and_cast<PastryLeafSet*>
00130 (getParentModule()->getSubmodule("pastryLeafSet"));
00131 neighborhoodSet = check_and_cast<PastryNeighborhoodSet*>
00132 (getParentModule()->getSubmodule("pastryNeighborhoodSet"));
00133
00134 stateCache.msg = NULL;
00135 stateCache.prox = NULL;
00136
00137 rowToAsk = 0;
00138
00139
00140 joins = 0;
00141 joinTries = 0;
00142 joinPartial = 0;
00143 joinSeen = 0;
00144 joinReceived = 0;
00145 joinSent = 0;
00146 stateSent = 0;
00147 stateReceived = 0;
00148 repairReqSent = 0;
00149 repairReqReceived = 0;
00150 stateReqSent = 0;
00151 stateReqReceived = 0;
00152
00153 joinBytesSeen = 0;
00154 joinBytesReceived = 0;
00155 joinBytesSent = 0;
00156 stateBytesSent = 0;
00157 stateBytesReceived = 0;
00158 repairReqBytesSent = 0;
00159 repairReqBytesReceived = 0;
00160 stateReqBytesSent = 0;
00161 stateReqBytesReceived = 0;
00162
00163 totalLookups = 0;
00164 responsibleLookups = 0;
00165 routingTableLookups = 0;
00166 closerNodeLookups = 0;
00167 closerNodeLookupsFromNeighborhood = 0;
00168
00169 leafsetReqSent = 0;
00170 leafsetReqBytesSent = 0;
00171 leafsetReqReceived = 0;
00172 leafsetReqBytesReceived = 0;
00173 leafsetSent = 0;
00174 leafsetBytesSent = 0;
00175 leafsetReceived = 0;
00176 leafsetBytesReceived = 0;
00177
00178 routingTableReqSent = 0;
00179 routingTableReqBytesSent = 0;
00180 routingTableReqReceived = 0;
00181 routingTableReqBytesReceived = 0;
00182 routingTableSent = 0;
00183 routingTableBytesSent = 0;
00184 routingTableReceived = 0;
00185 routingTableBytesReceived = 0;
00186
00187 WATCH(joins);
00188 WATCH(joinTries);
00189 WATCH(joinSeen);
00190 WATCH(joinBytesSeen);
00191 WATCH(joinReceived);
00192 WATCH(joinBytesReceived);
00193 WATCH(joinSent);
00194 WATCH(joinBytesSent);
00195 WATCH(stateSent);
00196 WATCH(stateBytesSent);
00197 WATCH(stateReceived);
00198 WATCH(stateBytesReceived);
00199 WATCH(repairReqSent);
00200 WATCH(repairReqBytesSent);
00201 WATCH(repairReqReceived);
00202 WATCH(repairReqBytesReceived);
00203 WATCH(stateReqSent);
00204 WATCH(stateReqBytesSent);
00205 WATCH(stateReqReceived);
00206 WATCH(stateReqBytesReceived);
00207 WATCH(lastStateChange);
00208
00209 WATCH(leafsetReqSent);
00210 WATCH(leafsetReqBytesSent);
00211 WATCH(leafsetReqReceived);
00212 WATCH(leafsetReqBytesReceived);
00213 WATCH(leafsetSent);
00214 WATCH(leafsetBytesSent);
00215 WATCH(leafsetReceived);
00216 WATCH(leafsetBytesReceived);
00217
00218 WATCH(routingTableReqSent);
00219 WATCH(routingTableReqBytesSent);
00220 WATCH(routingTableReqReceived);
00221 WATCH(routingTableReqBytesReceived);
00222 WATCH(routingTableSent);
00223 WATCH(routingTableBytesSent);
00224 WATCH(routingTableReceived);
00225 WATCH(routingTableBytesReceived);
00226 }
00227
00228
00229 void BasePastry::baseChangeState(int toState)
00230 {
00231 switch (toState) {
00232 case INIT:
00233 state = INIT;
00234
00235 if (!thisNode.getKey().isUnspecified())
00236 bootstrapList->removeBootstrapNode(thisNode);
00237
00238 if (joinTimeout->isScheduled()) cancelEvent(joinTimeout);
00239
00240 purgeVectors();
00241
00242 bootstrapNode = bootstrapList->getBootstrapNode();
00243
00244 routingTable->initializeTable(bitsPerDigit, repairTimeout,
00245 thisNode);
00246 leafSet->initializeSet(numberOfLeaves, bitsPerDigit,
00247 repairTimeout, thisNode,
00248 this);
00249 neighborhoodSet->initializeSet(numberOfNeighbors, bitsPerDigit,
00250 thisNode);
00251
00252 updateTooltip();
00253 lastStateChange = simTime();
00254
00255 getParentModule()->getParentModule()->bubble("entering INIT state");
00256
00257 break;
00258
00259 case JOINING_2:
00260 state = JOINING_2;
00261
00262
00263
00264
00265 if (bootstrapNode.isUnspecified()) {
00266
00267 changeState(READY);
00268 return;
00269 }
00270
00271 cancelEvent(joinTimeout);
00272 scheduleAt(simTime() + joinTimeoutAmount, joinTimeout);
00273
00274 updateTooltip();
00275 getParentModule()->getParentModule()->bubble("entering JOIN state");
00276
00277 RECORD_STATS(joinTries++);
00278
00279 break;
00280
00281 case READY:
00282 assert(state != READY);
00283 state = READY;
00284
00285
00286
00287
00288
00289 if (bootstrapNode.isUnspecified()) {
00290 RECORD_STATS(joinTries++);
00291 RECORD_STATS(joins++);
00292 setOverlayReady(true);
00293 return;
00294 }
00295
00296 getParentModule()->getParentModule()->bubble("entering READY state");
00297 updateTooltip();
00298 RECORD_STATS(joins++);
00299
00300 break;
00301
00302 default:
00303 break;
00304 }
00305 setOverlayReady(state == READY);
00306 }
00307
00308
00309 void BasePastry::newLeafs(void)
00310 {
00311 if (! enableNewLeafs) return;
00312
00313 PastryNewLeafsMessage* msg = leafSet->getNewLeafsMessage();
00314 if (msg) {
00315 send(msg, "appOut");
00316 EV << "[BasePastry::newLeafs() @ " << thisNode.getAddress()
00317 << " (" << thisNode.getKey().toString(16) << ")]\n"
00318 << " newLeafs() called."
00319 << endl;
00320 }
00321 }
00322
00323
00324 void BasePastry::changeState(int toState)
00325 {
00326
00327 }
00328
00329
00330 bool BasePastry::recursiveRoutingHook(const TransportAddress& dest,
00331 BaseRouteMessage* msg)
00332 {
00333 if (dest == thisNode) {
00334 return true;
00335 }
00336
00337 PastryMessage* pmsg =
00338 dynamic_cast<PastryMessage*>(msg->getEncapsulatedMsg());
00339
00340 if (pmsg && pmsg->getPastryMsgType() == PASTRY_MSG_JOIN) {
00341 PastryJoinMessage* jmsg = static_cast<PastryJoinMessage*>(pmsg);
00342 if (jmsg->getSendStateTo() != thisNode) {
00343 RECORD_STATS(joinSeen++; joinBytesSeen += jmsg->getByteLength());
00344
00345 handleFailedNode(jmsg->getSendStateTo());
00346
00347 sendStateTables(jmsg->getSendStateTo(), PASTRY_STATE_JOIN,
00348 check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo())
00349 ->getHopCount(), false);
00350 }
00351 }
00352
00353 if (recFwdQueue.find(dest) != recFwdQueue.end()) {
00354
00355
00356 return true;
00357 }
00358
00359 assert(msg->getControlInfo());
00360
00361 if (optimisticForward) {
00362
00363 return true;
00364 } else {
00365 if (routeMsgAcks) throw cRuntimeError("!optimisticForward && "
00366 "routeMsgAcks");
00367
00368 recFwdQueue[dest] = msg;
00369 pingNode(dest, timeoutPing, pingRetries, NULL,
00370 "PING next hop", NULL, PING_NEXT_HOP);
00371
00372 return false;
00373 }
00374 }
00375
00376 int BasePastry::getNextRowToMaintain()
00377 {
00378 int digit = 0;
00379 int lastRow = routingTable->getLastRow();
00380
00381 int* choices = new int[lastRow + 1];
00382 int sum = 0;
00383
00384 for (int i = 0; i < lastRow; ++i) {
00385 sum += (choices[i] = lastRow - i);
00386 }
00387
00388 int rval = intuniform(0, sum);
00389
00390 while (true) {
00391 rval -= choices [digit];
00392 if (rval <= 0)
00393 break;
00394 ++digit;
00395 }
00396 delete[] choices;
00397
00398 return digit;
00399 }
00400
00401 void BasePastry::doRoutingTableMaintenance()
00402 {
00403 if (sendPullFlag) {
00404
00405 rowToAsk = getNextRowToMaintain();
00406
00407
00408 const TransportAddress& ask4row = routingTable->getRandomNode(rowToAsk);
00409
00410 if ((!ask4row.isUnspecified()) && (ask4row != thisNode)) {
00411 PastryRoutingRowRequestMessage* msg = new PastryRoutingRowRequestMessage("ROWREQ");
00412 msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00413 msg->setStatType(MAINTENANCE_STAT);
00414 msg->setSendStateTo(thisNode);
00415 msg->setRow(rowToAsk + 1);
00416 msg->setBitLength(PASTRYRTREQ_L(msg));
00417
00418 RECORD_STATS(routingTableReqSent++; routingTableReqBytesSent += msg->getByteLength());
00419
00420 EV << "[BasePastry::doRoutingTableMaintenance() @ " << thisNode.getAddress()
00421 << " (" << thisNode.getKey().toString(16) << ")]\n"
00422 << " Sending Message to Node in Row" << rowToAsk
00423 << endl;
00424
00425 sendMessageToUDP(ask4row, msg);
00426 }
00427 } else {
00428
00429 for (int i = 0; i < routingTable->getLastRow(); i++) {
00430 const TransportAddress& ask4row = routingTable->getRandomNode(i);
00431
00432 if ((!ask4row.isUnspecified()) && (ask4row != thisNode)) {
00433 PastryRoutingRowRequestMessage* msg = new PastryRoutingRowRequestMessage("ROWREQ");
00434 msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00435 msg->setStatType(MAINTENANCE_STAT);
00436 msg->setSendStateTo(thisNode);
00437 msg->setRow(i + 1);
00438 msg->setBitLength(PASTRYRTREQ_L(msg));
00439
00440 RECORD_STATS(routingTableReqSent++; routingTableReqBytesSent += msg->getByteLength());
00441
00442 sendMessageToUDP(ask4row, msg);
00443 } else {
00444 EV << "[BasePastry::doRoutingTableMaintenance() @ " << thisNode.getAddress()
00445 << " (" << thisNode.getKey().toString(16) << ")]\n"
00446 << " could not send Message to Node in Row" << i
00447 << endl;
00448 }
00449 }
00450 }
00451 }
00452
00453 void BasePastry::pingResponse(PingResponse* msg, cPolymorphic* context,
00454 int rpcId, simtime_t rtt)
00455 {
00456 EV << "[BasePastry::pingResponse() @ " << thisNode.getAddress()
00457 << " (" << thisNode.getKey().toString(16) << ")]\n"
00458 << " Pong (or Ping-context from NeighborCache) received (from "
00459 << msg->getSrcNode().getAddress() << ")"
00460 << endl;
00461
00462 const NodeHandle& src = msg->getSrcNode();
00463 assert(!src.isUnspecified());
00464
00465
00466 if (rpcId == PING_SINGLE_NODE) {
00467 routingTable->mergeNode(src, rtt);
00468 return;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 if (state == DISCOVERY) {
00482 if (nearNodeRtt > rtt) {
00483 nearNode = src;
00484 nearNodeRtt = rtt;
00485 nearNodeImproved = true;
00486 }
00487 }
00488
00489 if (context != NULL && stateCache.msg && stateCache.prox) {
00490 PingContext* pingContext = check_and_cast<PingContext*>(context);
00491 if (pingContext->nonce != stateCache.nonce) {
00492 delete context;
00493 return;
00494
00495 }
00496 switch (pingContext->stateObject) {
00497 case ROUTINGTABLE: {
00498
00499
00500
00501
00502
00503
00504
00505 *(stateCache.prox->pr_rt.begin() + pingContext->index) = rtt;
00506 break;
00507 }
00508 case LEAFSET: {
00509
00510
00511
00512
00513
00514
00515
00516 *(stateCache.prox->pr_ls.begin() + pingContext->index) = rtt;
00517 break;
00518 }
00519 case NEIGHBORHOODSET: {
00520
00521
00522
00523
00524
00525
00526
00527 *(stateCache.prox->pr_ns.begin() + pingContext->index) = rtt;
00528 break;
00529 }
00530 default: {
00531 throw cRuntimeError("wrong state object type!");
00532 }
00533 }
00534 checkProxCache();
00535 }
00536 delete context;
00537
00538 std::map<TransportAddress, BaseRouteMessage*>::iterator pos;
00539 if ((pos = recFwdQueue.find(src)) != recFwdQueue.end()) {
00540
00541 if (!optimisticForward) {
00542 sendMessageToUDP(pos->first, pos->second);
00543 } else if (!avoidDuplicates) {
00544 delete pos->second;
00545 }
00546 recFwdQueue.erase(pos);
00547 }
00548 }
00549
00550
00551 void BasePastry::proxCallback(const TransportAddress& node, int rpcId,
00552 cPolymorphic *contextPointer, Prox prox)
00553 {
00554 Enter_Method("proxCallback()");
00555
00556 EV << "[BasePastry::proxCallback() @ " << thisNode.getAddress()
00557 << " (" << thisNode.getKey().toString(16) << ")]\n"
00558 << " Pong received (from "
00559 << node.getAddress() << ")"
00560 << endl;
00561
00562 double rtt = ((prox == Prox::PROX_TIMEOUT) ? PASTRY_PROX_INFINITE
00563 : prox.proximity);
00564
00565
00566 if (rpcId == PING_SINGLE_NODE) {
00567 routingTable->mergeNode((const NodeHandle&)node, rtt);
00568 return;
00569 }
00570
00571 if (contextPointer != NULL && stateCache.msg && stateCache.prox) {
00572 PingContext* pingContext = check_and_cast<PingContext*>(contextPointer);
00573
00574 if (pingContext->nonce != stateCache.nonce) {
00575 delete contextPointer;
00576 return;
00577 }
00578
00579 if (rtt == PASTRY_PROX_INFINITE && state== READY) {
00580 handleFailedNode(node);
00581 updateTooltip();
00582
00583
00584
00585 if (state != READY) {
00586 delete contextPointer;
00587 return;
00588 }
00589 }
00590 switch (pingContext->stateObject) {
00591 case ROUTINGTABLE:
00592 *(stateCache.prox->pr_rt.begin() + pingContext->index) = rtt;
00593 break;
00594
00595 case LEAFSET:
00596 *(stateCache.prox->pr_ls.begin() + pingContext->index) = rtt;
00597 break;
00598
00599 case NEIGHBORHOODSET:
00600 *(stateCache.prox->pr_ns.begin() + pingContext->index) = rtt;
00601 break;
00602
00603 default:
00604 throw cRuntimeError("wrong state object type!");
00605 }
00606 checkProxCache();
00607 }
00608 delete contextPointer;
00609 }
00610
00611
00612 void BasePastry::prePing(const PastryStateMessage* stateMsg)
00613 {
00614 uint32_t rt_size = stateMsg->getRoutingTableArraySize();
00615 uint32_t ls_size = stateMsg->getLeafSetArraySize();
00616 uint32_t ns_size = stateMsg->getNeighborhoodSetArraySize();
00617
00618 for (uint32_t i = 0; i < rt_size + ls_size + ns_size; i++) {
00619 const NodeHandle* node;
00620 if (i < rt_size) {
00621 node = &(stateMsg->getRoutingTable(i));
00622 }
00623 else if (i < (rt_size + ls_size) ) {
00624 node = &(stateMsg->getLeafSet(i - rt_size));
00625 }
00626 else {
00627 node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00628 }
00629 if ((node->isUnspecified()) || (*node == thisNode)) {
00630 continue;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 neighborCache->getProx(*node, NEIGHBORCACHE_DEFAULT, PING_RECEIVED_STATE, this, NULL);
00642 }
00643 }
00644
00645 void BasePastry::pingNodes(void)
00646 {
00647 EV << "[BasePastry::pingNodes() @ " << thisNode.getAddress()
00648 << " (" << thisNode.getKey().toString(16) << ")]" << endl;
00649
00650 if (stateCache.msg == NULL) throw cRuntimeError("no state msg");
00651
00652 assert(stateCache.prox == NULL);
00653 stateCache.prox = new PastryStateMsgProximity();
00654
00655 uint32_t rt_size = stateCache.msg->getRoutingTableArraySize();
00656 stateCache.prox->pr_rt.resize(rt_size, PASTRY_PROX_UNDEF);
00657
00658 uint32_t ls_size = stateCache.msg->getLeafSetArraySize();
00659 stateCache.prox->pr_ls.resize(ls_size, PASTRY_PROX_UNDEF);
00660
00661 uint32_t ns_size = stateCache.msg->getNeighborhoodSetArraySize();
00662 stateCache.prox->pr_ns.resize(ns_size, PASTRY_PROX_UNDEF);
00663
00664 std::vector< std::pair<const NodeHandle*, PingContext*> > nodesToPing;
00665
00666 for (uint32_t i = 0; i < rt_size + ls_size + ns_size; i++) {
00667 const NodeHandle* node;
00668 std::vector<simtime_t>::iterator proxPos;
00669 PingContext* pingContext = NULL;
00670 StateObject stateObject;
00671 uint32_t index;
00672 if (stateCache.msg == NULL) break;
00673 if (i < rt_size) {
00674 node = &(stateCache.msg->getRoutingTable(i));
00675 proxPos = stateCache.prox->pr_rt.begin() + i;
00676 stateObject = ROUTINGTABLE;
00677 index = i;
00678 } else if ( i < (rt_size + ls_size) ) {
00679 node = &(stateCache.msg->getLeafSet(i - rt_size));
00680 proxPos = stateCache.prox->pr_ls.begin() + (i - rt_size);
00681 stateObject = LEAFSET;
00682 index = i - rt_size;
00683 } else {
00684 node = &(stateCache.msg->getNeighborhoodSet(i - rt_size - ls_size));
00685 proxPos = stateCache.prox->pr_ns.begin() + (i - rt_size - ls_size);
00686 stateObject = NEIGHBORHOODSET;
00687 index = i - rt_size - ls_size;
00688 }
00689
00690 if (!node->isUnspecified()) {
00691 pingContext = new PingContext(stateObject, index,
00692 stateCache.nonce);
00693
00694 Prox prox = neighborCache->getProx(*node, NEIGHBORCACHE_DEFAULT, -1,
00695 this, pingContext);
00696 if (prox == Prox::PROX_SELF) {
00697 *proxPos = 0;
00698 } else if (prox == Prox::PROX_TIMEOUT) {
00699 *proxPos = PASTRY_PROX_INFINITE;
00700 } else if (prox == Prox::PROX_UNKNOWN) {
00701 *proxPos = PASTRY_PROX_PENDING;
00702 } else {
00703 *proxPos = prox.proximity;
00704 }
00705 }
00706 }
00707 checkProxCache();
00708 }
00709
00710 void BasePastry::determineAliveTable(const PastryStateMessage* stateMsg)
00711 {
00712 uint32_t rt_size = stateMsg->getRoutingTableArraySize();
00713 aliveTable.pr_rt.clear();
00714 aliveTable.pr_rt.resize(rt_size, 1);
00715
00716 uint32_t ls_size = stateMsg->getLeafSetArraySize();
00717 aliveTable.pr_ls.clear();
00718 aliveTable.pr_ls.resize(ls_size, 1);
00719
00720 uint32_t ns_size = stateMsg->getNeighborhoodSetArraySize();
00721 aliveTable.pr_ns.clear();
00722 aliveTable.pr_ns.resize(ns_size, 1);
00723
00724 for (uint32_t i = 0; i < rt_size + ls_size + ns_size; i++) {
00725 const TransportAddress* node;
00726 std::vector<simtime_t>::iterator tblPos;
00727 if (i < rt_size) {
00728 node = &(stateMsg->getRoutingTable(i));
00729 tblPos = aliveTable.pr_rt.begin() + i;
00730 } else if ( i < (rt_size + ls_size) ) {
00731 node = &(stateMsg->getLeafSet(i - rt_size));
00732 tblPos = aliveTable.pr_ls.begin() + (i - rt_size);
00733 } else {
00734 node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00735 tblPos = aliveTable.pr_ns.begin() + (i - rt_size - ls_size);
00736 }
00737 if (neighborCache->getProx(*node, NEIGHBORCACHE_DEFAULT_IMMEDIATELY) ==
00738 Prox::PROX_TIMEOUT) {
00739 *tblPos = PASTRY_PROX_INFINITE;
00740 }
00741 }
00742 }
00743
00744 void BasePastry::sendStateTables(const TransportAddress& destination, int type, ...)
00745 {
00746 if (destination.getAddress() == thisNode.getAddress())
00747 opp_error("Pastry: trying to send state to self!");
00748
00749 int hops = 0;
00750 bool last = false;
00751 simtime_t timestamp = 0;
00752
00753 if ((type == PASTRY_STATE_JOIN) || (type == PASTRY_STATE_UPDATE)) {
00754
00755 va_list ap;
00756 va_start(ap, type);
00757 if (type == PASTRY_STATE_JOIN) {
00758 hops = va_arg(ap, int);
00759 last = static_cast<bool>(va_arg(ap, int));
00760 } else {
00761 timestamp = *va_arg(ap, simtime_t*);
00762 }
00763 va_end(ap);
00764 }
00765
00766
00767 PastryStateMessage* stateMsg;
00768 if (type == PASTRY_STATE_JOIN) {
00769 stateMsg = new PastryStateMessage("STATE (Join)");
00770 stateMsg->setJoinHopCount(hops);
00771 stateMsg->setLastHop(last);
00772 stateMsg->setTimestamp(simTime());
00773 } else if (type == PASTRY_STATE_UPDATE) {
00774 stateMsg = new PastryStateMessage("STATE (Update)");
00775 EV << "[BasePastry::sendStateTables() @ " << thisNode.getAddress()
00776 << " (" << thisNode.getKey().toString(16) << ")]\n"
00777 << " sending state (update) to " << destination
00778 << endl;
00779 stateMsg->setTimestamp(timestamp);
00780 } else if (type == PASTRY_STATE_REPAIR) {
00781 stateMsg = new PastryStateMessage("STATE (Repair)");
00782 stateMsg->setTimestamp(timestamp);
00783 EV << "[BasePastry::sendStateTables() @ " << thisNode.getAddress()
00784 << " (" << thisNode.getKey().toString(16) << ")]\n"
00785 << " sending state (repair) to " << destination
00786 << endl;
00787 } else {
00788 stateMsg = new PastryStateMessage("STATE");
00789 EV << "[BasePastry::sendStateTables() @ " << thisNode.getAddress()
00790 << " (" << thisNode.getKey().toString(16) << ")]\n"
00791 << " sending state (standard) to " << destination
00792 << endl;
00793 }
00794
00795
00796 stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00797 stateMsg->setStatType(MAINTENANCE_STAT);
00798 stateMsg->setPastryStateMsgType(type);
00799 stateMsg->setSender(thisNode);
00800
00801
00802
00803
00804 if ((type == PASTRY_STATE_JOIN) && (useDiscovery)) {
00805 routingTable->dumpRowToMessage(stateMsg, hops);
00806 if (last) leafSet->dumpToStateMessage(stateMsg);
00807 else stateMsg->setLeafSetArraySize(0);
00808 if (hops == 1) neighborhoodSet->dumpToStateMessage(stateMsg);
00809 else stateMsg->setNeighborhoodSetArraySize(0);
00810 }
00811 else {
00812 routingTable->dumpToStateMessage(stateMsg);
00813 leafSet->dumpToStateMessage(stateMsg);
00814 neighborhoodSet->dumpToStateMessage(stateMsg);
00815 }
00816
00817
00818 stateMsg->setBitLength(PASTRYSTATE_L(stateMsg));
00819 RECORD_STATS(stateSent++; stateBytesSent += stateMsg->getByteLength());
00820 sendMessageToUDP(destination, stateMsg);
00821 }
00822
00823 void BasePastry::sendStateDelayed(const TransportAddress& destination)
00824 {
00825 PastrySendState* selfMsg = new PastrySendState("sendStateWait");
00826 selfMsg->setDest(destination);
00827 sendStateWait.push_back(selfMsg);
00828 scheduleAt(simTime() + sendStateWaitAmount, selfMsg);
00829 }
00830
00831 void BasePastry::pingTimeout(PingCall* msg,
00832 const TransportAddress& dest,
00833 cPolymorphic* context,
00834 int rpcId)
00835 {
00836 EV << "[BasePastry::sendStateDelayed() @ " << thisNode.getAddress()
00837 << " (" << thisNode.getKey().toString(16) << ")]\n"
00838 << " Ping timeout occurred (" << dest.getAddress() << ")"
00839 << endl;
00840
00841
00842 if (state == READY) {
00843 handleFailedNode(dest);
00844 updateTooltip();
00845
00846
00847
00848 if (state != READY) {
00849 delete context;
00850 return;
00851 }
00852 }
00853
00854
00855 if (context && stateCache.msg && stateCache.prox &&
00856 rpcId == PING_RECEIVED_STATE) {
00857 PingContext* pingContext = check_and_cast<PingContext*>(context);
00858 if (pingContext->nonce != stateCache.nonce) {
00859 delete context;
00860 return;
00861
00862
00863
00864 }
00865
00866 switch (pingContext->stateObject) {
00867 case ROUTINGTABLE: {
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 *(stateCache.prox->pr_rt.begin() + pingContext->index) =
00881 PASTRY_PROX_INFINITE;
00882 break;
00883 }
00884 case LEAFSET: {
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 *(stateCache.prox->pr_ls.begin() + pingContext->index) =
00898 PASTRY_PROX_INFINITE;
00899 break;
00900 }
00901 case NEIGHBORHOODSET: {
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 *(stateCache.prox->pr_ns.begin() + pingContext->index) =
00915 PASTRY_PROX_INFINITE;
00916 break;
00917 }
00918 }
00919 checkProxCache();
00920 }
00921
00922 delete context;
00923
00924 if (rpcId == PING_NEXT_HOP) {
00925
00926 std::map<TransportAddress, BaseRouteMessage*>::iterator pos;
00927 if ((pos = recFwdQueue.find(dest)) == recFwdQueue.end()) return;
00928 BaseRouteMessage* rmsg = pos->second;
00929 recFwdQueue.erase(pos);
00930 if (dynamic_cast<PastryJoinMessage*>(rmsg->getEncapsulatedMsg()) &&
00931 rmsg->getDestKey() == thisNode.getKey()) {
00932
00933 changeState(INIT);
00934 return;
00935 }
00936 assert(rmsg->getControlInfo());
00937 sendToKey(rmsg->getDestKey(), rmsg);
00938 }
00939 }
00940
00941 void BasePastry::sendRequest(const TransportAddress& ask, int type)
00942 {
00943 assert(ask != thisNode);
00944 std::string msgName("Req: ");
00945 switch (type) {
00946 case PASTRY_REQ_REPAIR:
00947 if (ask.isUnspecified())
00948 opp_error("Pastry::sendRequest(): asked for repair from "
00949 "unspecified node!");
00950 msgName += "Repair";
00951 break;
00952
00953 case PASTRY_REQ_STATE:
00954 if (ask.isUnspecified())
00955 opp_error("Pastry::sendRequest(): asked for state from "
00956 "unspecified node!");
00957 msgName += "State";
00958 break;
00959
00960 case PASTRY_REQ_LEAFSET:
00961 if (ask.isUnspecified())
00962 opp_error("Pastry::sendRequest(): asked for leafset from "
00963 "unspecified node!");
00964 msgName += "Leafset";
00965 break;
00966 }
00967 PastryRequestMessage* msg = new PastryRequestMessage(msgName.c_str());
00968 msg->setPastryMsgType(PASTRY_MSG_REQ);
00969 msg->setPastryReqType(type);
00970 msg->setStatType(MAINTENANCE_STAT);
00971 msg->setSendStateTo(thisNode);
00972 msg->setBitLength(PASTRYREQ_L(msg));
00973 sendMessageToUDP(ask, msg);
00974
00975 switch (type) {
00976 case PASTRY_REQ_REPAIR:
00977 RECORD_STATS(repairReqSent++; repairReqBytesSent += msg->getByteLength());
00978 break;
00979
00980 case PASTRY_REQ_STATE:
00981 RECORD_STATS(stateReqSent++; stateReqBytesSent += msg->getByteLength());
00982 break;
00983
00984 case PASTRY_REQ_LEAFSET:
00985 RECORD_STATS(leafsetReqSent++; leafsetReqBytesSent += msg->getByteLength());
00986 break;
00987 }
00988 }
00989
00990
00991 void BasePastry::sendLeafset(const TransportAddress& tell, bool pull)
00992 {
00993 if (tell.isUnspecified())
00994 opp_error("Pastry::sendLeafset(): send leafset to "
00995 "unspecified node!");
00996
00997 PastryLeafsetMessage* msg = new PastryLeafsetMessage("Leafset");
00998 if (pull) msg->setPastryMsgType(PASTRY_MSG_LEAFSET_PULL);
00999 else msg->setPastryMsgType(PASTRY_MSG_LEAFSET);
01000 msg->setTimestamp(simTime());
01001 msg->setStatType(MAINTENANCE_STAT);
01002 msg->setSender(thisNode);
01003 msg->setSendStateTo(thisNode);
01004 leafSet->dumpToStateMessage(msg);
01005 msg->setBitLength(PASTRYLEAFSET_L(msg));
01006 RECORD_STATS(leafsetSent++; leafsetBytesSent += msg->getByteLength());
01007 sendMessageToUDP(tell, msg);
01008
01009
01010 }
01011
01012 void BasePastry::sendRoutingRow(const TransportAddress& tell, int row)
01013 {
01014 if (tell.isUnspecified())
01015 opp_error("Pastry::sendRoutingTable(): asked for routing Table from "
01016 "unspecified node!");
01017
01018 PastryRoutingRowMessage* msg = new PastryRoutingRowMessage("Routing Row");
01019 msg->setPastryMsgType(PASTRY_MSG_RROW);
01020 msg->setStatType(MAINTENANCE_STAT);
01021
01022 msg->setSender(thisNode);
01023 msg->setRow(row);
01024 routingTable->dumpRowToMessage(msg, row);
01025 msg->setBitLength(PASTRYRTABLE_L(msg));
01026 RECORD_STATS(routingTableSent++; routingTableBytesSent += msg->getByteLength());
01027 sendMessageToUDP(tell, msg);
01028 }
01029
01030 void BasePastry::handleRequestMessage(PastryRequestMessage* msg)
01031 {
01032 assert(msg->getSendStateTo() != thisNode);
01033 uint32_t reqtype = msg->getPastryReqType();
01034 if (reqtype == PASTRY_REQ_REPAIR) {
01035 RECORD_STATS(repairReqReceived++; repairReqBytesReceived +=
01036 msg->getByteLength());
01037 if (state == READY)
01038 sendStateTables(msg->getSendStateTo(),
01039 PASTRY_STATE_REPAIR);
01040 else
01041 EV << "[BasePastry::handleRequestMessage() @ " << thisNode.getAddress()
01042 << " (" << thisNode.getKey().toString(16) << ")]\n"
01043 << " received repair request before reaching"
01044 << " READY state, dropping message!"
01045 << endl;
01046 delete msg;
01047 }
01048 else if (reqtype == PASTRY_REQ_STATE) {
01049 RECORD_STATS(stateReqReceived++; stateReqBytesReceived +=
01050 msg->getByteLength());
01051 if (state == READY)
01052 sendStateTables(msg->getSendStateTo());
01053 else
01054 EV << "[BasePastry::handleRequestMessage() @ " << thisNode.getAddress()
01055 << " (" << thisNode.getKey().toString(16) << ")]\n"
01056 << " received state request before reaching"
01057 << " READY state, dropping message!"
01058 << endl;
01059 delete msg;
01060 }
01061 else if (PASTRY_REQ_LEAFSET) {
01062 RECORD_STATS(leafsetReqReceived++; leafsetReqBytesReceived +=
01063 msg->getByteLength());
01064 if (state == READY) {
01065 sendLeafset(msg->getSendStateTo());
01066 }
01067 else
01068 EV << "[BasePastry::handleRequestMessage() @ " << thisNode.getAddress()
01069 << " (" << thisNode.getKey().toString(16) << ")]\n"
01070 << " received leafset request before reaching"
01071 << " READY state, dropping message!"
01072 << endl;
01073 delete msg;
01074 }
01075
01076 }
01077
01078 void BasePastry::handleLeafsetMessage(PastryLeafsetMessage* msg, bool mergeSender)
01079 {
01080 uint32_t lsSize = msg->getLeafSetArraySize();
01081 PastryStateMessage* stateMsg;
01082
01083 stateMsg = new PastryStateMessage("STATE");
01084 stateMsg->setTimestamp(msg->getTimestamp());
01085 stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
01086 stateMsg->setStatType(MAINTENANCE_STAT);
01087 stateMsg->setSender(msg->getSender());
01088 stateMsg->setLeafSetArraySize(lsSize);
01089 stateMsg->setNeighborhoodSetArraySize(0);
01090 stateMsg->setRoutingTableArraySize(0);
01091
01092 for (uint32_t i = 0; i < lsSize; i++) {
01093 stateMsg->setLeafSet(i, msg->getLeafSet(i));
01094 }
01095
01096 if (mergeSender) {
01097 stateMsg->setLeafSetArraySize(lsSize+1);
01098 stateMsg->setLeafSet(lsSize, msg->getSender());
01099 }
01100
01101 handleStateMessage(stateMsg);
01102 delete msg;
01103 }
01104
01105 bool BasePastry::isSiblingFor(const NodeHandle& node,
01106 const OverlayKey& key,
01107 int numSiblings,
01108 bool* err)
01109 {
01110 if (key.isUnspecified())
01111 error("Pastry::isSiblingFor(): key is unspecified!");
01112
01113 if ((numSiblings == 1) && (node == thisNode)) {
01114 if (leafSet->isClosestNode(key)) {
01115 *err = false;
01116 return true;
01117 } else {
01118 *err = false;
01119 return false;
01120 }
01121 }
01122
01123 NodeVector* result = leafSet->createSiblingVector(key, numSiblings);
01124
01125 if (result == NULL) {
01126 *err = true;
01127 return false;
01128 }
01129
01130 if (result->contains(node.getKey())) {
01131 delete result;
01132 *err = false;
01133 return true;
01134 } else {
01135 delete result;
01136 *err = true;
01137 return false;
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 }
01152
01153
01154 void BasePastry::handleAppMessage(BaseOverlayMessage* msg)
01155 {
01156 delete msg;
01157 }
01158
01159 void BasePastry::updateTooltip()
01160 {
01161 if (ev.isGUI()) {
01162 std::stringstream ttString;
01163
01164
01165 ttString << leafSet->getPredecessor() << endl << thisNode << endl
01166 << leafSet->getSuccessor();
01167
01168 getParentModule()->getParentModule()->getDisplayString().
01169 setTagArg("tt", 0, ttString.str().c_str());
01170 getParentModule()->getDisplayString().
01171 setTagArg("tt", 0, ttString.str().c_str());
01172 getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
01173
01174
01175 showOverlayNeighborArrow(leafSet->getSuccessor(), true,
01176 "m=m,50,0,50,0;ls=red,1");
01177 showOverlayNeighborArrow(leafSet->getPredecessor(), false,
01178 "m=m,50,100,50,100;ls=green,1");
01179
01180 }
01181 }
01182
01183 BasePastry::~BasePastry()
01184 {
01185 cancelAndDelete(joinTimeout);
01186
01187 purgeVectors();
01188 }
01189
01190 void BasePastry::finishOverlay()
01191 {
01192
01193 if (!thisNode.getKey().isUnspecified()) bootstrapList->removeBootstrapNode(thisNode);
01194
01195
01196 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01197 if (time < GlobalStatistics::MIN_MEASURED) return;
01198
01199
01200
01201
01202
01203
01204
01205 if (joinTries > 0 && joinTimeout->isScheduled()) joinTries--;
01206 if (joinTries > 0) {
01207 globalStatistics->addStdDev("Pastry: join success ratio", (double)joins / (double)joinTries);
01208 globalStatistics->addStdDev("Pastry: join tries", joinTries);
01209 } else if (state == READY) {
01210
01211 globalStatistics->addStdDev("Pastry: join success ratio", 1);
01212 globalStatistics->addStdDev("Pastry: join tries", 1);
01213 } else {
01214 globalStatistics->addStdDev("Pastry: join success ratio", 0);
01215 globalStatistics->addStdDev("Pastry: join tries", 1);
01216 }
01217
01218 globalStatistics->addStdDev("Pastry: joins with missing replies from routing path/s",
01219 joinPartial / time);
01220 globalStatistics->addStdDev("Pastry: JOIN Messages seen/s", joinSeen / time);
01221 globalStatistics->addStdDev("Pastry: bytes of JOIN Messages seen/s", joinBytesSeen / time);
01222 globalStatistics->addStdDev("Pastry: JOIN Messages received/s", joinReceived / time);
01223 globalStatistics->addStdDev("Pastry: bytes of JOIN Messages received/s",
01224 joinBytesReceived / time);
01225 globalStatistics->addStdDev("Pastry: JOIN Messages sent/s", joinSent / time);
01226 globalStatistics->addStdDev("Pastry: bytes of JOIN Messages sent/s", joinBytesSent / time);
01227 globalStatistics->addStdDev("Pastry: STATE Messages sent/s", stateSent / time);
01228 globalStatistics->addStdDev("Pastry: bytes of STATE Messages sent/s", stateBytesSent / time);
01229 globalStatistics->addStdDev("Pastry: STATE Messages received/s", stateReceived / time);
01230 globalStatistics->addStdDev("Pastry: bytes of STATE Messages received/s",
01231 stateBytesReceived / time);
01232 globalStatistics->addStdDev("Pastry: REPAIR Requests sent/s", repairReqSent / time);
01233 globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests sent/s",
01234 repairReqBytesSent / time);
01235 globalStatistics->addStdDev("Pastry: REPAIR Requests received/s", repairReqReceived / time);
01236 globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests received/s",
01237 repairReqBytesReceived / time);
01238 globalStatistics->addStdDev("Pastry: STATE Requests sent/s", stateReqSent / time);
01239 globalStatistics->addStdDev("Pastry: bytes of STATE Requests sent/s", stateReqBytesSent / time);
01240 globalStatistics->addStdDev("Pastry: STATE Requests received/s", stateReqReceived / time);
01241 globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01242 stateReqBytesReceived / time);
01243
01244 globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01245 stateReqBytesReceived / time);
01246
01247 globalStatistics->addStdDev("Pastry: total number of lookups", totalLookups);
01248 globalStatistics->addStdDev("Pastry: responsible lookups", responsibleLookups);
01249 globalStatistics->addStdDev("Pastry: lookups in routing table", routingTableLookups);
01250 globalStatistics->addStdDev("Pastry: lookups using closerNode()", closerNodeLookups);
01251 globalStatistics->addStdDev("Pastry: lookups using closerNode() with result from "
01252 "neighborhood set", closerNodeLookupsFromNeighborhood);
01253 globalStatistics->addStdDev("Pastry: LEAFSET Requests sent/s", leafsetReqSent / time);
01254 globalStatistics->addStdDev("Pastry: bytes of LEAFSET Requests sent/s", leafsetReqBytesSent / time);
01255 globalStatistics->addStdDev("Pastry: LEAFSET Requests received/s", leafsetReqReceived / time);
01256 globalStatistics->addStdDev("Pastry: bytes of LEAFSET Requests received/s",
01257 leafsetReqBytesReceived / time);
01258 globalStatistics->addStdDev("Pastry: LEAFSET Messages sent/s", leafsetSent / time);
01259 globalStatistics->addStdDev("Pastry: bytes of LEAFSET Messages sent/s", leafsetBytesSent / time);
01260 globalStatistics->addStdDev("Pastry: LEAFSET Messages received/s", leafsetReceived / time);
01261 globalStatistics->addStdDev("Pastry: bytes of LEAFSET Messages received/s",
01262 leafsetBytesReceived / time);
01263 globalStatistics->addStdDev("Pastry: ROUTING TABLE Requests sent/s", routingTableReqSent / time);
01264 globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Requests sent/s", routingTableReqBytesSent / time);
01265 globalStatistics->addStdDev("Pastry: ROUTING TABLE Requests received/s", routingTableReqReceived / time);
01266 globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Requests received/s",
01267 routingTableReqBytesReceived / time);
01268 globalStatistics->addStdDev("Pastry: ROUTING TABLE Messages sent/s", routingTableSent / time);
01269 globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Messages sent/s", routingTableBytesSent / time);
01270 globalStatistics->addStdDev("Pastry: ROUTING TABLE Messages received/s", routingTableReceived / time);
01271 globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Messages received/s",
01272 routingTableBytesReceived / time);
01273
01274 }
01275
01276 int BasePastry::getMaxNumSiblings()
01277 {
01278 return (int)floor(numberOfLeaves / 2.0);
01279 }
01280
01281 int BasePastry::getMaxNumRedundantNodes()
01282 {
01283 return (int)floor(numberOfLeaves);
01284 }
01285
01286 NodeVector* BasePastry::findNode(const OverlayKey& key,
01287 int numRedundantNodes,
01288 int numSiblings,
01289 BaseOverlayMessage* msg)
01290 {
01291 if ((numRedundantNodes > getMaxNumRedundantNodes()) ||
01292 (numSiblings > getMaxNumSiblings())) {
01293
01294 opp_error("(Pastry::findNode()) numRedundantNodes or numSiblings "
01295 "too big!");
01296 }
01297 RECORD_STATS(totalLookups++);
01298
01299 NodeVector* nextHops = new NodeVector(numRedundantNodes);
01300
01301 const NodeHandle* next;
01302 PastryFindNodeExtData* findNodeExt = NULL;
01303 if (msg && msg->hasObject("findNodeExt")) {
01304 findNodeExt =
01305 check_and_cast<PastryFindNodeExtData*>(msg->
01306 getObject("findNodeExt"));
01307 }
01308
01309 if (state != READY) {
01310 return nextHops;
01311 } else if (key.isUnspecified() || leafSet->isClosestNode(key)) {
01312 RECORD_STATS(responsibleLookups++);
01313 nextHops->add(thisNode);
01314 } else {
01315
01316 if (findNodeExt) {
01317 const TransportAddress& stateRecipient =
01318 findNodeExt->getSendStateTo();
01319 if (!stateRecipient.isUnspecified()) {
01320 RECORD_STATS(joinSeen++);
01321 sendStateTables(stateRecipient, PASTRY_STATE_JOIN,
01322 findNodeExt->getJoinHopCount(), false);
01323 }
01324 }
01325
01326 next = &(leafSet->getDestinationNode(key));
01327
01328 if (next->isUnspecified()) {
01329 next = &(routingTable->lookupNextHop(key));
01330 if (!next->isUnspecified()) {
01331 RECORD_STATS(routingTableLookups++);
01332 }
01333 } else {
01334 RECORD_STATS(responsibleLookups++);
01335 }
01336
01337 if (next->isUnspecified()) {
01338 RECORD_STATS(closerNodeLookups++);
01339
01340 if (optimizeLookup) {
01341 const NodeHandle* tmp;
01342 next = &(routingTable->findCloserNode(key, true));
01343 tmp = &(neighborhoodSet->findCloserNode(key, true));
01344
01345 if ((! tmp->isUnspecified()) &&
01346 (leafSet->isCloser(*tmp, key, *next))) {
01347 RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01348 next = tmp;
01349 }
01350
01351 tmp = &(leafSet->findCloserNode(key, true));
01352 if ((! tmp->isUnspecified()) &&
01353 (leafSet->isCloser(*tmp, key, *next))) {
01354 RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01355 next = tmp;
01356 }
01357 } else {
01358 next = &(routingTable->findCloserNode(key));
01359
01360 if (next->isUnspecified()) {
01361 RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01362 next = &(neighborhoodSet->findCloserNode(key));
01363 }
01364
01365 if (next->isUnspecified()) {
01366 RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01367 next = &(leafSet->findCloserNode(key));
01368 }
01369 }
01370 }
01371
01372 if (!next->isUnspecified()) {
01373 if (findNodeExt) {
01374 findNodeExt->setJoinHopCount(findNodeExt->getJoinHopCount() + 1);
01375 }
01376 nextHops->add(*next);
01377 }
01378 }
01379
01380 bool err;
01381
01382
01383 if ((numSiblings >= 0) && isSiblingFor(thisNode, key, numSiblings, &err)) {
01384 if (err == false) {
01385 delete nextHops;
01386 return leafSet->createSiblingVector(key, numSiblings);
01387 }
01388 }
01389
01390 if ( (numRedundantNodes > 1)) {
01391
01392
01393
01394
01395
01396 KeyDistanceComparator<KeyRingMetric> comp(key);
01397 NodeVector* additionalHops = new NodeVector( numRedundantNodes, &comp );
01398
01399 routingTable->findCloserNodes(key, additionalHops);
01400 leafSet->findCloserNodes(key, additionalHops);
01401 neighborhoodSet->findCloserNodes(key, additionalHops);
01402
01403 if (useRegularNextHop && (nextHops->size() > 0) &&
01404 (*additionalHops)[0] != (*nextHops)[0]) {
01405 for (uint32_t i = 0; i < additionalHops->size(); i++) {
01406 if ((*additionalHops)[i] != (*nextHops)[0])
01407 nextHops->push_back((*additionalHops)[i]);
01408 }
01409 delete additionalHops;
01410 } else {
01411 delete nextHops;
01412 return additionalHops;
01413 }
01414 }
01415 return nextHops;
01416 }
01417 AbstractLookup* BasePastry::createLookup(RoutingType routingType,
01418 const BaseOverlayMessage* msg,
01419 const cObject* dummy,
01420 bool appLookup)
01421 {
01422 assert(dummy == NULL);
01423 PastryFindNodeExtData* findNodeExt =
01424 new PastryFindNodeExtData("findNodeExt");
01425
01426 if (msg) {
01427 const PastryMessage* pmsg =
01428 dynamic_cast<const PastryMessage*>(msg->getEncapsulatedMsg());
01429 if ((pmsg) && (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN)) {
01430 const PastryJoinMessage* jmsg =
01431 check_and_cast<const PastryJoinMessage*>(pmsg);
01432 findNodeExt->setSendStateTo(jmsg->getSendStateTo());
01433 findNodeExt->setJoinHopCount(1);
01434 }
01435 }
01436 findNodeExt->setBitLength(PASTRYFINDNODEEXTDATA_L);
01437
01438 AbstractLookup* newLookup = BaseOverlay::createLookup(routingType,
01439 msg, findNodeExt,
01440 appLookup);
01441
01442 delete findNodeExt;
01443 return newLookup;
01444 }
01445
01446 bool stateMsgIsSmaller(const PastryStateMsgHandle& hnd1,
01447 const PastryStateMsgHandle& hnd2)
01448 {
01449 return (hnd1.msg->getJoinHopCount() < hnd2.msg->getJoinHopCount());
01450 }
01451
01452 std::ostream& operator<<(std::ostream& os, const PastryStateMsgProximity pr)
01453 {
01454 os << "PastryStateMsgProximity {" << endl;
01455 os << " pr_rt {" << endl;
01456 for (std::vector<simtime_t>::const_iterator i = pr.pr_rt.begin();
01457 i != pr.pr_rt.end(); ++i) {
01458 os << " " << *i << endl;
01459 }
01460 os << " }" << endl;
01461 os << " pr_ls {" << endl;
01462 for (std::vector<simtime_t>::const_iterator i = pr.pr_ls.begin();
01463 i != pr.pr_ls.end(); ++i) {
01464 os << " " << *i << endl;
01465 }
01466 os << " }" << endl;
01467 os << " pr_ns {" << endl;
01468 for (std::vector<simtime_t>::const_iterator i = pr.pr_ns.begin();
01469 i != pr.pr_ns.end(); ++i) {
01470 os << " " << *i << endl;
01471 }
01472 os << " }" << endl;
01473 os << "}" << endl;
01474 return os;
01475 }