Koorde Class Reference

#include <Koorde.h>

Inheritance diagram for Koorde:

Chord BaseOverlay BaseRpc 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 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
NodeVectorfindNode (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 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::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 }

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::recordOverlaySentStats ( BaseOverlayMessage *  msg  )  [virtual]

collects statistics

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

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 }

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 }

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.

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

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

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

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

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

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

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

Parameters:
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.
Returns:
NodeVector with closest nodes.

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

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

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

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

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

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

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

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


Member Data Documentation

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]


The documentation for this class was generated from the following files:
Generated on Tue Jul 24 16:51:18 2007 for ITM OverSim by  doxygen 1.5.1