oversim::Koorde Class Reference

Koorde overlay module. More...

#include <Koorde.h>

Inheritance diagram for oversim::Koorde:
oversim::Chord BaseOverlay ProxListener BaseRpc TopologyVis RpcListener

List of all members.

Public Member Functions

virtual ~Koorde ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void handleTimerEvent (cMessage *msg)
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 ()
 handle an expired de bruijn timer
virtual bool handleRpcCall (BaseCallMessage *msg)
 handle an expired fix_fingers timer (dummy function)
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, int &step)
 find a "good" routing key to destKey between startingKey and endKey with the longest matching prefix possible
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 bool handleFailedNode (const TransportAddress &failed)
 Handles a failed node.
virtual void rpcJoin (JoinCall *call)
 Join Remote-Procedure-Call.
virtual void findFriendModules ()
 Assigns the finger table and successor list module to our reference.
virtual void initializeFriendModules ()
 initializes finger table and successor list

Protected Attributes

int deBruijnDelay
 number of seconds between two de bruijn calls
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 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 setupDeBruijnBeforeJoin
 if true, first setup the de bruijn node using the bootstrap node and than join the ring
bool setupDeBruijnAtJoin
 if true, join the ring and setup the de bruijn node using the bootstrap node in parallel
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
 timer for periodic de bruijn stabilization

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

Definition at line 50 of file Koorde.h.


Constructor & Destructor Documentation

oversim::Koorde::~Koorde (  )  [virtual]

Definition at line 74 of file Koorde.cc.

00075 {
00076     cancelAndDelete(deBruijn_timer);
00077 }


Member Function Documentation

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

changes node state

Parameters:
state state to change to

Reimplemented from oversim::Chord.

Definition at line 79 of file Koorde.cc.

Referenced by handleDeBruijnTimeout().

00080 {
00081     Chord::changeState(toState);
00082 
00083     switch(state) {
00084     case INIT:
00085         // init de Bruijn nodes
00086         deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
00087 
00088         for (int i=0; i < deBruijnListSize; i++) {
00089             deBruijnNodes[i] = NodeHandle::UNSPECIFIED_NODE;
00090         }
00091 
00092         updateTooltip();
00093         break;
00094     case BOOTSTRAP:
00095         if (setupDeBruijnBeforeJoin) {
00096             // setup de bruijn node before joining the ring
00097             cancelEvent(join_timer);
00098             cancelEvent(deBruijn_timer);
00099             scheduleAt(simTime(), deBruijn_timer);
00100         } else if (setupDeBruijnAtJoin) {
00101             cancelEvent(deBruijn_timer);
00102             scheduleAt(simTime(), deBruijn_timer);
00103         }
00104         break;
00105     case READY:
00106         // init de Bruijn Protocol
00107         cancelEvent(deBruijn_timer);
00108         scheduleAt(simTime(), deBruijn_timer);
00109 
00110         // since we don't need the fixfingers protocol in Koorde cancel timer
00111         cancelEvent(fixfingers_timer);
00112         break;
00113     default:
00114         break;
00115     }
00116 
00117 }

NodeHandle oversim::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

Definition at line 473 of file Koorde.cc.

Referenced by findNode().

