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
BaseOverlayoverlay
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 286 of file IterativeLookup.h.


Constructor & Destructor Documentation

IterativePathLookup::IterativePathLookup ( IterativeLookup lookup  )  [protected]

Definition at line 719 of file IterativeLookup.cc.

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         // need to add some extra space for backup nodes, if we have to
00731         // remove failed nodes from the nextHops vector
00732         this->nextHops = LookupVector(2*(lookup->config.redundantNodes),
00733                                       lookup);
00734     } else {
00735         this->nextHops = LookupVector((lookup->config.redundantNodes),
00736                                       lookup);
00737     }
00738 }

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

Definition at line 740 of file IterativeLookup.cc.

00741 {}


Member Function Documentation

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

Definition at line 743 of file IterativeLookup.cc.

Referenced by IterativeLookup::handleRpcResponse().

00744 {
00745     if (finished) {
00746         return false;
00747     }
00748 
00749     // shall we use all responses, or only
00750     // the first one (rpcId == step)?
00751     if (lookup->config.useAllParallelResponses
00752         && lookup->config.merge) {
00753 
00754         return true;
00755     }
00756 
00757     return (rpcId == step);
00758 }

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

Adds a NodeHandle to next hops.

Definition at line 1128 of file IterativeLookup.cc.

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

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 }

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

Definition at line 981 of file IterativeLookup.cc.

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         // FIXME: This is needed for a node to be asked again when detecting
01008         // a failed node. It could pose problems when parallel lookups and
01009         // failed node recovery are both needed at the same time!
01010         lookup->setVisited(src, false);
01011 
01012         nextHops.add(LookupEntry(src, *oldSrc, false));
01013     }
01014 
01015     oldNextHops.erase(oldPos);
01016 
01017     sendNewRpcAfterTimeout(findNodeExt);
01018 }

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

Definition at line 760 of file IterativeLookup.cc.

