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) 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 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 39 of file Chord.cc.

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

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

Definition at line 117 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);
00124 }


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 152 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     }
00246 }

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 602 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;
00674 }

OverlayKey oversim::Chord::distance ( const OverlayKey x,
const OverlayKey y 
) 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
Returns:
OverlayKey Distance between x and y

Reimplemented from BaseOverlay.

Definition at line 1390 of file Chord.cc.

01391 {
01392     return KeyUniRingMetric().distance(x, y);
01393 }

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

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

Reimplemented in oversim::Koorde.

Definition at line 1347 of file Chord.cc.

Referenced by initializeOverlay().

01348 {
01349     fingerTable = check_and_cast<ChordFingerTable*>
01350                   (getParentModule()->getSubmodule("fingerTable"));
01351 
01352     successorList = check_and_cast<ChordSuccessorList*>
01353                     (getParentModule()->getSubmodule("successorList"));
01354 }

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 548 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;
00599 }

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

collects statistical data in derived class

Reimplemented from BaseOverlay.

Reimplemented in oversim::Koorde.

Definition at line 726 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);
00754 }

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 416 of file Chord.cc.

00417 {
00418     return extendedFingerTable ? numFingerCandidates : 1;
00419 }

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 411 of file Chord.cc.

Referenced by isSiblingFor().

00412 {
00413     return successorListSize;
00414 }

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 502 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         callUpdate(predecessorNode, false);
00524         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
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());
00546 }

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

handle a expired fix_fingers timer

Parameters:
msg the timer self-message

Definition at line 845 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);
00875 }

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

handle a expired join timer

Parameters:
msg the timer self-message

Definition at line 758 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);
00790 }

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

handle a received NEWSUCCESSORHINT message

Parameters:
chordMsg the message to process

Definition at line 878 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     }
00914 }

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 294 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;
00314 }

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

Definition at line 1247 of file Chord.cc.

Referenced by handleRpcResponse().

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

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

Reimplemented in oversim::Koorde.

Definition at line 986 of file Chord.cc.

Referenced by handleRpcResponse().

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

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

Definition at line 1182 of file Chord.cc.

Referenced by handleRpcResponse().

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

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 316 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( )
00358 }

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

Definition at line 1068 of file Chord.cc.

Referenced by handleRpcResponse().

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

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 360 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( )
00409 }

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

handle a expired stabilize timer

Parameters:
msg the timer self-message

Definition at line 793 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         callUpdate(predecessorNode, false);
00805         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00806         missingPredecessorStabRequests = 0;
00807         updateTooltip();
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);
00842 }

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

Reimplemented from BaseRpc.

Reimplemented in oversim::Koorde.

Definition at line 249 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     }
00275 }

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 278 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;
00291 }

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

initializes finger table and successor list

Reimplemented in oversim::Koorde.

Definition at line 1357 of file Chord.cc.

Referenced by changeState().

01358 {
01359     // initialize finger table
01360     fingerTable->initializeTable(thisNode.getKey().getLength(), thisNode, this);
01361 
01362     // initialize successor list
01363     successorList->initializeList(par("successorListSize"), thisNode, this);
01364 }

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 46 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");
00114 }

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 422 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;
00500 }

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 135 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);
00149 }

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 128 of file Chord.cc.

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

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

Reimplemented from BaseRpc.

Definition at line 1336 of file Chord.cc.

01339 {
01340     EV << "[Chord::pingTimeout() @ " << thisNode.getAddress()
01341        << " (" << thisNode.getKey().toString(16) << ")]\n"
01342        << "    Ping RPC timeout: id=" << rpcId << endl;
01343 
01344     handleFailedNode(dest);
01345 }

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

Implements ProxListener.

Definition at line 1312 of file Chord.cc.

01314 {
01315     if (prox == Prox::PROX_TIMEOUT) {
01316         handleFailedNode(node);
01317         return;
01318     }
01319 
01320     fingerTable->updateFinger(rpcId, (NodeHandle&)node, prox.proximity);
01321 }

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 676 of file Chord.cc.

00677 {
00678     BaseOverlayMessage* innerMsg = msg;
00679     while (innerMsg->getType() != APPDATA &&
00680            innerMsg->getEncapsulatedMsg() != NULL) {
00681         innerMsg =
00682             static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedMsg());
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     }
00723 }

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

Fixfingers Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1218 of file Chord.cc.

Referenced by handleRpcCall().

