Chord Class Reference

#include <Chord.h>

Inheritance diagram for Chord:

BaseOverlay BaseRpc TopologyVis RpcListener Koorde

List of all members.


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

Public Member Functions

 Chord ()
virtual ~Chord ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void handleTimerEvent (cMessage *msg)
 Processes "timer" self-messages.
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
virtual void recordOverlaySentStats (BaseOverlayMessage *msg)
 Collect overlay specific sent messages statistics.
virtual void finishOverlay ()
 collects statistical data in derived class
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

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 succesesor list module to our reference.
virtual void initializeFriendModules ()
 initializes finger table and successor list
virtual bool handleRpc (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invokation 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.
void rpcJoin (JoinCall *call)
 Join Remote-Procedure-Call.
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 void predecessorIsDead ()
virtual void successorIsDead ()

Protected Attributes

int joinRetry
int stabilizeRetry
 // retries before neighbor considered failed
double joinDelay
double stabilizeDelay
 stabilize interval (secs)
double fixfingersDelay
int successorListSize
bool aggressiveJoinMode
 use modified (faster) JOIN protocol
bool extendedFingerTable
unsigned int numFingerCandidates
bool proximityRouting
bool mergeOptimizationL1
bool mergeOptimizationL2
bool mergeOptimizationL3
bool mergeOptimizationL4
cMessage * join_timer
cMessage * stabilize_timer
cMessage * fixfingers_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
int missingSuccessorStabResponses
 missing StabilizeResponse msgs
NodeHandle predecessorNode
 predecessor of this node
NodeHandle bootstrapNode
 node used to bootrap
ChordFingerTablefingerTable
 pointer to this node's finger table
ChordSuccessorListsuccessorList
 pointer to this node's successor list

Friends

class ChordSuccessorList

Constructor & Destructor Documentation

Chord::Chord (  ) 

00039 {
00040     stabilize_timer = fixfingers_timer = join_timer = NULL;
00041 }

Chord::~Chord (  )  [virtual]

00114 {
00115     // destroy self timer messages
00116     cancelAndDelete(join_timer);
00117     cancelAndDelete(stabilize_timer);
00118     cancelAndDelete(fixfingers_timer);
00119 }


Member Function Documentation

void 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 Koorde.

Referenced by Koorde::initializeOverlay().

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

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

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from BaseOverlay.

Reimplemented in Koorde.

Referenced by Koorde::handleTimerEvent().

00242 {
00243     // catch JOIN timer
00244     if (msg->isName("join_timer")) {
00245         handleJoinTimerExpired(msg);
00246     }
00247     // catch STABILIZE timer
00248     else if (msg->isName("stabilize_timer")) {
00249         handleStabilizeTimerExpired(msg);
00250     }
00251     // catch FIX_FINGERS timer
00252     else if (msg->isName("fixfingers_timer")) {
00253         handleFixFingersTimerExpired(msg);
00254     }
00255     // unknown self message
00256     else {
00257         error("Chord::handleTimerEvent(): received self message of "
00258               "unknown type!");
00259     }
00260 }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Reimplemented in Koorde.

Referenced by Koorde::handleUDPMessage().

00264 {
00265     ChordMessage* chordMsg = check_and_cast<ChordMessage*>(msg);
00266     switch(chordMsg->getCommand()) {
00267     case NEWSUCCESSORHINT:
00268         handleNewSuccessorHint(chordMsg);
00269         break;
00270     default:
00271         error("handleUDPMessage(): Unknown message type!");
00272         break;
00273     }
00274 
00275     delete chordMsg;
00276 }

void 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 Koorde.

Referenced by Koorde::recordOverlaySentStats().

00609 {
00610     BaseOverlayMessage* innerMsg;
00611 
00612     if (msg->getType() == OVERLAYROUTE)
00613         innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg());
00614     else
00615         innerMsg = msg;
00616 
00617     switch (innerMsg->getType()) {
00618 
00619     case OVERLAYSIGNALING: {
00620         ChordMessage* chordMsg = dynamic_cast<ChordMessage*>(innerMsg);
00621         switch(chordMsg->getCommand()) {
00622         case NEWSUCCESSORHINT:
00623             RECORD_STATS(newsuccessorhintCount++; newsuccessorhintBytesSent +=
00624                              msg->byteLength());
00625             break;
00626         }
00627         break;
00628     }
00629 
00630     case RPC: {
00631         if ((dynamic_cast<StabilizeCall*>(innerMsg) != NULL) ||
00632             (dynamic_cast<StabilizeResponse*>(innerMsg) != NULL)) {
00633             RECORD_STATS(stabilizeCount++; stabilizeBytesSent +=
00634                              msg->byteLength());
00635         } else if ((dynamic_cast<NotifyCall*>(innerMsg) != NULL) ||
00636                    (dynamic_cast<NotifyResponse*>(innerMsg) != NULL)) {
00637             RECORD_STATS(notifyCount++; notifyBytesSent +=
00638                              msg->byteLength());
00639         } else if ((dynamic_cast<FixfingersCall*>(innerMsg) != NULL) ||
00640                    (dynamic_cast<FixfingersResponse*>(innerMsg) != NULL)) {
00641             RECORD_STATS(fixfingersCount++; fixfingersBytesSent +=
00642                              msg->byteLength());
00643         } else if ((dynamic_cast<JoinCall*>(innerMsg) != NULL) ||
00644                    (dynamic_cast<JoinResponse*>(innerMsg) != NULL)) {
00645             RECORD_STATS(joinCount++; joinBytesSent += msg->byteLength());
00646         }
00647         break;
00648     }
00649     }
00650 }