00475 {
00476     if (findNodeExt->getRouteKey().isUnspecified()) {
00477         if (!deBruijnNode.isUnspecified()) {
00478             int step;
00479             findNodeExt->setRouteKey(findStartKey(thisNode.getKey(),
00480                               successorList->getSuccessor().getKey(), destKey,
00481                               step));
00482             findNodeExt->setStep(step);
00483         } else {
00484             breakLookup = true;
00485             return successorList->getSuccessor();
00486         }
00487     }
00488 
00489     // check if the route key falls in our responsibility or
00490     // else forward the message to our successor
00491     if (findNodeExt->getRouteKey().isBetweenR(thisNode.getKey(),
00492         successorList->getSuccessor().getKey())) {
00493         if ((unsigned int)findNodeExt->getStep() > destKey.getLength())
00494             error("Koorde::findDeBruijnHop - Bounding error: "
00495                   "trying to get non existing bit out of overlay key!");
00496 
00497         // update the route key
00498         OverlayKey add = OverlayKey(destKey.getBit(destKey.getLength() -
00499                                                    findNodeExt->getStep()));
00500         for (int i = 1; i < shiftingBits; i++) {
00501             add = (add << 1) + OverlayKey(destKey.getBit(destKey.getLength() -
00502                                           findNodeExt->getStep() - i));
00503         }
00504 
00505         OverlayKey routeKey = (findNodeExt->getRouteKey()<<shiftingBits) + add;
00506         findNodeExt->setRouteKey(routeKey);
00507         findNodeExt->setStep(findNodeExt->getStep() + shiftingBits);
00508 
00509         if (deBruijnNode.isUnspecified()) {
00510             breakLookup = true;
00511             if (useSucList)
00512                 return walkSuccessorList(findNodeExt->getRouteKey());
00513             else
00514                 return successorList->getSuccessor();
00515         }
00516 
00517         // check if the new route key falls between our
00518         // de Bruijn node and its successor
00519         if (deBruijnNumber > 0) {
00520             if (findNodeExt->getRouteKey().isBetweenR(deBruijnNode.getKey(),
00521                                                       deBruijnNodes[0].getKey())) {
00522                 return deBruijnNode;
00523             } else {
00524                 // otherwise check if the route key falls between
00525                 // our de Bruijn successors
00526                 NodeHandle nextHop = walkDeBruijnList(findNodeExt->
00527                                                       getRouteKey());
00528                 return nextHop;
00529             }
00530         } else {
00531             return deBruijnNode;
00532         }
00533     } else {
00534         breakLookup = true;
00535         // if optimization is set search the successor list and
00536         // de bruijn node to find "good" next hop
00537         if (useSucList) {
00538             if (deBruijnNode.isUnspecified()) {
00539                 return walkSuccessorList(findNodeExt->getRouteKey());
00540             } else {
00541                 NodeHandle tmpHandle =
00542                     walkSuccessorList(findNodeExt->getRouteKey());
00543 
00544                 // todo: optimization - check complete deBruijnList
00545                 if (deBruijnNode.getKey().isBetween(tmpHandle.getKey(),
00546                                                findNodeExt->getRouteKey())) {
00547                     return deBruijnNode;
00548                 } else {
00549                     return tmpHandle;
00550                 }
00551             }
00552         } else
00553             return successorList->getSuccessor();
00554     }
00555 }

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

Assigns the finger table and successor list module to our reference.

Reimplemented from oversim::Chord.

Definition at line 764 of file Koorde.cc.

00765 {
00766     successorList = check_and_cast<ChordSuccessorList*>
00767                     (getParentModule()->getSubmodule("successorList"));
00768 }

NodeVector * oversim::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 oversim::Chord.

Definition at line 405 of file Koorde.cc.

