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