oversim::Chord Class Reference

Chord overlay module. More...

#include <Chord.h>

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

List of all members.

Public Member Functions

 Chord ()
virtual ~Chord ()
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
OverlayKey distance (const OverlayKey &x, const OverlayKey &y, bool useAlternative=false) const
 This method should implement the distance between two keys.
virtual void updateTooltip ()
 updates information shown in tk-environment
void proxCallback (const TransportAddress &node, int rpcId, cPolymorphic *contextPointer, Prox prox)

Protected Member Functions

virtual void changeState (int toState)
 changes node state
virtual void handleJoinTimerExpired (cMessage *msg)
 handle a expired join timer
virtual void handleStabilizeTimerExpired (cMessage *msg)
 handle a expired stabilize timer
virtual void handleFixFingersTimerExpired (cMessage *msg)
 handle a expired fix_fingers timer
virtual void handleNewSuccessorHint (ChordMessage *chordMsg)
 handle a received NEWSUCCESSORHINT message
virtual NodeVectorclosestPreceedingNode (const OverlayKey &key)
 looks up the finger table and returns the closest preceeding node.
virtual void findFriendModules ()
 Assigns the finger table and successor list module to our reference.
virtual void initializeFriendModules ()
 initializes finger table and successor list
virtual bool handleRpcCall (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invocation messages.
NodeVectorfindNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg)
 Implements the find node call.
virtual void joinOverlay ()
 Join the overlay with a given nodeID in thisNode.key.
virtual void joinForeignPartition (const NodeHandle &node)
 Join another overlay partition with the given node as bootstrap node.
virtual bool isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err)
 Query if a node is among the siblings for a given key.
int getMaxNumSiblings ()
 Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.
int getMaxNumRedundantNodes ()
 Query the maximum number of redundant next hop nodes that are returned by findNode().
void rpcFixfingers (FixfingersCall *call)
 Fixfingers Remote-Procedure-Call.
virtual void rpcJoin (JoinCall *call)
 Join Remote-Procedure-Call.
virtual void rpcNotify (NotifyCall *call)
 NOTIFY Remote-Procedure-Call.
void rpcStabilize (StabilizeCall *call)
 STABILIZE Remote-Procedure-Call.
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 pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt)
virtual void pingTimeout (PingCall *pingCall, const TransportAddress &dest, cPolymorphic *context, int rpcId)
virtual void handleRpcJoinResponse (JoinResponse *joinResponse)
virtual void handleRpcNotifyResponse (NotifyResponse *notifyResponse)
virtual void handleRpcStabilizeResponse (StabilizeResponse *stabilizeResponse)
virtual void handleRpcFixfingersResponse (FixfingersResponse *fixfingersResponse, double rtt=-1)
virtual bool handleFailedNode (const TransportAddress &failed)
 Handles a failed node.

Protected Attributes

int joinRetry
int stabilizeRetry
 // retries before neighbor considered failed
double joinDelay
double stabilizeDelay
 stabilize interval (secs)
double fixfingersDelay
double checkPredecessorDelay
int successorListSize
bool aggressiveJoinMode
 use modified (faster) JOIN protocol
bool extendedFingerTable
unsigned int numFingerCandidates
bool proximityRouting
bool memorizeFailedSuccessor
bool newChordFingerTable
bool mergeOptimizationL1
bool mergeOptimizationL2
bool mergeOptimizationL3
bool mergeOptimizationL4
cMessage * join_timer
cMessage * stabilize_timer
cMessage * fixfingers_timer
cMessage * checkPredecessor_timer
int joinCount
int stabilizeCount
int fixfingersCount
int notifyCount
int newsuccessorhintCount
int joinBytesSent
int stabilizeBytesSent
int notifyBytesSent
int fixfingersBytesSent
int newsuccessorhintBytesSent
int keyLength
 length of an overlay key in bits
int missingPredecessorStabRequests
 missing StabilizeCall msgs
NodeHandle predecessorNode
 predecessor of this node
TransportAddress bootstrapNode
 node used to bootstrap
ChordFingerTablefingerTable
 pointer to this node's finger table
ChordSuccessorListsuccessorList
 pointer to this node's successor list

Private Attributes

TransportAddress failedSuccessor

Friends

class ChordSuccessorList
class ChordFingerTable

Detailed Description

Chord overlay module.

Implementation of the Chord KBR overlay as described in "Chord: A Scalable Peer-to-Peer Lookup Protocol for Inetnet Applications" by I. Stoica et al. published in Transactions on Networking.

Author:
Markus Mauch, Ingmar Baumgart
See also:
BaseOverlay, ChordFingerTable, ChordSuccessorList

Definition at line 47 of file Chord.h.


Constructor & Destructor Documentation

oversim::Chord::Chord (  ) 

Definition at line 38 of file Chord.cc.

