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