Chord Class Reference

#include <Chord.h>

Inheritance diagram for Chord:

BaseOverlay BaseRpc TopologyVis RpcListener Koorde

List of all members.


Detailed Description

protocol states

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
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 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, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
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 pingResponse (PingResponse *pingResponse, int id, simtime_t rtt)
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
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]

00100 {
00101     // destroy self timer messages
00102     cancelAndDelete(join_timer);
00103     cancelAndDelete(stabilize_timer);
00104     cancelAndDelete(fixfingers_timer);
00105 }


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.

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     // fetch some parameters
00052     useCommonAPIforward = par("useCommonAPIforward");
00053     successorListSize = par("successorListSize");
00054     joinRetry = par("joinRetry");
00055     stabilizeRetry = par("stabilizeRetry");
00056     joinDelay = par("joinDelay");
00057     stabilizeDelay = par("stabilizeDelay");
00058     fixfingersDelay = par("fixfingersDelay");
00059     aggressiveJoinMode = par("aggressiveJoinMode");
00060     extendedFingerTable = par("extendedFingerTable");
00061     numFingerCandidates = par("numFingerCandidates");
00062     proximityRouting = par("proximityRouting");
00063 
00064     keyLength = OverlayKey::getLength();
00065     missingPredecessorStabRequests = 0;
00066     missingSuccessorStabResponses = 0;
00067 
00068     // statistics
00069     joinCount = 0;
00070     stabilizeCount = 0;
00071     fixfingersCount = 0;
00072     notifyCount = 0;
00073     newsuccessorhintCount = 0;
00074     joinBytesSent = 0;
00075     stabilizeBytesSent = 0;
00076     notifyBytesSent = 0;
00077     fixfingersBytesSent = 0;
00078     newsuccessorhintBytesSent = 0;
00079 
00080 
00081     // find friend modules
00082     findFriendModules();
00083 
00084     // add some watches
00085     WATCH(predecessorNode);
00086     WATCH(thisNode);
00087     WATCH(bootstrapNode);
00088     WATCH(joinRetry);
00089     WATCH(missingPredecessorStabRequests);
00090     WATCH(missingSuccessorStabResponses);
00091     
00092     // self-messages
00093     join_timer = new cMessage("join_timer");
00094     stabilize_timer = new cMessage("stabilize_timer");
00095     fixfingers_timer = new cMessage("fixfingers_timer");
00096 }

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

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from BaseOverlay.

Reimplemented in Koorde.

00221 {
00222     // catch JOIN timer
00223     if (msg->isName("join_timer")) {
00224         handleJoinTimerExpired(msg);
00225     }
00226     // catch STABILIZE timer
00227     else if (msg->isName("stabilize_timer")) {
00228         handleStabilizeTimerExpired(msg);
00229     }
00230     // catch FIX_FINGERS timer
00231     else if (msg->isName("fixfingers_timer")) {
00232         handleFixFingersTimerExpired(msg);
00233     }
00234     // unknown self message
00235     else {
00236         error("Chord::handleTimerEvent(): received self message of "
00237               "unknown type!");
00238     }
00239 }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Reimplemented in Koorde.

00243 {
00244     ChordMessage* chordMsg = check_and_cast<ChordMessage*>(msg);
00245     switch(chordMsg->getCommand()) {
00246     case NEWSUCCESSORHINT:
00247         handleNewSuccessorHint(chordMsg);
00248         break;
00249     default:
00250         error("handleUDPMessage(): Unknown message type!");
00251         break;
00252     }
00253 
00254     delete chordMsg;
00255 }

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.

00641 {
00642     BaseOverlayMessage* innerMsg;
00643 
00644     if (msg->getType() == OVERLAYROUTE)
00645         innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg());
00646     else
00647         innerMsg = msg;
00648 
00649     switch (innerMsg->getType()) {
00650 
00651     case OVERLAYSIGNALING: {
00652         ChordMessage* chordMsg = dynamic_cast<ChordMessage*>(innerMsg);
00653         switch(chordMsg->getCommand()) {
00654         case NEWSUCCESSORHINT:
00655             RECORD_STATS(newsuccessorhintCount++; newsuccessorhintBytesSent +=
00656                              msg->byteLength());
00657             break;
00658         }
00659         break;
00660     }
00661 
00662     case RPC: {
00663         if ((dynamic_cast<StabilizeCall*>(innerMsg) != NULL) ||
00664             (dynamic_cast<StabilizeResponse*>(innerMsg) != NULL)) {
00665             RECORD_STATS(stabilizeCount++; stabilizeBytesSent +=
00666                              msg->byteLength());
00667         } else if ((dynamic_cast<NotifyCall*>(innerMsg) != NULL) ||
00668                    (dynamic_cast<NotifyResponse*>(innerMsg) != NULL)) {
00669             RECORD_STATS(notifyCount++; notifyBytesSent +=
00670                              msg->byteLength());
00671         } else if ((dynamic_cast<FixfingersCall*>(innerMsg) != NULL) ||
00672                    (dynamic_cast<FixfingersResponse*>(innerMsg) != NULL)) {
00673             RECORD_STATS(fixfingersCount++; fixfingersBytesSent +=
00674                              msg->byteLength());
00675         } else if ((dynamic_cast<JoinCall*>(innerMsg) != NULL) ||
00676                    (dynamic_cast<JoinResponse*>(innerMsg) != NULL)) {
00677             RECORD_STATS(joinCount++; joinBytesSent += msg->byteLength());
00678         }
00679         break;
00680     }
00681     }
00682 }

