Koorde.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2007 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 
00023 #include <IPAddressResolver.h>
00024 #include <IPvXAddress.h>
00025 #include <IInterfaceTable.h>
00026 #include <IPv4InterfaceData.h>
00027 #include <GlobalStatistics.h>
00028 
00029 #include "Koorde.h"
00030 
00031 using namespace std;
00032 
00033 namespace oversim {
00034 
00035 Define_Module(Koorde);
00036 
00037 void Koorde::initializeOverlay(int stage)
00038 {
00039     // because of IPAddressResolver, we need to wait until interfaces
00040     // are registered, address auto-assignment takes place etc.
00041     if (stage != MIN_STAGE_OVERLAY)
00042         return;
00043 
00044     // fetch some parameters
00045     deBruijnDelay = par("deBruijnDelay");
00046     deBruijnListSize = par("deBruijnListSize");
00047     shiftingBits = par("shiftingBits");
00048     useOtherLookup = par("useOtherLookup");
00049     useSucList = par("useSucList");
00050     setupDeBruijnBeforeJoin = par("setupDeBruijnBeforeJoin");
00051     setupDeBruijnAtJoin = par("setupDeBruijnAtJoin");
00052 
00053     // init flags
00054     breakLookup = false;
00055 
00056     // some local variables
00057     deBruijnNumber = 0;
00058     deBruijnNodes = new NodeHandle[deBruijnListSize];
00059 
00060     // statistics
00061     deBruijnCount = 0;
00062     deBruijnBytesSent = 0;
00063 
00064     // add some watches
00065     WATCH(deBruijnNumber);
00066     WATCH(deBruijnNode);
00067 
00068     // timer messages
00069     deBruijn_timer = new cMessage("deBruijn_timer");
00070 
00071     Chord::initializeOverlay(stage);
00072 }
00073 
00074 Koorde::~Koorde()
00075 {
00076     cancelAndDelete(deBruijn_timer);
00077 }
00078 
00079 void Koorde::changeState(int toState)
00080 {
00081     Chord::changeState(toState);
00082 
00083     switch(state) {
00084     case INIT:
00085         // init de Bruijn nodes
00086         deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
00087 
00088         for (int i=0; i < deBruijnListSize; i++) {
00089             deBruijnNodes[i] = NodeHandle::UNSPECIFIED_NODE;
00090         }
00091 
00092         updateTooltip();
00093         break;
00094     case BOOTSTRAP:
00095         if (setupDeBruijnBeforeJoin) {
00096             // setup de bruijn node before joining the ring
00097             cancelEvent(join_timer);
00098             cancelEvent(deBruijn_timer);
00099             scheduleAt(simTime(), deBruijn_timer);
00100         } else if (setupDeBruijnAtJoin) {
00101             cancelEvent(deBruijn_timer);
00102             scheduleAt(simTime(), deBruijn_timer);
00103         }
00104         break;
00105     case READY:
00106         // init de Bruijn Protocol
00107         cancelEvent(deBruijn_timer);
00108         scheduleAt(simTime(), deBruijn_timer);
00109 
00110         // since we don't need the fixfingers protocol in Koorde cancel timer
00111         cancelEvent(fixfingers_timer);
00112         break;
00113     default:
00114         break;
00115     }
00116 
00117 }
00118 
00119 void Koorde::handleTimerEvent(cMessage* msg)
00120 {
00121     if (msg->isName("deBruijn_timer")) {
00122         handleDeBruijnTimerExpired();
00123     } else if (msg->isName("fixfingers_timer")) {
00124         handleFixFingersTimerExpired(msg);
00125     } else {
00126         Chord::handleTimerEvent(msg);
00127     }
00128 }
00129 
00130 bool Koorde::handleFailedNode(const TransportAddress& failed)
00131 {
00132     if (!deBruijnNode.isUnspecified()) {
00133         if (failed == deBruijnNode) {
00134             deBruijnNode = deBruijnNodes[0];
00135             for (int i = 0; i < deBruijnNumber - 1; i++) {
00136                 deBruijnNodes[i] = deBruijnNodes[i+1];
00137             }
00138 
00139             if (deBruijnNumber > 0) {
00140                 deBruijnNodes[deBruijnNumber - 1] = NodeHandle::UNSPECIFIED_NODE;
00141                 --deBruijnNumber;
00142             }
00143         } else {
00144             bool removed = false;
00145             for (int i = 0; i < deBruijnNumber - 1; i++) {
00146                 if ((!deBruijnNodes[i].isUnspecified()) &&
00147                         (failed == deBruijnNodes[i])) {
00148                     removed = true;
00149                 }
00150                 if (removed ||
00151                         ((!deBruijnNodes[deBruijnNumber - 1].isUnspecified())
00152                           && failed == deBruijnNodes[deBruijnNumber - 1])) {
00153                     deBruijnNodes[deBruijnNumber - 1] =
00154                             NodeHandle::UNSPECIFIED_NODE;
00155                     --deBruijnNumber;
00156                 }
00157             }
00158         }
00159     }
00160 
00161     return Chord::handleFailedNode(failed);
00162 }
00163 
00164 void Koorde::handleDeBruijnTimerExpired()
00165 {
00166     OverlayKey lookup = thisNode.getKey() << shiftingBits;
00167 
00168     if (state == READY) {
00169         if (successorList->getSize() > 0) {
00170             // look for some nodes before our actual de-bruijn key
00171             // to have redundancy if our de-bruijn node fails
00172             lookup -= (successorList->getSuccessor(successorList->getSize() /
00173                                               2).getKey() - thisNode.getKey());
00174         }
00175 
00176         if (lookup.isBetweenR(thisNode.getKey(),
00177                               successorList->getSuccessor().getKey())
00178                 || successorList->isEmpty()) {
00179 
00180             int sucNum = successorList->getSize();
00181             if (sucNum > deBruijnListSize)
00182                 sucNum = deBruijnListSize;
00183 
00184             deBruijnNode = thisNode;
00185             for (int i = 0; i < sucNum; i++) {
00186                 deBruijnNodes[i] = successorList->getSuccessor(i);
00187                 deBruijnNumber = i+1;
00188             }
00189 
00190             updateTooltip();
00191         } else if (lookup.isBetweenR(predecessorNode.getKey(),
00192                                      thisNode.getKey())) {
00193             int sucNum = successorList->getSize();
00194             if ((sucNum + 1) > deBruijnListSize)
00195                 sucNum = deBruijnListSize - 1;
00196 
00197             deBruijnNode = predecessorNode;
00198             deBruijnNodes[0] = thisNode;
00199             for (int i = 0; i < sucNum; i++) {
00200                 deBruijnNodes[i+1] = successorList->getSuccessor(i);
00201                 deBruijnNumber = i+2;
00202             }
00203 
00204             updateTooltip();
00205         } else {
00206             DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
00207             call->setDestKey(lookup);
00208             call->setBitLength(DEBRUIJNCALL_L(call));
00209 
00210             sendRouteRpcCall(OVERLAY_COMP, deBruijnNode,
00211                              call->getDestKey(), call, NULL,
00212                              DEFAULT_ROUTING);
00213         }
00214 
00215         cancelEvent(deBruijn_timer);
00216         scheduleAt(simTime() + deBruijnDelay, deBruijn_timer);
00217     } else {
00218         if (setupDeBruijnBeforeJoin || setupDeBruijnAtJoin) {
00219             DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
00220             call->setDestKey(lookup);
00221             call->setBitLength(DEBRUIJNCALL_L(call));
00222 
00223             sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, call->getDestKey(),
00224                              call, NULL, DEFAULT_ROUTING);
00225 
00226             scheduleAt(simTime() + deBruijnDelay, deBruijn_timer);
00227         }
00228     }
00229 }
00230 
00231 #if 0
00232 void Koorde::handleFixFingersTimerExpired(cMessage* msg)
00233 {
00234     // just in case not all timers from Chord code could be canceled
00235 }
00236 #endif
00237 
00238 
00239 void Koorde::handleUDPMessage(BaseOverlayMessage* msg)
00240 {
00241     Chord::handleUDPMessage(msg);
00242 }
00243 
00244 
00245 bool Koorde::handleRpcCall(BaseCallMessage* msg)
00246 {
00247     if (state == READY) {
00248         // delegate messages
00249         RPC_SWITCH_START( msg )
00250         RPC_DELEGATE( DeBruijn, handleRpcDeBruijnRequest );
00251         RPC_SWITCH_END( )
00252 
00253         if (RPC_HANDLED) return true;
00254     } else {
00255         EV << "[Koorde::handleRpcCall() @ " << thisNode.getAddress()
00256            << " (" << thisNode.getKey().toString(16) << ")]\n"
00257            << "    Received RPC call and state != READY!"
00258            << endl;
00259     }
00260 
00261     return Chord::handleRpcCall(msg);
00262 }
00263 
00264 void Koorde::handleRpcResponse(BaseResponseMessage* msg,
00265                                cPolymorphic* context,
00266                                int rpcId, simtime_t rtt)
00267 {
00268     Chord::handleRpcResponse(msg, context, rpcId, rtt);
00269 
00270     RPC_SWITCH_START( msg )
00271     RPC_ON_RESPONSE( DeBruijn ) {
00272         handleRpcDeBruijnResponse(_DeBruijnResponse);
00273         EV << "[Koorde::handleRpcResponse() @ " << thisNode.getAddress()
00274            << " (" << thisNode.getKey().toString(16) << ")]\n"
00275            << "    DeBruijn RPC Response received: id=" << rpcId
00276            << "\n    msg=" << *_DeBruijnResponse << " rtt=" << rtt
00277            << endl;
00278         break;
00279     }
00280     RPC_SWITCH_END( )
00281 }
00282 
00283 void Koorde::handleRpcTimeout(BaseCallMessage* msg,
00284                               const TransportAddress& dest,
00285                               cPolymorphic* context, int rpcId,
00286                               const OverlayKey& destKey)
00287 {
00288     Chord::handleRpcTimeout(msg, dest, context, rpcId, destKey);
00289 
00290     RPC_SWITCH_START( msg )
00291     RPC_ON_CALL( DeBruijn ) {
00292         handleDeBruijnTimeout(_DeBruijnCall);
00293         EV << "[Koorde::handleRpcTimeout() @ " << thisNode.getAddress()
00294            << " (" << thisNode.getKey().toString(16) << ")]\n"
00295            << "    DeBruijn RPC Call timed out: id=" << rpcId
00296            << "\n    msg=" << *_DeBruijnCall
00297            << endl;
00298         break;
00299     }
00300     RPC_SWITCH_END( )
00301 }
00302 
00303 
00304 void Koorde::handleRpcJoinResponse(JoinResponse* joinResponse)
00305 {
00306     Chord::handleRpcJoinResponse(joinResponse);
00307 
00308     // has to be canceled in Koorde
00309     cancelEvent(fixfingers_timer);
00310 
00311     // immediate deBruijn protocol
00312     cancelEvent(deBruijn_timer);
00313     scheduleAt(simTime(), deBruijn_timer);
00314 }
00315 
00316 
00317 void Koorde::rpcJoin(JoinCall* joinCall)
00318 {
00319     Chord::rpcJoin(joinCall);
00320 
00321     if (predecessorNode == successorList->getSuccessor()) {
00322         // second node join -> need to setup our de bruijn node
00323         handleDeBruijnTimerExpired();
00324     }
00325 }
00326 
00327 
00328 void Koorde::handleRpcDeBruijnRequest(DeBruijnCall* deBruijnCall)
00329 {
00330     // The key lies between thisNode and its predecessor and
00331     // because routing the message to the predecessor of a key
00332     // is near to impossible we set the deBruijnNodes here
00333     // and the information is as actual as the predecessor pointer.
00334     //
00335     // If this is the only node in the ring, it is the temporary de bruijn
00336     // node for the joining node.
00337     if ((predecessorNode.isUnspecified() && successorList->isEmpty())
00338             || deBruijnCall->getDestKey().isBetweenR(predecessorNode.getKey(),
00339                                               thisNode.getKey())) {
00340         DeBruijnResponse* deBruijnResponse =
00341             new DeBruijnResponse("DeBruijnResponse");
00342 
00343         if (predecessorNode.isUnspecified()) {
00344             deBruijnResponse->setDBNode(thisNode);
00345         } else {
00346             deBruijnResponse->setDBNode(predecessorNode);
00347         }
00348 
00349         int sucNum = successorList->getSize() + 1;
00350         deBruijnResponse->setSucNum(sucNum);
00351         deBruijnResponse->setSucNodeArraySize(sucNum);
00352 
00353         deBruijnResponse->setSucNode(0, thisNode);
00354         for (int k = 1; k < sucNum; k++) {
00355             deBruijnResponse->setSucNode(k, successorList->getSuccessor(k-1));
00356         }
00357         deBruijnResponse->setBitLength(DEBRUIJNRESPONSE_L(deBruijnResponse));
00358 
00359         sendRpcResponse(deBruijnCall, deBruijnResponse);
00360     } else if (deBruijnCall->getDestKey().isBetweenR(thisNode.getKey(),
00361                successorList->getSuccessor().getKey())) {
00362         error("Koorde::handleRpcDeBruijnRequest() - unknown error.");
00363     } else {
00364         error("Koorde::handleRpcDeBruijnRequest() - "
00365               "Request couldn't be delivered!");
00366     }
00367 }
00368 
00369 void Koorde::handleRpcDeBruijnResponse(DeBruijnResponse* deBruijnResponse)
00370 {
00371     int sucNum = deBruijnResponse->getSucNum();
00372     if (sucNum > deBruijnListSize)
00373         sucNum = deBruijnListSize;
00374 
00375     for (int i = 0; i < sucNum; i++) {
00376         deBruijnNodes[i] = deBruijnResponse->getSucNode(i);
00377         deBruijnNumber = i+1;
00378     }
00379 
00380     deBruijnNode = deBruijnResponse->getDBNode();
00381 
00382     updateTooltip();
00383 
00384     if (setupDeBruijnBeforeJoin && (state == BOOTSTRAP)) {
00385         // now that we have a valid de bruijn node it's time to join the ring
00386         if (!join_timer->isScheduled()) {
00387             scheduleAt(simTime(), join_timer);
00388         }
00389     }
00390 }
00391 
00392 void Koorde::handleDeBruijnTimeout(DeBruijnCall* deBruijnCall)
00393 {
00394     if (setupDeBruijnBeforeJoin && (state == BOOTSTRAP)) {
00395         // failed to set initial de bruijn node
00396         // -> get a new bootstrap node and try again
00397         changeState(BOOTSTRAP);
00398         return;
00399     }
00400 
00401     cancelEvent(deBruijn_timer);
00402     scheduleAt(simTime(), deBruijn_timer);
00403 }
00404 
00405 NodeVector* Koorde::findNode(const OverlayKey& key,
00406                              int numRedundantNodes,
00407                              int numSiblings,
00408                              BaseOverlayMessage* msg)
00409 {
00410     // TODO: return redundant nodes for iterative routing
00411     // TODO: try to always calculate optimal routing key (if e.g.
00412     //       the originator didn't have its deBruijnNode set already, the
00413     //       routing key may be very far away on the ring)
00414     NodeVector* nextHop = new NodeVector();
00415     KoordeFindNodeExtMessage *findNodeExt = NULL;
00416 
00417     if (state != READY)
00418         return nextHop;
00419 
00420     if (msg != NULL) {
00421         if (!msg->hasObject("findNodeExt")) {
00422             findNodeExt = new KoordeFindNodeExtMessage("findNodeExt");
00423             findNodeExt->setRouteKey(OverlayKey::UNSPECIFIED_KEY);
00424             findNodeExt->setStep(1);
00425             findNodeExt->setBitLength(KOORDEFINDNODEEXTMESSAGE_L);
00426             msg->addObject( findNodeExt );
00427         }
00428 
00429         findNodeExt = (KoordeFindNodeExtMessage*) msg->getObject("findNodeExt");
00430     }
00431 
00432     if (key.isUnspecified()) {
00433         error("Koorde::findNode() - direct Messaging is no longer in use.");
00434     } else if (key.isBetweenR(predecessorNode.getKey(), thisNode.getKey())) {
00435         // the message is destined for this node
00436         nextHop->push_back(thisNode);
00437     } else if (key.isBetweenR(thisNode.getKey(),
00438                               successorList->getSuccessor().getKey())){
00439         // the message destined for our successor
00440         nextHop->push_back(successorList->getSuccessor());
00441     } else {
00442         // if useOtherLookup is enabled we try to use
00443         // our successor list to get to the key
00444         if (useOtherLookup) {
00445             NodeHandle tmpNode = walkSuccessorList(key);
00446             if (tmpNode !=
00447                   successorList->getSuccessor(successorList->getSize() - 1)) {
00448                 nextHop->push_back(tmpNode);
00449             } else {
00450                 NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
00451                 if (tmpHandle != thisNode || breakLookup) {
00452                     nextHop->push_back(tmpHandle);
00453                     breakLookup = false;
00454                 } else {
00455                     return findNode(key, numRedundantNodes, numSiblings, msg);
00456                 }
00457             }
00458         } else {
00459             // find next hop using either the de Bruijn node and
00460             // its successors or our own successors
00461             NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
00462             if (tmpHandle != thisNode || breakLookup) {
00463                 nextHop->push_back(tmpHandle);
00464                 breakLookup = false;
00465             } else {
00466                 return findNode(key, numRedundantNodes, numSiblings, msg);
00467             }
00468         }
00469     }
00470     return nextHop;
00471 }
00472 
00473 NodeHandle Koorde::findDeBruijnHop(const OverlayKey& destKey,
00474                                    KoordeFindNodeExtMessage* findNodeExt)
00475 {
00476     if (findNodeExt->getRouteKey().isUnspecified()) {
00477         if (!deBruijnNode.isUnspecified()) {
00478             int step;
00479             findNodeExt->setRouteKey(findStartKey(thisNode.getKey(),
00480                               successorList->getSuccessor().getKey(), destKey,
00481                               step));
00482             findNodeExt->setStep(step);
00483         } else {
00484             breakLookup = true;
00485             return successorList->getSuccessor();
00486         }
00487     }
00488 
00489     // check if the route key falls in our responsibility or
00490     // else forward the message to our successor
00491     if (findNodeExt->getRouteKey().isBetweenR(thisNode.getKey(),
00492         successorList->getSuccessor().getKey())) {
00493         if ((unsigned int)findNodeExt->getStep() > destKey.getLength())
00494             error("Koorde::findDeBruijnHop - Bounding error: "
00495                   "trying to get non existing bit out of overlay key!");
00496 
00497         // update the route key
00498         OverlayKey add = OverlayKey(destKey.getBit(destKey.getLength() -
00499                                                    findNodeExt->getStep()));
00500         for (int i = 1; i < shiftingBits; i++) {
00501             add = (add << 1) + OverlayKey(destKey.getBit(destKey.getLength() -
00502                                           findNodeExt->getStep() - i));
00503         }
00504 
00505         OverlayKey routeKey = (findNodeExt->getRouteKey()<<shiftingBits) + add;
00506         findNodeExt->setRouteKey(routeKey);
00507         findNodeExt->setStep(findNodeExt->getStep() + shiftingBits);
00508 
00509         if (deBruijnNode.isUnspecified()) {
00510             breakLookup = true;
00511             if (useSucList)
00512                 return walkSuccessorList(findNodeExt->getRouteKey());
00513             else
00514                 return successorList->getSuccessor();
00515         }
00516 
00517         // check if the new route key falls between our
00518         // de Bruijn node and its successor
00519         if (deBruijnNumber > 0) {
00520             if (findNodeExt->getRouteKey().isBetweenR(deBruijnNode.getKey(),
00521                                                       deBruijnNodes[0].getKey())) {
00522                 return deBruijnNode;
00523             } else {
00524                 // otherwise check if the route key falls between
00525                 // our de Bruijn successors
00526                 NodeHandle nextHop = walkDeBruijnList(findNodeExt->
00527                                                       getRouteKey());
00528                 return nextHop;
00529             }
00530         } else {
00531             return deBruijnNode;
00532         }
00533     } else {
00534         breakLookup = true;
00535         // if optimization is set search the successor list and
00536         // de bruijn node to find "good" next hop
00537         if (useSucList) {
00538             if (deBruijnNode.isUnspecified()) {
00539                 return walkSuccessorList(findNodeExt->getRouteKey());
00540             } else {
00541                 NodeHandle tmpHandle =
00542                     walkSuccessorList(findNodeExt->getRouteKey());
00543 
00544                 // todo: optimization - check complete deBruijnList
00545                 if (deBruijnNode.getKey().isBetween(tmpHandle.getKey(),
00546                                                findNodeExt->getRouteKey())) {
00547                     return deBruijnNode;
00548                 } else {
00549                     return tmpHandle;
00550                 }
00551             }
00552         } else
00553             return successorList->getSuccessor();
00554     }
00555 }
00556 
00557 
00558 const NodeHandle& Koorde::walkDeBruijnList(const OverlayKey& key)
00559 {
00560     if (deBruijnNumber == 0)
00561         return NodeHandle::UNSPECIFIED_NODE;
00562 
00563     for (int i = 0; i < deBruijnNumber-1; i++) {
00564         if (key.isBetweenR(deBruijnNodes[i].getKey(),deBruijnNodes[i+1].getKey())) {
00565             return deBruijnNodes[i];
00566         }
00567     }
00568 
00569     return deBruijnNodes[deBruijnNumber-1];
00570 }
00571 
00572 const NodeHandle& Koorde::walkSuccessorList(const OverlayKey& key)
00573 {
00574     for (unsigned int i = 0; i < successorList->getSize()-1; i++) {
00575         if (key.isBetweenR(successorList->getSuccessor(i).getKey(),
00576                            successorList->getSuccessor(i+1).getKey())) {
00577             return successorList->getSuccessor(i);
00578         }
00579     }
00580 
00581     return successorList->getSuccessor(successorList->getSize()-1);
00582 }
00583 
00584 void Koorde::updateTooltip()
00585 {
00586     //
00587     // Updates the tooltip display strings.
00588     //
00589 
00590     if (ev.isGUI()) {
00591         std::stringstream ttString;
00592 
00593         // show our predecessor, successor and de Bruijn node in tooltip
00594         ttString << "Pred "<< predecessorNode << endl << "This  "
00595                  << thisNode << endl
00596                  << "Suc   " << successorList->getSuccessor() << endl
00597                  << "DeBr " << deBruijnNode << endl;
00598         ttString << "List ";
00599 
00600         for (unsigned int i = 0; i < successorList->getSize(); i++) {
00601             ttString << successorList->getSuccessor(i).getAddress() << " ";
00602         }
00603 
00604         ttString << endl;
00605         ttString << "DList ";
00606 
00607         for (int i = 0; i < deBruijnNumber; i++) {
00608             ttString << deBruijnNodes[i].getAddress() << " ";
00609         }
00610 
00611         ttString << endl;
00612 
00613         getParentModule()->getParentModule()->
00614             getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
00615         getParentModule()->getDisplayString().setTagArg("tt", 0,
00616                                                   ttString.str().c_str());
00617         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
00618 
00619         // draw an arrow to our current successor
00620         showOverlayNeighborArrow(successorList->getSuccessor(), true,
00621                                  "m=m,50,0,50,0;ls=red,1");
00622     }
00623 }
00624 
00625 
00626 void Koorde::finishOverlay()
00627 {
00628     // statistics
00629     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00630 
00631     if (time >= GlobalStatistics::MIN_MEASURED) {
00632         globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Messages/s",
00633                                     deBruijnCount / time);
00634         globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Bytes/s",
00635                                     deBruijnBytesSent / time);
00636     }
00637 
00638     Chord::finishOverlay();
00639 }
00640 
00641 void Koorde::recordOverlaySentStats(BaseOverlayMessage* msg)
00642 {
00643     Chord::recordOverlaySentStats(msg);
00644 
00645     BaseOverlayMessage* innerMsg = msg;
00646     while (innerMsg->getType() != APPDATA &&
00647            innerMsg->getEncapsulatedPacket() != NULL) {
00648         innerMsg =
00649             static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedPacket());
00650     }
00651 
00652     switch (innerMsg->getType()) {
00653         case RPC: {
00654             if ((dynamic_cast<DeBruijnCall*>(innerMsg) != NULL) ||
00655                 (dynamic_cast<DeBruijnResponse*>(innerMsg) != NULL)) {
00656                 RECORD_STATS(deBruijnCount++; deBruijnBytesSent +=
00657                                  msg->getByteLength());
00658             }
00659         break;
00660         }
00661     }
00662 }
00663 
00664 OverlayKey Koorde::findStartKey(const OverlayKey& startKey,
00665                                 const OverlayKey& endKey,
00666                                 const OverlayKey& destKey,
00667                                 int& step)
00668 {
00669     OverlayKey diffKey, newStart, tmpDest, newKey, powKey;
00670     int nBits;
00671 
00672     if (startKey == endKey)
00673         return startKey;
00674 
00675     diffKey = endKey - startKey;
00676     nBits = diffKey.log_2();
00677 
00678     if (nBits < 0) {
00679         nBits = 0;
00680     }
00681 
00682     while ((startKey.getLength() - nBits) % shiftingBits != 0) {
00683        nBits--;
00684    }
00685 
00686     step = nBits + 1;
00687 
00688 #if 0
00689     // TODO: work in progress to find better start key
00690     uint shared;
00691     for (shared = 0; shared < (startKey.getLength() - nBits); shared += shiftingBits) {
00692         if (destKey.sharedPrefixLength(startKey << shared) >= (startKey.getLength() - nBits - shared)) {
00693              break;
00694          }
00695     }
00696 
00697     uint nBits2 = startKey.getLength() - shared;
00698 
00699     newStart = (startKey >> nBits2) << nBits2;
00700 
00701     tmpDest = destKey >> (destKey.getLength() - nBits2);
00702     newKey = tmpDest + newStart;
00703 
00704     std::cout << "startKey: " << startKey.toString(2) << endl
00705               << "endKey  : " << endKey.toString(2) << endl
00706               << "diff    : " << (endKey-startKey).toString(2) << endl
00707               << "newKey  : " << newKey.toString(2) << endl
00708               << "destKey : " << destKey.toString(2) << endl
00709               << "nbits   : " << nBits << endl
00710               << "nbits2  : " << nBits2 << endl;
00711 
00712     // is the new constructed route key bigger than our start key return it
00713     if (newKey.isBetweenR(startKey, endKey)) {
00714         std::cout << "HIT" << endl;
00715         return newKey;
00716     } else {
00717         nBits2 -= shiftingBits;
00718         newStart = (startKey >> nBits2) << nBits2;
00719 
00720         tmpDest = destKey >> (destKey.getLength() - nBits2);
00721         newKey = tmpDest + newStart;
00722 
00723         if (newKey.isBetweenR(startKey, endKey)) {
00724             std::cout << "startKey: " << startKey.toString(2) << endl
00725                       << "endKey  : " << endKey.toString(2) << endl
00726                       << "diff    : " << (endKey-startKey).toString(2) << endl
00727                       << "newKey  : " << newKey.toString(2) << endl
00728                       << "destKey : " << destKey.toString(2) << endl
00729                       << "nbits   : " << nBits << endl
00730                       << "nbits2  : " << nBits2 << endl;
00731             std::cout << "HIT2" << endl;
00732             return newKey;
00733         }
00734     }
00735 
00736     std::cout << "MISS" << endl;
00737 #endif
00738 
00739     newStart = (startKey >> nBits) << nBits;
00740 
00741     tmpDest = destKey >> (destKey.getLength() - nBits);
00742     newKey = tmpDest + newStart;
00743 
00744     // is the new constructed route key bigger than our start key return it
00745     if (newKey.isBetweenR(startKey, endKey)) {
00746         return newKey;
00747     }
00748 
00749     // If the part of the destination key smaller than the one of
00750     // the original key add pow(nBits) (this is the first bit where
00751     // the start key and end key differ) to the new constructed key
00752     // and check if it's between start and end key.
00753     newKey += powKey.pow2(nBits);
00754 
00755     if (newKey.isBetweenR(startKey, endKey)) {
00756         return newKey;
00757     } else {
00758         // this part should not be called
00759         throw cRuntimeError("Koorde::findStartKey(): Invalid start key");
00760         return OverlayKey::UNSPECIFIED_KEY;
00761     }
00762 }
00763 
00764 void Koorde::findFriendModules()
00765 {
00766     successorList = check_and_cast<ChordSuccessorList*>
00767                     (getParentModule()->getSubmodule("successorList"));
00768 }
00769 
00770 void Koorde::initializeFriendModules()
00771 {
00772     // initialize successor list
00773     successorList->initializeList(par("successorListSize"), thisNode, this);
00774 }
00775 
00776 }; //namespace
00777 
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3