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