void Chord::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

Reimplemented in Koorde.

00686 {
00687     // remove this node from the bootstrap list
00688     removeBootstrapNode(thisNode);
00689 
00690     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00691     if(time == 0) return;
00692 
00693     globalStatistics->addStdDev("Chord: Sent JOIN Messages/s",
00694                                 joinCount / time);
00695     globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Messages/s",
00696                                 newsuccessorhintCount / time);
00697     globalStatistics->addStdDev("Chord: Sent STABILIZE Messages/s",
00698                                 stabilizeCount / time);
00699     globalStatistics->addStdDev("Chord: Sent NOTIFY Messages/s",
00700                                 notifyCount / time);
00701     globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Messages/s",
00702                                 fixfingersCount / time);
00703     globalStatistics->addStdDev("Chord: Sent JOIN Bytes/s",
00704                                 joinBytesSent / time);
00705     globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Bytes/s",
00706                                 newsuccessorhintBytesSent / time);
00707     globalStatistics->addStdDev("Chord: Sent STABILIZE Bytes/s",
00708                                 stabilizeBytesSent / time);
00709     globalStatistics->addStdDev("Chord: Sent NOTIFY Bytes/s",
00710                                 notifyBytesSent / time);
00711     globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Bytes/s",
00712                                 fixfingersBytesSent / time);
00713 }

void Chord::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented in Koorde.

01153 {
01154     if (ev.isGUI()) {
01155         std::stringstream ttString;
01156 
01157         // show our predecessor and successor in tooltip
01158         ttString << predecessorNode << endl << thisNode << endl
01159         << successorList->getSuccessor();
01160 
01161         parentModule()->parentModule()->displayString().
01162         setTagArg("tt", 0, ttString.str().c_str());
01163         parentModule()->displayString().
01164         setTagArg("tt", 0, ttString.str().c_str());
01165         displayString().setTagArg("tt", 0, ttString.str().c_str());
01166 
01167         // draw an arrow to our current successor
01168         showOverlayNeighborArrow(successorList->getSuccessor(), true,
01169                                  "m=m,50,0,50,0;o=red,1");
01170         showOverlayNeighborArrow(predecessorNode, false,
01171                                  "m=m,50,100,50,100;o=green,1");
01172     }
01173 }

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

changes node state

Parameters:
toState state to change to

Reimplemented in Koorde.