void Chord::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

Reimplemented in Koorde.

Referenced by Koorde::finishOverlay().

00654 {
00655     // remove this node from the bootstrap list
00656     bootstrapList->removeBootstrapNode(thisNode);
00657 
00658     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00659     if(time == 0) return;
00660 
00661     globalStatistics->addStdDev("Chord: Sent JOIN Messages/s",
00662                                 joinCount / time);
00663     globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Messages/s",
00664                                 newsuccessorhintCount / time);
00665     globalStatistics->addStdDev("Chord: Sent STABILIZE Messages/s",
00666                                 stabilizeCount / time);
00667     globalStatistics->addStdDev("Chord: Sent NOTIFY Messages/s",
00668                                 notifyCount / time);
00669     globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Messages/s",
00670                                 fixfingersCount / time);
00671     globalStatistics->addStdDev("Chord: Sent JOIN Bytes/s",
00672                                 joinBytesSent / time);
00673     globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Bytes/s",
00674                                 newsuccessorhintBytesSent / time);
00675     globalStatistics->addStdDev("Chord: Sent STABILIZE Bytes/s",
00676                                 stabilizeBytesSent / time);
00677     globalStatistics->addStdDev("Chord: Sent NOTIFY Bytes/s",
00678                                 notifyBytesSent / time);
00679     globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Bytes/s",
00680                                 fixfingersBytesSent / time);
00681 }

OverlayKey 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.

01294 {
01295     return KeyUniRingMetric().distance(x, y);
01296 }

void Chord::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented in Koorde.

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

01271 {
01272     if (ev.isGUI()) {
01273         std::stringstream ttString;
01274 
01275         // show our predecessor and successor in tooltip
01276         ttString << predecessorNode << endl << thisNode << endl
01277                  << successorList->getSuccessor();
01278 
01279         parentModule()->parentModule()->displayString().
01280         setTagArg("tt", 0, ttString.str().c_str());
01281         parentModule()->displayString().
01282         setTagArg("tt", 0, ttString.str().c_str());
01283         displayString().setTagArg("tt", 0, ttString.str().c_str());
01284 
01285         // draw an arrow to our current successor
01286         showOverlayNeighborArrow(successorList->getSuccessor(), true,
01287                                  "m=m,50,0,50,0;o=red,1");
01288         showOverlayNeighborArrow(predecessorNode, false,
01289                                  "m=m,50,100,50,100;o=green,1");
01290     }
01291 }

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

changes node state

Parameters:
toState state to change to

Reimplemented in Koorde.

Referenced by Koorde::changeState(), handleJoinTimerExpired(), handleRpcJoinResponse(), handleStabilizeTimerExpired(), and joinOverlay().

00148 {
00149     //
00150     // Defines tasks to be executed when a state change occurs.
00151     //
00152 
00153     switch (toState) {
00154     case INIT:
00155         state = INIT;
00156 
00157         setOverlayReady(false);
00158 
00159         if (thisNode.key.isUnspecified()) {
00160             thisNode.key = OverlayKey::random();
00161             callUpdate(thisNode, true);
00162         }
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.ip
00175             << " (" << thisNode.key.toString(16) << ")]\n"
00176             << "    Entered INIT stage"
00177             << endl;
00178         }
00179 
00180         parentModule()->parentModule()->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(simulation.simTime(), join_timer);
00192 
00193         // debug message
00194         if (debugOutput) {
00195             EV << "[Chord::changeState() @ " << thisNode.ip
00196             << " (" << thisNode.key.toString(16) << ")]\n"
00197             << "    Entered BOOTSTRAP stage"
00198             << endl;
00199         }
00200         parentModule()->parentModule()->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             bootstrapNode = thisNode;
00209             changeState(READY);
00210             updateTooltip();
00211         }
00212         break;
00213 
00214     case READY:
00215         state = READY;
00216 
00217         setOverlayReady(true);
00218 
00219         // initiate stabilization protocol
00220         cancelEvent(stabilize_timer);
00221         scheduleAt(simulation.simTime() + stabilizeDelay, stabilize_timer);
00222 
00223         // initiate finger repair protocol
00224         cancelEvent(fixfingers_timer);
00225         scheduleAt(simulation.simTime() + fixfingersDelay,
00226                    fixfingers_timer);
00227 
00228         // debug message
00229         if (debugOutput) {
00230             EV << "[Chord::changeState() @ " << thisNode.ip
00231             << " (" << thisNode.key.toString(16) << ")]\n"
00232             << "    Entered READY stage"
00233             << endl;
00234         }
00235         parentModule()->parentModule()->bubble("Enter READY state.");
00236         break;
00237     }
00238 }

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

handle a expired join timer

Parameters:
msg the timer self-message

Referenced by handleTimerEvent().

00686 {
00687     // only process timer, if node is not bootstrapped yet
00688     if (state == READY)
00689         return;
00690 
00691     // enter state BOOTSTRAP
00692     if (state != BOOTSTRAP)
00693         changeState(BOOTSTRAP);
00694 
00695     // change bootstrap node from time to time
00696     joinRetry--;
00697     if (joinRetry == 0) {
00698         joinRetry = par("joinRetry");
00699         changeState(BOOTSTRAP);
00700         return;
00701     }
00702 
00703     // call JOIN RPC
00704     JoinCall* call = new JoinCall("JoinCall");
00705     call->setLength(JOINCALL_L(call));
00706 
00707     RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00708                                defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
00709                               SEMI_RECURSIVE_ROUTING : defaultRoutingType;
00710 
00711     sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, thisNode.key,
00712                      call, NULL, routingType, joinDelay);
00713 
00714     // schedule next bootstrap process in the case this one fails
00715     cancelEvent(join_timer);
00716     scheduleAt(simulation.simTime() + joinDelay, msg);
00717 }

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

