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 *msg)
 Processes "timer" self-messages.
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
virtual void recordOverlaySentStats (BaseOverlayMessage *msg)
 Collect overlay specific sent messages statistics.
virtual void finishOverlay ()
 collects statistical data in derived class
virtual void updateTooltip ()
 updates information shown in tk-environment

Protected Member Functions

virtual void changeState (int state)
 changes node state
virtual void handleDeBruijnTimerExpired (cMessage *msg)
 handle a expired join timer
virtual void handleFixFingersTimerExpired (cMessage *msg)
 handle a expired fix_fingers timer (dummy function)
virtual bool handleRpc (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invokation messages.
virtual void handleRpcResponse (BaseResponseMessage *msg, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
virtual void handleRpcJoinResponse (JoinResponse *joinResponse)
 handle a received JOIN response
virtual void handleRpcDeBruijnRequest (DeBruijnCall *deBruinCall)
 handle a received DEBRUIJN request
virtual void handleRpcDeBruijnResponse (DeBruijnResponse *deBruijnResponse)
 handle a received DEBRUIJN response
virtual void handleDeBruijnTimeout (DeBruijnCall *deBruijnCall)
 handle a DEBRUIJN timeout
virtual NodeHandle findDeBruijnHop (const OverlayKey &destKey, KoordeFindNodeExtMessage *findNodeExt)
 returns the NodeHandle of the next hop to destination key using the de Bruijn list
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 *  msg  )  [virtual]

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from Chord.

00102 {
00103     // catch DeBruijn timer
00104     if (msg->isName("deBruijn_timer"))
00105         handleDeBruijnTimerExpired(msg);
00106     else if (msg->isName("fixfingers_timer"))
00107         handleFixFingersTimerExpired(msg);
00108     else
00109         Chord::handleTimerEvent(msg);
00110 }

void Koorde::handleUDPMessage ( BaseOverlayMessage *  msg  )  [virtual]

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from Chord.

00176 {
00177     Chord::handleUDPMessage(msg);
00178 }

void Koorde::recordOverlaySentStats ( BaseOverlayMessage *  msg  )  [virtual]

Collect overlay specific sent messages statistics.

This method is called from BaseOverlay::sendMessageToUDP() for every overlay message that is sent by a node. Use this to collect statistical data for overlay protocol specific message types.

Parameters:
msg The overlay message to be sent to the UDP layer

Reimplemented from Chord.

00725 {
00726     Chord::recordOverlaySentStats(msg);
00727 
00728     BaseOverlayMessage* innerMsg;
00729 
00730     if (msg->getType() == OVERLAYROUTE)
00731         innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg());
00732     else
00733         innerMsg = msg;
00734 
00735     switch (innerMsg->getType()) {
00736 
00737     case RPC: {
00738             if ((dynamic_cast<DeBruijnCall*>(innerMsg) != NULL) ||
00739                     (dynamic_cast<DeBruijnResponse*>(innerMsg) != NULL)) {
00740                 RECORD_STATS(deBruijnCount++; deBruijnBytesSent +=
00741                                  msg->byteLength());
00742             }
00743             break;
00744         }
00745     }
00746 }

void Koorde::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from Chord.

00707 {
00708     // destroy self timer messages
00709     cancelEvent(deBruijn_timer);
00710 
00711     delete deBruijn_timer;
00712 
00713     // statistics
00714     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00715 
00716     if(time != 0) {    
00717         globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Messages/s", deBruijnCount / time);
00718         globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Bytes/s", deBruijnBytesSent / time);
00719     }
00720 
00721     Chord::finishOverlay();
00722 }

void Koorde::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented from Chord.