00116 {
00117     //
00118     // Defines tasks to be executed when a state change occurs.
00119     //
00120 
00121     switch (toState) {
00122     case INIT:
00123         state = INIT;
00124 
00125         // remove current node handle from the bootstrap list
00126         if(!thisNode.key.isUnspecified()) {
00127             removeBootstrapNode(thisNode);
00128         }
00129 
00130         // Calculate node's id by hashing its IP address
00131         //  thisNode.key = OverlayKey::sha1(const_cast<char*>(
00132         //                      thisNode.ip.str().c_str()));
00133         // better use random numbers (our ip address might not be random)
00134         // keep old id if INIT gets called twice
00135         if (thisNode.key.isUnspecified()) {
00136             thisNode.key = OverlayKey::random();
00137             callUpdate(thisNode, true);
00138         }
00139 
00140 
00141         // initialize predecessor pointer
00142         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00143 
00144         // initialize finger table and successor list
00145         initializeFriendModules();
00146 
00147         updateTooltip();
00148 
00149         // debug message
00150         if (debugOutput) {
00151             EV << "[Chord::changeState() @ " << thisNode.ip
00152             << " (" << thisNode.key.toString(16) << ")]\n"
00153             << "    Entered INIT stage"
00154             << endl;
00155         }
00156         // FIXME: bubble() sometimes doesn't work
00157         parentModule()->parentModule()->bubble("Enter INIT state.");
00158         break;
00159 
00160     case BOOTSTRAP:
00161         state = BOOTSTRAP;
00162 
00163         // initiate bootstrap process
00164         cancelEvent(join_timer);
00165         // workaround: prevent notificationBoard from taking
00166         // ownership of join_timer message
00167         take(join_timer);
00168         scheduleAt(simulation.simTime(), join_timer);
00169 
00170         // debug message
00171         if (debugOutput) {
00172             EV << "[Chord::changeState() @ " << thisNode.ip
00173             << " (" << thisNode.key.toString(16) << ")]\n"
00174             << "    Entered BOOTSTRAP stage"
00175             << endl;
00176         }
00177         parentModule()->parentModule()->bubble("Enter BOOTSTRAP state.");
00178 
00179         // find a new bootstrap node and enroll to the bootstrap list
00180         bootstrapNode = getBootstrapNode();
00181 
00182         // is this the first node?
00183         if (bootstrapNode.isUnspecified()) {
00184             // create new cord ring
00185             bootstrapNode = thisNode;
00186             changeState(READY);
00187             updateTooltip();
00188         }
00189         break;
00190 
00191     case READY:
00192         state = READY;
00193 
00194         //registerBootstrapNode(thisNode);
00195 
00196         // initiate stabilization protocol
00197         cancelEvent(stabilize_timer);
00198         scheduleAt(simulation.simTime() + stabilizeDelay, stabilize_timer);
00199 
00200         // initiate finger repair protocol
00201         cancelEvent(fixfingers_timer);
00202         scheduleAt(simulation.simTime() + fixfingersDelay,
00203                    fixfingers_timer);
00204 
00205         // debug message
00206         if (debugOutput) {
00207             EV << "[Chord::changeState() @ " << thisNode.ip
00208             << " (" << thisNode.key.toString(16) << ")]\n"
00209             << "    Entered READY stage"
00210             << endl;
00211         }
00212         parentModule()->parentModule()->bubble("Enter READY state.");
00213         break;
00214     }
00215 
00216     setOverlayReady(state == READY);
00217 }

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

handle a expired join timer

Parameters:
msg the timer self-message
00718 {
00719     // only process timer, if node is not bootstrapped yet
00720     if (state == READY)
00721         return;
00722 
00723     // enter state BOOTSTRAP
00724     if (state != BOOTSTRAP)
00725         changeState(BOOTSTRAP);
00726 
00727     // change bootstrap node from time to time
00728     joinRetry--;
00729     if (joinRetry == 0) {
00730         joinRetry = par("joinRetry");
00731         changeState(BOOTSTRAP);
00732         return;
00733     }
00734 
00735     // call JOIN RPC
00736     JoinCall* call = new JoinCall("JoinCall");
00737     call->setLength(JOINCALL_L(call));
00738 
00739     sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, thisNode.key,
00740                      call, joinDelay);
00741 
00742     // schedule next bootstrap process in the case this one fails
00743     cancelEvent(join_timer);
00744     scheduleAt(simulation.simTime() + joinDelay, msg);
00745 }

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

handle a expired stabilize timer

Parameters:
msg the timer self-message
00749 {
00750     if (state != READY)
00751         return;
00752 
00753     if (missingPredecessorStabRequests >= stabilizeRetry) {
00754         // predecessor node seems to be dead
00755         // remove it from the predecessor / successor lists
00756         successorList->removeSuccessor(predecessorNode);
00757         predecessorIsDead();
00758 
00759         callUpdate(predecessorNode, false);
00760         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00761 
00762         missingPredecessorStabRequests = 0;
00763         updateTooltip();
00764     }
00765 
00766     if (missingSuccessorStabResponses >= stabilizeRetry) {
00767         // successor node seems to be dead
00768         // remove it from the predecessor / successor list
00769         successorIsDead();
00770         NodeHandle successor = successorList->popSuccessor();
00771 
00772         // if we had a ring consisting of 2 nodes and our successor seems
00773         // to be dead. Remove also predecessor because the successor
00774         // and predecessor are the same node
00775         if ((!predecessorNode.isUnspecified()) &&
00776             predecessorNode == successor) {
00777             predecessorIsDead();
00778             callUpdate(predecessorNode, false);
00779             predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00780         }
00781 
00782         missingSuccessorStabResponses = 0;
00783         updateTooltip();
00784 
00785         if (successorList->isEmpty()) {
00786             changeState(INIT);
00787             changeState(BOOTSTRAP);
00788             return;
00789         }
00790     }
00791 
00792     if (!successorList->isEmpty()) {
00793         // call STABILIZE RPC
00794         StabilizeCall* call = new StabilizeCall("StabilizeCall");
00795         call->setLength(STABILIZECALL_L(call));
00796 
00797         sendUdpRpcCall(successorList->getSuccessor(), call);
00798 
00799         missingPredecessorStabRequests++;
00800         missingSuccessorStabResponses++;
00801     }
00802 
00803     // schedule next stabilization process
00804     cancelEvent(stabilize_timer);
00805     scheduleAt(simulation.simTime() + stabilizeDelay, msg);
00806 }

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