handle a expired stabilize timer

Parameters:
msg the timer self-message

Referenced by handleTimerEvent().

00721 {
00722     if (state != READY)
00723         return;
00724 
00725     if (missingPredecessorStabRequests >= stabilizeRetry) {
00726         // predecessor node seems to be dead
00727         // remove it from the predecessor / successor lists
00728         successorList->removeSuccessor(predecessorNode);
00729         predecessorIsDead();
00730 
00731         callUpdate(predecessorNode, false);
00732         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00733 
00734         missingPredecessorStabRequests = 0;
00735         updateTooltip();
00736     }
00737 
00738     if (missingSuccessorStabResponses >= stabilizeRetry) {
00739         // successor node seems to be dead
00740         // remove it from the predecessor / successor list
00741         successorIsDead();
00742         NodeHandle successor = successorList->popSuccessor();
00743 
00744         // if we had a ring consisting of 2 nodes and our successor seems
00745         // to be dead. Remove also predecessor because the successor
00746         // and predecessor are the same node
00747         if ((!predecessorNode.isUnspecified()) &&
00748             predecessorNode == successor) {
00749             predecessorIsDead();
00750             callUpdate(predecessorNode, false);
00751             predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00752         }
00753 
00754         missingSuccessorStabResponses = 0;
00755         updateTooltip();
00756 
00757         if (successorList->isEmpty()) {
00758             changeState(INIT);
00759             changeState(BOOTSTRAP);
00760             return;
00761         }
00762     }
00763 
00764     if (!successorList->isEmpty()) {
00765         // call STABILIZE RPC
00766         StabilizeCall* call = new StabilizeCall("StabilizeCall");
00767         call->setLength(STABILIZECALL_L(call));
00768 
00769         sendUdpRpcCall(successorList->getSuccessor(), call);
00770 
00771         missingPredecessorStabRequests++;
00772         missingSuccessorStabResponses++;
00773     }
00774 
00775     // check if fingers are still alive and remove unreachable finger nodes
00776     if (mergeOptimizationL4) {
00777         OverlayKey offset;
00778         for (uint nextFinger = 0; nextFinger < thisNode.key.getLength();
00779              nextFinger++) {
00780             offset = OverlayKey::pow2(nextFinger);
00781 
00782             // send message only for non-trivial fingers
00783             if (offset > successorList->getSuccessor().key - thisNode.key) {
00784                 if ((fingerTable->getFinger(nextFinger)).isUnspecified()) {
00785                     continue;
00786                 } else {
00787                     pingNode(fingerTable->getFinger(nextFinger), -1, 0, NULL,
00788                              NULL, NULL, nextFinger);
00789                 }
00790             }
00791         }
00792     }
00793 
00794     // schedule next stabilization process
00795     cancelEvent(stabilize_timer);
00796     scheduleAt(simulation.simTime() + stabilizeDelay, msg);
00797 }

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

handle a expired fix_fingers timer

Parameters:
msg the timer self-message

Reimplemented in Koorde.

Referenced by handleTimerEvent().

00801 {
00802     if ((state != READY) || successorList->isEmpty())
00803         return;
00804 
00805     OverlayKey offset, lookupKey;
00806     for (uint nextFinger = 0; nextFinger < thisNode.key.getLength();
00807          nextFinger++) {
00808         // calculate "n + 2^(i - 1)"
00809         offset = OverlayKey::pow2(nextFinger);
00810         lookupKey = thisNode.key + offset;
00811 
00812         // send message only for non-trivial fingers
00813         if (offset > successorList->getSuccessor().key - thisNode.key) {
00814             // call FIXFINGER RPC
00815             FixfingersCall* call = new FixfingersCall("FixfingersCall");
00816             call->setFinger(nextFinger);
00817             call->setLength(FIXFINGERSCALL_L(call));
00818 
00819             sendRouteRpcCall(OVERLAY_COMP, lookupKey, call, NULL,
00820                              DEFAULT_ROUTING, fixfingersDelay);
00821         } else {
00822             // let trivial fingers point to the successor node
00823             fingerTable->setFinger(nextFinger, successorList->getSuccessor());
00824         }
00825     }
00826 
00827     // schedule next finger repair process
00828     cancelEvent(fixfingers_timer);
00829     scheduleAt(simulation.simTime() + fixfingersDelay, msg);
00830 }

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

handle a received NEWSUCCESSORHINT message

Parameters:
chordMsg the message to process

Referenced by handleUDPMessage().

00834 {
00835     NewSuccessorHintMessage* newSuccessorHintMsg =
00836         check_and_cast<NewSuccessorHintMessage*>(chordMsg);
00837 
00838     // fetch the successor's predecessor
00839     NodeHandle predecessor = newSuccessorHintMsg->getPreNode();
00840 
00841     // is the successor's predecessor a new successor for this node?
00842     if (predecessor.key.isBetween(thisNode.key,
00843                                   successorList->getSuccessor().key)
00844         || (thisNode.key == successorList->getSuccessor().key)) {
00845         // add the successor's predecessor to the successor list
00846         successorList->addSuccessor(predecessor);
00847         updateTooltip();
00848     }
00849 
00850     // if the successor node reports a new successor, put it into the
00851     // successor list and start stabilizing
00852     if (mergeOptimizationL3) {
00853         if (successorList->getSuccessor() == predecessor) {
00854             StabilizeCall *call = new StabilizeCall("StabilizeCall");
00855             call->setLength(STABILIZECALL_L(call));
00856 
00857             sendUdpRpcCall(predecessor, call);
00858         } else {
00859             if (successorList->getSuccessor() == newSuccessorHintMsg->
00860                                                                getSrcNode()) {
00861 
00862                 StabilizeCall *call = new StabilizeCall("StabilizeCall");
00863                 call->setLength(STABILIZECALL_L(call));
00864 
00865                 sendUdpRpcCall(predecessor, call);
00866             }
00867         }
00868     }
00869 }

