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, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, 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.

00037 {
00038     // because of IPAddressResolver, we need to wait until interfaces
00039     // are registered, address auto-assignment takes place etc.
00040     if(stage != MIN_STAGE_OVERLAY)
00041         return;
00042 
00043     // fetch some parameters
00044     deBruijnDelay = par("deBruijnDelay");
00045     deBruijnListSize = par("deBruijnListSize");
00046     shiftingBits = par("shiftingBits");
00047     useOtherLookup = par("useOtherLookup");
00048     useSucList = par("useSucList");
00049 
00050     // init flags
00051     sucDeBruijnNodeSet = false;
00052     preDeBruijnNodeSet = false;
00053     breakLookup = false;
00054     firstTimer = true;
00055     preOrSuc = false;
00056 
00057     // some local variables
00058     failedDBResponses = 0;
00059     deBruijnRetryTime = 20;
00060     deBruijnNumber = 0;
00061     deBruijnNodes = new NodeHandle[deBruijnListSize];
00062 
00063     // statistics
00064     deBruijnCount = 0;
00065     deBruijnBytesSent = 0;
00066 
00067     // add some watches
00068     WATCH(sucDeBruijnNodeSet);
00069     WATCH(deBruijnNumber);
00070     WATCH(deBruijnNode);
00071 
00072     //timer Messages
00073     deBruijn_timer = new cMessage("deBruijn_timer");
00074 
00075     Chord::initializeOverlay(stage);
00076 }

void Koorde::handleTimerEvent ( cMessage *  msg  )  [virtual]

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from Chord.

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

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from Chord.

00186 {
00187     Chord::handleUDPMessage(msg);
00188 }

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.

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

void Koorde::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from Chord.

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

void Koorde::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented from Chord.

Referenced by changeState(), handleDeBruijnTimeout(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), handleRpcNotifyResponse(), handleRpcStabilizeResponse(), and rpcNotify().

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

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

changes node state

Parameters:
state state to change to

Reimplemented from Chord.

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

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

handle a expired join timer

Parameters:
msg the timer self-message

Referenced by handleTimerEvent().

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

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

handle a expired fix_fingers timer (dummy function)

Parameters:
msg the timer self-message

Reimplemented from Chord.

Referenced by handleTimerEvent().

00180 {
00181     // just in case not all timers from Chord code could be canceled
00182 }

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.

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

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

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

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from Chord.

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

void Koorde::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
cPolymorphic *  context,
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
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from Chord.

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

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

handle a received JOIN response

Parameters:
joinResponse the message to process

Reimplemented from Chord.

Referenced by handleRpcResponse().

00319 {
00320     Chord::handleRpcJoinResponse(joinResponse);
00321 
00322     // has to be canceled in Koorde
00323     cancelEvent(fixfingers_timer);
00324 
00325     // immediate deBruijn protocol
00326     cancelEvent(deBruijn_timer);
00327     scheduleAt(simulation.simTime(), deBruijn_timer);
00328 }

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

handle a received DEBRUIJN request

Parameters:
deBruinCall the message to process

Referenced by handleRpc().

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

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

handle a received DEBRUIJN response

Parameters:
deBruijnResponse the message to process

Referenced by handleRpcResponse().

00475 {
00476     int sucNum = deBruijnResponse->getSucNum();
00477     if (sucNum > deBruijnListSize)
00478         sucNum = deBruijnListSize;
00479 
00480     for (int i = 0; i < sucNum; i++) {
00481         deBruijnNodes[i] = deBruijnResponse->getSucNode(i);
00482         deBruijnNumber = i+1;
00483     }
00484 
00485     deBruijnNode = deBruijnResponse->getDBNode();
00486 
00487     updateTooltip();
00488 }

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

handle a DEBRUIJN timeout

Parameters:
deBruijnCall the message which timed out

Referenced by handleRpcTimeout().

00491 {
00492     if (failedDBResponses == stabilizeRetry) {
00493         failedDBResponses = 0;
00494         deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
00495         preOrSuc = !preOrSuc;
00496     } else {
00497         failedDBResponses++;
00498     }
00499 
00500     updateTooltip();
00501     cancelEvent(deBruijn_timer);
00502     scheduleAt(simulation.simTime(), deBruijn_timer);
00503 }

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

Referenced by findNode().

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

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.

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

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

Referenced by findNode().

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

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

Referenced by findNode().