00409 {
00410     // TODO: return redundant nodes for iterative routing
00411     // TODO: try to always calculate optimal routing key (if e.g.
00412     //       the originator didn't have its deBruijnNode set already, the
00413     //       routing key may be very far away on the ring)
00414     NodeVector* nextHop = new NodeVector();
00415     KoordeFindNodeExtMessage *findNodeExt = NULL;
00416 
00417     if (state != READY)
00418         return nextHop;
00419 
00420     if (msg != NULL) {
00421         if (!msg->hasObject("findNodeExt")) {
00422             findNodeExt = new KoordeFindNodeExtMessage("findNodeExt");
00423             findNodeExt->setRouteKey(OverlayKey::UNSPECIFIED_KEY);
00424             findNodeExt->setStep(1);
00425             findNodeExt->setBitLength(KOORDEFINDNODEEXTMESSAGE_L);
00426             msg->addObject( findNodeExt );
00427         }
00428 
00429         findNodeExt = (KoordeFindNodeExtMessage*) msg->getObject("findNodeExt");
00430     }
00431 
00432     if (key.isUnspecified()) {
00433         error("Koorde::findNode() - direct Messaging is no longer in use.");
00434     } else if (key.isBetweenR(predecessorNode.getKey(), thisNode.getKey())) {
00435         // the message is destined for this node
00436         nextHop->push_back(thisNode);
00437     } else if (key.isBetweenR(thisNode.getKey(),
00438                               successorList->getSuccessor().getKey())){
00439         // the message destined for our successor
00440         nextHop->push_back(successorList->getSuccessor());
00441     } else {
00442         // if useOtherLookup is enabled we try to use
00443         // our successor list to get to the key
00444         if (useOtherLookup) {
00445             NodeHandle tmpNode = walkSuccessorList(key);
00446             if (tmpNode !=
00447                   successorList->getSuccessor(successorList->getSize() - 1)) {
00448                 nextHop->push_back(tmpNode);
00449             } else {
00450                 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
00451                 if (tmpHandle != thisNode || breakLookup) {
00452                     nextHop->push_back(tmpHandle);
00453                     breakLookup = false;
00454                 } else {
00455                     return findNode(key, numRedundantNodes, numSiblings, msg);
00456                 }
00457             }
00458         } else {
00459             // find next hop using either the de Bruijn node and
00460             // its successors or our own successors
00461             NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
00462             if (tmpHandle != thisNode || breakLookup) {
00463                 nextHop->push_back(tmpHandle);
00464                 breakLookup = false;
00465             } else {
00466                 return findNode(key, numRedundantNodes, numSiblings, msg);
00467             }
00468         }
00469     }
00470     return nextHop;
00471 }

