#include <Chord.h>
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.
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 NodeVector * | closestPreceedingNode (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. | |
NodeVector * | findNode (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 | |
ChordFingerTable * | fingerTable |
pointer to this node's finger table | |
ChordSuccessorList * | successorList |
pointer to this node's successor list | |
Friends | |
class | ChordSuccessorList |
Chord::Chord | ( | ) |
Chord::~Chord | ( | ) | [virtual] |
00114 { 00115 // destroy self timer messages 00116 cancelAndDelete(join_timer); 00117 cancelAndDelete(stabilize_timer); 00118 cancelAndDelete(fixfingers_timer); 00119 }
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.
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.
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.
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.
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).
x | Left-hand-side Key | |
y | Right-hand-side key |
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
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
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
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
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
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.
key | key to find the closest preceeding node for |
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.
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.
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. |
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.
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.
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 |
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.
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().
Reimplemented from BaseOverlay.
00401 { 00402 return extendedFingerTable ? numFingerCandidates : 1; 00403 }
void Chord::rpcFixfingers | ( | FixfingersCall * | call | ) | [protected] |
Fixfingers Remote-Procedure-Call.
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.
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.
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.
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.
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.
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] |
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] |
void Chord::successorIsDead | ( | ) | [protected, virtual] |
friend class ChordSuccessorList [friend] |
int Chord::joinRetry [protected] |
Referenced by handleJoinTimerExpired(), and initializeOverlay().
int Chord::stabilizeRetry [protected] |
// retries before neighbor considered failed
Referenced by Koorde::handleDeBruijnTimeout(), handleStabilizeTimerExpired(), and initializeOverlay().
double Chord::joinDelay [protected] |
Referenced by handleJoinTimerExpired(), initializeOverlay(), and joinForeignPartition().
double Chord::stabilizeDelay [protected] |
stabilize interval (secs)
Referenced by changeState(), handleStabilizeTimerExpired(), and initializeOverlay().
double Chord::fixfingersDelay [protected] |
Referenced by changeState(), handleFixFingersTimerExpired(), and initializeOverlay().
int Chord::successorListSize [protected] |
Referenced by getMaxNumSiblings(), handleRpcJoinResponse(), and initializeOverlay().
bool Chord::aggressiveJoinMode [protected] |
use modified (faster) JOIN protocol
Referenced by handleRpcJoinResponse(), initializeOverlay(), and rpcJoin().
bool Chord::extendedFingerTable [protected] |
unsigned int Chord::numFingerCandidates [protected] |
Referenced by closestPreceedingNode(), getMaxNumRedundantNodes(), initializeOverlay(), and rpcFixfingers().
bool Chord::proximityRouting [protected] |
Referenced by handleRpcFixfingersResponse(), and initializeOverlay().
bool Chord::mergeOptimizationL1 [protected] |
Referenced by initializeOverlay(), and rpcNotify().
bool Chord::mergeOptimizationL2 [protected] |
Referenced by handleRpcJoinResponse(), and initializeOverlay().
bool Chord::mergeOptimizationL3 [protected] |
Referenced by handleNewSuccessorHint(), handleRpcNotifyResponse(), initializeOverlay(), and rpcNotify().
bool Chord::mergeOptimizationL4 [protected] |
Referenced by handleStabilizeTimerExpired(), and initializeOverlay().
cMessage* Chord::join_timer [protected] |
Referenced by changeState(), Chord(), handleJoinTimerExpired(), initializeOverlay(), and ~Chord().
cMessage* Chord::stabilize_timer [protected] |
Referenced by changeState(), Chord(), handleRpcJoinResponse(), handleStabilizeTimerExpired(), initializeOverlay(), and ~Chord().
cMessage* Chord::fixfingers_timer [protected] |
int Chord::joinCount [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::stabilizeCount [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::fixfingersCount [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::notifyCount [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::newsuccessorhintCount [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::joinBytesSent [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::stabilizeBytesSent [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::notifyBytesSent [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::fixfingersBytesSent [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::newsuccessorhintBytesSent [protected] |
Referenced by finishOverlay(), initializeOverlay(), and recordOverlaySentStats().
int Chord::keyLength [protected] |
int Chord::missingPredecessorStabRequests [protected] |
missing StabilizeCall msgs
Referenced by handleStabilizeTimerExpired(), initializeOverlay(), Koorde::rpcNotify(), rpcNotify(), and rpcStabilize().
int Chord::missingSuccessorStabResponses [protected] |
missing StabilizeResponse msgs
Referenced by Koorde::handleRpcStabilizeResponse(), handleRpcStabilizeResponse(), handleStabilizeTimerExpired(), and initializeOverlay().
NodeHandle Chord::predecessorNode [protected] |
predecessor of this node
Referenced by changeState(), closestPreceedingNode(), Koorde::findNode(), Koorde::handleDeBruijnTimerExpired(), Koorde::handleRpcDeBruijnRequest(), handleRpcJoinResponse(), handleStabilizeTimerExpired(), initializeOverlay(), isSiblingFor(), rpcJoin(), Koorde::rpcNotify(), rpcNotify(), rpcStabilize(), Koorde::updateTooltip(), and updateTooltip().
NodeHandle Chord::bootstrapNode [protected] |
node used to bootrap
Referenced by changeState(), handleJoinTimerExpired(), and initializeOverlay().
ChordFingerTable* Chord::fingerTable [protected] |
pointer to this node's finger table
Referenced by closestPreceedingNode(), findFriendModules(), handleFixFingersTimerExpired(), handleRpcFixfingersResponse(), handleStabilizeTimerExpired(), initializeFriendModules(), pingResponse(), and pingTimeout().
ChordSuccessorList* Chord::successorList [protected] |
pointer to this node's successor list
Referenced by closestPreceedingNode(), Koorde::findDeBruijnHop(), Koorde::findFriendModules(), findFriendModules(), Koorde::findNode(), findNode(), Koorde::handleDeBruijnTimerExpired(), handleFixFingersTimerExpired(), handleNewSuccessorHint(), Koorde::handleRpcDeBruijnRequest(), handleRpcJoinResponse(), Koorde::handleRpcNotifyResponse(), handleRpcNotifyResponse(), Koorde::handleRpcStabilizeResponse(), handleRpcStabilizeResponse(), handleStabilizeTimerExpired(), Koorde::initializeFriendModules(), initializeFriendModules(), isSiblingFor(), rpcFixfingers(), rpcJoin(), Koorde::rpcNotify(), rpcNotify(), Koorde::updateTooltip(), updateTooltip(), and Koorde::walkSuccessorList().