Koorde Class Reference

#include <Koorde.h>

Inheritance diagram for Koorde:

Chord BaseOverlay RpcListener List of all members.

Detailed Description

Koorde overlay module.

Implementation of the Koorde KBR overlay as described in "Koorde: A simple degree-optimal distributed hash table" by M. Kaashoek and D. Karger

Author:
Jochen Schenk
See also:
Chord, ChordSuccessorList


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
NodeVectorfindNode (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 NodeHandlewalkDeBruijnList (const OverlayKey &key)
 Given a key the function checks if the key falls between two nodes in the de Bruijn list.
virtual const NodeHandlewalkSuccessorList (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
NodeHandledeBruijnNodes
 List of de Bruijn nodes.
NodeHandle deBruijnNode
 Handle to our de Bruijn node.
cMessage * deBruijn_timer


Member Function Documentation

void Koorde::changeState ( int  state  )  [protected, virtual]

changes node state

Parameters:
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

Parameters:
destKey The destination key
findNodeExt The FindNodeExtensionMessage
Returns:
next hop to destination key
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

Parameters:
srcKey the source key
destKey the destination key
Returns:
number of matching bits
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.

Parameters:
key The lookup key.
contextPtr A pointer to the BaseRouteMessage or FindNodeCall message of this lookup.
Returns:
NodeVector with closest nodes.

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

Parameters:
startKey begin of the (key) interval
endKey end of the (key) interval
destKey destination key - should be matched as good as possible
Returns:
a "good" routing key to start from
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

Parameters:
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

Parameters:
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)

Parameters:
msg the timer self-message

Reimplemented from Chord.

00169 {
00170     // just in case not all timers from Chord code could be canceled
00171 }

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

Parameters:
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

Parameters:
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

Parameters:
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

Parameters:
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.

Parameters:
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

Parameters:
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.

Parameters:
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

Parameters:
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

Parameters:
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.

Parameters:
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]

Sets init stage.

See also:
InitStages.h

Reimplemented from BaseOverlay.

00052     {
00053         return 6;
00054     }

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

Parameters:
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

Parameters:
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.

Parameters:
key the key to check
Returns:
either the node directly preceding key or the node which has the shortest distance to the key
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.

Parameters:
key the key to check
Returns:
either the node directly preceding key or the node which has the shortest distance to the key
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 }


Member Data Documentation

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


The documentation for this class was generated from the following files:
Generated on Fri May 11 14:52:40 2007 for ITM OverSim by  doxygen 1.4.7