NodeVector * 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

Referenced by findNode().

00535 {
00536     NodeHandle tempHandle = NodeHandle::UNSPECIFIED_NODE;
00537 
00538     // find the closest preceding node in the successor list
00539     for (int j = successorList->getSize() - 1; j >= 0; j--) {
00540         if(successorList->getSuccessor(j).key.isBetweenR(thisNode.key, key)) {
00541             tempHandle = successorList->getSuccessor(j);
00542             break;
00543         }
00544     }
00545 
00546     if(tempHandle.isUnspecified()) {
00547         std::stringstream temp;
00548         temp << "Chord::closestPreceedingNode(): Successor list broken "
00549              << thisNode.key << " " << key;
00550         throw new cRuntimeError(temp.str().c_str());
00551     }
00552 
00553     NodeVector* nextHop;
00554 
00555     for (int i = fingerTable->getSize() - 1; i >= 0; i--) {
00556         if (fingerTable->getFinger(i).key.isBetweenLR(tempHandle.key, key)) {
00557             if(!extendedFingerTable) {
00558                 nextHop = new NodeVector();
00559                 nextHop->push_back(fingerTable->getFinger(i));
00560 
00561                 EV << "[Chord::closestPreceedingNode() @ " << thisNode.ip
00562                    << " (" << thisNode.key.toString(16) << ")]\n"
00563                    << "    ClosestPreceedingNode: node " << thisNode
00564                    << " for key " << key << "\n"
00565                    << "    finger " << fingerTable->getFinger(i).key
00566                    << " better than \n"
00567                    << "    " << tempHandle.key
00568                    << endl;
00569                 return nextHop;
00570             } else {
00571                 return fingerTable->getFinger(i, key);
00572             }
00573         }
00574     }
00575 
00576     nextHop = new NodeVector();
00577     EV << "[Chord::closestPreceedingNode() @ " << thisNode.ip
00578        << " (" << thisNode.key.toString(16) << ")]\n"
00579        << "    No finger found"
00580        << endl;
00581 
00582     // if no finger is found lookup the rest of the successor list
00583     for(int i = successorList->getSize() - 1; i >= 0
00584         && nextHop->size() <= numFingerCandidates ; i--) {
00585         if(successorList->getSuccessor(i).key.isBetween(thisNode.key, key)) {
00586             nextHop->push_back(successorList->getSuccessor(i));
00587         }
00588     }
00589 
00590     if(nextHop->size() != 0)
00591         return nextHop;
00592 
00593     // if this is the first and only node on the ring, it is responsible
00594     if ((predecessorNode.isUnspecified()) &&
00595         (successorList->getSuccessor() == thisNode)) {
00596         nextHop->push_back(thisNode);
00597         return nextHop;
00598     }
00599 
00600     // if there is still no node found return NodeHandle::UNSPECIFIED_NODE
00601     std::stringstream temp("Error in Chord::closestPreceedingNode()!\n");
00602     temp << thisNode.key << " " << key;
00603     error(temp.str().c_str());
00604     nextHop->push_back(NodeHandle::UNSPECIFIED_NODE);
00605     return nextHop;
00606 }

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

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

Reimplemented in Koorde.

Referenced by initializeOverlay().

01251 {
01252     fingerTable = check_and_cast<ChordFingerTable*>
01253                   (parentModule()->submodule("fingerTable"));
01254 
01255     successorList = check_and_cast<ChordSuccessorList*>
01256                     (parentModule()->submodule("successorList"));
01257 }

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

initializes finger table and successor list

Reimplemented in Koorde.

Referenced by changeState().

01261 {
01262     // initialize finger table
01263     fingerTable->initializeTable(thisNode.key.getLength(), thisNode, this);
01264 
01265     // initialize successor list
01266     successorList->initializeList(par("successorListSize"), thisNode, this);
01267 }

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

Processes Remote-Procedure-Call invokation messages.


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

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

Reimplemented in Koorde.

00280 {
00281     if (state != READY) {
00282 //      delete msg;
00283 //      EV << "[Chord::handleRpc() @ " << thisNode.ip
00284 //         << " (" << thisNode.key.toString(16) << ")]\n"
00285 //         << "    Received RPC call and state != READY"
00286 //         << endl;
00287         return false;
00288     }
00289 
00290     // delegate messages
00291     RPC_SWITCH_START( msg )
00292     // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
00293     RPC_DELEGATE( Join, rpcJoin );
00294     RPC_DELEGATE( Notify, rpcNotify );
00295     RPC_DELEGATE( Stabilize, rpcStabilize );
00296     RPC_DELEGATE( Fixfingers, rpcFixfingers );
00297     RPC_SWITCH_END( )
00298 
00299     return RPC_HANDLED;
00300 }

NodeVector * 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 Koorde.

