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
virtual void pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt)

Protected Member Functions

virtual void purgeVectors (void)
 delete all information/messages caching vectors, used for restarting overlay or finish()
virtual void changeState (int toState)
 changes node state
virtual bool recursiveRoutingHook (const TransportAddress &dest, BaseRouteMessage *msg)
 Hook for forwarded message in recursive lookup mode.
void iterativeJoinHook (BaseOverlayMessage *msg, bool incrHopCount)

Protected Attributes

std::vector< PastryStateMsgHandlestReceived
 State messages to process during join.
std::vector
< PastryStateMsgHandle >
::iterator 
stReceivedPos
std::vector< TransportAddressnotifyList
 List of nodes to notify after join.

Private Member Functions

void clearVectors ()
void doSecondStage (void)
 do the second stage of initialization as described in the paper
void doRoutingTableMaintenance ()
 periodic routing table maintenance requests the corresponding routing table row from one node in each row
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 routingTableMaintenanceInterval
simtime_t discoveryTimeoutAmount
bool partialJoinPath
int depth
int updateCounter
bool minimalJoinState
bool useDiscovery
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     if (useDiscovery) cancelAndDelete(discoveryTimeout);
00048     if (routingTableMaintenanceInterval > 0) cancelAndDelete(repairTaskTimeout);
00049 
00050     clearVectors();
00051 }


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 149 of file Pastry.cc.

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

00150 {
00151     if (readyWait->isScheduled()) cancelEvent(readyWait);
00152     baseChangeState(toState);
00153 
00154     switch (toState) {
00155     case INIT:
00156         cancelAllRpcs();
00157         purgeVectors();
00158         break;
00159 
00160     case DISCOVERY:
00161         state = DISCOVERY;
00162         //nearNode = bootstrapNode;
00163         nearNodeRtt = MAXTIME;
00164         pingNode(bootstrapNode, discoveryTimeoutAmount, 0,
00165                  NULL, "PING bootstrapNode in discovery mode",
00166                  NULL, PING_DISCOVERY, UDP_TRANSPORT); //TODO
00167         sendRequest(bootstrapNode, PASTRY_REQ_LEAFSET); //TODO should be an RPC
00168         depth = -1;
00169 
00170         // schedule join timer for discovery algorithm
00171         cancelEvent(joinTimeout);
00172         scheduleAt(simTime() + joinTimeoutAmount, joinTimeout);
00173 
00174         break;
00175 
00176     case JOINING_2: {
00177         joinHopCount = 0;
00178         PastryJoinMessage* msg = new PastryJoinMessage("JOIN-Request");
00179         //TODO add timestamp to join msg
00180         msg->setPastryMsgType(PASTRY_MSG_JOIN);
00181         msg->setStatType(MAINTENANCE_STAT);
00182         msg->setSendStateTo(thisNode);
00183         msg->setBitLength(PASTRYJOIN_L(msg));
00184         RECORD_STATS(joinSent++; joinBytesSent += msg->getByteLength());
00185         std::vector<TransportAddress> sourceRoute;
00186         sourceRoute.push_back(nearNode);
00187         sendToKey(thisNode.getKey(), msg, 0/*1*/, sourceRoute);
00188     }
00189     break;
00190 
00191     case READY:
00192         // determine list of all known nodes as notifyList
00193         notifyList.clear();
00194         leafSet->dumpToVector(notifyList);
00195         routingTable->dumpToVector(notifyList);
00196         sort(notifyList.begin(), notifyList.end());
00197         notifyList.erase(unique(notifyList.begin(), notifyList.end()),
00198                          notifyList.end());
00199 
00200         // schedule update
00201         cancelEvent(joinUpdateWait);
00202         scheduleAt(simTime() + 0.0001, joinUpdateWait);
00203 
00204         // schedule second stage
00205         if (secondStageInterval > 0) {
00206             cancelEvent(secondStageWait);
00207             scheduleAt(simTime() + secondStageInterval, secondStageWait);
00208         }
00209 
00210         // schedule routing table maintenance task
00211         if (routingTableMaintenanceInterval > 0) {
00212             cancelEvent(repairTaskTimeout);
00213             scheduleAt(simTime() + routingTableMaintenanceInterval, repairTaskTimeout);
00214         }
00215 
00216         break;
00217     }
00218 }

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

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

Implements BasePastry.

Definition at line 765 of file Pastry.cc.

