#include <Koorde.h>
Implementation of the Koorde KBR overlay as described in "Koorde: A simple degree-optimal distributed hash table" by M. Kaashoek and D. Karger
Public Member Functions | |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | handleTimerEvent (cMessage *msg) |
Processes "timer" self-messages. | |
virtual void | handleUDPMessage (BaseOverlayMessage *msg) |
Processes messages from underlay. | |
virtual void | recordOverlaySentStats (BaseOverlayMessage *msg) |
Collect overlay specific sent messages statistics. | |
virtual void | finishOverlay () |
collects statistical data in derived class | |
virtual void | updateTooltip () |
updates information shown in tk-environment | |
Protected Member Functions | |
virtual void | changeState (int state) |
changes node state | |
virtual void | handleDeBruijnTimerExpired (cMessage *msg) |
handle a expired join timer | |
virtual void | handleFixFingersTimerExpired (cMessage *msg) |
handle a expired fix_fingers timer (dummy function) | |
virtual bool | handleRpc (BaseCallMessage *msg) |
Processes Remote-Procedure-Call invokation messages. | |
virtual void | handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt) |
This method is called if an RPC response has been received. | |
virtual void | handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey) |
This method is called if an RPC timeout has been reached. | |
virtual void | handleRpcJoinResponse (JoinResponse *joinResponse) |
handle a received JOIN response | |
virtual void | handleRpcDeBruijnRequest (DeBruijnCall *deBruinCall) |
handle a received DEBRUIJN request | |
virtual void | handleRpcDeBruijnResponse (DeBruijnResponse *deBruijnResponse) |
handle a received DEBRUIJN response | |
virtual void | handleDeBruijnTimeout (DeBruijnCall *deBruijnCall) |
handle a DEBRUIJN timeout | |
virtual NodeHandle | findDeBruijnHop (const OverlayKey &destKey, KoordeFindNodeExtMessage *findNodeExt) |
returns the NodeHandle of the next hop to destination key using the de Bruijn list | |
NodeVector * | findNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg) |
Implements the find node call. | |
virtual OverlayKey | findStartKey (const OverlayKey &startKey, const OverlayKey &endKey, const OverlayKey &destKey) |
find a "good" routing key to destKey between startingKey and endKey with the longest matching prefix possible | |
virtual int | findLongestMatch (const OverlayKey &srcKey, const OverlayKey &destKey) |
find maximal number of bits in which two keys match using right shifting | |
virtual const NodeHandle & | walkDeBruijnList (const OverlayKey &key) |
Given a key the function checks if the key falls between two nodes in the de Bruijn list. | |
virtual const NodeHandle & | walkSuccessorList (const OverlayKey &key) |
Given a key the function checks if the key falls between two nodes in the de successor list. | |
virtual void | handleRpcStabilizeResponse (StabilizeResponse *stabilizeResponse) |
handles a received Stabilize response | |
virtual void | rpcNotify (NotifyCall *call) |
handles a received Notify request | |
virtual void | handleRpcNotifyResponse (NotifyResponse *notifyResponse) |
handles a received Notify response | |
virtual void | findFriendModules () |
Sets the pointer to the successor list module. | |
virtual void | initializeFriendModules () |
Intializes the successor list. | |
virtual void | predecessorIsDead () |
The function is called after the predecessor node is dead and resets the bit indicating the predecessor has a De-Bruijn-Node set. | |
virtual void | successorIsDead () |
The function is called after the successor node is dead and resets the bit indicating the successor has a De-Bruijn-Node set. | |
Protected Attributes | |
int | deBruijnDelay |
number of seconds between two de Bruijn algo calls | |
bool | pingProtocol |
enable ping protocol? | |
int | deBruijnNumber |
number of current nodes in de Bruijn list; depend on number of nodes in successor list | |
int | deBruijnListSize |
maximal number of nodes in de Bruijn list | |
int | shiftingBits |
number of bits concurrently shifted in one routing step | |
bool | fastLookup |
enable fast lookup (using successor list)? | |
bool | sucDeBruijnNodeSet |
flag is set if our successor has a de bruijn node | |
bool | preDeBruijnNodeSet |
flag is set if our predecessor has a de bruijn node | |
bool | useOtherLookup |
flag which is indicating that the optimization other lookup is enabled | |
bool | useSucList |
flag which is indicating that the optimization using the successorlist is enabled | |
bool | breakLookup |
flag is used during the recursive step when returning this node | |
bool | firstTimer |
indicates if this is the first de bruijn timer | |
int | deBruijnRetryTime |
time interval when the de bruijn call times out | |
int | failedDBResponses |
number of failed responses to a de bruijn call | |
bool | preOrSuc |
flag which indicates if the predecessor or successor is used as a springboard | |
int | deBruijnCount |
number of de bruijn calls | |
int | deBruijnBytesSent |
number of bytes sent during de bruijn calls | |
NodeHandle * | deBruijnNodes |
List of de Bruijn nodes. | |
NodeHandle | deBruijnNode |
Handle to our de Bruijn node. | |
cMessage * | deBruijn_timer |
void Koorde::initializeOverlay | ( | int | stage | ) | [virtual] |
Initializes derived-class-attributes.
Initializes derived-class-attributes, called by BaseOverlay::initialize(). By default this method is called once. If more stages are needed one can overload numInitStages() and add more stages.
stage | the init stage |
Reimplemented from Chord.
00037 { 00038 // because of IPAddressResolver, we need to wait until interfaces 00039 // are registered, address auto-assignment takes place etc. 00040 if(stage != MIN_STAGE_OVERLAY) 00041 return; 00042 00043 // fetch some parameters 00044 deBruijnDelay = par("deBruijnDelay"); 00045 deBruijnListSize = par("deBruijnListSize"); 00046 shiftingBits = par("shiftingBits"); 00047 useOtherLookup = par("useOtherLookup"); 00048 useSucList = par("useSucList"); 00049 00050 // init flags 00051 sucDeBruijnNodeSet = false; 00052 preDeBruijnNodeSet = false; 00053 breakLookup = false; 00054 firstTimer = true; 00055 preOrSuc = false; 00056 00057 // some local variables 00058 failedDBResponses = 0; 00059 deBruijnRetryTime = 20; 00060 deBruijnNumber = 0; 00061 deBruijnNodes = new NodeHandle[deBruijnListSize]; 00062 00063 // statistics 00064 deBruijnCount = 0; 00065 deBruijnBytesSent = 0; 00066 00067 // add some watches 00068 WATCH(sucDeBruijnNodeSet); 00069 WATCH(deBruijnNumber); 00070 WATCH(deBruijnNode); 00071 00072 //timer Messages 00073 deBruijn_timer = new cMessage("deBruijn_timer"); 00074 00075 Chord::initializeOverlay(stage); 00076 }
void Koorde::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Processes "timer" self-messages.
msg | A self-message |
Reimplemented from Chord.
00105 { 00106 // catch DeBruijn timer 00107 if (msg->isName("deBruijn_timer")) 00108 handleDeBruijnTimerExpired(msg); 00109 else if (msg->isName("fixfingers_timer")) 00110 handleFixFingersTimerExpired(msg); 00111 else 00112 Chord::handleTimerEvent(msg); 00113 }
void Koorde::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Processes messages from underlay.
msg | Message from UDP |
Reimplemented from Chord.
00186 { 00187 Chord::handleUDPMessage(msg); 00188 }
void Koorde::recordOverlaySentStats | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Collect overlay specific sent messages statistics.
This method is called from BaseOverlay::sendMessageToUDP() for every overlay message that is sent by a node. Use this to collect statistical data for overlay protocol specific message types.
msg | The overlay message to be sent to the UDP layer |
Reimplemented from Chord.
00734 { 00735 Chord::recordOverlaySentStats(msg); 00736 00737 BaseOverlayMessage* innerMsg; 00738 00739 if (msg->getType() == OVERLAYROUTE) 00740 innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg()); 00741 else 00742 innerMsg = msg; 00743 00744 switch (innerMsg->getType()) { 00745 00746 case RPC: { 00747 if ((dynamic_cast<DeBruijnCall*>(innerMsg) != NULL) || 00748 (dynamic_cast<DeBruijnResponse*>(innerMsg) != NULL)) { 00749 RECORD_STATS(deBruijnCount++; deBruijnBytesSent += 00750 msg->byteLength()); 00751 } 00752 break; 00753 } 00754 } 00755 }
void Koorde::finishOverlay | ( | ) | [virtual] |
collects statistical data in derived class
Reimplemented from Chord.
00716 { 00717 // destroy self timer messages 00718 cancelEvent(deBruijn_timer); 00719 00720 delete deBruijn_timer; 00721 00722 // statistics 00723 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); 00724 00725 if(time != 0) { 00726 globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Messages/s", deBruijnCount / time); 00727 globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Bytes/s", deBruijnBytesSent / time); 00728 } 00729 00730 Chord::finishOverlay(); 00731 }
void Koorde::updateTooltip | ( | ) | [virtual] |
updates information shown in tk-environment
Reimplemented from Chord.
Referenced by changeState(), handleDeBruijnTimeout(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), handleRpcNotifyResponse(), handleRpcStabilizeResponse(), and rpcNotify().
00674 { 00675 // 00676 // Updates the tooltip display strings. 00677 // 00678 00679 if (ev.isGUI()) { 00680 std::stringstream ttString; 00681 00682 // show our predecessor, successor and de Bruijn node in tooltip 00683 ttString << "Pred "<< predecessorNode << endl << "This " 00684 << thisNode << endl 00685 << "Suc " << successorList->getSuccessor() << endl 00686 << "DeBr " << deBruijnNode << endl; 00687 ttString << "List "; 00688 00689 for (unsigned int i = 0; i < successorList->getSize(); i++) { 00690 ttString << successorList->getSuccessor(i).ip << " "; 00691 } 00692 00693 ttString << endl; 00694 ttString << "DList "; 00695 00696 for (int i = 0; i < deBruijnNumber; i++) { 00697 ttString << deBruijnNodes[i].ip << " "; 00698 } 00699 00700 ttString << endl; 00701 00702 parentModule()->parentModule()->displayString().setTagArg( 00703 "tt", 0, ttString.str().c_str()); 00704 parentModule()->displayString().setTagArg("tt", 0, 00705 ttString.str().c_str()); 00706 displayString().setTagArg("tt", 0, ttString.str().c_str()); 00707 00708 // draw an arrow to our current successor 00709 showOverlayNeighborArrow(successorList->getSuccessor(), true, 00710 "m=m,50,0,50,0;o=red,1"); 00711 } 00712 }
void Koorde::changeState | ( | int | state | ) | [protected, virtual] |
changes node state
state | state to change to |
Reimplemented from Chord.
00079 { 00080 Chord::changeState(toState); 00081 00082 switch(state) { 00083 case INIT: 00084 // init de Bruijn nodes 00085 deBruijnNode = NodeHandle::UNSPECIFIED_NODE; 00086 for (int i=0; i < deBruijnListSize; i++) 00087 deBruijnNodes[i] = NodeHandle::UNSPECIFIED_NODE; 00088 updateTooltip(); 00089 break; 00090 case READY: 00091 // init de Bruijn Protocol 00092 cancelEvent(deBruijn_timer); 00093 scheduleAt(simulation.simTime() + deBruijnDelay, deBruijn_timer); 00094 00095 // since we don't need the fixfingers protocol in Koorde cancel timer 00096 cancelEvent(fixfingers_timer); 00097 break; 00098 default: 00099 break; 00100 } 00101 00102 }
void Koorde::handleDeBruijnTimerExpired | ( | cMessage * | msg | ) | [protected, virtual] |
handle a expired join timer
msg | the timer self-message |
Referenced by handleTimerEvent().
00117 { 00118 if (state == READY) { 00119 OverlayKey lookup = thisNode.key << shiftingBits; 00120 00121 if (lookup.isBetweenR(thisNode.key, successorList->getSuccessor().key) 00122 || successorList->isEmpty()) { 00123 00124 int sucNum = successorList->getSize(); 00125 if (sucNum > deBruijnListSize) 00126 sucNum = deBruijnListSize; 00127 00128 deBruijnNode = thisNode; 00129 for (int i = 0; i < sucNum; i++) { 00130 deBruijnNodes[i] = successorList->getSuccessor(i); 00131 deBruijnNumber = i+1; 00132 } 00133 00134 updateTooltip(); 00135 } else { 00136 DeBruijnCall* call = new DeBruijnCall("DeBruijnCall"); 00137 call->setDestKey(lookup); 00138 call->setLength(DEBRUIJNCALL_L(call)); 00139 00140 // if we don't have a de Bruijn node we use our successor 00141 // or our predecessor as a springboard if they have their 00142 // flags set or we didn't have a chance to get it 00143 if (deBruijnNode.isUnspecified()) { 00144 if (firstTimer || (sucDeBruijnNodeSet && !preOrSuc)) { 00145 sendRouteRpcCall(OVERLAY_COMP, 00146 successorList->getSuccessor(), 00147 call->getDestKey(), call, NULL, 00148 DEFAULT_ROUTING, deBruijnRetryTime); 00149 firstTimer = false; 00150 } else if (preOrSuc && preDeBruijnNodeSet) { 00151 sendRouteRpcCall(OVERLAY_COMP, 00152 predecessorNode, 00153 call->getDestKey(), call, NULL, 00154 DEFAULT_ROUTING, deBruijnRetryTime); 00155 } else { 00156 sendRouteRpcCall(OVERLAY_COMP, call->getDestKey(), 00157 call, NULL, DEFAULT_ROUTING, 00158 deBruijnRetryTime); 00159 00160 EV << "[Koorde::handleDeBruijnTimerExpired() @ " << thisNode.ip 00161 << " (" << thisNode.key.toString(16) << ")]\n" 00162 << " Have to route DeBruijnCall to destination key" 00163 << endl; 00164 } 00165 } else { 00166 sendRouteRpcCall(OVERLAY_COMP, deBruijnNode, 00167 call->getDestKey(), call, NULL, 00168 DEFAULT_ROUTING, deBruijnRetryTime); 00169 } 00170 00171 } 00172 00173 cancelEvent(deBruijn_timer); 00174 scheduleAt(simulation.simTime() + deBruijnDelay, deBruijn_timer); 00175 } 00176 }
void Koorde::handleFixFingersTimerExpired | ( | cMessage * | msg | ) | [protected, virtual] |
handle a expired fix_fingers timer (dummy function)
msg | the timer self-message |
Reimplemented from Chord.
Referenced by handleTimerEvent().
bool Koorde::handleRpc | ( | BaseCallMessage * | msg | ) | [protected, virtual] |
Processes Remote-Procedure-Call invokation messages.
This method should be overloaded when the overlay provides RPC functionality.
Reimplemented from Chord.
00192 { 00193 if (state != READY) { 00194 //EV << "[Koorde::handleRpc() @ " << thisNode.ip 00195 // << " (" << thisNode.key.toString(16) << ")]\n" 00196 // << " Received RPC call and state != READY!" 00197 // << endl; 00198 //cout << "RPC in non-Ready state received!" << endl; 00199 return false; 00200 } 00201 00202 // delegate messages 00203 RPC_SWITCH_START( msg ) 00204 // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> ) 00205 RPC_DELEGATE( Join, rpcJoin ); 00206 RPC_DELEGATE( Notify, rpcNotify ); 00207 RPC_DELEGATE( Stabilize, rpcStabilize ); 00208 RPC_DELEGATE( Fixfingers, rpcFixfingers ); 00209 RPC_DELEGATE( DeBruijn, handleRpcDeBruijnRequest ); 00210 RPC_SWITCH_END( ) 00211 00212 return RPC_HANDLED; 00213 }
void Koorde::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [protected, virtual] |
This method is called if an RPC response has been received.
msg | The response message. | |
context | Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code | |
rpcId | The RPC id. | |
rtt | The Round-Trip-Time of this RPC |
Reimplemented from Chord.
00218 { 00219 RPC_SWITCH_START(msg) 00220 RPC_ON_RESPONSE( Join ) { 00221 handleRpcJoinResponse(_JoinResponse); 00222 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00223 << " (" << thisNode.key.toString(16) << ")]\n" 00224 << " Join RPC Response received: id=" << rpcId 00225 << "\n msg=" << *_JoinResponse << " rtt=" << rtt 00226 << endl; 00227 break; 00228 } 00229 RPC_ON_RESPONSE( Notify ) { 00230 handleRpcNotifyResponse(_NotifyResponse); 00231 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00232 << " (" << thisNode.key.toString(16) << ")]\n" 00233 << " Notify RPC Response received: id=" << rpcId 00234 << "\n msg=" << *_NotifyResponse << " rtt=" << rtt 00235 << endl; 00236 break; 00237 } 00238 RPC_ON_RESPONSE( Stabilize ) { 00239 handleRpcStabilizeResponse(_StabilizeResponse); 00240 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00241 << " (" << thisNode.key.toString(16) << ")]\n" 00242 << " Stabilize RPC Response received: id=" << rpcId 00243 << "\n msg=" << *_StabilizeResponse << " rtt=" << rtt 00244 << endl; 00245 break; 00246 } 00247 RPC_ON_RESPONSE( Fixfingers ) { 00248 handleRpcFixfingersResponse(_FixfingersResponse); 00249 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00250 << " (" << thisNode.key.toString(16) << ")]\n" 00251 << " Fixfingers RPC Response received: id=" << rpcId 00252 << "\n msg=" << *_FixfingersResponse << " rtt=" << rtt 00253 << endl; 00254 break; 00255 } 00256 RPC_ON_RESPONSE( DeBruijn ) { 00257 handleRpcDeBruijnResponse(_DeBruijnResponse); 00258 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00259 << " (" << thisNode.key.toString(16) << ")]\n" 00260 << " DeBruijn RPC Response received: id=" << rpcId 00261 << "\n msg=" << *_DeBruijnResponse << " rtt=" << rtt 00262 << endl; 00263 break; 00264 } 00265 RPC_SWITCH_END( ) 00266 }
void Koorde::handleRpcTimeout | ( | BaseCallMessage * | msg, | |
const TransportAddress & | dest, | |||
cPolymorphic * | context, | |||
int | rpcId, | |||
const OverlayKey & | destKey | |||
) | [protected, virtual] |
This method is called if an RPC timeout has been reached.
msg | The original RPC message. | |
dest | The destination node | |
context | Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code | |
rpcId | The RPC id. | |
destKey | the destination OverlayKey |
Reimplemented from Chord.
00271 { 00272 RPC_SWITCH_START(msg) 00273 RPC_ON_CALL( Join ) { 00274 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00275 << " (" << thisNode.key.toString(16) << ")]\n" 00276 << " Join RPC Call timed out: id=" << rpcId 00277 << "\n msg=" << *_JoinCall 00278 << endl; 00279 break; 00280 } 00281 RPC_ON_CALL( Notify ) { 00282 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00283 << " (" << thisNode.key.toString(16) << ")]\n" 00284 << " Notify RPC Call timed out: id=" << rpcId 00285 << "\n msg=" << *_NotifyCall 00286 << endl; 00287 break; 00288 } 00289 RPC_ON_CALL( Stabilize ) { 00290 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00291 << " (" << thisNode.key.toString(16) << ")]\n" 00292 << " Stabilize RPC Call timed out: id=" << rpcId 00293 << "\n msg=" << *_StabilizeCall 00294 << endl; 00295 break; 00296 } 00297 RPC_ON_CALL( Fixfingers ) { 00298 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00299 << " (" << thisNode.key.toString(16) << ")]\n" 00300 << " Fixfingers RPC Call timed out: id=" << rpcId 00301 << "\n msg=" << *_FixfingersCall 00302 << endl; 00303 break; 00304 } 00305 RPC_ON_CALL( DeBruijn ) { 00306 handleDeBruijnTimeout(_DeBruijnCall); 00307 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00308 << " (" << thisNode.key.toString(16) << ")]\n" 00309 << " DeBruijn RPC Call timed out: id=" << rpcId 00310 << "\n msg=" << *_DeBruijnCall 00311 << endl; 00312 break; 00313 } 00314 RPC_SWITCH_END( ) 00315 }
void Koorde::handleRpcJoinResponse | ( | JoinResponse * | joinResponse | ) | [protected, virtual] |
handle a received JOIN response
joinResponse | the message to process |
Reimplemented from Chord.
Referenced by handleRpcResponse().
00319 { 00320 Chord::handleRpcJoinResponse(joinResponse); 00321 00322 // has to be canceled in Koorde 00323 cancelEvent(fixfingers_timer); 00324 00325 // immediate deBruijn protocol 00326 cancelEvent(deBruijn_timer); 00327 scheduleAt(simulation.simTime(), deBruijn_timer); 00328 }
void Koorde::handleRpcDeBruijnRequest | ( | DeBruijnCall * | deBruinCall | ) | [protected, virtual] |
handle a received DEBRUIJN request
deBruinCall | the message to process |
Referenced by handleRpc().
00441 { 00442 // The key lies between thisNode and its predecessor and 00443 // because routing the message to the predecessor of a key 00444 // is near to impossible we set the deBruijnNodes here 00445 // and the information is as actual as the predecessor pointer 00446 if (deBruijnCall->getDestKey().isBetweenR(predecessorNode.key, 00447 thisNode.key)) { 00448 DeBruijnResponse* deBruijnResponse = 00449 new DeBruijnResponse("DeBruijnResponse"); 00450 00451 deBruijnResponse->setDBNode(predecessorNode); 00452 00453 int sucNum = successorList->getSize() + 1; 00454 deBruijnResponse->setSucNum(sucNum); 00455 deBruijnResponse->setSucNodeArraySize(sucNum); 00456 00457 deBruijnResponse->setSucNode(0, thisNode); 00458 for (int k = 1; k < sucNum; k++) { 00459 deBruijnResponse->setSucNode(k, successorList->getSuccessor(k-1)); 00460 } 00461 deBruijnResponse->setLength(DEBRUIJNRESPONSE_L(deBruijnResponse)); 00462 00463 sendRpcResponse(deBruijnCall, deBruijnResponse); 00464 } else if (deBruijnCall->getDestKey().isBetweenR(thisNode.key, 00465 successorList->getSuccessor().key)) { 00466 error("Koorde::handleRpcDeBruijnRequest() - unknown error."); 00467 } else { 00468 error("Koorde::handleRpcDeBruijnRequest() - " 00469 "Request couldn't be delivered!"); 00470 } 00471 }
void Koorde::handleRpcDeBruijnResponse | ( | DeBruijnResponse * | deBruijnResponse | ) | [protected, virtual] |
handle a received DEBRUIJN response
deBruijnResponse | the message to process |
Referenced by handleRpcResponse().
00475 { 00476 int sucNum = deBruijnResponse->getSucNum(); 00477 if (sucNum > deBruijnListSize) 00478 sucNum = deBruijnListSize; 00479 00480 for (int i = 0; i < sucNum; i++) { 00481 deBruijnNodes[i] = deBruijnResponse->getSucNode(i); 00482 deBruijnNumber = i+1; 00483 } 00484 00485 deBruijnNode = deBruijnResponse->getDBNode(); 00486 00487 updateTooltip(); 00488 }
void Koorde::handleDeBruijnTimeout | ( | DeBruijnCall * | deBruijnCall | ) | [protected, virtual] |
handle a DEBRUIJN timeout
deBruijnCall | the message which timed out |
Referenced by handleRpcTimeout().
00491 { 00492 if (failedDBResponses == stabilizeRetry) { 00493 failedDBResponses = 0; 00494 deBruijnNode = NodeHandle::UNSPECIFIED_NODE; 00495 preOrSuc = !preOrSuc; 00496 } else { 00497 failedDBResponses++; 00498 } 00499 00500 updateTooltip(); 00501 cancelEvent(deBruijn_timer); 00502 scheduleAt(simulation.simTime(), deBruijn_timer); 00503 }
NodeHandle Koorde::findDeBruijnHop | ( | const OverlayKey & | destKey, | |
KoordeFindNodeExtMessage * | findNodeExt | |||
) | [protected, virtual] |
returns the NodeHandle of the next hop to destination key using the de Bruijn list
destKey | The destination key | |
findNodeExt | The FindNodeExtensionMessage |
Referenced by findNode().
00578 { 00579 // check if the route key falls in our responsibility or 00580 // else forward the message to our successor 00581 if (findNodeExt->getRouteKey().isBetweenR(thisNode.key, 00582 successorList->getSuccessor().key)) { 00583 if ((unsigned int)findNodeExt->getStep() > destKey.getLength()) 00584 error("Broose::findDeBruijnHop - Bounding error: " 00585 "trying to get non existing bit out of overlay key!"); 00586 00587 // updating the route key 00588 OverlayKey add = OverlayKey(destKey.getBit(destKey.getLength() - 00589 findNodeExt->getStep())); 00590 for (int i = 1; i < shiftingBits; i++) { 00591 add = (add << 1) + OverlayKey(destKey.getBit(destKey.getLength() - findNodeExt->getStep() - i)); 00592 } 00593 00594 OverlayKey routeKey = (findNodeExt->getRouteKey()<<shiftingBits) + add; 00595 findNodeExt->setRouteKey(routeKey); 00596 findNodeExt->setStep(findNodeExt->getStep() + shiftingBits); 00597 00598 if(deBruijnNode.isUnspecified()) { 00599 breakLookup = true; 00600 if (useSucList) 00601 return walkSuccessorList(findNodeExt->getRouteKey()); 00602 else 00603 return successorList->getSuccessor(); 00604 } 00605 00606 // check if the new route key falls between our 00607 // de Bruijn node and its successor 00608 if (deBruijnNumber > 0) { 00609 if (findNodeExt->getRouteKey().isBetweenR(deBruijnNode.key, 00610 deBruijnNodes[0].key)) { 00611 return deBruijnNode; 00612 } else { 00613 // otherwise check if the route key falls between 00614 // our de Bruijn successors 00615 NodeHandle nextHop = walkDeBruijnList(findNodeExt-> 00616 getRouteKey()); 00617 return nextHop; 00618 } 00619 } else { 00620 return deBruijnNode; 00621 } 00622 } else { 00623 breakLookup = true; 00624 // if optimization is set search the successor list and 00625 // de bruijn node to find "good" next hop 00626 if (useSucList) { 00627 if (!deBruijnNode.isUnspecified()) { 00628 return walkSuccessorList(findNodeExt->getRouteKey()); 00629 } else { 00630 NodeHandle tmpHandle = walkSuccessorList( 00631 findNodeExt->getRouteKey()); 00632 00633 //todo: optimization - check complete deBruijnList 00634 if (deBruijnNode.key.isBetween(tmpHandle.key, 00635 findNodeExt->getRouteKey())) { 00636 return deBruijnNode; 00637 } else { 00638 return tmpHandle; 00639 } 00640 } 00641 } else 00642 return successorList->getSuccessor(); 00643 } 00644 }
NodeVector * Koorde::findNode | ( | const OverlayKey & | key, | |
int | numRedundantNodes, | |||
int | numSiblings, | |||
BaseOverlayMessage * | msg | |||
) | [protected, virtual] |
Implements the find node call.
This method simply returns the closest nodes known in the corresponding routing topology. If the node is a sibling for this key (isSiblingFor(key) = true), this method returns all numSiblings siblings, with the closest neighbor to the key first.
key | The lookup key. | |
numRedundantNodes | Maximum number of next hop nodes to return. | |
numSiblings | number of siblings to return | |
msg | A pointer to the BaseRouteMessage or FindNodeCall message of this lookup. |
Reimplemented from Chord.
00509 { 00510 NodeVector* nextHop = new NodeVector(); 00511 KoordeFindNodeExtMessage *findNodeExt = NULL; 00512 00513 if (state != READY) 00514 return nextHop; 00515 00516 if (msg != NULL) { 00517 if (!msg->hasObject("findNodeExt")) { 00518 findNodeExt = new KoordeFindNodeExtMessage("findNodeExt"); 00519 00520 OverlayKey routeKey = findStartKey(thisNode.key, 00521 successorList->getSuccessor().key, key); 00522 int matchingBits = findLongestMatch(routeKey, key); 00523 findNodeExt->setRouteKey(routeKey); 00524 findNodeExt->setStep(matchingBits + 1); 00525 findNodeExt->setOtherLookup(false); 00526 findNodeExt->setLength(KOORDEFINDNODEEXTMESSAGE_L); 00527 findNodeExt->setSrcNode(thisNode); 00528 msg->addObject( findNodeExt ); 00529 } 00530 findNodeExt = (KoordeFindNodeExtMessage*) msg->getObject("findNodeExt"); 00531 } 00532 00533 if (key.isUnspecified()) { 00534 error("Koorde::findNode() - direct Messaging is no longer in use."); 00535 } else if (key.isBetweenR(predecessorNode.key, thisNode.key)) { 00536 // the message is destined for this node 00537 nextHop->push_back(thisNode); 00538 } else if (key.isBetweenR(thisNode.key, successorList->getSuccessor().key)){ 00539 // the message destined for our successor 00540 nextHop->push_back(successorList->getSuccessor()); 00541 } else { 00542 // if useOtherLookup is enabled we try to use 00543 // our successor list to get to the key 00544 if (useOtherLookup) { 00545 NodeHandle tmpNode = walkSuccessorList(key); 00546 if (tmpNode != successorList->getSuccessor( 00547 successorList->getSize()-1)) { 00548 findNodeExt->setOtherLookup(true); 00549 nextHop->push_back(tmpNode); 00550 } else if (findNodeExt->getOtherLookup() == true) { 00551 nextHop->push_back(tmpNode); 00552 } else { 00553 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt); 00554 if (tmpHandle != thisNode || breakLookup) { 00555 nextHop->push_back(tmpHandle); 00556 breakLookup = false; 00557 } else { 00558 return findNode(key, numRedundantNodes, numSiblings, msg); 00559 } 00560 } 00561 } else { 00562 // find next hop using either the de Bruijn node and 00563 // its successors or our own successors 00564 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt); 00565 if (tmpHandle != thisNode || breakLookup) { 00566 nextHop->push_back(tmpHandle); 00567 breakLookup = false; 00568 } else { 00569 return findNode(key, numRedundantNodes, numSiblings, msg); 00570 } 00571 } 00572 } 00573 return nextHop; 00574 }
OverlayKey Koorde::findStartKey | ( | const OverlayKey & | startKey, | |
const OverlayKey & | endKey, | |||
const OverlayKey & | destKey | |||
) | [protected, virtual] |
find a "good" routing key to destKey between startingKey and endKey with the longest matching prefix possible
startKey | begin of the (key) interval | |
endKey | end of the (key) interval | |
destKey | destination key - should be matched as good as possible |
Referenced by findNode().
00760 { 00761 OverlayKey diffKey, newStart, tmpDest, newKey, powKey; 00762 int nBits; 00763 00764 if (startKey == endKey) 00765 return startKey; 00766 00767 diffKey = endKey - startKey; 00768 nBits = diffKey.log_2(); 00769 00770 while ((startKey.getLength() - nBits) % shiftingBits != 0) { 00771 nBits--; 00772 } 00773 00774 newStart = startKey >> nBits; 00775 newStart = newStart << nBits; 00776 00777 tmpDest = destKey >> (destKey.getLength() - nBits); 00778 newKey = tmpDest + newStart; 00779 00780 // is the new constructed route key bigger than our start key return it 00781 if (newKey.isBetweenR(startKey, endKey)) { 00782 return newKey; 00783 } 00784 00785 // If the part of the destination key smaller than the one of 00786 // the orginal key add pow(nBits) (this is the first bit where 00787 // the start key and end key differ) to the new constructed key 00788 // and check if it's beetween start and end key. 00789 00790 newKey += powKey.pow2(nBits); 00791 if(newKey.isBetweenR(startKey, endKey)) { 00792 return newKey; 00793 } 00794 00795 // this part should not be called 00796 error("Koorde::findStartKey()"); 00797 return OverlayKey::UNSPECIFIED_KEY; 00798 }
int Koorde::findLongestMatch | ( | const OverlayKey & | srcKey, | |
const OverlayKey & | destKey | |||
) | [protected, virtual] |
find maximal number of bits in which two keys match using right shifting
srcKey | the source key | |
destKey | the destination key |
Referenced by findNode().
00802 { 00803 int keyLength = srcKey.getLength(); 00804 bool equal = true; 00805 00806 for (int i = keyLength; i>0; i--) { 00807 equal = true; 00808 for(int j = 1; j <= i; j++) { 00809 if (srcKey.getBit(i - j) != destKey.getBit(destKey.getLength() - j)) { 00810 equal = false; 00811 break; 00812 } 00813 } 00814 00815 if (equal) 00816 return i; 00817 00818 } 00819 return 0; 00820 }
const NodeHandle & Koorde::walkDeBruijnList | ( | const OverlayKey & | key | ) | [protected, virtual] |
Given a key the function checks if the key falls between two nodes in the de Bruijn list.
If no match is found the last node in the de Bruijn list is returned.
key | the key to check |
Referenced by findDeBruijnHop().
00648 { 00649 if (deBruijnNumber == 0) 00650 return NodeHandle::UNSPECIFIED_NODE; 00651 00652 for (int i = 0; i < deBruijnNumber-1; i++) { 00653 if (key.isBetweenR(deBruijnNodes[i].key,deBruijnNodes[i+1].key)) { 00654 return deBruijnNodes[i]; 00655 } 00656 } 00657 00658 return deBruijnNodes[deBruijnNumber-1]; 00659 }
const NodeHandle & Koorde::walkSuccessorList | ( | const OverlayKey & | key | ) | [protected, virtual] |
Given a key the function checks if the key falls between two nodes in the de successor list.
If no match is found the last node in the de successor list is returned.
key | the key to check |
Referenced by findDeBruijnHop(), and findNode().
00662 { 00663 for (unsigned int i = 0; i < successorList->getSize()-1; i++) { 00664 if (key.isBetweenR(successorList->getSuccessor(i).key, 00665 successorList->getSuccessor(i+1).key)) { 00666 return successorList->getSuccessor(i); 00667 } 00668 } 00669 00670 return successorList->getSuccessor(successorList->getSize()-1); 00671 }
void Koorde::handleRpcStabilizeResponse | ( | StabilizeResponse * | stabilizeResponse | ) | [protected, virtual] |
handles a received Stabilize response
stabilizeResponse | the message to process |
Reimplemented from Chord.
Referenced by handleRpcResponse().
00331 { 00332 // our successor seems to be alive 00333 missingSuccessorStabResponses = 0; 00334 00335 // fetch the successor's predecessor 00336 NodeHandle predecessor = stabilizeResponse->getPreNode(); 00337 00338 // is the successor's predecessor a new successor for this node? 00339 if (successorList->isEmpty() || 00340 predecessor.key.isBetween(thisNode.key, 00341 successorList->getSuccessor().key)) { 00342 // add the successor's predecessor to the successor list 00343 successorList->addSuccessor(predecessor); 00344 updateTooltip(); 00345 } 00346 00347 // compile NOTIFY RPC 00348 NotifyCall* notifyCall = new NotifyCall("NotifyCall"); 00349 00350 if (!deBruijnNode.isUnspecified()) { 00351 notifyCall->setPreDBNodeSet(true); 00352 } else { 00353 notifyCall->setPreDBNodeSet(false); 00354 } 00355 00356 notifyCall->setLength(NOTIFYCALL_L(notifyCall)); 00357 sendUdpRpcCall(successorList->getSuccessor(), notifyCall); 00358 }
void Koorde::rpcNotify | ( | NotifyCall * | call | ) | [protected, virtual] |
handles a received Notify request
call | the message to process |
Reimplemented from Chord.
Referenced by handleRpc().
00362 { 00363 // our predecessor seems to be alive 00364 missingPredecessorStabRequests = 0; 00365 00366 NodeHandle newPredecessor = call->getSrcNode(); 00367 00368 // is the new predecessor closer than the current one? 00369 if (predecessorNode.isUnspecified() || 00370 newPredecessor.key.isBetween(predecessorNode.key, thisNode.key)) { 00371 00372 if ((predecessorNode.isUnspecified()) || 00373 (newPredecessor != predecessorNode)) { 00374 // send update to application if we've got a new predecessor 00375 if (!predecessorNode.isUnspecified()) { 00376 callUpdate(predecessorNode, false); 00377 } 00378 callUpdate(newPredecessor, true); 00379 00380 // set up new predecessor 00381 predecessorNode = newPredecessor; 00382 } 00383 00384 preDeBruijnNodeSet = call->getPreDBNodeSet(); 00385 firstTimer = false; 00386 updateTooltip(); 00387 } 00388 00389 // needed if the predecessor doesn't change 00390 if (newPredecessor == predecessorNode) 00391 preDeBruijnNodeSet = call->getPreDBNodeSet(); 00392 00393 // compile NOTIFY response 00394 NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse"); 00395 00396 int sucNum = successorList->getSize(); 00397 00398 if (deBruijnNode.isUnspecified()) { 00399 notifyResponse->setSucDBNodeSet(false); 00400 } else { 00401 notifyResponse->setSucDBNodeSet(true); 00402 } 00403 00404 notifyResponse->setSucNum(sucNum); 00405 notifyResponse->setSucNodeArraySize(sucNum); 00406 00407 for (int k = 0; k < sucNum; k++) { 00408 notifyResponse->setSucNode(k, successorList->getSuccessor(k)); 00409 } 00410 00411 notifyResponse->setLength(NOTIFYRESPONSE_L(notifyResponse)); 00412 00413 sendRpcResponse(call, notifyResponse); 00414 }
void Koorde::handleRpcNotifyResponse | ( | NotifyResponse * | notifyResponse | ) | [protected, virtual] |
handles a received Notify response
notifyResponse | the message to process |
Reimplemented from Chord.
Referenced by handleRpcResponse().
00418 { 00419 if (successorList->getSuccessor() != notifyResponse->getSrcNode()) { 00420 EV << "[Koorde::handleRpcNotifyResponse() @ " << thisNode.ip 00421 << " (" << thisNode.key.toString(16) << ")]\n" 00422 << " The srcNode of the received NotifyResponse is not our current successor" 00423 << endl; 00424 return; 00425 } 00426 00427 // replace our successor list by our successor's successor list 00428 successorList->updateList(notifyResponse); 00429 00430 // store if the de bruijn node of my successor is set, also 00431 // reset firstTimer flag 00432 sucDeBruijnNodeSet = notifyResponse->getSucDBNodeSet(); 00433 firstTimer = false; 00434 00435 updateTooltip(); 00436 }
void Koorde::findFriendModules | ( | ) | [protected, virtual] |
Sets the pointer to the successor list module.
Reimplemented from Chord.
00823 { 00824 successorList = check_and_cast<ChordSuccessorList*> 00825 (parentModule()->submodule("successorList")); 00826 }
void Koorde::initializeFriendModules | ( | ) | [protected, virtual] |
Intializes the successor list.
Reimplemented from Chord.
00829 { 00830 // initialize successor list 00831 successorList->initializeList(par("successorListSize"), thisNode, this); 00832 }
void Koorde::predecessorIsDead | ( | ) | [protected, virtual] |
The function is called after the predecessor node is dead and resets the bit indicating the predecessor has a De-Bruijn-Node set.
Reimplemented from Chord.
00835 { 00836 preDeBruijnNodeSet = false; 00837 //todo: this info could be used to remove predecessor node 00838 // from de bruijn successor list or even as our de bruijn node 00839 }
void Koorde::successorIsDead | ( | ) | [protected, virtual] |
The function is called after the successor node is dead and resets the bit indicating the successor has a De-Bruijn-Node set.
Reimplemented from Chord.
00842 { 00843 sucDeBruijnNodeSet = false; 00844 //todo: this info could be used to remove successor node 00845 // from de bruijn successor list or even as our de bruijn node 00846 }
int Koorde::deBruijnDelay [protected] |
number of seconds between two de Bruijn algo calls
Referenced by changeState(), handleDeBruijnTimerExpired(), and initializeOverlay().
bool Koorde::pingProtocol [protected] |
enable ping protocol?
int Koorde::deBruijnNumber [protected] |
number of current nodes in de Bruijn list; depend on number of nodes in successor list
Referenced by findDeBruijnHop(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), initializeOverlay(), updateTooltip(), and walkDeBruijnList().
int Koorde::deBruijnListSize [protected] |
maximal number of nodes in de Bruijn list
Referenced by changeState(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), and initializeOverlay().
int Koorde::shiftingBits [protected] |
number of bits concurrently shifted in one routing step
Referenced by findDeBruijnHop(), findStartKey(), handleDeBruijnTimerExpired(), and initializeOverlay().
bool Koorde::fastLookup [protected] |
enable fast lookup (using successor list)?
bool Koorde::sucDeBruijnNodeSet [protected] |
flag is set if our successor has a de bruijn node
Referenced by handleDeBruijnTimerExpired(), handleRpcNotifyResponse(), initializeOverlay(), and successorIsDead().
bool Koorde::preDeBruijnNodeSet [protected] |
flag is set if our predecessor has a de bruijn node
Referenced by handleDeBruijnTimerExpired(), initializeOverlay(), predecessorIsDead(), and rpcNotify().
bool Koorde::useOtherLookup [protected] |
flag which is indicating that the optimization other lookup is enabled
Referenced by findNode(), and initializeOverlay().
bool Koorde::useSucList [protected] |
flag which is indicating that the optimization using the successorlist is enabled
Referenced by findDeBruijnHop(), and initializeOverlay().
bool Koorde::breakLookup [protected] |
flag is used during the recursive step when returning this node
Referenced by findDeBruijnHop(), findNode(), and initializeOverlay().
bool Koorde::firstTimer [protected] |
indicates if this is the first de bruijn timer
Referenced by handleDeBruijnTimerExpired(), handleRpcNotifyResponse(), initializeOverlay(), and rpcNotify().
int Koorde::deBruijnRetryTime [protected] |
time interval when the de bruijn call times out
Referenced by handleDeBruijnTimerExpired(), and initializeOverlay().
int Koorde::failedDBResponses [protected] |
number of failed responses to a de bruijn call
Referenced by handleDeBruijnTimeout(), and initializeOverlay().
bool Koorde::preOrSuc [protected] |
flag which indicates if the predecessor or successor is used as a springboard
Referenced by handleDeBruijnTimeout(), handleDeBruijnTimerExpired(), and initializeOverlay().
int Koorde::deBruijnCount [protected] |
number of de bruijn calls
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Koorde::deBruijnBytesSent [protected] |
number of bytes sent during de bruijn calls
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
NodeHandle* Koorde::deBruijnNodes [protected] |
List of de Bruijn nodes.
Referenced by changeState(), findDeBruijnHop(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), initializeOverlay(), updateTooltip(), and walkDeBruijnList().
NodeHandle Koorde::deBruijnNode [protected] |
Handle to our de Bruijn node.
Referenced by changeState(), findDeBruijnHop(), handleDeBruijnTimeout(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), handleRpcStabilizeResponse(), initializeOverlay(), rpcNotify(), and updateTooltip().
cMessage* Koorde::deBruijn_timer [protected] |