OverlayKey oversim::Koorde::findStartKey ( const OverlayKey startKey,
const OverlayKey endKey,
const OverlayKey destKey,
int &  step 
) [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
step reference to return the bit position
Returns:
a "good" routing key to start from

Definition at line 664 of file Koorde.cc.

Referenced by findDeBruijnHop().

00668 {
00669     OverlayKey diffKey, newStart, tmpDest, newKey, powKey;
00670     int nBits;
00671 
00672     if (startKey == endKey)
00673         return startKey;
00674 
00675     diffKey = endKey - startKey;
00676     nBits = diffKey.log_2();
00677 
00678     if (nBits < 0) {
00679         nBits = 0;
00680     }
00681 
00682     while ((startKey.getLength() - nBits) % shiftingBits != 0) {
00683        nBits--;
00684    }
00685 
00686     step = nBits + 1;
00687 
00688 #if 0
00689     // TODO: work in progress to find better start key
00690     uint shared;
00691     for (shared = 0; shared < (startKey.getLength() - nBits); shared += shiftingBits) {
00692         if (destKey.sharedPrefixLength(startKey << shared) >= (startKey.getLength() - nBits - shared)) {
00693              break;
00694          }
00695     }
00696 
00697     uint nBits2 = startKey.getLength() - shared;
00698 
00699     newStart = (startKey >> nBits2) << nBits2;
00700 
00701     tmpDest = destKey >> (destKey.getLength() - nBits2);
00702     newKey = tmpDest + newStart;
00703 
00704     std::cout << "startKey: " << startKey.toString(2) << endl
00705               << "endKey  : " << endKey.toString(2) << endl
00706               << "diff    : " << (endKey-startKey).toString(2) << endl
00707               << "newKey  : " << newKey.toString(2) << endl
00708               << "destKey : " << destKey.toString(2) << endl
00709               << "nbits   : " << nBits << endl
00710               << "nbits2  : " << nBits2 << endl;
00711 
00712     // is the new constructed route key bigger than our start key return it
00713     if (newKey.isBetweenR(startKey, endKey)) {
00714         std::cout << "HIT" << endl;
00715         return newKey;
00716     } else {
00717         nBits2 -= shiftingBits;
00718         newStart = (startKey >> nBits2) << nBits2;
00719 
00720         tmpDest = destKey >> (destKey.getLength() - nBits2);
00721         newKey = tmpDest + newStart;
00722 
00723         if (newKey.isBetweenR(startKey, endKey)) {
00724             std::cout << "startKey: " << startKey.toString(2) << endl
00725                       << "endKey  : " << endKey.toString(2) << endl
00726                       << "diff    : " << (endKey-startKey).toString(2) << endl
00727                       << "newKey  : " << newKey.toString(2) << endl
00728                       << "destKey : " << destKey.toString(2) << endl
00729                       << "nbits   : " << nBits << endl
00730                       << "nbits2  : " << nBits2 << endl;
00731             std::cout << "HIT2" << endl;
00732             return newKey;
00733         }
00734     }
00735 
00736     std::cout << "MISS" << endl;
00737 #endif
00738 
00739     newStart = (startKey >> nBits) << nBits;
00740 
00741     tmpDest = destKey >> (destKey.getLength() - nBits);
00742     newKey = tmpDest + newStart;
00743 
00744     // is the new constructed route key bigger than our start key return it
00745     if (newKey.isBetweenR(startKey, endKey)) {
00746         return newKey;
00747     }
00748 
00749     // If the part of the destination key smaller than the one of
00750     // the original key add pow(nBits) (this is the first bit where
00751     // the start key and end key differ) to the new constructed key
00752     // and check if it's between start and end key.
00753     newKey += powKey.pow2(nBits);
00754 
00755     if (newKey.isBetweenR(startKey, endKey)) {
00756         return newKey;
00757     } else {
00758         // this part should not be called
00759         throw cRuntimeError("Koorde::findStartKey(): Invalid start key");
00760         return OverlayKey::UNSPECIFIED_KEY;
00761     }
00762 }

void oversim::Koorde::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from oversim::Chord.

Definition at line 626 of file Koorde.cc.

00627 {
00628     // statistics
00629     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00630 
00631     if (time >= GlobalStatistics::MIN_MEASURED) {
00632         globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Messages/s",
00633                                     deBruijnCount / time);
00634         globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Bytes/s",
00635                                     deBruijnBytesSent / time);
00636     }
00637 
00638     Chord::finishOverlay();
00639 }

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

handle a DEBRUIJN timeout

Parameters:
deBruijnCall the message which timed out

Definition at line 392 of file Koorde.cc.

Referenced by handleRpcTimeout().

00393 {
00394     if (setupDeBruijnBeforeJoin && (state == BOOTSTRAP)) {
00395         // failed to set initial de bruijn node
00396         // -> get a new bootstrap node and try again
00397         changeState(BOOTSTRAP);
00398         return;
00399     }
00400 
00401     cancelEvent(deBruijn_timer);
00402     scheduleAt(simTime(), deBruijn_timer);
00403 }

void oversim::Koorde::handleDeBruijnTimerExpired (  )  [protected, virtual]

handle an expired de bruijn timer

Definition at line 164 of file Koorde.cc.

Referenced by handleTimerEvent(), and rpcJoin().