00766 {
00767     EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00768        << " (" << thisNode.getKey().toString(16) << ")]"
00769        << endl;
00770 
00771     // no cached STATE message?
00772     assert(stateCache.msg || !stateCache.prox);
00773     if (!stateCache.msg) return;
00774 
00775     // no entries in stateCache.prox?
00776     if (stateCache.prox->pr_rt.empty() &&
00777         stateCache.prox->pr_ls.empty() &&
00778         stateCache.prox->pr_ns.empty())
00779         throw new cRuntimeError("ERROR in Pastry: stateCache.prox empty!");
00780 
00781     /*
00782     //debug
00783     for (uint i = 0; i < stateCache.prox->pr_rt.size(); ++i) {
00784         if (stateCache.prox->pr_rt[i] == -3)
00785             EV << stateCache.msg->getRoutingTable(i).getAddress() << " ";
00786     }
00787     for (uint i = 0; i < stateCache.prox->pr_ls.size(); ++i) {
00788         if (stateCache.prox->pr_ls[i] == -3)
00789             EV << stateCache.msg->getLeafSet(i).getAddress() << " ";
00790     }
00791     for (uint i = 0; i < stateCache.prox->pr_ns.size(); ++i) {
00792         if (stateCache.prox->pr_ns[i] == -3)
00793             EV << stateCache.msg->getNeighborhoodSet(i).getAddress() << " ";
00794     }
00795     EV << endl;
00796      */
00797 
00798     // some entries not yet determined?
00799     if ((find(stateCache.prox->pr_rt.begin(), stateCache.prox->pr_rt.end(),
00800         PASTRY_PROX_PENDING) != stateCache.prox->pr_rt.end()) ||
00801         (find(stateCache.prox->pr_ls.begin(), stateCache.prox->pr_ls.end(),
00802          PASTRY_PROX_PENDING) != stateCache.prox->pr_ls.end()) ||
00803         (find(stateCache.prox->pr_ns.begin(), stateCache.prox->pr_ns.end(),
00804          PASTRY_PROX_PENDING) != stateCache.prox->pr_ns.end())) {
00805         //std::cout << "pending" << std::endl;
00806         return;
00807     }
00808 
00809     EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00810        << " (" << thisNode.getKey().toString(16) << ")]\n"
00811        << "    all proximities for current STATE message from "
00812        << stateCache.msg->getSender().getAddress()
00813        << " collected!"
00814        << endl;
00815     /*
00816     //debug
00817     if (stateCache.prox != NULL) {
00818         std::vector<PastryStateMsgHandle>::iterator it;
00819         for (it = stReceived.begin(); it != stReceived.end(); ++it) {
00820             if (it->prox == NULL) {
00821                 EV << ". " << endl;
00822                 continue;
00823             }
00824             for (uint i = 0; i < it->prox->pr_rt.size(); ++i) {
00825                 EV << it->prox->pr_rt[i] << " ";
00826             }
00827             for (uint i = 0; i < it->prox->pr_ls.size(); ++i) {
00828                 EV << it->prox->pr_ls[i] << " ";
00829             }
00830             for (uint i = 0; i < it->prox->pr_ns.size(); ++i) {
00831                 EV << it->prox->pr_ns[i] << " ";
00832             }
00833             EV << endl;
00834         }
00835         EV << endl;
00836     } else EV << "NULL" << endl;
00837 */
00838 
00839     simtime_t now = simTime();
00840 
00841     if (state == JOINING_2) {
00842         // save pointer to proximity vectors (it is NULL until now):
00843         stReceivedPos->prox = stateCache.prox;
00844 
00845         // collected proximities for all STATE messages?
00846         if (++stReceivedPos == stReceived.end()) {
00847             EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00848                << " (" << thisNode.getKey().toString(16) << ")]\n"
00849                << "    proximities for all STATE messages collected!"
00850                << endl;
00851             stateCache.msg = NULL;
00852             stateCache.prox = NULL;
00853             if (debugOutput) {
00854                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00855                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00856                    << "    [JOIN] starting to build own state from "
00857                    << stReceived.size() << " received state messages..."
00858                    << endl;
00859             }
00860             if (mergeState()) {
00861                 changeState(READY);
00862                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00863                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00864                    << "    changeState(READY) called"
00865                    << endl;
00866             } else {
00867                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00868                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00869                    << "    Error initializing while joining! Restarting ..."
00870                    << endl;
00871                 joinOverlay();
00872             }
00873 
00874         } else {
00875             EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00876                << " (" << thisNode.getKey().toString(16) << ")]\n"
00877                << "    NOT all proximities for all STATE messages collected!"
00878                << endl;
00879             /*
00880             for (uint32_t i = 0; i < stReceived.size(); ++i) {
00881                 EV << ((i == 0) ? "    " : " | ");
00882                 std::cout << ((i == 0) ? "    " : " | ");
00883                 if (stReceived[i].msg == stReceivedPos->msg) {
00884                     EV << "*";
00885                     std::cout << "*";
00886                 }
00887                 EV << stReceived[i].msg << " " << stReceived[i].prox;
00888                 std::cout << stReceived[i].msg << " " << stReceived[i].prox;
00889             }
00890             EV << endl;
00891             std::cout << std::endl;
00892              */
00893 
00894             // process next state message in vector:
00895             if (stReceivedPos->msg == NULL)
00896                 throw cRuntimeError("stReceivedPos->msg = NULL");
00897             stateCache = *stReceivedPos;
00898             if (stateCache.msg == NULL)
00899                 throw cRuntimeError("msg = NULL");
00900             processState();
00901         }
00902     } else {
00903         // state == READY
00904         if (stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) {
00905             // try to repair routingtable based on repair message:
00906             const TransportAddress& askRt =
00907                 routingTable->repair(stateCache.msg, stateCache.prox);
00908             if (! askRt.isUnspecified()) {
00909                 sendRequest(askRt, PASTRY_REQ_REPAIR);
00910             }
00911 
00912             // while not really known, it's safe to assume that a repair
00913             // message changed our state:
00914             lastStateChange = now;
00915         } else {
00916             if (stateCache.outdatedUpdate) {
00917                 // send another STATE message on outdated state update:
00918                 updateCounter++;
00919                 sendStateDelayed(stateCache.msg->getSender());
00920             } else {
00921                 // merge info in own state tables
00922                 // except leafset (was already handled in handleStateMessage)
00923                 if (neighborhoodSet->mergeState(stateCache.msg, stateCache.prox))
00924                     lastStateChange = now;
00925                 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00926                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00927                    << "    Merging nodes into routing table"
00928                    << endl;
00929                 if (routingTable->mergeState(stateCache.msg, stateCache.prox)) {
00930                     lastStateChange = now;
00931                     EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress()
00932                        << " (" << thisNode.getKey().toString(16) << ")]\n"
00933                        << "    Merged nodes into routing table"
00934                        << endl;
00935                 }
00936             }
00937         }
00938         updateTooltip();
00939 
00940         endProcessingState();
00941     }
00942 }

void Pastry::clearVectors (  )  [private]

Definition at line 53 of file Pastry.cc.

Referenced by purgeVectors(), and ~Pastry().

00054 {
00055     // purge pending state messages
00056     if (!stReceived.empty()) {
00057         for (std::vector<PastryStateMsgHandle>::iterator it =
00058             stReceived.begin(); it != stReceived.end(); it++) {
00059             // check whether one of the pointers is a duplicate of stateCache
00060             if (it->msg == stateCache.msg) stateCache.msg = NULL;
00061             if (it->prox == stateCache.prox) stateCache.prox = NULL;
00062             delete it->msg;
00063             delete it->prox;
00064         }
00065         stReceived.clear();
00066         stReceivedPos = stReceived.end();
00067     }
00068 
00069     // purge notify list:
00070     notifyList.clear();
00071 }

void Pastry::doJoinUpdate ( void   )  [private]

send updated state to all nodes when entering ready state

Definition at line 617 of file Pastry.cc.

Referenced by handleTimerEvent().

00618 {
00619     // send "update" state message to all nodes who sent us their state
00620     // during INIT, remove these from notifyList so they don't get our
00621     // state twice
00622     std::vector<TransportAddress>::iterator nListPos;
00623     if (!stReceived.empty()) {
00624         for (std::vector<PastryStateMsgHandle>::iterator it =
00625                  stReceived.begin(); it != stReceived.end(); ++it) {
00626             simtime_t timestamp = it->msg->getTimestamp();
00627             sendStateTables(it->msg->getSender(), PASTRY_STATE_UPDATE,
00628                             &timestamp);
00629             nListPos = find(notifyList.begin(), notifyList.end(),
00630                             it->msg->getSender());
00631             if (nListPos != notifyList.end()) {
00632                 notifyList.erase(nListPos);
00633             }
00634             delete it->msg;
00635             delete it->prox;
00636         }
00637         stReceived.clear();
00638     }
00639 
00640     // send a normal STATE message to all remaining known nodes
00641     for (std::vector<TransportAddress>::iterator it =
00642              notifyList.begin(); it != notifyList.end(); it++) {
00643         if (*it != thisNode) sendStateTables(*it, PASTRY_STATE_JOINUPDATE);
00644     }
00645     notifyList.clear();
00646 
00647     updateTooltip();
00648 }