00491 {
00492     bool err;
00493     NodeVector* nextHop;
00494 
00495     if (state != READY)
00496         return new NodeVector();
00497 
00498     // if key is unspecified, the message is for this node
00499     if (key.isUnspecified()) {
00500         nextHop = new NodeVector();
00501         nextHop->push_back(thisNode);
00502     }
00503 
00504     // the message is destined for this node
00505     else if (isSiblingFor(thisNode, key, 1, &err)) {
00506         nextHop = new NodeVector();
00507         nextHop->push_back(thisNode);
00508         for (uint i = 0; i < successorList->getSize(); i++) {
00509             nextHop->push_back(successorList->getSuccessor(i));
00510         }
00511         nextHop->downsizeTo(numSiblings);
00512     }
00513 
00514     // the message destined for our successor
00515     else if (key.isBetweenR(thisNode.key,
00516                             successorList->getSuccessor().key)) {
00517         nextHop = new NodeVector();
00518         for (uint i = 0; i < successorList->getSize(); i++) {
00519             nextHop->push_back(successorList->getSuccessor(i));
00520         }
00521         nextHop->downsizeTo(numRedundantNodes);
00522     }
00523 
00524     // find next hop with finger table and/or successor list
00525     else {
00526         nextHop = closestPreceedingNode(key);
00527         nextHop->downsizeTo(numRedundantNodes);
00528     }
00529 
00530     return nextHop;
00531 }

void 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.

00124 {
00125     changeState(INIT);
00126     changeState(BOOTSTRAP);
00127 }

void 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.

00131 {
00132     Enter_Method_Silent();
00133 
00134     // create a join call and sent to the bootstrap node.
00135     JoinCall *call = new JoinCall("JoinCall");
00136     call->setLength(JOINCALL_L(call));
00137 
00138     RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00139                                defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
00140                               SEMI_RECURSIVE_ROUTING : defaultRoutingType;
00141 
00142     sendRouteRpcCall(OVERLAY_COMP, node, thisNode.key,
00143                      call, NULL, routingType, joinDelay);
00144 }

bool 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.

Referenced by findNode().

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

int 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.

Referenced by isSiblingFor().

00396 {
00397     return successorListSize;
00398 }

int 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.

00401 {
00402     return extendedFingerTable ? numFingerCandidates : 1;
00403 }

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

Fixfingers Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Referenced by Koorde::handleRpc(), and handleRpc().

01153 {
01154     FixfingersResponse* fixfingersResponse =
01155         new FixfingersResponse("FixfingersResponse");
01156 
01157     fixfingersResponse->setSucNodeArraySize(1);
01158     fixfingersResponse->setSucNode(0, thisNode);
01159 
01160     if (extendedFingerTable) {
01161         fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
01162                                                 < numFingerCandidates + 1)
01163                                                 ? successorList->getSize() + 1
01164                                                 : numFingerCandidates + 1));
01165         for (unsigned int i = 0;
01166             i < (((successorList->getSize()) < numFingerCandidates)
01167                  ? (successorList->getSize()) : numFingerCandidates); i++) {
01168 
01169             assert(!successorList->getSuccessor(i).isUnspecified());
01170             fixfingersResponse->setSucNode(i + 1,
01171                                            successorList->getSuccessor(i));
01172         }
01173     }
01174     fixfingersResponse->setFinger(call->getFinger());
01175     fixfingersResponse->setLength(FIXFINGERSRESPONSE_L(fixfingersResponse));
01176 
01177     sendRpcResponse(call, fixfingersResponse);
01178 }

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

Join Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Referenced by Koorde::handleRpc(), and handleRpc().

00873 {
00874     NodeHandle requestor = joinCall->getSrcNode();
00875 
00876     // compile successor list
00877     JoinResponse* joinResponse =
00878         new JoinResponse("JoinResponse");
00879 
00880     int sucNum = successorList->getSize();
00881     joinResponse->setSucNum(sucNum);
00882     joinResponse->setSucNodeArraySize(sucNum);
00883 
00884     for (int k = 0; k < sucNum; k++) {
00885         joinResponse->setSucNode(k, successorList->getSuccessor(k));
00886     }
00887 
00888     // sent our predecessor as hint to the joining node
00889     if (predecessorNode.isUnspecified() && successorList->isEmpty()) {
00890         // we are the only node in the ring
00891         joinResponse->setPreNode(thisNode);
00892     } else {
00893         joinResponse->setPreNode(predecessorNode);
00894     }
00895 
00896     joinResponse->setLength(JOINRESPONSE_L(joinResponse));
00897 
00898     sendRpcResponse(joinCall, joinResponse);
00899 
00900     if (aggressiveJoinMode) {
00901         // aggressiveJoinMode differs from standard join operations:
00902         // 1. set our predecessor pointer to the joining node
00903         // 2. send our old predecessor as hint in JoinResponse msgs
00904         // 3. send a NEWSUCCESSORHINT to our old predecessor to update
00905         //    its successor pointer
00906 
00907         // send NEWSUCCESSORHINT to our old predecessor
00908 
00909         if (!predecessorNode.isUnspecified()) {
00910             NewSuccessorHintMessage* newSuccessorHintMsg =
00911                 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
00912             newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
00913 
00914             newSuccessorHintMsg->setSrcNode(thisNode);
00915             newSuccessorHintMsg->setPreNode(requestor);
00916             newSuccessorHintMsg->
00917             setLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
00918 
00919             sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
00920         }
00921 
00922         if (predecessorNode.isUnspecified() || (predecessorNode != requestor)) {
00923             // send update to application if we've got a new predecessor
00924             if (!predecessorNode.isUnspecified()) {
00925                 callUpdate(predecessorNode, false);
00926             }
00927             callUpdate(requestor, true);
00928 
00929             // the requestor is our new predecessor
00930             predecessorNode = requestor;
00931         }
00932     }
00933 
00934     // if we don't have a successor, the requestor is also our new successor
00935     if (successorList->isEmpty())
00936         successorList->addSuccessor(requestor);
00937 
00938     updateTooltip();
00939 }

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

