IterativePathLookup Class Reference

This class implements a path lookup. More...

#include <IterativeLookup.h>

List of all members.

Protected Member Functions

bool accepts (int rpcId)
void handleResponse (FindNodeResponse *msg)
void handleTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcId)
void handleFailedNodeResponse (const NodeHandle &src, cPacket *findNodeExt, bool retry)
 IterativePathLookup (IterativeLookup *lookup)
virtual ~IterativePathLookup ()
int add (const NodeHandle &handle, const NodeHandle &source=NodeHandle::UNSPECIFIED_NODE)
 Adds a NodeHandle to next hops.

Protected Attributes

IterativeLookuplookup
int hops
int step
int pendingRpcs
bool finished
bool success
LookupVector nextHops
std::map< TransportAddress,
NodeHandle
oldNextHops

Private Member Functions

void sendRpc (int num, cPacket *FindNodeExt=NULL)
void sendNewRpcAfterTimeout (cPacket *findNodeExt)

Friends

class IterativeLookup


Detailed Description

This class implements a path lookup.

Author:
Sebastian Mies

Definition at line 263 of file IterativeLookup.h.


Constructor & Destructor Documentation

IterativePathLookup::IterativePathLookup ( IterativeLookup lookup  )  [protected]

Definition at line 636 of file IterativeLookup.cc.

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         // need to add some extra space for backup nodes, if we have to
00647         // remove failed nodes from the nextHops vector
00648         this->nextHops = LookupVector(2*(lookup->config.redundantNodes),
00649                                       lookup);
00650     } else {
00651         this->nextHops = LookupVector((lookup->config.redundantNodes),
00652                                       lookup);
00653     }
00654 }

IterativePathLookup::~IterativePathLookup (  )  [protected, virtual]

Definition at line 656 of file IterativeLookup.cc.

00657 {}


Member Function Documentation

bool IterativePathLookup::accepts ( int  rpcId  )  [protected]

Definition at line 659 of file IterativeLookup.cc.

Referenced by IterativeLookup::handleRpcResponse().

00660 {
00661     if (finished) {
00662         return false;
00663     }
00664 
00665     // shall we use all responses, or only
00666     // the first one (rpcId == step)?
00667     if (lookup->config.useAllParallelResponses
00668         && lookup->config.merge) {
00669 
00670         return true;
00671     }
00672 
00673     return (rpcId == step);
00674 }

int IterativePathLookup::add ( const NodeHandle handle,
const NodeHandle source = NodeHandle::UNSPECIFIED_NODE 
) [protected]

Adds a NodeHandle to next hops.

Definition at line 1021 of file IterativeLookup.cc.

Referenced by IterativeLookup::start().

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 }

void IterativePathLookup::handleFailedNodeResponse ( const NodeHandle src,
cPacket *  findNodeExt,
bool  retry 
) [protected]

Definition at line 878 of file IterativeLookup.cc.

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         // FIXME: This is needed for a node to be asked again when detecting
00905         // a failed node. It could pose problems when parallel lookups and
00906         // failed node recovery are both needed at the same time!
00907         lookup->setVisited(src, false);
00908 
00909         nextHops.add(LookupEntry(src, *oldSrc, false));
00910     }
00911 
00912     oldNextHops.erase(oldPos);
00913 
00914     sendNewRpcAfterTimeout(findNodeExt);
00915 }

void IterativePathLookup::handleResponse ( FindNodeResponse msg  )  [protected]

Definition at line 676 of file IterativeLookup.cc.

Referenced by IterativeLookup::handleRpcResponse().

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     // don't count local hops
00687     if (lookup->overlay->getThisNode() != source) {
00688         hops++;
00689     }
00690 
00691     lookup->setVisited(source);
00692 
00693 //  if (source.getKey() == lookup->key) {
00694 //      cout << "received response from destination for key " << lookup->key
00695 //           << " with isSibling = " << msg->getSiblings() << endl;
00696 //  }
00697 
00698     step++;
00699 
00700     // decrease pending rpcs
00701     pendingRpcs--;
00702 
00703     if (msg->getClosestNodesArraySize() != 0) {
00704         // mode: merge or replace
00705         if (!lookup->config.merge) {
00706             nextHops.clear();
00707         }
00708     } else {
00709         //cout << "findNode() returned 0 nodes!" << endl;
00710     }
00711 
00712     int numNewRpcs = 0;
00713 
00714     // add new next hops
00715     for (uint32_t i=0; i < msg->getClosestNodesArraySize(); i++) {
00716         const NodeHandle& handle = msg->getClosestNodes(i);
00717 
00718         // add NodeHandle to next hops and siblings
00719         int pos = add(handle, source);
00720 
00721         // only send new rpcs if we've learned about new nodes
00722         if ((pos >= 0) && (pos < lookup->config.redundantNodes)) {
00723             numNewRpcs++;
00724         }
00725 
00726         // check if node was found
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                 //cout << "adding sibling " << handle << endl;
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     // check if sibling lookup is finished
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     // extract find node extension object
00772     cPacket* findNodeExt = NULL;
00773     if (msg->hasObject("findNodeExt")) {
00774         findNodeExt = (cPacket*)msg->removeObject("findNodeExt");
00775     }
00776 
00777     // If config.newRpcOnEveryResponse is true, send a new RPC
00778     // even if there was no lookup progress
00779     if ((numNewRpcs == 0) && lookup->config.newRpcOnEveryResponse) {
00780         numNewRpcs = 1;
00781     }
00782 
00783     // send next rpcs
00784     sendRpc(min(numNewRpcs, lookup->config.parallelRpcs), findNodeExt);
00785 
00786     delete findNodeExt;
00787 }