void Pastry::doRoutingTableMaintenance (  )  [private]

periodic routing table maintenance requests the corresponding routing table row from one node in each row

Definition at line 696 of file Pastry.cc.

Referenced by handleTimerEvent().

00697 {
00698     for (int i = 0; i < routingTable->getLastRow(); i++) {
00699         const TransportAddress& ask4row = routingTable->getRandomNode(i);
00700 
00701         if ((!ask4row.isUnspecified()) && (ask4row != thisNode)) {
00702             PastryRoutingRowRequestMessage* msg =
00703                 new PastryRoutingRowRequestMessage("ROWREQ");
00704             msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00705             msg->setStatType(MAINTENANCE_STAT);
00706             msg->setSendStateTo(thisNode);
00707             msg->setRow(i + 1);
00708             msg->setBitLength(PASTRYRTREQ_L(msg));
00709 
00710             RECORD_STATS(routingTableReqSent++;
00711                          routingTableReqBytesSent += msg->getByteLength());
00712 
00713             sendMessageToUDP(ask4row, msg);
00714         } else {
00715             EV << "[Pastry::doRoutingTableMaintenance() @ "
00716                << thisNode.getAddress()
00717                << " (" << thisNode.getKey().toString(16) << ")]\n"
00718                << "    could not send Message to Node in Row" << i
00719                << endl;
00720         }
00721     }
00722 }

void Pastry::doSecondStage ( void   )  [private]

do the second stage of initialization as described in the paper

Definition at line 650 of file Pastry.cc.

Referenced by handleTimerEvent().

00651 {
00652     getParentModule()->getParentModule()->bubble("entering SECOND STAGE");
00653 
00654     // probe nodes in local state
00655     if (leafSet->isValid()) {
00656         PastryStateMessage* stateMsg = new PastryStateMessage("STATE");
00657         stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00658         stateMsg->setStatType(MAINTENANCE_STAT);
00659         stateMsg->setPastryStateMsgType(PASTRY_STATE_STD);
00660         stateMsg->setSender(thisNode);
00661         routingTable->dumpToStateMessage(stateMsg);
00662         leafSet->dumpToStateMessage(stateMsg);
00663         neighborhoodSet->dumpToStateMessage(stateMsg);
00664         //stateMsg->setBitLength(PASTRYSTATE_L(stateMsg));
00665         PastryStateMsgHandle handle(stateMsg);
00666 
00667         if (!stateCache.msg) {
00668             stateCache = handle;
00669             processState();
00670         } else {
00671             stateCacheQueue.push(handle);
00672             prePing(stateMsg);
00673         }
00674     }
00675 
00676     // "second stage" for locality:
00677     notifyList.clear();
00678     routingTable->dumpToVector(notifyList);
00679     neighborhoodSet->dumpToVector(notifyList);
00680     sort(notifyList.begin(), notifyList.end());
00681     notifyList.erase(unique(notifyList.begin(), notifyList.end()),
00682                      notifyList.end());
00683     for (std::vector<TransportAddress>::iterator it = notifyList.begin();
00684          it != notifyList.end(); it++) {
00685         if (*it == thisNode) continue;
00686         EV << "[Pastry::doSecondStage() @ " << thisNode.getAddress()
00687            << " (" << thisNode.getKey().toString(16) << ")]\n"
00688            << "    second stage: requesting state from " << *it
00689            << endl;
00690         sendRequest(*it, PASTRY_REQ_STATE);
00691     }
00692     notifyList.clear();
00693 }

void Pastry::endProcessingState ( void   )  [private]

Definition at line 944 of file Pastry.cc.

Referenced by checkProxCache(), and processState().

00945 {
00946     // if state message was not an update, send one back:
00947     if (stateCache.msg &&
00948         stateCache.msg->getPastryStateMsgType() != PASTRY_STATE_UPDATE &&
00949         (alwaysSendUpdate || lastStateChange == simTime()) &&
00950         thisNode != stateCache.msg->getSender()) {//hack
00951         simtime_t timestamp = stateCache.msg->getTimestamp();
00952         sendStateTables(stateCache.msg->getSender(), PASTRY_STATE_UPDATE,
00953                         &timestamp);
00954     }
00955 
00956     delete stateCache.msg;
00957     stateCache.msg = NULL;
00958     delete stateCache.prox;
00959     stateCache.prox = NULL;
00960 
00961     // process next queued message:
00962     if (! stateCacheQueue.empty()) {
00963         stateCache = stateCacheQueue.front();
00964         stateCacheQueue.pop();
00965         processState();
00966     } //TODO get rid of the delayed update messages...
00967     /*else {
00968         std::cout << thisNode.getAddress() << "\t" << simTime()
00969                   << " all states processed ("
00970                   << updateCounter << ")" << std::endl;
00971         updateCounter = 0;
00972     }*/
00973 }

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 725 of file Pastry.cc.

Referenced by handleUDPMessage(), and recursiveRoutingHook().

00726 {
00727     if (state != READY) {
00728         return false;
00729     }
00730     bool wasValid = leafSet->isValid();
00731 
00732     //std::cout << thisNode.getAddress() << " is handling failed node: "
00733     //          << failed.getAddress() << std::endl;
00734     if (failed.isUnspecified())
00735         opp_error("Pastry::handleFailedNode(): failed is unspecified!");
00736 
00737     const TransportAddress& lsAsk = leafSet->failedNode(failed);
00738     const TransportAddress& rtAsk = routingTable->failedNode(failed);
00739     neighborhoodSet->failedNode(failed);
00740 
00741     if (! lsAsk.isUnspecified()) {
00742         newLeafs();
00743         if (sendStateAtLeafsetRepair) sendRequest(lsAsk, PASTRY_REQ_REPAIR);
00744         else sendRequest(lsAsk, PASTRY_REQ_LEAFSET);
00745     }
00746     if (! rtAsk.isUnspecified() &&
00747         (lsAsk.isUnspecified() ||
00748          lsAsk != rtAsk)) sendRequest(rtAsk, PASTRY_REQ_REPAIR);
00749 
00750     if (wasValid && lsAsk.isUnspecified() && (! leafSet->isValid())) {
00751         EV << "[Pastry::handleFailedNode() @ " << thisNode.getAddress()
00752            << " (" << thisNode.getKey().toString(16) << ")]\n"
00753            << "    lost connection to the network, trying to re-join."
00754            << endl;
00755         //std::cout << thisNode.getAddress()
00756         //          << " Pastry: lost connection to the network, trying to re-join."
00757         //          << std::endl;
00758         join();
00759         return false;
00760     }
00761 
00762     return true;
00763 }

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 1071 of file Pastry.cc.

Referenced by handleUDPMessage().