00165 {
00166     OverlayKey lookup = thisNode.getKey() << shiftingBits;
00167 
00168     if (state == READY) {
00169         if (successorList->getSize() > 0) {
00170             // look for some nodes before our actual de-bruijn key
00171             // to have redundancy if our de-bruijn node fails
00172             lookup -= (successorList->getSuccessor(successorList->getSize() /
00173                                               2).getKey() - thisNode.getKey());
00174         }
00175 
00176         if (lookup.isBetweenR(thisNode.getKey(),
00177                               successorList->getSuccessor().getKey())
00178                 || successorList->isEmpty()) {
00179 
00180             int sucNum = successorList->getSize();
00181             if (sucNum > deBruijnListSize)
00182                 sucNum = deBruijnListSize;
00183 
00184             deBruijnNode = thisNode;
00185             for (int i = 0; i < sucNum; i++) {
00186                 deBruijnNodes[i] = successorList->getSuccessor(i);
00187                 deBruijnNumber = i+1;
00188             }
00189 
00190             updateTooltip();
00191         } else if (lookup.isBetweenR(predecessorNode.getKey(),
00192                                      thisNode.getKey())) {
00193             int sucNum = successorList->getSize();
00194             if ((sucNum + 1) > deBruijnListSize)
00195                 sucNum = deBruijnListSize - 1;
00196 
00197             deBruijnNode = predecessorNode;
00198             deBruijnNodes[0] = thisNode;
00199             for (int i = 0; i < sucNum; i++) {
00200                 deBruijnNodes[i+1] = successorList->getSuccessor(i);
00201                 deBruijnNumber = i+2;
00202             }
00203 
00204             updateTooltip();
00205         } else {
00206             DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
00207             call->setDestKey(lookup);
00208             call->setBitLength(DEBRUIJNCALL_L(call));
00209 
00210             sendRouteRpcCall(OVERLAY_COMP, deBruijnNode,
00211                              call->getDestKey(), call, NULL,
00212                              DEFAULT_ROUTING);
00213         }
00214 
00215         cancelEvent(deBruijn_timer);
00216         scheduleAt(simTime() + deBruijnDelay, deBruijn_timer);
00217     } else {
00218         if (setupDeBruijnBeforeJoin || setupDeBruijnAtJoin) {
00219             DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
00220             call->setDestKey(lookup);
00221             call->setBitLength(DEBRUIJNCALL_L(call));
00222 
00223             sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, call->getDestKey(),
00224                              call, NULL, DEFAULT_ROUTING);
00225 
00226             scheduleAt(simTime() + deBruijnDelay, deBruijn_timer);
00227         }
00228     }
00229 }

bool oversim::Koorde::handleFailedNode ( const TransportAddress failed  )  [protected, virtual]

Handles a failed node.

This method is called whenever a node given by findNode() was unreachable. The default implementation does nothing at all.

Parameters:
failed the failed node
Returns:
true if lookup should retry here

Reimplemented from oversim::Chord.

Definition at line 130 of file Koorde.cc.

00131 {
00132     if (!deBruijnNode.isUnspecified()) {
00133         if (failed == deBruijnNode) {
00134             deBruijnNode = deBruijnNodes[0];
00135             for (int i = 0; i < deBruijnNumber - 1; i++) {
00136                 deBruijnNodes[i] = deBruijnNodes[i+1];
00137             }
00138 
00139             if (deBruijnNumber > 0) {
00140                 deBruijnNodes[deBruijnNumber - 1] = NodeHandle::UNSPECIFIED_NODE;
00141                 --deBruijnNumber;
00142             }
00143         } else {
00144             bool removed = false;
00145             for (int i = 0; i < deBruijnNumber - 1; i++) {
00146                 if ((!deBruijnNodes[i].isUnspecified()) &&
00147                         (failed == deBruijnNodes[i])) {
00148                     removed = true;
00149                 }
00150                 if (removed ||
00151                         ((!deBruijnNodes[deBruijnNumber - 1].isUnspecified())
00152                           && failed == deBruijnNodes[deBruijnNumber - 1])) {
00153                     deBruijnNodes[deBruijnNumber - 1] =
00154                             NodeHandle::UNSPECIFIED_NODE;
00155                     --deBruijnNumber;
00156                 }
00157             }
00158         }
00159     }
00160 
00161     return Chord::handleFailedNode(failed);
00162 }

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

handle an expired fix_fingers timer (dummy function)

Parameters:
msg the timer self-message

Reimplemented from oversim::Chord.

Definition at line 245 of file Koorde.cc.

