00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <iostream>
00025 #include <assert.h>
00026
00027 #include <UnderlayConfigurator.h>
00028 #include <LookupListener.h>
00029 #include <BaseOverlay.h>
00030 #include <GlobalStatistics.h>
00031
00032 #include "IterativeLookup.h"
00033
00034 using namespace std;
00035
00036
00037
00038 LookupListener::~LookupListener()
00039 {}
00040
00041
00042
00043 AbstractLookup::~AbstractLookup()
00044 {}
00045
00046 std::ostream& operator<<(std::ostream& os, const LookupEntry& n)
00047 {
00048 os << "handle: " << n.handle << " source: " << n.source
00049 << " alreadyUsed: " << n.alreadyUsed;
00050
00051 return os;
00052 };
00053
00054 std::ostream& operator<<(std::ostream& os, const LookupVector& n)
00055 {
00056 for (LookupVector::const_iterator i=n.begin(); i !=n.end(); i++) {
00057 os << *i;
00058 if (i+1 != n.end()) {
00059 os << endl;
00060 }
00061 }
00062
00063 return os;
00064 };
00065
00066
00067
00068
00069 IterativeLookup::IterativeLookup(BaseOverlay* overlay,
00070 RoutingType routingType,
00071 const IterativeLookupConfiguration& config,
00072 const cPacket* findNodeExt,
00073 bool appLookup) :
00074 overlay(overlay),
00075 routingType(routingType),
00076 config(config),
00077 firstCallExt(NULL),
00078 finished(false),
00079 success(false),
00080 running(false),
00081 appLookup(appLookup)
00082 {
00083 if (findNodeExt) firstCallExt = static_cast<cPacket*>(findNodeExt->dup());
00084
00085 if ((config.parallelPaths > 1) && (!config.merge)) {
00086 throw cRuntimeError("IterativeLookup::IterativeLookup(): "
00087 "config.merge must be enabled for "
00088 "using parallel paths!");
00089 }
00090
00091 if (config.verifySiblings && (!config.merge)) {
00092 throw cRuntimeError("IterativeLookup::IterativeLookup(): "
00093 "config.merge must be enabled for "
00094 "using secure lookups!");
00095 }
00096
00097
00098 if (config.majoritySiblings && (!config.merge)) {
00099 throw cRuntimeError("IterativeLookup::IterativeLookup(): "
00100 "config.merge must be enabled for "
00101 "using majority decision for sibling selection!");
00102 }
00103
00104 if (config.useAllParallelResponses && (!config.merge)) {
00105 throw cRuntimeError("IterativeLookup::IterativeLookup(): "
00106 "config.merge must be enabled if "
00107 "config.useAllParallelResponses is true!");
00108 }
00109 }
00110
00111 IterativeLookup::~IterativeLookup()
00112 {
00113 stop();
00114 delete firstCallExt;
00115 overlay->removeLookup(this);
00116
00117
00118 }
00119
00120 void IterativeLookup::abortLookup()
00121 {
00122 if (listener != NULL) {
00123 delete listener;
00124 listener = NULL;
00125 }
00126 delete this;
00127 }
00128
00129 void IterativeLookup::start()
00130 {
00131
00132
00133
00134 successfulPaths = 0;
00135 finishedPaths = 0;
00136 accumulatedHops = 0;
00137
00138
00139 finished = false;
00140 success = false;
00141 running = true;
00142
00143
00144 siblings = NodeVector(numSiblings == 0 ? 1 : numSiblings, this);
00145 visited.clear();
00146 dead.clear();
00147 pinged.clear();
00148
00149 startTime = simTime();
00150
00151
00152 FindNodeCall* call = createFindNodeCall(firstCallExt);
00153 NodeVector* nextHops = overlay->findNode(key, overlay->getMaxNumRedundantNodes(),
00154 (routingType == EXHAUSTIVE_ITERATIVE_ROUTING) ? -1 : numSiblings, call);
00155
00156 bool err;
00157
00158 setVisited(overlay->getThisNode());
00159
00160
00161 if (nextHops->size() == 0) {
00162
00163 finished = true;
00164 success = false;
00165 } else if ((numSiblings == 0)
00166 && overlay->isSiblingFor(overlay->getThisNode(),
00167 key, numSiblings,
00168 &err)) {
00169 if (overlay->getThisNode().getKey() == key) {
00170 addSibling(overlay->getThisNode(), true);
00171 success = true;
00172 } else {
00173 std::cout << "IterativeLookup: numSiblings==0 and no node with this id"
00174 << endl;
00175 success = false;
00176 }
00177 finished = true;
00178 }
00179
00180 else if (numSiblings != 0 && routingType != EXHAUSTIVE_ITERATIVE_ROUTING &&
00181 overlay->isSiblingFor(overlay->getThisNode(), key,
00182 numSiblings, &err)) {
00183
00184 for (uint32_t i=0; i<nextHops->size(); i++) {
00185 addSibling(nextHops->at(i), true);
00186 }
00187
00188 success = finished = true;
00189 }
00190
00191
00192 if (finished) {
00193
00194 delete nextHops;
00195 delete call;
00196 delete this;
00197 return;
00198 }
00199
00200
00201 cPacket* findNodeExt = NULL;
00202 if (call->hasObject("findNodeExt"))
00203 findNodeExt = (cPacket*)call->removeObject("findNodeExt");
00204 delete call;
00205
00206
00207 if ((uint32_t)config.parallelPaths > nextHops->size()) {
00208 config.parallelPaths = nextHops->size();
00209 }
00210
00211
00212 for (int i = 0; i < config.parallelPaths; i++) {
00213
00214
00215 IterativePathLookup* pathLookup = new IterativePathLookup(this);
00216 paths.push_back(pathLookup);
00217
00218
00219 for (uint32_t k=0; (k * config.parallelPaths + i) < nextHops->size(); k++) {
00220 pathLookup->add(nextHops->at(k * config.parallelPaths + i));
00221 }
00222
00223
00224 pathLookup->sendRpc(config.parallelRpcs, findNodeExt);
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 delete nextHops;
00235 delete findNodeExt;
00236
00237 checkStop();
00238 }
00239
00240 void IterativeLookup::stop()
00241 {
00242
00243 if (!running)
00244 return;
00245
00246 for (uint32_t i=0; i<paths.size(); i++) {
00247 success |= paths[i]->success;
00248 }
00249
00250
00251 for (RpcInfoMap::iterator i = rpcs.begin(); i != rpcs.end(); i++) {
00252
00253 overlay->cancelRpcMessage(i->second.nonce);
00254 }
00255 rpcs.clear();
00256
00257
00258 for (PendingPings::iterator i = pendingPings.begin(); i != pendingPings.end(); i++) {
00259 overlay->cancelRpcMessage(i->second);
00260 }
00261 pendingPings.clear();
00262
00263
00264 for (uint32_t i=0; i<paths.size(); i++) {
00265 delete paths[i];
00266 }
00267 paths.clear();
00268
00269
00270 running = false;
00271 finished = true;
00272
00273 #if 0
00274 EV << "[IterativeLookup::stop() @ " << overlay->getThisNode().getAddress()
00275 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00276 << " Lookup " << (isValid() ? "succeeded\n" : "failed\n")
00277 << " (" << successfulPaths << " successful paths)\n"
00278 << " (" << finishedPaths << " finished paths)"
00279 << endl;
00280 #endif
00281
00282
00283 if (listener != NULL) {
00284 listener->lookupFinished(this);
00285 listener = NULL;
00286 }
00287 }
00288
00289 inline void IterativeLookup::checkStop()
00290 {
00291 bool finishLookup = false;
00292
00293 if (config.majoritySiblings && (numSiblings > 0) &&
00294 finishedPaths == (uint32_t)config.parallelPaths) {
00295 if (majoritySiblings.size() <= (uint)numSiblings) {
00296
00297 MajoritySiblings::iterator it;
00298 for (it = majoritySiblings.begin(); it != majoritySiblings.end(); it++) {
00299 siblings.add(*it);
00300 }
00301 success = true;
00302 finishLookup = true;
00303 }
00304 }
00305
00306
00307 if (((successfulPaths >= 1) && (numSiblings == 0) && (siblings.size() >= 1)) ||
00308 ((finishedPaths == (uint32_t)config.parallelPaths) &&
00309 (numSiblings > 0) && (pendingPings.size() == 0))) {
00310
00311 for (uint32_t i=0; i<paths.size(); i++) {
00312 success |= paths[i]->success;
00313 }
00314 finishLookup = true;
00315
00316 } else if ((rpcs.size() == 0) && (pendingPings.size() == 0)) {
00317 finishLookup = true;
00318 }
00319
00320 if (finishLookup == true) {
00321
00322
00323 if (successfulPaths >= 1) {
00324 success = true;
00325 }
00326
00327 if (success == false) {
00328
00329 }
00330
00331 if (success == false && retries > 0) {
00332
00333 retries--;
00334 LookupListener* oldListener = listener;
00335 listener = NULL;
00336 stop();
00337 listener = oldListener;
00338 start();
00339 } else {
00340 delete this;
00341 }
00342 }
00343 }
00344
00345
00346
00347
00348 IterativePathLookup* IterativeLookup::createPathLookup()
00349 {
00350 return new IterativePathLookup(this);
00351 }
00352
00353 FindNodeCall* IterativeLookup::createFindNodeCall(cPacket* findNodeExt)
00354 {
00355 FindNodeCall* call = new FindNodeCall("FindNodeCall");
00356 if (appLookup) {
00357 call->setStatType(APP_LOOKUP_STAT);
00358 } else {
00359 call->setStatType(MAINTENANCE_STAT);
00360 }
00361
00362 if (routingType == EXHAUSTIVE_ITERATIVE_ROUTING) {
00363 call->setExhaustiveIterative(true);
00364 } else {
00365 call->setExhaustiveIterative(false);
00366 }
00367
00368 call->setLookupKey(key);
00369 call->setNumRedundantNodes(config.redundantNodes);
00370 call->setNumSiblings(numSiblings);
00371 if (routingType == EXHAUSTIVE_ITERATIVE_ROUTING) {
00372 call->setExhaustiveIterative(true);
00373 } else {
00374 call->setExhaustiveIterative(false);
00375 }
00376 call->setBitLength(FINDNODECALL_L(call));
00377
00378
00379 if (findNodeExt) {
00380 call->addObject(static_cast<cObject*>(findNodeExt->dup()));
00381 call->addBitLength(findNodeExt->getBitLength());
00382 }
00383
00384 return call;
00385 }
00386
00387
00388
00389
00390
00391 int IterativeLookup::compare(const OverlayKey& lhs, const OverlayKey& rhs) const
00392 {
00393 return overlay->distance(lhs, key).compareTo(overlay->distance(rhs, key));
00394 }
00395
00396
00397
00398
00399
00400 bool IterativeLookup::addSibling(const NodeHandle& handle, bool assured)
00401 {
00402 bool result = false;
00403
00404 EV << "[IterativeLookup::addSibling() @ " << overlay->getThisNode().getAddress()
00405 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00406 << " Adding potential sibling " << handle
00407 << endl;
00408
00409 majoritySiblings.insert(handle);
00410
00411 if (config.verifySiblings && !assured && !getVisited(handle)) {
00412
00413 if (siblings.isAddable(handle) && !getPinged(handle)) {
00414 int id = intuniform(1, 2147483647);
00415 int nonce = overlay->pingNode(handle, -1, 0, NULL, NULL, this, id);
00416 pendingPings.insert(make_pair(id, nonce));
00417 setPinged(handle);
00418 }
00419
00420 return false;
00421 }
00422
00423 if (numSiblings == 0) {
00424 if (handle.getKey() == key) {
00425 siblings.clear();
00426 siblings.push_back( handle );
00427 result = true;
00428 }
00429 } else {
00430 if (config.parallelPaths == 1 && !config.verifySiblings) {
00431 result = true;
00432 if (!siblings.isFull()) {
00433 siblings.push_back(handle);
00434 }
00435 } else {
00436 if (siblings.add(handle) >= 0) {
00437 result = true;
00438 }
00439 }
00440 }
00441
00442 return result;
00443 }
00444
00445 void IterativeLookup::setVisited(const TransportAddress& addr, bool visitedFlag)
00446 {
00447 if (visitedFlag)
00448 this->visited.insert(addr);
00449 else
00450 this->visited.erase(addr);
00451 }
00452
00453 bool IterativeLookup::getVisited(const TransportAddress& addr)
00454 {
00455 return (visited.count(addr) != 0);
00456 }
00457
00458 void IterativeLookup::setDead(const TransportAddress& addr)
00459 {
00460 dead.insert(addr);
00461 }
00462
00463 bool IterativeLookup::getDead(const TransportAddress& addr)
00464 {
00465 return (dead.count(addr) != 0);
00466 }
00467
00468 void IterativeLookup::setPinged(const TransportAddress& addr)
00469 {
00470 pinged.insert(addr);
00471 }
00472
00473 bool IterativeLookup::getPinged(const TransportAddress& addr)
00474 {
00475 return (pinged.count(addr) != 0);
00476 }
00477
00478
00479
00480
00481
00482 void IterativeLookup::handleRpcResponse(BaseResponseMessage* msg,
00483 cPolymorphic* context,
00484 int rpcId, simtime_t rtt)
00485 {
00486
00487 if (finished || !running)
00488 return;
00489
00490
00491 const TransportAddress& src = msg->getSrcNode();
00492 FindNodeResponse* findNodeResponse = dynamic_cast<FindNodeResponse*>(msg);
00493 PingResponse* pingResponse = dynamic_cast<PingResponse*>(msg);
00494 FailedNodeResponse* failedNodeResponse =
00495 dynamic_cast<FailedNodeResponse*>(msg);
00496
00497 if (pingResponse != NULL) {
00498 pendingPings.erase(rpcId);
00499
00500 addSibling(pingResponse->getSrcNode(), true);
00501 }
00502
00503
00504 if (findNodeResponse != NULL) {
00505
00506
00507
00508 if (rpcs.count(src) == 0)
00509 return;
00510
00511
00512 RpcInfoVector infos = rpcs[src];
00513 rpcs.erase(src);
00514
00515
00516 bool rpcHandled = false;
00517
00518 for (uint32_t i=0; i<infos.size(); i++) {
00519
00520 const RpcInfo& info = infos[i];
00521
00522
00523 if (info.path->finished)
00524 continue;
00525
00526
00527
00528 if (!rpcHandled &&
00529 (info.path->accepts(info.vrpcId) ||
00530 ((routingType == EXHAUSTIVE_ITERATIVE_ROUTING)
00531 || (findNodeResponse->getSiblings() &&
00532 config.acceptLateSiblings)))) {
00533 info.path->handleResponse(findNodeResponse);
00534 rpcHandled = true;
00535 } else {
00536 EV << "[IterativeLookup::handleRpcResponse()]\n"
00537 << " Path does not accept message with id " << info.vrpcId
00538 << endl;
00539
00540 info.path->handleTimeout(NULL, findNodeResponse->getSrcNode(),
00541 info.vrpcId);
00542 }
00543
00544
00545 if (info.path->finished) {
00546 finishedPaths++;
00547
00548
00549 accumulatedHops += info.path->hops;
00550
00551 if (info.path->success)
00552 successfulPaths++;
00553 }
00554
00555 }
00556 }
00557
00558
00559
00560 if (failedNodeResponse != NULL) {
00561 cPacket* findNodeExt = NULL;
00562 if (failedNodeResponse->hasObject("findNodeExt")) {
00563 findNodeExt =
00564 (cPacket*)failedNodeResponse->removeObject("findNodeExt");
00565 }
00566
00567 for (std::vector<IterativePathLookup*>::iterator i = paths.begin();
00568 i != paths.end(); i++) {
00569
00570 (*i)->handleFailedNodeResponse(failedNodeResponse->getSrcNode(),
00571 findNodeExt,
00572 failedNodeResponse->getTryAgain());
00573 }
00574 }
00575
00576 checkStop();
00577 }
00578
00579
00580 void IterativeLookup::handleRpcTimeout(BaseCallMessage* msg,
00581 const TransportAddress& dest,
00582 cPolymorphic* context, int rpcId,
00583 const OverlayKey& destKey)
00584 {
00585
00586 if (finished || !running)
00587 return;
00588
00589 if (dynamic_cast<PingCall*>(msg) != NULL) {
00590 pendingPings.erase(rpcId);
00591 checkStop();
00592 return;
00593 }
00594
00595
00596 if (rpcs.count(dest)==0) {
00597 cout << "IterativeLookup::handleRpcTimeout(): RPC Timeout, but node"
00598 << " is not in rpcs structure!" << endl;
00599 return;
00600 }
00601
00602
00603 setDead(dest);
00604
00605 RpcInfoVector infos = rpcs[dest];
00606 rpcs.erase(dest);
00607
00608
00609 for (uint32_t i=0; i < infos.size(); i++) {
00610
00611 const RpcInfo& info = infos[i];
00612
00613
00614 if (info.path->finished)
00615 continue;
00616
00617
00618 info.path->handleTimeout(msg, dest, info.vrpcId);
00619
00620
00621 if (info.path->finished) {
00622 finishedPaths++;
00623
00624
00625 accumulatedHops += info.path->hops;
00626
00627 if (info.path->success)
00628 successfulPaths++;
00629 }
00630 }
00631 checkStop();
00632 }
00633
00634 void IterativeLookup::sendRpc(const NodeHandle& handle, FindNodeCall* call,
00635 IterativePathLookup* listener, int rpcId)
00636 {
00637
00638 if (finished || !running) {
00639 delete call;
00640 return;
00641 }
00642
00643
00644 RpcInfo info;
00645 info.path = listener;
00646 info.vrpcId = rpcId;
00647
00648
00649 if (rpcs.count(handle) == 0) {
00650 RpcInfoVector newVector;
00651
00652 overlay->countFindNodeCall(call);
00653 newVector.nonce = overlay->sendUdpRpcCall(handle, call, NULL,
00654 -1, 0, -1, this);
00655
00656
00657 rpcs[handle] = newVector;
00658 } else {
00659 EV << "[IterativeLookup::sendRpc()]\n"
00660 << " RPC already sent...not sent again"
00661 << endl;
00662 delete call;
00663 }
00664
00665
00666 rpcs[handle].push_back(info);
00667 }
00668
00669
00670
00671
00672
00673 void IterativeLookup::lookup(const OverlayKey& key, int numSiblings,
00674 int hopCountMax, int retries, LookupListener* listener)
00675 {
00676 EV << "[IterativeLookup::lookup() @ " << overlay->overlay->getThisNode().getAddress()
00677 << " (" << overlay->overlay->getThisNode().getKey().toString(16) << ")]\n"
00678 << " Lookup of key " << key
00679 << endl;
00680
00681
00682 if (finished || running)
00683 return;
00684
00685
00686 this->key = key;
00687 this->numSiblings = numSiblings;
00688 this->hopCountMax = hopCountMax;
00689 this->listener = listener;
00690 this->retries = retries;
00691
00692 if ((routingType == EXHAUSTIVE_ITERATIVE_ROUTING)
00693 && (numSiblings > config.redundantNodes)) {
00694 throw cRuntimeError("IterativeLookup::lookup(): "
00695 "With EXHAUSTIVE_ITERATIVE_ROUTING numRedundantNodes "
00696 "must be >= numSiblings!");
00697 }
00698
00699
00700 start();
00701 }
00702
00703 const NodeVector& IterativeLookup::getResult() const
00704 {
00705
00706 return siblings;
00707 }
00708
00709 bool IterativeLookup::isValid() const
00710 {
00711 return success && finished;
00712 }
00713
00714 uint32_t IterativeLookup::getAccumulatedHops() const
00715 {
00716 return accumulatedHops;
00717 }
00718
00719 IterativePathLookup::IterativePathLookup(IterativeLookup* lookup)
00720 {
00721 this->lookup = lookup;
00722 this->hops = 0;
00723 this->step = 0;
00724 this->pendingRpcs = 0;
00725 this->finished = false;
00726 this->success = false;
00727 this->overlay = lookup->overlay;
00728
00729 if (lookup->routingType == EXHAUSTIVE_ITERATIVE_ROUTING) {
00730
00731
00732 this->nextHops = LookupVector(2*(lookup->config.redundantNodes),
00733 lookup);
00734 } else {
00735 this->nextHops = LookupVector((lookup->config.redundantNodes),
00736 lookup);
00737 }
00738 }
00739
00740 IterativePathLookup::~IterativePathLookup()
00741 {}
00742
00743 bool IterativePathLookup::accepts(int rpcId)
00744 {
00745 if (finished) {
00746 return false;
00747 }
00748
00749
00750
00751 if (lookup->config.useAllParallelResponses
00752 && lookup->config.merge) {
00753
00754 return true;
00755 }
00756
00757 return (rpcId == step);
00758 }
00759
00760 void IterativePathLookup::handleResponse(FindNodeResponse* msg)
00761 {
00762 if (finished)
00763 return;
00764
00765 if (simTime() > (lookup->startTime + LOOKUP_TIMEOUT)) {
00766 EV << "[IterativePathLookup::handleResponse()]\n"
00767 << " Iterative lookup path timed out!"
00768 << endl;
00769 finished = true;
00770 success = false;
00771 return;
00772 }
00773
00774 const NodeHandle& source = msg->getSrcNode();
00775 std::map<TransportAddress, NodeHandle>::iterator oldPos;
00776 oldPos = oldNextHops.find(source);
00777 if (oldPos != oldNextHops.end()) oldNextHops.erase(oldPos);
00778
00779
00780 if (lookup->overlay->getThisNode() != source) {
00781 hops++;
00782 }
00783
00784 lookup->setVisited(source);
00785
00786
00787
00788
00789
00790
00791 step++;
00792
00793
00794 pendingRpcs--;
00795
00796 if (msg->getClosestNodesArraySize() != 0) {
00797
00798 if (!lookup->config.merge) {
00799 nextHops.clear();
00800 }
00801 } else {
00802
00803 }
00804
00805 int numNewRpcs = 0;
00806
00807
00808 for (uint32_t i=0; i < msg->getClosestNodesArraySize(); i++) {
00809 const NodeHandle& handle = msg->getClosestNodes(i);
00810
00811
00812 int pos = add(handle, source);
00813
00814
00815 if ((pos >= 0) && (pos < lookup->config.redundantNodes)) {
00816 numNewRpcs++;
00817 }
00818
00819
00820 if ((lookup->numSiblings == 0) && (handle.getKey() == lookup->key)) {
00821
00822 lookup->addSibling(handle);
00823
00824
00825 finished = true;
00826 success = true;
00827 return;
00828 } else {
00829 if (lookup->numSiblings != 0 &&
00830 (lookup->routingType != EXHAUSTIVE_ITERATIVE_ROUTING) &&
00831 msg->getSiblings()) {
00832
00833
00834 lookup->addSibling(handle);
00835 }
00836 }
00837 }
00838
00839 #if 0
00840 cout << "nextHops.size " << nextHops.size()
00841 << " find node response " << msg->getClosestNodesArraySize()
00842 << " config " << lookup->config.redundantNodes << endl;
00843
00844 cout << "looking for " << lookup->key << endl;
00845
00846 for (uint32_t i=0; i < msg->getClosestNodesArraySize(); i++) {
00847 cout << "find node " << msg->getClosestNodes(i) << endl;
00848 }
00849
00850 cout << "next Hops " << nextHops << endl;
00851 #endif
00852
00853
00854 if ((lookup->routingType != EXHAUSTIVE_ITERATIVE_ROUTING)
00855 && msg->getSiblings()
00856 && msg->getClosestNodesArraySize() != 0 &&
00857 lookup->numSiblings != 0) {
00858
00859 finished = true;
00860 success = true;
00861 return;
00862 }
00863
00864
00865 cPacket* findNodeExt = NULL;
00866 if (msg->hasObject("findNodeExt")) {
00867 findNodeExt = (cPacket*)msg->removeObject("findNodeExt");
00868 }
00869
00870
00871
00872 if ((numNewRpcs == 0) && lookup->config.newRpcOnEveryResponse) {
00873 numNewRpcs = 1;
00874 }
00875
00876
00877 sendRpc(min(numNewRpcs, lookup->config.parallelRpcs), findNodeExt);
00878
00879 delete findNodeExt;
00880 }
00881
00882 void IterativePathLookup::sendNewRpcAfterTimeout(cPacket* findNodeExt)
00883 {
00884
00885 if (lookup->config.newRpcOnEveryTimeout) {
00886
00887 sendRpc(1, findNodeExt);
00888 } else if (pendingRpcs == 0) {
00889
00890 sendRpc(lookup->config.parallelRpcs, findNodeExt);
00891 }
00892 }
00893
00894 void IterativePathLookup::handleTimeout(BaseCallMessage* msg,
00895 const TransportAddress& dest, int rpcId)
00896 {
00897 if (finished)
00898 return;
00899
00900 EV << "[IterativePathLookup::handleTimeout()]\n"
00901 << " Timeout of RPC " << rpcId
00902 << endl;
00903
00904
00905
00906
00907
00908
00909 if ((lookup->routingType == EXHAUSTIVE_ITERATIVE_ROUTING)
00910 && lookup->getDead(dest)) {
00911 LookupVector::iterator it = nextHops.findIterator(
00912 (dynamic_cast<const NodeHandle&>(dest)).getKey());
00913 if (it != nextHops.end()) {
00914 nextHops.erase(it);
00915 }
00916 }
00917
00918 std::map<TransportAddress, NodeHandle>::iterator oldPos;
00919 oldPos = oldNextHops.find(dest);
00920
00921
00922 pendingRpcs--;
00923
00924 cPacket* findNodeExt = NULL;
00925 if (msg && msg->hasObject("findNodeExt")) {
00926 findNodeExt = static_cast<cPacket*>(
00927 msg->removeObject("findNodeExt"));
00928 }
00929
00930 if (simTime() > (lookup->startTime + LOOKUP_TIMEOUT)) {
00931 EV << "[IterativePathLookup::handleTimeout()]\n"
00932 << " Iterative lookup path timed out!"
00933 << endl;
00934 delete findNodeExt;
00935 finished = true;
00936 success = false;
00937 return;
00938 }
00939
00940 if (oldPos == oldNextHops.end() || (!lookup->config.failedNodeRpcs)) {
00941 sendNewRpcAfterTimeout(findNodeExt);
00942 delete findNodeExt;
00943 } else {
00944 if (oldPos->second.isUnspecified()) {
00945
00946
00947
00948
00949 FindNodeCall* findNodeCall = dynamic_cast<FindNodeCall*>(msg);
00950
00951
00952 if (findNodeCall && lookup->overlay->handleFailedNode(dest)) {
00953 NodeVector* retry = lookup->overlay->findNode(
00954 findNodeCall->getLookupKey(), -1, lookup->numSiblings, msg);
00955
00956 for (NodeVector::iterator i = retry->begin(); i != retry->end(); i++) {
00957 nextHops.add(LookupEntry(*i, NodeHandle::UNSPECIFIED_NODE, false));
00958 }
00959
00960 delete retry;
00961 }
00962
00963 sendNewRpcAfterTimeout(findNodeExt);
00964 delete findNodeExt;
00965
00966 } else {
00967 FailedNodeCall* call = new FailedNodeCall("FailedNodeCall");
00968 call->setFailedNode(dest);
00969 call->setBitLength(FAILEDNODECALL_L(call));
00970 if (findNodeExt) {
00971 call->addObject(findNodeExt);
00972 call->addBitLength(findNodeExt->getBitLength());
00973 }
00974 lookup->overlay->countFailedNodeCall(call);
00975 lookup->overlay->sendUdpRpcCall(oldPos->second, call, NULL,
00976 -1, 0, -1, lookup);
00977 }
00978 }
00979 }
00980
00981 void IterativePathLookup::handleFailedNodeResponse(const NodeHandle& src,
00982 cPacket* findNodeExt, bool retry)
00983 {
00984 if (finished) {
00985 return;
00986 }
00987
00988 std::map<TransportAddress, NodeHandle>::iterator oldPos;
00989 for (oldPos = oldNextHops.begin(); oldPos != oldNextHops.end(); oldPos++) {
00990 if ((! oldPos->second.isUnspecified()) &&
00991 (oldPos->second == src)) break;
00992 }
00993
00994 if (oldPos == oldNextHops.end()) {
00995 return;
00996 }
00997
00998 std::map<TransportAddress, NodeHandle>::iterator oldSrcPos =
00999 oldNextHops.find(src);
01000 const NodeHandle* oldSrc = &NodeHandle::UNSPECIFIED_NODE;
01001
01002 if (oldSrcPos != oldNextHops.end()) {
01003 oldSrc = &(oldSrcPos->second);
01004 }
01005
01006 if (retry) {
01007
01008
01009
01010 lookup->setVisited(src, false);
01011
01012 nextHops.add(LookupEntry(src, *oldSrc, false));
01013 }
01014
01015 oldNextHops.erase(oldPos);
01016
01017 sendNewRpcAfterTimeout(findNodeExt);
01018 }
01019
01020 void IterativePathLookup::sendRpc(int num, cPacket* findNodeExt)
01021 {
01022
01023 if (finished)
01024 return;
01025
01026
01027 if (lookup->hopCountMax && (hops >= lookup->hopCountMax)) {
01028 EV << "[IterativePathLookup::sendRpc()]\n"
01029 << " Max hop count exceeded - lookup failed!"
01030 << endl;
01031
01032
01033
01034
01035 finished = true;
01036 success = false;
01037
01038 return;
01039 }
01040
01041
01042
01043 if (lookup->config.strictParallelRpcs) {
01044 num = min(num, lookup->config.parallelRpcs - pendingRpcs);
01045 }
01046
01047
01048 if ((num == 0) && (pendingRpcs == 0)
01049 && !lookup->config.finishOnFirstUnchanged) {
01050 num = lookup->config.parallelRpcs;
01051
01052
01053 }
01054
01055
01056 LookupVector::iterator it = nextHops.begin();
01057 int i = 0;
01058 for (LookupVector::iterator it = nextHops.begin();
01059 ((num > 0) && (i < lookup->config.redundantNodes)
01060 && (it != nextHops.end())); it++, i++) {
01061
01062
01063 if (it->alreadyUsed || lookup->getDead(it->handle)) continue;
01064
01065
01066
01067 if ((!lookup->config.visitOnlyOnce) || (!lookup->getVisited(it->handle))) {
01068
01069 pendingRpcs++;
01070 num--;
01071 FindNodeCall* call = lookup->createFindNodeCall(findNodeExt);
01072 lookup->sendRpc(it->handle, call, this, step);
01073 oldNextHops[it->handle] = it->source;
01074
01075
01076
01077
01078
01079
01080 it->alreadyUsed = true;
01081 } else {
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 }
01098 }
01099
01100
01101
01102
01103 if (pendingRpcs == 0) {
01104 if (lookup->routingType == EXHAUSTIVE_ITERATIVE_ROUTING) {
01105 int i = 0;
01106 for (LookupVector::iterator it = nextHops.begin();
01107 ((i < lookup->config.redundantNodes)
01108 && (it != nextHops.end())); it++, i++) {
01109 lookup->addSibling(it->handle);
01110 }
01111
01112 success = true;
01113 } else {
01114 success = false;
01115
01116
01117 EV << "[IterativePathLookup::sendRpc() @ " << overlay->getThisNode().getAddress()
01118 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
01119 << " Path failed (no further nodes to query) "
01120 << endl;
01121 }
01122
01123 finished = true;
01124 }
01125
01126 }
01127
01128 int IterativePathLookup::add(const NodeHandle& handle, const NodeHandle& source)
01129 {
01130 if (lookup->config.merge) {
01131 return nextHops.add(LookupEntry(handle, source, false));
01132 } else {
01133 nextHops.push_back(LookupEntry(handle, source, false));
01134 return (nextHops.size() - 1);
01135 }
01136 }
01137