01072 {
01073     if (debugOutput) {
01074         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01075            << " (" << thisNode.getKey().toString(16) << ")]\n"
01076            << "    new STATE message to process "
01077            << static_cast<void*>(msg) << " in state " <<
01078             ((state == READY)?"READY":((state == JOINING_2)?"JOIN":"INIT"))
01079            << endl;
01080         if (state == JOINING_2) {
01081             EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01082                << " (" << thisNode.getKey().toString(16) << ")]\n"
01083                << "    ***   own joinHopCount:  " << joinHopCount << endl
01084                << "    ***   already received:  " << stReceived.size() << endl
01085                << "    ***   last-hop flag:     "
01086                << (msg->getLastHop() ? "true" : "false") << endl
01087                << "    ***   msg joinHopCount:  "
01088                << msg->getJoinHopCount() << endl;
01089         }
01090     }
01091     if (state == INIT || state == DISCOVERY) {
01092         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01093            << " (" << thisNode.getKey().toString(16) << ")]\n"
01094            << "    can't handle state messages until at least reaching JOIN state."
01095            << endl;
01096         delete msg;
01097         return;
01098     }
01099 
01100     PastryStateMsgHandle handle(msg);
01101 
01102     // in JOIN state, store all received state Messages, need them later:
01103     if (state == JOINING_2) {
01104         //std::cout << simTime() << " " << thisNode.getAddress() << " "
01105         //          << msg->getJoinHopCount()
01106         //          << (msg->getLastHop() ? " *" : "") << std::endl;
01107 
01108         if (msg->getPastryStateMsgType() != PASTRY_STATE_JOIN) {
01109             delete msg;
01110             return;
01111         }
01112 
01113         if (joinHopCount && stReceived.size() == joinHopCount) {
01114             EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01115                << " (" << thisNode.getKey().toString(16) << ")]\n"
01116                << "    Warning: dropping state message received after "
01117                << "all needed state messages were collected in JOIN state."
01118                << endl;
01119             delete msg;
01120             return;
01121         }
01122 
01123         stReceived.push_back(handle);
01124         if (pingBeforeSecondStage && proximityNeighborSelection) prePing(msg);
01125 
01126         if (msg->getLastHop()) {
01127             if (joinTimeout->isScheduled()) {
01128                 //std::cout << simTime() << " " << thisNode.getAddress()
01129                 //<< " cancelEvent(joinTimeout), received:"
01130                 //<< stReceived.size() << ", hopcount:" << joinHopCount << std::endl;
01131                 cancelEvent(joinTimeout);
01132             }
01133             /*if (msg->getSender().getKey() == thisNode.getKey()) {
01134                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01135                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01136                    << "    Error: OverlayKey already in use, restarting!"
01137                    << endl;
01138                 //std::cout << "Pastry: Error: OverlayKey already in use, restarting!"
01139                 //                   << std::endl;
01140                 joinOverlay();
01141                 return;
01142             }*/
01143 
01144             if (joinHopCount) {
01145                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01146                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01147                    << "    Error: received a second `last' state message! Restarting ..."
01148                    << endl;
01149                 //std::cout << thisNode.getAddress() << "Pastry: Error: received a second `last' state message! "
01150                 //                    "Restarting ..." << std::endl;
01151                 joinOverlay();
01152                 return;
01153             }
01154 
01155             joinHopCount = msg->getJoinHopCount();
01156             //std::cout << stReceived.size() << " " << joinHopCount << std::endl;
01157             if (stReceived.size() < joinHopCount) {
01158                 // some states still missing:
01159                 cancelEvent(readyWait);
01160                 scheduleAt(simTime() + readyWaitAmount, readyWait);
01161                 //std::cout << simTime() << " " << thisNode.getAddress() << " readyWait scheduled!" << std::endl;
01162             }
01163         }
01164 
01165         if (joinHopCount) {
01166             if (stReceived.size() > joinHopCount) {
01167                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01168                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01169                    << "    Error: too many state messages received in JOIN state! ("
01170                    << stReceived.size() << " > " << joinHopCount << ") Restarting ..."
01171                    << endl;
01172                 //std::cout << " failed!" << std::endl;
01173                 joinOverlay();
01174                 return;
01175             }
01176             if (stReceived.size() == joinHopCount) {
01177                 // all state messages are here, sort by hopcount:
01178                 sort(stReceived.begin(), stReceived.end(),
01179                      stateMsgIsSmaller);
01180 
01181                 // start pinging the nodes found in the first state message:
01182                 stReceivedPos = stReceived.begin();
01183                 stateCache = *stReceivedPos;
01184                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01185                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01186                    << "    have all STATE messages, now pinging nodes."
01187                    << endl;
01188                 if (pingBeforeSecondStage && proximityNeighborSelection) {
01189                     pingNodes();
01190                 } else {
01191                     mergeState(); // JOINING / stateCache
01192                     //endProcessingState(); //no way
01193                     stateCache.msg = NULL;
01194                     changeState(READY);
01195                     EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01196                        << " (" << thisNode.getKey().toString(16) << ")]\n"
01197                        << "    changeState(READY) called"
01198                        << endl;
01199                 }
01200 
01201                 // cancel timeout:
01202                 if (readyWait->isScheduled()) cancelEvent(readyWait);
01203             } else {
01204                 //TODO occasionally, here we got a wrong hop count in
01205                 // iterative mode due to more than one it. lookup during join
01206                 // procedure
01207                 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01208                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01209                    << "    Still need some STATE messages."
01210                    << endl;
01211             }
01212 
01213         }
01214         return;
01215     }
01216 
01217     if (debugOutput) {
01218         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01219            << " (" << thisNode.getKey().toString(16) << ")]\n"
01220            << "    handling STATE message"
01221            << endl;
01222         EV << "        type: " << ((msg->getPastryStateMsgType()
01223                                     == PASTRY_STATE_UPDATE) ? "update"
01224                                                             :"standard")
01225            << endl;
01226         if (msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE) {
01227             EV << "        msg timestamp:      " <<
01228                 msg->getTimestamp() << endl;
01229             EV << "        last state change:  " <<
01230                 lastStateChange << endl;
01231         }
01232     }
01233 
01234     if (((msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE))
01235             && (msg->getTimestamp() <= lastStateChange)) {
01236         // if we received an update based on our outdated state,
01237         // mark handle for retrying later:
01238         EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress()
01239            << " (" << thisNode.getKey().toString(16) << ")]\n"
01240            << "    outdated state from " << msg->getSender()
01241            << endl;
01242         handle.outdatedUpdate = true;
01243     }
01244 
01245     // determine aliveTable to prevent leafSet from merging nodes that are
01246     // known to be dead:
01247     determineAliveTable(msg);
01248 
01249     if (msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) {
01250         // try to repair leafset based on repair message right now
01251         const TransportAddress& askLs = leafSet->repair(msg, &aliveTable);
01252         if (! askLs.isUnspecified()) {
01253             sendRequest(askLs, PASTRY_REQ_REPAIR);
01254         }
01255 
01256         // while not really known, it's safe to assume that a repair
01257         // message changed our state:
01258         lastStateChange = simTime();
01259         newLeafs();
01260     } else if (leafSet->mergeState(msg, &aliveTable)) {
01261         // merged state into leafset right now
01262         lastStateChange = simTime();
01263         newLeafs();
01264         updateTooltip();
01265     }
01266     // in READY state, only ping nodes to get proximity metric:
01267     if (!stateCache.msg) {
01268         // no state message is processed right now, start immediately:
01269         stateCache = handle;
01270         processState();
01271     } else {
01272         if (proximityNeighborSelection && (pingBeforeSecondStage ||
01273             msg->getPastryStateMsgType() == PASTRY_STATE_STD)) {
01274             // enqueue message for later processing:
01275             stateCacheQueue.push(handle);
01276             prePing(msg);
01277         } else {
01278             bool temp = true;
01279             if (!neighborhoodSet->mergeState(msg, NULL)) {
01280                 temp = false;
01281             }
01282             if (!leafSet->mergeState(msg, NULL)) {
01283                 temp = false;
01284             } else {
01285                 newLeafs();
01286             }
01287             if (!routingTable->mergeState(msg, NULL)) {
01288                 temp = false;
01289             }
01290             if (temp) lastStateChange = simTime();
01291             delete msg;
01292         }
01293     }
01294 }

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