void IterativePathLookup::handleTimeout ( BaseCallMessage msg,
const TransportAddress dest,
int  rpcId 
) [protected]

Definition at line 801 of file IterativeLookup.cc.

Referenced by IterativeLookup::handleRpcResponse(), and IterativeLookup::handleRpcTimeout().

00803 {
00804     if (finished)
00805         return;
00806 
00807     EV << "[IterativePathLookup::handleTimeout()]\n"
00808        << "    Timeout of RPC " << rpcId
00809        << endl;
00810 
00811     //std::cout << lookup->overlay->getThisNode() << ": Path timeout for node"
00812     //          << dest << endl;
00813 
00814     // For exhaustive-iterative remove dead nodes from nextHops vector
00815     // (which is also our results vector)
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     // decrease pending rpcs
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             // TODO: handleFailedNode should always be called for local
00843             // nodes, independant of config.failedNodeRpcs
00844             // Attention: currently this method is also called,
00845             // if a node responded and the path doesn't accept a message
00846             FindNodeCall* findNodeCall = dynamic_cast<FindNodeCall*>(msg);
00847             // answer was from local findNode()
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 }

void IterativePathLookup::sendNewRpcAfterTimeout ( cPacket *  findNodeExt  )  [private]

Definition at line 789 of file IterativeLookup.cc.

Referenced by handleFailedNodeResponse(), and handleTimeout().

00790 {
00791     // two alternatives to react on a timeout
00792     if (lookup->config.newRpcOnEveryTimeout) {
00793         // always send one new RPC for every timeout
00794         sendRpc(1, findNodeExt);
00795     } else if (pendingRpcs == 0) {
00796         // wait until all RPCs have timed out and then send alpha new RPCs
00797         sendRpc(lookup->config.parallelRpcs, findNodeExt);
00798     }
00799 }

void IterativePathLookup::sendRpc ( int  num,
cPacket *  FindNodeExt = NULL 
) [private]

Definition at line 917 of file IterativeLookup.cc.

Referenced by handleResponse(), sendNewRpcAfterTimeout(), and IterativeLookup::start().

00918 {
00919     // path finished? yes -> quit
00920     if (finished)
00921         return;
00922 
00923     // check for maximum hop count
00924     if (lookup->hopCountMax && (hops >= lookup->hopCountMax)) {
00925         EV << "[IterativePathLookup::sendRpc()]\n"
00926            << "    Max hop count exceeded - lookup failed!"
00927            << endl;
00928         //cout << "[IterativePathLookup::sendRpc()]\n"
00929         //     << "    Max hop count exceeded - lookup failed!"
00930         //     << endl;
00931 
00932         finished = true;
00933         success = false;
00934 
00935         return;
00936     }
00937 
00938     // if strictParallelRpcs is true, limit concurrent in-flight requests
00939     // to config.parallelRpcs
00940     if (lookup->config.strictParallelRpcs) {
00941         num = min(num, lookup->config.parallelRpcs - pendingRpcs);
00942     }
00943 
00944     // try all remaining nodes
00945     if ((num == 0) && (pendingRpcs == 0)
00946             && !lookup->config.finishOnFirstUnchanged) {
00947         num = lookup->config.parallelRpcs;
00948         //cout << "trying all remaining nodes ("
00949         //     << lookup->numSiblings << ")" << endl;
00950     }
00951 
00952     // send rpc messages
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         // ignore nodes to which we've already sent an RPC
00960         if (it->alreadyUsed || lookup->getDead(it->handle)) continue;
00961 
00962         // check if node has already been visited? no ->
00963         // TODO: doesn't work with Broose
00964         if ((!lookup->config.visitOnlyOnce) || (!lookup->getVisited(it->handle))) {
00965             // send rpc to node increase pending rpcs
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             //cout << "Sending RPC to " << it->handle
00973             //     << " ( " << num << " more )"
00974             //     << " thisNode = " << lookup->overlay->getThisNode().getKey() << endl;
00975 
00976             // mark node as already used
00977             it->alreadyUsed = true;
00978         } else {
00979             //EV << "[IterativePathLookup::sendRpc()]\n"
00980             //   << "    Last next hop ("
00981             //   << it->handle
00982             //   << ") already visited."
00983             //   << endl;
00984 
00985 //            std::cout << "visited:" << std::endl;
00986 //            for (TransportAddress::Set::iterator it = lookup->visited.begin();
00987 //            it != lookup->visited.end(); it++)
00988 //                std::cout << *it << std::endl;
00989 //
00990 //            std::cout << "nextHops:" << std::endl;
00991 //            for (NodePairVector::iterator it = nextHops.begin();
00992 //                 it != nextHops.end(); it++)
00993 //                std::cout << it->first << std::endl;
00994         }
00995     }
00996 
00997     // no rpc sent, no pending rpcs?
00998     // -> failed for normal lookups
00999     // -> exhaustive lookups are always successful
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             //cout << "failed nextHops for key " << lookup->key << endl;
01013             //cout << nextHops << endl;
01014         }
01015 
01016         finished = true;
01017     }
01018     //cout << endl;
01019 }


Friends And Related Function Documentation

friend class IterativeLookup [friend]

Definition at line 265 of file IterativeLookup.h.


Member Data Documentation

int IterativePathLookup::hops [protected]

int IterativePathLookup::step [protected]

Definition at line 272 of file IterativeLookup.h.

Referenced by accepts(), handleResponse(), IterativePathLookup(), and sendRpc().

bool IterativePathLookup::success [protected]


The documentation for this class was generated from the following files:

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