Referenced by IterativeLookup::handleRpcResponse().

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     // don't count local hops
00780     if (lookup->overlay->getThisNode() != source) {
00781         hops++;
00782     }
00783 
00784     lookup->setVisited(source);
00785 
00786 //  if (source.getKey() == lookup->key) {
00787 //      cout << "received response from destination for key " << lookup->key
00788 //           << " with isSibling = " << msg->getSiblings() << endl;
00789 //  }
00790 
00791     step++;
00792 
00793     // decrease pending rpcs
00794     pendingRpcs--;
00795 
00796     if (msg->getClosestNodesArraySize() != 0) {
00797         // mode: merge or replace
00798         if (!lookup->config.merge) {
00799             nextHops.clear();
00800         }
00801     } else {
00802         //cout << "findNode() returned 0 nodes!" << endl;
00803     }
00804 
00805     int numNewRpcs = 0;
00806 
00807     // add new next hops
00808     for (uint32_t i=0; i < msg->getClosestNodesArraySize(); i++) {
00809         const NodeHandle& handle = msg->getClosestNodes(i);
00810 
00811         // add NodeHandle to next hops and siblings
00812         int pos = add(handle, source);
00813 
00814         // only send new rpcs if we've learned about new nodes
00815         if ((pos >= 0) && (pos < lookup->config.redundantNodes)) {
00816             numNewRpcs++;
00817         }
00818 
00819         // check if node was found
00820         if ((lookup->numSiblings == 0) && (handle.getKey() == lookup->key)) {
00821 
00822             lookup->addSibling(handle);
00823 
00824             // TODO: how do we resume, if the potential sibling doesn't authenticate?
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                 //cout << "adding sibling " << handle << endl;
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     // check if sibling lookup is finished
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     // extract find node extension object
00865     cPacket* findNodeExt = NULL;
00866     if (msg->hasObject("findNodeExt")) {
00867         findNodeExt = (cPacket*)msg->removeObject("findNodeExt");
00868     }
00869 
00870     // If config.newRpcOnEveryResponse is true, send a new RPC
00871     // even if there was no lookup progress
00872     if ((numNewRpcs == 0) && lookup->config.newRpcOnEveryResponse) {
00873         numNewRpcs = 1;
00874     }
00875 
00876     // send next rpcs
00877     sendRpc(min(numNewRpcs, lookup->config.parallelRpcs), findNodeExt);
00878 
00879     delete findNodeExt;
00880 }

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

Definition at line 894 of file IterativeLookup.cc.

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

00896 {
00897     if (finished)
00898         return;
00899 
00900     EV << "[IterativePathLookup::handleTimeout()]\n"
00901        << "    Timeout of RPC " << rpcId
00902        << endl;
00903 
00904     //std::cout << lookup->overlay->getThisNode() << ": Path timeout for node"
00905     //          << dest << endl;
00906 
00907     // For exhaustive-iterative remove dead nodes from nextHops vector
00908     // (which is also our results vector)
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     // decrease pending rpcs
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             // TODO: handleFailedNode should always be called for local
00946             // nodes, independent of config.failedNodeRpcs
00947             // Attention: currently this method is also called,
00948             // if a node responded and the path doesn't accept a message
00949             FindNodeCall* findNodeCall = dynamic_cast<FindNodeCall*>(msg);
00950             // answer was from local findNode()
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 }

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

Definition at line 882 of file IterativeLookup.cc.

Referenced by handleFailedNodeResponse(), and handleTimeout().

00883 {
00884     // two alternatives to react on a timeout
00885     if (lookup->config.newRpcOnEveryTimeout) {
00886         // always send one new RPC for every timeout
00887         sendRpc(1, findNodeExt);
00888     } else if (pendingRpcs == 0) {
00889         // wait until all RPCs have timed out and then send alpha new RPCs
00890         sendRpc(lookup->config.parallelRpcs, findNodeExt);
00891     }
00892 }

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

Definition at line 1020 of file IterativeLookup.cc.

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

01021 {
01022     // path finished? yes -> quit
01023     if (finished)
01024         return;
01025 
01026     // check for maximum hop count
01027     if (lookup->hopCountMax && (hops >= lookup->hopCountMax)) {
01028         EV << "[IterativePathLookup::sendRpc()]\n"
01029            << "    Max hop count exceeded - lookup failed!"
01030            << endl;
01031         //cout << "[IterativePathLookup::sendRpc()]\n"
01032         //     << "    Max hop count exceeded - lookup failed!"
01033         //     << endl;
01034 
01035         finished = true;
01036         success = false;
01037 
01038         return;
01039     }
01040 
01041     // if strictParallelRpcs is true, limit concurrent in-flight requests
01042     // to config.parallelRpcs
01043     if (lookup->config.strictParallelRpcs) {
01044         num = min(num, lookup->config.parallelRpcs - pendingRpcs);
01045     }
01046 
01047     // try all remaining nodes
01048     if ((num == 0) && (pendingRpcs == 0)
01049             && !lookup->config.finishOnFirstUnchanged) {
01050         num = lookup->config.parallelRpcs;
01051         //cout << "trying all remaining nodes ("
01052         //     << lookup->numSiblings << ")" << endl;
01053     }
01054 
01055     // send rpc messages
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         // ignore nodes to which we've already sent an RPC
01063         if (it->alreadyUsed || lookup->getDead(it->handle)) continue;
01064 
01065         // check if node has already been visited? no ->
01066         // TODO: doesn't work with Broose
01067         if ((!lookup->config.visitOnlyOnce) || (!lookup->getVisited(it->handle))) {
01068             // send rpc to node increase pending rpcs
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             //cout << "Sending RPC to " << it->handle
01076             //     << " ( " << num << " more )"
01077             //     << " thisNode = " << lookup->overlay->getThisNode().getKey() << endl;
01078 
01079             // mark node as already used
01080             it->alreadyUsed = true;
01081         } else {
01082             //EV << "[IterativePathLookup::sendRpc()]\n"
01083             //   << "    Last next hop ("
01084             //   << it->handle
01085             //   << ") already visited."
01086             //   << endl;
01087 
01088 //            std::cout << "visited:" << std::endl;
01089 //            for (TransportAddress::Set::iterator it = lookup->visited.begin();
01090 //            it != lookup->visited.end(); it++)
01091 //                std::cout << *it << std::endl;
01092 //
01093 //            std::cout << "nextHops:" << std::endl;
01094 //            for (NodePairVector::iterator it = nextHops.begin();
01095 //                 it != nextHops.end(); it++)
01096 //                std::cout << it->first << std::endl;
01097         }
01098     }
01099 
01100     // no rpc sent, no pending rpcs?
01101     // -> failed for normal lookups
01102     // -> exhaustive lookups are always successful
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             //cout << "failed nextHops for key " << lookup->key << endl;
01116             //cout << nextHops << endl;
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     //cout << endl;
01126 }


Friends And Related Function Documentation

friend class IterativeLookup [friend]

Definition at line 288 of file IterativeLookup.h.


Member Data Documentation

int IterativePathLookup::hops [protected]

Definition at line 292 of file IterativeLookup.h.

Referenced by IterativePathLookup(), and sendRpc().

int IterativePathLookup::step [protected]

Definition at line 296 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 Wed May 26 16:21:17 2010 for OverSim by  doxygen 1.6.3