Pastry Class Reference

Pastry overlay module. More...

#include <Pastry.h>

Inheritance diagram for Pastry:

BasePastry BaseOverlay ProxListener BaseRpc TopologyVis RpcListener

List of all members.

Public Member Functions

virtual ~Pastry ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void handleTimerEvent (cMessage *msg)
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
void handleStateMessage (PastryStateMessage *msg)
 processes state messages, merging with own state tables

Protected Member Functions

virtual void changeState (int toState)
 changes node state

Private Member Functions

void doSecondStage (void)
 do the second stage of initialization as described in the paper
bool handleFailedNode (const TransportAddress &failed)
 notifies leafset and routingtable of a failed node and sends out a repair request if possible
void checkProxCache (void)
 checks whether proxCache is complete, takes appropriate actions depending on the protocol state
void processState (void)
bool mergeState (void)
void endProcessingState (void)
void doJoinUpdate (void)
 send updated state to all nodes when entering ready state
virtual void joinOverlay ()
 Join the overlay with a given nodeID in thisNode.key.

Private Attributes

simtime_t secondStageInterval
simtime_t ringCheckInterval
simtime_t discoveryTimeoutAmount
bool partialJoinPath
int depth
int updateCounter
bool useSecondStage
bool sendStateAtLeafsetRepair
bool pingBeforeSecondStage
bool overrideOldPastry
bool overrideNewPastry
cMessage * secondStageWait
cMessage * ringCheck
cMessage * discoveryTimeout
cMessage * repairTaskTimeout


Detailed Description

Pastry overlay module.

Author:
Felix Palmen
See also:
BaseOverlay

Definition at line 54 of file Pastry.h.


Constructor & Destructor Documentation

Pastry::~Pastry (  )  [virtual]

Definition at line 41 of file Pastry.cc.

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 }


Member Function Documentation

void Pastry::changeState ( int  toState  )  [protected, virtual]

changes node state

Parameters:
toState state to change to

Reimplemented from BasePastry.

Definition at line 121 of file Pastry.cc.

Referenced by checkProxCache(), handleStateMessage(), handleTimerEvent(), and joinOverlay().

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 }

void Pastry::checkProxCache ( void   )  [private, virtual]

checks whether proxCache is complete, takes appropriate actions depending on the protocol state

Implements BasePastry.

Definition at line 656 of file Pastry.cc.

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 }

void Pastry::doJoinUpdate ( void   )  [private]

send updated state to all nodes when entering ready state

Definition at line 540 of file Pastry.cc.

Referenced by handleTimerEvent().

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 }

void Pastry::doSecondStage ( void   )  [private]

do the second stage of initialization as described in the paper

Definition at line 573 of file Pastry.cc.

Referenced by handleTimerEvent().

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 }

void Pastry::endProcessingState ( void   )  [private]

Definition at line 827 of file Pastry.cc.

Referenced by checkProxCache(), and processState().

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 }

bool Pastry::handleFailedNode ( const TransportAddress failed  )  [private, virtual]

notifies leafset and routingtable of a failed node and sends out a repair request if possible

Parameters:
failed the failed node
Returns:
true as long as local state is READY (signals lookup to try again)

Reimplemented from BaseOverlay.

Definition at line 618 of file Pastry.cc.

Referenced by handleUDPMessage().

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 }

void Pastry::handleStateMessage ( PastryStateMessage msg  )  [virtual]

processes state messages, merging with own state tables

Parameters:
msg the pastry state message

Implements BasePastry.

Definition at line 953 of file Pastry.cc.

Referenced by handleUDPMessage().

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 }

void Pastry::handleTimerEvent ( cMessage *  msg  )  [virtual]

Reimplemented from BaseRpc.

Definition at line 201 of file Pastry.cc.

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 }

void Pastry::handleUDPMessage ( BaseOverlayMessage msg  )  [virtual]

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Definition at line 304 of file Pastry.cc.

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 }

void Pastry::initializeOverlay ( int  stage  )  [virtual]

Initializes derived-class-attributes.


Initializes derived-class-attributes, called by BaseOverlay::initialize(). By default this method is called once. If more stages are needed one can overload numInitStages() and add more stages.

Parameters:
stage the init stage

Reimplemented from BaseOverlay.

Definition at line 52 of file Pastry.cc.

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 }

void Pastry::joinOverlay (  )  [private, virtual]

Join the overlay with a given nodeID in thisNode.key.

Join the overlay with a given nodeID in thisNode.key. This method may be called by an application to join the overlay with a specific nodeID. It is also called if the node's IP address changes.

Reimplemented from BaseOverlay.

Definition at line 106 of file Pastry.cc.

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 }

bool Pastry::mergeState ( void   )  [private]

Definition at line 858 of file Pastry.cc.

Referenced by checkProxCache(), handleStateMessage(), and processState().

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 }

void Pastry::processState ( void   )  [private]

Definition at line 1177 of file Pastry.cc.

Referenced by checkProxCache(), doSecondStage(), endProcessingState(), handleStateMessage(), and handleTimerEvent().

01178 {
01179     if (pingBeforeSecondStage ||
01180         stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_STD) {
01181         pingNodes();
01182     } else {
01183         mergeState();
01184         endProcessingState();
01185     }
01186 }


Member Data Documentation

int Pastry::depth [private]

Definition at line 86 of file Pastry.h.

Referenced by changeState(), handleTimerEvent(), and handleUDPMessage().

cMessage* Pastry::discoveryTimeout [private]

Definition at line 99 of file Pastry.h.

Referenced by handleUDPMessage(), initializeOverlay(), and ~Pastry().

simtime_t Pastry::discoveryTimeoutAmount [private]

Definition at line 83 of file Pastry.h.

Referenced by changeState(), handleUDPMessage(), and initializeOverlay().

bool Pastry::overrideNewPastry [private]

Definition at line 95 of file Pastry.h.

Referenced by initializeOverlay().

bool Pastry::overrideOldPastry [private]

Definition at line 94 of file Pastry.h.

Referenced by initializeOverlay().

bool Pastry::partialJoinPath [private]

Definition at line 84 of file Pastry.h.

Referenced by handleTimerEvent(), and initializeOverlay().

Definition at line 92 of file Pastry.h.

Referenced by handleStateMessage(), initializeOverlay(), and processState().

cMessage* Pastry::repairTaskTimeout [private]

Definition at line 100 of file Pastry.h.

Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Pastry().

cMessage* Pastry::ringCheck [private]

Definition at line 98 of file Pastry.h.

Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Pastry().

simtime_t Pastry::ringCheckInterval [private]

Definition at line 82 of file Pastry.h.

Referenced by changeState(), handleTimerEvent(), and initializeOverlay().

simtime_t Pastry::secondStageInterval [private]

Definition at line 81 of file Pastry.h.

Referenced by changeState(), and initializeOverlay().

cMessage* Pastry::secondStageWait [private]

Definition at line 97 of file Pastry.h.

Referenced by changeState(), initializeOverlay(), and ~Pastry().

Definition at line 91 of file Pastry.h.

Referenced by handleFailedNode(), and initializeOverlay().

int Pastry::updateCounter [private]

Definition at line 88 of file Pastry.h.

Referenced by checkProxCache(), and initializeOverlay().

bool Pastry::useSecondStage [private]

Definition at line 90 of file Pastry.h.


The documentation for this class was generated from the following files:

Generated on Tue Sep 8 17:27:00 2009 for OverSim by  doxygen 1.5.8