00802 {
00803     int keyLength = srcKey.getLength();
00804     bool equal = true;
00805 
00806     for (int i = keyLength; i>0; i--) {
00807         equal = true;
00808         for(int j = 1; j <= i; j++) {
00809             if (srcKey.getBit(i - j) != destKey.getBit(destKey.getLength() - j)) {
00810                 equal = false;
00811                 break;
00812             }
00813         }
00814 
00815         if (equal)
00816             return i;
00817 
00818     }
00819     return 0;
00820 }

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

Referenced by findDeBruijnHop().

00648 {
00649     if (deBruijnNumber == 0)
00650         return NodeHandle::UNSPECIFIED_NODE;
00651 
00652     for (int i = 0; i < deBruijnNumber-1; i++) {
00653         if (key.isBetweenR(deBruijnNodes[i].key,deBruijnNodes[i+1].key)) {
00654             return deBruijnNodes[i];
00655         }
00656     }
00657 
00658     return deBruijnNodes[deBruijnNumber-1];
00659 }

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

Referenced by findDeBruijnHop(), and findNode().

00662 {
00663     for (unsigned int i = 0; i < successorList->getSize()-1; i++) {
00664         if (key.isBetweenR(successorList->getSuccessor(i).key,
00665                            successorList->getSuccessor(i+1).key)) {
00666             return successorList->getSuccessor(i);
00667         }
00668     }
00669 
00670     return successorList->getSuccessor(successorList->getSize()-1);
00671 }

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

handles a received Stabilize response

Parameters:
stabilizeResponse the message to process

Reimplemented from Chord.

Referenced by handleRpcResponse().

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

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

handles a received Notify request

Parameters:
call the message to process

Reimplemented from Chord.

Referenced by handleRpc().

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

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

handles a received Notify response

Parameters:
notifyResponse the message to process

Reimplemented from Chord.

Referenced by handleRpcResponse().

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

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

Sets the pointer to the successor list module.

Reimplemented from Chord.

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

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

Intializes the successor list.

Reimplemented from Chord.

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

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.

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

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.

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


Member Data Documentation

int Koorde::deBruijnDelay [protected]

number of seconds between two de Bruijn algo calls

Referenced by changeState(), handleDeBruijnTimerExpired(), and initializeOverlay().

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

Referenced by findDeBruijnHop(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), initializeOverlay(), updateTooltip(), and walkDeBruijnList().

int Koorde::deBruijnListSize [protected]

maximal number of nodes in de Bruijn list

Referenced by changeState(), handleDeBruijnTimerExpired(), handleRpcDeBruijnResponse(), and initializeOverlay().

int Koorde::shiftingBits [protected]

number of bits concurrently shifted in one routing step

Referenced by findDeBruijnHop(), findStartKey(), handleDeBruijnTimerExpired(), and initializeOverlay().

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

Referenced by handleDeBruijnTimerExpired(), handleRpcNotifyResponse(), initializeOverlay(), and successorIsDead().

bool Koorde::preDeBruijnNodeSet [protected]

flag is set if our predecessor has a de bruijn node

Referenced by handleDeBruijnTimerExpired(), initializeOverlay(), predecessorIsDead(), and rpcNotify().

bool Koorde::useOtherLookup [protected]

flag which is indicating that the optimization other lookup is enabled

Referenced by findNode(), and initializeOverlay().

bool Koorde::useSucList [protected]

flag which is indicating that the optimization using the successorlist is enabled

Referenced by findDeBruijnHop(), and initializeOverlay().

bool Koorde::breakLookup [protected]

flag is used during the recursive step when returning this node

Referenced by findDeBruijnHop(), findNode(), and initializeOverlay().

bool Koorde::firstTimer [protected]

indicates if this is the first de bruijn timer

Referenced by handleDeBruijnTimerExpired(), handleRpcNotifyResponse(), initializeOverlay(), and rpcNotify().

int Koorde::deBruijnRetryTime [protected]

time interval when the de bruijn call times out

Referenced by handleDeBruijnTimerExpired(), and initializeOverlay().

int Koorde::failedDBResponses [protected]

number of failed responses to a de bruijn call

Referenced by handleDeBruijnTimeout(), and initializeOverlay().

bool Koorde::preOrSuc [protected]

flag which indicates if the predecessor or successor is used as a springboard

Referenced by handleDeBruijnTimeout(), handleDeBruijnTimerExpired(), and initializeOverlay().

int Koorde::deBruijnCount [protected]

number of de bruijn calls

Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().

int Koorde::deBruijnBytesSent [protected]

number of bytes sent during de bruijn calls

Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().

cMessage* Koorde::deBruijn_timer [protected]


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:07 2008 for ITM OverSim by  doxygen 1.5.5