handle a expired fix_fingers timer

Parameters:
msg the timer self-message

Reimplemented in Koorde.

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

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

handle a received NEWSUCCESSORHINT message

Parameters:
chordMsg the message to process
00842 {
00843     NewSuccessorHintMessage* newSuccessorHintMsg =
00844         check_and_cast<NewSuccessorHintMessage*>(chordMsg);
00845 
00846     // fetch the successor's predecessor
00847     NodeHandle predecessor = newSuccessorHintMsg->getPreNode();
00848 
00849     // is the successor's predecessor a new successor for this node?
00850     if (predecessor.key.isBetween(thisNode.key,
00851                                   successorList->getSuccessor().key)
00852         || (thisNode.key == successorList->getSuccessor().key)) {
00853         // add the successor's predecessor to the successor list
00854         successorList->addSuccessor(predecessor);
00855         updateTooltip();
00856     }
00857 }

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
00546 {
00547     NodeHandle tempHandle = NodeHandle::UNSPECIFIED_NODE;
00548 
00549     // find the closest perceeding node in the successor list
00550     for (int j = successorList->getSize() - 1; j >= 0; j--) {
00551         if(successorList->getSuccessor(j).key.isBetweenR(thisNode.key, key)) {
00552             tempHandle = successorList->getSuccessor(j);
00553             break;
00554         }
00555     }
00556 
00557     if(tempHandle.isUnspecified()) {
00558         std::stringstream temp;
00559         temp << "Chord::closestPreceedingNode(): Successor list broken " << thisNode.key << " " << key;
00560         throw new cRuntimeError(temp.str().c_str());
00561     }
00562 
00563     NodeVector* nextHop;
00564 
00565     for (int i = fingerTable->getSize() - 1; i >= 0; i--) {
00566         if (fingerTable->getFinger(i).key.isBetweenLR(tempHandle.key, key)) {
00567             // is there a closer preceeding node in the successor list?
00568             //for (int j = successorList->getSize() - 1; j >= 0; j--) {
00569             if(!extendedFingerTable) {
00570                 nextHop = new NodeVector();
00571                 // if (successorList->getSuccessor(j).key.
00572                 //    isBetween(fingerTable->getFinger(i).key, key)) {
00573                 //    nextHop->push_back(successorList->getSuccessor(j));
00574                 //       }
00575                 //       else {
00576                 // if no, settle with the node already found
00577                 nextHop->push_back(fingerTable->getFinger(i));
00578                 //}
00579                 EV << "[Chord::closestPreceedingNode() @ " << thisNode.ip
00580                 << " (" << thisNode.key.toString(16) << ")]\n"
00581                 << "    ClosestPreceedingNode: node " << thisNode << " for key " << key << "\n"
00582                 << "    finger " << fingerTable->getFinger(i).key << " better than \n"
00583                 << "    " << tempHandle.key
00584                 << endl;
00585                 return nextHop;
00586             } else {
00587                 //       if (successorList->getSuccessor(j).key.
00588                 //    isBetween(fingerTable->getFinger(i, key)->begin()->key, key)) { //TODO
00589                 //    nextHop = new NodeVector();
00590                 //    nextHop->push_back(successorList->getSuccessor(j));
00591                 //    return nextHop;
00592                 //       }
00593                 //       else {
00594                 // if(*fingerTable->getFinger(i, key)->begin() != fingerTable->getFinger(i))
00595                 //      std::cout << "thisNode.key =    " << thisNode.key
00596                 //       << "\nfinger =  " << fingerTable->getFinger(i).key
00597                 //       << "\nused =    " << fingerTable->getFinger(i, key)->begin()->key
00598                 //       << "\ndestKey = " << key
00599                 //       << "\n" << std::endl;
00600                 return fingerTable->getFinger(i, key);
00601                 //}
00602             }
00603             //}
00604         }
00605     }
00606 
00607     nextHop = new NodeVector();
00608     EV << "[Chord::closestPreceedingNode() @ " << thisNode.ip
00609     << " (" << thisNode.key.toString(16) << ")]\n"
00610     << "    No finger found"
00611     << endl;
00612 
00613     // if no finger is found lookup the rest of the successor list
00614     for(int i = successorList->getSize() - 1; i >= 0
00615         && nextHop->size() <= numFingerCandidates ; i--) {
00616         if(successorList->getSuccessor(i).key.isBetween(thisNode.key, key)) {
00617             nextHop->push_back(successorList->getSuccessor(i));
00618             //return nextHop;
00619         }
00620     }
00621 
00622     if(nextHop->size() != 0)
00623         return nextHop;
00624 
00625     // if this is the first and only node on the ring, it is responsible
00626     if ((predecessorNode.isUnspecified()) &&
00627         (successorList->getSuccessor() == thisNode)) {
00628         nextHop->push_back(thisNode);
00629         return nextHop;
00630     }
00631 
00632     // if there is still no node found return NodeHandle::UNSPECIFIED_NODE
00633     std::stringstream temp("Error in Chord::closestPreceedingNode()!\n");
00634     temp << thisNode.key << " " << key;
00635     error(temp.str().c_str());
00636     nextHop->push_back(NodeHandle::UNSPECIFIED_NODE);
00637     return nextHop;
00638 }

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

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