00040 {
00041     stabilize_timer = fixfingers_timer = join_timer = NULL;
00042     fingerTable = NULL;

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

Definition at line 116 of file Chord.cc.

00118 {
00119     // destroy self timer messages
00120     cancelAndDelete(join_timer);
00121     cancelAndDelete(stabilize_timer);
00122     cancelAndDelete(fixfingers_timer);
00123     cancelAndDelete(checkPredecessor_timer);


Member Function Documentation

void oversim::Chord::changeState ( int  toState  )  [protected, virtual]

changes node state

Parameters:
toState state to change to

Reimplemented in oversim::Koorde.

Definition at line 151 of file Chord.cc.

Referenced by handleJoinTimerExpired(), handleRpcJoinResponse(), and joinOverlay().

00153 {
00154     //
00155     // Defines tasks to be executed when a state change occurs.
00156     //
00157 
00158     switch (toState) {
00159     case INIT:
00160         state = INIT;
00161 
00162         setOverlayReady(false);
00163 
00164         // initialize predecessor pointer
00165         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00166 
00167         // initialize finger table and successor list
00168         initializeFriendModules();
00169 
00170         updateTooltip();
00171 
00172         // debug message
00173         if (debugOutput) {
00174             EV << "[Chord::changeState() @ " << thisNode.getAddress()
00175             << " (" << thisNode.getKey().toString(16) << ")]\n"
00176             << "    Entered INIT stage"
00177             << endl;
00178         }
00179 
00180         getParentModule()->getParentModule()->bubble("Enter INIT state.");
00181         break;
00182 
00183     case BOOTSTRAP:
00184         state = BOOTSTRAP;
00185 
00186         // initiate bootstrap process
00187         cancelEvent(join_timer);
00188         // workaround: prevent notificationBoard from taking
00189         // ownership of join_timer message
00190         take(join_timer);
00191         scheduleAt(simTime(), join_timer);
00192 
00193         // debug message
00194         if (debugOutput) {
00195             EV << "[Chord::changeState() @ " << thisNode.getAddress()
00196             << " (" << thisNode.getKey().toString(16) << ")]\n"
00197             << "    Entered BOOTSTRAP stage"
00198             << endl;
00199         }
00200         getParentModule()->getParentModule()->bubble("Enter BOOTSTRAP state.");
00201 
00202         // find a new bootstrap node and enroll to the bootstrap list
00203         bootstrapNode = bootstrapList->getBootstrapNode();
00204 
00205         // is this the first node?
00206         if (bootstrapNode.isUnspecified()) {
00207             // create new cord ring
00208             assert(predecessorNode.isUnspecified());
00209             bootstrapNode = thisNode;
00210             changeState(READY);
00211             updateTooltip();
00212         }
00213         break;
00214 
00215     case READY:
00216         state = READY;
00217 
00218         setOverlayReady(true);
00219 
00220         // initiate stabilization protocol
00221         cancelEvent(stabilize_timer);
00222         scheduleAt(simTime() + stabilizeDelay, stabilize_timer);
00223 
00224         // initiate finger repair protocol
00225         cancelEvent(fixfingers_timer);
00226         scheduleAt(simTime() + fixfingersDelay,
00227                    fixfingers_timer);
00228 
00229         // initiate predecessor check
00230         cancelEvent(checkPredecessor_timer);
00231         if (checkPredecessorDelay > 0) {
00232             scheduleAt(simTime() + checkPredecessorDelay,
00233                        checkPredecessor_timer);
00234         }
00235 
00236         // debug message
00237         if (debugOutput) {
00238             EV << "[Chord::changeState() @ " << thisNode.getAddress()
00239             << " (" << thisNode.getKey().toString(16) << ")]\n"
00240             << "    Entered READY stage"
00241             << endl;
00242         }
00243         getParentModule()->getParentModule()->bubble("Enter READY state.");
00244         break;
00245     }

NodeVector * oversim::Chord::closestPreceedingNode ( const OverlayKey key  )  [protected, virtual]

looks up the finger table and returns the closest preceeding node.

Parameters:
key key to find the closest preceeding node for
Returns:
node vector of the closest preceeding nodes to key

Definition at line 601 of file Chord.cc.

Referenced by findNode().

00603 {
00604     NodeHandle tempHandle = NodeHandle::UNSPECIFIED_NODE;
00605 
00606     // find the closest preceding node in the successor list
00607     for (int j = successorList->getSize() - 1; j >= 0; j--) {
00608         // return a predecessor of the key, unless we know a node with an Id = destKey
00609         if (successorList->getSuccessor(j).getKey().isBetweenR(thisNode.getKey(), key)) {
00610             tempHandle = successorList->getSuccessor(j);
00611             break;
00612         }
00613     }
00614 
00615     if(tempHandle.isUnspecified()) {
00616         std::stringstream temp;
00617         temp << "Chord::closestPreceedingNode(): Successor list broken "
00618              << thisNode.getKey() << " " << key;
00619         throw cRuntimeError(temp.str().c_str());
00620     }
00621 
00622     NodeVector* nextHop = NULL;
00623 
00624     for (int i = fingerTable->getSize() - 1; i >= 0; i--) {
00625         // return a predecessor of the key, unless we know a node with an Id = destKey
00626         if (fingerTable->getFinger(i).getKey().isBetweenLR(tempHandle.getKey(), key)) {
00627             if(!extendedFingerTable) {
00628                 nextHop = new NodeVector();
00629                 nextHop->push_back(fingerTable->getFinger(i));
00630 
00631                 EV << "[Chord::closestPreceedingNode() @ " << thisNode.getAddress()
00632                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00633                    << "    ClosestPreceedingNode: node " << thisNode
00634                    << " for key " << key << "\n"
00635                    << "    finger " << fingerTable->getFinger(i).getKey()
00636                    << " better than \n"
00637                    << "    " << tempHandle.getKey()
00638                    << endl;
00639                 return nextHop;
00640             } else {
00641                 return fingerTable->getFinger(i, key);
00642             }
00643         }
00644     }
00645 
00646     nextHop = new NodeVector();
00647     EV << "[Chord::closestPreceedingNode() @ " << thisNode.getAddress()
00648        << " (" << thisNode.getKey().toString(16) << ")]\n"
00649        << "    No finger found"
00650        << endl;
00651 
00652     // if no finger is found lookup the rest of the successor list
00653     for (int i = successorList->getSize() - 1; i >= 0
00654         && nextHop->size() <= numFingerCandidates ; i--) {
00655         if (successorList->getSuccessor(i).getKey().isBetween(thisNode.getKey(), key)) {
00656             nextHop->push_back(successorList->getSuccessor(i));
00657         }
00658     }
00659 
00660     if (nextHop->size() != 0) {
00661         return nextHop;
00662     }
00663 
00664     // if this is the first and only node on the ring, it is responsible
00665     if ((predecessorNode.isUnspecified()) &&
00666         (successorList->getSuccessor() == thisNode)) {
00667         nextHop->push_back(thisNode);
00668         return nextHop;
00669     }
00670 
00671     // if there is still no node found throw an exception
00672     throw cRuntimeError("Error in Chord::closestPreceedingNode()!");
00673     return nextHop;

OverlayKey oversim::Chord::distance ( const OverlayKey x,
const OverlayKey y,
bool  useAlternative = false 
) const [virtual]

This method should implement the distance between two keys.

It may be overloaded to implement a new metric. The default implementation uses the standard-metric d = abs(x-y).

Parameters:
x Left-hand-side Key
y Right-hand-side key
useAlternative use an alternative distance metric
Returns:
OverlayKey Distance between x and y

Reimplemented from BaseOverlay.

Definition at line 1402 of file Chord.cc.

01402        : The following should be removed, since Chord doesn't have a simple metric
01403 OverlayKey Chord::distance(const OverlayKey& x,
01404                            const OverlayKey& y,
01405                            bool useAlternative) const
01406 {
01407     return KeyUniRingMetric().distance(x, y);

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

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

Reimplemented in oversim::Koorde.

Definition at line 1358 of file Chord.cc.

Referenced by initializeOverlay().

01360 {
01361     fingerTable = check_and_cast<ChordFingerTable*>
01362                   (getParentModule()->getSubmodule("fingerTable"));
01363 
01364     successorList = check_and_cast<ChordSuccessorList*>
01365                     (getParentModule()->getSubmodule("successorList"));

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

Reimplemented in oversim::Koorde.

Definition at line 547 of file Chord.cc.

00552 {
00553     bool err;
00554     NodeVector* nextHop;
00555 
00556     if (state != READY)
00557         return new NodeVector();
00558 
00559     if (successorList->isEmpty() && !predecessorNode.isUnspecified()) {
00560         throw new cRuntimeError("Chord: Node is READY, has a "
00561                                 "predecessor but no successor!");
00562         join();
00563         return new NodeVector();
00564     }
00565 
00566     // if key is unspecified, the message is for this node
00567     if (key.isUnspecified()) {
00568         nextHop = new NodeVector();
00569         nextHop->push_back(thisNode);
00570     }
00571 
00572     // the message is destined for this node
00573     else if (isSiblingFor(thisNode, key, 1, &err)) {
00574         nextHop = new NodeVector();
00575         nextHop->push_back(thisNode);
00576         for (uint32_t i = 0; i < successorList->getSize(); i++) {
00577             nextHop->push_back(successorList->getSuccessor(i));
00578         }
00579         nextHop->downsizeTo(numSiblings);
00580     }
00581 
00582     // the message destined for our successor
00583     else if (key.isBetweenR(thisNode.getKey(),
00584                             successorList->getSuccessor().getKey())) {
00585         nextHop = new NodeVector();
00586         for (uint32_t i = 0; i < successorList->getSize(); i++) {
00587             nextHop->push_back(successorList->getSuccessor(i));
00588         }
00589         nextHop->downsizeTo(numRedundantNodes);
00590     }
00591 
00592     // find next hop with finger table and/or successor list
00593     else {
00594         nextHop = closestPreceedingNode(key);
00595         nextHop->downsizeTo(numRedundantNodes);
00596     }
00597 
00598     return nextHop;

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

collects statistical data in derived class

Reimplemented from BaseOverlay.

Reimplemented in oversim::Koorde.

Definition at line 725 of file Chord.cc.

00727 {
00728     // remove this node from the bootstrap list
00729     bootstrapList->removeBootstrapNode(thisNode);
00730 
00731     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00732     if (time < GlobalStatistics::MIN_MEASURED) return;
00733 
00734     globalStatistics->addStdDev("Chord: Sent JOIN Messages/s",
00735                                 joinCount / time);
00736     globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Messages/s",
00737                                 newsuccessorhintCount / time);
00738     globalStatistics->addStdDev("Chord: Sent STABILIZE Messages/s",
00739                                 stabilizeCount / time);
00740     globalStatistics->addStdDev("Chord: Sent NOTIFY Messages/s",
00741                                 notifyCount / time);
00742     globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Messages/s",
00743                                 fixfingersCount / time);
00744     globalStatistics->addStdDev("Chord: Sent JOIN Bytes/s",
00745                                 joinBytesSent / time);
00746     globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Bytes/s",
00747                                 newsuccessorhintBytesSent / time);
00748     globalStatistics->addStdDev("Chord: Sent STABILIZE Bytes/s",
00749                                 stabilizeBytesSent / time);
00750     globalStatistics->addStdDev("Chord: Sent NOTIFY Bytes/s",
00751                                 notifyBytesSent / time);
00752     globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Bytes/s",
00753                                 fixfingersBytesSent / time);

int oversim::Chord::getMaxNumRedundantNodes (  )  [protected, virtual]

Query the maximum number of redundant next hop nodes that are returned by findNode().

Returns:
int number of redundant nodes returned by findNode().

Reimplemented from BaseOverlay.

Definition at line 415 of file Chord.cc.

00417 {
00418     return extendedFingerTable ? numFingerCandidates : 1;

int oversim::Chord::getMaxNumSiblings (  )  [protected, virtual]

Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.

Returns:
int number of siblings.

Reimplemented from BaseOverlay.

Definition at line 410 of file Chord.cc.

Referenced by isSiblingFor().

00412 {
00413     return successorListSize;

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

Reimplemented in oversim::Koorde.

Definition at line 501 of file Chord.cc.

Referenced by handleRpcTimeout(), pingTimeout(), and proxCallback().

00503 {
00504     Enter_Method_Silent();
00505 
00506     if (!predecessorNode.isUnspecified() && failed == predecessorNode)
00507         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00508 
00509     //TODO const reference -> trying to compare unspec NH
00510     TransportAddress oldSuccessor = successorList->getSuccessor();
00511 
00512     if (successorList->handleFailedNode(failed))
00513         updateTooltip();
00514     // check pointer for koorde
00515     if (fingerTable != NULL)
00516         fingerTable->handleFailedNode(failed);
00517 
00518     // if we had a ring consisting of 2 nodes and our successor seems
00519     // to be dead. Remove also predecessor because the successor
00520     // and predecessor are the same node
00521     if ((!predecessorNode.isUnspecified()) &&
00522         oldSuccessor == predecessorNode) {
00523         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00524         callUpdate(predecessorNode, false);
00525     }
00526 
00527     if (failed == oldSuccessor) {
00528         // schedule next stabilization process
00529         if (memorizeFailedSuccessor) {
00530             failedSuccessor = oldSuccessor;
00531         }
00532         cancelEvent(stabilize_timer);
00533         scheduleAt(simTime(), stabilize_timer);
00534     }
00535 
00536     if (state != READY) return true;
00537 
00538     if (successorList->isEmpty()) {
00539         // lost our last successor - cancel periodic stabilize tasks
00540         // and wait for rejoin
00541         cancelEvent(stabilize_timer);
00542         cancelEvent(fixfingers_timer);
00543     }
00544 
00545     return !(successorList->isEmpty());

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

handle a expired fix_fingers timer

Parameters:
msg the timer self-message

Definition at line 844 of file Chord.cc.

Referenced by oversim::Koorde::handleTimerEvent(), and handleTimerEvent().

00846 {
00847     if ((state != READY) || successorList->isEmpty())
00848         return;
00849 
00850     OverlayKey offset, lookupKey;
00851     for (uint32_t nextFinger = 0; nextFinger < thisNode.getKey().getLength();
00852          nextFinger++) {
00853         // calculate "n + 2^(i - 1)"
00854         offset = OverlayKey::pow2(nextFinger);
00855         lookupKey = thisNode.getKey() + offset;
00856 
00857         // send message only for non-trivial fingers
00858         if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
00859             // call FIXFINGER RPC
00860             FixfingersCall* call = new FixfingersCall("FixfingersCall");
00861             call->setFinger(nextFinger);
00862             call->setBitLength(FIXFINGERSCALL_L(call));
00863 
00864             sendRouteRpcCall(OVERLAY_COMP, lookupKey, call, NULL,
00865                              DEFAULT_ROUTING, fixfingersDelay);
00866         } else {
00867             // delete trivial fingers (points to the successor node)
00868             fingerTable->removeFinger(nextFinger);
00869         }
00870     }
00871 
00872     // schedule next finger repair process
00873     cancelEvent(fixfingers_timer);
00874     scheduleAt(simTime() + fixfingersDelay, msg);

void oversim::Chord::handleJoinTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired join timer

Parameters:
msg the timer self-message

Definition at line 757 of file Chord.cc.

Referenced by handleTimerEvent().

00759 {
00760     // only process timer, if node is not bootstrapped yet
00761     if (state == READY)
00762         return;
00763 
00764     // enter state BOOTSTRAP
00765     if (state != BOOTSTRAP)
00766         changeState(BOOTSTRAP);
00767 
00768     // change bootstrap node from time to time
00769     joinRetry--;
00770     if (joinRetry == 0) {
00771         joinRetry = par("joinRetry");
00772         changeState(BOOTSTRAP);
00773         return;
00774     }
00775 
00776     // call JOIN RPC
00777     JoinCall* call = new JoinCall("JoinCall");
00778     call->setBitLength(JOINCALL_L(call));
00779 
00780     RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00781                                defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
00782                               SEMI_RECURSIVE_ROUTING : defaultRoutingType;
00783 
00784     sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, thisNode.getKey(),
00785                      call, NULL, routingType, joinDelay);
00786 
00787     // schedule next bootstrap process in the case this one fails
00788     cancelEvent(join_timer);
00789     scheduleAt(simTime() + joinDelay, msg);

void oversim::Chord::handleNewSuccessorHint ( ChordMessage *  chordMsg  )  [protected, virtual]

handle a received NEWSUCCESSORHINT message

Parameters:
chordMsg the message to process

Definition at line 877 of file Chord.cc.

Referenced by handleUDPMessage().

00879 {
00880     NewSuccessorHintMessage* newSuccessorHintMsg =
00881         check_and_cast<NewSuccessorHintMessage*>(chordMsg);
00882 
00883     // fetch the successor's predecessor
00884     NodeHandle predecessor = newSuccessorHintMsg->getPreNode();
00885 
00886     // is the successor's predecessor a new successor for this node?
00887     if (predecessor.getKey().isBetween(thisNode.getKey(),
00888                                   successorList->getSuccessor().getKey())
00889         || (thisNode.getKey() == successorList->getSuccessor().getKey())) {
00890         // add the successor's predecessor to the successor list
00891         successorList->addSuccessor(predecessor);
00892         updateTooltip();
00893     }
00894 
00895     // if the successor node reports a new successor, put it into the
00896     // successor list and start stabilizing
00897     if (mergeOptimizationL3) {
00898         if (successorList->getSuccessor() == predecessor) {
00899             StabilizeCall *call = new StabilizeCall("StabilizeCall");
00900             call->setBitLength(STABILIZECALL_L(call));
00901 
00902             sendUdpRpcCall(predecessor, call);
00903         } else {
00904             if (successorList->getSuccessor() == newSuccessorHintMsg->
00905                                                                getSrcNode()) {
00906 
00907                 StabilizeCall *call = new StabilizeCall("StabilizeCall");
00908                 call->setBitLength(STABILIZECALL_L(call));
00909 
00910                 sendUdpRpcCall(predecessor, call);
00911             }
00912         }
00913     }

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

Processes Remote-Procedure-Call invocation messages.


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

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

Reimplemented in oversim::Koorde.

Definition at line 293 of file Chord.cc.

00295 {
00296     if (state != READY) {
00297         EV << "[Chord::handleRpcCall() @ " << thisNode.getAddress()
00298            << " (" << thisNode.getKey().toString(16) << ")]\n"
00299            << "    Received RPC call and state != READY"
00300            << endl;
00301         return false;
00302     }
00303 
00304     // delegate messages
00305     RPC_SWITCH_START( msg )
00306     // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
00307     RPC_DELEGATE( Join, rpcJoin );
00308     RPC_DELEGATE( Notify, rpcNotify );
00309     RPC_DELEGATE( Stabilize, rpcStabilize );
00310     RPC_DELEGATE( Fixfingers, rpcFixfingers );
00311     RPC_SWITCH_END( )
00312 
00313     return RPC_HANDLED;

void oversim::Chord::handleRpcFixfingersResponse ( FixfingersResponse *  fixfingersResponse,
double  rtt = -1 
) [protected, virtual]

Definition at line 1256 of file Chord.cc.

Referenced by handleRpcResponse().

01259 {
01260     /*
01261     OverlayCtrlInfo* ctrlInfo =
01262         check_and_cast<OverlayCtrlInfo*>(fixfingersResponse->getControlInfo());
01263 
01264     RECORD_STATS(globalStatistics->recordOutVector("Chord: FIX_FINGERS response Hop Count", ctrlInfo->getHopCount()));
01265      */
01266 
01267     // set new finger pointer#
01268     if (!extendedFingerTable) {
01269         fingerTable->setFinger(fixfingersResponse->getFinger(),
01270                                fixfingersResponse->getSucNode(0));
01271     } else {
01272         Successors successors;
01273         for (unsigned int i = 0; i < fixfingersResponse->getSucNodeArraySize();
01274              i++) {
01275             if (fixfingersResponse->getSucNode(i).isUnspecified())
01276                 continue;
01277             if (fixfingersResponse->getSucNode(i) == thisNode)
01278                 break;
01279             successors.insert(std::make_pair(MAXTIME,
01280                                              fixfingersResponse->getSucNode(i)));
01281         }
01282 
01283         if (successors.size() == 0) {
01284             return;
01285         }
01286 
01287         fingerTable->setFinger(fixfingersResponse->getFinger(), successors);
01288 
01289 #if 0
01290         if (proximityRouting || globalParameters->getTopologyAdaptation()) {
01291 #else
01292         if (proximityRouting) {
01293 #endif
01294             for (unsigned int i = 0;
01295                  i < fixfingersResponse->getSucNodeArraySize();
01296                  i++) {
01297                 if (fixfingersResponse->getSucNode(i).isUnspecified())
01298                     continue;
01299                 if (fixfingersResponse->getSucNode(i) == thisNode)
01300                     break;
01301                 //pingNode(fixfingersResponse->getSucNode(i), -1, 0, NULL,
01302                 //         NULL, NULL, fixfingersResponse->getFinger(),
01303                 //         INVALID_TRANSPORT);
01304                 Prox prox =
01305                     neighborCache->getProx(fixfingersResponse->getSucNode(i),
01306                                            NEIGHBORCACHE_DEFAULT,
01307                                            fixfingersResponse->getFinger(),
01308                                            this, NULL);
01309                 if (prox == Prox::PROX_TIMEOUT) {
01310                     fingerTable->removeFinger(fixfingersResponse->getFinger());
01311                 } else if (prox != Prox::PROX_UNKNOWN &&
01312                            prox != Prox::PROX_SELF) {
01313                     fingerTable->updateFinger(fixfingersResponse->getFinger(),
01314                                               fixfingersResponse->getSucNode(i),
01315                                               prox.proximity);
01316                 }
01317             }
01318         }
01319     }

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

Reimplemented in oversim::Koorde.

Definition at line 987 of file Chord.cc.

Referenced by handleRpcResponse().

00989 {
00990     // determine the numer of successor nodes to add
00991     int sucNum = successorListSize - 1;
00992 
00993     if (joinResponse->getSucNum() < successorListSize - 1) {
00994         sucNum = joinResponse->getSucNum();
00995     }
00996 
00997     // add successor getNode(s)
00998     for (int k = 0; k < sucNum; k++) {
00999         NodeHandle successor = joinResponse->getSucNode(k);
01000         successorList->addSuccessor(successor);
01001     }
01002 
01003     // the sender of this message is our new successor
01004     successorList->addSuccessor(joinResponse->getSrcNode());
01005 
01006     // in aggressiveJoinMode: use hint in JoinResponse
01007     // to set our new predecessor
01008     if (aggressiveJoinMode) {
01009         // it is possible that the joinResponse doesn't contain a valid
01010         // predecessor especially when merging two partitions
01011         if (!joinResponse->getPreNode().isUnspecified()) {
01012             if (!predecessorNode.isUnspecified()) {
01013 
01014 
01015                 // inform the original predecessor about the new predecessor
01016                 if (mergeOptimizationL2) {
01017                     NewSuccessorHintMessage* newSuccessorHintMsg =
01018                         new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01019                     newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01020                     newSuccessorHintMsg->setSrcNode(thisNode);
01021                     newSuccessorHintMsg->setPreNode(joinResponse->getPreNode());
01022                     newSuccessorHintMsg->
01023                         setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01024 
01025                     sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
01026                 }
01027             }
01028 
01029             NodeHandle oldPredecessor = predecessorNode;
01030             predecessorNode = joinResponse->getPreNode();
01031 
01032             if (!oldPredecessor.isUnspecified()
01033                 && !joinResponse->getPreNode().isUnspecified()
01034                 && oldPredecessor != joinResponse->getPreNode()) {
01035                 callUpdate(oldPredecessor, false);
01036             }
01037             callUpdate(predecessorNode, true);
01038         }
01039     }
01040 
01041     updateTooltip();
01042 
01043     changeState(READY);
01044 
01045     // immediate stabilization protocol
01046     cancelEvent(stabilize_timer);
01047     scheduleAt(simTime(), stabilize_timer);
01048 
01049     // immediate finger repair protocol
01050     cancelEvent(fixfingers_timer);
01051     scheduleAt(simTime(), fixfingers_timer);

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

Definition at line 1191 of file Chord.cc.

Referenced by handleRpcResponse().

01193 {
01194     if (state != READY) {
01195         return;
01196     }
01197 
01198     if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
01199         EV << "[Chord::handleRpcNotifyResponse() @ " << thisNode.getAddress()
01200            << " (" << thisNode.getKey().toString(16) << ")]\n"
01201            << "    The srcNode of the received NotifyResponse is not our "
01202            << " current successor"
01203            << endl;
01204         return;
01205     }
01206 
01207     // if the NotifyResponse sender couldn't accept me as predecessor,
01208     // put its predecessor into the successor list and starts stabilizing
01209     if (mergeOptimizationL3) {
01210         if (!notifyResponse->getPreNodeSet()) {
01211             StabilizeCall *call = new StabilizeCall("StabilizeCall");
01212             call->setBitLength(STABILIZECALL_L(call));
01213 
01214             successorList->addSuccessor(notifyResponse->getPreNode());
01215             if (successorList->getSuccessor() == notifyResponse->getPreNode())
01216                 sendUdpRpcCall(notifyResponse->getPreNode(), call);
01217             return;
01218         }
01219     }
01220 
01221     // replace our successor list by our successor's successor list
01222     successorList->updateList(notifyResponse);
01223 
01224     updateTooltip();

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

Reimplemented in oversim::Koorde.

Definition at line 315 of file Chord.cc.

00319 {
00320     RPC_SWITCH_START(msg)
00321     RPC_ON_RESPONSE( Join ) {
00322         handleRpcJoinResponse(_JoinResponse);
00323         EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00324         << " (" << thisNode.getKey().toString(16) << ")]\n"
00325         << "    Received a Join RPC Response: id=" << rpcId << "\n"
00326         << "    msg=" << *_JoinResponse << " rtt=" << rtt
00327         << endl;
00328         break;
00329     }
00330     RPC_ON_RESPONSE( Notify ) {
00331         handleRpcNotifyResponse(_NotifyResponse);
00332         EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00333         << " (" << thisNode.getKey().toString(16) << ")]\n"
00334         << "    Received a Notify RPC Response: id=" << rpcId << "\n"
00335         << "    msg=" << *_NotifyResponse << " rtt=" << rtt
00336         << endl;
00337         break;
00338     }
00339     RPC_ON_RESPONSE( Stabilize ) {
00340         handleRpcStabilizeResponse(_StabilizeResponse);
00341         EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00342         << " (" << thisNode.getKey().toString(16) << ")]\n"
00343         << "    Received a Stabilize RPC Response: id=" << rpcId << "\n"
00344         << "    msg=" << *_StabilizeResponse << " rtt=" << rtt
00345         << endl;
00346         break;
00347     }
00348     RPC_ON_RESPONSE( Fixfingers ) {
00349         handleRpcFixfingersResponse(_FixfingersResponse, SIMTIME_DBL(rtt));
00350         EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00351         << " (" << thisNode.getKey().toString(16) << ")]\n"
00352         << "    Received a Fixfingers RPC Response: id=" << rpcId << "\n"
00353         << "    msg=" << *_FixfingersResponse << " rtt=" << rtt
00354         << endl;
00355         break;
00356     }
00357     RPC_SWITCH_END( )

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

Definition at line 1071 of file Chord.cc.

Referenced by handleRpcResponse().

01073 {
01074     if (state != READY) {
01075         return;
01076     }
01077 
01078     // fetch the successor's predecessor
01079     const NodeHandle& predecessor = stabilizeResponse->getPreNode();
01080 
01081     // is the successor's predecessor a new successor for this node?
01082     if ((successorList->isEmpty() ||
01083          predecessor.getKey().isBetween(thisNode.getKey(),
01084                                   successorList->getSuccessor().getKey())) &&
01085         (failedSuccessor.isUnspecified() || failedSuccessor != predecessor)) {
01086         if (successorList->isEmpty() && predecessor.isUnspecified()) {
01087             // successor is emptry and the sender of the response has
01088             // no predecessor => take the sender as new successor
01089             successorList->addSuccessor(stabilizeResponse->getSrcNode());
01090         } else {
01091             // add the successor's predecessor to the successor list
01092             successorList->addSuccessor(predecessor);
01093         }
01094         updateTooltip();
01095     }
01096 
01097     // compile NOTIFY RPC
01098     NotifyCall* notifyCall = new NotifyCall("NotifyCall");
01099     notifyCall->setBitLength(NOTIFYCALL_L(notifyCall));
01100     notifyCall->setFailed(failedSuccessor);
01101     failedSuccessor = TransportAddress::UNSPECIFIED_NODE;
01102 
01103     sendUdpRpcCall(successorList->getSuccessor(), notifyCall);

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

Reimplemented in oversim::Koorde.

Definition at line 359 of file Chord.cc.

00364 {
00365     RPC_SWITCH_START(msg)
00366     RPC_ON_CALL( FindNode ) {
00367         EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00368         << " (" << thisNode.getKey().toString(16) << ")]\n"
00369         << "    FindNode RPC Call timed out: id=" << rpcId << "\n"
00370         << "    msg=" << *_FindNodeCall
00371         << endl;
00372         break;
00373     }
00374     RPC_ON_CALL( Join ) {
00375         EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00376         << " (" << thisNode.getKey().toString(16) << ")]\n"
00377         << "    Join RPC Call timed out: id=" << rpcId << "\n"
00378         << "    msg=" << *_JoinCall
00379         << endl;
00380         break;
00381     }
00382     RPC_ON_CALL( Notify ) {
00383         EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00384         << " (" << thisNode.getKey().toString(16) << ")]\n"
00385         << "    Notify RPC Call timed out: id=" << rpcId << "\n"
00386         << "    msg=" << *_NotifyCall
00387         << endl;
00388         if (!handleFailedNode(dest)) join();
00389         break;
00390     }
00391     RPC_ON_CALL( Stabilize ) {
00392         EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00393         << " (" << thisNode.getKey().toString(16) << ")]\n"
00394         << "    Stabilize RPC Call timed out: id=" << rpcId << "\n"
00395         << "    msg=" << *_StabilizeCall
00396         << endl;
00397         if (!handleFailedNode(dest)) join();
00398         break;
00399     }
00400     RPC_ON_CALL( Fixfingers ) {
00401         EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00402         << " (" << thisNode.getKey().toString(16) << ")]\n"
00403         << "    Fixfingers RPC Call timed out: id=" << rpcId << "\n"
00404         << "    msg=" << *_FixfingersCall
00405         << endl;
00406         break;
00407     }
00408     RPC_SWITCH_END( )

void oversim::Chord::handleStabilizeTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired stabilize timer

Parameters:
msg the timer self-message

Definition at line 792 of file Chord.cc.

Referenced by handleTimerEvent().

00794 {
00795     if (state != READY)
00796         return;
00797 
00798     // alternative predecessor check
00799     if ((checkPredecessorDelay == 0) &&
00800         (missingPredecessorStabRequests >= stabilizeRetry)) {
00801         // predecessor node seems to be dead
00802         // remove it from the predecessor / successor lists
00803         //successorList->removeSuccessor(predecessorNode);
00804         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00805         missingPredecessorStabRequests = 0;
00806         updateTooltip();
00807         callUpdate(predecessorNode, false);
00808     }
00809 
00810     if (!successorList->isEmpty()) {
00811         // call STABILIZE RPC
00812         StabilizeCall* call = new StabilizeCall("StabilizeCall");
00813         call->setBitLength(STABILIZECALL_L(call));
00814 
00815         sendUdpRpcCall(successorList->getSuccessor(), call);
00816 
00817         missingPredecessorStabRequests++;
00818     }
00819 
00820     // check if fingers are still alive and remove unreachable finger nodes
00821     if (mergeOptimizationL4) {
00822         OverlayKey offset;
00823         for (uint32_t nextFinger = 0; nextFinger < thisNode.getKey().getLength();
00824              nextFinger++) {
00825             offset = OverlayKey::pow2(nextFinger);
00826 
00827             // send message only for non-trivial fingers
00828             if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
00829                 if ((fingerTable->getFinger(nextFinger)).isUnspecified()) {
00830                     continue;
00831                 } else {
00832                     pingNode(fingerTable->getFinger(nextFinger), -1, 0, NULL,
00833                              NULL, NULL, nextFinger);
00834                 }
00835             }
00836         }
00837     }
00838 
00839     // schedule next stabilization process
00840     cancelEvent(stabilize_timer);
00841     scheduleAt(simTime() + stabilizeDelay, msg);

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

Reimplemented from BaseRpc.

Reimplemented in oversim::Koorde.

Definition at line 248 of file Chord.cc.

00250 {
00251     // catch JOIN timer
00252     if (msg == join_timer) {
00253         handleJoinTimerExpired(msg);
00254     }
00255     // catch STABILIZE timer
00256     else if (msg == stabilize_timer) {
00257         handleStabilizeTimerExpired(msg);
00258     }
00259     // catch FIX_FINGERS timer
00260     else if (msg == fixfingers_timer) {
00261         handleFixFingersTimerExpired(msg);
00262     }
00263     // catch CHECK_PREDECESSOR timer
00264     else if (msg == checkPredecessor_timer) {
00265         cancelEvent(checkPredecessor_timer);
00266         scheduleAt(simTime() + checkPredecessorDelay,
00267                    checkPredecessor_timer);
00268         if (!predecessorNode.isUnspecified()) pingNode(predecessorNode);
00269     }
00270     // unknown self message
00271     else {
00272         error("Chord::handleTimerEvent(): received self message of "
00273               "unknown type!");
00274     }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Reimplemented in oversim::Koorde.

Definition at line 277 of file Chord.cc.

00279 {
00280     ChordMessage* chordMsg = check_and_cast<ChordMessage*>(msg);
00281     switch(chordMsg->getCommand()) {
00282     case NEWSUCCESSORHINT:
00283         handleNewSuccessorHint(chordMsg);
00284         break;
00285     default:
00286         error("handleUDPMessage(): Unknown message type!");
00287         break;
00288     }
00289 
00290     delete chordMsg;

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

initializes finger table and successor list

Reimplemented in oversim::Koorde.

Definition at line 1368 of file Chord.cc.

Referenced by changeState().

01370 {
01371     // initialize finger table
01372     fingerTable->initializeTable(thisNode.getKey().getLength(), thisNode, this);
01373 
01374     // initialize successor list
01375     successorList->initializeList(par("successorListSize"), thisNode, this);

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

Reimplemented in oversim::Koorde.

Definition at line 45 of file Chord.cc.

00047 {
00048     // because of IPAddressResolver, we need to wait until interfaces
00049     // are registered, address auto-assignment takes place etc.
00050     if (stage != MIN_STAGE_OVERLAY)
00051         return;
00052 
00053     if (iterativeLookupConfig.merge == true) {
00054         throw cRuntimeError("Chord::initializeOverlay(): "
00055               "Chord doesn't work with iterativeLookupConfig.merge = true!");
00056     }
00057 
00058     // Chord provides KBR services
00059     kbr = true;
00060 
00061     // fetch some parameters
00062     useCommonAPIforward = par("useCommonAPIforward");
00063     successorListSize = par("successorListSize");
00064     joinRetry = par("joinRetry");
00065     stabilizeRetry = par("stabilizeRetry");
00066     joinDelay = par("joinDelay");
00067     stabilizeDelay = par("stabilizeDelay");
00068     fixfingersDelay = par("fixfingersDelay");
00069     checkPredecessorDelay = par("checkPredecessorDelay");
00070     aggressiveJoinMode = par("aggressiveJoinMode");
00071     extendedFingerTable = par("extendedFingerTable");
00072     numFingerCandidates = par("numFingerCandidates");
00073     proximityRouting = par("proximityRouting");
00074     memorizeFailedSuccessor = par("memorizeFailedSuccessor");
00075 
00076     // merging optimizations
00077     mergeOptimizationL1 = par("mergeOptimizationL1");
00078     mergeOptimizationL2 = par("mergeOptimizationL2");
00079     mergeOptimizationL3 = par("mergeOptimizationL3");
00080     mergeOptimizationL4 = par("mergeOptimizationL4");
00081 
00082     keyLength = OverlayKey::getLength();
00083     missingPredecessorStabRequests = 0;
00084 
00085     // statistics
00086     joinCount = 0;
00087     stabilizeCount = 0;
00088     fixfingersCount = 0;
00089     notifyCount = 0;
00090     newsuccessorhintCount = 0;
00091     joinBytesSent = 0;
00092     stabilizeBytesSent = 0;
00093     notifyBytesSent = 0;
00094     fixfingersBytesSent = 0;
00095     newsuccessorhintBytesSent = 0;
00096 
00097     failedSuccessor = TransportAddress::UNSPECIFIED_NODE;
00098 
00099     // find friend modules
00100     findFriendModules();
00101 
00102     // add some watches
00103     WATCH(predecessorNode);
00104     WATCH(thisNode);
00105     WATCH(bootstrapNode);
00106     WATCH(joinRetry);
00107     WATCH(missingPredecessorStabRequests);
00108 
00109     // self-messages
00110     join_timer = new cMessage("join_timer");
00111     stabilize_timer = new cMessage("stabilize_timer");
00112     fixfingers_timer = new cMessage("fixfingers_timer");
00113     checkPredecessor_timer = new cMessage("checkPredecessor_timer");

bool oversim::Chord::isSiblingFor ( const NodeHandle node,
const OverlayKey key,
int  numSiblings,
bool *  err 
) [protected, virtual]

Query if a node is among the siblings for a given key.

Query if a node is among the siblings for a given key. This means, that the nodeId of this node is among the closest numSiblings nodes to the key and that by a local findNode() call all other siblings to this key can be retrieved.

Parameters:
node the NodeHandle
key destination key
numSiblings The nodes knows all numSiblings nodes close to this key
err return false if the range could not be determined
Returns:
bool true, if the node is responsible for the key.

Reimplemented from BaseOverlay.

Definition at line 421 of file Chord.cc.

Referenced by findNode().

00426 {
00427     if (key.isUnspecified())
00428         error("Chord::isSiblingFor(): key is unspecified!");
00429 
00430     if (state != READY) {
00431         *err = true;
00432         return false;
00433     }
00434 
00435     if (numSiblings > getMaxNumSiblings()) {
00436         opp_error("Chord::isSiblingFor(): numSiblings too big!");
00437     }
00438     // set default number of siblings to consider
00439     if (numSiblings == -1) numSiblings = getMaxNumSiblings();
00440 
00441     // if this is the first and only node on the ring, it is responsible
00442     if ((predecessorNode.isUnspecified()) && (node == thisNode)) {
00443         if (successorList->isEmpty() || (node.getKey() == key)) {
00444             *err = false;
00445             return true;
00446         } else {
00447             *err = true;
00448             return false;
00449         }
00450     }
00451 
00452     if ((node == thisNode)
00453          && (key.isBetweenR(predecessorNode.getKey(), thisNode.getKey()))) {
00454 
00455         *err = false;
00456         return true;
00457     }
00458 
00459     NodeHandle prevNode = predecessorNode;
00460     NodeHandle curNode;
00461 
00462     for (int i = -1; i < (int)successorList->getSize();
00463          i++, prevNode = curNode) {
00464 
00465         if (i < 0) {
00466             curNode = thisNode;
00467         } else {
00468             curNode = successorList->getSuccessor(i);
00469         }
00470 
00471         if (node == curNode) {
00472             // is the message destined for curNode?
00473             if (key.isBetweenR(prevNode.getKey(), curNode.getKey())) {
00474                 if (numSiblings <= ((int)successorList->getSize() - i)) {
00475                     *err = false;
00476                     return true;
00477                 } else {
00478                     *err = true;
00479                     return false;
00480                 }
00481             } else {
00482                 // the key doesn't directly belong to this node, but
00483                 // the node could be a sibling for this key
00484                 if (numSiblings <= 1) {
00485                     *err = false;
00486                     return false;
00487                 } else {
00488                     // In Chord we don't know if we belong to the
00489                     // replicaSet of one of our predecessors
00490                     *err = true;
00491                     return false;
00492                 }
00493             }
00494         }
00495     }
00496 
00497     // node is not in our neighborSet
00498     *err = true;
00499     return false;

void oversim::Chord::joinForeignPartition ( const NodeHandle node  )  [protected, virtual]

Join another overlay partition with the given node as bootstrap node.

Join another overlay partition with the given node as bootstrap node. This method is called to join a foreign overlay partition and start the merging process.

Parameters:
node The foreign bootstrap node

Reimplemented from BaseOverlay.

Definition at line 134 of file Chord.cc.

00136 {
00137     Enter_Method_Silent();
00138 
00139     // create a join call and sent to the bootstrap node.
00140     JoinCall *call = new JoinCall("JoinCall");
00141     call->setBitLength(JOINCALL_L(call));
00142 
00143     RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00144                                defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
00145                               SEMI_RECURSIVE_ROUTING : defaultRoutingType;
00146 
00147     sendRouteRpcCall(OVERLAY_COMP, node, thisNode.getKey(),
00148                      call, NULL, routingType, joinDelay);

void oversim::Chord::joinOverlay (  )  [protected, virtual]

Join the overlay with a given nodeID in thisNode.key.

Join the overlay with a given nodeID in thisNode.key. This method may be called by an application to join the overlay with a specific nodeID. It is also called if the node's IP address changes.

Reimplemented from BaseOverlay.

Definition at line 127 of file Chord.cc.

00129 {
00130     changeState(INIT);
00131     changeState(BOOTSTRAP);

void oversim::Chord::pingResponse ( PingResponse *  pingResponse,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [protected, virtual]

Reimplemented from BaseRpc.

Definition at line 1333 of file Chord.cc.

01336 {
01337     EV << "[Chord::pingResponse() @ " << thisNode.getAddress()
01338        << " (" << thisNode.getKey().toString(16) << ")]\n"
01339        << "    Received a Ping RPC Response: id=" << rpcId << "\n"
01340        << "    msg=" << *pingResponse << " rtt=" << rtt
01341        << endl;
01342 
01343     if (rpcId != -1)
01344         fingerTable->updateFinger(rpcId, pingResponse->getSrcNode(), rtt);

void oversim::Chord::pingTimeout ( PingCall *  pingCall,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId 
) [protected, virtual]

Reimplemented from BaseRpc.

Definition at line 1346 of file Chord.cc.

01350 {
01351     EV << "[Chord::pingTimeout() @ " << thisNode.getAddress()
01352        << " (" << thisNode.getKey().toString(16) << ")]\n"
01353        << "    Ping RPC timeout: id=" << rpcId << endl;
01354 
01355     // call join dependant on return value?
01356     handleFailedNode(dest);

void oversim::Chord::proxCallback ( const TransportAddress node,
int  rpcId,
cPolymorphic *  contextPointer,
Prox  prox 
) [virtual]

Implements ProxListener.

Definition at line 1321 of file Chord.cc.

01324 {
01325     if (prox == Prox::PROX_TIMEOUT) {
01326         // call join dependant on return value?
01327         handleFailedNode(node);
01328         return;
01329     }
01330 
01331     fingerTable->updateFinger(rpcId, (NodeHandle&)node, prox.proximity);

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

Reimplemented in oversim::Koorde.

Definition at line 675 of file Chord.cc.

00677 {
00678     BaseOverlayMessage* innerMsg = msg;
00679     while (innerMsg->getType() != APPDATA &&
00680            innerMsg->getEncapsulatedPacket() != NULL) {
00681         innerMsg =
00682             static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedPacket());
00683     }
00684 
00685     switch (innerMsg->getType()) {
00686         case OVERLAYSIGNALING: {
00687             ChordMessage* chordMsg = dynamic_cast<ChordMessage*>(innerMsg);
00688             switch(chordMsg->getCommand()) {
00689             case NEWSUCCESSORHINT:
00690                 RECORD_STATS(newsuccessorhintCount++;
00691                              newsuccessorhintBytesSent += msg->getByteLength());
00692                 break;
00693             }
00694             break;
00695         }
00696 
00697         case RPC: {
00698             if ((dynamic_cast<StabilizeCall*>(innerMsg) != NULL) ||
00699                     (dynamic_cast<StabilizeResponse*>(innerMsg) != NULL)) {
00700                 RECORD_STATS(stabilizeCount++; stabilizeBytesSent +=
00701                              msg->getByteLength());
00702             } else if ((dynamic_cast<NotifyCall*>(innerMsg) != NULL) ||
00703                     (dynamic_cast<NotifyResponse*>(innerMsg) != NULL)) {
00704                 RECORD_STATS(notifyCount++; notifyBytesSent +=
00705                              msg->getByteLength());
00706             } else if ((dynamic_cast<FixfingersCall*>(innerMsg) != NULL) ||
00707                     (dynamic_cast<FixfingersResponse*>(innerMsg) != NULL)) {
00708                 RECORD_STATS(fixfingersCount++; fixfingersBytesSent +=
00709                              msg->getByteLength());
00710             } else if ((dynamic_cast<JoinCall*>(innerMsg) != NULL) ||
00711                     (dynamic_cast<JoinResponse*>(innerMsg) != NULL)) {
00712                 RECORD_STATS(joinCount++; joinBytesSent += msg->getByteLength());
00713             }
00714             break;
00715         }
00716 
00717         case APPDATA:
00718             break;
00719 
00720         default:
00721             throw cRuntimeError("Unknown message type!");
00722     }

void oversim::Chord::rpcFixfingers ( FixfingersCall *  call  )  [protected]

Fixfingers Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1227 of file Chord.cc.

Referenced by handleRpcCall().

01229 {
01230     FixfingersResponse* fixfingersResponse =
01231         new FixfingersResponse("FixfingersResponse");
01232 
01233     fixfingersResponse->setSucNodeArraySize(1);
01234     fixfingersResponse->setSucNode(0, thisNode);
01235 
01236     if (extendedFingerTable) {
01237         fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
01238                                                 < numFingerCandidates + 1)
01239                                                 ? successorList->getSize() + 1
01240                                                 : numFingerCandidates + 1));
01241         for (unsigned int i = 0;
01242             i < (((successorList->getSize()) < numFingerCandidates)
01243                  ? (successorList->getSize()) : numFingerCandidates); i++) {
01244 
01245             assert(!successorList->getSuccessor(i).isUnspecified());
01246             fixfingersResponse->setSucNode(i + 1,
01247                                            successorList->getSuccessor(i));
01248         }
01249     }
01250     fixfingersResponse->setFinger(call->getFinger());
01251     fixfingersResponse->setBitLength(FIXFINGERSRESPONSE_L(fixfingersResponse));
01252 
01253     sendRpcResponse(call, fixfingersResponse);

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

Join Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Reimplemented in oversim::Koorde.

Definition at line 916 of file Chord.cc.

Referenced by handleRpcCall().

00918 {
00919     NodeHandle requestor = joinCall->getSrcNode();
00920 
00921     // compile successor list
00922     JoinResponse* joinResponse =
00923         new JoinResponse("JoinResponse");
00924 
00925     int sucNum = successorList->getSize();
00926     joinResponse->setSucNum(sucNum);
00927     joinResponse->setSucNodeArraySize(sucNum);
00928 
00929     for (int k = 0; k < sucNum; k++) {
00930         joinResponse->setSucNode(k, successorList->getSuccessor(k));
00931     }
00932 
00933     // sent our predecessor as hint to the joining node
00934     if (predecessorNode.isUnspecified() && successorList->isEmpty()) {
00935         // we are the only node in the ring
00936         joinResponse->setPreNode(thisNode);
00937     } else {
00938         joinResponse->setPreNode(predecessorNode);
00939     }
00940 
00941     joinResponse->setBitLength(JOINRESPONSE_L(joinResponse));
00942 
00943     sendRpcResponse(joinCall, joinResponse);
00944 
00945     if (aggressiveJoinMode) {
00946         // aggressiveJoinMode differs from standard join operations:
00947         // 1. set our predecessor pointer to the joining node
00948         // 2. send our old predecessor as hint in JoinResponse msgs
00949         // 3. send a NEWSUCCESSORHINT to our old predecessor to update
00950         //    its successor pointer
00951 
00952         // send NEWSUCCESSORHINT to our old predecessor
00953 
00954         if (!predecessorNode.isUnspecified()) {
00955             NewSuccessorHintMessage* newSuccessorHintMsg =
00956                 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
00957             newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
00958 
00959             newSuccessorHintMsg->setSrcNode(thisNode);
00960             newSuccessorHintMsg->setPreNode(requestor);
00961             newSuccessorHintMsg->
00962             setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
00963 
00964             sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
00965         }
00966 
00967         if (predecessorNode.isUnspecified() || (predecessorNode != requestor)) {
00968             // the requestor is our new predecessor
00969             NodeHandle oldPredecessor = predecessorNode;
00970             predecessorNode = requestor;
00971 
00972             // send update to application if we've got a new predecessor
00973             if (!oldPredecessor.isUnspecified()) {
00974                 callUpdate(oldPredecessor, false);
00975             }
00976             callUpdate(predecessorNode, true);
00977 
00978         }
00979     }
00980 
00981     // if we don't have a successor, the requestor is also our new successor
00982     if (successorList->isEmpty())
00983         successorList->addSuccessor(requestor);
00984 
00985     updateTooltip();

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

NOTIFY Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1105 of file Chord.cc.

Referenced by handleRpcCall().

01107 {
01108     // our predecessor seems to be alive
01109     if (!predecessorNode.isUnspecified() &&
01110         call->getSrcNode() == predecessorNode) {
01111         missingPredecessorStabRequests = 0;
01112     }
01113 
01114     bool newPredecessorSet = false;
01115 
01116     NodeHandle newPredecessor = call->getSrcNode();
01117 
01118     // is the new predecessor closer than the current one?
01119     if (predecessorNode.isUnspecified() ||
01120         newPredecessor.getKey().isBetween(predecessorNode.getKey(), thisNode.getKey()) ||
01121         (!call->getFailed().isUnspecified() &&
01122          call->getFailed() == predecessorNode)) {
01123 
01124         if ((predecessorNode.isUnspecified()) ||
01125             (newPredecessor != predecessorNode)) {
01126 
01127             // set up new predecessor
01128             NodeHandle oldPredecessor = predecessorNode;
01129             predecessorNode = newPredecessor;
01130 
01131             if (successorList->isEmpty()) {
01132                 successorList->addSuccessor(newPredecessor);
01133             }
01134 
01135             newPredecessorSet = true;
01136             updateTooltip();
01137 
01138             // send update to application if we've got a new predecessor
01139             if (!oldPredecessor.isUnspecified()) {
01140                 callUpdate(oldPredecessor, false);
01141             }
01142             callUpdate(predecessorNode, true);
01143 
01144             // inform the original predecessor about the new predecessor
01145             if (mergeOptimizationL1) {
01146                 if (!oldPredecessor.isUnspecified()) {
01147                     NewSuccessorHintMessage *newSuccessorHintMsg =
01148                         new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01149                     newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01150 
01151                     newSuccessorHintMsg->setSrcNode(thisNode);
01152                     newSuccessorHintMsg->setPreNode(predecessorNode);
01153                     newSuccessorHintMsg->
01154                         setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01155                     sendMessageToUDP(oldPredecessor, newSuccessorHintMsg);
01156                 }
01157             }
01158 
01159 
01160         }
01161     }
01162 
01163     // compile NOTIFY response
01164     NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
01165 
01166     int sucNum = successorList->getSize();
01167     notifyResponse->setSucNum(sucNum);
01168     notifyResponse->setSucNodeArraySize(sucNum);
01169 
01170     // can't accept the notify sender as predecessor,
01171     // tell it about my correct predecessor
01172     if (mergeOptimizationL3) {
01173         if (!newPredecessorSet && (predecessorNode != newPredecessor)) {
01174 
01175             notifyResponse->setPreNode(predecessorNode);
01176             notifyResponse->setPreNodeSet(false);
01177         } else {
01178             notifyResponse->setPreNodeSet(true);
01179         }
01180     }
01181 
01182     for (int k = 0; k < sucNum; k++) {
01183         notifyResponse->setSucNode(k, successorList->getSuccessor(k));
01184     }
01185 
01186     notifyResponse->setBitLength(NOTIFYRESPONSE_L(notifyResponse));
01187 
01188     sendRpcResponse(call, notifyResponse);

void oversim::Chord::rpcStabilize ( StabilizeCall *  call  )  [protected]

STABILIZE Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1054 of file Chord.cc.

Referenced by handleRpcCall().

01056 {
01057     // our predecessor seems to be alive
01058     if (!predecessorNode.isUnspecified() &&
01059         call->getSrcNode() == predecessorNode) {
01060         missingPredecessorStabRequests = 0;
01061     }
01062 
01063     // reply with StabilizeResponse message
01064     StabilizeResponse* stabilizeResponse =
01065         new StabilizeResponse("StabilizeResponse");
01066     stabilizeResponse->setPreNode(predecessorNode);
01067     stabilizeResponse->setBitLength(STABILIZERESPONSE_L(stabilizeResponse));
01068 
01069     sendRpcResponse(call, stabilizeResponse);

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

updates information shown in tk-environment

Reimplemented in oversim::Koorde.

Definition at line 1378 of file Chord.cc.

Referenced by changeState(), handleFailedNode(), handleNewSuccessorHint(), handleRpcJoinResponse(), handleRpcNotifyResponse(), handleRpcStabilizeResponse(), handleStabilizeTimerExpired(), rpcJoin(), and rpcNotify().

01380 {
01381     if (ev.isGUI()) {
01382         std::stringstream ttString;
01383 
01384         // show our predecessor and successor in tooltip
01385         ttString << predecessorNode << endl << thisNode << endl
01386                  << successorList->getSuccessor();
01387 
01388         getParentModule()->getParentModule()->getDisplayString().
01389         setTagArg("tt", 0, ttString.str().c_str());
01390         getParentModule()->getDisplayString().
01391         setTagArg("tt", 0, ttString.str().c_str());
01392         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
01393 
01394         // draw an arrow to our current successor
01395         showOverlayNeighborArrow(successorList->getSuccessor(), true,
01396                                  "m=m,50,0,50,0;ls=red,1");
01397         showOverlayNeighborArrow(predecessorNode, false,
01398                                  "m=m,50,100,50,100;ls=green,1");
01399     }


Friends And Related Function Documentation

friend class ChordFingerTable [friend]

Definition at line 271 of file Chord.h.

friend class ChordSuccessorList [friend]

Definition at line 270 of file Chord.h.


Member Data Documentation

use modified (faster) JOIN protocol

Definition at line 89 of file Chord.h.

Referenced by handleRpcJoinResponse(), initializeOverlay(), and rpcJoin().

node used to bootstrap

Definition at line 131 of file Chord.h.

Referenced by changeState(), oversim::Koorde::handleDeBruijnTimerExpired(), handleJoinTimerExpired(), and initializeOverlay().

Definition at line 105 of file Chord.h.

Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Chord().

Definition at line 274 of file Chord.h.

Referenced by handleFailedNode(), handleRpcStabilizeResponse(), and initializeOverlay().

cMessage* oversim::Chord::fixfingers_timer [protected]

Definition at line 116 of file Chord.h.

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

Definition at line 110 of file Chord.h.

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

double oversim::Chord::fixfingersDelay [protected]

Definition at line 86 of file Chord.h.

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

cMessage* oversim::Chord::join_timer [protected]

Definition at line 113 of file Chord.h.

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

int oversim::Chord::joinCount [protected]

Definition at line 108 of file Chord.h.

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

double oversim::Chord::joinDelay [protected]

Definition at line 84 of file Chord.h.

Referenced by handleJoinTimerExpired(), initializeOverlay(), and joinForeignPartition().

int oversim::Chord::joinRetry [protected]

Definition at line 82 of file Chord.h.

Referenced by handleJoinTimerExpired(), and initializeOverlay().

int oversim::Chord::keyLength [protected]

length of an overlay key in bits

Definition at line 119 of file Chord.h.

Referenced by initializeOverlay().

Definition at line 93 of file Chord.h.

Referenced by handleFailedNode(), and initializeOverlay().

Definition at line 95 of file Chord.h.

Referenced by initializeOverlay(), and rpcNotify().

Definition at line 96 of file Chord.h.

Referenced by handleRpcJoinResponse(), and initializeOverlay().

Definition at line 98 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), and initializeOverlay().

missing StabilizeCall msgs

Definition at line 120 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), initializeOverlay(), rpcNotify(), and rpcStabilize().

Definition at line 94 of file Chord.h.

Definition at line 117 of file Chord.h.

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

Definition at line 112 of file Chord.h.

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

Definition at line 115 of file Chord.h.

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

int oversim::Chord::notifyCount [protected]

Definition at line 111 of file Chord.h.

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

unsigned int oversim::Chord::numFingerCandidates [protected]

Definition at line 92 of file Chord.h.

Referenced by handleRpcFixfingersResponse(), and initializeOverlay().

cMessage* oversim::Chord::stabilize_timer [protected]

Definition at line 114 of file Chord.h.

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

Definition at line 109 of file Chord.h.

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

double oversim::Chord::stabilizeDelay [protected]

stabilize interval (secs)

Definition at line 85 of file Chord.h.

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

// retries before neighbor considered failed

Definition at line 83 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), and initializeOverlay().

Definition at line 88 of file Chord.h.

Referenced by getMaxNumSiblings(), handleRpcJoinResponse(), 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