NOTIFY Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Reimplemented in Koorde.

Referenced by handleRpc().

01049 {
01050     // our predecessor seems to be alive
01051     missingPredecessorStabRequests = 0;
01052     bool newPredecessorSet = false;
01053 
01054     NodeHandle newPredecessor = call->getSrcNode();
01055 
01056     // is the new predecessor closer than the current one?
01057     if (predecessorNode.isUnspecified() ||
01058         newPredecessor.key.isBetween(predecessorNode.key, thisNode.key)) {
01059 
01060         if ((predecessorNode.isUnspecified()) ||
01061             (newPredecessor != predecessorNode)) {
01062             // send update to application if we've got a new predecessor
01063             if (!predecessorNode.isUnspecified()) {
01064                 callUpdate(predecessorNode, false);
01065             }
01066             callUpdate(newPredecessor, true);
01067 
01068             // inform the original predecessor about the new predecessor
01069             if (mergeOptimizationL1) {
01070                 if (!predecessorNode.isUnspecified()) {
01071                     NewSuccessorHintMessage *newSuccessorHintMsg =
01072                         new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01073                     newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01074 
01075                     newSuccessorHintMsg->setSrcNode(thisNode);
01076                     newSuccessorHintMsg->setPreNode(newPredecessor);
01077                     newSuccessorHintMsg->
01078                         setLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01079                     sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
01080                 }
01081             }
01082 
01083             // set up new predecessor
01084             predecessorNode = newPredecessor;
01085             updateTooltip();
01086 
01087             newPredecessorSet = true;
01088         }
01089     }
01090 
01091     // compile NOTIFY response
01092     NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
01093 
01094     int sucNum = successorList->getSize();
01095     notifyResponse->setSucNum(sucNum);
01096     notifyResponse->setSucNodeArraySize(sucNum);
01097 
01098     // can't accept the notify sender as predecessor,
01099     // tell it about my correct predecessor
01100     if (mergeOptimizationL3) {
01101         if (!newPredecessorSet && (predecessorNode != newPredecessor)) {
01102 
01103             notifyResponse->setPreNode(predecessorNode);
01104             notifyResponse->setPreNodeSet(false);
01105         } else {
01106             notifyResponse->setPreNodeSet(true);
01107         }
01108     }
01109 
01110     for (int k = 0; k < sucNum; k++) {
01111         notifyResponse->setSucNode(k, successorList->getSuccessor(k));
01112     }
01113 
01114     notifyResponse->setLength(NOTIFYRESPONSE_L(notifyResponse));
01115 
01116     sendRpcResponse(call, notifyResponse);
01117 }

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

STABILIZE Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Referenced by Koorde::handleRpc(), and handleRpc().

01010 {
01011     // our predecessor seems to be alive
01012     missingPredecessorStabRequests = 0;
01013 
01014     // reply with StabilizeResponse message
01015     StabilizeResponse* stabilizeResponse =
01016         new StabilizeResponse("StabilizeResponse");
01017     stabilizeResponse->setPreNode(predecessorNode);
01018     stabilizeResponse->setLength(STABILIZERESPONSE_L(stabilizeResponse));
01019 
01020     sendRpcResponse(call, stabilizeResponse);
01021 }

void 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 Koorde.

00305 {
00306     RPC_SWITCH_START(msg)
00307     RPC_ON_RESPONSE( Join ) {
00308         handleRpcJoinResponse(_JoinResponse);
00309         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00310         << " (" << thisNode.key.toString(16) << ")]\n"
00311         << "    Received a Join RPC Response: id=" << rpcId << "\n"
00312         << "    msg=" << *_JoinResponse << " rtt=" << rtt
00313         << endl;
00314         break;
00315     }
00316     RPC_ON_RESPONSE( Notify ) {
00317         handleRpcNotifyResponse(_NotifyResponse);
00318         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00319         << " (" << thisNode.key.toString(16) << ")]\n"
00320         << "    Received a Notify RPC Response: id=" << rpcId << "\n"
00321         << "    msg=" << *_NotifyResponse << " rtt=" << rtt
00322         << endl;
00323         break;
00324     }
00325     RPC_ON_RESPONSE( Stabilize ) {
00326         handleRpcStabilizeResponse(_StabilizeResponse);
00327         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00328         << " (" << thisNode.key.toString(16) << ")]\n"
00329         << "    Received a Stabilize RPC Response: id=" << rpcId << "\n"
00330         << "    msg=" << *_StabilizeResponse << " rtt=" << rtt
00331         << endl;
00332         break;
00333     }
00334     RPC_ON_RESPONSE( Fixfingers ) {
00335         handleRpcFixfingersResponse(_FixfingersResponse, rtt);
00336         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00337         << " (" << thisNode.key.toString(16) << ")]\n"
00338         << "    Received a Fixfingers RPC Response: id=" << rpcId << "\n"
00339         << "    msg=" << *_FixfingersResponse << " rtt=" << rtt
00340         << endl;
00341         break;
00342     }
00343     RPC_SWITCH_END( )
00344 }

void 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 Koorde.