Reimplemented in Koorde.

01133 {
01134     fingerTable = check_and_cast<ChordFingerTable*>
01135                   (parentModule()->submodule("fingerTable"));
01136 
01137     successorList = check_and_cast<ChordSuccessorList*>
01138                     (parentModule()->submodule("successorList"));
01139 }

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

initializes finger table and successor list

Reimplemented in Koorde.

01143 {
01144     // initialize finger table
01145     fingerTable->initializeTable(thisNode.key.getLength(), thisNode, this);
01146 
01147     // initialize successor list
01148     successorList->initializeList(par("successorListSize"), thisNode, this);
01149 }

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.

00259 {
00260     if (state != READY) {
00261 //      delete msg;
00262 //      EV << "[Chord::handleRpc() @ " << thisNode.ip
00263 //         << " (" << thisNode.key.toString(16) << ")]\n"
00264 //         << "    Received RPC call and state != READY"
00265 //         << endl;
00266         return false;
00267     }
00268 
00269     // delegate messages
00270     RPC_SWITCH_START( msg )
00271     // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
00272     RPC_DELEGATE( Join, rpcJoin );
00273     RPC_DELEGATE( Notify, rpcNotify );
00274     RPC_DELEGATE( Stabilize, rpcStabilize );
00275     RPC_DELEGATE( Fixfingers, rpcFixfingers );
00276     RPC_SWITCH_END( )
00277 
00278     return RPC_HANDLED;
00279 }

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.

00477 {
00478     bool err;
00479     NodeVector* nextHop;
00480 
00481     if (state != READY)
00482         return new NodeVector();
00483 
00484     //     // example code for findNodeExt
00485 
00486     //      if (msg != NULL) {
00487     //       if (!msg->hasObject("findNodeExt")) {
00488     //           ChordFindNodeExtMessage *extMsg =
00489     //        new ChordFindNodeExtMessage("findNodeExt");
00490     //          extMsg->setLength(8*10);
00491     //           msg->addObject( extMsg );
00492     //               }
00493     //
00494     //        ChordFindNodeExtMessage *extMsg =
00495     //            (ChordFindNodeExtMessage*) msg->getObject("findNodeExt");
00496     //
00497     //      cout << "ChordCount: " << extMsg->getChordCount() + 1 << endl;
00498     //
00499     //          extMsg->setChordCount(extMsg->getChordCount() + 1);
00500     //      }
00501 
00502     // if key is unspecified, the message is for this node
00503     if (key.isUnspecified()) {
00504         nextHop = new NodeVector();
00505         nextHop->push_back(thisNode);
00506     }
00507 
00508     // the message is destined for this node
00509     else if (isSiblingFor(thisNode, key, 1, &err)) {
00510         nextHop = new NodeVector();
00511         nextHop->push_back(thisNode);
00512         for (uint i = 0; i < successorList->getSize(); i++) {
00513             nextHop->push_back(successorList->getSuccessor(i));
00514         }
00515         nextHop->downsizeTo(numSiblings);
00516     }
00517 
00518     // the message destined for our successor
00519     else if (key.isBetweenR(thisNode.key,
00520                             successorList->getSuccessor().key)) {
00521         nextHop = new NodeVector();
00522         for (uint i = 0; i < successorList->getSize(); i++) {
00523             nextHop->push_back(successorList->getSuccessor(i));
00524         }
00525         nextHop->downsizeTo(numRedundantNodes);
00526     }
00527 
00528     // find next hop with finger table and/or successor list
00529     else {
00530         nextHop = closestPreceedingNode(key);
00531         nextHop->downsizeTo(numRedundantNodes);
00532     }
00533 
00534     if ((nextHop->size() > 0) && ((*nextHop)[0].key == thisNode.key)) {
00535         if (!isSiblingFor(thisNode, key, 1, &err)) {
00536             std::cout << "aaaaaaaaaaargh!" << endl;
00537             nextHop->clear();
00538         }
00539     }
00540 
00541     return nextHop;
00542 }

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.