00665 {
00666     //
00667     // Updates the tooltip display strings.
00668     //
00669 
00670     if (ev.isGUI()) {
00671         std::stringstream ttString;
00672 
00673         // show our predecessor, successor and de Bruijn node in tooltip
00674         ttString << "Pred "<< predecessorNode << endl << "This  "
00675                  << thisNode << endl
00676                  << "Suc   " << successorList->getSuccessor() << endl
00677                  << "DeBr " << deBruijnNode << endl;
00678         ttString << "List ";
00679 
00680         for (unsigned int i = 0; i < successorList->getSize(); i++) {
00681             ttString << successorList->getSuccessor(i).ip << " ";
00682         }
00683 
00684         ttString << endl;
00685         ttString << "DList ";
00686 
00687         for (int i = 0; i < deBruijnNumber; i++) {
00688             ttString << deBruijnNodes[i].ip << " ";
00689         }
00690 
00691         ttString << endl;
00692 
00693         parentModule()->parentModule()->displayString().setTagArg(
00694             "tt", 0, ttString.str().c_str());
00695         parentModule()->displayString().setTagArg("tt", 0,
00696                 ttString.str().c_str());
00697         displayString().setTagArg("tt", 0, ttString.str().c_str());
00698 
00699         // draw an arrow to our current successor
00700         showOverlayNeighborArrow(successorList->getSuccessor(), true,
00701                                  "m=m,50,0,50,0;o=red,1");
00702     }
00703 }

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

changes node state

Parameters:
state state to change to

Reimplemented from Chord.

00078 {
00079     Chord::changeState(toState);
00080 
00081     switch(state) {
00082     case INIT:
00083         // init de Bruijn nodes
00084         deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
00085         for (int i=0; i < deBruijnListSize; i++)
00086             deBruijnNodes[i] = NodeHandle::UNSPECIFIED_NODE;
00087         updateTooltip();
00088         break;
00089     case READY:
00090         // init de Bruijn Protocol
00091         cancelEvent(deBruijn_timer);
00092         scheduleAt(simulation.simTime() + deBruijnDelay, deBruijn_timer);
00093 
00094         // since we don't need the fixfingers protocol in Koorde cancel timer
00095         cancelEvent(fixfingers_timer);
00096         break;
00097     }
00098 
00099 }

void Koorde::handleDeBruijnTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired join timer

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() @ " << thisNode.ip 
00152                        << " (" << thisNode.key.toString(16) << ")]\n"
00153                        << "    Have to route DeBruijnCall to destination key"
00154                        << endl;
00155                 }
00156             } else {
00157                 sendRpcMessage(deBruijnNode, call, NULL, call->getDestKey(),
00158                                -1, deBruijnRetryTime);
00159             }
00160 
00161         }
00162 
00163         cancelEvent(deBruijn_timer);
00164         scheduleAt(simulation.simTime() + deBruijnDelay, deBruijn_timer);
00165     }
00166 }

void Koorde::handleFixFingersTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired fix_fingers timer (dummy function)

Parameters:
msg the timer self-message

Reimplemented from Chord.

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

bool Koorde::handleRpc ( BaseCallMessage *  msg  )  [protected, virtual]

Processes Remote-Procedure-Call invokation messages.


This method should be overloaded when the overlay provides RPC functionality.

Returns:
true, if rpc has been handled

Reimplemented from Chord.

00182 {
00183     if (state != READY) {
00184         //EV << "[Koorde::handleRpc() @ " << thisNode.ip 
00185         //   << " (" << thisNode.key.toString(16) << ")]\n"
00186         //   << "    Received RPC call and state != READY!"
00187         //   << endl;
00188         //cout << "RPC in non-Ready state received!" << endl;
00189         return false;
00190     }
00191 
00192     // delegate messages
00193     RPC_SWITCH_START( msg )
00194     // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
00195     RPC_DELEGATE( Join, rpcJoin );
00196     RPC_DELEGATE( Notify, rpcNotify );
00197     RPC_DELEGATE( Stabilize, rpcStabilize );
00198     RPC_DELEGATE( Fixfingers, rpcFixfingers );
00199     RPC_DELEGATE( DeBruijn, handleRpcDeBruijnRequest );
00200     RPC_SWITCH_END( )
00201 
00202     return RPC_HANDLED;    
00203 }