00246 {
00247     if (state == READY) {
00248         // delegate messages
00249         RPC_SWITCH_START( msg )
00250         RPC_DELEGATE( DeBruijn, handleRpcDeBruijnRequest );
00251         RPC_SWITCH_END( )
00252 
00253         if (RPC_HANDLED) return true;
00254     } else {
00255         EV << "[Koorde::handleRpcCall() @ " << thisNode.getAddress()
00256            << " (" << thisNode.getKey().toString(16) << ")]\n"
00257            << "    Received RPC call and state != READY!"
00258            << endl;
00259     }
00260 
00261     return Chord::handleRpcCall(msg);
00262 }

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

handle a received DEBRUIJN request

Parameters:
deBruinCall the message to process

Definition at line 328 of file Koorde.cc.

Referenced by handleRpcCall().

00329 {
00330     // The key lies between thisNode and its predecessor and
00331     // because routing the message to the predecessor of a key
00332     // is near to impossible we set the deBruijnNodes here
00333     // and the information is as actual as the predecessor pointer.
00334     //
00335     // If this is the only node in the ring, it is the temporary de bruijn
00336     // node for the joining node.
00337     if ((predecessorNode.isUnspecified() && successorList->isEmpty())
00338             || deBruijnCall->getDestKey().isBetweenR(predecessorNode.getKey(),
00339                                               thisNode.getKey())) {
00340         DeBruijnResponse* deBruijnResponse =
00341             new DeBruijnResponse("DeBruijnResponse");
00342 
00343         if (predecessorNode.isUnspecified()) {
00344             deBruijnResponse->setDBNode(thisNode);
00345         } else {
00346             deBruijnResponse->setDBNode(predecessorNode);
00347         }
00348 
00349         int sucNum = successorList->getSize() + 1;
00350         deBruijnResponse->setSucNum(sucNum);
00351         deBruijnResponse->setSucNodeArraySize(sucNum);
00352 
00353         deBruijnResponse->setSucNode(0, thisNode);
00354         for (int k = 1; k < sucNum; k++) {
00355             deBruijnResponse->setSucNode(k, successorList->getSuccessor(k-1));
00356         }
00357         deBruijnResponse->setBitLength(DEBRUIJNRESPONSE_L(deBruijnResponse));
00358 
00359         sendRpcResponse(deBruijnCall, deBruijnResponse);
00360     } else if (deBruijnCall->getDestKey().isBetweenR(thisNode.getKey(),
00361                successorList->getSuccessor().getKey())) {
00362         error("Koorde::handleRpcDeBruijnRequest() - unknown error.");
00363     } else {
00364         error("Koorde::handleRpcDeBruijnRequest() - "
00365               "Request couldn't be delivered!");
00366     }
00367 }

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

handle a received DEBRUIJN response

Parameters:
deBruijnResponse the message to process

Definition at line 369 of file Koorde.cc.

Referenced by handleRpcResponse().

00370 {
00371     int sucNum = deBruijnResponse->getSucNum();
00372     if (sucNum > deBruijnListSize)
00373         sucNum = deBruijnListSize;
00374 
00375     for (int i = 0; i < sucNum; i++) {
00376         deBruijnNodes[i] = deBruijnResponse->getSucNode(i);
00377         deBruijnNumber = i+1;
00378     }
00379 
00380     deBruijnNode = deBruijnResponse->getDBNode();
00381 
00382     updateTooltip();
00383 
00384     if (setupDeBruijnBeforeJoin && (state == BOOTSTRAP)) {
00385         // now that we have a valid de bruijn node it's time to join the ring
00386         if (!join_timer->isScheduled()) {
00387             scheduleAt(simTime(), join_timer);
00388         }
00389     }
00390 }

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

handle a received JOIN response

Parameters:
joinResponse the message to process

Reimplemented from oversim::Chord.

Definition at line 304 of file Koorde.cc.

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

void oversim::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 oversim::Chord.

Definition at line 264 of file Koorde.cc.