00110 {
00111     changeState(INIT);
00112     changeState(BOOTSTRAP);
00113 }

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.

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

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.

00381 {
00382     return successorListSize;
00383 }

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.

00386 {
00387     return extendedFingerTable ? numFingerCandidates : 1;
00388 }

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

Fixfingers Remote-Procedure-Call.

Parameters:
call RPC Parameter Message
01070 {
01071     FixfingersResponse* fixfingersResponse =
01072         new FixfingersResponse("FixfingersResponse");
01073 
01074     fixfingersResponse->setSucNodeArraySize(1);
01075     fixfingersResponse->setSucNode(0, thisNode);
01076 
01077     if(extendedFingerTable) {
01078         fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
01079                                                 < numFingerCandidates + 1)
01080                                                 ? successorList->getSize() + 1
01081                                                 : numFingerCandidates + 1));
01082         for(unsigned int i = 0;
01083             i < (((successorList->getSize()) < numFingerCandidates)
01084                  ? (successorList->getSize()) : numFingerCandidates); i++) {
01085             assert(!successorList->getSuccessor(i).isUnspecified());
01086             fixfingersResponse->setSucNode(i + 1,
01087                                            successorList->getSuccessor(i));
01088         }
01089     }
01090     fixfingersResponse->setFinger(call->getFinger());
01091     fixfingersResponse->setLength(FIXFINGERSRESPONSE_L(fixfingersResponse)); //TODO
01092 
01093     sendRpcResponse(call, fixfingersResponse);
01094 }

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

Join Remote-Procedure-Call.

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

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

NOTIFY Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Reimplemented in Koorde.

01011 {
01012     // our predecessor seems to be alive
01013     missingPredecessorStabRequests = 0;
01014 
01015     NodeHandle newPredecessor = call->getSrcNode();
01016 
01017     // is the new predecessor closer than the current one?
01018     if (predecessorNode.isUnspecified() ||
01019         newPredecessor.key.isBetween(predecessorNode.key, thisNode.key)) {
01020 
01021         if ((predecessorNode.isUnspecified()) ||
01022             (newPredecessor != predecessorNode)) {
01023             // send update to application if we've got a new predecessor
01024             if (!predecessorNode.isUnspecified()) {
01025                 callUpdate(predecessorNode, false);
01026             }
01027             callUpdate(newPredecessor, true);
01028 
01029             // set up new predecessor
01030             predecessorNode = newPredecessor;
01031             updateTooltip();
01032         }
01033     }
01034 
01035     // compile NOTIFY response
01036     NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
01037 
01038     int sucNum = successorList->getSize();
01039     notifyResponse->setSucNum(sucNum);
01040     notifyResponse->setSucNodeArraySize(sucNum);
01041 
01042     for (int k = 0; k < sucNum; k++) {
01043         notifyResponse->setSucNode(k, successorList->getSuccessor(k));
01044     }
01045 
01046     notifyResponse->setLength(NOTIFYRESPONSE_L(notifyResponse));
01047 
01048     sendRpcResponse(call, notifyResponse);
01049 }

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

STABILIZE Remote-Procedure-Call.

Parameters:
call RPC Parameter Message
00972 {
00973     // our predecessor seems to be alive
00974     missingPredecessorStabRequests = 0;
00975 
00976     // reply with StabilizeResponse message
00977     StabilizeResponse* stabilizeResponse =
00978         new StabilizeResponse("StabilizeResponse");
00979     stabilizeResponse->setPreNode(predecessorNode);
00980     stabilizeResponse->setLength(STABILIZERESPONSE_L(stabilizeResponse));
00981 
00982     sendRpcResponse(call, stabilizeResponse);
00983 }

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

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

Parameters:
msg The response message.
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

Reimplemented in Koorde.