void Koorde::handleRpcResponse ( BaseResponseMessage *  msg,
int  rpcId,
simtime_t  rtt 
) [protected, virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from Chord.

00207 {
00208     RPC_SWITCH_START(msg)
00209     RPC_ON_RESPONSE( Join ) {
00210         handleRpcJoinResponse(_JoinResponse);
00211         EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 
00212            << " (" << thisNode.key.toString(16) << ")]\n"
00213            << "    Join RPC Response received: id=" << rpcId
00214            << "\n    msg=" << *_JoinResponse << " rtt=" << rtt
00215            << endl;
00216         break;
00217     }
00218     RPC_ON_RESPONSE( Notify ) {
00219         handleRpcNotifyResponse(_NotifyResponse);
00220         EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 
00221            << " (" << thisNode.key.toString(16) << ")]\n"
00222            << "    Notify RPC Response received: id=" << rpcId
00223            << "\n    msg=" << *_NotifyResponse << " rtt=" << rtt
00224            << endl;
00225         break;
00226     }
00227     RPC_ON_RESPONSE( Stabilize ) {
00228         handleRpcStabilizeResponse(_StabilizeResponse);
00229         EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 
00230            << " (" << thisNode.key.toString(16) << ")]\n"
00231            << "    Stabilize RPC Response received: id=" << rpcId
00232            << "\n    msg=" << *_StabilizeResponse << " rtt=" << rtt
00233            << endl;
00234         break;
00235     }
00236     RPC_ON_RESPONSE( Fixfingers ) {
00237         handleRpcFixfingersResponse(_FixfingersResponse);
00238         EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 
00239            << " (" << thisNode.key.toString(16) << ")]\n"
00240            << "    Fixfingers RPC Response received: id=" << rpcId
00241            << "\n    msg=" << *_FixfingersResponse << " rtt=" << rtt
00242            << endl;
00243         break;
00244     }
00245     RPC_ON_RESPONSE( DeBruijn ) {
00246         handleRpcDeBruijnResponse(_DeBruijnResponse);
00247         EV << "[Koorde::handleRpcResponse() @ " << thisNode.ip 
00248            << " (" << thisNode.key.toString(16) << ")]\n"
00249            << "    DeBruijn RPC Response received: id=" << rpcId
00250            << "\n    msg=" << *_DeBruijnResponse << " rtt=" << rtt
00251            << endl;
00252         break;
00253     }
00254     RPC_SWITCH_END( )
00255 }

void Koorde::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
int  rpcId,
const OverlayKey destKey 
) [protected, virtual]

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from Chord.

00259 {
00260     RPC_SWITCH_START(msg)
00261     RPC_ON_CALL( Join ) {
00262         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 
00263            << " (" << thisNode.key.toString(16) << ")]\n"
00264            << "    Join RPC Call timed out: id=" << rpcId
00265            << "\n    msg=" << *_JoinCall
00266            << endl;
00267         break;
00268     }
00269     RPC_ON_CALL( Notify ) {
00270         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 
00271            << " (" << thisNode.key.toString(16) << ")]\n"
00272            << "    Notify RPC Call timed out: id=" << rpcId
00273            << "\n    msg=" << *_NotifyCall
00274            << endl;
00275         break;
00276     }
00277     RPC_ON_CALL( Stabilize ) {
00278         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 
00279            << " (" << thisNode.key.toString(16) << ")]\n"
00280            << "    Stabilize RPC Call timed out: id=" << rpcId
00281            << "\n    msg=" << *_StabilizeCall
00282            << endl;
00283         break;
00284     }
00285     RPC_ON_CALL( Fixfingers ) {
00286         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 
00287            << " (" << thisNode.key.toString(16) << ")]\n"
00288            << "    Fixfingers RPC Call timed out: id=" << rpcId
00289            << "\n    msg=" << *_FixfingersCall
00290            << endl;
00291         break;
00292     }
00293     RPC_ON_CALL( DeBruijn ) {
00294         handleDeBruijnTimeout(_DeBruijnCall);
00295         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.ip 
00296            << " (" << thisNode.key.toString(16) << ")]\n"
00297            << "    DeBruijn RPC Call timed out: id=" << rpcId
00298            << "\n    msg=" << *_DeBruijnCall
00299            << endl;
00300         break;
00301     }
00302     RPC_SWITCH_END( )
00303 }

