00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <GlobalStatistics.h>
00025 #include <Comparator.h>
00026 #include <BootstrapList.h>
00027 #include <GlobalParameters.h>
00028 #include <NeighborCache.h>
00029
00030 #include <ChordFingerTable.h>
00031 #include <ChordSuccessorList.h>
00032
00033 #include "Chord.h"
00034
00035 namespace oversim {
00036
00037 Define_Module(Chord);
00038
00039 Chord::Chord()
00040 {
00041 stabilize_timer = fixfingers_timer = join_timer = NULL;
00042 fingerTable = NULL;
00043 }
00044
00045
00046 void Chord::initializeOverlay(int stage)
00047 {
00048
00049
00050 if (stage != MIN_STAGE_OVERLAY)
00051 return;
00052
00053 if (iterativeLookupConfig.merge == true) {
00054 throw cRuntimeError("Chord::initializeOverlay(): "
00055 "Chord doesn't work with iterativeLookupConfig.merge = true!");
00056 }
00057
00058
00059 kbr = true;
00060
00061
00062 useCommonAPIforward = par("useCommonAPIforward");
00063 successorListSize = par("successorListSize");
00064 joinRetry = par("joinRetry");
00065 stabilizeRetry = par("stabilizeRetry");
00066 joinDelay = par("joinDelay");
00067 stabilizeDelay = par("stabilizeDelay");
00068 fixfingersDelay = par("fixfingersDelay");
00069 checkPredecessorDelay = par("checkPredecessorDelay");
00070 aggressiveJoinMode = par("aggressiveJoinMode");
00071 extendedFingerTable = par("extendedFingerTable");
00072 numFingerCandidates = par("numFingerCandidates");
00073 proximityRouting = par("proximityRouting");
00074 memorizeFailedSuccessor = par("memorizeFailedSuccessor");
00075
00076
00077 mergeOptimizationL1 = par("mergeOptimizationL1");
00078 mergeOptimizationL2 = par("mergeOptimizationL2");
00079 mergeOptimizationL3 = par("mergeOptimizationL3");
00080 mergeOptimizationL4 = par("mergeOptimizationL4");
00081
00082 keyLength = OverlayKey::getLength();
00083 missingPredecessorStabRequests = 0;
00084
00085
00086 joinCount = 0;
00087 stabilizeCount = 0;
00088 fixfingersCount = 0;
00089 notifyCount = 0;
00090 newsuccessorhintCount = 0;
00091 joinBytesSent = 0;
00092 stabilizeBytesSent = 0;
00093 notifyBytesSent = 0;
00094 fixfingersBytesSent = 0;
00095 newsuccessorhintBytesSent = 0;
00096
00097 failedSuccessor = TransportAddress::UNSPECIFIED_NODE;
00098
00099
00100 findFriendModules();
00101
00102
00103 WATCH(predecessorNode);
00104 WATCH(thisNode);
00105 WATCH(bootstrapNode);
00106 WATCH(joinRetry);
00107 WATCH(missingPredecessorStabRequests);
00108
00109
00110 join_timer = new cMessage("join_timer");
00111 stabilize_timer = new cMessage("stabilize_timer");
00112 fixfingers_timer = new cMessage("fixfingers_timer");
00113 checkPredecessor_timer = new cMessage("checkPredecessor_timer");
00114 }
00115
00116
00117 Chord::~Chord()
00118 {
00119
00120 cancelAndDelete(join_timer);
00121 cancelAndDelete(stabilize_timer);
00122 cancelAndDelete(fixfingers_timer);
00123 cancelAndDelete(checkPredecessor_timer);
00124 }
00125
00126
00127
00128 void Chord::joinOverlay()
00129 {
00130 changeState(INIT);
00131 changeState(BOOTSTRAP);
00132 }
00133
00134
00135 void Chord::joinForeignPartition(const NodeHandle &node)
00136 {
00137 Enter_Method_Silent();
00138
00139
00140 JoinCall *call = new JoinCall("JoinCall");
00141 call->setBitLength(JOINCALL_L(call));
00142
00143 RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00144 defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
00145 SEMI_RECURSIVE_ROUTING : defaultRoutingType;
00146
00147 sendRouteRpcCall(OVERLAY_COMP, node, thisNode.getKey(),
00148 call, NULL, routingType, joinDelay);
00149 }
00150
00151
00152 void Chord::changeState(int toState)
00153 {
00154
00155
00156
00157
00158 switch (toState) {
00159 case INIT:
00160 state = INIT;
00161
00162 setOverlayReady(false);
00163
00164
00165 predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00166
00167
00168 initializeFriendModules();
00169
00170 updateTooltip();
00171
00172
00173 if (debugOutput) {
00174 EV << "[Chord::changeState() @ " << thisNode.getAddress()
00175 << " (" << thisNode.getKey().toString(16) << ")]\n"
00176 << " Entered INIT stage"
00177 << endl;
00178 }
00179
00180 getParentModule()->getParentModule()->bubble("Enter INIT state.");
00181 break;
00182
00183 case BOOTSTRAP:
00184 state = BOOTSTRAP;
00185
00186
00187 cancelEvent(join_timer);
00188
00189
00190 take(join_timer);
00191 scheduleAt(simTime(), join_timer);
00192
00193
00194 if (debugOutput) {
00195 EV << "[Chord::changeState() @ " << thisNode.getAddress()
00196 << " (" << thisNode.getKey().toString(16) << ")]\n"
00197 << " Entered BOOTSTRAP stage"
00198 << endl;
00199 }
00200 getParentModule()->getParentModule()->bubble("Enter BOOTSTRAP state.");
00201
00202
00203 bootstrapNode = bootstrapList->getBootstrapNode();
00204
00205
00206 if (bootstrapNode.isUnspecified()) {
00207
00208 assert(predecessorNode.isUnspecified());
00209 bootstrapNode = thisNode;
00210 changeState(READY);
00211 updateTooltip();
00212 }
00213 break;
00214
00215 case READY:
00216 state = READY;
00217
00218 setOverlayReady(true);
00219
00220
00221 cancelEvent(stabilize_timer);
00222 scheduleAt(simTime() + stabilizeDelay, stabilize_timer);
00223
00224
00225 cancelEvent(fixfingers_timer);
00226 scheduleAt(simTime() + fixfingersDelay,
00227 fixfingers_timer);
00228
00229
00230 cancelEvent(checkPredecessor_timer);
00231 if (checkPredecessorDelay > 0) {
00232 scheduleAt(simTime() + checkPredecessorDelay,
00233 checkPredecessor_timer);
00234 }
00235
00236
00237 if (debugOutput) {
00238 EV << "[Chord::changeState() @ " << thisNode.getAddress()
00239 << " (" << thisNode.getKey().toString(16) << ")]\n"
00240 << " Entered READY stage"
00241 << endl;
00242 }
00243 getParentModule()->getParentModule()->bubble("Enter READY state.");
00244 break;
00245 }
00246 }
00247
00248
00249 void Chord::handleTimerEvent(cMessage* msg)
00250 {
00251
00252 if (msg == join_timer) {
00253 handleJoinTimerExpired(msg);
00254 }
00255
00256 else if (msg == stabilize_timer) {
00257 handleStabilizeTimerExpired(msg);
00258 }
00259
00260 else if (msg == fixfingers_timer) {
00261 handleFixFingersTimerExpired(msg);
00262 }
00263
00264 else if (msg == checkPredecessor_timer) {
00265 cancelEvent(checkPredecessor_timer);
00266 scheduleAt(simTime() + checkPredecessorDelay,
00267 checkPredecessor_timer);
00268 if (!predecessorNode.isUnspecified()) pingNode(predecessorNode);
00269 }
00270
00271 else {
00272 error("Chord::handleTimerEvent(): received self message of "
00273 "unknown type!");
00274 }
00275 }
00276
00277
00278 void Chord::handleUDPMessage(BaseOverlayMessage* msg)
00279 {
00280 ChordMessage* chordMsg = check_and_cast<ChordMessage*>(msg);
00281 switch(chordMsg->getCommand()) {
00282 case NEWSUCCESSORHINT:
00283 handleNewSuccessorHint(chordMsg);
00284 break;
00285 default:
00286 error("handleUDPMessage(): Unknown message type!");
00287 break;
00288 }
00289
00290 delete chordMsg;
00291 }
00292
00293
00294 bool Chord::handleRpcCall(BaseCallMessage* msg)
00295 {
00296 if (state != READY) {
00297 EV << "[Chord::handleRpcCall() @ " << thisNode.getAddress()
00298 << " (" << thisNode.getKey().toString(16) << ")]\n"
00299 << " Received RPC call and state != READY"
00300 << endl;
00301 return false;
00302 }
00303
00304
00305 RPC_SWITCH_START( msg )
00306
00307 RPC_DELEGATE( Join, rpcJoin );
00308 RPC_DELEGATE( Notify, rpcNotify );
00309 RPC_DELEGATE( Stabilize, rpcStabilize );
00310 RPC_DELEGATE( Fixfingers, rpcFixfingers );
00311 RPC_SWITCH_END( )
00312
00313 return RPC_HANDLED;
00314 }
00315
00316 void Chord::handleRpcResponse(BaseResponseMessage* msg,
00317 cPolymorphic* context, int rpcId,
00318 simtime_t rtt)
00319 {
00320 RPC_SWITCH_START(msg)
00321 RPC_ON_RESPONSE( Join ) {
00322 handleRpcJoinResponse(_JoinResponse);
00323 EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00324 << " (" << thisNode.getKey().toString(16) << ")]\n"
00325 << " Received a Join RPC Response: id=" << rpcId << "\n"
00326 << " msg=" << *_JoinResponse << " rtt=" << rtt
00327 << endl;
00328 break;
00329 }
00330 RPC_ON_RESPONSE( Notify ) {
00331 handleRpcNotifyResponse(_NotifyResponse);
00332 EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00333 << " (" << thisNode.getKey().toString(16) << ")]\n"
00334 << " Received a Notify RPC Response: id=" << rpcId << "\n"
00335 << " msg=" << *_NotifyResponse << " rtt=" << rtt
00336 << endl;
00337 break;
00338 }
00339 RPC_ON_RESPONSE( Stabilize ) {
00340 handleRpcStabilizeResponse(_StabilizeResponse);
00341 EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00342 << " (" << thisNode.getKey().toString(16) << ")]\n"
00343 << " Received a Stabilize RPC Response: id=" << rpcId << "\n"
00344 << " msg=" << *_StabilizeResponse << " rtt=" << rtt
00345 << endl;
00346 break;
00347 }
00348 RPC_ON_RESPONSE( Fixfingers ) {
00349 handleRpcFixfingersResponse(_FixfingersResponse, SIMTIME_DBL(rtt));
00350 EV << "[Chord::handleRpcResponse() @ " << thisNode.getAddress()
00351 << " (" << thisNode.getKey().toString(16) << ")]\n"
00352 << " Received a Fixfingers RPC Response: id=" << rpcId << "\n"
00353 << " msg=" << *_FixfingersResponse << " rtt=" << rtt
00354 << endl;
00355 break;
00356 }
00357 RPC_SWITCH_END( )
00358 }
00359
00360 void Chord::handleRpcTimeout(BaseCallMessage* msg,
00361 const TransportAddress& dest,
00362 cPolymorphic* context, int rpcId,
00363 const OverlayKey&)
00364 {
00365 RPC_SWITCH_START(msg)
00366 RPC_ON_CALL( FindNode ) {
00367 EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00368 << " (" << thisNode.getKey().toString(16) << ")]\n"
00369 << " FindNode RPC Call timed out: id=" << rpcId << "\n"
00370 << " msg=" << *_FindNodeCall
00371 << endl;
00372 break;
00373 }
00374 RPC_ON_CALL( Join ) {
00375 EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00376 << " (" << thisNode.getKey().toString(16) << ")]\n"
00377 << " Join RPC Call timed out: id=" << rpcId << "\n"
00378 << " msg=" << *_JoinCall
00379 << endl;
00380 break;
00381 }
00382 RPC_ON_CALL( Notify ) {
00383 EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00384 << " (" << thisNode.getKey().toString(16) << ")]\n"
00385 << " Notify RPC Call timed out: id=" << rpcId << "\n"
00386 << " msg=" << *_NotifyCall
00387 << endl;
00388 if (!handleFailedNode(dest)) join();
00389 break;
00390 }
00391 RPC_ON_CALL( Stabilize ) {
00392 EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00393 << " (" << thisNode.getKey().toString(16) << ")]\n"
00394 << " Stabilize RPC Call timed out: id=" << rpcId << "\n"
00395 << " msg=" << *_StabilizeCall
00396 << endl;
00397 if (!handleFailedNode(dest)) join();
00398 break;
00399 }
00400 RPC_ON_CALL( Fixfingers ) {
00401 EV << "[Chord::handleRpcTimeout() @ " << thisNode.getAddress()
00402 << " (" << thisNode.getKey().toString(16) << ")]\n"
00403 << " Fixfingers RPC Call timed out: id=" << rpcId << "\n"
00404 << " msg=" << *_FixfingersCall
00405 << endl;
00406 break;
00407 }
00408 RPC_SWITCH_END( )
00409 }
00410
00411 int Chord::getMaxNumSiblings()
00412 {
00413 return successorListSize;
00414 }
00415
00416 int Chord::getMaxNumRedundantNodes()
00417 {
00418 return extendedFingerTable ? numFingerCandidates : 1;
00419 }
00420
00421
00422 bool Chord::isSiblingFor(const NodeHandle& node,
00423 const OverlayKey& key,
00424 int numSiblings,
00425 bool* err)
00426 {
00427 if (key.isUnspecified())
00428 error("Chord::isSiblingFor(): key is unspecified!");
00429
00430 if (state != READY) {
00431 *err = true;
00432 return false;
00433 }
00434
00435 if (numSiblings > getMaxNumSiblings()) {
00436 opp_error("Chord::isSiblingFor(): numSiblings too big!");
00437 }
00438
00439 if (numSiblings == -1) numSiblings = getMaxNumSiblings();
00440
00441
00442 if ((predecessorNode.isUnspecified()) && (node == thisNode)) {
00443 if (successorList->isEmpty() || (node.getKey() == key)) {
00444 *err = false;
00445 return true;
00446 } else {
00447 *err = true;
00448 return false;
00449 }
00450 }
00451
00452 if ((node == thisNode)
00453 && (key.isBetweenR(predecessorNode.getKey(), thisNode.getKey()))) {
00454
00455 *err = false;
00456 return true;
00457 }
00458
00459 NodeHandle prevNode = predecessorNode;
00460 NodeHandle curNode;
00461
00462 for (int i = -1; i < (int)successorList->getSize();
00463 i++, prevNode = curNode) {
00464
00465 if (i < 0) {
00466 curNode = thisNode;
00467 } else {
00468 curNode = successorList->getSuccessor(i);
00469 }
00470
00471 if (node == curNode) {
00472
00473 if (key.isBetweenR(prevNode.getKey(), curNode.getKey())) {
00474 if (numSiblings <= ((int)successorList->getSize() - i)) {
00475 *err = false;
00476 return true;
00477 } else {
00478 *err = true;
00479 return false;
00480 }
00481 } else {
00482
00483
00484 if (numSiblings <= 1) {
00485 *err = false;
00486 return false;
00487 } else {
00488
00489
00490 *err = true;
00491 return false;
00492 }
00493 }
00494 }
00495 }
00496
00497
00498 *err = true;
00499 return false;
00500 }
00501
00502 bool Chord::handleFailedNode(const TransportAddress& failed)
00503 {
00504 Enter_Method_Silent();
00505
00506 if (!predecessorNode.isUnspecified() && failed == predecessorNode)
00507 predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00508
00509
00510 TransportAddress oldSuccessor = successorList->getSuccessor();
00511
00512 if (successorList->handleFailedNode(failed))
00513 updateTooltip();
00514
00515 if (fingerTable != NULL)
00516 fingerTable->handleFailedNode(failed);
00517
00518
00519
00520
00521 if ((!predecessorNode.isUnspecified()) &&
00522 oldSuccessor == predecessorNode) {
00523 callUpdate(predecessorNode, false);
00524 predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00525 }
00526
00527 if (failed == oldSuccessor) {
00528
00529 if (memorizeFailedSuccessor) {
00530 failedSuccessor = oldSuccessor;
00531 }
00532 cancelEvent(stabilize_timer);
00533 scheduleAt(simTime(), stabilize_timer);
00534 }
00535
00536 if (state != READY) return true;
00537
00538 if (successorList->isEmpty()) {
00539
00540
00541 cancelEvent(stabilize_timer);
00542 cancelEvent(fixfingers_timer);
00543 }
00544
00545 return !(successorList->isEmpty());
00546 }
00547
00548 NodeVector* Chord::findNode(const OverlayKey& key,
00549 int numRedundantNodes,
00550 int numSiblings,
00551 BaseOverlayMessage* msg)
00552 {
00553 bool err;
00554 NodeVector* nextHop;
00555
00556 if (state != READY)
00557 return new NodeVector();
00558
00559 if (successorList->isEmpty() && !predecessorNode.isUnspecified()) {
00560 throw new cRuntimeError("Chord: Node is READY, has a "
00561 "predecessor but no successor!");
00562 join();
00563 return new NodeVector();
00564 }
00565
00566
00567 if (key.isUnspecified()) {
00568 nextHop = new NodeVector();
00569 nextHop->push_back(thisNode);
00570 }
00571
00572
00573 else if (isSiblingFor(thisNode, key, 1, &err)) {
00574 nextHop = new NodeVector();
00575 nextHop->push_back(thisNode);
00576 for (uint32_t i = 0; i < successorList->getSize(); i++) {
00577 nextHop->push_back(successorList->getSuccessor(i));
00578 }
00579 nextHop->downsizeTo(numSiblings);
00580 }
00581
00582
00583 else if (key.isBetweenR(thisNode.getKey(),
00584 successorList->getSuccessor().getKey())) {
00585 nextHop = new NodeVector();
00586 for (uint32_t i = 0; i < successorList->getSize(); i++) {
00587 nextHop->push_back(successorList->getSuccessor(i));
00588 }
00589 nextHop->downsizeTo(numRedundantNodes);
00590 }
00591
00592
00593 else {
00594 nextHop = closestPreceedingNode(key);
00595 nextHop->downsizeTo(numRedundantNodes);
00596 }
00597
00598 return nextHop;
00599 }
00600
00601
00602 NodeVector* Chord::closestPreceedingNode(const OverlayKey& key)
00603 {
00604 NodeHandle tempHandle = NodeHandle::UNSPECIFIED_NODE;
00605
00606
00607 for (int j = successorList->getSize() - 1; j >= 0; j--) {
00608
00609 if (successorList->getSuccessor(j).getKey().isBetweenR(thisNode.getKey(), key)) {
00610 tempHandle = successorList->getSuccessor(j);
00611 break;
00612 }
00613 }
00614
00615 if(tempHandle.isUnspecified()) {
00616 std::stringstream temp;
00617 temp << "Chord::closestPreceedingNode(): Successor list broken "
00618 << thisNode.getKey() << " " << key;
00619 throw cRuntimeError(temp.str().c_str());
00620 }
00621
00622 NodeVector* nextHop = NULL;
00623
00624 for (int i = fingerTable->getSize() - 1; i >= 0; i--) {
00625
00626 if (fingerTable->getFinger(i).getKey().isBetweenLR(tempHandle.getKey(), key)) {
00627 if(!extendedFingerTable) {
00628 nextHop = new NodeVector();
00629 nextHop->push_back(fingerTable->getFinger(i));
00630
00631 EV << "[Chord::closestPreceedingNode() @ " << thisNode.getAddress()
00632 << " (" << thisNode.getKey().toString(16) << ")]\n"
00633 << " ClosestPreceedingNode: node " << thisNode
00634 << " for key " << key << "\n"
00635 << " finger " << fingerTable->getFinger(i).getKey()
00636 << " better than \n"
00637 << " " << tempHandle.getKey()
00638 << endl;
00639 return nextHop;
00640 } else {
00641 return fingerTable->getFinger(i, key);
00642 }
00643 }
00644 }
00645
00646 nextHop = new NodeVector();
00647 EV << "[Chord::closestPreceedingNode() @ " << thisNode.getAddress()
00648 << " (" << thisNode.getKey().toString(16) << ")]\n"
00649 << " No finger found"
00650 << endl;
00651
00652
00653 for (int i = successorList->getSize() - 1; i >= 0
00654 && nextHop->size() <= numFingerCandidates ; i--) {
00655 if (successorList->getSuccessor(i).getKey().isBetween(thisNode.getKey(), key)) {
00656 nextHop->push_back(successorList->getSuccessor(i));
00657 }
00658 }
00659
00660 if (nextHop->size() != 0) {
00661 return nextHop;
00662 }
00663
00664
00665 if ((predecessorNode.isUnspecified()) &&
00666 (successorList->getSuccessor() == thisNode)) {
00667 nextHop->push_back(thisNode);
00668 return nextHop;
00669 }
00670
00671
00672 throw cRuntimeError("Error in Chord::closestPreceedingNode()!");
00673 return nextHop;
00674 }
00675
00676 void Chord::recordOverlaySentStats(BaseOverlayMessage* msg)
00677 {
00678 BaseOverlayMessage* innerMsg = msg;
00679 while (innerMsg->getType() != APPDATA &&
00680 innerMsg->getEncapsulatedMsg() != NULL) {
00681 innerMsg =
00682 static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedMsg());
00683 }
00684
00685 switch (innerMsg->getType()) {
00686 case OVERLAYSIGNALING: {
00687 ChordMessage* chordMsg = dynamic_cast<ChordMessage*>(innerMsg);
00688 switch(chordMsg->getCommand()) {
00689 case NEWSUCCESSORHINT:
00690 RECORD_STATS(newsuccessorhintCount++;
00691 newsuccessorhintBytesSent += msg->getByteLength());
00692 break;
00693 }
00694 break;
00695 }
00696
00697 case RPC: {
00698 if ((dynamic_cast<StabilizeCall*>(innerMsg) != NULL) ||
00699 (dynamic_cast<StabilizeResponse*>(innerMsg) != NULL)) {
00700 RECORD_STATS(stabilizeCount++; stabilizeBytesSent +=
00701 msg->getByteLength());
00702 } else if ((dynamic_cast<NotifyCall*>(innerMsg) != NULL) ||
00703 (dynamic_cast<NotifyResponse*>(innerMsg) != NULL)) {
00704 RECORD_STATS(notifyCount++; notifyBytesSent +=
00705 msg->getByteLength());
00706 } else if ((dynamic_cast<FixfingersCall*>(innerMsg) != NULL) ||
00707 (dynamic_cast<FixfingersResponse*>(innerMsg) != NULL)) {
00708 RECORD_STATS(fixfingersCount++; fixfingersBytesSent +=
00709 msg->getByteLength());
00710 } else if ((dynamic_cast<JoinCall*>(innerMsg) != NULL) ||
00711 (dynamic_cast<JoinResponse*>(innerMsg) != NULL)) {
00712 RECORD_STATS(joinCount++; joinBytesSent += msg->getByteLength());
00713 }
00714 break;
00715 }
00716
00717 case APPDATA:
00718 break;
00719
00720 default:
00721 throw cRuntimeError("Unknown message type!");
00722 }
00723 }
00724
00725
00726 void Chord::finishOverlay()
00727 {
00728
00729 bootstrapList->removeBootstrapNode(thisNode);
00730
00731 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00732 if (time < GlobalStatistics::MIN_MEASURED) return;
00733
00734 globalStatistics->addStdDev("Chord: Sent JOIN Messages/s",
00735 joinCount / time);
00736 globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Messages/s",
00737 newsuccessorhintCount / time);
00738 globalStatistics->addStdDev("Chord: Sent STABILIZE Messages/s",
00739 stabilizeCount / time);
00740 globalStatistics->addStdDev("Chord: Sent NOTIFY Messages/s",
00741 notifyCount / time);
00742 globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Messages/s",
00743 fixfingersCount / time);
00744 globalStatistics->addStdDev("Chord: Sent JOIN Bytes/s",
00745 joinBytesSent / time);
00746 globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Bytes/s",
00747 newsuccessorhintBytesSent / time);
00748 globalStatistics->addStdDev("Chord: Sent STABILIZE Bytes/s",
00749 stabilizeBytesSent / time);
00750 globalStatistics->addStdDev("Chord: Sent NOTIFY Bytes/s",
00751 notifyBytesSent / time);
00752 globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Bytes/s",
00753 fixfingersBytesSent / time);
00754 }
00755
00756
00757
00758 void Chord::handleJoinTimerExpired(cMessage* msg)
00759 {
00760
00761 if (state == READY)
00762 return;
00763
00764
00765 if (state != BOOTSTRAP)
00766 changeState(BOOTSTRAP);
00767
00768
00769 joinRetry--;
00770 if (joinRetry == 0) {
00771 joinRetry = par("joinRetry");
00772 changeState(BOOTSTRAP);
00773 return;
00774 }
00775
00776
00777 JoinCall* call = new JoinCall("JoinCall");
00778 call->setBitLength(JOINCALL_L(call));
00779
00780 RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
00781 defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
00782 SEMI_RECURSIVE_ROUTING : defaultRoutingType;
00783
00784 sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, thisNode.getKey(),
00785 call, NULL, routingType, joinDelay);
00786
00787
00788 cancelEvent(join_timer);
00789 scheduleAt(simTime() + joinDelay, msg);
00790 }
00791
00792
00793 void Chord::handleStabilizeTimerExpired(cMessage* msg)
00794 {
00795 if (state != READY)
00796 return;
00797
00798
00799 if ((checkPredecessorDelay == 0) &&
00800 (missingPredecessorStabRequests >= stabilizeRetry)) {
00801
00802
00803
00804 callUpdate(predecessorNode, false);
00805 predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00806 missingPredecessorStabRequests = 0;
00807 updateTooltip();
00808 }
00809
00810 if (!successorList->isEmpty()) {
00811
00812 StabilizeCall* call = new StabilizeCall("StabilizeCall");
00813 call->setBitLength(STABILIZECALL_L(call));
00814
00815 sendUdpRpcCall(successorList->getSuccessor(), call);
00816
00817 missingPredecessorStabRequests++;
00818 }
00819
00820
00821 if (mergeOptimizationL4) {
00822 OverlayKey offset;
00823 for (uint32_t nextFinger = 0; nextFinger < thisNode.getKey().getLength();
00824 nextFinger++) {
00825 offset = OverlayKey::pow2(nextFinger);
00826
00827
00828 if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
00829 if ((fingerTable->getFinger(nextFinger)).isUnspecified()) {
00830 continue;
00831 } else {
00832 pingNode(fingerTable->getFinger(nextFinger), -1, 0, NULL,
00833 NULL, NULL, nextFinger);
00834 }
00835 }
00836 }
00837 }
00838
00839
00840 cancelEvent(stabilize_timer);
00841 scheduleAt(simTime() + stabilizeDelay, msg);
00842 }
00843
00844
00845 void Chord::handleFixFingersTimerExpired(cMessage* msg)
00846 {
00847 if ((state != READY) || successorList->isEmpty())
00848 return;
00849
00850 OverlayKey offset, lookupKey;
00851 for (uint32_t nextFinger = 0; nextFinger < thisNode.getKey().getLength();
00852 nextFinger++) {
00853
00854 offset = OverlayKey::pow2(nextFinger);
00855 lookupKey = thisNode.getKey() + offset;
00856
00857
00858 if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
00859
00860 FixfingersCall* call = new FixfingersCall("FixfingersCall");
00861 call->setFinger(nextFinger);
00862 call->setBitLength(FIXFINGERSCALL_L(call));
00863
00864 sendRouteRpcCall(OVERLAY_COMP, lookupKey, call, NULL,
00865 DEFAULT_ROUTING, fixfingersDelay);
00866 } else {
00867
00868 fingerTable->removeFinger(nextFinger);
00869 }
00870 }
00871
00872
00873 cancelEvent(fixfingers_timer);
00874 scheduleAt(simTime() + fixfingersDelay, msg);
00875 }
00876
00877
00878 void Chord::handleNewSuccessorHint(ChordMessage* chordMsg)
00879 {
00880 NewSuccessorHintMessage* newSuccessorHintMsg =
00881 check_and_cast<NewSuccessorHintMessage*>(chordMsg);
00882
00883
00884 NodeHandle predecessor = newSuccessorHintMsg->getPreNode();
00885
00886
00887 if (predecessor.getKey().isBetween(thisNode.getKey(),
00888 successorList->getSuccessor().getKey())
00889 || (thisNode.getKey() == successorList->getSuccessor().getKey())) {
00890
00891 successorList->addSuccessor(predecessor);
00892 updateTooltip();
00893 }
00894
00895
00896
00897 if (mergeOptimizationL3) {
00898 if (successorList->getSuccessor() == predecessor) {
00899 StabilizeCall *call = new StabilizeCall("StabilizeCall");
00900 call->setBitLength(STABILIZECALL_L(call));
00901
00902 sendUdpRpcCall(predecessor, call);
00903 } else {
00904 if (successorList->getSuccessor() == newSuccessorHintMsg->
00905 getSrcNode()) {
00906
00907 StabilizeCall *call = new StabilizeCall("StabilizeCall");
00908 call->setBitLength(STABILIZECALL_L(call));
00909
00910 sendUdpRpcCall(predecessor, call);
00911 }
00912 }
00913 }
00914 }
00915
00916
00917 void Chord::rpcJoin(JoinCall* joinCall)
00918 {
00919 NodeHandle requestor = joinCall->getSrcNode();
00920
00921
00922 JoinResponse* joinResponse =
00923 new JoinResponse("JoinResponse");
00924
00925 int sucNum = successorList->getSize();
00926 joinResponse->setSucNum(sucNum);
00927 joinResponse->setSucNodeArraySize(sucNum);
00928
00929 for (int k = 0; k < sucNum; k++) {
00930 joinResponse->setSucNode(k, successorList->getSuccessor(k));
00931 }
00932
00933
00934 if (predecessorNode.isUnspecified() && successorList->isEmpty()) {
00935
00936 joinResponse->setPreNode(thisNode);
00937 } else {
00938 joinResponse->setPreNode(predecessorNode);
00939 }
00940
00941 joinResponse->setBitLength(JOINRESPONSE_L(joinResponse));
00942
00943 sendRpcResponse(joinCall, joinResponse);
00944
00945 if (aggressiveJoinMode) {
00946
00947
00948
00949
00950
00951
00952
00953
00954 if (!predecessorNode.isUnspecified()) {
00955 NewSuccessorHintMessage* newSuccessorHintMsg =
00956 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
00957 newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
00958
00959 newSuccessorHintMsg->setSrcNode(thisNode);
00960 newSuccessorHintMsg->setPreNode(requestor);
00961 newSuccessorHintMsg->
00962 setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
00963
00964 sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
00965 }
00966
00967 if (predecessorNode.isUnspecified() || (predecessorNode != requestor)) {
00968
00969 if (!predecessorNode.isUnspecified()) {
00970 callUpdate(predecessorNode, false);
00971 }
00972 callUpdate(requestor, true);
00973
00974
00975 predecessorNode = requestor;
00976 }
00977 }
00978
00979
00980 if (successorList->isEmpty())
00981 successorList->addSuccessor(requestor);
00982
00983 updateTooltip();
00984 }
00985
00986 void Chord::handleRpcJoinResponse(JoinResponse* joinResponse)
00987 {
00988
00989 int sucNum = successorListSize - 1;
00990
00991 if (joinResponse->getSucNum() < successorListSize - 1) {
00992 sucNum = joinResponse->getSucNum();
00993 }
00994
00995
00996 for (int k = 0; k < sucNum; k++) {
00997 NodeHandle successor = joinResponse->getSucNode(k);
00998 successorList->addSuccessor(successor);
00999 }
01000
01001
01002 successorList->addSuccessor(joinResponse->getSrcNode());
01003
01004
01005
01006 if (aggressiveJoinMode) {
01007
01008
01009 if (!joinResponse->getPreNode().isUnspecified()) {
01010 if (!predecessorNode.isUnspecified()) {
01011
01012
01013
01014 if (mergeOptimizationL2) {
01015 NewSuccessorHintMessage* newSuccessorHintMsg =
01016 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01017 newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01018 newSuccessorHintMsg->setSrcNode(thisNode);
01019 newSuccessorHintMsg->setPreNode(joinResponse->getPreNode());
01020 newSuccessorHintMsg->
01021 setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01022
01023 sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
01024 }
01025 }
01026
01027 if (!predecessorNode.isUnspecified()
01028 && !joinResponse->getPreNode().isUnspecified()
01029 && predecessorNode != joinResponse->getPreNode()) {
01030 callUpdate(predecessorNode, false);
01031 }
01032 predecessorNode = joinResponse->getPreNode();
01033 callUpdate(predecessorNode, true);
01034 }
01035 }
01036
01037 updateTooltip();
01038
01039 changeState(READY);
01040
01041
01042 cancelEvent(stabilize_timer);
01043 scheduleAt(simTime(), stabilize_timer);
01044
01045
01046 cancelEvent(fixfingers_timer);
01047 scheduleAt(simTime(), fixfingers_timer);
01048 }
01049
01050
01051 void Chord::rpcStabilize(StabilizeCall* call)
01052 {
01053
01054 if (!predecessorNode.isUnspecified() &&
01055 call->getSrcNode() == predecessorNode) {
01056 missingPredecessorStabRequests = 0;
01057 }
01058
01059
01060 StabilizeResponse* stabilizeResponse =
01061 new StabilizeResponse("StabilizeResponse");
01062 stabilizeResponse->setPreNode(predecessorNode);
01063 stabilizeResponse->setBitLength(STABILIZERESPONSE_L(stabilizeResponse));
01064
01065 sendRpcResponse(call, stabilizeResponse);
01066 }
01067
01068 void Chord::handleRpcStabilizeResponse(StabilizeResponse* stabilizeResponse)
01069 {
01070 if (state != READY) {
01071 return;
01072 }
01073
01074
01075 const NodeHandle& predecessor = stabilizeResponse->getPreNode();
01076
01077
01078 if ((successorList->isEmpty() ||
01079 predecessor.getKey().isBetween(thisNode.getKey(),
01080 successorList->getSuccessor().getKey())) &&
01081 (failedSuccessor.isUnspecified() || failedSuccessor != predecessor)) {
01082 if (successorList->isEmpty() && predecessor.isUnspecified()) {
01083
01084
01085 successorList->addSuccessor(stabilizeResponse->getSrcNode());
01086 } else {
01087
01088 successorList->addSuccessor(predecessor);
01089 }
01090 updateTooltip();
01091 }
01092
01093
01094 NotifyCall* notifyCall = new NotifyCall("NotifyCall");
01095 notifyCall->setBitLength(NOTIFYCALL_L(notifyCall));
01096 notifyCall->setFailed(failedSuccessor);
01097 failedSuccessor = TransportAddress::UNSPECIFIED_NODE;
01098
01099 sendUdpRpcCall(successorList->getSuccessor(), notifyCall);
01100 }
01101
01102 void Chord::rpcNotify(NotifyCall* call)
01103 {
01104
01105 if (!predecessorNode.isUnspecified() &&
01106 call->getSrcNode() == predecessorNode) {
01107 missingPredecessorStabRequests = 0;
01108 }
01109
01110 bool newPredecessorSet = false;
01111
01112 NodeHandle newPredecessor = call->getSrcNode();
01113
01114
01115 if (predecessorNode.isUnspecified() ||
01116 newPredecessor.getKey().isBetween(predecessorNode.getKey(), thisNode.getKey()) ||
01117 (!call->getFailed().isUnspecified() &&
01118 call->getFailed() == predecessorNode)) {
01119
01120 if ((predecessorNode.isUnspecified()) ||
01121 (newPredecessor != predecessorNode)) {
01122
01123 if (!predecessorNode.isUnspecified()) {
01124 callUpdate(predecessorNode, false);
01125 }
01126 callUpdate(newPredecessor, true);
01127
01128
01129 if (mergeOptimizationL1) {
01130 if (!predecessorNode.isUnspecified()) {
01131 NewSuccessorHintMessage *newSuccessorHintMsg =
01132 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01133 newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01134
01135 newSuccessorHintMsg->setSrcNode(thisNode);
01136 newSuccessorHintMsg->setPreNode(newPredecessor);
01137 newSuccessorHintMsg->
01138 setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01139 sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
01140 }
01141 }
01142
01143 predecessorNode = newPredecessor;
01144 if (successorList->isEmpty()) {
01145 successorList->addSuccessor(newPredecessor);
01146 }
01147 updateTooltip();
01148
01149 newPredecessorSet = true;
01150 }
01151 }
01152
01153
01154 NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
01155
01156 int sucNum = successorList->getSize();
01157 notifyResponse->setSucNum(sucNum);
01158 notifyResponse->setSucNodeArraySize(sucNum);
01159
01160
01161
01162 if (mergeOptimizationL3) {
01163 if (!newPredecessorSet && (predecessorNode != newPredecessor)) {
01164
01165 notifyResponse->setPreNode(predecessorNode);
01166 notifyResponse->setPreNodeSet(false);
01167 } else {
01168 notifyResponse->setPreNodeSet(true);
01169 }
01170 }
01171
01172 for (int k = 0; k < sucNum; k++) {
01173 notifyResponse->setSucNode(k, successorList->getSuccessor(k));
01174 }
01175
01176 notifyResponse->setBitLength(NOTIFYRESPONSE_L(notifyResponse));
01177
01178 sendRpcResponse(call, notifyResponse);
01179 }
01180
01181
01182 void Chord::handleRpcNotifyResponse(NotifyResponse* notifyResponse)
01183 {
01184 if (state != READY) {
01185 return;
01186 }
01187
01188 if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
01189 EV << "[Chord::handleRpcNotifyResponse() @ " << thisNode.getAddress()
01190 << " (" << thisNode.getKey().toString(16) << ")]\n"
01191 << " The srcNode of the received NotifyResponse is not our "
01192 << " current successor"
01193 << endl;
01194 return;
01195 }
01196
01197
01198
01199 if (mergeOptimizationL3) {
01200 if (!notifyResponse->getPreNodeSet()) {
01201 StabilizeCall *call = new StabilizeCall("StabilizeCall");
01202 call->setBitLength(STABILIZECALL_L(call));
01203
01204 successorList->addSuccessor(notifyResponse->getPreNode());
01205 if (successorList->getSuccessor() == notifyResponse->getPreNode())
01206 sendUdpRpcCall(notifyResponse->getPreNode(), call);
01207 return;
01208 }
01209 }
01210
01211
01212 successorList->updateList(notifyResponse);
01213
01214 updateTooltip();
01215 }
01216
01217
01218 void Chord::rpcFixfingers(FixfingersCall* call)
01219 {
01220 FixfingersResponse* fixfingersResponse =
01221 new FixfingersResponse("FixfingersResponse");
01222
01223 fixfingersResponse->setSucNodeArraySize(1);
01224 fixfingersResponse->setSucNode(0, thisNode);
01225
01226 if (extendedFingerTable) {
01227 fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
01228 < numFingerCandidates + 1)
01229 ? successorList->getSize() + 1
01230 : numFingerCandidates + 1));
01231 for (unsigned int i = 0;
01232 i < (((successorList->getSize()) < numFingerCandidates)
01233 ? (successorList->getSize()) : numFingerCandidates); i++) {
01234
01235 assert(!successorList->getSuccessor(i).isUnspecified());
01236 fixfingersResponse->setSucNode(i + 1,
01237 successorList->getSuccessor(i));
01238 }
01239 }
01240 fixfingersResponse->setFinger(call->getFinger());
01241 fixfingersResponse->setBitLength(FIXFINGERSRESPONSE_L(fixfingersResponse));
01242
01243 sendRpcResponse(call, fixfingersResponse);
01244 }
01245
01246
01247 void Chord::handleRpcFixfingersResponse(FixfingersResponse* fixfingersResponse,
01248 double rtt)
01249 {
01250
01251
01252
01253
01254
01255
01256
01257
01258 if (!extendedFingerTable) {
01259 fingerTable->setFinger(fixfingersResponse->getFinger(),
01260 fixfingersResponse->getSucNode(0));
01261 } else {
01262 Successors successors;
01263 for (unsigned int i = 0; i < fixfingersResponse->getSucNodeArraySize();
01264 i++) {
01265 if (fixfingersResponse->getSucNode(i).isUnspecified())
01266 continue;
01267 if (fixfingersResponse->getSucNode(i) == thisNode)
01268 break;
01269 successors.insert(std::make_pair(MAXTIME,
01270 fixfingersResponse->getSucNode(i)));
01271 }
01272
01273 if (successors.size() == 0) {
01274 return;
01275 }
01276
01277 fingerTable->setFinger(fixfingersResponse->getFinger(), successors);
01278
01279 #if 0
01280 if (proximityRouting || globalParameters->getTopologyAdaptation()) {
01281 #else
01282 if (proximityRouting) {
01283 #endif
01284 for (unsigned int i = 0;
01285 i < fixfingersResponse->getSucNodeArraySize();
01286 i++) {
01287 if (fixfingersResponse->getSucNode(i).isUnspecified())
01288 continue;
01289 if (fixfingersResponse->getSucNode(i) == thisNode)
01290 break;
01291
01292
01293
01294 Prox prox =
01295 neighborCache->getProx(fixfingersResponse->getSucNode(i),
01296 NEIGHBORCACHE_DEFAULT,
01297 fixfingersResponse->getFinger(),
01298 this, NULL);
01299 if (prox == Prox::PROX_TIMEOUT) {
01300 fingerTable->removeFinger(fixfingersResponse->getFinger());
01301 } else if (prox != Prox::PROX_UNKNOWN &&
01302 prox != Prox::PROX_SELF) {
01303 fingerTable->updateFinger(fixfingersResponse->getFinger(),
01304 fixfingersResponse->getSucNode(i),
01305 prox.proximity);
01306 }
01307 }
01308 }
01309 }
01310 }
01311
01312 void Chord::proxCallback(const TransportAddress &node, int rpcId,
01313 cPolymorphic *contextPointer, Prox prox)
01314 {
01315 if (prox == Prox::PROX_TIMEOUT) {
01316 handleFailedNode(node);
01317 return;
01318 }
01319
01320 fingerTable->updateFinger(rpcId, (NodeHandle&)node, prox.proximity);
01321 }
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 void Chord::pingTimeout(PingCall* pingCall,
01337 const TransportAddress& dest,
01338 cPolymorphic* context, int rpcId)
01339 {
01340 EV << "[Chord::pingTimeout() @ " << thisNode.getAddress()
01341 << " (" << thisNode.getKey().toString(16) << ")]\n"
01342 << " Ping RPC timeout: id=" << rpcId << endl;
01343
01344 handleFailedNode(dest);
01345 }
01346
01347 void Chord::findFriendModules()
01348 {
01349 fingerTable = check_and_cast<ChordFingerTable*>
01350 (getParentModule()->getSubmodule("fingerTable"));
01351
01352 successorList = check_and_cast<ChordSuccessorList*>
01353 (getParentModule()->getSubmodule("successorList"));
01354 }
01355
01356
01357 void Chord::initializeFriendModules()
01358 {
01359
01360 fingerTable->initializeTable(thisNode.getKey().getLength(), thisNode, this);
01361
01362
01363 successorList->initializeList(par("successorListSize"), thisNode, this);
01364 }
01365
01366
01367 void Chord::updateTooltip()
01368 {
01369 if (ev.isGUI()) {
01370 std::stringstream ttString;
01371
01372
01373 ttString << predecessorNode << endl << thisNode << endl
01374 << successorList->getSuccessor();
01375
01376 getParentModule()->getParentModule()->getDisplayString().
01377 setTagArg("tt", 0, ttString.str().c_str());
01378 getParentModule()->getDisplayString().
01379 setTagArg("tt", 0, ttString.str().c_str());
01380 getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
01381
01382
01383 showOverlayNeighborArrow(successorList->getSuccessor(), true,
01384 "m=m,50,0,50,0;ls=red,1");
01385 showOverlayNeighborArrow(predecessorNode, false,
01386 "m=m,50,100,50,100;ls=green,1");
01387 }
01388 }
01389
01390 OverlayKey Chord::distance(const OverlayKey& x, const OverlayKey& y) const
01391 {
01392 return KeyUniRingMetric().distance(x, y);
01393 }
01394
01395 };