Reimplemented from BaseRpc.

Definition at line 243 of file Pastry.cc.

00244 {
00245 
00246     if (msg == joinTimeout) {
00247         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00248            << " (" << thisNode.getKey().toString(16) << ")]\n"
00249            << "    timeout expired, restarting..."
00250            << endl;
00251         join();
00252     } else if (msg == readyWait) {
00253         if (partialJoinPath) {
00254             RECORD_STATS(joinPartial++);
00255             sort(stReceived.begin(), stReceived.end(), stateMsgIsSmaller);
00256 
00257             // start pinging the nodes found in the first state message:
00258             stReceivedPos = stReceived.begin();
00259             stateCache = *stReceivedPos;
00260             EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00261                << " (" << thisNode.getKey().toString(16) << ")]\n"
00262                << "    joining despite some missing STATE messages."
00263                << endl;
00264             processState();
00265         } else {
00266             EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00267                << " (" << thisNode.getKey().toString(16) << ")]\n"
00268                << "    timeout waiting for missing state messages"
00269                << " in JOIN state, restarting..."
00270                << endl;
00271             joinOverlay();
00272         }
00273     } else if (msg == joinUpdateWait) {
00274         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00275            << " (" << thisNode.getKey().toString(16) << ")]\n"
00276            << "    sending state updates to all nodes."
00277            << endl;
00278         doJoinUpdate();
00279     } else if (msg == secondStageWait) {
00280         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00281            << " (" << thisNode.getKey().toString(16) << ")]\n"
00282            << "    sending STATE requests to all nodes in"
00283            << " second stage of initialization."
00284            << endl;
00285         doSecondStage();
00286     } else if (msg->isName("sendStateWait")) {
00287         PastrySendState* sendStateMsg = check_and_cast<PastrySendState*>(msg);
00288 
00289         std::vector<PastrySendState*>::iterator pos =
00290             std::find(sendStateWait.begin(), sendStateWait.end(),
00291                       sendStateMsg);
00292         if (pos != sendStateWait.end()) sendStateWait.erase(pos);
00293 
00294         sendStateTables(sendStateMsg->getDest());
00295         delete sendStateMsg;
00296     } else if (msg == discoveryTimeout) {
00297         if ((depth == 0) && (nearNodeImproved)) {
00298             depth++; //repeat last step if closer node was found
00299         }
00300         if ((depth == 0) || (pingedNodes < 1)) {
00301             changeState(JOINING_2);
00302         } else {
00303             PastryRoutingRowRequestMessage* msg =
00304                 new PastryRoutingRowRequestMessage("ROWREQ");
00305             msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00306             msg->setStatType(MAINTENANCE_STAT);
00307             msg->setSendStateTo(thisNode);
00308             msg->setRow(depth);
00309             msg->setBitLength(PASTRYRTREQ_L(msg));
00310             RECORD_STATS(routingTableReqSent++;
00311                          routingTableReqBytesSent += msg->getByteLength());
00312             sendMessageToUDP(nearNode, msg);
00313         }
00314     } else if (msg == repairTaskTimeout) {
00315         EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress()
00316            << " (" << thisNode.getKey().toString(16) << ")]\n"
00317            << "    starting routing table maintenance"
00318            << endl;
00319         doRoutingTableMaintenance();
00320         scheduleAt(simTime() + routingTableMaintenanceInterval,
00321                    repairTaskTimeout);
00322     }
00323 }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Definition at line 325 of file Pastry.cc.