00267 {
00268     Chord::handleRpcResponse(msg, context, rpcId, rtt);
00269 
00270     RPC_SWITCH_START( msg )
00271     RPC_ON_RESPONSE( DeBruijn ) {
00272         handleRpcDeBruijnResponse(_DeBruijnResponse);
00273         EV << "[Koorde::handleRpcResponse() @ " << thisNode.getAddress()
00274            << " (" << thisNode.getKey().toString(16) << ")]\n"
00275            << "    DeBruijn RPC Response received: id=" << rpcId
00276            << "\n    msg=" << *_DeBruijnResponse << " rtt=" << rtt
00277            << endl;
00278         break;
00279     }
00280     RPC_SWITCH_END( )
00281 }

void oversim::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 oversim::Chord.

Definition at line 283 of file Koorde.cc.

00287 {
00288     Chord::handleRpcTimeout(msg, dest, context, rpcId, destKey);
00289 
00290     RPC_SWITCH_START( msg )
00291     RPC_ON_CALL( DeBruijn ) {
00292         handleDeBruijnTimeout(_DeBruijnCall);
00293         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.getAddress()
00294            << " (" << thisNode.getKey().toString(16) << ")]\n"
00295            << "    DeBruijn RPC Call timed out: id=" << rpcId
00296            << "\n    msg=" << *_DeBruijnCall
00297            << endl;
00298         break;
00299     }
00300     RPC_SWITCH_END( )
00301 }

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

Reimplemented from oversim::Chord.

Definition at line 119 of file Koorde.cc.

00120 {
00121     if (msg->isName("deBruijn_timer")) {
00122         handleDeBruijnTimerExpired();
00123     } else if (msg->isName("fixfingers_timer")) {
00124         handleFixFingersTimerExpired(msg);
00125     } else {
00126         Chord::handleTimerEvent(msg);
00127     }
00128 }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from oversim::Chord.

Definition at line 239 of file Koorde.cc.

00240 {
00241     Chord::handleUDPMessage(msg);
00242 }

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

initializes finger table and successor list

Reimplemented from oversim::Chord.

Definition at line 770 of file Koorde.cc.

00771 {
00772     // initialize successor list
00773     successorList->initializeList(par("successorListSize"), thisNode, this);
00774 }

void oversim::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 oversim::Chord.

Definition at line 37 of file Koorde.cc.

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

void oversim::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 oversim::Chord.

Definition at line 641 of file Koorde.cc.

00642 {
00643     Chord::recordOverlaySentStats(msg);
00644 
00645     BaseOverlayMessage* innerMsg = msg;
00646     while (innerMsg->getType() != APPDATA &&
00647            innerMsg->getEncapsulatedPacket() != NULL) {
00648         innerMsg =
00649             static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedPacket());
00650     }
00651 
00652     switch (innerMsg->getType()) {
00653         case RPC: {
00654             if ((dynamic_cast<DeBruijnCall*>(innerMsg) != NULL) ||
00655                 (dynamic_cast<DeBruijnResponse*>(innerMsg) != NULL)) {
00656                 RECORD_STATS(deBruijnCount++; deBruijnBytesSent +=
00657                                  msg->getByteLength());
00658             }
00659         break;
00660         }
00661     }
00662 }

void oversim::Koorde::rpcJoin ( JoinCall *  call  )  [protected, virtual]

Join Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Reimplemented from oversim::Chord.

Definition at line 317 of file Koorde.cc.

00318 {
00319     Chord::rpcJoin(joinCall);
00320 
00321     if (predecessorNode == successorList->getSuccessor()) {
00322         // second node join -> need to setup our de bruijn node
00323         handleDeBruijnTimerExpired();
00324     }
00325 }

void oversim::Koorde::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented from oversim::Chord.

Definition at line 584 of file Koorde.cc.

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

