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 predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00524 callUpdate(predecessorNode, false);
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->getEncapsulatedPacket() != NULL) {
00681 innerMsg =
00682 static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedPacket());
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 predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00805 missingPredecessorStabRequests = 0;
00806 updateTooltip();
00807 callUpdate(predecessorNode, false);
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 NodeHandle oldPredecessor = predecessorNode;
00970 predecessorNode = requestor;
00971
00972
00973 if (!oldPredecessor.isUnspecified()) {
00974 callUpdate(oldPredecessor, false);
00975 }
00976 callUpdate(predecessorNode, true);
00977
00978 }
00979 }
00980
00981
00982 if (successorList->isEmpty())
00983 successorList->addSuccessor(requestor);
00984
00985 updateTooltip();
00986 }
00987
00988 void Chord::handleRpcJoinResponse(JoinResponse* joinResponse)
00989 {
00990
00991 int sucNum = successorListSize - 1;
00992
00993 if (joinResponse->getSucNum() < successorListSize - 1) {
00994 sucNum = joinResponse->getSucNum();
00995 }
00996
00997
00998 for (int k = 0; k < sucNum; k++) {
00999 NodeHandle successor = joinResponse->getSucNode(k);
01000 successorList->addSuccessor(successor);
01001 }
01002
01003
01004 successorList->addSuccessor(joinResponse->getSrcNode());
01005
01006
01007
01008 if (aggressiveJoinMode) {
01009
01010
01011 if (!joinResponse->getPreNode().isUnspecified()) {
01012 if (!predecessorNode.isUnspecified()) {
01013
01014
01015
01016 if (mergeOptimizationL2) {
01017 NewSuccessorHintMessage* newSuccessorHintMsg =
01018 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01019 newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01020 newSuccessorHintMsg->setSrcNode(thisNode);
01021 newSuccessorHintMsg->setPreNode(joinResponse->getPreNode());
01022 newSuccessorHintMsg->
01023 setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01024
01025 sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
01026 }
01027 }
01028
01029 NodeHandle oldPredecessor = predecessorNode;
01030 predecessorNode = joinResponse->getPreNode();
01031
01032 if (!oldPredecessor.isUnspecified()
01033 && !joinResponse->getPreNode().isUnspecified()
01034 && oldPredecessor != joinResponse->getPreNode()) {
01035 callUpdate(oldPredecessor, false);
01036 }
01037 callUpdate(predecessorNode, true);
01038 }
01039 }
01040
01041 updateTooltip();
01042
01043 changeState(READY);
01044
01045
01046 cancelEvent(stabilize_timer);
01047 scheduleAt(simTime(), stabilize_timer);
01048
01049
01050 cancelEvent(fixfingers_timer);
01051 scheduleAt(simTime(), fixfingers_timer);
01052 }
01053
01054
01055 void Chord::rpcStabilize(StabilizeCall* call)
01056 {
01057
01058 if (!predecessorNode.isUnspecified() &&
01059 call->getSrcNode() == predecessorNode) {
01060 missingPredecessorStabRequests = 0;
01061 }
01062
01063
01064 StabilizeResponse* stabilizeResponse =
01065 new StabilizeResponse("StabilizeResponse");
01066 stabilizeResponse->setPreNode(predecessorNode);
01067 stabilizeResponse->setBitLength(STABILIZERESPONSE_L(stabilizeResponse));
01068
01069 sendRpcResponse(call, stabilizeResponse);
01070 }
01071
01072 void Chord::handleRpcStabilizeResponse(StabilizeResponse* stabilizeResponse)
01073 {
01074 if (state != READY) {
01075 return;
01076 }
01077
01078
01079 const NodeHandle& predecessor = stabilizeResponse->getPreNode();
01080
01081
01082 if ((successorList->isEmpty() ||
01083 predecessor.getKey().isBetween(thisNode.getKey(),
01084 successorList->getSuccessor().getKey())) &&
01085 (failedSuccessor.isUnspecified() || failedSuccessor != predecessor)) {
01086 if (successorList->isEmpty() && predecessor.isUnspecified()) {
01087
01088
01089 successorList->addSuccessor(stabilizeResponse->getSrcNode());
01090 } else {
01091
01092 successorList->addSuccessor(predecessor);
01093 }
01094 updateTooltip();
01095 }
01096
01097
01098 NotifyCall* notifyCall = new NotifyCall("NotifyCall");
01099 notifyCall->setBitLength(NOTIFYCALL_L(notifyCall));
01100 notifyCall->setFailed(failedSuccessor);
01101 failedSuccessor = TransportAddress::UNSPECIFIED_NODE;
01102
01103 sendUdpRpcCall(successorList->getSuccessor(), notifyCall);
01104 }
01105
01106 void Chord::rpcNotify(NotifyCall* call)
01107 {
01108
01109 if (!predecessorNode.isUnspecified() &&
01110 call->getSrcNode() == predecessorNode) {
01111 missingPredecessorStabRequests = 0;
01112 }
01113
01114 bool newPredecessorSet = false;
01115
01116 NodeHandle newPredecessor = call->getSrcNode();
01117
01118
01119 if (predecessorNode.isUnspecified() ||
01120 newPredecessor.getKey().isBetween(predecessorNode.getKey(), thisNode.getKey()) ||
01121 (!call->getFailed().isUnspecified() &&
01122 call->getFailed() == predecessorNode)) {
01123
01124 if ((predecessorNode.isUnspecified()) ||
01125 (newPredecessor != predecessorNode)) {
01126
01127
01128 NodeHandle oldPredecessor = predecessorNode;
01129 predecessorNode = newPredecessor;
01130
01131 if (successorList->isEmpty()) {
01132 successorList->addSuccessor(newPredecessor);
01133 }
01134
01135 newPredecessorSet = true;
01136 updateTooltip();
01137
01138
01139 if (!oldPredecessor.isUnspecified()) {
01140 callUpdate(oldPredecessor, false);
01141 }
01142 callUpdate(predecessorNode, true);
01143
01144
01145 if (mergeOptimizationL1) {
01146 if (!oldPredecessor.isUnspecified()) {
01147 NewSuccessorHintMessage *newSuccessorHintMsg =
01148 new NewSuccessorHintMessage("NEWSUCCESSORHINT");
01149 newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
01150
01151 newSuccessorHintMsg->setSrcNode(thisNode);
01152 newSuccessorHintMsg->setPreNode(predecessorNode);
01153 newSuccessorHintMsg->
01154 setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
01155 sendMessageToUDP(oldPredecessor, newSuccessorHintMsg);
01156 }
01157 }
01158
01159
01160 }
01161 }
01162
01163
01164 NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
01165
01166 int sucNum = successorList->getSize();
01167 notifyResponse->setSucNum(sucNum);
01168 notifyResponse->setSucNodeArraySize(sucNum);
01169
01170
01171
01172 if (mergeOptimizationL3) {
01173 if (!newPredecessorSet && (predecessorNode != newPredecessor)) {
01174
01175 notifyResponse->setPreNode(predecessorNode);
01176 notifyResponse->setPreNodeSet(false);
01177 } else {
01178 notifyResponse->setPreNodeSet(true);
01179 }
01180 }
01181
01182 for (int k = 0; k < sucNum; k++) {
01183 notifyResponse->setSucNode(k, successorList->getSuccessor(k));
01184 }
01185
01186 notifyResponse->setBitLength(NOTIFYRESPONSE_L(notifyResponse));
01187
01188 sendRpcResponse(call, notifyResponse);
01189 }
01190
01191
01192 void Chord::handleRpcNotifyResponse(NotifyResponse* notifyResponse)
01193 {
01194 if (state != READY) {
01195 return;
01196 }
01197
01198 if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
01199 EV << "[Chord::handleRpcNotifyResponse() @ " << thisNode.getAddress()
01200 << " (" << thisNode.getKey().toString(16) << ")]\n"
01201 << " The srcNode of the received NotifyResponse is not our "
01202 << " current successor"
01203 << endl;
01204 return;
01205 }
01206
01207
01208
01209 if (mergeOptimizationL3) {
01210 if (!notifyResponse->getPreNodeSet()) {
01211 StabilizeCall *call = new StabilizeCall("StabilizeCall");
01212 call->setBitLength(STABILIZECALL_L(call));
01213
01214 successorList->addSuccessor(notifyResponse->getPreNode());
01215 if (successorList->getSuccessor() == notifyResponse->getPreNode())
01216 sendUdpRpcCall(notifyResponse->getPreNode(), call);
01217 return;
01218 }
01219 }
01220
01221
01222 successorList->updateList(notifyResponse);
01223
01224 updateTooltip();
01225 }
01226
01227
01228 void Chord::rpcFixfingers(FixfingersCall* call)
01229 {
01230 FixfingersResponse* fixfingersResponse =
01231 new FixfingersResponse("FixfingersResponse");
01232
01233 fixfingersResponse->setSucNodeArraySize(1);
01234 fixfingersResponse->setSucNode(0, thisNode);
01235
01236 if (extendedFingerTable) {
01237 fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
01238 < numFingerCandidates + 1)
01239 ? successorList->getSize() + 1
01240 : numFingerCandidates + 1));
01241 for (unsigned int i = 0;
01242 i < (((successorList->getSize()) < numFingerCandidates)
01243 ? (successorList->getSize()) : numFingerCandidates); i++) {
01244
01245 assert(!successorList->getSuccessor(i).isUnspecified());
01246 fixfingersResponse->setSucNode(i + 1,
01247 successorList->getSuccessor(i));
01248 }
01249 }
01250 fixfingersResponse->setFinger(call->getFinger());
01251 fixfingersResponse->setBitLength(FIXFINGERSRESPONSE_L(fixfingersResponse));
01252
01253 sendRpcResponse(call, fixfingersResponse);
01254 }
01255
01256
01257 void Chord::handleRpcFixfingersResponse(FixfingersResponse* fixfingersResponse,
01258 double rtt)
01259 {
01260
01261
01262
01263
01264
01265
01266
01267
01268 if (!extendedFingerTable) {
01269 fingerTable->setFinger(fixfingersResponse->getFinger(),
01270 fixfingersResponse->getSucNode(0));
01271 } else {
01272 Successors successors;
01273 for (unsigned int i = 0; i < fixfingersResponse->getSucNodeArraySize();
01274 i++) {
01275 if (fixfingersResponse->getSucNode(i).isUnspecified())
01276 continue;
01277 if (fixfingersResponse->getSucNode(i) == thisNode)
01278 break;
01279 successors.insert(std::make_pair(MAXTIME,
01280 fixfingersResponse->getSucNode(i)));
01281 }
01282
01283 if (successors.size() == 0) {
01284 return;
01285 }
01286
01287 fingerTable->setFinger(fixfingersResponse->getFinger(), successors);
01288
01289 #if 0
01290 if (proximityRouting || globalParameters->getTopologyAdaptation()) {
01291 #else
01292 if (proximityRouting) {
01293 #endif
01294 for (unsigned int i = 0;
01295 i < fixfingersResponse->getSucNodeArraySize();
01296 i++) {
01297 if (fixfingersResponse->getSucNode(i).isUnspecified())
01298 continue;
01299 if (fixfingersResponse->getSucNode(i) == thisNode)
01300 break;
01301
01302
01303
01304 Prox prox =
01305 neighborCache->getProx(fixfingersResponse->getSucNode(i),
01306 NEIGHBORCACHE_DEFAULT,
01307 fixfingersResponse->getFinger(),
01308 this, NULL);
01309 if (prox == Prox::PROX_TIMEOUT) {
01310 fingerTable->removeFinger(fixfingersResponse->getFinger());
01311 } else if (prox != Prox::PROX_UNKNOWN &&
01312 prox != Prox::PROX_SELF) {
01313 fingerTable->updateFinger(fixfingersResponse->getFinger(),
01314 fixfingersResponse->getSucNode(i),
01315 prox.proximity);
01316 }
01317 }
01318 }
01319 }
01320 }
01321
01322 void Chord::proxCallback(const TransportAddress &node, int rpcId,
01323 cPolymorphic *contextPointer, Prox prox)
01324 {
01325 if (prox == Prox::PROX_TIMEOUT) {
01326
01327 handleFailedNode(node);
01328 return;
01329 }
01330
01331 fingerTable->updateFinger(rpcId, (NodeHandle&)node, prox.proximity);
01332 }
01333
01334 void Chord::pingResponse(PingResponse* pingResponse, cPolymorphic* context,
01335 int rpcId, simtime_t rtt)
01336 {
01337 EV << "[Chord::pingResponse() @ " << thisNode.getAddress()
01338 << " (" << thisNode.getKey().toString(16) << ")]\n"
01339 << " Received a Ping RPC Response: id=" << rpcId << "\n"
01340 << " msg=" << *pingResponse << " rtt=" << rtt
01341 << endl;
01342
01343 if (rpcId != -1)
01344 fingerTable->updateFinger(rpcId, pingResponse->getSrcNode(), rtt);
01345 }
01346
01347 void Chord::pingTimeout(PingCall* pingCall,
01348 const TransportAddress& dest,
01349 cPolymorphic* context, int rpcId)
01350 {
01351 EV << "[Chord::pingTimeout() @ " << thisNode.getAddress()
01352 << " (" << thisNode.getKey().toString(16) << ")]\n"
01353 << " Ping RPC timeout: id=" << rpcId << endl;
01354
01355
01356 handleFailedNode(dest);
01357 }
01358
01359 void Chord::findFriendModules()
01360 {
01361 fingerTable = check_and_cast<ChordFingerTable*>
01362 (getParentModule()->getSubmodule("fingerTable"));
01363
01364 successorList = check_and_cast<ChordSuccessorList*>
01365 (getParentModule()->getSubmodule("successorList"));
01366 }
01367
01368
01369 void Chord::initializeFriendModules()
01370 {
01371
01372 fingerTable->initializeTable(thisNode.getKey().getLength(), thisNode, this);
01373
01374
01375 successorList->initializeList(par("successorListSize"), thisNode, this);
01376 }
01377
01378
01379 void Chord::updateTooltip()
01380 {
01381 if (ev.isGUI()) {
01382 std::stringstream ttString;
01383
01384
01385 ttString << predecessorNode << endl << thisNode << endl
01386 << successorList->getSuccessor();
01387
01388 getParentModule()->getParentModule()->getDisplayString().
01389 setTagArg("tt", 0, ttString.str().c_str());
01390 getParentModule()->getDisplayString().
01391 setTagArg("tt", 0, ttString.str().c_str());
01392 getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
01393
01394
01395 showOverlayNeighborArrow(successorList->getSuccessor(), true,
01396 "m=m,50,0,50,0;ls=red,1");
01397 showOverlayNeighborArrow(predecessorNode, false,
01398 "m=m,50,100,50,100;ls=green,1");
01399 }
01400 }
01401
01402
01403 OverlayKey Chord::distance(const OverlayKey& x,
01404 const OverlayKey& y,
01405 bool useAlternative) const
01406 {
01407 return KeyUniRingMetric().distance(x, y);
01408 }
01409
01410 };