00326 {
00327     PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg);
00328     uint32_t type = pastryMsg->getPastryMsgType();
00329 
00330     if (debugOutput) {
00331         EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00332            << " (" << thisNode.getKey().toString(16) << ")]\n"
00333            << "    incoming message of type ";
00334         switch(type) {
00335         case PASTRY_MSG_STD:
00336             EV << "PASTRY_MSG_STD";
00337             break;
00338         case PASTRY_MSG_JOIN:
00339             EV << "PASTRY_MSG_JOIN";
00340             break;
00341         case PASTRY_MSG_STATE:
00342             EV << "PASTRY_MSG_STATE";
00343             break;
00344         case PASTRY_MSG_LEAFSET:
00345             EV << "PASTRY_MSG_LEAFSET";
00346             break;
00347         case PASTRY_MSG_ROWREQ:
00348             EV << "PASTRY_MSG_ROWREQ";
00349             break;
00350         case PASTRY_MSG_RROW:
00351             EV << "PASTRY_MSG_RROW";
00352             break;
00353         case PASTRY_MSG_REQ:
00354             EV << "PASTRY_MSG_REQ";
00355             break;
00356         default:
00357             EV << "UNKNOWN (" << type <<")";
00358             break;
00359         }
00360         EV << endl;
00361     }
00362 
00363     switch (type) {
00364     case PASTRY_MSG_STD:
00365         opp_error("Pastry received PastryMessage of unknown type!");
00366         break;
00367 
00368     case PASTRY_MSG_JOIN: {
00369         PastryJoinMessage* jmsg =
00370             check_and_cast<PastryJoinMessage*>(pastryMsg);
00371         RECORD_STATS(joinReceived++; joinBytesReceived +=
00372                      jmsg->getByteLength());
00373         if (state != READY) {
00374             if (jmsg->getSendStateTo() == thisNode) {
00375                 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00376                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00377                    << "    PastryJoinMessage received by originator!"
00378                    << endl;
00379             } else {
00380                 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00381                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00382                    << "    received join message before reaching "
00383                    << "READY state, dropping message!"
00384                    << endl;
00385             }
00386         }
00387         else if (jmsg->getSendStateTo() == thisNode) {
00388             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00389                << " (" << thisNode.getKey().toString(16) << ")]\n"
00390                << "    PastryJoinMessage gets dropped because it is "
00391                << "outdated and has been received by originator!"
00392                << endl;
00393         } else {
00394             OverlayCtrlInfo* overlayCtrlInfo
00395                 = check_and_cast<OverlayCtrlInfo*>(jmsg->getControlInfo());
00396 
00397             uint32_t joinHopCount =  overlayCtrlInfo->getHopCount();
00398             if ((joinHopCount > 1) &&
00399                 ((defaultRoutingType == ITERATIVE_ROUTING) ||
00400                  (defaultRoutingType == EXHAUSTIVE_ITERATIVE_ROUTING)))
00401                  joinHopCount--;
00402 
00403             // remove node from state if it is rejoining
00404             handleFailedNode(jmsg->getSendStateTo());
00405 
00406             sendStateTables(jmsg->getSendStateTo(),
00407                             (minimalJoinState ?
00408                               PASTRY_STATE_MINJOIN : PASTRY_STATE_JOIN),
00409                              joinHopCount, true);
00410         }
00411 
00412         delete jmsg;
00413     }
00414     break;
00415 
00416     case PASTRY_MSG_LEAFSET: {
00417         PastryLeafsetMessage* lmsg =
00418             check_and_cast<PastryLeafsetMessage*>(pastryMsg);
00419         RECORD_STATS(leafsetReceived++; leafsetBytesReceived +=
00420             lmsg->getByteLength());
00421 
00422         if (state == DISCOVERY) {
00423             uint32_t lsSize = lmsg->getLeafSetArraySize();
00424             const NodeHandle* node;
00425             pingedNodes = 0;
00426 
00427             for (uint32_t i = 0; i < lsSize; i++) {
00428                 node = &(lmsg->getLeafSet(i));
00429                 // unspecified nodes not considered
00430                 if ( !(node->isUnspecified()) ) {
00431                     pingNode(*node, discoveryTimeoutAmount, 0,
00432                              NULL, "PING received leafs for nearest node",
00433                              NULL, -1, UDP_TRANSPORT);//TODO
00434                     pingedNodes++;
00435                }
00436             }
00437 
00438             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00439                << " (" << thisNode.getKey().toString(16) << ")]\n"
00440                << "    received leafset, waiting for pings"
00441               << endl;
00442 
00443             if (discoveryTimeout->isScheduled()) cancelEvent(discoveryTimeout);
00444             scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout);
00445             delete lmsg;
00446         } else if (state == READY) {
00447             handleLeafsetMessage(lmsg, false);
00448         } else {
00449             delete lmsg;
00450         }
00451     }
00452     break;
00453 
00454     case PASTRY_MSG_ROWREQ: {
00455         PastryRoutingRowRequestMessage* rtrmsg =
00456             check_and_cast<PastryRoutingRowRequestMessage*>(pastryMsg);
00457         RECORD_STATS(routingTableReqReceived++; routingTableReqBytesReceived +=
00458             rtrmsg->getByteLength());
00459         if (state == READY)
00460             if (rtrmsg->getRow() == -1)
00461                 sendRoutingRow(rtrmsg->getSendStateTo(), routingTable->getLastRow());
00462                 else if (rtrmsg->getRow() > routingTable->getLastRow())
00463                     EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00464                        << " (" << thisNode.getKey().toString(16) << ")]\n"
00465                        << "    received request for nonexistent routing"
00466                        << "table row, dropping message!"
00467                        << endl;
00468                 else sendRoutingRow(rtrmsg->getSendStateTo(), rtrmsg->getRow());
00469         else
00470             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00471                << " (" << thisNode.getKey().toString(16) << ")]\n"
00472                << "    received routing table request before reaching "
00473                << "READY state, dropping message!"
00474                << endl;
00475         delete rtrmsg;
00476     }
00477     break;
00478 
00479     case PASTRY_MSG_RROW: {
00480         PastryRoutingRowMessage* rtmsg =
00481             check_and_cast<PastryRoutingRowMessage*>(pastryMsg);
00482         RECORD_STATS(routingTableReceived++; routingTableBytesReceived +=
00483             rtmsg->getByteLength());
00484 
00485         if (state == DISCOVERY) {
00486             uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize();
00487             const NodeHandle* node;
00488             if (depth == -1) {
00489                 depth = rtmsg->getRow();
00490             }
00491             pingedNodes = 0;
00492             nearNodeImproved = false;
00493 
00494             if (depth > 0) {
00495                 for (uint32_t i = 0; i < nodesPerRow; i++) {
00496                     node = &(rtmsg->getRoutingTable(i));
00497                     // unspecified nodes not considered
00498                     if ( !(node->isUnspecified()) ) {
00499                         // we look for best connection here, so Timeout is short and there are no retries
00500                         pingNode(*node, discoveryTimeoutAmount, 0, NULL,
00501                                  "PING received routing table for nearest node",
00502                                  NULL, -1, UDP_TRANSPORT); //TODO
00503                         pingedNodes++;
00504                     }
00505                 }
00506                 depth--;
00507             }
00508             EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
00509                << " (" << thisNode.getKey().toString(16) << ")]\n"
00510                << "    received routing table, waiting for pings"
00511                << endl;
00512             if (discoveryTimeout->isScheduled()) {
00513                 cancelEvent(discoveryTimeout);
00514             }
00515             scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout);
00516         }
00517 
00518         else if (state == READY) {
00519 
00520             uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize();
00521             PastryStateMessage* stateMsg;
00522 
00523             stateMsg = new PastryStateMessage("STATE");
00524             stateMsg->setTimestamp(rtmsg->getTimestamp());
00525             stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00526             stateMsg->setStatType(MAINTENANCE_STAT);
00527             stateMsg->setSender(rtmsg->getSender());
00528             stateMsg->setLeafSetArraySize(0);
00529             stateMsg->setNeighborhoodSetArraySize(0);
00530             stateMsg->setRoutingTableArraySize(nodesPerRow);
00531 
00532             for (uint32_t i = 0; i < nodesPerRow; i++) {
00533                 stateMsg->setRoutingTable(i, rtmsg->getRoutingTable(i));
00534             }
00535 
00536             handleStateMessage(stateMsg);
00537         }
00538 
00539         delete rtmsg;
00540     }
00541     break;
00542 
00543     case PASTRY_MSG_REQ: {
00544         PastryRequestMessage* lrmsg =
00545             check_and_cast<PastryRequestMessage*>(pastryMsg);
00546         handleRequestMessage(lrmsg);
00547     }
00548     break;
00549 
00550     case PASTRY_MSG_STATE: {
00551         PastryStateMessage* stateMsg =
00552             check_and_cast<PastryStateMessage*>(msg);
00553         RECORD_STATS(stateReceived++; stateBytesReceived +=
00554                      stateMsg->getByteLength());
00555         handleStateMessage(stateMsg);
00556     }
00557     break;
00558     }
00559 }

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 80 of file Pastry.cc.