00350 {
00351     RPC_SWITCH_START(msg)
00352     RPC_ON_CALL( FindNode ) {
00353         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00354         << " (" << thisNode.key.toString(16) << ")]\n"
00355         << "    FindNode RPC Call timed out: id=" << rpcId << "\n"
00356         << "    msg=" << *_FindNodeCall
00357         << endl;
00358         break;
00359     }
00360     RPC_ON_CALL( Join ) {
00361         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00362         << " (" << thisNode.key.toString(16) << ")]\n"
00363         << "    Join RPC Call timed out: id=" << rpcId << "\n"
00364         << "    msg=" << *_JoinCall
00365         << endl;
00366         break;
00367     }
00368     RPC_ON_CALL( Notify ) {
00369         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00370         << " (" << thisNode.key.toString(16) << ")]\n"
00371         << "    Notify RPC Call timed out: id=" << rpcId << "\n"
00372         << "    msg=" << *_NotifyCall
00373         << endl;
00374         break;
00375     }
00376     RPC_ON_CALL( Stabilize ) {
00377         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00378         << " (" << thisNode.key.toString(16) << ")]\n"
00379         << "    Stabilize RPC Call timed out: id=" << rpcId << "\n"
00380         << "    msg=" << *_StabilizeCall
00381         << endl;
00382         break;
00383     }
00384     RPC_ON_CALL( Fixfingers ) {
00385         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00386         << " (" << thisNode.key.toString(16) << ")]\n"
00387         << "    Fixfingers RPC Call timed out: id=" << rpcId << "\n"
00388         << "    msg=" << *_FixfingersCall
00389         << endl;
00390         break;
00391     }
00392     RPC_SWITCH_END( )
00393 }

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

Reimplemented from BaseRpc.

01228 {
01229     EV << "[Chord::pingResponse() @ " << thisNode.ip
01230        << " (" << thisNode.key.toString(16) << ")]\n"
01231        << "    Received a Ping RPC Response: id=" << rpcId << "\n"
01232        << "    msg=" << *pingResponse << " rtt=" << rtt
01233        << endl;
01234 
01235     fingerTable->updateFinger(rpcId, pingResponse->getSrcNode(), rtt);
01236 }

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

Reimplemented from BaseRpc.

01241 {
01242     EV << "[Chord::pingTimeout() @ " << thisNode.ip
01243        << " (" << thisNode.key.toString(16) << ")]\n"
01244        << "    Ping RPC timeout: id=" << rpcId << endl;
01245 
01246     if (dest == fingerTable->getFinger(rpcId))
01247         fingerTable->setFinger(rpcId, NodeHandle::UNSPECIFIED_NODE);
01248 }

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

Todo:
check commented out addSuccessor (Schenk)

Reimplemented in Koorde.

Referenced by Koorde::handleRpcJoinResponse(), and handleRpcResponse().

00942 {
00943     // determine the numer of successor nodes to add
00944     int sucNum = successorListSize - 1;
00945 
00946     if (joinResponse->getSucNum() < successorListSize - 1) {
00947         sucNum = joinResponse->getSucNum();
00948     }
00949 
00950     // add successor node(s)
00951     for (int k = 0; k < sucNum; k++) {
00952         NodeHandle successor = joinResponse->getSucNode(k);
00953         successorList->addSuccessor(successor);
00954     }
00955 
00956     // \todo {check commented out addSuccessor (Schenk)}
00957     //successorList->addSuccessor(joinResponse->getSrcNode());
00958 
00959     // the sender of this message is our new successor
00960     successorList->addSuccessor(joinResponse->getSrcNode());
00961 
00962     // in aggressiveJoinMode: use hint in JoinResponse
00963     // to set our new predecessor
00964     if (aggressiveJoinMode) {
00965         // it is possible that the joinResponse doesn't contain a valid
00966         // predecessor especially when merging two partitions
00967         if (!joinResponse->getPreNode().isUnspecified()) {
00968             if (!predecessorNode.isUnspecified()) {
00969 
00970 
00971                 // inform the original predecessor about the new predecessor
00972                 if (mergeOptimizationL2) {
00973                     NewSuccessorHintMessage* newSuccessorHintMsg =
00974                         new NewSuccessorHintMessage("NEWSUCCESSORHINT");
00975                     newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
00976                     newSuccessorHintMsg->setSrcNode(thisNode);
00977                     newSuccessorHintMsg->setPreNode(joinResponse->getPreNode());
00978                     newSuccessorHintMsg->
00979                         setLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
00980 
00981                     sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
00982                 }
00983             }
00984 
00985             if (!predecessorNode.isUnspecified()
00986                 && !joinResponse->getPreNode().isUnspecified()
00987                 && predecessorNode != joinResponse->getPreNode()) {
00988                 callUpdate(predecessorNode, false);
00989             }
00990             predecessorNode = joinResponse->getPreNode();
00991             callUpdate(predecessorNode, true);
00992         }
00993     }
00994 
00995     updateTooltip();
00996 
00997     changeState(READY);
00998 
00999     // immediate stabilization protocol
01000     cancelEvent(stabilize_timer);
01001     scheduleAt(simulation.simTime(), stabilize_timer);
01002 
01003     // immediate finger repair protocol
01004     cancelEvent(fixfingers_timer);
01005     scheduleAt(simulation.simTime(), fixfingers_timer);
01006 }

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

Reimplemented in Koorde.

Referenced by handleRpcResponse().