void Koorde::handleRpcJoinResponse ( JoinResponse *  joinResponse  )  [protected, virtual]

handle a received JOIN response

Parameters:
joinResponse the message to process

Reimplemented from Chord.

00307 {
00308     Chord::handleRpcJoinResponse(joinResponse);
00309 
00310     // has to be canceled in Koorde
00311     cancelEvent(fixfingers_timer);
00312 
00313     // immediate deBruijn protocol
00314     cancelEvent(deBruijn_timer);
00315     scheduleAt(simulation.simTime(), deBruijn_timer);
00316 }

void Koorde::handleRpcDeBruijnRequest ( DeBruijnCall *  deBruinCall  )  [protected, virtual]

handle a received DEBRUIJN request

Parameters:
deBruinCall the message to process
00429 {
00430     // The key lies between thisNode and its predecessor and
00431     // because routing the message to the predecessor of a key
00432     // is near to impossible we set the deBruijnNodes here
00433     // and the information is as actual as the predecessor pointer
00434     if (deBruijnCall->getDestKey().isBetweenR(predecessorNode.key,
00435             thisNode.key)) {
00436         DeBruijnResponse* deBruijnResponse =
00437             new DeBruijnResponse("DeBruijnResponse");
00438 
00439         deBruijnResponse->setDBNode(predecessorNode);
00440 
00441         int sucNum = successorList->getSize() + 1;
00442         deBruijnResponse->setSucNum(sucNum);
00443         deBruijnResponse->setSucNodeArraySize(sucNum);
00444 
00445         deBruijnResponse->setSucNode(0, thisNode);
00446         for (int k = 1; k < sucNum; k++) {
00447             deBruijnResponse->setSucNode(k, successorList->getSuccessor(k-1));
00448         }
00449         deBruijnResponse->setLength(DEBRUIJNRESPONSE_L(deBruijnResponse));
00450 
00451         sendRpcResponse(deBruijnCall, deBruijnResponse);
00452     } else if (deBruijnCall->getDestKey().isBetweenR(thisNode.key,
00453                successorList->getSuccessor().key)) {
00454         error("Koorde::handleRpcDeBruijnRequest() - unknown error.");
00455     } else {
00456         error("Koorde::handleRpcDeBruijnRequest() - "
00457               "Request couldn't be delivered!");
00458     }
00459 }

void Koorde::handleRpcDeBruijnResponse ( DeBruijnResponse *  deBruijnResponse  )  [protected, virtual]

handle a received DEBRUIJN response

Parameters:
deBruijnResponse the message to process
00463 {
00464     int sucNum = deBruijnResponse->getSucNum();
00465     if (sucNum > deBruijnListSize)
00466         sucNum = deBruijnListSize;
00467 
00468     for (int i = 0; i < sucNum; i++) {
00469         deBruijnNodes[i] = deBruijnResponse->getSucNode(i);
00470         deBruijnNumber = i+1;
00471     }
00472 
00473     deBruijnNode = deBruijnResponse->getDBNode();
00474 
00475     updateTooltip();
00476 }

void Koorde::handleDeBruijnTimeout ( DeBruijnCall *  deBruijnCall  )  [protected, virtual]

handle a DEBRUIJN timeout

Parameters:
deBruijnCall the message which timed out
00479 {
00480     if (failedDBResponses == stabilizeRetry) {
00481         failedDBResponses = 0;
00482         deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
00483         preOrSuc = !preOrSuc;
00484     } else {
00485         failedDBResponses++;
00486     }
00487 
00488     updateTooltip();
00489     cancelEvent(deBruijn_timer);
00490     scheduleAt(simulation.simTime(), deBruijn_timer);
00491 }

