Pastry.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 
00026 #include <cassert>
00027 
00028 #include <IPAddressResolver.h>
00029 #include <IPvXAddress.h>
00030 #include <IInterfaceTable.h>
00031 #include <IPv4InterfaceData.h>
00032 #include <RpcMacros.h>
00033 #include <InitStages.h>
00034 #include <GlobalStatistics.h>
00035 
00036 #include "Pastry.h"
00037 
00038 
00039 Define_Module(Pastry);
00040 
00041 Pastry::~Pastry()
00042 {
00043     // destroy self timer messages
00044     cancelAndDelete(readyWait);
00045     cancelAndDelete(joinUpdateWait);
00046     cancelAndDelete(secondStageWait);
00047     cancelAndDelete(ringCheck);
00048     if (useDiscovery) cancelAndDelete(discoveryTimeout);
00049     if (routingTableMaintenanceInterval > 0) cancelAndDelete(repairTaskTimeout);
00050 }
00051 
00052 void Pastry::initializeOverlay(int stage)
00053 {
00054     if ( stage != MIN_STAGE_OVERLAY )
00055         return;
00056 
00057     // Pastry provides KBR services
00058     kbr = true;
00059 
00060     baseInit();
00061 
00062     useDiscovery = par("useDiscovery");
00063     pingBeforeSecondStage = par("pingBeforeSecondStage");
00064     secondStageInterval = par("secondStageWait");
00065     discoveryTimeoutAmount = par("discoveryTimeoutAmount");
00066     routingTableMaintenanceInterval = par("repairTaskTimeoutAmount"); // TODO parameter into derived classes
00067     sendStateAtLeafsetRepair = par("sendStateAtLeafsetRepair");
00068     ringCheckInterval = par("ringCheckInterval");
00069     partialJoinPath = par("partialJoinPath");
00070     readyWaitAmount = par("readyWait");
00071 
00072     overrideOldPastry = par("overrideOldPastry");
00073     overrideNewPastry = par("overrideNewPastry");
00074 
00075     if (overrideOldPastry) {
00076         //useSecondStage = true;
00077         //secondStageInterval = ???;
00078         useDiscovery = false;
00079         sendStateAtLeafsetRepair = true;
00080         routingTableMaintenanceInterval = 0;
00081     }
00082 
00083     if (overrideNewPastry) {
00084         //useSecondStage = false;
00085         secondStageInterval = 0;
00086         useDiscovery = true;
00087         discoveryTimeoutAmount = 0.4;
00088         routingTableMaintenanceInterval = 60;
00089         sendStateAtLeafsetRepair = false;
00090     }
00091 
00092     joinTimeout = new cMessage("joinTimeout");
00093     readyWait = new cMessage("readyWait");
00094     secondStageWait = new cMessage("secondStageWait");
00095     joinUpdateWait = new cMessage("joinUpdateWait");
00096     ringCheck = new cMessage("ringCheck");
00097 
00098     if (useDiscovery) discoveryTimeout = new cMessage("discoveryTimeout");
00099     if (routingTableMaintenanceInterval > 0) repairTaskTimeout =
00100         new cMessage("repairTaskTimeout");
00101 
00102     sendPullFlag = false;
00103     updateCounter = 0;
00104 }
00105 
00106 void Pastry::joinOverlay()
00107 {
00108     changeState(INIT);
00109 
00110     if (bootstrapNode.isUnspecified()) {
00111         // no existing pastry network -> first node of a new one
00112         changeState(READY);
00113     } else {
00114         // join existing pastry network
00115         nearNode = bootstrapNode;
00116         if (useDiscovery) changeState(DISCOVERY);
00117         else changeState(JOINING_2);
00118     }
00119 }
00120 
00121 void Pastry::changeState(int toState)
00122 {
00123     if (ringCheck->isScheduled()) cancelEvent(ringCheck);
00124     if (readyWait->isScheduled()) cancelEvent(readyWait);
00125     baseChangeState(toState);
00126 
00127     switch (toState) {
00128     case INIT:
00129         cancelAllRpcs();
00130         purgeVectors();
00131         break;
00132 
00133     case DISCOVERY:
00134         state = DISCOVERY;
00135         //nearNode = bootstrapNode;
00136         nearNodeRtt = MAXTIME;
00137         pingNode(bootstrapNode, discoveryTimeoutAmount, 0,
00138                  NULL, "PING bootstrapNode in discovery mode",
00139                  NULL, -1, UDP_TRANSPORT); //TODO
00140         sendRequest(bootstrapNode, PASTRY_REQ_LEAFSET);
00141         depth = -1;
00142 
00143         break;
00144 
00145     case JOINING_2:
00146 
00147         joinHopCount = 0;
00148 
00149         {
00150             PastryJoinMessage* msg = new PastryJoinMessage("JOIN-Request");
00151             //TODO add timestamp to join msg
00152             msg->setPastryMsgType(PASTRY_MSG_JOIN);
00153             msg->setStatType(MAINTENANCE_STAT);
00154             //msg->setJoinHopCount(1);
00155             msg->setSendStateTo(thisNode);
00156             msg->setBitLength(PASTRYJOIN_L(msg));
00157             RECORD_STATS(joinSent++; joinBytesSent += msg->getByteLength());
00158             std::vector<TransportAddress> sourceRoute;
00159             sourceRoute.push_back(nearNode);
00160             sendToKey(thisNode.getKey(), msg, 0/*1*/, sourceRoute);
00161 
00162         }
00163 
00164 
00165         break;
00166 
00167     case READY:
00168         if (ringCheckInterval > 0) {
00169             scheduleAt(simTime()+ringCheckInterval, ringCheck);
00170         }
00171 
00172         // determine list of all known nodes as notifyList
00173         notifyList.clear();
00174         leafSet->dumpToVector(notifyList);
00175         routingTable->dumpToVector(notifyList);
00176         sort(notifyList.begin(), notifyList.end());
00177         notifyList.erase(unique(notifyList.begin(), notifyList.end()),
00178                          notifyList.end());
00179 
00180         // schedule update
00181         cancelEvent(joinUpdateWait);
00182         scheduleAt(simTime() + sendStateWaitAmount, joinUpdateWait);
00183 
00184         // schedule second stage
00185         if (secondStageInterval > 0) {
00186             cancelEvent(secondStageWait);
00187             scheduleAt(simTime() + secondStageInterval, secondStageWait);
00188         }
00189 
00190         // schedule routing table maintenance task
00191         if (routingTableMaintenanceInterval > 0) {
00192             cancelEvent(repairTaskTimeout);
00193             scheduleAt(simTime() + routingTableMaintenanceInterval, repairTaskTimeout);
00194             //leaf2ask = NULL;
00195         }
00196 
00197         break;
00198     }
00199 }
00200 
00201 void Pastry::handleTimerEvent(cMessage* msg)
00202 {
00203 
00204     if (msg->isName("joinTimeout")) {
00205         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00206         << " (" << thisNode.getKey().toString(16) << ")]\n"
00207         << "    timeout expired, restarting..."
00208         << endl;
00209         //std::cout << simTime() << " " << thisNode.getAddress() << " " << stReceived.size() <<" Pastry: join timeout expired, restarting..." << std::endl;
00210         join();
00211     } else if (msg->isName("readyWait")) {
00212         if (partialJoinPath) {
00213             RECORD_STATS(joinPartial++);
00214             sort(stReceived.begin(), stReceived.end(), stateMsgIsSmaller);
00215 
00216             // start pinging the nodes found in the first state message:
00217             stReceivedPos = stReceived.begin();
00218             stateCache = *stReceivedPos;
00219             EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00220                << " (" << thisNode.getKey().toString(16) << ")]\n"
00221                << "    joining despite some missing STATE messages."
00222                << endl;
00223             processState();
00224             /*if (pingBeforeSecondStage ||
00225                 stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_STD) {
00226                 pingNodes();
00227             } else {
00228                 mergeState(); //JOINING / stateCache
00229                 endProcessingState();
00230                 //TODO -> READY
00231             }*/
00232         } else {
00233             EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00234                << " (" << thisNode.getKey().toString(16) << ")]\n"
00235                << "    timeout waiting for missing state messages in JOIN state, restarting..."
00236                << endl;
00237             //std::cout << thisNode.getAddress() << "Pastry: timeout waiting for missing state messages in JOIN "
00238             //                "state, restarting..." << std::endl;
00239             join();
00240         }
00241     } else if (msg->isName("joinUpdateWait")) {
00242         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00243            << " (" << thisNode.getKey().toString(16) << ")]\n"
00244            << "    sending state updates to all nodes."
00245            << endl;
00246         doJoinUpdate();
00247     } else if (msg->isName("secondStageWait")) {
00248         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00249            << " (" << thisNode.getKey().toString(16) << ")]\n"
00250            << "    sending STATE requests to all nodes in second stage of initialization."
00251            << endl;
00252         doSecondStage();
00253     } else if (msg->isName("ringCheck")) {
00254         if (state == READY) {
00255             // ping direct neighbors on the ring:
00256             const NodeHandle& pred = leafSet->getPredecessor();
00257             const NodeHandle& succ = leafSet->getSuccessor();
00258             if (! pred.isUnspecified()) {
00259                 pingNode(pred, timeoutPing, pingRetries,
00260                          NULL, "PING ring check");
00261             }
00262             if (! succ.isUnspecified()) {
00263                 pingNode(succ, timeoutPing, pingRetries,
00264                          NULL, "PING ring check");
00265             }
00266         }
00267         scheduleAt(simTime() + ringCheckInterval, ringCheck);
00268     } else if (msg->isName("sendStateWait")) {
00269         PastrySendState* sendStateMsg = check_and_cast<PastrySendState*>(msg);
00270 
00271         std::vector<PastrySendState*>::iterator pos =
00272             std::find(sendStateWait.begin(), sendStateWait.end(),
00273                       sendStateMsg);
00274         if (pos != sendStateWait.end()) sendStateWait.erase(pos);
00275 
00276         sendStateTables(sendStateMsg->getDest());
00277         delete sendStateMsg;
00278     } else if (msg->isName("discoveryTimeout")) {
00279         if ((depth == 0) && (nearNodeImproved)) {
00280             depth++; //repeat last step if closer node was found
00281         }
00282         if ((depth == 0) || (pingedNodes < 1)) {
00283             changeState(JOINING_2);
00284         } else {
00285             PastryRoutingRowRequestMessage* msg = new PastryRoutingRowRequestMessage("ROWREQ");
00286             msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00287             msg->setStatType(MAINTENANCE_STAT);
00288             msg->setSendStateTo(thisNode);
00289             msg->setRow(depth);
00290             msg->setBitLength(PASTRYRTREQ_L(msg));
00291             RECORD_STATS(routingTableReqSent++; routingTableReqBytesSent += msg->getByteLength());
00292             sendMessageToUDP(nearNode, msg);
00293         }
00294     } else if (msg->isName("repairTaskTimeout")) {
00295         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00296            << " (" << thisNode.getKey().toString(16) << ")]\n"
00297            << "    starting routing table maintenance"
00298            << endl;
00299         doRoutingTableMaintenance();
00300         scheduleAt(simTime() + routingTableMaintenanceInterval, repairTaskTimeout);
00301     }
00302 }
00303 
00304 void Pastry::handleUDPMessage(BaseOverlayMessage* msg)
00305 {
00306     PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg);
00307     uint32_t type = pastryMsg->getPastryMsgType();
00308 
00309     if (debugOutput) {
00310         EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00311            << " (" << thisNode.getKey().toString(16) << ")]\n"
00312            << "    incoming message of type ";
00313         switch(type) {
00314         case PASTRY_MSG_STD:
00315             EV << "PASTRY_MSG_STD";
00316             break;
00317         case PASTRY_MSG_JOIN:
00318             EV << "PASTRY_MSG_JOIN";
00319             break;
00320         case PASTRY_MSG_STATE:
00321             EV << "PASTRY_MSG_STATE";
00322             break;
00323         case PASTRY_MSG_LEAFSET:
00324             EV << "PASTRY_MSG_LEAFSET";
00325             break;
00326         case PASTRY_MSG_ROWREQ:
00327             EV << "PASTRY_MSG_ROWREQ";
00328             break;
00329         case PASTRY_MSG_RROW:
00330             EV << "PASTRY_MSG_RROW";
00331             break;
00332         case PASTRY_MSG_REQ:
00333             EV << "PASTRY_MSG_REQ";
00334             break;
00335         default:
00336             EV << "UNKNOWN (" << type <<")";
00337             break;
00338         }
00339         EV << endl;
00340     }
00341 
00342     switch (type) {
00343     case PASTRY_MSG_STD:
00344         opp_error("Pastry received PastryMessage of unknown type!");
00345         break;
00346 
00347     case PASTRY_MSG_JOIN: {
00348         PastryJoinMessage* jmsg =
00349             check_and_cast<PastryJoinMessage*>(pastryMsg);
00350         RECORD_STATS(joinReceived++; joinBytesReceived +=
00351                      jmsg->getByteLength());
00352         if (state != READY) {
00353             if (jmsg->getSendStateTo() == thisNode) {
00354                 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00355                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00356                    << "    PastryJoinMessage received by originator!"
00357                    << endl;
00358             } else {
00359                 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00360                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00361                    << "    received join message before reaching "
00362                    << "READY state, dropping message!"
00363                    << endl;
00364             }
00365         }
00366         else if (jmsg->getSendStateTo() == thisNode) {
00367             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00368                << " (" << thisNode.getKey().toString(16) << ")]\n"
00369                << "    PastryJoinMessage gets dropped because it is "
00370                << "outdated and has been received by originator!"
00371                << endl;
00372         } else {
00373             OverlayCtrlInfo* overlayCtrlInfo
00374                 = check_and_cast<OverlayCtrlInfo*>(jmsg->getControlInfo());
00375 
00376             uint32_t joinHopCount =  overlayCtrlInfo->getHopCount();
00377             if ((joinHopCount > 1) &&
00378                 ((defaultRoutingType == ITERATIVE_ROUTING) ||
00379                  (defaultRoutingType == EXHAUSTIVE_ITERATIVE_ROUTING)))
00380                  joinHopCount--;
00381 
00382             // remove node from state if it is rejoining
00383             handleFailedNode(jmsg->getSendStateTo());
00384 
00385             sendStateTables(jmsg->getSendStateTo(),
00386                             PASTRY_STATE_JOIN, joinHopCount, true);
00387         }
00388 
00389         delete jmsg;
00390     }
00391         break;
00392 
00393     case PASTRY_MSG_LEAFSET: {
00394         PastryLeafsetMessage* lmsg =
00395             check_and_cast<PastryLeafsetMessage*>(pastryMsg);
00396         RECORD_STATS(leafsetReceived++; leafsetBytesReceived +=
00397             lmsg->getByteLength());
00398 
00399         if (state == DISCOVERY) {
00400             uint32_t lsSize = lmsg->getLeafSetArraySize();
00401             const NodeHandle* node;
00402             pingedNodes = 0;
00403 
00404             for (uint32_t i = 0; i < lsSize; i++) {
00405                 node = &(lmsg->getLeafSet(i));
00406                 // unspecified nodes not considered
00407                 if ( !(node->isUnspecified()) ) {
00408                     pingNode(*node, discoveryTimeoutAmount, 0,
00409                              NULL, "PING received leafs for nearest node",
00410                              NULL, -1, UDP_TRANSPORT);//TODO
00411                     pingedNodes++;
00412                }
00413             }
00414 
00415             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00416                << " (" << thisNode.getKey().toString(16) << ")]\n"
00417                << "    received leafset, waiting for pings"
00418               << endl;
00419             if (discoveryTimeout->isScheduled()) cancelEvent(discoveryTimeout);
00420             scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout);
00421             delete lmsg;
00422         }
00423 
00424         else if (state == READY) {
00425             handleLeafsetMessage(lmsg, false);
00426 
00427         } else {
00428             delete lmsg;
00429         }
00430     }
00431         break;
00432 
00433     case PASTRY_MSG_ROWREQ: {
00434         PastryRoutingRowRequestMessage* rtrmsg =
00435             check_and_cast<PastryRoutingRowRequestMessage*>(pastryMsg);
00436         RECORD_STATS(routingTableReqReceived++; routingTableReqBytesReceived +=
00437             rtrmsg->getByteLength());
00438         if (state == READY)
00439             if (rtrmsg->getRow() == -1)
00440                 sendRoutingRow(rtrmsg->getSendStateTo(), routingTable->getLastRow());
00441                 else if (rtrmsg->getRow() > routingTable->getLastRow())
00442                     EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00443                        << " (" << thisNode.getKey().toString(16) << ")]\n"
00444                        << "    received request for nonexistent routing"
00445                        << "table row, dropping message!"
00446                        << endl;
00447                 else sendRoutingRow(rtrmsg->getSendStateTo(), rtrmsg->getRow());
00448         else
00449             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00450                << " (" << thisNode.getKey().toString(16) << ")]\n"
00451                << "    received routing table request before reaching "
00452                << "READY state, dropping message!"
00453                << endl;
00454         delete rtrmsg;
00455     }
00456         break;
00457 
00458     case PASTRY_MSG_RROW: {
00459         PastryRoutingRowMessage* rtmsg =
00460             check_and_cast<PastryRoutingRowMessage*>(pastryMsg);
00461         RECORD_STATS(routingTableReceived++; routingTableBytesReceived +=
00462             rtmsg->getByteLength());
00463 
00464         if (state == DISCOVERY) {
00465             uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize();
00466             const NodeHandle* node;
00467             if (depth == -1) {
00468                 depth = rtmsg->getRow();
00469             }
00470             pingedNodes = 0;
00471             nearNodeImproved = false;
00472 
00473             if (depth > 0) {
00474                 for (uint32_t i = 0; i < nodesPerRow; i++) {
00475                     node = &(rtmsg->getRoutingTable(i));
00476                     // unspecified nodes not considered
00477                     if ( !(node->isUnspecified()) ) {
00478                         // we look for best connection here, so Timeout is short and there are no retries
00479                         pingNode(*node, discoveryTimeoutAmount, 0, NULL,
00480                                  "PING received routing table for nearest node",
00481                                  NULL, -1, UDP_TRANSPORT); //TODO
00482                         pingedNodes++;
00483                     }
00484                 }
00485                 depth--;
00486             }
00487             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00488                << " (" << thisNode.getKey().toString(16) << ")]\n"
00489                << "    received routing table, waiting for pings"
00490                << endl;
00491             if (discoveryTimeout->isScheduled()) {
00492                 cancelEvent(discoveryTimeout);
00493             }
00494             scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout);
00495         }
00496 
00497         else if (state == READY) {
00498 
00499             uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize();
00500             PastryStateMessage* stateMsg;
00501 
00502             stateMsg = new PastryStateMessage("STATE");
00503             stateMsg->setTimestamp(rtmsg->getTimestamp());
00504             stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00505             stateMsg->setStatType(MAINTENANCE_STAT);
00506             stateMsg->setSender(rtmsg->getSender());
00507             stateMsg->setLeafSetArraySize(0);
00508             stateMsg->setNeighborhoodSetArraySize(0);
00509             stateMsg->setRoutingTableArraySize(nodesPerRow);
00510 
00511             for (uint32_t i = 0; i < nodesPerRow; i++) {
00512                 stateMsg->setRoutingTable(i, rtmsg->getRoutingTable(i));
00513             }
00514 
00515             handleStateMessage(stateMsg);
00516         }
00517 
00518         delete rtmsg;
00519     }
00520         break;
00521 
00522     case PASTRY_MSG_REQ: {
00523         PastryRequestMessage* lrmsg =
00524             check_and_cast<PastryRequestMessage*>(pastryMsg);
00525         handleRequestMessage(lrmsg);
00526     }
00527         break;
00528 
00529     case PASTRY_MSG_STATE: {
00530         PastryStateMessage* stateMsg =
00531             check_and_cast<PastryStateMessage*>(msg);
00532         RECORD_STATS(stateReceived++; stateBytesReceived +=
00533                      stateMsg->getByteLength());
00534         handleStateMessage(stateMsg);
00535     }
00536         break;
00537     }
00538 }
00539 
00540 void Pastry::doJoinUpdate(void)
00541 {
00542     // send "update" state message to all nodes who sent us their state
00543     // during INIT, remove these from notifyList so they don't get our
00544     // state twice
00545     std::vector<TransportAddress>::iterator nListPos;
00546     if (!stReceived.empty()) {
00547         for (std::vector<PastryStateMsgHandle>::iterator it =
00548                  stReceived.begin(); it != stReceived.end(); ++it) {
00549             simtime_t timestamp = it->msg->getTimestamp();
00550             sendStateTables(it->msg->getSender(), PASTRY_STATE_UPDATE,
00551                             &timestamp);
00552             nListPos = find(notifyList.begin(), notifyList.end(),
00553                             it->msg->getSender());
00554             if (nListPos != notifyList.end()) {
00555                 notifyList.erase(nListPos);
00556             }
00557             delete it->msg;
00558             delete it->prox;
00559         }
00560         stReceived.clear();
00561     }
00562 
00563     // send a normal STATE message to all remaining known nodes
00564     for (std::vector<TransportAddress>::iterator it =
00565              notifyList.begin(); it != notifyList.end(); it++) {
00566         if (*it != thisNode) sendStateTables(*it, PASTRY_STATE_JOINUPDATE);
00567     }
00568     notifyList.clear();
00569 
00570     updateTooltip();
00571 }
00572 
00573 void Pastry::doSecondStage(void)
00574 {
00575     getParentModule()->getParentModule()->bubble("entering SECOND STAGE");
00576 
00577     // probe nodes in local state
00578     if (leafSet->isValid()) {
00579         PastryStateMessage* stateMsg = new PastryStateMessage("STATE");
00580         stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00581         stateMsg->setStatType(MAINTENANCE_STAT);
00582         stateMsg->setPastryStateMsgType(PASTRY_STATE_STD);
00583         stateMsg->setSender(thisNode);
00584         routingTable->dumpToStateMessage(stateMsg);
00585         leafSet->dumpToStateMessage(stateMsg);
00586         neighborhoodSet->dumpToStateMessage(stateMsg);
00587         //stateMsg->setBitLength(PASTRYSTATE_L(stateMsg));
00588         PastryStateMsgHandle handle(stateMsg);
00589 
00590         if (!stateCache.msg) {
00591             stateCache = handle;
00592             processState();
00593         } else {
00594             stateCacheQueue.push(handle);
00595             prePing(stateMsg);
00596         }
00597     }
00598 
00599     // "second stage" for locality:
00600     notifyList.clear();
00601     routingTable->dumpToVector(notifyList);
00602     neighborhoodSet->dumpToVector(notifyList);
00603     sort(notifyList.begin(), notifyList.end());
00604     notifyList.erase(unique(notifyList.begin(), notifyList.end()),
00605                      notifyList.end());
00606     for (std::vector<TransportAddress>::iterator it = notifyList.begin();
00607          it != notifyList.end(); it++) {
00608         if (*it == thisNode) continue;
00609         EV << "[Pastry::doSecondStage() @ " << thisNode.getAddress()
00610            << " (" << thisNode.getKey().toString(16) << ")]\n"
00611            << "    second stage: requesting state from " << *it
00612            << endl;
00613         sendRequest(*it, PASTRY_REQ_STATE);
00614     }
00615     notifyList.clear();
00616 }
00617 
00618 bool Pastry::handleFailedNode(const TransportAddress& failed)
00619 {
00620     if (state != READY) {
00621         return false;
00622     }
00623     bool wasValid = leafSet->isValid();
00624 
00625     //std::cout << thisNode.getAddress() << " is handling failed node: " << failed.getAddress() << std::endl;
00626     if (failed.isUnspecified())
00627         opp_error("Pastry::handleFailedNode(): failed is unspecified!");
00628 
00629     const TransportAddress& lsAsk = leafSet->failedNode(failed);
00630     const TransportAddress& rtAsk = routingTable->failedNode(failed);
00631     neighborhoodSet->failedNode(failed);
00632 
00633     if (! lsAsk.isUnspecified()) {
00634         newLeafs();
00635         if (sendStateAtLeafsetRepair) sendRequest(lsAsk, PASTRY_REQ_REPAIR);
00636         else sendRequest(lsAsk, PASTRY_REQ_LEAFSET);
00637     }
00638     if (! rtAsk.isUnspecified() &&
00639         (lsAsk.isUnspecified() ||
00640          lsAsk != rtAsk)) sendRequest(rtAsk, PASTRY_REQ_REPAIR);
00641 
00642     if (wasValid && lsAsk.isUnspecified() && (! leafSet->isValid())) {
00643         EV << "[Pastry::handleFailedNode() @ " << thisNode.getAddress()
00644            << " (" << thisNode.getKey().toString(16) << ")]\n"
00645            << "    lost connection to the network, trying to re-join."
00646            << endl;
00647         //std::cout << thisNode.getAddress() << " Pastry: lost connection to the network, trying to re-join."
00648         //          << std::endl;
00649         join();
00650         return false;
00651     }
00652 
00653     return true;
00654 }
00655 
00656 void Pastry::checkProxCache(void)
00657 {
00658     //std::cout << "checkProxCache()" << stateCache.msg << " " << stateCache.prox << std::endl;
00659     EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00660        << " (" << thisNode.getKey().toString(16) << ")]"
00661        << endl;
00662 
00663     // no cached STATE message?
00664     if (!(stateCache.msg && stateCache.prox)) return;
00665 
00666     // no entries in stateCache.prox?
00667     if (stateCache.prox->pr_rt.empty() &&
00668         stateCache.prox->pr_ls.empty() &&
00669         stateCache.prox->pr_ns.empty())
00670         throw new cRuntimeError("ERROR in Pastry: stateCache.prox empty!");
00671 
00672     /*
00673         //debug
00674         for (uint i = 0; i < stateCache.prox->pr_rt.size(); ++i) {
00675         if (stateCache.prox->pr_rt[i] == -3)
00676             EV << stateCache.msg->getRoutingTable(i).getAddress() << " ";
00677         }
00678         for (uint i = 0; i < stateCache.prox->pr_ls.size(); ++i) {
00679             if (stateCache.prox->pr_ls[i] == -3)
00680                 EV << stateCache.msg->getLeafSet(i).getAddress() << " ";
00681         }
00682         for (uint i = 0; i < stateCache.prox->pr_ns.size(); ++i) {
00683             if (stateCache.prox->pr_ns[i] == -3)
00684                 EV << stateCache.msg->getNeighborhoodSet(i).getAddress() << " ";
00685         }
00686         EV << endl;
00687      */
00688 
00689     // some entries not yet determined?
00690     if ((find(stateCache.prox->pr_rt.begin(), stateCache.prox->pr_rt.end(),
00691         PASTRY_PROX_PENDING) != stateCache.prox->pr_rt.end()) ||
00692         (find(stateCache.prox->pr_ls.begin(), stateCache.prox->pr_ls.end(),
00693          PASTRY_PROX_PENDING) != stateCache.prox->pr_ls.end()) ||
00694         (find(stateCache.prox->pr_ns.begin(), stateCache.prox->pr_ns.end(),
00695          PASTRY_PROX_PENDING) != stateCache.prox->pr_ns.end())) {
00696         //std::cout << "pending" << std::endl;
00697         return;
00698     }
00699 
00700     EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00701        << " (" << thisNode.getKey().toString(16) << ")]\n"
00702        << "    all proximities for current STATE message from "
00703        << stateCache.msg->getSender().getAddress()
00704        << " collected!"
00705        << endl;
00706     /*
00707     //debug
00708     if (stateCache.prox != NULL) {
00709         std::vector<PastryStateMsgHandle>::iterator it;
00710         for (it = stReceived.begin(); it != stReceived.end(); ++it) {
00711             if (it->prox == NULL) {
00712                 EV << ". " << endl;
00713                 continue;
00714             }
00715             for (uint i = 0; i < it->prox->pr_rt.size(); ++i) {
00716                 EV << it->prox->pr_rt[i] << " ";
00717             }
00718             for (uint i = 0; i < it->prox->pr_ls.size(); ++i) {
00719                 EV << it->prox->pr_ls[i] << " ";
00720             }
00721             for (uint i = 0; i < it->prox->pr_ns.size(); ++i) {
00722                 EV << it->prox->pr_ns[i] << " ";
00723             }
00724             EV << endl;
00725         }
00726         EV << endl;
00727     } else EV << "NULL" << endl;
00728 */
00729 
00730     simtime_t now = simTime();
00731 
00732     if (state == JOINING_2) {
00733         // save pointer to proximity vectors:
00734         stReceivedPos->prox = stateCache.prox;
00735 
00736         // collected proximities for all STATE messages?
00737         if (++stReceivedPos == stReceived.end()) {
00738             EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00739                << " (" << thisNode.getKey().toString(16) << ")]\n"
00740                << "    proximities for all STATE messages collected!"
00741                << endl;
00742             stateCache.msg = NULL;
00743             stateCache.prox = NULL;
00744             if (debugOutput) {
00745                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00746                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00747                    << "    [JOIN] starting to build own state from "
00748                    << stReceived.size() << " received state messages..."
00749                    << endl;
00750             }
00751             if (mergeState()) {
00752                 changeState(READY);
00753                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00754                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00755                    << "    changeState(READY) called"
00756                    << endl;
00757             } else {
00758                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00759                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00760                    << "    Error initializing while joining! Restarting ..."
00761                    << endl;
00762                 join();
00763             }
00764 
00765         } else {
00766             EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00767                << " (" << thisNode.getKey().toString(16) << ")]\n"
00768                << "    NOT all proximities for all STATE messages collected!"
00769                << endl;
00770             for (uint32_t i = 0; i < stReceived.size(); ++i) {
00771                 EV << ((i == 0) ? "    " : " | ");
00772                 if (stReceived[i].msg == stReceivedPos->msg) EV << "*";
00773                 EV << stReceived[i].msg;
00774             }
00775             EV << endl;
00776 
00777             // process next state message in vector:
00778             if (stReceivedPos->msg == NULL)
00779                 throw cRuntimeError("stReceivedPos->msg = NULL");
00780             stateCache = *stReceivedPos;
00781             if (stateCache.msg == NULL)
00782                 throw cRuntimeError("msg = NULL");
00783             processState();
00784         }
00785     } else {
00786         // state == READY
00787         if (stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) {
00788             // try to repair routingtable based on repair message:
00789             const TransportAddress& askRt =
00790                 routingTable->repair(stateCache.msg, stateCache.prox);
00791             if (! askRt.isUnspecified()) {
00792                 sendRequest(askRt, PASTRY_REQ_REPAIR);
00793             }
00794 
00795             // while not really known, it's safe to assume that a repair
00796             // message changed our state:
00797             lastStateChange = now;
00798         } else {
00799             if (stateCache.outdatedUpdate) {
00800                 // send another STATE message on outdated state update:
00801                 updateCounter++;
00802                 sendStateDelayed(stateCache.msg->getSender());
00803             } else {
00804                 // merge info in own state tables
00805                 // except leafset (was already handled in handleStateMessage)
00806                 if (neighborhoodSet->mergeState(stateCache.msg, stateCache.prox))
00807                     lastStateChange = now;
00808                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00809                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00810                    << "    Merging nodes into routing table"
00811                    << endl;
00812                 if (routingTable->mergeState(stateCache.msg, stateCache.prox)) {
00813                     lastStateChange = now;
00814                     EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00815                        << " (" << thisNode.getKey().toString(16) << ")]\n"
00816                        << "    Merged nodes into routing table"
00817                        << endl;
00818                 }
00819             }
00820         }
00821         updateTooltip();
00822 
00823         endProcessingState();
00824     }
00825 }
00826 
00827 void Pastry::endProcessingState(void)
00828 {
00829     // if state message was not an update, send one back:
00830     if (stateCache.msg &&
00831         stateCache.msg->getPastryStateMsgType() != PASTRY_STATE_UPDATE &&
00832         (alwaysSendUpdate || lastStateChange == simTime()) &&
00833         thisNode != stateCache.msg->getSender()) {//hack
00834         simtime_t timestamp = stateCache.msg->getTimestamp();
00835         sendStateTables(stateCache.msg->getSender(), PASTRY_STATE_UPDATE,
00836                         &timestamp);
00837     }
00838 
00839     delete stateCache.msg;
00840     stateCache.msg = NULL;
00841     delete stateCache.prox;
00842     stateCache.prox = NULL;
00843 
00844     // process next queued message:
00845     if (! stateCacheQueue.empty()) {
00846         stateCache = stateCacheQueue.front();
00847         stateCacheQueue.pop();
00848         processState();
00849     } //TODO get rid of the delayed update messages...
00850     /*else {
00851         std::cout << thisNode.getAddress() << "\t" << simTime()
00852                   << " all states processed ("
00853                   << updateCounter << ")" << std::endl;
00854         updateCounter = 0;
00855     }*/
00856 }
00857 
00858 bool Pastry::mergeState(void)
00859 {
00860     bool ret = true;
00861 
00862     if (state == JOINING_2) {
00863         // building initial state
00864         if (debugOutput) {
00865             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00866                << " (" << thisNode.getKey().toString(16) << ")]\n"
00867                << "    [JOIN] starting to build own state from "
00868                << stReceived.size() << " received state messages..."
00869                << endl;
00870         }
00871         if (stateCache.msg &&
00872             stateCache.msg->getNeighborhoodSetArraySize() > 0) {
00873             if (debugOutput) {
00874                 EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00875                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00876                    << "    [JOIN] initializing NeighborhoodSet from "
00877                    << stReceived.front().msg->getJoinHopCount() << ". hop"
00878                    << endl;
00879             }
00880             if (!neighborhoodSet->mergeState(stReceived.front().msg,
00881                                              stReceived.front().prox )) {
00882                 EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00883                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00884                    << "    Error initializing own neighborhoodSet while joining! Restarting ..."
00885                    << endl;
00886                 ret = false;
00887             }
00888         }
00889         if (debugOutput) {
00890             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00891                << " (" << thisNode.getKey().toString(16) << ")]\n"
00892                << "    [JOIN] initializing LeafSet from "
00893                << stReceived.back().msg->getJoinHopCount() << ". hop"
00894                << endl;
00895         }
00896 
00897         assert(!stateCache.msg || stateCache.msg->getLeafSetArraySize() > 0);
00898 
00899         if (!leafSet->mergeState(stReceived.back().msg,
00900                                  stReceived.back().prox )) {
00901             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00902                << " (" << thisNode.getKey().toString(16) << ")]\n"
00903                << "    Error initializing own leafSet while joining! Restarting ..."
00904                << endl;
00905             //std::cout << "Pastry: Error initializing own leafSet while "
00906             //                    "joining! Restarting ..." << std::endl;
00907             ret = false;
00908         } else {
00909             newLeafs();
00910         }
00911         if (debugOutput) {
00912             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00913                << " (" << thisNode.getKey().toString(16) << ")]\n"
00914                << "    [JOIN] initializing RoutingTable from all hops"
00915                << endl;
00916         }
00917 
00918         assert(!stateCache.msg ||
00919                stateCache.msg->getRoutingTableArraySize() > 0);
00920 
00921         if (!routingTable->initStateFromHandleVector(stReceived)) {
00922             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00923                << " (" << thisNode.getKey().toString(16) << ")]\n"
00924                << "    Error initializing own routingTable while joining! Restarting ..."
00925                << endl;
00926             //std::cout << "Pastry: Error initializing own routingTable "
00927             //             "while joining! Restarting ..." << std::endl;
00928 
00929             ret = false;
00930         }
00931         stateCache.msg = NULL;
00932         stateCache.prox = NULL;
00933     } else if (state == READY) {
00934         // merging singe state (stateCache.msg)
00935         if ((stateCache.msg->getNeighborhoodSetArraySize() > 0) &&
00936             (!neighborhoodSet->mergeState(stateCache.msg, NULL))) {
00937             ret = false;
00938         }
00939         if (!leafSet->mergeState(stateCache.msg, NULL)) {
00940             ret = false;
00941         } else {
00942             newLeafs();
00943         }
00944         if (!routingTable->mergeState(stateCache.msg, NULL)) {
00945             ret = false;
00946         }
00947     }
00948 
00949     if (ret) lastStateChange = simTime();
00950     return ret;
00951 }
00952 
00953 void Pastry::handleStateMessage(PastryStateMessage* msg)
00954 {
00955     if (debugOutput) {
00956         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
00957            << " (" << thisNode.getKey().toString(16) << ")]\n"
00958            << "    new STATE message to process "
00959            << static_cast<void*>(msg) << " in state " <<
00960             ((state == READY)?"READY":((state == JOINING_2)?"JOIN":"INIT"))
00961            << endl;
00962         if (state == JOINING_2) {
00963             EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
00964                << " (" << thisNode.getKey().toString(16) << ")]\n"
00965                << "    ***   own joinHopCount:  " << joinHopCount << endl
00966                << "    ***   already received:  " << stReceived.size() << endl
00967                << "    ***   last-hop flag:     "
00968                << (msg->getLastHop() ? "true" : "false") << endl
00969                << "    ***   msg joinHopCount:  "
00970                << msg->getJoinHopCount() << endl;
00971         }
00972     }
00973     if (state == INIT || state == DISCOVERY) {
00974         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
00975            << " (" << thisNode.getKey().toString(16) << ")]\n"
00976            << "    can't handle state messages until at least reaching JOIN state."
00977            << endl;
00978         delete msg;
00979         return;
00980     }
00981 
00982     PastryStateMsgHandle handle(msg);
00983 
00984     // in JOIN state, store all received state Messages, need them later:
00985     if (state == JOINING_2) {
00986         //std::cout << simTime() << " " << thisNode.getAddress() << " "
00987         //          << msg->getJoinHopCount()
00988         //          << (msg->getLastHop() ? " *" : "") << std::endl;
00989 
00990         if (msg->getPastryStateMsgType() != PASTRY_STATE_JOIN) {
00991             delete msg;
00992             return;
00993         }
00994 
00995         if (joinHopCount && stReceived.size() == joinHopCount) {
00996             EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
00997                << " (" << thisNode.getKey().toString(16) << ")]\n"
00998                << "    Warning: dropping state message received after "
00999                << "all needed state messages were collected in JOIN state."
01000                << endl;
01001             delete msg;
01002             return;
01003         }
01004 
01005         stReceived.push_back(handle);
01006         if (pingBeforeSecondStage) prePing(msg);
01007 
01008         if (msg->getLastHop()) {
01009             if (joinTimeout->isScheduled()) {
01010                 //std::cout << simTime() << " " << thisNode.getAddress()
01011                 //<< " cancelEvent(joinTimeout), received:"
01012                 //<< stReceived.size() << ", hopcount:" << joinHopCount << std::endl;
01013                 cancelEvent(joinTimeout);
01014             }
01015             /*if (msg->getSender().getKey() == thisNode.getKey()) {
01016                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01017                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01018                    << "    Error: OverlayKey already in use, restarting!"
01019                    << endl;
01020                 //std::cout << "Pastry: Error: OverlayKey already in use, restarting!"
01021                 //                   << std::endl;
01022                 join();
01023                 return;
01024             }*/
01025 
01026             if (joinHopCount) {
01027                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01028                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01029                    << "    Error: received a second `last' state message! Restarting ..."
01030                    << endl;
01031                 //std::cout << thisNode.getAddress() << "Pastry: Error: received a second `last' state message! "
01032                 //                    "Restarting ..." << std::endl;
01033                 join();
01034                 return;
01035             }
01036 
01037             joinHopCount = msg->getJoinHopCount();
01038             //std::cout << stReceived.size() << " " << joinHopCount << std::endl;
01039             if (stReceived.size() < joinHopCount) {
01040                 // some states still missing:
01041                 cancelEvent(readyWait);
01042                 scheduleAt(simTime() + readyWaitAmount, readyWait);
01043                 //std::cout << simTime() << " " << thisNode.getAddress() << " readyWait scheduled!" << std::endl;
01044             }
01045         }
01046 
01047         if (joinHopCount) {
01048             if (stReceived.size() > joinHopCount) {
01049                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01050                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01051                    << "    Error: too many state messages received in JOIN state! ("
01052                    << stReceived.size() << " > " << joinHopCount << ") Restarting ..."
01053                    << endl;
01054                 //std::cout << " failed!" << std::endl;
01055                 join();
01056                 return;
01057             }
01058             if (stReceived.size() == joinHopCount) {
01059                 // all state messages are here, sort by hopcount:
01060                 sort(stReceived.begin(), stReceived.end(),
01061                      stateMsgIsSmaller);
01062 
01063                 // start pinging the nodes found in the first state message:
01064                 stReceivedPos = stReceived.begin();
01065                 stateCache = *stReceivedPos;
01066                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01067                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01068                    << "    have all STATE messages, now pinging nodes."
01069                    << endl;
01070                 if (pingBeforeSecondStage) pingNodes();
01071                 else {
01072                     mergeState(); // JOINING / stateCache
01073                     //endProcessingState(); no way
01074                     //stateCache.msg = NULL; //test
01075                     changeState(READY);
01076                     EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01077                        << " (" << thisNode.getKey().toString(16) << ")]\n"
01078                        << "    changeState(READY) called"
01079                        << endl;
01080                 }
01081 
01082                 // cancel timeout:
01083                 if (readyWait->isScheduled()) cancelEvent(readyWait);
01084             } else {
01085                 //TODO occasionally, here we got a wrong hop count in
01086                 // iterative mode due to more than one it. lookup during join
01087                 // procedure
01088                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01089                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01090                    << "    Still need some STATE messages."
01091                    << endl;
01092             }
01093 
01094         }
01095         return;
01096     }
01097 
01098     if (debugOutput) {
01099         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01100            << " (" << thisNode.getKey().toString(16) << ")]\n"
01101            << "    handling STATE message"
01102            << endl;
01103         EV << "        type: " << ((msg->getPastryStateMsgType()
01104                                     == PASTRY_STATE_UPDATE) ? "update"
01105                                                             :"standard")
01106            << endl;
01107         if (msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE) {
01108             EV << "        msg timestamp:      " <<
01109                 msg->getTimestamp() << endl;
01110             EV << "        last state change:  " <<
01111                 lastStateChange << endl;
01112         }
01113     }
01114 
01115     if (((msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE))
01116             && (msg->getTimestamp() <= lastStateChange)) {
01117         // if we received an update based on our outdated state,
01118         // mark handle for retrying later:
01119         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01120            << " (" << thisNode.getKey().toString(16) << ")]\n"
01121            << "    outdated state from " << msg->getSender()
01122            << endl;
01123         handle.outdatedUpdate = true;
01124     }
01125 
01126     // determine aliveTable to prevent leafSet from merging nodes that are
01127     // known to be dead:
01128     determineAliveTable(msg);
01129 
01130     if (msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) {
01131         // try to repair leafset based on repair message right now
01132         const TransportAddress& askLs = leafSet->repair(msg, &aliveTable);
01133         if (! askLs.isUnspecified()) {
01134             sendRequest(askLs, PASTRY_REQ_REPAIR);
01135         }
01136 
01137         // while not really known, it's safe to assume that a repair
01138         // message changed our state:
01139         lastStateChange = simTime();
01140         newLeafs();
01141     } else if (leafSet->mergeState(msg, &aliveTable)) {
01142         // merged state into leafset right now
01143         lastStateChange = simTime();
01144         newLeafs();
01145         updateTooltip();
01146     }
01147     // in READY state, only ping nodes to get proximity metric:
01148     if (!stateCache.msg) {
01149         // no state message is processed right now, start immediately:
01150         stateCache = handle;
01151         processState();
01152     } else {
01153         if (pingBeforeSecondStage ||
01154             msg->getPastryStateMsgType() == PASTRY_STATE_STD) {
01155             // enqueue message for later processing:
01156             stateCacheQueue.push(handle);
01157             prePing(msg);
01158         } else {
01159             bool temp = true;
01160             if (!neighborhoodSet->mergeState(msg, NULL)) {
01161                 temp = false;
01162             }
01163             if (!leafSet->mergeState(msg, NULL)) {
01164                 temp = false;
01165             } else {
01166                 newLeafs();
01167             }
01168             if (!routingTable->mergeState(msg, NULL)) {
01169                 temp = false;
01170             }
01171             if (temp) lastStateChange = simTime();
01172             delete msg;
01173         }
01174     }
01175 }
01176 
01177 void Pastry::processState(void)
01178 {
01179     if (pingBeforeSecondStage ||
01180         stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_STD) {
01181         pingNodes();
01182     } else {
01183         mergeState();
01184         endProcessingState();
01185     }
01186 }

Generated on Tue Sep 8 17:26:53 2009 for OverSim by  doxygen 1.5.8