01121 {
01122     if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
01123         EV << "[Chord::handleRpcNotifyResponse() @ " << thisNode.ip
01124            << " (" << thisNode.key.toString(16) << ")]\n"
01125            << "    The srcNode of the received NotifyResponse is not our "
01126            << " current successor"
01127            << endl;
01128         return;
01129     }
01130 
01131     // if the NotifyResponse sender couldn't accept me as predecessor,
01132     // put its predecessor into the successor list and starts stabilizing
01133     if (mergeOptimizationL3) {
01134         if (!notifyResponse->getPreNodeSet()) {
01135             StabilizeCall *call = new StabilizeCall("StabilizeCall");
01136             call->setLength(STABILIZECALL_L(call));
01137 
01138             successorList->addSuccessor(notifyResponse->getPreNode());
01139             if (successorList->getSuccessor() == notifyResponse->getPreNode())
01140                 sendUdpRpcCall(notifyResponse->getPreNode(), call);
01141             return;
01142         }
01143     }
01144 
01145     // replace our successor list by our successor's successor list
01146     successorList->updateList(notifyResponse);
01147 
01148     updateTooltip();
01149 }

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

Reimplemented in Koorde.

Referenced by handleRpcResponse().

01024 {
01025     // our successor seems to be alive
01026     missingSuccessorStabResponses = 0;
01027 
01028     // fetch the successor's predecessor
01029     NodeHandle predecessor = stabilizeResponse->getPreNode();
01030 
01031     // is the successor's predecessor a new successor for this node?
01032     if (successorList->isEmpty() ||
01033         predecessor.key.isBetween(thisNode.key,
01034                                   successorList->getSuccessor().key)) {
01035         // add the successor's predecessor to the successor list
01036         successorList->addSuccessor(predecessor);
01037         updateTooltip();
01038     }
01039 
01040     // compile NOTIFY RPC
01041     NotifyCall* notifyCall = new NotifyCall("NotifyCall");
01042     notifyCall->setLength(NOTIFYCALL_L(notifyCall));
01043 
01044     sendUdpRpcCall(successorList->getSuccessor(), notifyCall);
01045 }

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

Referenced by Koorde::handleRpcResponse(), and handleRpcResponse().

01183 {
01184     // set new finger pointer#
01185     if (!extendedFingerTable) {
01186         fingerTable->setFinger(fixfingersResponse->getFinger(),
01187                                fixfingersResponse->getSucNode(0));
01188     } else {
01189         Successors successors;
01190         for (unsigned int i = 0; i < fixfingersResponse->getSucNodeArraySize();
01191              i++) {
01192             if (fixfingersResponse->getSucNode(i).isUnspecified())
01193                 continue;
01194             if (fixfingersResponse->getSucNode(i) == thisNode)
01195                 break;
01196             successors.insert(std::make_pair(DBL_MAX,
01197                                              fixfingersResponse->getSucNode(i)));
01198         }
01199 
01200         if (successors.size() == 0) {
01201             return;
01202         }
01203 
01204         fingerTable->setFinger(fixfingersResponse->getFinger(), successors);
01205 
01206 #if 0
01207         if (proximityRouting || globalParameters->getTopologyAdaptation()) {
01208 #else
01209         if (proximityRouting) {
01210 #endif
01211             for (unsigned int i = 0;
01212                  i < fixfingersResponse->getSucNodeArraySize();
01213                  i++) {
01214                 if (fixfingersResponse->getSucNode(i).isUnspecified())
01215                     continue;
01216                 if (fixfingersResponse->getSucNode(i) == thisNode)
01217                     break;
01218                 pingNode(fixfingersResponse->getSucNode(i), -1, 0, NULL,
01219                          NULL, NULL, fixfingersResponse->getFinger());
01220             }
01221         }
01222     }
01223 }

void Chord::predecessorIsDead (  )  [protected, virtual]

Reimplemented in Koorde.

Referenced by handleStabilizeTimerExpired().

01299 {}

void Chord::successorIsDead (  )  [protected, virtual]

Reimplemented in Koorde.

Referenced by handleStabilizeTimerExpired().

01302 {}


Friends And Related Function Documentation

friend class ChordSuccessorList [friend]


Member Data Documentation

int Chord::joinRetry [protected]

int Chord::stabilizeRetry [protected]

// retries before neighbor considered failed

Referenced by Koorde::handleDeBruijnTimeout(), handleStabilizeTimerExpired(), and initializeOverlay().

double Chord::joinDelay [protected]

double Chord::stabilizeDelay [protected]

stabilize interval (secs)

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

double Chord::fixfingersDelay [protected]

int Chord::successorListSize [protected]

bool Chord::aggressiveJoinMode [protected]

use modified (faster) JOIN protocol

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

bool Chord::extendedFingerTable [protected]

unsigned int Chord::numFingerCandidates [protected]

bool Chord::proximityRouting [protected]

bool Chord::mergeOptimizationL1 [protected]

Referenced by initializeOverlay(), and rpcNotify().

bool Chord::mergeOptimizationL2 [protected]

bool Chord::mergeOptimizationL3 [protected]

bool Chord::mergeOptimizationL4 [protected]

cMessage* Chord::join_timer [protected]

cMessage* Chord::stabilize_timer [protected]

cMessage* Chord::fixfingers_timer [protected]

int Chord::joinCount [protected]

int Chord::stabilizeCount [protected]

int Chord::fixfingersCount [protected]

int Chord::notifyCount [protected]

int Chord::joinBytesSent [protected]

int Chord::stabilizeBytesSent [protected]

int Chord::notifyBytesSent [protected]

int Chord::fixfingersBytesSent [protected]

int Chord::keyLength [protected]

length of an overlay key in bits

Referenced by Koorde::findLongestMatch(), and initializeOverlay().

node used to bootrap

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


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

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