00283 {
00284     RPC_SWITCH_START(msg)
00285 /*    RPC_ON_RESPONSE( Ping ) {
00286         handleRpcPingResponse(_PingResponse, rpcId, rtt);
00287         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00288         << " (" << thisNode.key.toString(16) << ")]\n"
00289         << "    Received a Ping RPC Response: id=" << rpcId << "\n"
00290         << "    msg=" << *_PingResponse << " rtt=" << rtt
00291         << endl;
00292         break;
00293     }*/ /* now handled in pingResponse */
00294     RPC_ON_RESPONSE( Join ) {
00295         handleRpcJoinResponse(_JoinResponse);
00296         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00297         << " (" << thisNode.key.toString(16) << ")]\n"
00298         << "    Received a Join RPC Response: id=" << rpcId << "\n"
00299         << "    msg=" << *_JoinResponse << " rtt=" << rtt
00300         << endl;
00301         break;
00302     }
00303     RPC_ON_RESPONSE( Notify ) {
00304         handleRpcNotifyResponse(_NotifyResponse);
00305         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00306         << " (" << thisNode.key.toString(16) << ")]\n"
00307         << "    Received a Notify RPC Response: id=" << rpcId << "\n"
00308         << "    msg=" << *_NotifyResponse << " rtt=" << rtt
00309         << endl;
00310         break;
00311     }
00312     RPC_ON_RESPONSE( Stabilize ) {
00313         handleRpcStabilizeResponse(_StabilizeResponse);
00314         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00315         << " (" << thisNode.key.toString(16) << ")]\n"
00316         << "    Received a Stabilize RPC Response: id=" << rpcId << "\n"
00317         << "    msg=" << *_StabilizeResponse << " rtt=" << rtt
00318         << endl;
00319         break;
00320     }
00321     RPC_ON_RESPONSE( Fixfingers ) {
00322         handleRpcFixfingersResponse(_FixfingersResponse, rtt);
00323         EV << "[Chord::handleRpcResponse() @ " << thisNode.ip
00324         << " (" << thisNode.key.toString(16) << ")]\n"
00325         << "    Received a Fixfingers RPC Response: id=" << rpcId << "\n"
00326         << "    msg=" << *_FixfingersResponse << " rtt=" << rtt
00327         << endl;
00328         break;
00329     }
00330     RPC_SWITCH_END( )
00331 }

void Chord::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
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
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

Reimplemented in Koorde.

00335 {
00336     RPC_SWITCH_START(msg)
00337     RPC_ON_CALL( FindNode ) {
00338         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00339         << " (" << thisNode.key.toString(16) << ")]\n"
00340         << "    FindNode RPC Call timed out: id=" << rpcId << "\n"
00341         << "    msg=" << *_FindNodeCall
00342         << endl;
00343         break;
00344     }
00345     RPC_ON_CALL( Join ) {
00346         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00347         << " (" << thisNode.key.toString(16) << ")]\n"
00348         << "    Join RPC Call timed out: id=" << rpcId << "\n"
00349         << "    msg=" << *_JoinCall
00350         << endl;
00351         break;
00352     }
00353     RPC_ON_CALL( Notify ) {
00354         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00355         << " (" << thisNode.key.toString(16) << ")]\n"
00356         << "    Notify RPC Call timed out: id=" << rpcId << "\n"
00357         << "    msg=" << *_NotifyCall
00358         << endl;
00359         break;
00360     }
00361     RPC_ON_CALL( Stabilize ) {
00362         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00363         << " (" << thisNode.key.toString(16) << ")]\n"
00364         << "    Stabilize RPC Call timed out: id=" << rpcId << "\n"
00365         << "    msg=" << *_StabilizeCall
00366         << endl;
00367         break;
00368     }
00369     RPC_ON_CALL( Fixfingers ) {
00370         EV << "[Chord::handleRpcTimeout() @ " << thisNode.ip
00371         << " (" << thisNode.key.toString(16) << ")]\n"
00372         << "    Fixfingers RPC Call timed out: id=" << rpcId << "\n"
00373         << "    msg=" << *_FixfingersCall
00374         << endl;
00375         break;
00376     }
00377     RPC_SWITCH_END( )
00378 }

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

Todo:
check commented out addSuccessor (Schenk)

Reimplemented in Koorde.

00930 {
00931     // determine the numer of successor nodes to add
00932     int sucNum = successorListSize - 1;
00933 
00934     if (joinResponse->getSucNum() < successorListSize - 1) {
00935         sucNum = joinResponse->getSucNum();
00936     }
00937 
00938     // add successor node(s)
00939     for (int k = 0; k < sucNum; k++) {
00940         NodeHandle successor = joinResponse->getSucNode(k);
00941         successorList->addSuccessor(successor);
00942     }
00943 
00944     // \todo {check commented out addSuccessor (Schenk)}
00945     //successorList->addSuccessor(joinResponse->getSrcNode());
00946 
00947     // the sender of this message is our new successor
00948     successorList->addSuccessor(joinResponse->getSrcNode());
00949 
00950     // in aggressiveJoinMode: use hint in JoinResponse
00951     // to set our new predecessor
00952     if (aggressiveJoinMode) {
00953         predecessorNode = joinResponse->getPreNode();
00954         callUpdate(predecessorNode, true);
00955     }
00956 
00957     updateTooltip();
00958 
00959     changeState(READY);
00960 
00961     // immediate stabilization protocol
00962     cancelEvent(stabilize_timer);
00963     scheduleAt(simulation.simTime(), stabilize_timer);
00964 
00965     // immediate finger repair protocol
00966     cancelEvent(fixfingers_timer);
00967     scheduleAt(simulation.simTime(), fixfingers_timer);
00968 }

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