00081 {
00082     if ( stage != MIN_STAGE_OVERLAY )
00083         return;
00084 
00085     // Pastry provides KBR services
00086     kbr = true;
00087 
00088     baseInit();
00089 
00090     useDiscovery = par("useDiscovery");
00091     pingBeforeSecondStage = par("pingBeforeSecondStage");
00092     secondStageInterval = par("secondStageWait");
00093     discoveryTimeoutAmount = par("discoveryTimeoutAmount");
00094     routingTableMaintenanceInterval = par("routingTableMaintenanceInterval");
00095     sendStateAtLeafsetRepair = par("sendStateAtLeafsetRepair");
00096     partialJoinPath = par("partialJoinPath");
00097     readyWaitAmount = par("readyWait");
00098     minimalJoinState = par("minimalJoinState");
00099 
00100     overrideOldPastry = par("overrideOldPastry");
00101     overrideNewPastry = par("overrideNewPastry");
00102 
00103     if (overrideOldPastry) {
00104         //useSecondStage = true;
00105         //secondStageInterval = ???;
00106         useDiscovery = false;
00107         sendStateAtLeafsetRepair = true;
00108         routingTableMaintenanceInterval = 0;
00109     }
00110 
00111     if (overrideNewPastry) {
00112         //useSecondStage = false;
00113         secondStageInterval = 0;
00114         useDiscovery = true;
00115         discoveryTimeoutAmount = 0.4;
00116         routingTableMaintenanceInterval = 60;
00117         sendStateAtLeafsetRepair = false;
00118     }
00119 
00120     joinTimeout = new cMessage("joinTimeout");
00121     readyWait = new cMessage("readyWait");
00122     secondStageWait = new cMessage("secondStageWait");
00123     joinUpdateWait = new cMessage("joinUpdateWait");
00124 
00125     discoveryTimeout =
00126         (useDiscovery ? new cMessage("discoveryTimeout") : NULL);
00127     repairTaskTimeout =
00128         ((routingTableMaintenanceInterval > 0) ?
00129                 new cMessage("repairTaskTimeout") : NULL);
00130 
00131     updateCounter = 0;
00132 }

void Pastry::iterativeJoinHook ( BaseOverlayMessage *  msg,
bool  incrHopCount 
) [protected, virtual]

Reimplemented from BasePastry.

Definition at line 591 of file Pastry.cc.

00592 {
00593     PastryFindNodeExtData* findNodeExt = NULL;
00594     if (msg && msg->hasObject("findNodeExt")) {
00595         findNodeExt =
00596             check_and_cast<PastryFindNodeExtData*>(msg->
00597                     getObject("findNodeExt"));
00598     }
00599     // Send state tables on any JOIN message we see:
00600     if (findNodeExt) {
00601         const TransportAddress& stateRecipient =
00602             findNodeExt->getSendStateTo();
00603         if (!stateRecipient.isUnspecified()) {
00604             RECORD_STATS(joinSeen++);
00605             sendStateTables(stateRecipient,
00606                             minimalJoinState ?
00607                             PASTRY_STATE_MINJOIN : PASTRY_STATE_JOIN,
00608                             findNodeExt->getJoinHopCount(), false);
00609         }
00610         if (incrHopCount) {
00611             findNodeExt->setJoinHopCount(findNodeExt->getJoinHopCount() + 1);
00612         }
00613     }
00614 }

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 134 of file Pastry.cc.

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

00135 {
00136     changeState(INIT);
00137 
00138     if (bootstrapNode.isUnspecified()) {
00139         // no existing pastry network -> first node of a new one
00140         changeState(READY);
00141     } else {
00142         // join existing pastry network
00143         nearNode = bootstrapNode;
00144         if (useDiscovery) changeState(DISCOVERY);
00145         else changeState(JOINING_2);
00146     }
00147 }

bool Pastry::mergeState ( void   )  [private]

Definition at line 975 of file Pastry.cc.

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

00976 {
00977     bool ret = true;
00978 
00979     if (state == JOINING_2) {
00980         // building initial state
00981         if (debugOutput) {
00982             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00983                << " (" << thisNode.getKey().toString(16) << ")]\n"
00984                << "    [JOIN] starting to build own state from "
00985                << stReceived.size() << " received state messages..."
00986                << endl;
00987         }
00988         if (stateCache.msg &&
00989             stateCache.msg->getNeighborhoodSetArraySize() > 0) {
00990             if (debugOutput) {
00991                 EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
00992                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00993                    << "    [JOIN] initializing NeighborhoodSet from "
00994                    << stReceived.front().msg->getJoinHopCount() << ". hop"
00995                    << endl;
00996             }
00997             if (!neighborhoodSet->mergeState(stReceived.front().msg,
00998                                              stReceived.front().prox )) {
00999                 EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
01000                    << " (" << thisNode.getKey().toString(16) << ")]\n"
01001                    << "    Error initializing own neighborhoodSet"
01002                    << " while joining! Restarting ..."
01003                    << endl;
01004                 ret = false;
01005             }
01006         }
01007         if (debugOutput) {
01008             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
01009                << " (" << thisNode.getKey().toString(16) << ")]\n"
01010                << "    [JOIN] initializing LeafSet from "
01011                << stReceived.back().msg->getJoinHopCount() << ". hop"
01012                << endl;
01013         }
01014 
01015         //assert(!stateCache.msg || stateCache.msg->getLeafSetArraySize() > 0);
01016 
01017         if (!leafSet->mergeState(stReceived.back().msg,
01018                                  stReceived.back().prox )) {
01019             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
01020                << " (" << thisNode.getKey().toString(16) << ")]\n"
01021                << "    Error initializing own leafSet while joining!"
01022                << " Restarting ..."
01023                << endl;
01024             //std::cout << "Pastry: Error initializing own leafSet while "
01025             //                    "joining! Restarting ..." << std::endl;
01026             ret = false;
01027         } else {
01028             newLeafs();
01029         }
01030         if (debugOutput) {
01031             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
01032                << " (" << thisNode.getKey().toString(16) << ")]\n"
01033                << "    [JOIN] initializing RoutingTable from all hops"
01034                << endl;
01035         }
01036 
01037         assert(!stateCache.msg ||
01038                stateCache.msg->getRoutingTableArraySize() > 0);
01039 
01040         if (!routingTable->initStateFromHandleVector(stReceived)) {
01041             EV << "[Pastry::mergeState() @ " << thisNode.getAddress()
01042                << " (" << thisNode.getKey().toString(16) << ")]\n"
01043                << "    Error initializing own routingTable while joining!"
01044                << " Restarting ..."
01045                << endl;
01046             //std::cout << "Pastry: Error initializing own routingTable "
01047             //             "while joining! Restarting ..." << std::endl;
01048 
01049             ret = false;
01050         }
01051     } else if (state == READY) {
01052         // merging single state (stateCache.msg)
01053         if ((stateCache.msg->getNeighborhoodSetArraySize() > 0) &&
01054             (!neighborhoodSet->mergeState(stateCache.msg, NULL))) {
01055             ret = false;
01056         }
01057         if (!leafSet->mergeState(stateCache.msg, NULL)) {
01058             ret = false;
01059         } else {
01060             newLeafs();
01061         }
01062         if (!routingTable->mergeState(stateCache.msg, NULL)) {
01063             ret = false;
01064         }
01065     }
01066 
01067     if (ret) lastStateChange = simTime();
01068     return ret;
01069 }