NodeHandle Koorde::findDeBruijnHop ( const OverlayKey destKey,
KoordeFindNodeExtMessage *  findNodeExt 
) [protected, virtual]

returns the NodeHandle of the next hop to destination key using the de Bruijn list

Parameters:
destKey The destination key
findNodeExt The FindNodeExtensionMessage
Returns:
next hop to destination key
00566 {
00567     // check if the route key falls in our responsibility or
00568     // else forward the message to our successor
00569     if (findNodeExt->getRouteKey().isBetweenR(thisNode.key,
00570             successorList->getSuccessor().key)) {
00571         if ((unsigned int)findNodeExt->getStep() > destKey.getLength())
00572             error("Broose::findDeBruijnHop - Bounding error: "
00573                   "trying to get non existing bit out of overlay key!");
00574 
00575         // updating the route key
00576         OverlayKey add
00577             = OverlayKey(destKey.bitAtPlace(findNodeExt->getStep()));
00578         for (int i = 1; i < shiftingBits; i++) {
00579             add
00580                 = (add
00581                    << 1) + OverlayKey(destKey.bitAtPlace(
00582                                           findNodeExt->getStep()+i));
00583         }
00584 
00585         OverlayKey routeKey = (findNodeExt->getRouteKey()<<shiftingBits) + add;
00586         findNodeExt->setRouteKey(routeKey);
00587         findNodeExt->setStep(findNodeExt->getStep() + shiftingBits);
00588 
00589         if(deBruijnNode.isUnspecified()) {
00590             breakLookup = true;
00591             if (useSucList)
00592                 return walkSuccessorList(findNodeExt->getRouteKey());
00593             else
00594                 return successorList->getSuccessor();
00595         }
00596 
00597         // check if the new route key falls between our
00598         // de Bruijn node and its successor
00599         if (deBruijnNumber > 0) {
00600             if (findNodeExt->getRouteKey().isBetweenR(deBruijnNode.key,
00601                     deBruijnNodes[0].key)) {
00602                 return deBruijnNode;
00603             } else {
00604                 // otherwise check if the route key falls between
00605                 // our de Bruijn successors
00606                 NodeHandle nextHop = walkDeBruijnList(findNodeExt->
00607                                                       getRouteKey());
00608                 return nextHop;
00609             }
00610         } else {
00611             return deBruijnNode;
00612         }
00613     } else {
00614         breakLookup = true;
00615         // if optimization is set search the successor list and
00616         // de bruijn node to find "good" next hop
00617         if (useSucList) {
00618             if (!deBruijnNode.isUnspecified()) {
00619                 return walkSuccessorList(findNodeExt->getRouteKey());
00620             } else {
00621                 NodeHandle tmpHandle = walkSuccessorList(
00622                                                  findNodeExt->getRouteKey());
00623 
00624                 //todo: optimization - check complete deBruijnList
00625                 if (deBruijnNode.key.isBetween(tmpHandle.key,
00626                                                findNodeExt->getRouteKey())) {
00627                     return deBruijnNode;
00628                 } else {
00629                     return tmpHandle;
00630                 }
00631             }
00632         } else
00633             return successorList->getSuccessor();
00634     }
00635 }

NodeVector * Koorde::findNode ( const OverlayKey key,
int  numRedundantNodes,
int  numSiblings,
BaseOverlayMessage *  msg 
) [protected, virtual]

Implements the find node call.

This method simply returns the closest nodes known in the corresponding routing topology. If the node is a sibling for this key (isSiblingFor(key) = true), this method returns all numSiblings siblings, with the closest neighbor to the key first.

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.