Reimplemented in Koorde.

01053 {
01054     if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
01055         EV << "[Chord::handleRpcNotifyResponse() @ " << thisNode.ip
01056         << " (" << thisNode.key.toString(16) << ")]\n"
01057         << "    The srcNode of the received NotifyResponse is not our current successor"
01058         << endl;
01059         return;
01060     }
01061 
01062     // replace our successor list by our successor's successor list
01063     successorList->updateList(notifyResponse);
01064 
01065     updateTooltip();
01066 }

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

Reimplemented in Koorde.

00986 {
00987     // our successor seems to be alive
00988     missingSuccessorStabResponses = 0;
00989 
00990     // fetch the successor's predecessor
00991     NodeHandle predecessor = stabilizeResponse->getPreNode();
00992 
00993     // is the successor's predecessor a new successor for this node?
00994     if (successorList->isEmpty() ||
00995         predecessor.key.isBetween(thisNode.key,
00996                                   successorList->getSuccessor().key)) {
00997         // add the successor's predecessor to the successor list
00998         successorList->addSuccessor(predecessor);
00999         updateTooltip();
01000     }
01001 
01002     // compile NOTIFY RPC
01003     NotifyCall* notifyCall = new NotifyCall("NotifyCall");
01004     notifyCall->setLength(NOTIFYCALL_L(notifyCall));
01005 
01006     sendUdpRpcCall(successorList->getSuccessor(), notifyCall);
01007 }

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

01098 {
01099     // set new finger pointer#
01100     if(!extendedFingerTable)
01101         fingerTable->setFinger(fixfingersResponse->getFinger(), fixfingersResponse->getSucNode(0));
01102 
01103     else {
01104         Successors successors;
01105         successors.insert(std::make_pair(rtt, fixfingersResponse->getSucNode(0)));
01106 
01107         for (unsigned int i = 1; i < fixfingersResponse->getSucNodeArraySize(); i++) {
01108             if (fixfingersResponse->getSucNode(i).isUnspecified())
01109                 continue;
01110             if (fixfingersResponse->getSucNode(i) == thisNode)
01111                 break;
01112             successors.insert(std::make_pair(DBL_MAX, fixfingersResponse->getSucNode(i)));
01113             if (proximityRouting)
01114                 pingNode(fixfingersResponse->getSucNode(i), -1, 0, NULL, NULL,
01115                          fixfingersResponse->getFinger());
01116         }
01117         fingerTable->setFinger(fixfingersResponse->getFinger(), successors);
01118     }
01119 }

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

Reimplemented from BaseRpc.

01123 {
01124     EV << "[Chord::pingResponse() @ " << thisNode.ip
01125             << " (" << thisNode.key.toString(16) << ")]\n"
01126             << "    Received a Ping RPC Response: id=" << rpcId << "\n"
01127             << "    msg=" << *pingResponse << " rtt=" << rtt
01128             << endl;
01129     fingerTable->updateFinger(rpcId, pingResponse->getSrcNode(), rtt);
01130 }

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

Reimplemented in Koorde.

01176 {}

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

Reimplemented in Koorde.

01179 {}


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

double Chord::joinDelay [protected]

double Chord::stabilizeDelay [protected]

stabilize interval (secs)

double Chord::fixfingersDelay [protected]

int Chord::successorListSize [protected]

bool Chord::aggressiveJoinMode [protected]

use modified (faster) JOIN protocol

bool Chord::extendedFingerTable [protected]

unsigned int Chord::numFingerCandidates [protected]

bool Chord::proximityRouting [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::newsuccessorhintCount [protected]

int Chord::joinBytesSent [protected]

int Chord::stabilizeBytesSent [protected]

int Chord::notifyBytesSent [protected]

int Chord::fixfingersBytesSent [protected]

int Chord::newsuccessorhintBytesSent [protected]

int Chord::keyLength [protected]

length of an overlay key in bits

int Chord::missingPredecessorStabRequests [protected]

missing StabilizeCall msgs

int Chord::missingSuccessorStabResponses [protected]

missing StabilizeResponse msgs

NodeHandle Chord::predecessorNode [protected]

predecessor of this node

NodeHandle Chord::bootstrapNode [protected]

node used to bootrap

ChordFingerTable* Chord::fingerTable [protected]

pointer to this node's finger table

ChordSuccessorList* Chord::successorList [protected]

pointer to this node's successor list


The documentation for this class was generated from the following files:
Generated on Thu Apr 17 13:19:28 2008 for ITM OverSim by  doxygen 1.5.3