00585 {
00586     //
00587     // Updates the tooltip display strings.
00588     //
00589 
00590     if (ev.isGUI()) {
00591         std::stringstream ttString;
00592 
00593         // show our predecessor, successor and de Bruijn node in tooltip
00594         ttString << "Pred "<< predecessorNode << endl << "This  "
00595                  << thisNode << endl
00596                  << "Suc   " << successorList->getSuccessor() << endl
00597                  << "DeBr " << deBruijnNode << endl;
00598         ttString << "List ";
00599 
00600         for (unsigned int i = 0; i < successorList->getSize(); i++) {
00601             ttString << successorList->getSuccessor(i).getAddress() << " ";
00602         }
00603 
00604         ttString << endl;
00605         ttString << "DList ";
00606 
00607         for (int i = 0; i < deBruijnNumber; i++) {
00608             ttString << deBruijnNodes[i].getAddress() << " ";
00609         }
00610 
00611         ttString << endl;
00612 
00613         getParentModule()->getParentModule()->
00614             getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
00615         getParentModule()->getDisplayString().setTagArg("tt", 0,
00616                                                   ttString.str().c_str());
00617         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
00618 
00619         // draw an arrow to our current successor
00620         showOverlayNeighborArrow(successorList->getSuccessor(), true,
00621                                  "m=m,50,0,50,0;ls=red,1");
00622     }
00623 }

const NodeHandle & oversim::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

Definition at line 558 of file Koorde.cc.

Referenced by findDeBruijnHop().

00559 {
00560     if (deBruijnNumber == 0)
00561         return NodeHandle::UNSPECIFIED_NODE;
00562 
00563     for (int i = 0; i < deBruijnNumber-1; i++) {
00564         if (key.isBetweenR(deBruijnNodes[i].getKey(),deBruijnNodes[i+1].getKey())) {
00565             return deBruijnNodes[i];
00566         }
00567     }
00568 
00569     return deBruijnNodes[deBruijnNumber-1];
00570 }

const NodeHandle & oversim::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

Definition at line 572 of file Koorde.cc.

Referenced by findDeBruijnHop(), and findNode().

00573 {
00574     for (unsigned int i = 0; i < successorList->getSize()-1; i++) {
00575         if (key.isBetweenR(successorList->getSuccessor(i).getKey(),
00576                            successorList->getSuccessor(i+1).getKey())) {
00577             return successorList->getSuccessor(i);
00578         }
00579     }
00580 
00581     return successorList->getSuccessor(successorList->getSize()-1);
00582 }


Member Data Documentation

bool oversim::Koorde::breakLookup [protected]

flag is used during the recursive step when returning this node

Definition at line 83 of file Koorde.h.

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

cMessage* oversim::Koorde::deBruijn_timer [protected]

timer for periodic de bruijn stabilization

Definition at line 96 of file Koorde.h.

Referenced by changeState(), handleDeBruijnTimeout(), handleDeBruijnTimerExpired(), handleRpcJoinResponse(), initializeOverlay(), and ~Koorde().

number of bytes sent during de bruijn calls

Definition at line 89 of file Koorde.h.

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

number of de bruijn calls

Definition at line 88 of file Koorde.h.

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

number of seconds between two de bruijn calls

Definition at line 77 of file Koorde.h.

Referenced by handleDeBruijnTimerExpired(), and initializeOverlay().

maximal number of nodes in de bruijn list

Definition at line 79 of file Koorde.h.

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

number of current nodes in de bruijn list; depend on number of nodes in successor list

Definition at line 78 of file Koorde.h.

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

if true, join the ring and setup the de bruijn node using the bootstrap node in parallel

Definition at line 85 of file Koorde.h.

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

if true, first setup the de bruijn node using the bootstrap node and than join the ring

Definition at line 84 of file Koorde.h.

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

number of bits concurrently shifted in one routing step

Definition at line 80 of file Koorde.h.

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

flag which is indicating that the optimization other lookup is enabled

Definition at line 81 of file Koorde.h.

Referenced by findNode(), and initializeOverlay().

bool oversim::Koorde::useSucList [protected]

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

Definition at line 82 of file Koorde.h.

Referenced by findDeBruijnHop(), and initializeOverlay().


The documentation for this class was generated from the following files:
Generated on Wed May 26 16:21:20 2010 for OverSim by  doxygen 1.6.3