01219 {
01220     FixfingersResponse* fixfingersResponse =
01221         new FixfingersResponse("FixfingersResponse");
01222 
01223     fixfingersResponse->setSucNodeArraySize(1);
01224     fixfingersResponse->setSucNode(0, thisNode);
01225 
01226     if (extendedFingerTable) {
01227         fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
01228                                                 < numFingerCandidates + 1)
01229                                                 ? successorList->getSize() + 1
01230                                                 : numFingerCandidates + 1));
01231         for (unsigned int i = 0;
01232             i < (((successorList->getSize()) < numFingerCandidates)
01233                  ? (successorList->getSize()) : numFingerCandidates); i++) {
01234 
01235             assert(!successorList->getSuccessor(i).isUnspecified());
01236             fixfingersResponse->setSucNode(i + 1,
01237                                            successorList->getSuccessor(i));
01238         }
01239     }
01240     fixfingersResponse->setFinger(call->getFinger());
01241     fixfingersResponse->setBitLength(FIXFINGERSRESPONSE_L(fixfingersResponse));
01242 
01243     sendRpcResponse(call, fixfingersResponse);
01244 }

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

Join Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Reimplemented in oversim::Koorde.

Definition at line 917 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             // send update to application if we've got a new predecessor
00969             if (!predecessorNode.isUnspecified()) {
00970                 callUpdate(predecessorNode, false);
00971             }
00972             callUpdate(requestor, true);
00973 
00974             // the requestor is our new predecessor
00975             predecessorNode = requestor;
00976         }
00977     }
00978 
00979     // if we don't have a successor, the requestor is also our new successor
00980     if (successorList->isEmpty())
00981         successorList->addSuccessor(requestor);
00982 
00983     updateTooltip();
00984 }

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

NOTIFY Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1102 of file Chord.cc.

Referenced by handleRpcCall().

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

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

STABILIZE Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1051 of file Chord.cc.

Referenced by handleRpcCall().

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

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

updates information shown in tk-environment

Reimplemented in oversim::Koorde.

Definition at line 1367 of file Chord.cc.

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

01368 {
01369     if (ev.isGUI()) {
01370         std::stringstream ttString;
01371 
01372         // show our predecessor and successor in tooltip
01373         ttString << predecessorNode << endl << thisNode << endl
01374                  << successorList->getSuccessor();
01375 
01376         getParentModule()->getParentModule()->getDisplayString().
01377         setTagArg("tt", 0, ttString.str().c_str());
01378         getParentModule()->getDisplayString().
01379         setTagArg("tt", 0, ttString.str().c_str());
01380         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
01381 
01382         // draw an arrow to our current successor
01383         showOverlayNeighborArrow(successorList->getSuccessor(), true,
01384                                  "m=m,50,0,50,0;ls=red,1");
01385         showOverlayNeighborArrow(predecessorNode, false,
01386                                  "m=m,50,100,50,100;ls=green,1");
01387     }
01388 }


Friends And Related Function Documentation

friend class ChordFingerTable [friend]

Definition at line 269 of file Chord.h.

friend class ChordSuccessorList [friend]

Definition at line 268 of file Chord.h.


Member Data Documentation

use modified (faster) JOIN protocol

Definition at line 87 of file Chord.h.

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

node used to bootstrap

Definition at line 129 of file Chord.h.

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

Definition at line 103 of file Chord.h.

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

Definition at line 272 of file Chord.h.

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

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

Definition at line 114 of file Chord.h.

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

Definition at line 108 of file Chord.h.

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

double oversim::Chord::fixfingersDelay [protected]

Definition at line 84 of file Chord.h.

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

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

Definition at line 111 of file Chord.h.

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

int oversim::Chord::joinCount [protected]

Definition at line 106 of file Chord.h.

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

double oversim::Chord::joinDelay [protected]

Definition at line 82 of file Chord.h.

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

int oversim::Chord::joinRetry [protected]

Definition at line 80 of file Chord.h.

Referenced by handleJoinTimerExpired(), and initializeOverlay().

int oversim::Chord::keyLength [protected]

length of an overlay key in bits

Definition at line 117 of file Chord.h.

Referenced by initializeOverlay().

Definition at line 91 of file Chord.h.

Referenced by handleFailedNode(), and initializeOverlay().

Definition at line 93 of file Chord.h.

Referenced by initializeOverlay(), and rpcNotify().

Definition at line 94 of file Chord.h.

Referenced by handleRpcJoinResponse(), and initializeOverlay().

Definition at line 96 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), and initializeOverlay().

missing StabilizeCall msgs

Definition at line 118 of file Chord.h.

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

Definition at line 92 of file Chord.h.

Definition at line 115 of file Chord.h.

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

Definition at line 110 of file Chord.h.

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

Definition at line 113 of file Chord.h.

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

int oversim::Chord::notifyCount [protected]

Definition at line 109 of file Chord.h.

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

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

Definition at line 90 of file Chord.h.

Referenced by handleRpcFixfingersResponse(), and initializeOverlay().

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

Definition at line 112 of file Chord.h.

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

Definition at line 107 of file Chord.h.

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

double oversim::Chord::stabilizeDelay [protected]

stabilize interval (secs)

Definition at line 83 of file Chord.h.

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

// retries before neighbor considered failed

Definition at line 81 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), and initializeOverlay().

Definition at line 86 of file Chord.h.

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


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

Generated on Tue Sep 8 17:27:03 2009 for OverSim by  doxygen 1.5.8