00497 {
00498     NodeVector* nextHop = new NodeVector();
00499     KoordeFindNodeExtMessage *findNodeExt = NULL;
00500 
00501     if (state != READY)
00502         return nextHop;
00503 
00504     if (msg != NULL) {
00505         if (!msg->hasObject("findNodeExt")) {
00506             findNodeExt = new KoordeFindNodeExtMessage("findNodeExt");
00507 
00508             OverlayKey routeKey = findStartKey(thisNode.key,
00509                                      successorList->getSuccessor().key, key);
00510             int matchingBits = findLongestMatch(routeKey, key);
00511             findNodeExt->setRouteKey(routeKey);
00512             findNodeExt->setStep(matchingBits + 1);
00513             findNodeExt->setOtherLookup(false);
00514             findNodeExt->setLength(KOORDEFINDNODEEXTMESSAGE_L);
00515             findNodeExt->setSrcNode(thisNode);
00516             msg->addObject( findNodeExt );
00517         }
00518         findNodeExt = (KoordeFindNodeExtMessage*) msg->getObject("findNodeExt");
00519     }
00520 
00521     if (key.isUnspecified()) {
00522         error("Koorde::findNode() - direct Messaging is no longer in use.");
00523     } else if (key.isBetweenR(predecessorNode.key, thisNode.key)) {
00524         // the message is destined for this node
00525         nextHop->push_back(thisNode);
00526     } else if (key.isBetweenR(thisNode.key, successorList->getSuccessor().key)){
00527         // the message destined for our successor
00528         nextHop->push_back(successorList->getSuccessor());
00529     } else {
00530         // if useOtherLookup is enabled we try to use
00531         // our successor list to get to the key
00532         if (useOtherLookup) {
00533             NodeHandle tmpNode = walkSuccessorList(key);
00534             if (tmpNode != successorList->getSuccessor(
00535                                              successorList->getSize()-1)) {
00536                 findNodeExt->setOtherLookup(true);
00537                 nextHop->push_back(tmpNode);
00538             } else if (findNodeExt->getOtherLookup() == true) {
00539                 nextHop->push_back(tmpNode);
00540             } else {
00541                 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
00542                 if (tmpHandle != thisNode || breakLookup) {
00543                     nextHop->push_back(tmpHandle);
00544                     breakLookup = false;
00545                 } else {
00546                     return findNode(key, numRedundantNodes, numSiblings, msg);
00547                 }
00548             }
00549         } else {
00550             // find next hop using either the de Bruijn node and
00551             // its successors or our own successors
00552             NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
00553             if (tmpHandle != thisNode || breakLookup) {
00554                 nextHop->push_back(tmpHandle);
00555                 breakLookup = false;
00556             } else {
00557                 return findNode(key, numRedundantNodes, numSiblings, msg);
00558             }
00559         }
00560     }
00561     return nextHop;
00562 }

OverlayKey Koorde::findStartKey ( const OverlayKey startKey,
const OverlayKey endKey,
const OverlayKey destKey 
) [protected, virtual]

find a "good" routing key to destKey between startingKey and endKey with the longest matching prefix possible

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
00751 {
00752     OverlayKey diffKey, newStart, tmpDest, newKey, powKey;
00753     int nBits;
00754 
00755     if (startKey == endKey)
00756         return startKey;
00757 
00758     diffKey = endKey - startKey;
00759     nBits = diffKey.log_2();
00760 
00761     while ((startKey.getLength() - nBits) % shiftingBits != 0) {
00762         nBits--;
00763     }
00764 
00765     newStart = startKey >> nBits;
00766     newStart = newStart << nBits;
00767 
00768     tmpDest = destKey >> (destKey.getLength() - nBits);
00769     newKey = tmpDest + newStart;
00770 
00771     // is the new constructed route key bigger than our start key return it
00772     if (newKey.isBetweenR(startKey, endKey)) {
00773         return newKey;
00774     }
00775 
00776     // If the part of the destination key smaller than the one of
00777     // the orginal key add pow(nBits) (this is the first bit where
00778     // the start key and end key differ) to the new constructed key
00779     // and check if it's beetween start and end key.
00780 
00781     newKey += powKey.pow2(nBits);
00782     if(newKey.isBetweenR(startKey, endKey)) {
00783         return newKey;
00784     }
00785 
00786     // this part should not be called
00787     error("Koorde::findStartKey()");
00788     return OverlayKey::UNSPECIFIED_KEY;
00789 }

int Koorde::findLongestMatch ( const OverlayKey srcKey,
const OverlayKey destKey 
) [protected, virtual]

