#include <Chord.h>
Inheritance diagram for Chord:
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 | |
virtual | ~Chord () |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | receiveChangeNotification (int category, cPolymorphic *details) |
callback-method for events at the NotificationBoard | |
virtual bool | isResponsible (const OverlayKey &key) |
Query if the node is responsible for a key. | |
virtual void | handleTimerEvent (cMessage *msg) |
handles 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 statisticts | |
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 const NodeHandle & | 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 void | handleRpc (BaseCallMessage *msg) |
Processes Remote-Procedure-Call invokation messages. | |
NodeVector * | findNode (const OverlayKey &key, BaseOverlayMessage *msg) |
Implements the find node call. | |
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 NodeHandle &dest, int rpcId) |
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) |
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 | |
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 | state |
current node state | |
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 |
Chord::~Chord | ( | ) | [virtual] |
00093 { 00094 // destroy self timer messages 00095 cancelEvent(join_timer); 00096 cancelEvent(stabilize_timer); 00097 cancelEvent(fixfingers_timer); 00098 00099 delete join_timer; 00100 delete stabilize_timer; 00101 delete fixfingers_timer; 00102 }
void Chord::changeState | ( | int | toState | ) | [protected, virtual] |
changes node state
toState | state to change to |
Reimplemented in Koorde.
00118 { 00119 // 00120 // Defines tasks to be executed when a state change occurs. 00121 // 00122 00123 switch (toState) { 00124 case INIT: 00125 state = INIT; 00126 00127 // remove current node handle from the bootstrap list 00128 if(!thisNode.key.isUnspecified()) { 00129 bootstrapOracle->removePeer(thisNode); 00130 } 00131 00132 // Calculate node's id by hashing its IP address 00133 // thisNode.key = OverlayKey::sha1(const_cast<char*>( 00134 // thisNode.ip.str().c_str())); 00135 // better use random numbers (our ip address might not be random) 00136 // keep old id if INIT gets called twice 00137 if (thisNode.key.isUnspecified()) { 00138 thisNode.key = OverlayKey::random(); 00139 callUpdate(thisNode, true); 00140 } 00141 00142 00143 // initialize predecessor pointer 00144 predecessorNode = NodeHandle::UNSPECIFIED_NODE; 00145 00146 // initialize finger table and successor list 00147 initializeFriendModules(); 00148 00149 updateTooltip(); 00150 00151 // debug message 00152 if (debugOutput) { 00153 EV << "CHORD: Node " << thisNode.ip 00154 << " entered INIT stage." << 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: Node " << thisNode.ip 00173 << " entered BOOTSTRAP stage." << endl; 00174 } 00175 parentModule()->parentModule()->bubble("Enter BOOTSTRAP state."); 00176 00177 // find a new bootstrap node and enroll to the bootstrap list 00178 bootstrapNode = bootstrapOracle->getBootstrapNode(); 00179 00180 // is this the first node? 00181 if (bootstrapNode.isUnspecified()) { 00182 // create new cord ring 00183 bootstrapNode = thisNode; 00184 changeState(READY); 00185 updateTooltip(); 00186 } 00187 break; 00188 00189 case READY: 00190 state = READY; 00191 00192 bootstrapOracle->registerPeer(thisNode); 00193 00194 // initiate stabilization protocol 00195 cancelEvent(stabilize_timer); 00196 scheduleAt(simulation.simTime() + stabilizeDelay, stabilize_timer); 00197 00198 // initiate finger repair protocol 00199 cancelEvent(fixfingers_timer); 00200 scheduleAt(simulation.simTime() + fixfingersDelay, 00201 fixfingers_timer); 00202 00203 // debug message 00204 if (debugOutput) { 00205 EV << "CHORD: Node " << thisNode.ip << " entered READY stage." 00206 << endl; 00207 } 00208 parentModule()->parentModule()->bubble("Enter READY state."); 00209 break; 00210 } 00211 00212 setReadyIcon(state == READY); 00213 }
const NodeHandle & 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 |
00415 { 00416 for (int i = fingerTable->getSize() - 1; i >= 0; i--) { 00417 if (fingerTable->getFinger(i).key.isBetween(thisNode.key, key)) { 00418 // is there a closer preceeding node in the successor list? 00419 for (int j = successorList->getSize() - 1; j >= 0; j--) { 00420 if (successorList->getSuccessor(j).key. 00421 isBetween(fingerTable->getFinger(i).key, key)) { 00422 return successorList->getSuccessor(j); 00423 } 00424 } 00425 00426 // if no, settle with the node already found 00427 return fingerTable->getFinger(i); 00428 } 00429 } 00430 00431 // if no finger is found lookup the rest of the successor list 00432 for (int i = successorList->getSize()-1; i >= 0; i--) { 00433 if(successorList->getSuccessor(i).key.isBetween(thisNode.key, key)) { 00434 return successorList->getSuccessor(i); 00435 } 00436 } 00437 00438 // if this is the first and only node on the ring, it is responsible 00439 if ((predecessorNode.isUnspecified()) && 00440 (successorList->getSuccessor() == thisNode)) { 00441 return thisNode; 00442 } 00443 00444 // if there is still no node found return NodeHandle::UNSPECIFIED_NODE 00445 return NodeHandle::UNSPECIFIED_NODE; 00446 }
void Chord::findFriendModules | ( | ) | [protected, virtual] |
Assigns the finger table and succesesor list module to our reference.
Reimplemented in Koorde.
00882 { 00883 fingerTable = check_and_cast<ChordFingerTable*> 00884 (parentModule()->submodule("fingerTable")); 00885 00886 successorList = check_and_cast<ChordSuccessorList*> 00887 (parentModule()->submodule("successorList")); 00888 }
NodeVector * Chord::findNode | ( | const OverlayKey & | key, | |
BaseOverlayMessage * | msg | |||
) | [protected, virtual] |
Implements the find node call.
This method simply returns the closest nodes known in the corresponding routing topology.
key | The lookup key. | |
msg | A pointer to the BaseRouteMessage or FindNodeCall message of this lookup. |
Reimplemented from BaseOverlay.
Reimplemented in Koorde.
00364 { 00365 NodeVector* nextHop = new NodeVector(1); 00366 00367 if (state != READY) 00368 return nextHop; 00369 00370 // // example code for findNodeExt 00371 00372 // if (msg != NULL) { 00373 // if (!msg->hasObject("findNodeExt")) { 00374 // ChordFindNodeExtMessage *extMsg = 00375 // new ChordFindNodeExtMessage("findNodeExt"); 00376 // extMsg->setLength(8*10); 00377 // msg->addObject( extMsg ); 00378 // } 00379 // 00380 // ChordFindNodeExtMessage *extMsg = 00381 // (ChordFindNodeExtMessage*) msg->getObject("findNodeExt"); 00382 // 00383 // cout << "ChordCount: " << extMsg->getChordCount() + 1 << endl; 00384 // 00385 // extMsg->setChordCount(extMsg->getChordCount() + 1); 00386 // } 00387 00388 // if key is unspecified, the message is for this node 00389 if (key.isUnspecified()) { 00390 // nextHop->push_back(thisNode); 00391 nextHop->push_back(thisNode); 00392 } else if (isResponsible(key)) { 00393 // the message is destined for this node 00394 // nextHop->push_back(thisNode); 00395 nextHop->push_back(thisNode); 00396 } else if (key.isBetweenR(thisNode.key, 00397 successorList->getSuccessor().key)) { 00398 // the message destined for our successor 00399 // nextHop->push_back(successorList->getSuccessor()); 00400 nextHop->push_back(successorList->getSuccessor()); 00401 } else { 00402 // find next hop with finger table 00403 NodeHandle tmpNode = closestPreceedingNode(key); 00404 if (!tmpNode.isUnspecified()) { 00405 // nextHop->push_back(tmpNode); 00406 nextHop->push_back(tmpNode); 00407 } 00408 } 00409 00410 return nextHop; 00411 }
void Chord::finishOverlay | ( | ) | [virtual] |
collects statisticts
Reimplemented from BaseOverlay.
Reimplemented in Koorde.
00494 { 00495 recordScalar("Chord: Sent JOIN Messages", joinCount); 00496 recordScalar("Chord: Sent NEWSUCCESSORHINT Messages", 00497 newsuccessorhintCount); 00498 recordScalar("Chord: Sent STABILIZE Messages", stabilizeCount); 00499 recordScalar("Chord: Sent NOTIFY Messages", notifyCount); 00500 recordScalar("Chord: Sent FIX_FINGERS Messages", fixfingersCount); 00501 recordScalar("Chord: Sent JOIN Bytes", joinBytesSent); 00502 recordScalar("Chord: Sent NEWSUCCESSORHINT Bytes", 00503 newsuccessorhintBytesSent); 00504 recordScalar("Chord: Sent STABILIZE Bytes", stabilizeBytesSent); 00505 recordScalar("Chord: Sent NOTIFY Bytes", notifyBytesSent); 00506 recordScalar("Chord: Sent FIX_FINGERS Bytes", fixfingersBytesSent); 00507 00508 // remove this node from the bootstrap list 00509 bootstrapOracle->removePeer(thisNode); 00510 }
void Chord::handleFixFingersTimerExpired | ( | cMessage * | msg | ) | [protected, virtual] |
handle a expired fix_fingers timer
msg | the timer self-message |
Reimplemented in Koorde.
00603 { 00604 if ((state != READY) || successorList->isEmpty()) 00605 return; 00606 00607 for (uint nextFinger = 0; nextFinger < thisNode.key.getLength(); 00608 nextFinger++) { 00609 // calculate "n + 2^(i - 1)" 00610 OverlayKey offset = OverlayKey::pow2(nextFinger); 00611 OverlayKey lookupKey = thisNode.key + offset; 00612 00613 // send message only for non-trivial fingers 00614 if (offset > successorList->getSuccessor().key - thisNode.key) { 00615 // call FIXFINGER RPC 00616 FixfingersCall* call = new FixfingersCall("FixfingersCall"); 00617 call->setFinger(nextFinger); 00618 call->setLength(FIXFINGERSCALL_L(call)); 00619 00620 sendRpcMessage(NodeHandle::UNSPECIFIED_NODE, call, NULL, 00621 lookupKey, -1, fixfingersDelay); 00622 00623 } else { 00624 // let trivial fingers point to the successor node 00625 fingerTable->setFinger(nextFinger, 00626 successorList->getSuccessor()); 00627 } 00628 } 00629 00630 // schedule next finger repair process 00631 cancelEvent(fixfingers_timer); 00632 scheduleAt(simulation.simTime() + fixfingersDelay, msg); 00633 }
void Chord::handleJoinTimerExpired | ( | cMessage * | msg | ) | [protected, virtual] |
handle a expired join timer
msg | the timer self-message |
00515 { 00516 // only process timer, if node is not bootstrapped yet 00517 if (state == READY) 00518 return; 00519 00520 // enter state BOOTSTRAP 00521 if (state != BOOTSTRAP) 00522 changeState(BOOTSTRAP); 00523 00524 // change bootstrap node from time to time 00525 joinRetry--; 00526 if (joinRetry == 0) { 00527 joinRetry = par("joinRetry"); 00528 changeState(BOOTSTRAP); 00529 return; 00530 } 00531 00532 // call JOIN RPC 00533 JoinCall* call = new JoinCall("JoinCall"); 00534 call->setLength(JOINCALL_L(call)); 00535 00536 sendRpcMessage(bootstrapNode, call, NULL, thisNode.key, -1, joinDelay); 00537 00538 // schedule next bootstrap process in the case this one fails 00539 cancelEvent(join_timer); 00540 scheduleAt(simulation.simTime() + joinDelay, msg); 00541 }
void Chord::handleNewSuccessorHint | ( | ChordMessage * | chordMsg | ) | [protected, virtual] |
handle a received NEWSUCCESSORHINT message
chordMsg | the message to process |
00637 { 00638 NewSuccessorHintMessage* newSuccessorHintMsg = 00639 check_and_cast<NewSuccessorHintMessage*>(chordMsg); 00640 00641 // fetch the successor's predecessor 00642 NodeHandle predecessor = newSuccessorHintMsg->getPreNode(); 00643 00644 // is the successor's predecessor a new successor for this node? 00645 if (predecessor.key.isBetween(thisNode.key, 00646 successorList->getSuccessor().key) 00647 || (thisNode.key == successorList->getSuccessor().key)) { 00648 // add the successor's predecessor to the successor list 00649 successorList->addSuccessor(predecessor); 00650 updateTooltip(); 00651 } 00652 }
void Chord::handleRpc | ( | BaseCallMessage * | msg | ) | [protected, virtual] |
Processes Remote-Procedure-Call invokation messages.
Reimplemented from BaseOverlay.
Reimplemented in Koorde.
00255 { 00256 if (state != READY) { 00257 delete msg; 00258 EV << "Chord::handleRpc(): Received RPC call " 00259 << "and state != READY!" << endl; 00260 return; 00261 } 00262 00263 // delegate messages 00264 RPC_SWITCH_START( msg ) 00265 // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> ) 00266 RPC_DELEGATE( Join, rpcJoin ); 00267 RPC_DELEGATE( Notify, rpcNotify ); 00268 RPC_DELEGATE( Stabilize, rpcStabilize ); 00269 RPC_DELEGATE( Fixfingers, rpcFixfingers ); 00270 RPC_SWITCH_END( ) 00271 }
void Chord::handleRpcFixfingersResponse | ( | FixfingersResponse * | fixfingersResponse | ) | [protected, virtual] |
00873 { 00874 // set new finger pointer 00875 NodeHandle successor = fixfingersResponse->getSucNode(); 00876 fingerTable->setFinger(fixfingersResponse->getFinger(), successor); 00877 }
void Chord::handleRpcJoinResponse | ( | JoinResponse * | joinResponse | ) | [protected, virtual] |
Reimplemented in Koorde.
00717 { 00718 // determine the numer of successor nodes to add 00719 int sucNum = successorListSize - 1; 00720 00721 if (joinResponse->getSucNum() < successorListSize - 1) { 00722 sucNum = joinResponse->getSucNum(); 00723 } 00724 00725 // add successor node(s) 00726 for (int k = 0; k < sucNum; k++) { 00727 NodeHandle successor = joinResponse->getSucNode(k); 00728 successorList->addSuccessor(successor); 00729 } 00730 00731 // \todo {check commented out addSuccessor (Schenk)} 00732 //successorList->addSuccessor(joinResponse->getSrcNode()); 00733 00734 00735 // the sender of this message is our new successor 00736 successorList->addSuccessor(joinResponse->getSrcNode()); 00737 00738 // in aggressiveJoinMode: use hint in JoinResponse 00739 // to set our new predecessor 00740 if (aggressiveJoinMode) { 00741 predecessorNode = joinResponse->getPreNode(); 00742 } 00743 00744 updateTooltip(); 00745 00746 changeState(READY); 00747 00748 // immediate stabilization protocol 00749 cancelEvent(stabilize_timer); 00750 scheduleAt(simulation.simTime(), stabilize_timer); 00751 00752 // immediate finger repair protocol 00753 cancelEvent(fixfingers_timer); 00754 scheduleAt(simulation.simTime(), fixfingers_timer); 00755 }
void Chord::handleRpcNotifyResponse | ( | NotifyResponse * | notifyResponse | ) | [protected, virtual] |
Reimplemented in Koorde.
00830 { 00831 if (successorList->getSuccessor() != notifyResponse->getSrcNode()) { 00832 EV << "Chord::handleRpcNotifyResponse: The srcNode of the received " 00833 << "NotifyResponse is not our current successor!" << endl; 00834 return; 00835 } 00836 00837 // determine number of successor nodes to add 00838 int sucNum = successorListSize - 1; 00839 if (notifyResponse->getSucNum() < successorListSize - 1) { 00840 sucNum = notifyResponse->getSucNum(); 00841 } 00842 00843 // replace our successor list by our successor's successor list 00844 // and add our current successor to the list 00845 successorList->clear(); 00846 successorList->addSuccessor(notifyResponse->getSrcNode()); 00847 for (int k = 0; k < sucNum; k++) { 00848 NodeHandle successor = notifyResponse->getSucNode(k); 00849 // don't add nodes, if this would change our successor 00850 if (!successor.key.isBetweenLR(thisNode.key, 00851 notifyResponse->getSrcNode().key)) { 00852 successorList->addSuccessor(successor); 00853 } 00854 } 00855 updateTooltip(); 00856 }
void Chord::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
int | rpcId, | |||
simtime_t | rtt | |||
) | [protected, virtual] |
This method is called if an RPC response has been received.
msg | The response message. | |
rpcId | The RPC id. | |
rtt | The Round-Trip-Time of this RPC |
Reimplemented from RpcListener.
Reimplemented in Koorde.
00275 { 00276 RPC_SWITCH_START(msg) 00277 RPC_ON_RESPONSE( Join ) { 00278 handleRpcJoinResponse(_JoinResponse); 00279 EV << "Join RPC Response received: id=" << rpcId 00280 << " msg=" << *_JoinResponse << " rtt=" << rtt << endl; 00281 break; 00282 } 00283 RPC_ON_RESPONSE( Notify ) { 00284 handleRpcNotifyResponse(_NotifyResponse); 00285 EV << "Notify RPC Response received: id=" << rpcId 00286 << " msg=" << *_NotifyResponse << " rtt=" << rtt << endl; 00287 break; 00288 } 00289 RPC_ON_RESPONSE( Stabilize ) { 00290 handleRpcStabilizeResponse(_StabilizeResponse); 00291 EV << "Stabilize RPC Response received: id=" << rpcId 00292 << " msg=" << *_StabilizeResponse << " rtt=" << rtt << endl; 00293 break; 00294 } 00295 RPC_ON_RESPONSE( Fixfingers ) { 00296 handleRpcFixfingersResponse(_FixfingersResponse); 00297 EV << "Fixfingers RPC Response received: id=" << rpcId 00298 << " msg=" << *_FixfingersResponse << " rtt=" << rtt << endl; 00299 break; 00300 } 00301 RPC_SWITCH_END( ) 00302 }
void Chord::handleRpcStabilizeResponse | ( | StabilizeResponse * | stabilizeResponse | ) | [protected, virtual] |
Reimplemented in Koorde.
00773 { 00774 // our successor seems to be alive 00775 missingSuccessorStabResponses = 0; 00776 00777 // fetch the successor's predecessor 00778 NodeHandle predecessor = stabilizeResponse->getPreNode(); 00779 00780 // is the successor's predecessor a new successor for this node? 00781 if (successorList->isEmpty() || 00782 predecessor.key.isBetween(thisNode.key, 00783 successorList->getSuccessor().key)) { 00784 // add the successor's predecessor to the successor list 00785 successorList->addSuccessor(predecessor); 00786 updateTooltip(); 00787 } 00788 00789 // compile NOTIFY RPC 00790 NotifyCall* notifyCall = new NotifyCall("NotifyCall"); 00791 notifyCall->setLength(NOTIFYCALL_L(notifyCall)); 00792 00793 sendRpcMessage(successorList->getSuccessor(), notifyCall); 00794 }
void Chord::handleRpcTimeout | ( | BaseCallMessage * | msg, | |
const NodeHandle & | dest, | |||
int | rpcId | |||
) | [protected, virtual] |
This method is called if an RPC timeout has been reached.
msg | The original RPC message. | |
dest | The destination of the RPC | |
rpcId | The RPC id. |
Reimplemented in Koorde.
00306 { 00307 RPC_SWITCH_START(msg) 00308 RPC_ON_CALL( FindNode ) { 00309 EV << "FindNode RPC Call timed out: id=" << rpcId 00310 << " msg=" << *_FindNodeCall << endl; 00311 break; 00312 } 00313 RPC_ON_CALL( Join ) { 00314 EV << "Join RPC Call timed out: id=" << rpcId 00315 << " msg=" << *_JoinCall << endl; 00316 break; 00317 } 00318 RPC_ON_CALL( Notify ) { 00319 EV << "Notify RPC Call timed out: id=" << rpcId 00320 << " msg=" << *_NotifyCall << endl; 00321 break; 00322 } 00323 RPC_ON_CALL( Stabilize ) { 00324 EV << "Stabilize RPC Call timed out: id=" << rpcId 00325 << " msg=" << *_StabilizeCall << endl; 00326 break; 00327 } 00328 RPC_ON_CALL( Fixfingers ) { 00329 EV << "Fixfingers RPC Call timed out: id=" << rpcId 00330 << " msg=" << *_FixfingersCall << endl; 00331 break; 00332 } 00333 RPC_SWITCH_END( ) 00334 }
void Chord::handleStabilizeTimerExpired | ( | cMessage * | msg | ) | [protected, virtual] |
handle a expired stabilize timer
msg | the timer self-message |
00545 { 00546 if (state != READY) 00547 return; 00548 00549 if (missingPredecessorStabRequests >= stabilizeRetry) { 00550 // predecessor node seems to be dead 00551 // remove it from the predecessor / successor lists 00552 successorList->removeSuccessor(predecessorNode); 00553 predecessorIsDead(); 00554 predecessorNode = NodeHandle::UNSPECIFIED_NODE; 00555 00556 missingPredecessorStabRequests = 0; 00557 updateTooltip(); 00558 } 00559 00560 if (missingSuccessorStabResponses >= stabilizeRetry) { 00561 // successor node seems to be dead 00562 // remove it from the predecessor / successor list 00563 successorIsDead(); 00564 NodeHandle successor = successorList->popSuccessor(); 00565 00566 // if we had a ring consisting of 2 nodes and our successor seems 00567 // to be dead. Remove also predecessor because the successor 00568 // and predecessor are the same node 00569 if ((!predecessorNode.isUnspecified()) && 00570 predecessorNode == successor) { 00571 predecessorIsDead(); 00572 predecessorNode = NodeHandle::UNSPECIFIED_NODE; 00573 } 00574 00575 missingSuccessorStabResponses = 0; 00576 updateTooltip(); 00577 00578 if (successorList->isEmpty()) { 00579 changeState(INIT); 00580 changeState(BOOTSTRAP); 00581 return; 00582 } 00583 } 00584 00585 if (!successorList->isEmpty()) { 00586 // call STABILIZE RPC 00587 StabilizeCall* call = new StabilizeCall("StabilizeCall"); 00588 call->setLength(STABILIZECALL_L(call)); 00589 00590 sendRpcMessage(successorList->getSuccessor(), call); 00591 00592 missingPredecessorStabRequests++; 00593 missingSuccessorStabResponses++; 00594 } 00595 00596 // schedule next stabilization process 00597 cancelEvent(stabilize_timer); 00598 scheduleAt(simulation.simTime() + stabilizeDelay, msg); 00599 }
void Chord::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
handles self-messages
msg | the self-message |
Reimplemented from BaseOverlay.
Reimplemented in Koorde.
00217 { 00218 // catch JOIN timer 00219 if (msg->isName("join_timer")) { 00220 handleJoinTimerExpired(msg); 00221 } 00222 // catch STABILIZE timer 00223 else if (msg->isName("stabilize_timer")) { 00224 handleStabilizeTimerExpired(msg); 00225 } 00226 // catch FIX_FINGERS timer 00227 else if (msg->isName("fixfingers_timer")) { 00228 handleFixFingersTimerExpired(msg); 00229 } 00230 // unknown self message 00231 else { 00232 error("Chord::handleTimerEvent(): received self message of " 00233 "unknown type!"); 00234 } 00235 }
void Chord::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
processes messages from underlay
msg | message from UDP |
Implements BaseOverlay.
Reimplemented in Koorde.
00239 { 00240 ChordMessage* chordMsg = check_and_cast<ChordMessage*>(msg); 00241 switch(chordMsg->getCommand()) { 00242 case NEWSUCCESSORHINT: 00243 handleNewSuccessorHint(chordMsg); 00244 break; 00245 default: 00246 error("handleUDPMessage(): Unknown message type!"); 00247 break; 00248 } 00249 00250 delete chordMsg; 00251 }
void Chord::initializeFriendModules | ( | ) | [protected, virtual] |
initializes finger table and successor list
Reimplemented in Koorde.
00893 { 00894 // initialize finger table 00895 fingerTable->initializeTable(thisNode.key.getLength(), thisNode); 00896 00897 // initialize successor list 00898 successorList->initializeList(par("successorListSize"), thisNode); 00899 }
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.
00037 { 00038 // because of IPAddressResolver, we need to wait until interfaces 00039 // are registered, address auto-assignment takes place etc. 00040 if(stage != MIN_STAGE_OVERLAY) 00041 return; 00042 00043 // fetch some parameters 00044 useCommonAPIforward = par("useCommonAPIforward"); 00045 successorListSize = par("successorListSize"); 00046 joinRetry = par("joinRetry"); 00047 stabilizeRetry = par("stabilizeRetry"); 00048 joinDelay = par("joinDelay"); 00049 stabilizeDelay = par("stabilizeDelay"); 00050 fixfingersDelay = par("fixfingersDelay"); 00051 aggressiveJoinMode = par("aggressiveJoinMode"); 00052 00053 keyLength = OverlayKey::getLength(); 00054 missingPredecessorStabRequests = 0; 00055 missingSuccessorStabResponses = 0; 00056 00057 // statistics 00058 joinCount = 0; 00059 stabilizeCount = 0; 00060 fixfingersCount = 0; 00061 notifyCount = 0; 00062 newsuccessorhintCount = 0; 00063 joinBytesSent = 0; 00064 stabilizeBytesSent = 0; 00065 notifyBytesSent = 0; 00066 fixfingersBytesSent = 0; 00067 newsuccessorhintBytesSent = 0; 00068 00069 00070 // find friend modules 00071 findFriendModules(); 00072 00073 // add some watches 00074 WATCH(predecessorNode); 00075 WATCH(thisNode); 00076 WATCH(bootstrapNode); 00077 WATCH(joinRetry); 00078 WATCH(missingPredecessorStabRequests); 00079 WATCH(missingSuccessorStabResponses); 00080 00081 // self-messages 00082 join_timer = new cMessage("join_timer"); 00083 stabilize_timer = new cMessage("stabilize_timer"); 00084 fixfingers_timer = new cMessage("fixfingers_timer"); 00085 00086 // initialize chord protocol 00087 changeState(INIT); 00088 changeState(BOOTSTRAP); 00089 }
bool Chord::isResponsible | ( | const OverlayKey & | key | ) | [virtual] |
Query if the node is responsible for a key.
Query if the node currently is responsible for the given key. Usually this means, that the nodeId of this node is close to the key.
key | destination key |
Reimplemented from BaseOverlay.
00338 { 00339 if (key.isUnspecified()) 00340 error("Chord::isResponsible(): key is unspecified!"); 00341 00342 if (state != READY) 00343 return false; 00344 00345 // if this is the first and only node on the ring, it is responsible 00346 if (predecessorNode.isUnspecified()) { 00347 if(successorList->isEmpty()) { 00348 return true; 00349 } else { 00350 return false; 00351 } 00352 } 00353 00354 // is the message destined for this node? 00355 if (key.isBetweenR(predecessorNode.key, thisNode.key)) { 00356 return true; 00357 } 00358 00359 return false; 00360 }
void Chord::predecessorIsDead | ( | ) | [protected, virtual] |
void Chord::receiveChangeNotification | ( | int | category, | |
cPolymorphic * | details | |||
) | [virtual] |
callback-method for events at the NotificationBoard
category | ||
details |
00106 { 00107 Enter_Method_Silent(); 00108 // get new ip address 00109 thisNode.ip = IPAddressResolver().addressOf( 00110 parentModule()->parentModule()).get4(); 00111 00112 changeState(INIT); 00113 changeState(BOOTSTRAP); 00114 }
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.
00449 { 00450 BaseOverlayMessage* innerMsg; 00451 00452 if (msg->getType() == OVERLAYROUTE) 00453 innerMsg = dynamic_cast<BaseOverlayMessage*>(msg->encapsulatedMsg()); 00454 else 00455 innerMsg = msg; 00456 00457 switch (innerMsg->getType()) { 00458 00459 case OVERLAYSIGNALING: { 00460 ChordMessage* chordMsg = dynamic_cast<ChordMessage*>(innerMsg); 00461 switch(chordMsg->getCommand()) { 00462 case NEWSUCCESSORHINT: 00463 RECORD_STATS(newsuccessorhintCount++; newsuccessorhintBytesSent += 00464 msg->byteLength()); 00465 break; 00466 } 00467 break; 00468 } 00469 00470 case RPC: { 00471 if ((dynamic_cast<StabilizeCall*>(innerMsg) != NULL) || 00472 (dynamic_cast<StabilizeResponse*>(innerMsg) != NULL)) { 00473 RECORD_STATS(stabilizeCount++; stabilizeBytesSent += 00474 msg->byteLength()); 00475 } else if ((dynamic_cast<NotifyCall*>(innerMsg) != NULL) || 00476 (dynamic_cast<NotifyResponse*>(innerMsg) != NULL)) { 00477 RECORD_STATS(notifyCount++; notifyBytesSent += 00478 msg->byteLength()); 00479 } else if ((dynamic_cast<FixfingersCall*>(innerMsg) != NULL) || 00480 (dynamic_cast<FixfingersResponse*>(innerMsg) != NULL)) { 00481 RECORD_STATS(fixfingersCount++; fixfingersBytesSent += 00482 msg->byteLength()); 00483 } else if ((dynamic_cast<JoinCall*>(innerMsg) != NULL) || 00484 (dynamic_cast<JoinResponse*>(innerMsg) != NULL)) { 00485 RECORD_STATS(joinCount++; joinBytesSent += msg->byteLength()); 00486 } 00487 break; 00488 } 00489 } 00490 }
void Chord::rpcFixfingers | ( | FixfingersCall * | call | ) | [protected] |
Fixfingers Remote-Procedure-Call.
call | RPC Parameter Message |
00860 { 00861 FixfingersResponse* fixfingersResponse = 00862 new FixfingersResponse("FixfingersResponse"); 00863 00864 fixfingersResponse->setSucNode(thisNode); 00865 fixfingersResponse->setFinger(call->getFinger()); 00866 fixfingersResponse->setLength(FIXFINGERSRESPONSE_L(fixfingersResponse)); 00867 00868 sendRpcResponse(call, fixfingersResponse); 00869 }
void Chord::rpcJoin | ( | JoinCall * | call | ) | [protected] |
Join Remote-Procedure-Call.
call | RPC Parameter Message |
00656 { 00657 NodeHandle requestor = joinCall->getSrcNode(); 00658 00659 // compile successor list 00660 JoinResponse* joinResponse = 00661 new JoinResponse("JoinResponse"); 00662 00663 int sucNum = successorList->getSize(); 00664 joinResponse->setSucNum(sucNum); 00665 joinResponse->setSucNodeArraySize(sucNum); 00666 00667 for (int k = 0; k < sucNum; k++) { 00668 joinResponse->setSucNode(k, successorList->getSuccessor(k)); 00669 } 00670 00671 // sent our predecessor as hint to the joining node 00672 if (predecessorNode.isUnspecified() && successorList->isEmpty()) { 00673 // we are the only node in the ring 00674 joinResponse->setPreNode(thisNode); 00675 } else { 00676 joinResponse->setPreNode(predecessorNode); 00677 } 00678 00679 joinResponse->setLength(JOINRESPONSE_L(joinResponse)); 00680 00681 sendRpcResponse(joinCall, joinResponse); 00682 00683 if (aggressiveJoinMode) { 00684 // aggressiveJoinMode differs from standard join operations: 00685 // 1. set our predecessor pointer to the joining node 00686 // 2. send our old predecessor as hint in JoinResponse msgs 00687 // 3. send a NEWSUCCESSORHINT to our old predecessor to update 00688 // its successor pointer 00689 00690 // send NEWSUCCESSORHINT to our old predecessor 00691 00692 if (!predecessorNode.isUnspecified()) { 00693 NewSuccessorHintMessage* newSuccessorHintMsg = 00694 new NewSuccessorHintMessage("NEWSUCCESSORHINT"); 00695 newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT); 00696 00697 newSuccessorHintMsg->setSrcNode(thisNode); 00698 newSuccessorHintMsg->setPreNode(requestor); 00699 newSuccessorHintMsg->setLength( 00700 NEWSUCCESSORHINT_L(newSuccessorHintMsg)); 00701 00702 sendMessageToUDP(predecessorNode, newSuccessorHintMsg); 00703 } 00704 00705 // the requestor is our new predecessor 00706 predecessorNode = requestor; 00707 } 00708 00709 // if we don't have a successor, the requestor is also our new successor 00710 if (successorList->isEmpty()) 00711 successorList->addSuccessor(requestor); 00712 00713 updateTooltip(); 00714 }
void Chord::rpcNotify | ( | NotifyCall * | call | ) | [protected] |
NOTIFY Remote-Procedure-Call.
call | RPC Parameter Message |
Reimplemented in Koorde.
00798 { 00799 // our predecessor seems to be alive 00800 missingPredecessorStabRequests = 0; 00801 00802 NodeHandle predecessor = call->getSrcNode(); 00803 00804 // is the new predecessor closer than the current one? 00805 if (predecessorNode.isUnspecified() || 00806 predecessor.key.isBetween(predecessorNode.key, thisNode.key)) { 00807 // set up new predecessor 00808 predecessorNode = predecessor; 00809 updateTooltip(); 00810 } 00811 00812 // compile NOTIFY response 00813 NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse"); 00814 00815 int sucNum = successorList->getSize(); 00816 notifyResponse->setSucNum(sucNum); 00817 notifyResponse->setSucNodeArraySize(sucNum); 00818 00819 for (int k = 0; k < sucNum; k++) { 00820 notifyResponse->setSucNode(k, successorList->getSuccessor(k)); 00821 } 00822 00823 notifyResponse->setLength(NOTIFYRESPONSE_L(notifyResponse)); 00824 00825 sendRpcResponse(call, notifyResponse); 00826 }
void Chord::rpcStabilize | ( | StabilizeCall * | call | ) | [protected] |
STABILIZE Remote-Procedure-Call.
call | RPC Parameter Message |
00759 { 00760 // our predecessor seems to be alive 00761 missingPredecessorStabRequests = 0; 00762 00763 // reply with StabilizeResponse message 00764 StabilizeResponse* stabilizeResponse = 00765 new StabilizeResponse("StabilizeResponse"); 00766 stabilizeResponse->setPreNode(predecessorNode); 00767 stabilizeResponse->setLength(STABILIZERESPONSE_L(stabilizeResponse)); 00768 00769 sendRpcResponse(call, stabilizeResponse); 00770 }
void Chord::successorIsDead | ( | ) | [protected, virtual] |
void Chord::updateTooltip | ( | ) | [virtual] |
updates information shown in tk-environment
Reimplemented in Koorde.
00903 { 00904 if (ev.isGUI()) { 00905 std::stringstream ttString; 00906 00907 // show our predecessor and successor in tooltip 00908 ttString << predecessorNode << endl << thisNode << endl 00909 << successorList->getSuccessor(); 00910 00911 parentModule()->parentModule()->displayString(). 00912 setTagArg("tt", 0, ttString.str().c_str()); 00913 parentModule()->displayString(). 00914 setTagArg("tt", 0, ttString.str().c_str()); 00915 displayString().setTagArg("tt", 0, ttString.str().c_str()); 00916 00917 // draw an arrow to our current successor 00918 showOverlayNeighborArrow(successorList->getSuccessor(), true, 00919 "m=m,50,0,50,0;o=red,1"); 00920 showOverlayNeighborArrow(predecessorNode, false, 00921 "m=m,50,100,50,100;o=green,1"); 00922 } 00923 }
bool Chord::aggressiveJoinMode [protected] |
use modified (faster) JOIN protocol
NodeHandle Chord::bootstrapNode [protected] |
node used to bootrap
ChordFingerTable* Chord::fingerTable [protected] |
pointer to this node's finger table
cMessage* Chord::fixfingers_timer [protected] |
int Chord::fixfingersBytesSent [protected] |
int Chord::fixfingersCount [protected] |
double Chord::fixfingersDelay [protected] |
cMessage* Chord::join_timer [protected] |
int Chord::joinBytesSent [protected] |
int Chord::joinCount [protected] |
double Chord::joinDelay [protected] |
int Chord::joinRetry [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
int Chord::newsuccessorhintBytesSent [protected] |
int Chord::newsuccessorhintCount [protected] |
int Chord::notifyBytesSent [protected] |
int Chord::notifyCount [protected] |
NodeHandle Chord::predecessorNode [protected] |
predecessor of this node
cMessage* Chord::stabilize_timer [protected] |
int Chord::stabilizeBytesSent [protected] |
int Chord::stabilizeCount [protected] |
double Chord::stabilizeDelay [protected] |
stabilize interval (secs)
int Chord::stabilizeRetry [protected] |
// retries before neighbor considered failed
int Chord::state [protected] |
current node state
ChordSuccessorList* Chord::successorList [protected] |
pointer to this node's successor list
int Chord::successorListSize [protected] |