#include <Koorde.h>
Inheritance diagram for Koorde:
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.
00102 { 00103 // catch DeBruijn timer 00104 if (msg->isName("deBruijn_timer")) 00105 handleDeBruijnTimerExpired(msg); 00106 else if (msg->isName("fixfingers_timer")) 00107 handleFixFingersTimerExpired(msg); 00108 else 00109 Chord::handleTimerEvent(msg); 00110 }
void Koorde::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Processes messages from underlay.
msg | Message from UDP |
Reimplemented from Chord.
00176 { 00177 Chord::handleUDPMessage(msg); 00178 }
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.
00725 { 00726 Chord::recordOverlaySentStats(msg); 00727 00728 BaseOverlayMessage* innerMsg; 00729 00730 if (msg->getType() == OVERLAYROUTE) 00731 innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg()); 00732 else 00733 innerMsg = msg; 00734 00735 switch (innerMsg->getType()) { 00736 00737 case RPC: { 00738 if ((dynamic_cast<DeBruijnCall*>(innerMsg) != NULL) || 00739 (dynamic_cast<DeBruijnResponse*>(innerMsg) != NULL)) { 00740 RECORD_STATS(deBruijnCount++; deBruijnBytesSent += 00741 msg->byteLength()); 00742 } 00743 break; 00744 } 00745 } 00746 }
void Koorde::finishOverlay | ( | ) | [virtual] |
collects statistical data in derived class
Reimplemented from Chord.
00707 { 00708 // destroy self timer messages 00709 cancelEvent(deBruijn_timer); 00710 00711 delete deBruijn_timer; 00712 00713 // statistics 00714 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); 00715 00716 if(time != 0) { 00717 globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Messages/s", deBruijnCount / time); 00718 globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Bytes/s", deBruijnBytesSent / time); 00719 } 00720 00721 Chord::finishOverlay(); 00722 }
void Koorde::updateTooltip | ( | ) | [virtual] |
updates information shown in tk-environment
Reimplemented from Chord.
00665 { 00666 // 00667 // Updates the tooltip display strings. 00668 // 00669 00670 if (ev.isGUI()) { 00671 std::stringstream ttString; 00672 00673 // show our predecessor, successor and de Bruijn node in tooltip 00674 ttString << "Pred "<< predecessorNode << endl << "This " 00675 << thisNode << endl 00676 << "Suc " << successorList->getSuccessor() << endl 00677 << "DeBr " << deBruijnNode << endl; 00678 ttString << "List "; 00679 00680 for (unsigned int i = 0; i < successorList->getSize(); i++) { 00681 ttString << successorList->getSuccessor(i).ip << " "; 00682 } 00683 00684 ttString << endl; 00685 ttString << "DList "; 00686 00687 for (int i = 0; i < deBruijnNumber; i++) { 00688 ttString << deBruijnNodes[i].ip << " "; 00689 } 00690 00691 ttString << endl; 00692 00693 parentModule()->parentModule()->displayString().setTagArg( 00694 "tt", 0, ttString.str().c_str()); 00695 parentModule()->displayString().setTagArg("tt", 0, 00696 ttString.str().c_str()); 00697 displayString().setTagArg("tt", 0, ttString.str().c_str()); 00698 00699 // draw an arrow to our current successor 00700 showOverlayNeighborArrow(successorList->getSuccessor(), true, 00701 "m=m,50,0,50,0;o=red,1"); 00702 } 00703 }
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 } 00098 00099 }
void Koorde::handleDeBruijnTimerExpired | ( | cMessage * | msg | ) | [protected, virtual] |
handle a expired join timer
msg | the timer self-message |
00114 { 00115 if (state == READY) { 00116 OverlayKey lookup = thisNode.key << shiftingBits; 00117 00118 if (lookup.isBetweenR(thisNode.key, successorList->getSuccessor().key) 00119 || successorList->isEmpty()) { 00120 00121 int sucNum = successorList->getSize(); 00122 if (sucNum > deBruijnListSize) 00123 sucNum = deBruijnListSize; 00124 00125 deBruijnNode = thisNode; 00126 for (int i = 0; i < sucNum; i++) { 00127 deBruijnNodes[i] = successorList->getSuccessor(i); 00128 deBruijnNumber = i+1; 00129 } 00130 00131 updateTooltip(); 00132 } else { 00133 DeBruijnCall* call = new DeBruijnCall("DeBruijnCall"); 00134 call->setDestKey(lookup); 00135 call->setLength(DEBRUIJNCALL_L(call)); 00136 00137 // if we don't have a de Bruijn node we use our successor 00138 // or our predecessor as a springboard if they have their 00139 // flags set or we didn't have a chance to get it 00140 if (deBruijnNode.isUnspecified()) { 00141 if(firstTimer || (sucDeBruijnNodeSet && !preOrSuc)) { 00142 sendRpcMessage(successorList->getSuccessor(), call, NULL, 00143 call->getDestKey(), -1, deBruijnRetryTime); 00144 firstTimer = false; 00145 } else if (preOrSuc && preDeBruijnNodeSet) { 00146 sendRpcMessage(predecessorNode, call, NULL, 00147 call->getDestKey(), -1, deBruijnRetryTime); 00148 } else { 00149 sendRpcMessage(NodeHandle::UNSPECIFIED_NODE, call, NULL, 00150 call->getDestKey(), -1, deBruijnRetryTime); 00151 EV << "[Koorde::handleDeBruijnTimerExpired() @ " << thisNode.ip 00152 << " (" << thisNode.key.toString(16) << ")]\n" 00153 << " Have to route DeBruijnCall to destination key" 00154 << endl; 00155 } 00156 } else { 00157 sendRpcMessage(deBruijnNode, call, NULL, call->getDestKey(), 00158 -1, deBruijnRetryTime); 00159 } 00160 00161 } 00162 00163 cancelEvent(deBruijn_timer); 00164 scheduleAt(simulation.simTime() + deBruijnDelay, deBruijn_timer); 00165 } 00166 }
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.
00182 { 00183 if (state != READY) { 00184 //EV << "[Koorde::handleRpc() @ " << thisNode.ip 00185 // << " (" << thisNode.key.toString(16) << ")]\n" 00186 // << " Received RPC call and state != READY!" 00187 // << endl; 00188 //cout << "RPC in non-Ready state received!" << endl; 00189 return false; 00190 } 00191 00192 // delegate messages 00193 RPC_SWITCH_START( msg ) 00194 // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> ) 00195 RPC_DELEGATE( Join, rpcJoin ); 00196 RPC_DELEGATE( Notify, rpcNotify ); 00197 RPC_DELEGATE( Stabilize, rpcStabilize ); 00198 RPC_DELEGATE( Fixfingers, rpcFixfingers ); 00199 RPC_DELEGATE( DeBruijn, handleRpcDeBruijnRequest ); 00200 RPC_SWITCH_END( ) 00201 00202 return RPC_HANDLED; 00203 }
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.
00207 { 00208 RPC_SWITCH_START(msg) 00209 RPC_ON_RESPONSE( Join ) { 00210 handleRpcJoinResponse(_JoinResponse); 00211 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00212 << " (" << thisNode.key.toString(16) << ")]\n" 00213 << " Join RPC Response received: id=" << rpcId 00214 << "\n msg=" << *_JoinResponse << " rtt=" << rtt 00215 << endl; 00216 break; 00217 } 00218 RPC_ON_RESPONSE( Notify ) { 00219 handleRpcNotifyResponse(_NotifyResponse); 00220 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00221 << " (" << thisNode.key.toString(16) << ")]\n" 00222 << " Notify RPC Response received: id=" << rpcId 00223 << "\n msg=" << *_NotifyResponse << " rtt=" << rtt 00224 << endl; 00225 break; 00226 } 00227 RPC_ON_RESPONSE( Stabilize ) { 00228 handleRpcStabilizeResponse(_StabilizeResponse); 00229 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00230 << " (" << thisNode.key.toString(16) << ")]\n" 00231 << " Stabilize RPC Response received: id=" << rpcId 00232 << "\n msg=" << *_StabilizeResponse << " rtt=" << rtt 00233 << endl; 00234 break; 00235 } 00236 RPC_ON_RESPONSE( Fixfingers ) { 00237 handleRpcFixfingersResponse(_FixfingersResponse); 00238 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00239 << " (" << thisNode.key.toString(16) << ")]\n" 00240 << " Fixfingers RPC Response received: id=" << rpcId 00241 << "\n msg=" << *_FixfingersResponse << " rtt=" << rtt 00242 << endl; 00243 break; 00244 } 00245 RPC_ON_RESPONSE( DeBruijn ) { 00246 handleRpcDeBruijnResponse(_DeBruijnResponse); 00247 EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 00248 << " (" << thisNode.key.toString(16) << ")]\n" 00249 << " DeBruijn RPC Response received: id=" << rpcId 00250 << "\n msg=" << *_DeBruijnResponse << " rtt=" << rtt 00251 << endl; 00252 break; 00253 } 00254 RPC_SWITCH_END( ) 00255 }
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.
00259 { 00260 RPC_SWITCH_START(msg) 00261 RPC_ON_CALL( Join ) { 00262 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00263 << " (" << thisNode.key.toString(16) << ")]\n" 00264 << " Join RPC Call timed out: id=" << rpcId 00265 << "\n msg=" << *_JoinCall 00266 << endl; 00267 break; 00268 } 00269 RPC_ON_CALL( Notify ) { 00270 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00271 << " (" << thisNode.key.toString(16) << ")]\n" 00272 << " Notify RPC Call timed out: id=" << rpcId 00273 << "\n msg=" << *_NotifyCall 00274 << endl; 00275 break; 00276 } 00277 RPC_ON_CALL( Stabilize ) { 00278 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00279 << " (" << thisNode.key.toString(16) << ")]\n" 00280 << " Stabilize RPC Call timed out: id=" << rpcId 00281 << "\n msg=" << *_StabilizeCall 00282 << endl; 00283 break; 00284 } 00285 RPC_ON_CALL( Fixfingers ) { 00286 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00287 << " (" << thisNode.key.toString(16) << ")]\n" 00288 << " Fixfingers RPC Call timed out: id=" << rpcId 00289 << "\n msg=" << *_FixfingersCall 00290 << endl; 00291 break; 00292 } 00293 RPC_ON_CALL( DeBruijn ) { 00294 handleDeBruijnTimeout(_DeBruijnCall); 00295 EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 00296 << " (" << thisNode.key.toString(16) << ")]\n" 00297 << " DeBruijn RPC Call timed out: id=" << rpcId 00298 << "\n msg=" << *_DeBruijnCall 00299 << endl; 00300 break; 00301 } 00302 RPC_SWITCH_END( ) 00303 }
void Koorde::handleRpcJoinResponse | ( | JoinResponse * | joinResponse | ) | [protected, virtual] |
handle a received JOIN response
joinResponse | the message to process |
Reimplemented from Chord.
00307 { 00308 Chord::handleRpcJoinResponse(joinResponse); 00309 00310 // has to be canceled in Koorde 00311 cancelEvent(fixfingers_timer); 00312 00313 // immediate deBruijn protocol 00314 cancelEvent(deBruijn_timer); 00315 scheduleAt(simulation.simTime(), deBruijn_timer); 00316 }
void Koorde::handleRpcDeBruijnRequest | ( | DeBruijnCall * | deBruinCall | ) | [protected, virtual] |
handle a received DEBRUIJN request
deBruinCall | the message to process |
00429 { 00430 // The key lies between thisNode and its predecessor and 00431 // because routing the message to the predecessor of a key 00432 // is near to impossible we set the deBruijnNodes here 00433 // and the information is as actual as the predecessor pointer 00434 if (deBruijnCall->getDestKey().isBetweenR(predecessorNode.key, 00435 thisNode.key)) { 00436 DeBruijnResponse* deBruijnResponse = 00437 new DeBruijnResponse("DeBruijnResponse"); 00438 00439 deBruijnResponse->setDBNode(predecessorNode); 00440 00441 int sucNum = successorList->getSize() + 1; 00442 deBruijnResponse->setSucNum(sucNum); 00443 deBruijnResponse->setSucNodeArraySize(sucNum); 00444 00445 deBruijnResponse->setSucNode(0, thisNode); 00446 for (int k = 1; k < sucNum; k++) { 00447 deBruijnResponse->setSucNode(k, successorList->getSuccessor(k-1)); 00448 } 00449 deBruijnResponse->setLength(DEBRUIJNRESPONSE_L(deBruijnResponse)); 00450 00451 sendRpcResponse(deBruijnCall, deBruijnResponse); 00452 } else if (deBruijnCall->getDestKey().isBetweenR(thisNode.key, 00453 successorList->getSuccessor().key)) { 00454 error("Koorde::handleRpcDeBruijnRequest() - unknown error."); 00455 } else { 00456 error("Koorde::handleRpcDeBruijnRequest() - " 00457 "Request couldn't be delivered!"); 00458 } 00459 }
void Koorde::handleRpcDeBruijnResponse | ( | DeBruijnResponse * | deBruijnResponse | ) | [protected, virtual] |
handle a received DEBRUIJN response
deBruijnResponse | the message to process |
00463 { 00464 int sucNum = deBruijnResponse->getSucNum(); 00465 if (sucNum > deBruijnListSize) 00466 sucNum = deBruijnListSize; 00467 00468 for (int i = 0; i < sucNum; i++) { 00469 deBruijnNodes[i] = deBruijnResponse->getSucNode(i); 00470 deBruijnNumber = i+1; 00471 } 00472 00473 deBruijnNode = deBruijnResponse->getDBNode(); 00474 00475 updateTooltip(); 00476 }
void Koorde::handleDeBruijnTimeout | ( | DeBruijnCall * | deBruijnCall | ) | [protected, virtual] |
handle a DEBRUIJN timeout
deBruijnCall | the message which timed out |
00479 { 00480 if (failedDBResponses == stabilizeRetry) { 00481 failedDBResponses = 0; 00482 deBruijnNode = NodeHandle::UNSPECIFIED_NODE; 00483 preOrSuc = !preOrSuc; 00484 } else { 00485 failedDBResponses++; 00486 } 00487 00488 updateTooltip(); 00489 cancelEvent(deBruijn_timer); 00490 scheduleAt(simulation.simTime(), deBruijn_timer); 00491 }
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 |
00566 { 00567 // check if the route key falls in our responsibility or 00568 // else forward the message to our successor 00569 if (findNodeExt->getRouteKey().isBetweenR(thisNode.key, 00570 successorList->getSuccessor().key)) { 00571 if ((unsigned int)findNodeExt->getStep() > destKey.getLength()) 00572 error("Broose::findDeBruijnHop - Bounding error: " 00573 "trying to get non existing bit out of overlay key!"); 00574 00575 // updating the route key 00576 OverlayKey add 00577 = OverlayKey(destKey.bitAtPlace(findNodeExt->getStep())); 00578 for (int i = 1; i < shiftingBits; i++) { 00579 add 00580 = (add 00581 << 1) + OverlayKey(destKey.bitAtPlace( 00582 findNodeExt->getStep()+i)); 00583 } 00584 00585 OverlayKey routeKey = (findNodeExt->getRouteKey()<<shiftingBits) + add; 00586 findNodeExt->setRouteKey(routeKey); 00587 findNodeExt->setStep(findNodeExt->getStep() + shiftingBits); 00588 00589 if(deBruijnNode.isUnspecified()) { 00590 breakLookup = true; 00591 if (useSucList) 00592 return walkSuccessorList(findNodeExt->getRouteKey()); 00593 else 00594 return successorList->getSuccessor(); 00595 } 00596 00597 // check if the new route key falls between our 00598 // de Bruijn node and its successor 00599 if (deBruijnNumber > 0) { 00600 if (findNodeExt->getRouteKey().isBetweenR(deBruijnNode.key, 00601 deBruijnNodes[0].key)) { 00602 return deBruijnNode; 00603 } else { 00604 // otherwise check if the route key falls between 00605 // our de Bruijn successors 00606 NodeHandle nextHop = walkDeBruijnList(findNodeExt-> 00607 getRouteKey()); 00608 return nextHop; 00609 } 00610 } else { 00611 return deBruijnNode; 00612 } 00613 } else { 00614 breakLookup = true; 00615 // if optimization is set search the successor list and 00616 // de bruijn node to find "good" next hop 00617 if (useSucList) { 00618 if (!deBruijnNode.isUnspecified()) { 00619 return walkSuccessorList(findNodeExt->getRouteKey()); 00620 } else { 00621 NodeHandle tmpHandle = walkSuccessorList( 00622 findNodeExt->getRouteKey()); 00623 00624 //todo: optimization - check complete deBruijnList 00625 if (deBruijnNode.key.isBetween(tmpHandle.key, 00626 findNodeExt->getRouteKey())) { 00627 return deBruijnNode; 00628 } else { 00629 return tmpHandle; 00630 } 00631 } 00632 } else 00633 return successorList->getSuccessor(); 00634 } 00635 }
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.
00497 { 00498 NodeVector* nextHop = new NodeVector(); 00499 KoordeFindNodeExtMessage *findNodeExt = NULL; 00500 00501 if (state != READY) 00502 return nextHop; 00503 00504 if (msg != NULL) { 00505 if (!msg->hasObject("findNodeExt")) { 00506 findNodeExt = new KoordeFindNodeExtMessage("findNodeExt"); 00507 00508 OverlayKey routeKey = findStartKey(thisNode.key, 00509 successorList->getSuccessor().key, key); 00510 int matchingBits = findLongestMatch(routeKey, key); 00511 findNodeExt->setRouteKey(routeKey); 00512 findNodeExt->setStep(matchingBits + 1); 00513 findNodeExt->setOtherLookup(false); 00514 findNodeExt->setLength(KOORDEFINDNODEEXTMESSAGE_L); 00515 findNodeExt->setSrcNode(thisNode); 00516 msg->addObject( findNodeExt ); 00517 } 00518 findNodeExt = (KoordeFindNodeExtMessage*) msg->getObject("findNodeExt"); 00519 } 00520 00521 if (key.isUnspecified()) { 00522 error("Koorde::findNode() - direct Messaging is no longer in use."); 00523 } else if (key.isBetweenR(predecessorNode.key, thisNode.key)) { 00524 // the message is destined for this node 00525 nextHop->push_back(thisNode); 00526 } else if (key.isBetweenR(thisNode.key, successorList->getSuccessor().key)){ 00527 // the message destined for our successor 00528 nextHop->push_back(successorList->getSuccessor()); 00529 } else { 00530 // if useOtherLookup is enabled we try to use 00531 // our successor list to get to the key 00532 if (useOtherLookup) { 00533 NodeHandle tmpNode = walkSuccessorList(key); 00534 if (tmpNode != successorList->getSuccessor( 00535 successorList->getSize()-1)) { 00536 findNodeExt->setOtherLookup(true); 00537 nextHop->push_back(tmpNode); 00538 } else if (findNodeExt->getOtherLookup() == true) { 00539 nextHop->push_back(tmpNode); 00540 } else { 00541 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt); 00542 if (tmpHandle != thisNode || breakLookup) { 00543 nextHop->push_back(tmpHandle); 00544 breakLookup = false; 00545 } else { 00546 return findNode(key, numRedundantNodes, numSiblings, msg); 00547 } 00548 } 00549 } else { 00550 // find next hop using either the de Bruijn node and 00551 // its successors or our own successors 00552 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt); 00553 if (tmpHandle != thisNode || breakLookup) { 00554 nextHop->push_back(tmpHandle); 00555 breakLookup = false; 00556 } else { 00557 return findNode(key, numRedundantNodes, numSiblings, msg); 00558 } 00559 } 00560 } 00561 return nextHop; 00562 }
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 |
00751 { 00752 OverlayKey diffKey, newStart, tmpDest, newKey, powKey; 00753 int nBits; 00754 00755 if (startKey == endKey) 00756 return startKey; 00757 00758 diffKey = endKey - startKey; 00759 nBits = diffKey.log_2(); 00760 00761 while ((startKey.getLength() - nBits) % shiftingBits != 0) { 00762 nBits--; 00763 } 00764 00765 newStart = startKey >> nBits; 00766 newStart = newStart << nBits; 00767 00768 tmpDest = destKey >> (destKey.getLength() - nBits); 00769 newKey = tmpDest + newStart; 00770 00771 // is the new constructed route key bigger than our start key return it 00772 if (newKey.isBetweenR(startKey, endKey)) { 00773 return newKey; 00774 } 00775 00776 // If the part of the destination key smaller than the one of 00777 // the orginal key add pow(nBits) (this is the first bit where 00778 // the start key and end key differ) to the new constructed key 00779 // and check if it's beetween start and end key. 00780 00781 newKey += powKey.pow2(nBits); 00782 if(newKey.isBetweenR(startKey, endKey)) { 00783 return newKey; 00784 } 00785 00786 // this part should not be called 00787 error("Koorde::findStartKey()"); 00788 return OverlayKey::UNSPECIFIED_KEY; 00789 }
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 |
00793 { 00794 int keyLength = srcKey.getLength(); 00795 bool equal = true; 00796 00797 for (int i = keyLength; i>0; i--) { 00798 equal = true; 00799 for(int j = 1; j <= i; j++) { 00800 if (srcKey.bitAtPlace(keyLength - i + j) != destKey.bitAtPlace(j)) { 00801 equal = false; 00802 break; 00803 } 00804 } 00805 00806 if (equal) 00807 return i; 00808 00809 } 00810 return 0; 00811 }
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 |
00639 { 00640 if (deBruijnNumber == 0) 00641 return NodeHandle::UNSPECIFIED_NODE; 00642 00643 for (int i = 0; i < deBruijnNumber-1; i++) { 00644 if (key.isBetweenR(deBruijnNodes[i].key,deBruijnNodes[i+1].key)) { 00645 return deBruijnNodes[i]; 00646 } 00647 } 00648 00649 return deBruijnNodes[deBruijnNumber-1]; 00650 }
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 |
00653 { 00654 for (unsigned int i = 0; i < successorList->getSize()-1; i++) { 00655 if (key.isBetweenR(successorList->getSuccessor(i).key, 00656 successorList->getSuccessor(i+1).key)) { 00657 return successorList->getSuccessor(i); 00658 } 00659 } 00660 00661 return successorList->getSuccessor(successorList->getSize()-1); 00662 }
void Koorde::handleRpcStabilizeResponse | ( | StabilizeResponse * | stabilizeResponse | ) | [protected, virtual] |
handles a received Stabilize response
stabilizeResponse | the message to process |
Reimplemented from Chord.
00319 { 00320 // our successor seems to be alive 00321 missingSuccessorStabResponses = 0; 00322 00323 // fetch the successor's predecessor 00324 NodeHandle predecessor = stabilizeResponse->getPreNode(); 00325 00326 // is the successor's predecessor a new successor for this node? 00327 if (successorList->isEmpty() || 00328 predecessor.key.isBetween(thisNode.key, 00329 successorList->getSuccessor().key)) { 00330 // add the successor's predecessor to the successor list 00331 successorList->addSuccessor(predecessor); 00332 updateTooltip(); 00333 } 00334 00335 // compile NOTIFY RPC 00336 NotifyCall* notifyCall = new NotifyCall("NotifyCall"); 00337 00338 if (!deBruijnNode.isUnspecified()) { 00339 notifyCall->setPreDBNodeSet(true); 00340 } else { 00341 notifyCall->setPreDBNodeSet(false); 00342 } 00343 00344 notifyCall->setLength(NOTIFYCALL_L(notifyCall)); 00345 sendRpcMessage(successorList->getSuccessor(), notifyCall); 00346 }
void Koorde::rpcNotify | ( | NotifyCall * | call | ) | [protected, virtual] |
handles a received Notify request
call | the message to process |
Reimplemented from Chord.
00350 { 00351 // our predecessor seems to be alive 00352 missingPredecessorStabRequests = 0; 00353 00354 NodeHandle newPredecessor = call->getSrcNode(); 00355 00356 // is the new predecessor closer than the current one? 00357 if (predecessorNode.isUnspecified() || 00358 newPredecessor.key.isBetween(predecessorNode.key, thisNode.key)) { 00359 00360 if ((predecessorNode.isUnspecified()) || 00361 (newPredecessor != predecessorNode)) { 00362 // send update to application if we've got a new predecessor 00363 if (!predecessorNode.isUnspecified()) { 00364 callUpdate(predecessorNode, false); 00365 } 00366 callUpdate(newPredecessor, true); 00367 00368 // set up new predecessor 00369 predecessorNode = newPredecessor; 00370 } 00371 00372 preDeBruijnNodeSet = call->getPreDBNodeSet(); 00373 firstTimer = false; 00374 updateTooltip(); 00375 } 00376 00377 // needed if the predecessor doesn't change 00378 if (newPredecessor == predecessorNode) 00379 preDeBruijnNodeSet = call->getPreDBNodeSet(); 00380 00381 // compile NOTIFY response 00382 NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse"); 00383 00384 int sucNum = successorList->getSize(); 00385 00386 if (deBruijnNode.isUnspecified()) { 00387 notifyResponse->setSucDBNodeSet(false); 00388 } else { 00389 notifyResponse->setSucDBNodeSet(true); 00390 } 00391 00392 notifyResponse->setSucNum(sucNum); 00393 notifyResponse->setSucNodeArraySize(sucNum); 00394 00395 for (int k = 0; k < sucNum; k++) { 00396 notifyResponse->setSucNode(k, successorList->getSuccessor(k)); 00397 } 00398 00399 notifyResponse->setLength(NOTIFYRESPONSE_L(notifyResponse)); 00400 00401 sendRpcResponse(call, notifyResponse); 00402 }
void Koorde::handleRpcNotifyResponse | ( | NotifyResponse * | notifyResponse | ) | [protected, virtual] |
handles a received Notify response
notifyResponse | the message to process |
Reimplemented from Chord.
00406 { 00407 if (successorList->getSuccessor() != notifyResponse->getSrcNode()) { 00408 EV << "[Koorde::handleRpcNotifyResponse() @ " << thisNode.ip 00409 << " (" << thisNode.key.toString(16) << ")]\n" 00410 << " The srcNode of the received NotifyResponse is not our current successor" 00411 << endl; 00412 return; 00413 } 00414 00415 // replace our successor list by our successor's successor list 00416 successorList->updateList(notifyResponse); 00417 00418 // store if the de bruijn node of my successor is set, also 00419 // reset firstTimer flag 00420 sucDeBruijnNodeSet = notifyResponse->getSucDBNodeSet(); 00421 firstTimer = false; 00422 00423 updateTooltip(); 00424 }
void Koorde::findFriendModules | ( | ) | [protected, virtual] |
Sets the pointer to the successor list module.
Reimplemented from Chord.
00814 { 00815 successorList = check_and_cast<ChordSuccessorList*> 00816 (parentModule()->submodule("successorList")); 00817 }
void Koorde::initializeFriendModules | ( | ) | [protected, virtual] |
Intializes the successor list.
Reimplemented from Chord.
00820 { 00821 // initialize successor list 00822 successorList->initializeList(par("successorListSize"), thisNode, this); 00823 }
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.
00826 { 00827 preDeBruijnNodeSet = false; 00828 //todo: this info could be used to remove predecessor node 00829 // from de bruijn successor list or even as our de bruijn node 00830 }
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.
00833 { 00834 sucDeBruijnNodeSet = false; 00835 //todo: this info could be used to remove successor node 00836 // from de bruijn successor list or even as our de bruijn node 00837 }
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] |