Koorde Class Reference

#include <Koorde.h>

Inheritance diagram for Koorde:

Chord BaseOverlay BaseRpc TopologyVis 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
NodeHandle
walkDeBruijnList (const OverlayKey &key)
 Given a key the function checks if the key falls between two nodes in the de Bruijn list.
virtual const
NodeHandle
walkSuccessorList (const OverlayKey &key)
 Given a key the function checks if the key falls between two nodes in the de successor list.
virtual void handleRpcStabilizeResponse (StabilizeResponse *stabilizeResponse)
 handles a received Stabilize response
virtual void rpcNotify (NotifyCall *call)
 handles a received Notify request
virtual void handleRpcNotifyResponse (NotifyResponse *notifyResponse)
 handles a received Notify response
virtual void findFriendModules ()
 Sets the pointer to the successor list module.
virtual void initializeFriendModules ()
 Intializes the successor list.
virtual void predecessorIsDead ()
 The function is called after the predecessor node is dead and resets the bit indicating the predecessor has a De-Bruijn-Node set.
virtual void successorIsDead ()
 The function is called after the successor node is dead and resets the bit indicating the successor has a De-Bruijn-Node set.

Protected Attributes

int deBruijnDelay
 number of seconds between two de Bruijn algo calls
bool pingProtocol
 enable ping protocol?
int deBruijnNumber
 number of current nodes in de Bruijn list; depend on number of nodes in successor list
int deBruijnListSize
 maximal number of nodes in de Bruijn list
int shiftingBits
 number of bits concurrently shifted in one routing step
bool fastLookup
 enable fast lookup (using successor list)?
bool sucDeBruijnNodeSet
 flag is set if our successor has a de bruijn node
bool preDeBruijnNodeSet
 flag is set if our predecessor has a de bruijn node
bool useOtherLookup
 flag which is indicating that the optimization other lookup is enabled
bool useSucList
 flag which is indicating that the optimization using the successorlist is enabled
bool breakLookup
 flag is used during the recursive step when returning this node
bool firstTimer
 indicates if this is the first de bruijn timer
int deBruijnRetryTime
 time interval when the de bruijn call times out
int failedDBResponses
 number of failed responses to a de bruijn call
bool preOrSuc
 flag which indicates if the predecessor or successor is used as a springboard
int deBruijnCount
 number of de bruijn calls
int deBruijnBytesSent
 number of bytes sent during de bruijn calls
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.

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

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from Chord.

00183 {
00184     Chord::handleUDPMessage(msg);
00185 }

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.

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

void Koorde::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from Chord.

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

void Koorde::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented from Chord.

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

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     default:
00098         break;
00099     }
00100 
00101 }

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

handle a expired join timer

Parameters:
msg the timer self-message
00116 {
00117     if (state == READY) {
00118         OverlayKey lookup = thisNode.key << shiftingBits;
00119 
00120         if (lookup.isBetweenR(thisNode.key, successorList->getSuccessor().key)
00121                 || successorList->isEmpty()) {
00122 
00123             int sucNum = successorList->getSize();
00124             if (sucNum > deBruijnListSize)
00125                 sucNum = deBruijnListSize;
00126 
00127             deBruijnNode = thisNode;
00128             for (int i = 0; i < sucNum; i++) {
00129                 deBruijnNodes[i] = successorList->getSuccessor(i);
00130                 deBruijnNumber = i+1;
00131             }
00132 
00133             updateTooltip();
00134         } else {
00135             DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
00136             call->setDestKey(lookup);
00137             call->setLength(DEBRUIJNCALL_L(call));
00138 
00139             // if we don't have a de Bruijn node we use our successor
00140             // or our predecessor as a springboard if they have their
00141             // flags set or we didn't have a chance to get it
00142             if (deBruijnNode.isUnspecified()) {
00143                 if (firstTimer || (sucDeBruijnNodeSet && !preOrSuc)) {
00144                     sendRouteRpcCall(OVERLAY_COMP,
00145                                      successorList->getSuccessor(),
00146                                      call->getDestKey(), call,
00147                                      deBruijnRetryTime);
00148                     firstTimer = false;
00149                 } else if (preOrSuc && preDeBruijnNodeSet) {
00150                     sendRouteRpcCall(OVERLAY_COMP,
00151                                      predecessorNode,
00152                                      call->getDestKey(), call,
00153                                      deBruijnRetryTime);
00154                 } else {
00155                     sendRouteRpcCall(OVERLAY_COMP, call->getDestKey(),
00156                                      call, deBruijnRetryTime);
00157                     EV << "[Koorde::handleDeBruijnTimerExpired() @ " << thisNode.ip 
00158                        << " (" << thisNode.key.toString(16) << ")]\n"
00159                        << "    Have to route DeBruijnCall to destination key"
00160                        << endl;
00161                 }
00162             } else {
00163                 sendRouteRpcCall(OVERLAY_COMP, deBruijnNode,
00164                                  call->getDestKey(), call,
00165                                  deBruijnRetryTime);
00166             }
00167 
00168         }
00169 
00170         cancelEvent(deBruijn_timer);
00171         scheduleAt(simulation.simTime() + deBruijnDelay, deBruijn_timer);
00172     }
00173 }

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

