This class implements a path lookup. More...
#include <IterativeLookup.h>
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 | |
IterativeLookup * | lookup |
BaseOverlay * | overlay |
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 |
This class implements a path lookup.
Definition at line 286 of file IterativeLookup.h.
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.
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 }
friend class IterativeLookup [friend] |
Definition at line 288 of file IterativeLookup.h.
bool IterativePathLookup::finished [protected] |
Definition at line 298 of file IterativeLookup.h.
Referenced by accepts(), handleFailedNodeResponse(), handleResponse(), IterativeLookup::handleRpcResponse(), IterativeLookup::handleRpcTimeout(), handleTimeout(), IterativePathLookup(), and sendRpc().
int IterativePathLookup::hops [protected] |
Definition at line 295 of file IterativeLookup.h.
Referenced by handleResponse(), IterativeLookup::handleRpcResponse(), IterativeLookup::handleRpcTimeout(), IterativePathLookup(), and sendRpc().
IterativeLookup* IterativePathLookup::lookup [protected] |
Definition at line 291 of file IterativeLookup.h.
Referenced by accepts(), add(), handleFailedNodeResponse(), handleResponse(), handleTimeout(), sendNewRpcAfterTimeout(), and sendRpc().
LookupVector IterativePathLookup::nextHops [protected] |
Definition at line 300 of file IterativeLookup.h.
Referenced by add(), handleFailedNodeResponse(), handleResponse(), handleTimeout(), IterativePathLookup(), and sendRpc().
std::map<TransportAddress, NodeHandle> IterativePathLookup::oldNextHops [protected] |
Definition at line 301 of file IterativeLookup.h.
Referenced by handleFailedNodeResponse(), handleResponse(), handleTimeout(), and sendRpc().
BaseOverlay* IterativePathLookup::overlay [protected] |
Definition at line 292 of file IterativeLookup.h.
Referenced by IterativePathLookup(), and sendRpc().
int IterativePathLookup::pendingRpcs [protected] |
Definition at line 297 of file IterativeLookup.h.
Referenced by handleResponse(), handleTimeout(), IterativePathLookup(), sendNewRpcAfterTimeout(), 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] |
Definition at line 299 of file IterativeLookup.h.
Referenced by handleResponse(), IterativeLookup::handleRpcResponse(), IterativeLookup::handleRpcTimeout(), handleTimeout(), IterativePathLookup(), and sendRpc().