BasePastry.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 <sstream>
00025 
00026 #include <IPAddressResolver.h>
00027 #include <IPvXAddress.h>
00028 #include <IInterfaceTable.h>
00029 #include <IPv4InterfaceData.h>
00030 #include <RpcMacros.h>
00031 #include <InitStages.h>
00032 #include <NeighborCache.h>
00033 #include <GlobalStatistics.h>
00034 #include <BootstrapList.h>
00035 #include <assert.h>
00036 
00037 #include "BasePastry.h"
00038 
00039 
00040 void BasePastry::purgeVectors(void)
00041 {
00042     // purge Queue for processing multiple STATE messages:
00043     while (! stateCacheQueue.empty()) {
00044         delete stateCacheQueue.front().msg;
00045         delete stateCacheQueue.front().prox;
00046         stateCacheQueue.pop();
00047     }
00048 
00049     // delete cached state message:
00050     delete stateCache.msg;
00051     stateCache.msg = NULL;
00052     delete stateCache.prox;
00053     stateCache.prox = NULL;
00054 
00055     // purge vector of waiting sendState messages:
00056     if (! sendStateWait.empty()) {
00057         for (std::vector<PastrySendState*>::iterator it =
00058                  sendStateWait.begin(); it != sendStateWait.end(); it++) {
00059             if ( (*it)->isScheduled() ) cancelEvent(*it);
00060             delete *it;
00061         }
00062         sendStateWait.clear();
00063     }
00064 }
00065 
00066 void BasePastry::baseInit()
00067 {
00068     bitsPerDigit = par("bitsPerDigit");
00069     numberOfLeaves = par("numberOfLeaves");
00070     numberOfNeighbors = par("numberOfNeighbors");
00071     joinTimeoutAmount = par("joinTimeout");
00072     repairTimeout = par("repairTimeout");
00073     enableNewLeafs = par("enableNewLeafs");
00074     optimizeLookup = par("optimizeLookup");
00075     useRegularNextHop = par("useRegularNextHop");
00076     alwaysSendUpdate = par("alwaysSendUpdate");
00077     proximityNeighborSelection = par("proximityNeighborSelection");
00078 
00079     if (!neighborCache->isEnabled()) {
00080         throw cRuntimeError("NeighborCache is disabled, which is mandatory "
00081                                 "for Pastry/Bamboo. Activate it by setting "
00082                                 "\"**.neighborCache.enableNeighborCache "
00083                                 "= true\" in your omnetpp.ini!");
00084     }
00085 
00086     if (numberOfLeaves % 2) {
00087         EV << "[BasePastry::baseInit() @ " << thisNode.getAddress()
00088            << " (" << thisNode.getKey().toString(16) << ")]\n"
00089            << "    Warning: numberOfLeaves must be even - adding 1."
00090            << endl;
00091         numberOfLeaves++;
00092     }
00093 
00094     routingTable = check_and_cast<PastryRoutingTable*>
00095         (getParentModule()->getSubmodule("pastryRoutingTable"));
00096     leafSet = check_and_cast<PastryLeafSet*>
00097         (getParentModule()->getSubmodule("pastryLeafSet"));
00098     neighborhoodSet = check_and_cast<PastryNeighborhoodSet*>
00099         (getParentModule()->getSubmodule("pastryNeighborhoodSet"));
00100 
00101     stateCache.msg = NULL;
00102     stateCache.prox = NULL;
00103 
00104     rowToAsk = 0;
00105 
00106     // initialize statistics
00107     joins = 0;
00108     joinTries = 0;
00109     joinPartial = 0;
00110     joinSeen = 0;
00111     joinReceived = 0;
00112     joinSent = 0;
00113     stateSent = 0;
00114     stateReceived = 0;
00115     repairReqSent = 0;
00116     repairReqReceived = 0;
00117     stateReqSent = 0;
00118     stateReqReceived = 0;
00119 
00120     joinBytesSeen = 0;
00121     joinBytesReceived = 0;
00122     joinBytesSent = 0;
00123     stateBytesSent = 0;
00124     stateBytesReceived = 0;
00125     repairReqBytesSent = 0;
00126     repairReqBytesReceived = 0;
00127     stateReqBytesSent = 0;
00128     stateReqBytesReceived = 0;
00129 
00130     totalLookups = 0;
00131     responsibleLookups = 0;
00132     routingTableLookups = 0;
00133     closerNodeLookups = 0;
00134     closerNodeLookupsFromNeighborhood = 0;
00135 
00136     leafsetReqSent = 0;
00137     leafsetReqBytesSent = 0;
00138     leafsetReqReceived = 0;
00139     leafsetReqBytesReceived = 0;
00140     leafsetSent = 0;
00141     leafsetBytesSent = 0;
00142     leafsetReceived = 0;
00143     leafsetBytesReceived = 0;
00144 
00145     routingTableReqSent = 0;
00146     routingTableReqBytesSent = 0;
00147     routingTableReqReceived = 0;
00148     routingTableReqBytesReceived = 0;
00149     routingTableSent = 0;
00150     routingTableBytesSent = 0;
00151     routingTableReceived = 0;
00152     routingTableBytesReceived = 0;
00153 
00154     WATCH(joins);
00155     WATCH(joinTries);
00156     WATCH(joinSeen);
00157     WATCH(joinBytesSeen);
00158     WATCH(joinReceived);
00159     WATCH(joinBytesReceived);
00160     WATCH(joinSent);
00161     WATCH(joinBytesSent);
00162     WATCH(stateSent);
00163     WATCH(stateBytesSent);
00164     WATCH(stateReceived);
00165     WATCH(stateBytesReceived);
00166     WATCH(repairReqSent);
00167     WATCH(repairReqBytesSent);
00168     WATCH(repairReqReceived);
00169     WATCH(repairReqBytesReceived);
00170     WATCH(stateReqSent);
00171     WATCH(stateReqBytesSent);
00172     WATCH(stateReqReceived);
00173     WATCH(stateReqBytesReceived);
00174     WATCH(lastStateChange);
00175 
00176     WATCH(leafsetReqSent);
00177     WATCH(leafsetReqBytesSent);
00178     WATCH(leafsetReqReceived);
00179     WATCH(leafsetReqBytesReceived);
00180     WATCH(leafsetSent);
00181     WATCH(leafsetBytesSent);
00182     WATCH(leafsetReceived);
00183     WATCH(leafsetBytesReceived);
00184 
00185     WATCH(routingTableReqSent);
00186     WATCH(routingTableReqBytesSent);
00187     WATCH(routingTableReqReceived);
00188     WATCH(routingTableReqBytesReceived);
00189     WATCH(routingTableSent);
00190     WATCH(routingTableBytesSent);
00191     WATCH(routingTableReceived);
00192     WATCH(routingTableBytesReceived);
00193 }
00194 
00195 
00196 void BasePastry::baseChangeState(int toState)
00197 {
00198     switch (toState) {
00199     case INIT:
00200         state = INIT;
00201 
00202         if (!thisNode.getKey().isUnspecified())
00203             bootstrapList->removeBootstrapNode(thisNode);
00204 
00205         if (joinTimeout->isScheduled()) cancelEvent(joinTimeout);
00206 
00207         purgeVectors();
00208 
00209         bootstrapNode = bootstrapList->getBootstrapNode();
00210 
00211         routingTable->initializeTable(bitsPerDigit, repairTimeout, thisNode);
00212         leafSet->initializeSet(numberOfLeaves, bitsPerDigit,
00213                                repairTimeout, thisNode, this);
00214         neighborhoodSet->initializeSet(numberOfNeighbors, bitsPerDigit,
00215                                        thisNode);
00216 
00217         updateTooltip();
00218         lastStateChange = simTime();
00219 
00220         getParentModule()->getParentModule()->bubble("entering INIT state");
00221 
00222         break;
00223 
00224     case JOINING_2:
00225         state = JOINING_2;
00226 
00227         // bootstrapNode must be obtained before calling this method,
00228         // for example by calling changeState(INIT)
00229 
00230         if (bootstrapNode.isUnspecified()) {
00231             // no existing pastry network -> first node of a new one
00232             changeState(READY);
00233             return;
00234         }
00235 
00236         cancelEvent(joinTimeout);
00237         scheduleAt(simTime() + joinTimeoutAmount, joinTimeout);
00238 
00239         updateTooltip();
00240         getParentModule()->getParentModule()->bubble("entering JOIN state");
00241 
00242         RECORD_STATS(joinTries++);
00243 
00244         break;
00245 
00246     case READY:
00247         assert(state != READY);
00248         state = READY;
00249 
00250          //bootstrapList->registerBootstrapNode(thisNode);
00251 
00252         // if we are the first node in the network, there's nothing else
00253         // to do
00254         if (bootstrapNode.isUnspecified()) {
00255             RECORD_STATS(joinTries++);
00256             RECORD_STATS(joins++);
00257             setOverlayReady(true);
00258             return;
00259         }
00260 
00261         getParentModule()->getParentModule()->bubble("entering READY state");
00262         updateTooltip();
00263         RECORD_STATS(joins++);
00264 
00265         break;
00266 
00267     default: // discovery
00268         break;
00269     }
00270     setOverlayReady(state == READY);
00271 }
00272 
00273 
00274 void BasePastry::newLeafs(void)
00275 {
00276     if (! enableNewLeafs) return;
00277 
00278     PastryNewLeafsMessage* msg = leafSet->getNewLeafsMessage();
00279     if (msg) {
00280         send(msg, "appOut");
00281         EV << "[BasePastry::newLeafs() @ " << thisNode.getAddress()
00282            << " (" << thisNode.getKey().toString(16) << ")]\n"
00283            << "    newLeafs() called."
00284            << endl;
00285     }
00286 }
00287 
00288 
00289 void BasePastry::changeState(int toState)
00290 {
00291 
00292 }
00293 
00294 
00295 void BasePastry::pingResponse(PingResponse* msg, cPolymorphic* context,
00296                               int rpcId, simtime_t rtt)
00297 {
00298     EV << "[BasePastry::pingResponse() @ " << thisNode.getAddress()
00299        << " (" << thisNode.getKey().toString(16) << ")]\n"
00300        << "    Pong (or Ping-context from NeighborCache) received (from "
00301        << msg->getSrcNode().getAddress() << ")"
00302        << endl;
00303 
00304     const NodeHandle& src = msg->getSrcNode();
00305     assert(!src.isUnspecified());
00306 
00307     // merge single pinged nodes (bamboo global tuning)
00308     if (rpcId == PING_SINGLE_NODE) {
00309         routingTable->mergeNode(src, proximityNeighborSelection ?
00310                                      rtt : SimTime::getMaxTime());
00311         return;
00312     }
00313 
00314     /*// a node with the an equal ID has responded
00315     if ((src.getKey() == thisNode.getKey()) && (src.getAddress() != thisNode.getAddress())) {
00316         EV << "[BasePastry::pingResponse() @ " << thisNode.getAddress()
00317            << " (" << thisNode.getKey().toString(16) << ")]\n"
00318            << "    a node with the an equal ID has responded, rejoining" << endl;
00319         delete context;
00320         //joinOverlay();
00321         return;
00322     }*/
00323 
00324     if (context != NULL && stateCache.msg && stateCache.prox) {
00325         PingContext* pingContext = check_and_cast<PingContext*>(context);
00326         if (pingContext->nonce != stateCache.nonce) {
00327             delete context;
00328             return;
00329             //throw cRuntimeError("response doesn't fit stateCache");
00330         }
00331         switch (pingContext->stateObject) {
00332             case ROUTINGTABLE: {
00333                 /*node = &(stateCache.msg->getRoutingTable(pingContext->index));
00334                 if((node->isUnspecified()) || (*node != src)) {
00335                     std::cout << simTime() << " " << thisNode.getAddress() << " rt: state from "
00336                               << stateCache.msg->getSender().getAddress() << " *** failed: node "
00337                               << node->ip << " src " << src.getAddress() << std::endl;
00338                     break;
00339                 }*/
00340                 *(stateCache.prox->pr_rt.begin() + pingContext->index) = rtt;
00341                 break;
00342             }
00343             case LEAFSET: {
00344                 /*node = &(stateCache.msg->getLeafSet(pingContext->index));
00345                 if ((node->isUnspecified()) || (*node != src)) {
00346                     std::cout << simTime() << " " << thisNode.getAddress() << " ls: state from "
00347                               << stateCache.msg->getSender().getAddress() << " *** failed: node "
00348                               << node->ip << " src " << src.getAddress() << std::endl;
00349                     break;
00350                 }*/
00351                 *(stateCache.prox->pr_ls.begin() + pingContext->index) = rtt;
00352                 break;
00353             }
00354             case NEIGHBORHOODSET: {
00355                 /*node = &(stateCache.msg->getNeighborhoodSet(pingContext->index));
00356                 if((node->isUnspecified()) || (*node != src)) {
00357                     std::cout << simTime() << " " << thisNode.getAddress() << " ns: state from "
00358                               << stateCache.msg->getSender().getAddress() << " *** failed: node "
00359                               << node->ip << " src " << src.getAddress() << std::endl;
00360                     break;
00361                 }*/
00362                 *(stateCache.prox->pr_ns.begin() + pingContext->index) = rtt;
00363                 break;
00364             }
00365             default: {
00366                 throw cRuntimeError("wrong state object type!");
00367             }
00368         }
00369         checkProxCache();
00370     }
00371     delete context;
00372 }
00373 
00374 
00375 void BasePastry::proxCallback(const TransportAddress& node, int rpcId,
00376                               cPolymorphic *contextPointer, Prox prox)
00377 {
00378     Enter_Method("proxCallback()");
00379 
00380     EV << "[BasePastry::proxCallback() @ " << thisNode.getAddress()
00381            << " (" << thisNode.getKey().toString(16) << ")]\n"
00382            << "    Pong received (from "
00383            << node.getAddress() << ")"
00384            << endl;
00385 
00386     double rtt = ((prox == Prox::PROX_TIMEOUT) ? PASTRY_PROX_INFINITE
00387                                                : prox.proximity);
00388 
00389     // merge single pinged nodes (bamboo global tuning)
00390     if (rpcId == PING_SINGLE_NODE) {
00391         routingTable->mergeNode((const NodeHandle&)node,
00392                                 proximityNeighborSelection ?
00393                                 rtt : SimTime::getMaxTime());
00394         delete contextPointer;
00395         return;
00396     }
00397 
00398     if (contextPointer != NULL && stateCache.msg && stateCache.prox) {
00399         PingContext* pingContext = check_and_cast<PingContext*>(contextPointer);
00400 
00401         if (pingContext->nonce != stateCache.nonce) {
00402             delete contextPointer;
00403             return;
00404         }
00405         // handle failed node
00406         if (rtt == PASTRY_PROX_INFINITE && state== READY) {
00407             handleFailedNode(node); // TODO
00408             updateTooltip();
00409 
00410             // this could initiate a re-join, exit the handler in that
00411             // case because all local data was erased:
00412             if (state != READY) {
00413                 delete contextPointer;
00414                 return;
00415             }
00416         }
00417         switch (pingContext->stateObject) {
00418         case ROUTINGTABLE:
00419             *(stateCache.prox->pr_rt.begin() + pingContext->index) = rtt;
00420             break;
00421 
00422         case LEAFSET:
00423             *(stateCache.prox->pr_ls.begin() + pingContext->index) = rtt;
00424             break;
00425 
00426         case NEIGHBORHOODSET:
00427             *(stateCache.prox->pr_ns.begin() + pingContext->index) = rtt;
00428             break;
00429 
00430         default:
00431             throw cRuntimeError("wrong state object type!");
00432         }
00433         checkProxCache();
00434     }
00435     delete contextPointer;
00436 }
00437 
00438 
00439 void BasePastry::prePing(const PastryStateMessage* stateMsg)
00440 {
00441     uint32_t rt_size = stateMsg->getRoutingTableArraySize();
00442     uint32_t ls_size = stateMsg->getLeafSetArraySize();
00443     uint32_t ns_size = stateMsg->getNeighborhoodSetArraySize();
00444 
00445     for (uint32_t i = 0; i < rt_size + ls_size + ns_size; i++) {
00446         const NodeHandle* node;
00447         if (i < rt_size) {
00448             node = &(stateMsg->getRoutingTable(i));
00449         }
00450         else if (i < (rt_size + ls_size) ) {
00451             node = &(stateMsg->getLeafSet(i - rt_size));
00452         }
00453         else {
00454             node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00455         }
00456         if ((node->isUnspecified()) || (*node == thisNode)) {
00457             continue;
00458         }
00459         /*if (node->key == thisNode.getKey()) {
00460             cerr << "Pastry Warning: Other node with same key found, "
00461                 "restarting!" << endl;
00462             opp_error("TODO: Other node with same key found...");
00463             joinOverlay(); //segfault
00464             //return;
00465             continue;
00466         }*/
00467 
00468         neighborCache->getProx(*node, NEIGHBORCACHE_DEFAULT, PING_RECEIVED_STATE, this, NULL);
00469     }
00470 }
00471 
00472 void BasePastry::pingNodes(void)
00473 {
00474     EV << "[BasePastry::pingNodes() @ " << thisNode.getAddress()
00475        << " (" << thisNode.getKey().toString(16) << ")]" << endl;
00476 
00477     if (stateCache.msg == NULL) throw cRuntimeError("no state msg");
00478 
00479     assert(stateCache.prox == NULL);
00480     stateCache.prox = new PastryStateMsgProximity();
00481 
00482     uint32_t rt_size = stateCache.msg->getRoutingTableArraySize();
00483     stateCache.prox->pr_rt.resize(rt_size, PASTRY_PROX_UNDEF);
00484 
00485     uint32_t ls_size = stateCache.msg->getLeafSetArraySize();
00486     stateCache.prox->pr_ls.resize(ls_size, PASTRY_PROX_UNDEF);
00487 
00488     uint32_t ns_size = stateCache.msg->getNeighborhoodSetArraySize();
00489     stateCache.prox->pr_ns.resize(ns_size, PASTRY_PROX_UNDEF);
00490 
00491     std::vector< std::pair<const NodeHandle*, PingContext*> > nodesToPing;
00492     // set prox state
00493     for (uint32_t i = 0; i < rt_size + ls_size + ns_size; i++) {
00494         const NodeHandle* node;
00495         std::vector<simtime_t>::iterator proxPos;
00496         PingContext* pingContext = NULL;
00497         StateObject stateObject;
00498         uint32_t index;
00499         if (stateCache.msg == NULL) break;
00500         if (i < rt_size) {
00501             node = &(stateCache.msg->getRoutingTable(i));
00502             proxPos = stateCache.prox->pr_rt.begin() + i;
00503             stateObject = ROUTINGTABLE;
00504             index = i;
00505         } else if ( i < (rt_size + ls_size) ) {
00506             node = &(stateCache.msg->getLeafSet(i - rt_size));
00507             proxPos = stateCache.prox->pr_ls.begin() + (i - rt_size);
00508             stateObject = LEAFSET;
00509             index = i - rt_size;
00510         } else {
00511             node = &(stateCache.msg->getNeighborhoodSet(i - rt_size - ls_size));
00512             proxPos = stateCache.prox->pr_ns.begin() + (i - rt_size - ls_size);
00513             stateObject = NEIGHBORHOODSET;
00514             index = i - rt_size - ls_size;
00515         }
00516         // proximity is undefined for unspecified nodes:
00517         if (!node->isUnspecified()) {
00518             pingContext = new PingContext(stateObject, index,
00519                                           stateCache.nonce);
00520 
00521             Prox prox = neighborCache->getProx(*node, NEIGHBORCACHE_DEFAULT, -1,
00522                                                this, pingContext);
00523             if (prox == Prox::PROX_SELF) {
00524                 *proxPos = 0;
00525             } else if (prox == Prox::PROX_TIMEOUT) {
00526                 *proxPos = PASTRY_PROX_INFINITE;
00527             } else if (prox == Prox::PROX_UNKNOWN) {
00528                 *proxPos = PASTRY_PROX_PENDING;
00529             } else {
00530                 *proxPos = prox.proximity;
00531             }
00532         }
00533     }
00534     checkProxCache();
00535 }
00536 
00537 void BasePastry::determineAliveTable(const PastryStateMessage* stateMsg)
00538 {
00539     uint32_t rt_size = stateMsg->getRoutingTableArraySize();
00540     aliveTable.pr_rt.clear();
00541     aliveTable.pr_rt.resize(rt_size, 1);
00542 
00543     uint32_t ls_size = stateMsg->getLeafSetArraySize();
00544     aliveTable.pr_ls.clear();
00545     aliveTable.pr_ls.resize(ls_size, 1);
00546 
00547     uint32_t ns_size = stateMsg->getNeighborhoodSetArraySize();
00548     aliveTable.pr_ns.clear();
00549     aliveTable.pr_ns.resize(ns_size, 1);
00550 
00551     for (uint32_t i = 0; i < rt_size + ls_size + ns_size; i++) {
00552         const TransportAddress* node;
00553         std::vector<simtime_t>::iterator tblPos;
00554         if (i < rt_size) {
00555             node = &(stateMsg->getRoutingTable(i));
00556             tblPos = aliveTable.pr_rt.begin() + i;
00557         } else if ( i < (rt_size + ls_size) ) {
00558             node = &(stateMsg->getLeafSet(i - rt_size));
00559             tblPos = aliveTable.pr_ls.begin() + (i - rt_size);
00560         } else {
00561             node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00562             tblPos = aliveTable.pr_ns.begin() + (i - rt_size - ls_size);
00563         }
00564         if (neighborCache->getProx(*node, NEIGHBORCACHE_DEFAULT_IMMEDIATELY) ==
00565                 Prox::PROX_TIMEOUT) {
00566             *tblPos = PASTRY_PROX_INFINITE;
00567         }
00568     }
00569 }
00570 
00571 void BasePastry::sendStateTables(const TransportAddress& destination,
00572                                  int type, ...)
00573 {
00574     if (destination.getAddress() == thisNode.getAddress())
00575         opp_error("Pastry: trying to send state to self!");
00576 
00577     int hops = 0;
00578     bool last = false;
00579     simtime_t timestamp = 0;
00580 
00581     if ((type == PASTRY_STATE_JOIN) ||
00582         (type == PASTRY_STATE_MINJOIN) ||
00583         (type == PASTRY_STATE_UPDATE)) {
00584         // additional parameters needed:
00585         va_list ap;
00586         va_start(ap, type);
00587         if (type == PASTRY_STATE_JOIN || type == PASTRY_STATE_MINJOIN) {
00588             hops = va_arg(ap, int);
00589             last = static_cast<bool>(va_arg(ap, int));
00590         } else {
00591             timestamp = *va_arg(ap, simtime_t*);
00592         }
00593         va_end(ap);
00594     }
00595 
00596     // create new state msg and set special fields for some types:
00597     PastryStateMessage* stateMsg;
00598     if (type == PASTRY_STATE_JOIN || type == PASTRY_STATE_MINJOIN) {
00599         stateMsg = new PastryStateMessage("STATE (Join)");
00600         stateMsg->setJoinHopCount(hops);
00601         stateMsg->setLastHop(last);
00602         stateMsg->setTimestamp(simTime());
00603     } else if (type == PASTRY_STATE_UPDATE) {
00604         stateMsg = new PastryStateMessage("STATE (Update)");
00605         EV << "[BasePastry::sendStateTables() @ " << thisNode.getAddress()
00606            << " (" << thisNode.getKey().toString(16) << ")]\n"
00607            << "    sending state (update) to " << destination
00608            << endl;
00609         stateMsg->setTimestamp(timestamp);
00610     } else if (type == PASTRY_STATE_REPAIR) {
00611         stateMsg = new PastryStateMessage("STATE (Repair)");
00612         stateMsg->setTimestamp(timestamp);
00613         EV << "[BasePastry::sendStateTables() @ " << thisNode.getAddress()
00614            << " (" << thisNode.getKey().toString(16) << ")]\n"
00615            << "    sending state (repair) to " << destination
00616            << endl;
00617     } else {
00618         stateMsg = new PastryStateMessage("STATE");
00619         EV << "[BasePastry::sendStateTables() @ " << thisNode.getAddress()
00620            << " (" << thisNode.getKey().toString(16) << ")]\n"
00621            << "    sending state (standard) to " << destination
00622            << endl;
00623     }
00624 
00625     // fill in standard content:
00626     stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00627     stateMsg->setStatType(MAINTENANCE_STAT);
00628     stateMsg->setPastryStateMsgType(type);
00629     stateMsg->setSender(thisNode);
00630 
00631     // the following part of the new join works on the assumption, that the node
00632     // routing the join message is close to the joining node
00633     // therefore its switched on together with the discovery algorithm
00634     if (type == PASTRY_STATE_MINJOIN) {
00635         //send just the needed row for new join protocol
00636         routingTable->dumpRowToMessage(stateMsg, hops);
00637         if (last) leafSet->dumpToStateMessage(stateMsg);
00638         else stateMsg->setLeafSetArraySize(0);
00639         if (hops == 1) neighborhoodSet->dumpToStateMessage(stateMsg);
00640         else stateMsg->setNeighborhoodSetArraySize(0);
00641     } else {
00642         routingTable->dumpToStateMessage(stateMsg);
00643         leafSet->dumpToStateMessage(stateMsg);
00644         neighborhoodSet->dumpToStateMessage(stateMsg);
00645     }
00646 
00647     // send...
00648     stateMsg->setBitLength(PASTRYSTATE_L(stateMsg));
00649     RECORD_STATS(stateSent++; stateBytesSent += stateMsg->getByteLength());
00650     sendMessageToUDP(destination, stateMsg);
00651 }
00652 
00653 void BasePastry::sendStateDelayed(const TransportAddress& destination)
00654 {
00655     PastrySendState* selfMsg = new PastrySendState("sendStateWait");
00656     selfMsg->setDest(destination);
00657     sendStateWait.push_back(selfMsg);
00658     scheduleAt(simTime() + 0.0001, selfMsg);
00659 }
00660 
00661 void BasePastry::pingTimeout(PingCall* msg,
00662                              const TransportAddress& dest,
00663                              cPolymorphic* context,
00664                              int rpcId)
00665 {
00666     EV << "[BasePastry::sendStateDelayed() @ " << thisNode.getAddress()
00667        << " (" << thisNode.getKey().toString(16) << ")]\n"
00668        << "    Ping timeout occurred (" << dest.getAddress() << ")"
00669        << endl;
00670 
00671     // handle failed node
00672     if (state == READY) {
00673         handleFailedNode(dest); // TODO
00674         updateTooltip();
00675 
00676         // this could initiate a re-join, exit the handler in that
00677         // case because all local data was erased:
00678         if (state != READY) {
00679             delete context;
00680             return;
00681         }
00682     }
00683 
00684     //TODO must be removed
00685     if (context && stateCache.msg && stateCache.prox &&
00686         rpcId == PING_RECEIVED_STATE) {
00687         PingContext* pingContext = check_and_cast<PingContext*>(context);
00688         if (pingContext->nonce != stateCache.nonce) {
00689             delete context;
00690             return;
00691             //std::stringstream temp;
00692             //temp << thisNode << " timeout/call doesn't fit stateCache";
00693             //throw cRuntimeError(temp.str().c_str());
00694         }
00695         //const NodeHandle* node;
00696         switch (pingContext->stateObject) {
00697             case ROUTINGTABLE: {
00698                 /*if (pingContext->index >=
00699                     stateCache.msg->getRoutingTableArraySize()) {
00700                     std::cout << "*** FAILED ***" << std::endl;
00701                     break;
00702                 }
00703                 node = &(stateCache.msg->getRoutingTable(pingContext->index));
00704                 if((node->isUnspecified()) || (dest != *node)) {
00705                     std::cout << msg->getNonce() << " " << simTime() << " " << thisNode.getAddress() << " rt: state from "
00706                     << stateCache.msg->getSender().getAddress() << " *** failed: node "
00707                     << node->ip << " failed dest " << dest.getAddress() << std::endl;
00708                     break;
00709                 }*/
00710                 *(stateCache.prox->pr_rt.begin() + pingContext->index) =
00711                     PASTRY_PROX_INFINITE;
00712                 break;
00713             }
00714             case LEAFSET: {
00715                 /*if (pingContext->index >=
00716                     stateCache.msg->getLeafSetArraySize()) {
00717                     std::cout << "*** FAILED ***" << std::endl;
00718                     break;
00719                 }
00720                 node = &(stateCache.msg->getLeafSet(pingContext->index));
00721                 if((node->isUnspecified()) || (dest != *node)) {
00722                     std::cout << msg->getNonce() << " " << simTime() << " " << thisNode.getAddress() << " ls: state from "
00723                     << stateCache.msg->getSender().getAddress() << " *** failed: node "
00724                     << node->ip << " failed dest " << dest.getAddress() << std::endl;
00725                     break;
00726                 }*/
00727                 *(stateCache.prox->pr_ls.begin() + pingContext->index) =
00728                     PASTRY_PROX_INFINITE;
00729                 break;
00730             }
00731             case NEIGHBORHOODSET: {
00732                 /*if (pingContext->index >=
00733                     stateCache.msg->getNeighborhoodSetArraySize()) {
00734                     std::cout << "*** FAILED ***" << std::endl;
00735                     break;
00736                 }
00737                 node = &(stateCache.msg->getNeighborhoodSet(pingContext->index));
00738                 if((node->isUnspecified()) || (dest != *node)) {
00739                     std::cout << msg->getNonce() << " " << simTime() << " " << thisNode.getAddress() << " ns: state from "
00740                     << stateCache.msg->getSender().getAddress() << " *** failed: node "
00741                     << node->ip << " failed dest " << dest.getAddress() << std::endl;
00742                     break;
00743                 }*/
00744                 *(stateCache.prox->pr_ns.begin() + pingContext->index) =
00745                     PASTRY_PROX_INFINITE;
00746                 break;
00747             }
00748         }
00749         checkProxCache();
00750     }
00751 
00752     delete context;
00753 }
00754 
00755 void BasePastry::sendRequest(const TransportAddress& ask, int type)
00756 {
00757     assert(ask != thisNode);
00758     std::string msgName("Req: ");
00759     switch (type) {
00760     case PASTRY_REQ_REPAIR:
00761         if (ask.isUnspecified())
00762             throw cRuntimeError("Pastry::sendRequest(): asked for repair from "
00763                                 "unspecified node!");
00764         msgName += "Repair";
00765         break;
00766 
00767     case PASTRY_REQ_STATE:
00768         if (ask.isUnspecified())
00769             throw cRuntimeError("Pastry::sendRequest(): asked for state from "
00770                                 "unspecified node!");
00771         msgName += "State";
00772         break;
00773 
00774     case PASTRY_REQ_LEAFSET:
00775         if (ask.isUnspecified())
00776             throw cRuntimeError("Pastry::sendRequest(): asked for leafset from "
00777                   "unspecified node!");
00778         msgName += "Leafset";
00779         break;
00780     }
00781     PastryRequestMessage* msg = new PastryRequestMessage(msgName.c_str());
00782     msg->setPastryMsgType(PASTRY_MSG_REQ);
00783     msg->setPastryReqType(type);
00784     msg->setStatType(MAINTENANCE_STAT);
00785     msg->setSendStateTo(thisNode);
00786     msg->setBitLength(PASTRYREQ_L(msg));
00787     sendMessageToUDP(ask, msg); //TODO RPCs
00788 
00789     switch (type) {
00790     case PASTRY_REQ_REPAIR:
00791         RECORD_STATS(repairReqSent++; repairReqBytesSent += msg->getByteLength());
00792         break;
00793 
00794     case PASTRY_REQ_STATE:
00795         RECORD_STATS(stateReqSent++; stateReqBytesSent += msg->getByteLength());
00796         break;
00797 
00798     case PASTRY_REQ_LEAFSET:
00799         RECORD_STATS(leafsetReqSent++; leafsetReqBytesSent += msg->getByteLength());
00800         break;
00801     }
00802 }
00803 
00804 
00805 void BasePastry::sendLeafset(const TransportAddress& tell, bool pull)
00806 {
00807     if (tell.isUnspecified())
00808         opp_error("Pastry::sendLeafset(): send leafset to "
00809                   "unspecified node!");
00810 
00811     PastryLeafsetMessage* msg = new PastryLeafsetMessage("Leafset");
00812     if (pull) msg->setPastryMsgType(PASTRY_MSG_LEAFSET_PULL);
00813     else msg->setPastryMsgType(PASTRY_MSG_LEAFSET);
00814     msg->setTimestamp(simTime());
00815     msg->setStatType(MAINTENANCE_STAT);
00816     msg->setSender(thisNode);
00817     msg->setSendStateTo(thisNode);
00818     leafSet->dumpToStateMessage(msg);
00819     msg->setBitLength(PASTRYLEAFSET_L(msg));
00820     RECORD_STATS(leafsetSent++; leafsetBytesSent += msg->getByteLength());
00821     sendMessageToUDP(tell, msg);
00822 
00823 
00824 }
00825 
00826 void BasePastry::sendRoutingRow(const TransportAddress& tell, int row)
00827 {
00828     if (tell.isUnspecified())
00829         opp_error("Pastry::sendRoutingTable(): asked for routing Table from "
00830                   "unspecified node!");
00831 
00832     PastryRoutingRowMessage* msg = new PastryRoutingRowMessage("Routing Row");
00833     msg->setPastryMsgType(PASTRY_MSG_RROW);
00834     msg->setStatType(MAINTENANCE_STAT);
00835     //msg->setSendStateTo(thisNode);
00836     msg->setSender(thisNode);
00837     msg->setRow(row);
00838     routingTable->dumpRowToMessage(msg, row);
00839     msg->setBitLength(PASTRYRTABLE_L(msg));
00840     RECORD_STATS(routingTableSent++; routingTableBytesSent += msg->getByteLength());
00841     sendMessageToUDP(tell, msg);
00842 }
00843 
00844 void BasePastry::handleRequestMessage(PastryRequestMessage* msg)
00845 {
00846     assert(msg->getSendStateTo() != thisNode);
00847     uint32_t reqtype = msg->getPastryReqType();
00848     if (reqtype == PASTRY_REQ_REPAIR) {
00849         RECORD_STATS(repairReqReceived++; repairReqBytesReceived +=
00850             msg->getByteLength());
00851         if (state == READY)
00852             sendStateTables(msg->getSendStateTo(),
00853                             PASTRY_STATE_REPAIR);
00854         else
00855             EV << "[BasePastry::handleRequestMessage() @ " << thisNode.getAddress()
00856             << " (" << thisNode.getKey().toString(16) << ")]\n"
00857             << "    received repair request before reaching"
00858             << " READY state, dropping message!"
00859             << endl;
00860         delete msg;
00861     }
00862     else if (reqtype == PASTRY_REQ_STATE) {
00863         RECORD_STATS(stateReqReceived++; stateReqBytesReceived +=
00864             msg->getByteLength());
00865         if (state == READY)
00866             sendStateTables(msg->getSendStateTo());
00867         else
00868             EV << "[BasePastry::handleRequestMessage() @ " << thisNode.getAddress()
00869             << " (" << thisNode.getKey().toString(16) << ")]\n"
00870             << "    received state request before reaching"
00871             << " READY state, dropping message!"
00872             << endl;
00873         delete msg;
00874     }
00875     else if (PASTRY_REQ_LEAFSET) {
00876         RECORD_STATS(leafsetReqReceived++; leafsetReqBytesReceived +=
00877             msg->getByteLength());
00878         if (state == READY) {
00879             sendLeafset(msg->getSendStateTo());
00880         }
00881         else
00882             EV << "[BasePastry::handleRequestMessage() @ " << thisNode.getAddress()
00883             << " (" << thisNode.getKey().toString(16) << ")]\n"
00884             << "    received leafset request before reaching"
00885             << " READY state, dropping message!"
00886             << endl;
00887         delete msg;
00888     }
00889 
00890 }
00891 
00892 void BasePastry::handleLeafsetMessage(PastryLeafsetMessage* msg, bool mergeSender)
00893 {
00894     uint32_t lsSize = msg->getLeafSetArraySize();
00895     PastryStateMessage* stateMsg;
00896 
00897     stateMsg = new PastryStateMessage("STATE");
00898     stateMsg->setTimestamp(msg->getTimestamp());
00899     stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00900     stateMsg->setStatType(MAINTENANCE_STAT);
00901     stateMsg->setSender(msg->getSender());
00902     stateMsg->setLeafSetArraySize(lsSize);
00903     stateMsg->setNeighborhoodSetArraySize(0);
00904     stateMsg->setRoutingTableArraySize(0);
00905 
00906     for (uint32_t i = 0; i < lsSize; i++) {
00907         stateMsg->setLeafSet(i, msg->getLeafSet(i));
00908     }
00909 
00910     if (mergeSender) {
00911         stateMsg->setLeafSetArraySize(lsSize+1);
00912         stateMsg->setLeafSet(lsSize, msg->getSender());
00913     }
00914 
00915     handleStateMessage(stateMsg);
00916     delete msg;
00917 }
00918 
00919 bool BasePastry::isSiblingFor(const NodeHandle& node,
00920                               const OverlayKey& key,
00921                               int numSiblings,
00922                               bool* err)
00923 {
00924     if (key.isUnspecified())
00925         error("Pastry::isSiblingFor(): key is unspecified!");
00926 
00927     if ((numSiblings == 1) && (node == thisNode)) {
00928         if (leafSet->isClosestNode(key)) {
00929             *err = false;
00930             return true;
00931         } else {
00932             *err = false;
00933             return false;
00934         }
00935     }
00936 
00937     NodeVector* result =  leafSet->createSiblingVector(key, numSiblings);
00938 
00939     if (result == NULL) {
00940         *err = true;
00941         return false;
00942     }
00943 
00944     if (result->contains(node.getKey())) {
00945         delete result;
00946         *err = false;
00947         return true;
00948     } else {
00949         delete result;
00950         *err = true;
00951         return false;
00952     }
00953 
00954     /*
00955       const NodeHandle& dest = leafSet->getDestinationNode(key);
00956       if (!dest.isUnspecified()) {
00957       *err = false;
00958       return true;
00959       } else {
00960 
00961       *err = true;
00962       return false;
00963       }
00964     */
00965 }
00966 
00967 
00968 void BasePastry::handleAppMessage(BaseOverlayMessage* msg)
00969 {
00970     delete msg;
00971 }
00972 
00973 void BasePastry::updateTooltip()
00974 {
00975     if (ev.isGUI()) {
00976         std::stringstream ttString;
00977 
00978         // show our predecessor and successor in tooltip
00979         ttString << leafSet->getPredecessor() << endl << thisNode << endl
00980                  << leafSet->getSuccessor();
00981 
00982         getParentModule()->getParentModule()->getDisplayString().
00983             setTagArg("tt", 0, ttString.str().c_str());
00984         getParentModule()->getDisplayString().
00985             setTagArg("tt", 0, ttString.str().c_str());
00986         getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
00987 
00988         // draw arrows:
00989         showOverlayNeighborArrow(leafSet->getSuccessor(), true,
00990                                  "m=m,50,0,50,0;ls=red,1");
00991         showOverlayNeighborArrow(leafSet->getPredecessor(), false,
00992                                  "m=m,50,100,50,100;ls=green,1");
00993 
00994     }
00995 }
00996 
00997 BasePastry::~BasePastry()
00998 {
00999     cancelAndDelete(joinTimeout);
01000 
01001     purgeVectors();
01002 }
01003 
01004 void BasePastry::finishOverlay()
01005 {
01006     // remove this node from the bootstrap list
01007     if (!thisNode.getKey().isUnspecified()) bootstrapList->removeBootstrapNode(thisNode);
01008 
01009     // collect statistics
01010     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01011     if (time < GlobalStatistics::MIN_MEASURED) return;
01012 
01013     // join statistics
01014     //if (joinTries > joins)
01015         //std::cout << thisNode << " jt:" << joinTries << " j:" << joins << " jts:"
01016         //          << joinTimeout->isScheduled() << " rws:" << readyWait->isScheduled()
01017         //          << " state:" << state << " time:" << time << std::endl;
01018     // join is on the way...
01019     if (joinTries > 0 && joinTimeout->isScheduled()) joinTries--;
01020     if (joinTries > 0) {
01021         globalStatistics->addStdDev("Pastry: join success ratio", (double)joins / (double)joinTries);
01022         globalStatistics->addStdDev("Pastry: join tries", joinTries);
01023     } else if (state == READY) {
01024         // nodes has joined in init-/transition-phase
01025         globalStatistics->addStdDev("Pastry: join success ratio", 1);
01026         globalStatistics->addStdDev("Pastry: join tries", 1);
01027     } else {
01028         globalStatistics->addStdDev("Pastry: join success ratio", 0);
01029         globalStatistics->addStdDev("Pastry: join tries", 1);
01030     }
01031 
01032     globalStatistics->addStdDev("Pastry: joins with missing replies from routing path/s",
01033                                 joinPartial / time);
01034     globalStatistics->addStdDev("Pastry: JOIN Messages seen/s", joinSeen / time);
01035     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages seen/s", joinBytesSeen / time);
01036     globalStatistics->addStdDev("Pastry: JOIN Messages received/s", joinReceived / time);
01037     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages received/s",
01038                                 joinBytesReceived / time);
01039     globalStatistics->addStdDev("Pastry: JOIN Messages sent/s", joinSent / time);
01040     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages sent/s", joinBytesSent / time);
01041     globalStatistics->addStdDev("Pastry: STATE Messages sent/s", stateSent / time);
01042     globalStatistics->addStdDev("Pastry: bytes of STATE Messages sent/s", stateBytesSent / time);
01043     globalStatistics->addStdDev("Pastry: STATE Messages received/s", stateReceived / time);
01044     globalStatistics->addStdDev("Pastry: bytes of STATE Messages received/s",
01045                                 stateBytesReceived / time);
01046     globalStatistics->addStdDev("Pastry: REPAIR Requests sent/s", repairReqSent / time);
01047     globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests sent/s",
01048                                 repairReqBytesSent / time);
01049     globalStatistics->addStdDev("Pastry: REPAIR Requests received/s", repairReqReceived / time);
01050     globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests received/s",
01051                                 repairReqBytesReceived / time);
01052     globalStatistics->addStdDev("Pastry: STATE Requests sent/s", stateReqSent / time);
01053     globalStatistics->addStdDev("Pastry: bytes of STATE Requests sent/s", stateReqBytesSent / time);
01054     globalStatistics->addStdDev("Pastry: STATE Requests received/s", stateReqReceived / time);
01055     globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01056                                 stateReqBytesReceived / time);
01057 
01058     globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01059                                 stateReqBytesReceived / time);
01060 
01061     globalStatistics->addStdDev("Pastry: total number of lookups", totalLookups);
01062     globalStatistics->addStdDev("Pastry: responsible lookups", responsibleLookups);
01063     globalStatistics->addStdDev("Pastry: lookups in routing table", routingTableLookups);
01064     globalStatistics->addStdDev("Pastry: lookups using closerNode()", closerNodeLookups);
01065     globalStatistics->addStdDev("Pastry: lookups using closerNode() with result from "
01066                                 "neighborhood set", closerNodeLookupsFromNeighborhood);
01067     globalStatistics->addStdDev("Pastry: LEAFSET Requests sent/s", leafsetReqSent / time);
01068     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Requests sent/s", leafsetReqBytesSent / time);
01069     globalStatistics->addStdDev("Pastry: LEAFSET Requests received/s", leafsetReqReceived / time);
01070     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Requests received/s",
01071                                 leafsetReqBytesReceived / time);
01072     globalStatistics->addStdDev("Pastry: LEAFSET Messages sent/s", leafsetSent / time);
01073     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Messages sent/s", leafsetBytesSent / time);
01074     globalStatistics->addStdDev("Pastry: LEAFSET Messages received/s", leafsetReceived / time);
01075     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Messages received/s",
01076                                 leafsetBytesReceived / time);
01077     globalStatistics->addStdDev("Pastry: ROUTING TABLE Requests sent/s", routingTableReqSent / time);
01078     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Requests sent/s", routingTableReqBytesSent / time);
01079     globalStatistics->addStdDev("Pastry: ROUTING TABLE Requests received/s", routingTableReqReceived / time);
01080     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Requests received/s",
01081                                 routingTableReqBytesReceived / time);
01082     globalStatistics->addStdDev("Pastry: ROUTING TABLE Messages sent/s", routingTableSent / time);
01083     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Messages sent/s", routingTableBytesSent / time);
01084     globalStatistics->addStdDev("Pastry: ROUTING TABLE Messages received/s", routingTableReceived / time);
01085     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Messages received/s",
01086                                 routingTableBytesReceived / time);
01087 
01088 }
01089 
01090 int BasePastry::getMaxNumSiblings()
01091 {
01092     return (int)floor(numberOfLeaves / 2.0);
01093 }
01094 
01095 int BasePastry::getMaxNumRedundantNodes()
01096 {
01097     return (int)floor(numberOfLeaves);
01098 }
01099 
01100 NodeVector* BasePastry::findNode(const OverlayKey& key,
01101                                  int numRedundantNodes,
01102                                  int numSiblings,
01103                                  BaseOverlayMessage* msg)
01104 {
01105     if ((numRedundantNodes > getMaxNumRedundantNodes()) ||
01106         (numSiblings > getMaxNumSiblings())) {
01107 
01108         opp_error("(Pastry::findNode()) numRedundantNodes or numSiblings "
01109                   "too big!");
01110     }
01111     RECORD_STATS(totalLookups++);
01112 
01113     NodeVector* nextHops = new NodeVector(numRedundantNodes);
01114 
01115     if (state != READY) {
01116         return nextHops;
01117     } else if (key.isUnspecified() || leafSet->isClosestNode(key)) {
01118         RECORD_STATS(responsibleLookups++);
01119         nextHops->add(thisNode);
01120     } else {
01121         const NodeHandle* next = &(leafSet->getDestinationNode(key));
01122 
01123         if (next->isUnspecified()) {
01124             next = &(routingTable->lookupNextHop(key));
01125             if (!next->isUnspecified()) {
01126                 RECORD_STATS(routingTableLookups++);
01127             }
01128         } else {
01129             RECORD_STATS(responsibleLookups++);
01130         }
01131 
01132         if (next->isUnspecified()) {
01133             RECORD_STATS(closerNodeLookups++);
01134             // call findCloserNode() on all state objects
01135             if (optimizeLookup) {
01136                 const NodeHandle* tmp;
01137                 next = &(routingTable->findCloserNode(key, true));
01138                 tmp = &(neighborhoodSet->findCloserNode(key, true));
01139 
01140                 if ((! tmp->isUnspecified()) &&
01141                     (leafSet->isCloser(*tmp, key, *next))) {
01142                     RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01143                     next = tmp;
01144                 }
01145 
01146                 tmp = &(leafSet->findCloserNode(key, true));
01147                 if ((! tmp->isUnspecified()) &&
01148                     (leafSet->isCloser(*tmp, key, *next))) {
01149                     RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01150                     next = tmp;
01151                 }
01152             } else {
01153                 next = &(routingTable->findCloserNode(key));
01154 
01155                 if (next->isUnspecified()) {
01156                     RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01157                     next = &(neighborhoodSet->findCloserNode(key));
01158                 }
01159 
01160                 if (next->isUnspecified()) {
01161                     RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01162                     next = &(leafSet->findCloserNode(key));
01163                 }
01164             }
01165         }
01166 
01167         iterativeJoinHook(msg, !next->isUnspecified());
01168 
01169         if (!next->isUnspecified()) {
01170             nextHops->add(*next);
01171         }
01172     }
01173 
01174     bool err;
01175 
01176     // if we're a sibling, return all numSiblings
01177     if ((numSiblings >= 0) && isSiblingFor(thisNode, key, numSiblings, &err)) {
01178         if (err == false) {
01179             delete nextHops;
01180             return  leafSet->createSiblingVector(key, numSiblings);
01181         }
01182     }
01183 
01184     if (/*(nextHops->size() > 0) &&*/ (numRedundantNodes > 1)) {
01185 
01186         //memleak... comp should be a ptr and deleted in NodeVector::~NodeVector()...
01187         //KeyDistanceComparator<KeyRingMetric>* comp =
01188         //    new KeyDistanceComparator<KeyRingMetric>( key );
01189 
01190         KeyDistanceComparator<KeyRingMetric> comp(key);
01191         //KeyDistanceComparator<KeyPrefixMetric> comp(key);
01192         NodeVector* additionalHops = new NodeVector( numRedundantNodes, &comp );
01193 
01194         routingTable->findCloserNodes(key, additionalHops);
01195         leafSet->findCloserNodes(key, additionalHops);
01196         neighborhoodSet->findCloserNodes(key, additionalHops);
01197 
01198         if (useRegularNextHop && (nextHops->size() > 0) &&
01199             (*additionalHops)[0] != (*nextHops)[0]) {
01200             for (uint32_t i = 0; i < additionalHops->size(); i++) {
01201                 if ((*additionalHops)[i] != (*nextHops)[0])
01202                     nextHops->push_back((*additionalHops)[i]);
01203             }
01204             delete additionalHops;
01205         } else {
01206             delete nextHops;
01207             return additionalHops;
01208         }
01209     }
01210     return nextHops;
01211 }
01212 AbstractLookup* BasePastry::createLookup(RoutingType routingType,
01213                                          const BaseOverlayMessage* msg,
01214                                          const cObject* dummy,
01215                                          bool appLookup)
01216 {
01217     assert(dummy == NULL);
01218     PastryFindNodeExtData* findNodeExt =
01219         new PastryFindNodeExtData("findNodeExt");
01220 
01221     if (msg) {
01222         const PastryMessage* pmsg =
01223             dynamic_cast<const PastryMessage*>(msg->getEncapsulatedPacket());
01224         if ((pmsg) && (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN)) {
01225             const PastryJoinMessage* jmsg =
01226                 check_and_cast<const PastryJoinMessage*>(pmsg);
01227             findNodeExt->setSendStateTo(jmsg->getSendStateTo());
01228             findNodeExt->setJoinHopCount(1);
01229         }
01230     }
01231     findNodeExt->setBitLength(PASTRYFINDNODEEXTDATA_L);
01232 
01233     AbstractLookup* newLookup = BaseOverlay::createLookup(routingType,
01234                                                           msg, findNodeExt,
01235                                                           appLookup);
01236 
01237     delete findNodeExt;
01238     return newLookup;
01239 }
01240 
01241 bool stateMsgIsSmaller(const PastryStateMsgHandle& hnd1,
01242                        const PastryStateMsgHandle& hnd2)
01243 {
01244     return (hnd1.msg->getJoinHopCount() < hnd2.msg->getJoinHopCount());
01245 }
01246 
01247 
01248 std::ostream& operator<<(std::ostream& os, const PastryStateMsgProximity& pr)
01249 {
01250     os << "PastryStateMsgProximity {" << endl;
01251     os << "  pr_rt {" << endl;
01252     for (std::vector<simtime_t>::const_iterator i = pr.pr_rt.begin();
01253          i != pr.pr_rt.end(); ++i) {
01254         os << "    " << *i << endl;
01255     }
01256     os << "  }" << endl;
01257     os << "  pr_ls {" << endl;
01258     for (std::vector<simtime_t>::const_iterator i = pr.pr_ls.begin();
01259          i != pr.pr_ls.end(); ++i) {
01260         os << "    " << *i << endl;
01261     }
01262     os << "  }" << endl;
01263     os << "  pr_ns {" << endl;
01264     for (std::vector<simtime_t>::const_iterator i = pr.pr_ns.begin();
01265          i != pr.pr_ns.end(); ++i) {
01266         os << "    " << *i << endl;
01267     }
01268     os << "  }" << endl;
01269     os << "}" << endl;
01270     return os;
01271 }
01272 
01273 
01274 //virtual public: distance metric
01275 OverlayKey BasePastry::distance(const OverlayKey& x,
01276                                 const OverlayKey& y,
01277                                 bool useAlternative) const
01278 {
01279     if (!useAlternative) return KeyRingMetric().distance(x, y);
01280     return KeyPrefixMetric().distance(x, y);
01281 }
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3