handle a expired fix_fingers timer (dummy function)

Parameters:
msg the timer self-message

Reimplemented from Chord.

00177 {
00178     // just in case not all timers from Chord code could be canceled
00179 }

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.

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

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.

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

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.

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

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

handle a received JOIN response

Parameters:
joinResponse the message to process

Reimplemented from Chord.

00314 {
00315     Chord::handleRpcJoinResponse(joinResponse);
00316 
00317     // has to be canceled in Koorde
00318     cancelEvent(fixfingers_timer);
00319 
00320     // immediate deBruijn protocol
00321     cancelEvent(deBruijn_timer);
00322     scheduleAt(simulation.simTime(), deBruijn_timer);
00323 }

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

handle a received DEBRUIJN request

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

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

handle a received DEBRUIJN response

Parameters:
deBruijnResponse the message to process
00470 {
00471     int sucNum = deBruijnResponse->getSucNum();
00472     if (sucNum > deBruijnListSize)
00473         sucNum = deBruijnListSize;
00474 
00475     for (int i = 0; i < sucNum; i++) {
00476         deBruijnNodes[i] = deBruijnResponse->getSucNode(i);
00477         deBruijnNumber = i+1;
00478     }
00479 
00480     deBruijnNode = deBruijnResponse->getDBNode();
00481 
00482     updateTooltip();
00483 }

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

handle a DEBRUIJN timeout

Parameters:
deBruijnCall the message which timed out
00486 {
00487     if (failedDBResponses == stabilizeRetry) {
00488         failedDBResponses = 0;
00489         deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
00490         preOrSuc = !preOrSuc;
00491     } else {
00492         failedDBResponses++;
00493     }
00494 
00495     updateTooltip();
00496     cancelEvent(deBruijn_timer);
00497     scheduleAt(simulation.simTime(), deBruijn_timer);
00498 }

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

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.

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

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

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
00799 {
00800     int keyLength = srcKey.getLength();
00801     bool equal = true;
00802 
00803     for (int i = keyLength; i>0; i--) {
00804         equal = true;
00805         for(int j = 1; j <= i; j++) {
00806 /*            if (srcKey.bitAtPlace(keyLength - i + j) != destKey.bitAtPlace(j)) {*/
00807             if (srcKey.get(i - j, 1) != destKey.get(destKey.getLength() - j, 1)) {
00808                 equal = false;
00809                 break;
00810             }
00811         }
00812 
00813         if (equal)
00814             return i;
00815 
00816     }
00817     return 0;
00818 }

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
00645 {
00646     if (deBruijnNumber == 0)
00647         return NodeHandle::UNSPECIFIED_NODE;
00648 
00649     for (int i = 0; i < deBruijnNumber-1; i++) {
00650         if (key.isBetweenR(deBruijnNodes[i].key,deBruijnNodes[i+1].key)) {
00651             return deBruijnNodes[i];
00652         }
00653     }
00654 
00655     return deBruijnNodes[deBruijnNumber-1];
00656 }

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
00659 {
00660     for (unsigned int i = 0; i < successorList->getSize()-1; i++) {
00661         if (key.isBetweenR(successorList->getSuccessor(i).key,
00662                            successorList->getSuccessor(i+1).key)) {
00663             return successorList->getSuccessor(i);
00664         }
00665     }
00666 
00667     return successorList->getSuccessor(successorList->getSize()-1);
00668 }

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

handles a received Stabilize response

Parameters:
stabilizeResponse the message to process

Reimplemented from Chord.

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

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

handles a received Notify request

Parameters:
call the message to process

Reimplemented from Chord.

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

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

handles a received Notify response

Parameters:
notifyResponse the message to process

Reimplemented from Chord.

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

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

Sets the pointer to the successor list module.

Reimplemented from Chord.

00821 {
00822     successorList = check_and_cast<ChordSuccessorList*>
00823                     (parentModule()->submodule("successorList"));
00824 }

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

Intializes the successor list.

Reimplemented from Chord.

00827 {
00828     // initialize successor list
00829     successorList->initializeList(par("successorListSize"), thisNode, this);
00830 }

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.

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

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.

00840 {
00841     sucDeBruijnNodeSet = false;
00842     //todo: this info could be used to remove successor node
00843     //      from de bruijn successor list or even as our de bruijn node
00844 }


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 Thu Apr 17 13:19:29 2008 for ITM OverSim by  doxygen 1.5.3