find maximal number of bits in which two keys match using right shifting

Parameters:
srcKey the source key
destKey the destination key
Returns:
number of matching bits
00793 {
00794     int keyLength = srcKey.getLength();
00795     bool equal = true;
00796 
00797     for (int i = keyLength; i>0; i--) {
00798         equal = true;
00799         for(int j = 1; j <= i; j++) {
00800             if (srcKey.bitAtPlace(keyLength - i + j) != destKey.bitAtPlace(j)) {
00801                 equal = false;
00802                 break;
00803             }
00804         }
00805 
00806         if (equal)
00807             return i;
00808 
00809     }
00810     return 0;
00811 }

const NodeHandle & Koorde::walkDeBruijnList ( const OverlayKey key  )  [protected, virtual]

Given a key the function checks if the key falls between two nodes in the de Bruijn list.

If no match is found the last node in the de Bruijn list is returned.

Parameters:
key the key to check
Returns:
either the node directly preceding key or the node which has the shortest distance to the key
00639 {
00640     if (deBruijnNumber == 0)
00641         return NodeHandle::UNSPECIFIED_NODE;
00642 
00643     for (int i = 0; i < deBruijnNumber-1; i++) {
00644         if (key.isBetweenR(deBruijnNodes[i].key,deBruijnNodes[i+1].key)) {
00645             return deBruijnNodes[i];
00646         }
00647     }
00648 
00649     return deBruijnNodes[deBruijnNumber-1];
00650 }

const NodeHandle & Koorde::walkSuccessorList ( const OverlayKey key  )  [protected, virtual]

Given a key the function checks if the key falls between two nodes in the de successor list.

If no match is found the last node in the de successor list is returned.

Parameters:
key the key to check
Returns:
either the node directly preceding key or the node which has the shortest distance to the key
00653 {
00654     for (unsigned int i = 0; i < successorList->getSize()-1; i++) {
00655         if (key.isBetweenR(successorList->getSuccessor(i).key,
00656                            successorList->getSuccessor(i+1).key)) {
00657             return successorList->getSuccessor(i);
00658         }
00659     }
00660 
00661     return successorList->getSuccessor(successorList->getSize()-1);
00662 }

void Koorde::handleRpcStabilizeResponse ( StabilizeResponse *  stabilizeResponse  )  [protected, virtual]

handles a received Stabilize response

Parameters:
stabilizeResponse the message to process

Reimplemented from Chord.

00319 {
00320     // our successor seems to be alive
00321     missingSuccessorStabResponses = 0;
00322 
00323     // fetch the successor's predecessor
00324     NodeHandle predecessor = stabilizeResponse->getPreNode();
00325 
00326     // is the successor's predecessor a new successor for this node?
00327     if (successorList->isEmpty() ||
00328             predecessor.key.isBetween(thisNode.key,
00329                                       successorList->getSuccessor().key)) {
00330         // add the successor's predecessor to the successor list
00331         successorList->addSuccessor(predecessor);
00332         updateTooltip();
00333     }
00334 
00335     // compile NOTIFY RPC
00336     NotifyCall* notifyCall = new NotifyCall("NotifyCall");
00337 
00338     if (!deBruijnNode.isUnspecified()) {
00339         notifyCall->setPreDBNodeSet(true);
00340     } else {
00341         notifyCall->setPreDBNodeSet(false);
00342     }
00343 
00344     notifyCall->setLength(NOTIFYCALL_L(notifyCall));
00345     sendRpcMessage(successorList->getSuccessor(), notifyCall);
00346 }

void Koorde::rpcNotify ( NotifyCall *  call  )  [protected, virtual]

handles a received Notify request

Parameters:
call the message to process

Reimplemented from Chord.