void Pastry::pingResponse ( PingResponse *  pingResponse,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [virtual]

Reimplemented from BasePastry.

Definition at line 221 of file Pastry.cc.

00224 {
00225     if (state == DISCOVERY) {
00226         EV << "[Pastry::pingResponse() @ " << thisNode.getAddress()
00227            << " (" << thisNode.getKey().toString(16) << ")]\n"
00228            << "    Pong (or Ping-context from NeighborCache) received (from "
00229            << pingResponse->getSrcNode().getAddress() << ") in DISCOVERY mode"
00230            << endl;
00231 
00232         if (nearNodeRtt > rtt) {
00233             nearNode = pingResponse->getSrcNode();
00234             nearNodeRtt = rtt;
00235             nearNodeImproved = true;
00236         }
00237     } else {
00238         BasePastry::pingResponse(pingResponse, context, rpcId, rtt);
00239     }
00240 }

void Pastry::processState ( void   )  [private]

Definition at line 1296 of file Pastry.cc.

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

01297 {
01298     if (proximityNeighborSelection && (pingBeforeSecondStage ||
01299         stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_STD)) {
01300         pingNodes();
01301     } else {
01302         mergeState();
01303         endProcessingState();
01304     }
01305 }

void Pastry::purgeVectors ( void   )  [protected, virtual]

delete all information/messages caching vectors, used for restarting overlay or finish()

Reimplemented from BasePastry.

Definition at line 73 of file Pastry.cc.

Referenced by changeState().

00074 {
00075     clearVectors();
00076 
00077     BasePastry::purgeVectors();
00078 }

bool Pastry::recursiveRoutingHook ( const TransportAddress dest,
BaseRouteMessage *  msg 
) [protected, virtual]

Hook for forwarded message in recursive lookup mode.

This hook is called just before a message is forwarded to a next hop or if the message is at its destination just before it is sent to the app. Default implementation just returns true. This hook can for example be used to detect failed nodes and call handleFailedNode() before the actual forwarding takes place.

Parameters:
dest destination node
msg message to send
Returns:
true, if message should be forwarded; false, if message will be forwarded later by an other function or message has been discarded

Reimplemented from BaseOverlay.

Definition at line 562 of file Pastry.cc.

00564 {
00565     if (dest == thisNode) {
00566         return true;
00567     }
00568 
00569     PastryMessage* pmsg =
00570         dynamic_cast<PastryMessage*>(msg->getEncapsulatedPacket());
00571 
00572     if (pmsg && pmsg->getPastryMsgType() == PASTRY_MSG_JOIN) {
00573         PastryJoinMessage* jmsg = static_cast<PastryJoinMessage*>(pmsg);
00574         if (jmsg->getSendStateTo() != thisNode) {
00575             RECORD_STATS(joinSeen++; joinBytesSeen += jmsg->getByteLength());
00576             // remove node from state if it is rejoining
00577             handleFailedNode(jmsg->getSendStateTo());
00578 
00579             sendStateTables(jmsg->getSendStateTo(),
00580                             minimalJoinState ?
00581                             PASTRY_STATE_MINJOIN : PASTRY_STATE_JOIN,
00582                             check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo())
00583                             ->getHopCount(), false);
00584         }
00585     }
00586 
00587     // forward now:
00588     return true;
00589 }


Member Data Documentation

int Pastry::depth [private]

Definition at line 110 of file Pastry.h.

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

cMessage* Pastry::discoveryTimeout [private]

Definition at line 125 of file Pastry.h.

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

simtime_t Pastry::discoveryTimeoutAmount [private]

Definition at line 107 of file Pastry.h.

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

bool Pastry::minimalJoinState [private]
std::vector<TransportAddress> Pastry::notifyList [protected]

List of nodes to notify after join.

Definition at line 99 of file Pastry.h.

Referenced by changeState(), clearVectors(), doJoinUpdate(), and doSecondStage().

bool Pastry::overrideNewPastry [private]

Definition at line 121 of file Pastry.h.

Referenced by initializeOverlay().

bool Pastry::overrideOldPastry [private]

Definition at line 120 of file Pastry.h.

Referenced by initializeOverlay().

bool Pastry::partialJoinPath [private]

Definition at line 108 of file Pastry.h.

Referenced by handleTimerEvent(), and initializeOverlay().

Definition at line 118 of file Pastry.h.

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

cMessage* Pastry::repairTaskTimeout [private]

Definition at line 126 of file Pastry.h.

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

cMessage* Pastry::ringCheck [private]

Definition at line 124 of file Pastry.h.

Definition at line 106 of file Pastry.h.

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

simtime_t Pastry::secondStageInterval [private]

Definition at line 105 of file Pastry.h.

Referenced by changeState(), and initializeOverlay().

cMessage* Pastry::secondStageWait [private]

Definition at line 123 of file Pastry.h.

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

Definition at line 117 of file Pastry.h.

Referenced by handleFailedNode(), and initializeOverlay().

std::vector<PastryStateMsgHandle> Pastry::stReceived [protected]

State messages to process during join.

Definition at line 93 of file Pastry.h.

Referenced by checkProxCache(), clearVectors(), doJoinUpdate(), handleStateMessage(), handleTimerEvent(), and mergeState().

std::vector<PastryStateMsgHandle>::iterator Pastry::stReceivedPos [protected]

Definition at line 94 of file Pastry.h.

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

int Pastry::updateCounter [private]

Definition at line 112 of file Pastry.h.

Referenced by checkProxCache(), and initializeOverlay().

bool Pastry::useDiscovery [private]

Definition at line 115 of file Pastry.h.

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

bool Pastry::useSecondStage [private]

Definition at line 116 of file Pastry.h.


The documentation for this class was generated from the following files:
Generated on Wed May 26 16:21:18 2010 for OverSim by  doxygen 1.6.3