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