00350 {
00351     // our predecessor seems to be alive
00352     missingPredecessorStabRequests = 0;
00353 
00354     NodeHandle newPredecessor = call->getSrcNode();
00355 
00356     // is the new predecessor closer than the current one?
00357     if (predecessorNode.isUnspecified() ||
00358             newPredecessor.key.isBetween(predecessorNode.key, thisNode.key)) {
00359 
00360         if ((predecessorNode.isUnspecified()) ||
00361             (newPredecessor != predecessorNode)) {
00362             // send update to application if we've got a new predecessor
00363             if (!predecessorNode.isUnspecified()) {
00364                 callUpdate(predecessorNode, false);
00365             }
00366             callUpdate(newPredecessor, true);
00367             
00368             // set up new predecessor
00369             predecessorNode = newPredecessor;
00370         }
00371 
00372         preDeBruijnNodeSet = call->getPreDBNodeSet();
00373         firstTimer = false;
00374         updateTooltip();
00375     }
00376 
00377     // needed if the predecessor doesn't change
00378     if (newPredecessor == predecessorNode)
00379         preDeBruijnNodeSet = call->getPreDBNodeSet();
00380 
00381     // compile NOTIFY response
00382     NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
00383 
00384     int sucNum = successorList->getSize();
00385 
00386     if (deBruijnNode.isUnspecified()) {
00387         notifyResponse->setSucDBNodeSet(false);
00388     } else {
00389         notifyResponse->setSucDBNodeSet(true);
00390     }
00391 
00392     notifyResponse->setSucNum(sucNum);
00393     notifyResponse->setSucNodeArraySize(sucNum);
00394 
00395     for (int k = 0; k < sucNum; k++) {
00396         notifyResponse->setSucNode(k, successorList->getSuccessor(k));
00397     }
00398 
00399     notifyResponse->setLength(NOTIFYRESPONSE_L(notifyResponse));
00400 
00401     sendRpcResponse(call, notifyResponse);
00402 }

void Koorde::handleRpcNotifyResponse ( NotifyResponse *  notifyResponse  )  [protected, virtual]

handles a received Notify response

Parameters:
notifyResponse the message to process

Reimplemented from Chord.

00406 {
00407     if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
00408         EV << "[Koorde::handleRpcNotifyResponse() @ " << thisNode.ip 
00409            << " (" << thisNode.key.toString(16) << ")]\n"
00410            << "    The srcNode of the received NotifyResponse is not our current successor"
00411            << endl;
00412         return;
00413     }
00414 
00415     // replace our successor list by our successor's successor list
00416     successorList->updateList(notifyResponse);
00417 
00418     // store if the de bruijn node of my successor is set, also
00419     // reset firstTimer flag
00420     sucDeBruijnNodeSet = notifyResponse->getSucDBNodeSet();
00421     firstTimer = false;
00422 
00423     updateTooltip();
00424 }

void Koorde::findFriendModules (  )  [protected, virtual]

Sets the pointer to the successor list module.

Reimplemented from Chord.

00814 {
00815     successorList = check_and_cast<ChordSuccessorList*>
00816                     (parentModule()->submodule("successorList"));
00817 }

void Koorde::initializeFriendModules (  )  [protected, virtual]

Intializes the successor list.

Reimplemented from Chord.

00820 {
00821     // initialize successor list
00822     successorList->initializeList(par("successorListSize"), thisNode, this);
00823 }

void Koorde::predecessorIsDead (  )  [protected, virtual]

The function is called after the predecessor node is dead and resets the bit indicating the predecessor has a De-Bruijn-Node set.

Reimplemented from Chord.

00826 {
00827     preDeBruijnNodeSet = false;
00828     //todo: this info could be used to remove predecessor node
00829     //      from de bruijn successor list or even as our de bruijn node
00830 }

void Koorde::successorIsDead (  )  [protected, virtual]

The function is called after the successor node is dead and resets the bit indicating the successor has a De-Bruijn-Node set.

Reimplemented from Chord.

00833 {
00834     sucDeBruijnNodeSet = false;
00835     //todo: this info could be used to remove successor node
00836     //      from de bruijn successor list or even as our de bruijn node
00837 }


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 Wed Sep 26 12:13:01 2007 for ITM OverSim by  doxygen 1.5.1