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