Chord.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     // because of IPAddressResolver, we need to wait until interfaces
00049     // are registered, address auto-assignment takes place etc.
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     // Chord provides KBR services
00059     kbr = true;
00060 
00061     // fetch some parameters
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     // merging optimizations
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     // statistics
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     // find friend modules
00100     findFriendModules();
00101 
00102     // add some watches
00103     WATCH(predecessorNode);
00104     WATCH(thisNode);
00105     WATCH(bootstrapNode);
00106     WATCH(joinRetry);
00107     WATCH(missingPredecessorStabRequests);
00108 
00109     // self-messages
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     // destroy self timer messages
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     // create a join call and sent to the bootstrap node.
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     // Defines tasks to be executed when a state change occurs.
00156     //
00157 
00158     switch (toState) {
00159     case INIT:
00160         state = INIT;
00161 
00162         setOverlayReady(false);
00163 
00164         // initialize predecessor pointer
00165         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00166 
00167         // initialize finger table and successor list
00168         initializeFriendModules();
00169 
00170         updateTooltip();
00171 
00172         // debug message
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         // initiate bootstrap process
00187         cancelEvent(join_timer);
00188         // workaround: prevent notificationBoard from taking
00189         // ownership of join_timer message
00190         take(join_timer);
00191         scheduleAt(simTime(), join_timer);
00192 
00193         // debug message
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         // find a new bootstrap node and enroll to the bootstrap list
00203         bootstrapNode = bootstrapList->getBootstrapNode();
00204 
00205         // is this the first node?
00206         if (bootstrapNode.isUnspecified()) {
00207             // create new cord ring
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         // initiate stabilization protocol
00221         cancelEvent(stabilize_timer);
00222         scheduleAt(simTime() + stabilizeDelay, stabilize_timer);
00223 
00224         // initiate finger repair protocol
00225         cancelEvent(fixfingers_timer);
00226         scheduleAt(simTime() + fixfingersDelay,
00227                    fixfingers_timer);
00228 
00229         // initiate predecessor check
00230         cancelEvent(checkPredecessor_timer);
00231         if (checkPredecessorDelay > 0) {
00232             scheduleAt(simTime() + checkPredecessorDelay,
00233                        checkPredecessor_timer);
00234         }
00235 
00236         // debug message
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     // catch JOIN timer
00252     if (msg == join_timer) {
00253         handleJoinTimerExpired(msg);
00254     }
00255     // catch STABILIZE timer
00256     else if (msg == stabilize_timer) {
00257         handleStabilizeTimerExpired(msg);
00258     }
00259     // catch FIX_FINGERS timer
00260     else if (msg == fixfingers_timer) {
00261         handleFixFingersTimerExpired(msg);
00262     }
00263     // catch CHECK_PREDECESSOR timer
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     // unknown self message
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     // delegate messages
00305     RPC_SWITCH_START( msg )
00306     // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
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     // set default number of siblings to consider
00439     if (numSiblings == -1) numSiblings = getMaxNumSiblings();
00440 
00441     // if this is the first and only node on the ring, it is responsible
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             // is the message destined for curNode?
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                 // the key doesn't directly belong to this node, but
00483                 // the node could be a sibling for this key
00484                 if (numSiblings <= 1) {
00485                     *err = false;
00486                     return false;
00487                 } else {
00488                     // In Chord we don't know if we belong to the
00489                     // replicaSet of one of our predecessors
00490                     *err = true;
00491                     return false;
00492                 }
00493             }
00494         }
00495     }
00496 
00497     // node is not in our neighborSet
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     //TODO const reference -> trying to compare unspec NH
00510     TransportAddress oldSuccessor = successorList->getSuccessor();
00511 
00512     if (successorList->handleFailedNode(failed))
00513         updateTooltip();
00514     // check pointer for koorde
00515     if (fingerTable != NULL)
00516         fingerTable->handleFailedNode(failed);
00517 
00518     // if we had a ring consisting of 2 nodes and our successor seems
00519     // to be dead. Remove also predecessor because the successor
00520     // and predecessor are the same node
00521     if ((!predecessorNode.isUnspecified()) &&
00522         oldSuccessor == predecessorNode) {
00523         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00524         callUpdate(predecessorNode, false);
00525     }
00526 
00527     if (failed == oldSuccessor) {
00528         // schedule next stabilization process
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         // lost our last successor - cancel periodic stabilize tasks
00540         // and wait for rejoin
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     // if key is unspecified, the message is for this node
00567     if (key.isUnspecified()) {
00568         nextHop = new NodeVector();
00569         nextHop->push_back(thisNode);
00570     }
00571 
00572     // the message is destined for this node
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     // the message destined for our successor
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     // find next hop with finger table and/or successor list
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     // find the closest preceding node in the successor list
00607     for (int j = successorList->getSize() - 1; j >= 0; j--) {
00608         // return a predecessor of the key, unless we know a node with an Id = destKey
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         // return a predecessor of the key, unless we know a node with an Id = destKey
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     // if no finger is found lookup the rest of the successor list
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     // if this is the first and only node on the ring, it is responsible
00665     if ((predecessorNode.isUnspecified()) &&
00666         (successorList->getSuccessor() == thisNode)) {
00667         nextHop->push_back(thisNode);
00668         return nextHop;
00669     }
00670 
00671     // if there is still no node found throw an exception
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     // remove this node from the bootstrap list
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     // only process timer, if node is not bootstrapped yet
00761     if (state == READY)
00762         return;
00763 
00764     // enter state BOOTSTRAP
00765     if (state != BOOTSTRAP)
00766         changeState(BOOTSTRAP);
00767 
00768     // change bootstrap node from time to time
00769     joinRetry--;
00770     if (joinRetry == 0) {
00771         joinRetry = par("joinRetry");
00772         changeState(BOOTSTRAP);
00773         return;
00774     }
00775 
00776     // call JOIN RPC
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     // schedule next bootstrap process in the case this one fails
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     // alternative predecessor check
00799     if ((checkPredecessorDelay == 0) &&
00800         (missingPredecessorStabRequests >= stabilizeRetry)) {
00801         // predecessor node seems to be dead
00802         // remove it from the predecessor / successor lists
00803         //successorList->removeSuccessor(predecessorNode);
00804         predecessorNode = NodeHandle::UNSPECIFIED_NODE;
00805         missingPredecessorStabRequests = 0;
00806         updateTooltip();
00807         callUpdate(predecessorNode, false);
00808     }
00809 
00810     if (!successorList->isEmpty()) {
00811         // call STABILIZE RPC
00812         StabilizeCall* call = new StabilizeCall("StabilizeCall");
00813         call->setBitLength(STABILIZECALL_L(call));
00814 
00815         sendUdpRpcCall(successorList->getSuccessor(), call);
00816 
00817         missingPredecessorStabRequests++;
00818     }
00819 
00820     // check if fingers are still alive and remove unreachable finger nodes
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             // send message only for non-trivial fingers
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     // schedule next stabilization process
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         // calculate "n + 2^(i - 1)"
00854         offset = OverlayKey::pow2(nextFinger);
00855         lookupKey = thisNode.getKey() + offset;
00856 
00857         // send message only for non-trivial fingers
00858         if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
00859             // call FIXFINGER RPC
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             // delete trivial fingers (points to the successor node)
00868             fingerTable->removeFinger(nextFinger);
00869         }
00870     }
00871 
00872     // schedule next finger repair process
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     // fetch the successor's predecessor
00884     NodeHandle predecessor = newSuccessorHintMsg->getPreNode();
00885 
00886     // is the successor's predecessor a new successor for this node?
00887     if (predecessor.getKey().isBetween(thisNode.getKey(),
00888                                   successorList->getSuccessor().getKey())
00889         || (thisNode.getKey() == successorList->getSuccessor().getKey())) {
00890         // add the successor's predecessor to the successor list
00891         successorList->addSuccessor(predecessor);
00892         updateTooltip();
00893     }
00894 
00895     // if the successor node reports a new successor, put it into the
00896     // successor list and start stabilizing
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     // compile successor list
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     // sent our predecessor as hint to the joining node
00934     if (predecessorNode.isUnspecified() && successorList->isEmpty()) {
00935         // we are the only node in the ring
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         // aggressiveJoinMode differs from standard join operations:
00947         // 1. set our predecessor pointer to the joining node
00948         // 2. send our old predecessor as hint in JoinResponse msgs
00949         // 3. send a NEWSUCCESSORHINT to our old predecessor to update
00950         //    its successor pointer
00951 
00952         // send NEWSUCCESSORHINT to our old predecessor
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             // the requestor is our new predecessor
00969             NodeHandle oldPredecessor = predecessorNode;
00970             predecessorNode = requestor;
00971 
00972             // send update to application if we've got a new predecessor
00973             if (!oldPredecessor.isUnspecified()) {
00974                 callUpdate(oldPredecessor, false);
00975             }
00976             callUpdate(predecessorNode, true);
00977 
00978         }
00979     }
00980 
00981     // if we don't have a successor, the requestor is also our new successor
00982     if (successorList->isEmpty())
00983         successorList->addSuccessor(requestor);
00984 
00985     updateTooltip();
00986 }
00987 
00988 void Chord::handleRpcJoinResponse(JoinResponse* joinResponse)
00989 {
00990     // determine the numer of successor nodes to add
00991     int sucNum = successorListSize - 1;
00992 
00993     if (joinResponse->getSucNum() < successorListSize - 1) {
00994         sucNum = joinResponse->getSucNum();
00995     }
00996 
00997     // add successor getNode(s)
00998     for (int k = 0; k < sucNum; k++) {
00999         NodeHandle successor = joinResponse->getSucNode(k);
01000         successorList->addSuccessor(successor);
01001     }
01002 
01003     // the sender of this message is our new successor
01004     successorList->addSuccessor(joinResponse->getSrcNode());
01005 
01006     // in aggressiveJoinMode: use hint in JoinResponse
01007     // to set our new predecessor
01008     if (aggressiveJoinMode) {
01009         // it is possible that the joinResponse doesn't contain a valid
01010         // predecessor especially when merging two partitions
01011         if (!joinResponse->getPreNode().isUnspecified()) {
01012             if (!predecessorNode.isUnspecified()) {
01013 
01014 
01015                 // inform the original predecessor about the new predecessor
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     // immediate stabilization protocol
01046     cancelEvent(stabilize_timer);
01047     scheduleAt(simTime(), stabilize_timer);
01048 
01049     // immediate finger repair protocol
01050     cancelEvent(fixfingers_timer);
01051     scheduleAt(simTime(), fixfingers_timer);
01052 }
01053 
01054 
01055 void Chord::rpcStabilize(StabilizeCall* call)
01056 {
01057     // our predecessor seems to be alive
01058     if (!predecessorNode.isUnspecified() &&
01059         call->getSrcNode() == predecessorNode) {
01060         missingPredecessorStabRequests = 0;
01061     }
01062 
01063     // reply with StabilizeResponse message
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     // fetch the successor's predecessor
01079     const NodeHandle& predecessor = stabilizeResponse->getPreNode();
01080 
01081     // is the successor's predecessor a new successor for this node?
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             // successor is emptry and the sender of the response has
01088             // no predecessor => take the sender as new successor
01089             successorList->addSuccessor(stabilizeResponse->getSrcNode());
01090         } else {
01091             // add the successor's predecessor to the successor list
01092             successorList->addSuccessor(predecessor);
01093         }
01094         updateTooltip();
01095     }
01096 
01097     // compile NOTIFY RPC
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     // our predecessor seems to be alive
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     // is the new predecessor closer than the current one?
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             // set up new predecessor
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             // send update to application if we've got a new predecessor
01139             if (!oldPredecessor.isUnspecified()) {
01140                 callUpdate(oldPredecessor, false);
01141             }
01142             callUpdate(predecessorNode, true);
01143 
01144             // inform the original predecessor about the new predecessor
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     // compile NOTIFY response
01164     NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");
01165 
01166     int sucNum = successorList->getSize();
01167     notifyResponse->setSucNum(sucNum);
01168     notifyResponse->setSucNodeArraySize(sucNum);
01169 
01170     // can't accept the notify sender as predecessor,
01171     // tell it about my correct predecessor
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     // if the NotifyResponse sender couldn't accept me as predecessor,
01208     // put its predecessor into the successor list and starts stabilizing
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     // replace our successor list by our successor's successor list
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     OverlayCtrlInfo* ctrlInfo =
01262         check_and_cast<OverlayCtrlInfo*>(fixfingersResponse->getControlInfo());
01263 
01264     RECORD_STATS(globalStatistics->recordOutVector("Chord: FIX_FINGERS response Hop Count", ctrlInfo->getHopCount()));
01265      */
01266 
01267     // set new finger pointer#
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                 //pingNode(fixfingersResponse->getSucNode(i), -1, 0, NULL,
01302                 //         NULL, NULL, fixfingersResponse->getFinger(),
01303                 //         INVALID_TRANSPORT);
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         // call join dependant on return value?
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     // call join dependant on return value?
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     // initialize finger table
01372     fingerTable->initializeTable(thisNode.getKey().getLength(), thisNode, this);
01373 
01374     // initialize successor list
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         // show our predecessor and successor in tooltip
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         // draw an arrow to our current successor
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 // TODO: The following should be removed, since Chord doesn't have a simple metric
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 }; //namespace
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3