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