Pastry Class Reference

#include <Pastry.h>

Inheritance diagram for Pastry:

BaseOverlay BaseRpc TopologyVis RpcListener

List of all members.


Detailed Description

Pastry overlay module.

Author:
Felix Palmen
See also:
BaseOverlay

Public Member Functions

virtual ~Pastry ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void handleTimerEvent (cMessage *msg)
 Processes "timer" self-messages.
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
virtual void handleRpcResponse (BaseResponseMessage *msg, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
void handleStateMessage (PastryStateMessage *msg)
 processes state messages, merging with own state tables
virtual void handleAppMessage (BaseOverlayMessage *msg)
 processes messages from application
virtual void finishOverlay ()
 collects statistical data in derived class
virtual void updateTooltip ()
 updates information shown in tk-environment
virtual NodeVectorfindNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg)
 Implements the find node call.
int getMaxNumSiblings ()
 Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.
int getMaxNumRedundantNodes ()
 Query the maximum number of redundant next hop nodes that are returned by findNode().

Protected Member Functions

virtual void changeState (int toState)
 changes node state
void sendStateTables (const TransportAddress &destination, int type=PASTRY_STATE_STD,...)
 send a PastryStateMessage directly to a node
void sendStateDelayed (const TransportAddress &destination)
 send a standard state message with a small delay
virtual bool isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err)
 Query if a node is among the siblings for a given key.
virtual AbstractLookupcreateLookup (const BaseOverlayMessage *msg=NULL)

Protected Attributes

int joins
int joinTries
int joinPartial
int joinSeen
int joinBytesSeen
int joinReceived
int joinBytesReceived
int joinSent
int joinBytesSent
int stateSent
int stateBytesSent
int stateReceived
int stateBytesReceived
int repairReqSent
int repairReqBytesSent
int repairReqReceived
int repairReqBytesReceived
int stateReqSent
int stateReqBytesSent
int stateReqReceived
int stateReqBytesReceived
int totalLookups
int responsibleLookups
int routingTableLookups
int closerNodeLookups
int closerNodeLookupsFromNeighborhood

Private Member Functions

virtual bool forwardMessageRecursive (const TransportAddress &dest, BaseRouteMessage *msg)
 Hook for forwarded message in recursive lookup mode.
void doJoinUpdate (void)
 send updated state to all nodes when entering ready state
void doSecondStage (void)
 do the second stage of initialization as described in the paper
void purgeVectors (void)
 delete all information/messages caching vectors, used for restarting overlay or finish()
void prePing (const PastryStateMessage *stateMsg)
 ping all nodes in a given state message.
void pingNodes (void)
 ping all nodes in the pastry state message pointed to by private member stateCache
void determineAliveTable (const PastryStateMessage *stateMsg)
 change the aliveTable to match the given stateMsg.
void checkProxCache (void)
 checks whether proxCache is complete, takes appropriate actions depending on the protocol state
void sendRepairRequest (const TransportAddress &ask)
 send a repair request to a given node
bool handleFailedNode (const TransportAddress &failed)
 notifies leafset and routingtable of a failed node and sends out a repair request if possible
virtual void joinOverlay ()
 Join the overlay with a given nodeID in thisNode.key.
void setOwnNodeID ()
void newLeafs (void)
 Pastry API: send newLeafs() to application if enabled.

Private Attributes

PastryRoutingTableroutingTable
PastryLeafSetleafSet
PastryNeighborhoodSetneighborhoodSet
uint bitsPerDigit
uint numberOfLeaves
uint numberOfNeighbors
uint pingRetries
double pingTimeout
double readyWaitAmount
double joinTimeoutAmount
double secondStageWaitAmount
double pingCacheExpireTime
double repairTimeout
double ringCheckInterval
double sendStateWaitAmount
bool enableNewLeafs
bool optimizeLookup
bool optimisticForward
bool avoidDuplicates
bool partialJoinPath
bool useRegularNextHop
bool alwaysSendUpdate
bool coordBasedRouting
uint numCoordDigits
uint CBRstartAtDigit
uint CBRstopAtDigit
NodeHandle bootstrapNode
std::vector
< PastryStateMsgHandle
stReceived
 State messages to process during join.
std::vector
< PastryStateMsgHandle >
::iterator 
stReceivedPos
std::vector
< TransportAddress
notifyList
 List of nodes to notify after join.
PastryStateMsgHandle stateCache
 Handle for processing a single state message.
std::queue
< PastryStateMsgHandle
stateCacheQueue
 Queue of state messages waiting to be processed in READY state.
PastryStateMsgProximity aliveTable
 Early update of leaf set: helper structure for marking known-dead nodes.
PastryPingCache pingCache
 caches RPC Ping RTTs
std::map
< TransportAddress,
BaseRouteMessage * > 
recFwdQueue
 Queue of messages to be forwarded in recursive routing mode.
uint joinHopCount
cMessage * joinTimeout
cMessage * readyWait
cMessage * secondStageWait
cMessage * joinUpdateWait
cMessage * ringCheck
std::vector
< PastrySendState * > 
sendStateWait
simtime_t lastStateChange

Friends

class PastryLeafSet

Constructor & Destructor Documentation

Pastry::~Pastry (  )  [virtual]

00038 {
00039     // destroy self timer messages
00040     cancelAndDelete(joinTimeout);
00041     cancelAndDelete(readyWait);
00042     cancelAndDelete(joinUpdateWait);
00043     cancelAndDelete(secondStageWait);
00044     cancelAndDelete(ringCheck);
00045 
00046     purgeVectors();
00047 }


Member Function Documentation

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.

00050 {
00051     if ( stage != MIN_STAGE_OVERLAY )
00052         return;
00053 
00054     bitsPerDigit = par("bitsPerDigit");
00055     numberOfLeaves = par("numberOfLeaves");
00056     numberOfNeighbors = par("numberOfNeighbors");
00057     joinTimeoutAmount = par("joinTimeout");
00058     readyWaitAmount = par("readyWait");
00059     secondStageWaitAmount = par("secondStageWait");
00060     pingCacheExpireTime = par("pingCacheExpireTime");
00061     repairTimeout = par("repairTimeout");
00062     enableNewLeafs = par("enableNewLeafs");
00063     optimizeLookup = par("optimizeLookup");
00064     optimisticForward = par("optimisticForward");
00065     avoidDuplicates = par("avoidDuplicates");
00066     ringCheckInterval = par("ringCheckInterval");
00067     sendStateWaitAmount = par("sendStateWaitAmount");
00068     partialJoinPath = par("partialJoinPath");
00069     pingTimeout = par("pingTimeout");
00070     pingRetries = par("pingRetries");
00071     useRegularNextHop = par("useRegularNextHop");
00072     alwaysSendUpdate = par("alwaysSendUpdate");
00073 
00074     // coordinate-based routing (CBR)
00075     coordBasedRouting = par("coordBasedRouting");
00076     if(coordBasedRouting &&
00077        !dynamic_cast<SimpleNetConfigurator*>(underlayConfigurator)) {
00078         opp_error("Coordinate-based routing currently only"
00079                   " possible in SimpleUnderlay!");
00080     }
00081     numCoordDigits = par("numCoordDigits");
00082     CBRstartAtDigit = par("CBRstartAtDigit");
00083     CBRstopAtDigit = par("CBRstopAtDigit");
00084 
00085     if (numberOfLeaves % 2) {
00086         EV << "Pastry: Warning: numberOfLeaves must be even - adding 1.";
00087         numberOfLeaves++;
00088     }
00089 
00090     routingTable = check_and_cast<PastryRoutingTable*>
00091         (parentModule()->submodule("pastryRoutingTable"));
00092     leafSet = check_and_cast<PastryLeafSet*>
00093         (parentModule()->submodule("pastryLeafSet"));
00094     neighborhoodSet = check_and_cast<PastryNeighborhoodSet*>
00095         (parentModule()->submodule("pastryNeighborhoodSet"));
00096 
00097     joinTimeout = new cMessage("joinTimeout");
00098     readyWait = new cMessage("readyWait");
00099     secondStageWait = new cMessage("secondStageWait");
00100     joinUpdateWait = new cMessage("joinUpdateWait");
00101     ringCheck = new cMessage("ringCheck");
00102 
00103     stateCache.msg = NULL;
00104     stateCache.prox = NULL;
00105 
00106     // initialize statistics
00107     joins = 0;
00108     joinTries = 0;
00109     joinPartial = 0;
00110     joinSeen = 0;
00111     joinReceived = 0;
00112     joinSent = 0;
00113     stateSent = 0;
00114     stateReceived = 0;
00115     repairReqSent = 0;
00116     repairReqReceived = 0;
00117     stateReqSent = 0;
00118     stateReqReceived = 0;
00119 
00120     joinBytesSeen = 0;
00121     joinBytesReceived = 0;
00122     joinBytesSent = 0;
00123     stateBytesSent = 0;
00124     stateBytesReceived = 0;
00125     repairReqBytesSent = 0;
00126     repairReqBytesReceived = 0;
00127     stateReqBytesSent = 0;
00128     stateReqBytesReceived = 0;
00129 
00130     totalLookups = 0;
00131     responsibleLookups = 0;
00132     routingTableLookups = 0;
00133     closerNodeLookups = 0;
00134     closerNodeLookupsFromNeighborhood = 0;
00135 
00136     WATCH(joins);
00137     WATCH(joinTries);
00138     WATCH(joinSeen);
00139     WATCH(joinBytesSeen);
00140     WATCH(joinReceived);
00141     WATCH(joinBytesReceived);
00142     WATCH(joinSent);
00143     WATCH(joinBytesSent);
00144     WATCH(stateSent);
00145     WATCH(stateBytesSent);
00146     WATCH(stateReceived);
00147     WATCH(stateBytesReceived);
00148     WATCH(repairReqSent);
00149     WATCH(repairReqBytesSent);
00150     WATCH(repairReqReceived);
00151     WATCH(repairReqBytesReceived);
00152     WATCH(stateReqSent);
00153     WATCH(stateReqBytesSent);
00154     WATCH(stateReqReceived);
00155     WATCH(stateReqBytesReceived);
00156     WATCH(lastStateChange);
00157 }

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

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from BaseOverlay.

00356 {
00357 
00358     if (msg->isName("joinTimeout")) {
00359         EV << "Pastry: join timeout expired, restarting..." << endl;
00360         //std::cout << "join timeout @ " << thisNode << std::endl;
00361         joinOverlay();
00362     } else if (msg->isName("readyWait")) {
00363         if (partialJoinPath) {
00364             RECORD_STATS(joinPartial++);
00365             sort(stReceived.begin(), stReceived.end(), stateMsgIsSmaller);
00366 
00367             // start pinging the nodes found in the first state message:
00368             stReceivedPos = stReceived.begin();
00369             stateCache = *stReceivedPos;
00370             EV << "Pastry: joining despite some missing STATE messages."
00371                << endl;
00372             pingNodes();
00373         } else {
00374             EV << "Pastry: timeout waiting for missing state messages in JOIN "
00375                 "state, restarting..." << endl;
00376             joinOverlay();
00377         }
00378     } else if (msg->isName("joinUpdateWait")) {
00379         EV << "Pastry: sending state updates to all nodes." << endl;
00380         doJoinUpdate();
00381     } else if (msg->isName("secondStageWait")) {
00382         EV << "Pastry: sending STATE requests to all nodes in second stage "
00383             "of initialization." << endl;
00384         doSecondStage();
00385     } else if (msg->isName("ringCheck")) {
00386         if (state == READY) {
00387             // ping direct neighbors on the ring:
00388             const NodeHandle& pred = leafSet->getPredecessor();
00389             const NodeHandle& succ = leafSet->getSuccessor();
00390             if (! pred.isUnspecified()) {
00391                 pingNode(pred, pingTimeout, pingRetries, "PING ring check");
00392             }
00393             if (! succ.isUnspecified()) {
00394                 pingNode(succ, pingTimeout, pingRetries, "PING ring check");
00395             }
00396         }
00397         scheduleAt(simTime()+ringCheckInterval, ringCheck);
00398     } else if (msg->isName("sendStateWait")) {
00399         PastrySendState* sendStateMsg = check_and_cast<PastrySendState*>(msg);
00400 
00401         std::vector<PastrySendState*>::iterator pos =
00402             std::find(sendStateWait.begin(), sendStateWait.end(),
00403                       sendStateMsg);
00404         if (pos != sendStateWait.end()) sendStateWait.erase(pos);
00405 
00406         sendStateTables(sendStateMsg->getDest());
00407         delete sendStateMsg;
00408     }
00409 }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

00412 {
00413     PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg);
00414     uint type = pastryMsg->getPastryMsgType();
00415 
00416     if (debugOutput) {
00417         EV << "Pastry: incoming message of type ";
00418         switch(type) {
00419         case PASTRY_MSG_STD:
00420             EV << "PASTRY_MSG_STD";
00421             break;
00422         case PASTRY_MSG_JOIN:
00423             EV << "PASTRY_MSG_JOIN";
00424             break;
00425         case PASTRY_MSG_STATE:
00426             EV << "PASTRY_MSG_STATE";
00427             break;
00428         case PASTRY_MSG_RREQ:
00429             EV << "PASTRY_MSG_RREQ";
00430             break;
00431         case PASTRY_MSG_SREQ:
00432             EV << "PASTRY_MSG_SREQ";
00433             break;
00434         default:
00435             EV << "UNKNOWN (" << type <<")";
00436             break;
00437         }
00438         EV << endl;
00439     }
00440 
00441     switch (type) {
00442     case PASTRY_MSG_STD:
00443         opp_error("Pastry received PastryMessage of unknown type!");
00444         break;
00445 
00446     case PASTRY_MSG_JOIN: {
00447         PastryJoinMessage* jmsg =
00448             check_and_cast<PastryJoinMessage*>(pastryMsg);
00449         RECORD_STATS(joinReceived++; joinBytesReceived +=
00450                      jmsg->byteLength());
00451         if (state != READY) {
00452             if (jmsg->getSendStateTo() == thisNode) {
00453                 EV << "[Pastry::handleUDPMessage() @ " << thisNode.ip
00454                    << " (" << thisNode.key.toString(16) << ")]\n"
00455                    << "    PastryJoinMessage received by originator!";
00456             } else {
00457                 EV << "Pastry: received join message before reaching "
00458                    << "READY state, dropping message!" << endl;
00459             }
00460         }
00461         else if (jmsg->getSendStateTo() == thisNode) {
00462             EV << "[Pastry::handleUDPMessage() @ " << thisNode.ip
00463                << " (" << thisNode.key.toString(16) << ")]\n"
00464                << "    PastryJoinMessage gets dropped because it is "
00465                << "outdated and has been received by originator!"
00466                << endl;
00467         } else {
00468             sendStateTables(jmsg->getSendStateTo(),
00469                             PASTRY_STATE_JOIN, jmsg->getJoinHopCount(),
00470                             true);
00471         }
00472 
00473         delete jmsg;
00474     }
00475         break;
00476 
00477     case PASTRY_MSG_RREQ: {
00478         PastryRepairRequestMessage* rrmsg =
00479             check_and_cast<PastryRepairRequestMessage*>(pastryMsg);
00480         RECORD_STATS(repairReqReceived++; repairReqBytesReceived +=
00481                      rrmsg->byteLength());
00482         if (state == READY)
00483             sendStateTables(rrmsg->getSendStateTo(),
00484                             PASTRY_STATE_REPAIR);
00485         else
00486             EV << "Pastry: received repair request before reaching "
00487                << "READY state, dropping message!" << endl;
00488         delete rrmsg;
00489     }
00490         break;
00491 
00492     case PASTRY_MSG_SREQ: {
00493         PastryStateRequestMessage* srmsg =
00494             check_and_cast<PastryStateRequestMessage*>(pastryMsg);
00495         RECORD_STATS(stateReqReceived++; stateReqBytesReceived +=
00496                      srmsg->byteLength());
00497         if (state == READY)
00498             sendStateTables(srmsg->getSendStateTo());
00499         else
00500             EV << "Pastry: received state request before reaching "
00501                << "READY state, dropping message!" << endl;
00502         delete srmsg;
00503     }
00504         break;
00505 
00506     case PASTRY_MSG_STATE: {
00507         PastryStateMessage* stateMsg =
00508             check_and_cast<PastryStateMessage*>(msg);
00509         RECORD_STATS(stateReceived++; stateBytesReceived +=
00510                      stateMsg->byteLength());
00511         handleStateMessage(stateMsg);
00512     }
00513         break;
00514     }
00515 }

void Pastry::handleRpcResponse ( BaseResponseMessage *  msg,
int  rpcId,
simtime_t  rtt 
) [virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

00768 {
00769     const NodeHandle& src = msg->getSrcNode();
00770 
00771     // a node with the an equal ID has responsed
00772     if (src.key == thisNode.key) {
00773         joinOverlay();
00774         return;
00775     }
00776 
00777     const NodeHandle* node;
00778     int i;
00779     int n;
00780     PastryPingCacheEntry pce;
00781     std::map<TransportAddress, BaseRouteMessage*>::iterator pos;
00782 
00783     RPC_SWITCH_START(msg)
00784         RPC_ON_RESPONSE(Ping) {
00785         // insert into pingCache
00786         pce.inserted = simTime();
00787         pce.rtt = rtt;
00788         pingCache[src.ip] = pce;
00789 
00790         if (stateCache.msg && stateCache.prox) {
00791             // look for node in routing table of processed state message:
00792             n = stateCache.msg->getRoutingTableArraySize();
00793             for (i = 0; i < n; i++) {
00794                 node = &(stateCache.msg->getRoutingTable(i));
00795                 if ((!node->isUnspecified()) && (*node == src))
00796                     *(stateCache.prox->pr_rt.begin()+i) = rtt;
00797             }
00798 
00799             // look for node in leaf set of processed state message:
00800             n = stateCache.msg->getLeafSetArraySize();
00801             for (i = 0; i < n; i++) {
00802                 node = &(stateCache.msg->getLeafSet(i));
00803                 if ((!node->isUnspecified()) && (*node == src))
00804                     *(stateCache.prox->pr_ls.begin()+i) = rtt;
00805             }
00806 
00807             // look for node in neighb. set of processed state message:
00808             n = stateCache.msg->getNeighborhoodSetArraySize();
00809             for (i = 0; i < n; i++) {
00810                 node = &(stateCache.msg->getNeighborhoodSet(i));
00811                 if ((!node->isUnspecified()) && (*node == src))
00812                     *(stateCache.prox->pr_ns.begin()+i) = rtt;
00813             }
00814 
00815             checkProxCache();
00816         }
00817 
00818         if ((pos = recFwdQueue.find(src)) != recFwdQueue.end()) {
00819             // send message
00820             if (!optimisticForward) {
00821                 sendMessageToUDP(pos->first, pos->second);
00822             } else if (!avoidDuplicates) {
00823                 delete pos->second;
00824             }
00825             recFwdQueue.erase(pos);
00826         }
00827 
00828         break;
00829     }
00830     RPC_SWITCH_END()
00831         }

void Pastry::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
int  rpcId,
const OverlayKey destKey 
) [virtual]

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

01151 {
01152     const NodeHandle* node;
01153     int i;
01154     int n;
01155     PastryPingCacheEntry pce;
01156     std::map<TransportAddress, BaseRouteMessage*>::iterator pos;
01157 
01158     RPC_SWITCH_START(msg)
01159         RPC_ON_CALL(Ping) {
01160         EV << "Pastry: Ping timeout occured." << endl;
01161 
01162         // update ping cache:
01163         pce.inserted = simTime();
01164         pce.rtt = PASTRY_PROX_INFINITE;
01165         pingCache[dest.ip] = pce;
01166 
01167         // handle failed node
01168         if (state == READY) {
01169             handleFailedNode(dest);
01170             updateTooltip();
01171 
01172             // this could initiate a re-join, exit the handler in that
01173             // case because all local data was erased:
01174             if (state != READY) break;
01175         }
01176 
01177         if (stateCache.msg && stateCache.prox &&
01178                 msg->isName("PING received state")) {
01179             // look for node in routing table of processed state message:
01180             n = stateCache.msg->getRoutingTableArraySize();
01181             for (i = 0; i < n; i++) {
01182                 node = &(stateCache.msg->getRoutingTable(i));
01183                 if ((!node->isUnspecified()) && (node->ip == dest.ip))
01184                     *(stateCache.prox->pr_rt.begin() + i) = PASTRY_PROX_INFINITE;
01185             }
01186 
01187             // look for node in leaf set of processed state message:
01188             n = stateCache.msg->getLeafSetArraySize();
01189             for (i = 0; i < n; i++) {
01190                 node = &(stateCache.msg->getLeafSet(i));
01191                 if ((!node->isUnspecified()) && (node->ip == dest.ip))
01192                     *(stateCache.prox->pr_ls.begin() + i) = PASTRY_PROX_INFINITE;
01193             }
01194 
01195             // look for node in neighborhood set of processed state message:
01196             n = stateCache.msg->getNeighborhoodSetArraySize();
01197             for (i = 0; i < n; i++) {
01198                 node = &(stateCache.msg->getNeighborhoodSet(i));
01199                 if ((!node->isUnspecified()) && (node->ip == dest.ip))
01200                     *(stateCache.prox->pr_ns.begin() + i) = PASTRY_PROX_INFINITE;
01201             }
01202             checkProxCache();
01203         }
01204 
01205         if (msg->isName("PING next hop")) {
01206             // handle forward queue entry
01207             if ((pos = recFwdQueue.find(dest)) == recFwdQueue.end()) break;
01208             BaseRouteMessage* rmsg = pos->second;
01209             recFwdQueue.erase(pos);
01210             if (dynamic_cast<PastryJoinMessage*>(rmsg->encapsulatedMsg()) &&
01211                 rmsg->getDestKey() == thisNode.key) {
01212                 std::cout << "join timeout -> rejoin!";
01213                 changeState(INIT);
01214                 break;
01215             }
01216             assert(rmsg->controlInfo());
01217             sendToKey(rmsg->getDestKey(), rmsg);
01218         }
01219 
01220         break;
01221     }
01222     RPC_SWITCH_END()
01223 }

void Pastry::handleStateMessage ( PastryStateMessage *  msg  ) 

processes state messages, merging with own state tables

Parameters:
msg the pastry state message
00518 {
00519     if (debugOutput) {
00520         EV << "Pastry::handleStateMessage() new STATE message to process "
00521            << static_cast<void*>(msg) << " in state " <<
00522             ((state == READY)?"READY":((state == JOIN)?"JOIN":"INIT"))
00523            << endl;
00524         if (state == JOIN) {
00525             EV << " ***   own joinHopCount:  " << joinHopCount << endl;
00526             EV << " ***   already received:  " << stReceived.size() << endl;
00527             EV << " ***   last-hop flag:     " << msg->getLastHop() << endl;
00528             EV << " ***   msg joinHopCount:  "
00529                << msg->getJoinHopCount() << endl;
00530         }
00531     }
00532     if (state == INIT) {
00533         EV << "Pastry: can't handle state messages until at least reaching "
00534             "JOIN state." << endl;
00535         delete msg;
00536         return;
00537     }
00538 
00539     PastryStateMsgHandle handle(msg);
00540 
00541     // in JOIN state, store all received state Messages, need them later:
00542     if (state == JOIN) {
00543         if (joinHopCount && stReceived.size() == joinHopCount) {
00544             EV << "Pastry: Warning: dropping state message received after "
00545                 "all needed state messages were collected in JOIN state."
00546                << endl;
00547             delete msg;
00548             return;
00549         }
00550 
00551         stReceived.push_back(handle);
00552         prePing(msg);
00553 
00554         if (msg->getLastHop()) {
00555             if (joinTimeout->isScheduled()) cancelEvent(joinTimeout);
00556             if (msg->getSender().key == thisNode.key) {
00557                 EV << "Pastry: Error: OverlayKey already in use, restarting!"
00558                    << endl;
00559                 joinOverlay();
00560                 return;
00561             }
00562 
00563             if (joinHopCount) {
00564                 EV << "Pastry: Error: received a second `last' state message! "
00565                     "Restarting ..." << endl;
00566                 joinOverlay();
00567                 return;
00568             }
00569 
00570             joinHopCount = msg->getJoinHopCount();
00571             if (stReceived.size() < joinHopCount) {
00572                 // some states still missing:
00573                 cancelEvent(readyWait);
00574                 scheduleAt(simTime()+readyWaitAmount, readyWait);
00575             }
00576         }
00577 
00578         if (joinHopCount) {
00579             if (stReceived.size() > joinHopCount) {
00580                 EV << "Pastry: Error: too many state messages received in "
00581                     "JOIN state! Restarting ..." << endl;
00582                 joinOverlay();
00583                 return;
00584             }
00585             if (stReceived.size() == joinHopCount) {
00586                 // all state messages are here, sort by hopcount:
00587                 sort(stReceived.begin(), stReceived.end(),
00588                      stateMsgIsSmaller);
00589 
00590                 // start pinging the nodes found in the first state message:
00591                 stReceivedPos = stReceived.begin();
00592                 stateCache = *stReceivedPos;
00593                 EV << "Pastry: have all STATE messages, now pinging nodes."
00594                    << endl;
00595                 pingNodes();
00596 
00597                 // cancel timeout:
00598                 if (readyWait->isScheduled()) cancelEvent(readyWait);
00599             }
00600         }
00601         return;
00602     }
00603 
00604     if (debugOutput) {
00605         EV << "Pastry: handling STATE message" << endl;
00606         EV << "        type: " <<
00607         ((msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE)?
00608          "update":"standard") << endl;
00609         if (msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE) {
00610             EV << "        msg timestamp:      " <<
00611             msg->getTimestamp() << endl;
00612             EV << "        last state change:  " <<
00613             lastStateChange << endl;
00614         }
00615     }
00616 
00617     if (((msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE))
00618             && (msg->getTimestamp() <= lastStateChange)) {
00619         // if we received an update based on our outdated state,
00620         // mark handle for retrying later:
00621         EV << "Pastry: outdated state from " << msg->getSender() << endl;
00622         handle.outdatedUpdate = true;
00623     }
00624 
00625     // determine aliveTable to prevent leafSet from merging nodes that are
00626     // known to be dead:
00627     determineAliveTable(msg);
00628 
00629     if (msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) {
00630         // try to repair leafset based on repair message right now
00631         const TransportAddress& askLs = leafSet->repair(msg, aliveTable);
00632         if (! askLs.isUnspecified()) {
00633             //std::cout << "LS needs to be repaired!" << std::endl;
00634             sendRepairRequest(askLs);
00635         }
00636 
00637         // while not really known, it's safe to assume that a repair
00638         // message changed our state:
00639         lastStateChange = simTime();
00640         newLeafs();
00641     } else if (leafSet->mergeState(msg, aliveTable)) {
00642         // merged state into leafset right now
00643         lastStateChange = simTime();
00644         newLeafs();
00645     }
00646 
00647     // in READY state, only ping nodes to get proximity metric:
00648     if (!stateCache.msg) {
00649         // no state message is processed right now, start immediately:
00650         stateCache = handle;
00651         pingNodes();
00652     } else {
00653         // enqueue message for later processing:
00654         stateCacheQueue.push(handle);
00655         prePing(msg);
00656     }
00657 }

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

processes messages from application

Parameters:
msg message from application
01396 {
01397     delete msg;
01398 }

void Pastry::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

01425 {
01426     // remove this node from the bootstrap list
01427     if (!thisNode.key.isUnspecified()) removeBootstrapNode(thisNode);
01428 
01429     // collect statistics
01430     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01431     if(time == 0) return;
01432 
01433     globalStatistics->addStdDev("Pastry: Successful Joins/s", joins / time);
01434     globalStatistics->addStdDev("Pastry: overall join tries/s", joinTries / time);
01435     globalStatistics->addStdDev("Pastry: joins with missing replies from routing path/s",
01436                                 joinPartial / time);
01437     globalStatistics->addStdDev("Pastry: JOIN Messages seen/s", joinSeen / time);
01438     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages seen/s", joinBytesSeen / time);
01439     globalStatistics->addStdDev("Pastry: JOIN Messages received/s", joinReceived / time);
01440     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages received/s",
01441                                 joinBytesReceived / time);
01442     globalStatistics->addStdDev("Pastry: JOIN Messages sent/s", joinSent / time);
01443     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages sent/s", joinBytesSent / time);
01444     globalStatistics->addStdDev("Pastry: STATE Messages sent/s", stateSent / time);
01445     globalStatistics->addStdDev("Pastry: bytes of STATE Messages sent/s", stateBytesSent / time);
01446     globalStatistics->addStdDev("Pastry: STATE Messages received/s", stateReceived / time);
01447     globalStatistics->addStdDev("Pastry: bytes of STATE Messages received/s",
01448                                 stateBytesReceived / time);
01449     globalStatistics->addStdDev("Pastry: REPAIR Requests sent/s", repairReqSent / time);
01450     globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests sent/s",
01451                                 repairReqBytesSent / time);
01452     globalStatistics->addStdDev("Pastry: REPAIR Requests received/s", repairReqReceived / time);
01453     globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests received/s",
01454                                 repairReqBytesReceived / time);
01455     globalStatistics->addStdDev("Pastry: STATE Requests sent/s", stateReqSent / time);
01456     globalStatistics->addStdDev("Pastry: bytes of STATE Requests sent/s", stateReqBytesSent / time);
01457     globalStatistics->addStdDev("Pastry: STATE Requests received/s", stateReqReceived / time);
01458     globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01459                                 stateReqBytesReceived / time);
01460 
01461     globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01462                                 stateReqBytesReceived / time);
01463 
01464     globalStatistics->addStdDev("Pastry: total number of lookups", totalLookups);
01465     globalStatistics->addStdDev("Pastry: responsible lookups", responsibleLookups);
01466     globalStatistics->addStdDev("Pastry: lookups in routing table", routingTableLookups);
01467     globalStatistics->addStdDev("Pastry: lookups using closerNode()", closerNodeLookups);
01468     globalStatistics->addStdDev("Pastry: lookups using closerNode() with result from "
01469                                 "neighborhood set", closerNodeLookupsFromNeighborhood);
01470 }

void Pastry::updateTooltip (  )  [virtual]

updates information shown in tk-environment

01401 {
01402     if (ev.isGUI()) {
01403         std::stringstream ttString;
01404 
01405         // show our predecessor and successor in tooltip
01406         ttString << leafSet->getPredecessor() << endl << thisNode << endl
01407                  << leafSet->getSuccessor();
01408 
01409         parentModule()->parentModule()->displayString().
01410             setTagArg("tt", 0, ttString.str().c_str());
01411         parentModule()->displayString().
01412             setTagArg("tt", 0, ttString.str().c_str());
01413         displayString().setTagArg("tt", 0, ttString.str().c_str());
01414 
01415         // draw arrows:
01416         showOverlayNeighborArrow(leafSet->getSuccessor(), true,
01417                                  "m=m,50,0,50,0;o=red,1");
01418         showOverlayNeighborArrow(leafSet->getPredecessor(), false,
01419                                  "m=m,50,100,50,100;o=green,1");
01420 
01421     }
01422 }

NodeVector * Pastry::findNode ( const OverlayKey key,
int  numRedundantNodes,
int  numSiblings,
BaseOverlayMessage *  msg 
) [virtual]

Implements the find node call.

This method simply returns the closest nodes known in the corresponding routing topology. If the node is a sibling for this key (isSiblingFor(key) = true), this method returns all numSiblings siblings, with the closest neighbor to the key first.

Parameters:
key The lookup key.
numRedundantNodes Maximum number of next hop nodes to return.
numSiblings number of siblings to return
msg A pointer to the BaseRouteMessage or FindNodeCall message of this lookup.
Returns:
NodeVector with closest nodes.

Reimplemented from BaseOverlay.

01487 {
01488     if ((numRedundantNodes > getMaxNumRedundantNodes()) ||
01489         (numSiblings > getMaxNumSiblings())) {
01490 
01491         opp_error("(Pastry::findNode()) numRedundantNodes or numSiblings "
01492                   "too big!");
01493     }
01494     RECORD_STATS(totalLookups++);
01495 
01496     NodeVector* nextHops = new NodeVector(numRedundantNodes);//1);
01497 
01498     const NodeHandle* next;
01499     PastryFindNodeExtData* findNodeExt = NULL;
01500     if (msg && msg->hasObject("findNodeExt")) {
01501         findNodeExt =
01502             check_and_cast<PastryFindNodeExtData*>(msg->
01503                                                    getObject("findNodeExt"));
01504     }
01505 
01506     if (state != READY) {
01507         return nextHops;
01508     } else if (key.isUnspecified() || leafSet->isClosestNode(key)) {
01509         RECORD_STATS(responsibleLookups++);
01510         nextHops->add(thisNode);
01511     } else {
01512         // Send state tables on any JOIN message we see:
01513         if (findNodeExt) {
01514             const TransportAddress& stateRecipient =
01515                 findNodeExt->getSendStateTo();
01516             if (!stateRecipient.isUnspecified()) {
01517                 RECORD_STATS(joinSeen++);
01518                 sendStateTables(stateRecipient, PASTRY_STATE_JOIN,
01519                                 findNodeExt->getJoinHopCount(), false);
01520             }
01521         }
01522 
01523         next = &(leafSet->getDestinationNode(key));
01524 
01525         if (next->isUnspecified()) {
01526             next = &(routingTable->lookupNextHop(key));
01527             if (!next->isUnspecified()) {
01528                 RECORD_STATS(routingTableLookups++);
01529             }
01530         } else {
01531             RECORD_STATS(responsibleLookups++);
01532         }
01533 
01534         if (next->isUnspecified()) {
01535             RECORD_STATS(closerNodeLookups++);
01536             // call findCloserNode() on all state objects
01537 
01538             if (optimizeLookup) {
01539                 const NodeHandle* tmp;
01540                 next = &(routingTable->findCloserNode(key, true));
01541                 tmp = &(neighborhoodSet->findCloserNode(key, true));
01542 
01543                 if ((! tmp->isUnspecified()) &&
01544                     (leafSet->isCloser(*tmp, key, *next))) {
01545                     RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01546                     next = tmp;
01547                 }
01548 
01549                 tmp = &(leafSet->findCloserNode(key, true));
01550                 if ((! tmp->isUnspecified()) &&
01551                     (leafSet->isCloser(*tmp, key, *next))) {
01552                     RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01553                     next = tmp;
01554                 }
01555             } else {
01556                 next = &(routingTable->findCloserNode(key));
01557 
01558                 if (next->isUnspecified()) {
01559                     RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01560                     next = &(neighborhoodSet->findCloserNode(key));
01561                 }
01562 
01563                 if (next->isUnspecified()) {
01564                     RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01565                     next = &(leafSet->findCloserNode(key));
01566                 }
01567             }
01568         }
01569 
01570         if (!next->isUnspecified()) {
01571             if (findNodeExt) {
01572                 findNodeExt->setJoinHopCount(findNodeExt->getJoinHopCount() + 1);
01573             }
01574             nextHops->add(*next);
01575         }
01576     }
01577 
01578     bool err;
01579 
01580     /* if we're a sibling, return all numSiblings */
01581     if (isSiblingFor(thisNode, key, numSiblings, &err)) {
01582         if (err == false) {
01583             delete nextHops;
01584             return  leafSet->createSiblingVector(key, numSiblings);
01585         }
01586     }
01587 
01588     if (iterativeLookup && numRedundantNodes > 1) {
01589         //memleak... comp should be deleted in NodeVector::~NodeVector()...
01590         KeyDistanceComparator<KeyRingMetric> comp(key);
01591 //         KeyDistanceComparator<KeyRingMetric>* comp =
01592 //             new KeyDistanceComparator<KeyRingMetric>( key );
01593         NodeVector* additionalHops = new NodeVector( numRedundantNodes, &comp );
01594 
01595         routingTable->findCloserNodes(key, additionalHops);
01596         leafSet->findCloserNodes(key, additionalHops);
01597         neighborhoodSet->findCloserNodes(key, additionalHops);
01598 
01599         if (useRegularNextHop && (*additionalHops)[0] != (*nextHops)[0]) {
01600             for (uint i = 0; i < additionalHops->size(); i++) {
01601                 if ((*additionalHops)[i] != (*nextHops)[0])
01602                     nextHops->push_back((*additionalHops)[i]);
01603             }
01604             delete additionalHops;
01605             //delete comp;
01606         } else {
01607             delete nextHops;
01608             return additionalHops;
01609         }
01610     }
01611     return nextHops;
01612 }

int Pastry::getMaxNumSiblings (  )  [virtual]

Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.

Returns:
int number of siblings.

Reimplemented from BaseOverlay.

01473 {
01474     return (int) floor(numberOfLeaves/4.0);
01475 }

int Pastry::getMaxNumRedundantNodes (  )  [virtual]

Query the maximum number of redundant next hop nodes that are returned by findNode().

Returns:
int number of redundant nodes returned by findNode().

Reimplemented from BaseOverlay.

01478 {
01479     return 10;//test 1;
01480 }

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

changes node state

Parameters:
toState state to change to
00245 {
00246     if (ringCheck->isScheduled()) cancelEvent(ringCheck);
00247 
00248     switch (toState) {
00249     case INIT:
00250 
00251         state = INIT;
00252 
00253         if (!thisNode.key.isUnspecified())
00254             removeBootstrapNode(thisNode);
00255 
00256         if (joinTimeout->isScheduled()) cancelEvent(joinTimeout);
00257         if (readyWait->isScheduled()) cancelEvent(readyWait);
00258 
00259         purgeVectors();
00260 
00261         bootstrapNode = getBootstrapNode();
00262 
00263         routingTable->initializeTable(bitsPerDigit, repairTimeout,
00264                                       thisNode);
00265         leafSet->initializeSet(numberOfLeaves, repairTimeout, thisNode,
00266                                this);
00267         neighborhoodSet->initializeSet(numberOfNeighbors, thisNode);
00268 
00269         updateTooltip();
00270         lastStateChange = simTime();
00271 
00272         parentModule()->parentModule()->bubble("entering INIT state");
00273 
00274         break;
00275 
00276     case JOIN:
00277 
00278         state = JOIN;
00279 
00280         // bootstrapNode must be obtained before calling this method,
00281         // for example by calling changeState(INIT)
00282 
00283         if (bootstrapNode.isUnspecified()) {
00284             // no existing pastry network -> first node of a new one
00285             changeState(READY);
00286             return;
00287         }
00288 
00289         joinHopCount = 0;
00290 
00291         {
00292             PastryJoinMessage* msg = new PastryJoinMessage("JOIN-Request");
00293             msg->setPastryMsgType(PASTRY_MSG_JOIN);
00294             msg->setSignaling(true);
00295             msg->setJoinHopCount(1);
00296             msg->setSendStateTo(thisNode);
00297             msg->setLength(PASTRYJOIN_L(msg));
00298             RECORD_STATS(joinSent++; joinBytesSent += msg->byteLength());
00299             sendToKey(thisNode.key, msg, 0, bootstrapNode);
00300         }
00301 
00302         cancelEvent(joinTimeout);
00303         scheduleAt(simTime()+joinTimeoutAmount, joinTimeout);
00304 
00305         updateTooltip();
00306         parentModule()->parentModule()->bubble("entering JOIN state");
00307 
00308         RECORD_STATS(joinTries++);
00309 
00310         break;
00311 
00312     case READY:
00313         assert(state != READY);
00314         state = READY;
00315         if (ringCheckInterval > 0) {
00316             scheduleAt(simTime()+ringCheckInterval, ringCheck);
00317         }
00318 
00319         // registerBootstrapNode(thisNode);
00320 
00321         // if we are the first node in the network, there's nothing else
00322         // to do
00323         if (bootstrapNode.isUnspecified()) {
00324             RECORD_STATS(joinTries++);
00325             RECORD_STATS(joins++);
00326             setOverlayReady(true);
00327             return;
00328         }
00329 
00330         // determine list of all known nodes as notifyList
00331         notifyList.clear();
00332         leafSet->dumpToVector(notifyList);
00333         routingTable->dumpToVector(notifyList);
00334         sort(notifyList.begin(), notifyList.end());
00335         notifyList.erase(unique(notifyList.begin(), notifyList.end()),
00336                          notifyList.end());
00337 
00338         parentModule()->parentModule()->bubble("entering READY state");
00339 
00340         // schedule update
00341         cancelEvent(joinUpdateWait);
00342         scheduleAt(simTime() + sendStateWaitAmount, joinUpdateWait);
00343 
00344         // schedule second stage
00345         cancelEvent(secondStageWait);
00346         scheduleAt(simTime() + secondStageWaitAmount, secondStageWait);
00347 
00348         RECORD_STATS(joins++);
00349 
00350         break;
00351     }
00352     setOverlayReady(state == READY);
00353 }

void Pastry::sendStateTables ( const TransportAddress destination,
int  type = PASTRY_STATE_STD,
  ... 
) [protected]

send a PastryStateMessage directly to a node

Parameters:
destination destination node
type the type of the state message to be sent
... additional arguments for some types:
PASTRY_STATE_JOIN: int hops number of hops to destination node
PASTRY_STATE_JOIN: bool last mark the state message to originate from closest node found
PASTRY_STATE_UPDATE: simtime_t timestamp use this timestamp for the uptade message
01278 {
01279     if (destination.ip == thisNode.ip)
01280         opp_error("Pastry: trying to send state to self!");
01281 
01282 //     std::cout << simTime() << ": sendStateTables() from " << (TransportAddress&)thisNode
01283 //               << " to " << destination << std::endl;
01284 
01285     int hops = 0;
01286     bool last = false;
01287     simtime_t timestamp = 0;
01288 
01289     if ((type == PASTRY_STATE_JOIN) || (type == PASTRY_STATE_UPDATE)) {
01290         // additional parameters needed:
01291         va_list ap;
01292         va_start(ap, type);
01293         if (type == PASTRY_STATE_JOIN) {
01294             hops = va_arg(ap, int);
01295             last = static_cast<bool>(va_arg(ap, int));
01296         } else {
01297             timestamp = va_arg(ap, simtime_t);
01298         }
01299         va_end(ap);
01300     }
01301 
01302     // create new state msg and set special fields for some types:
01303     PastryStateMessage* stateMsg;
01304     if (type == PASTRY_STATE_JOIN) {
01305         stateMsg = new PastryStateMessage("STATE (Join)");
01306         stateMsg->setJoinHopCount(hops);
01307         stateMsg->setLastHop(last);
01308         stateMsg->setTimestamp(simTime());
01309     } else if (type == PASTRY_STATE_UPDATE) {
01310         stateMsg = new PastryStateMessage("STATE (Update)");
01311         EV << "Pastry: sending state (update) to " << destination << endl;
01312         stateMsg->setTimestamp(timestamp);
01313     } else if (type == PASTRY_STATE_REPAIR) {
01314         stateMsg = new PastryStateMessage("STATE (Repair)");
01315         stateMsg->setTimestamp(timestamp);
01316         EV << "Pastry: sending state (repair) to " << destination << endl;
01317     } else {
01318         stateMsg = new PastryStateMessage("STATE");
01319         EV << "Pastry: sending state (standard) to " << destination << endl;
01320         stateMsg->setTimestamp(simTime());
01321     }
01322 
01323     // fill in standard content:
01324     stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
01325     stateMsg->setSignaling(true);
01326     stateMsg->setPastryStateMsgType(type);
01327     stateMsg->setSender(thisNode);
01328     routingTable->dumpToStateMessage(stateMsg);
01329     leafSet->dumpToStateMessage(stateMsg);
01330     neighborhoodSet->dumpToStateMessage(stateMsg);
01331 
01332     // send...
01333     stateMsg->setLength(PASTRYSTATE_L(stateMsg));
01334     RECORD_STATS(stateSent++; stateBytesSent += stateMsg->byteLength());
01335     sendMessageToUDP(destination, stateMsg);
01336 }

void Pastry::sendStateDelayed ( const TransportAddress destination  )  [protected]

send a standard state message with a small delay

Parameters:
destination destination node
01339 {
01340     PastrySendState* selfMsg = new PastrySendState("sendStateWait");
01341     selfMsg->setDest(destination);
01342     sendStateWait.push_back(selfMsg);
01343     scheduleAt(simTime() + sendStateWaitAmount, selfMsg);
01344 }

bool Pastry::isSiblingFor ( const NodeHandle node,
const OverlayKey key,
int  numSiblings,
bool *  err 
) [protected, virtual]

Query if a node is among the siblings for a given key.

Query if a node is among the siblings for a given key. This means, that the nodeId of this node is among the closest numSiblings nodes to the key and that by a local findNode() call all other siblings to this key can be retrieved.

Parameters:
node the NodeHandle
key destination key
numSiblings The nodes knows all numSiblings nodes close to this key
err return false if the range could not be determined
Returns:
bool true, if the node is responsible for the key.

Reimplemented from BaseOverlay.

01350 {
01351     if (key.isUnspecified())
01352         error("Pastry::isSiblingFor(): key is unspecified!");
01353 
01354     if ((numSiblings == 1) && (node == thisNode)) {
01355         if (leafSet->isClosestNode(key)) {
01356             *err = false;
01357             return true;
01358         } else {
01359             *err = false;
01360             return false;
01361         }
01362     }
01363 
01364     NodeVector* result =  leafSet->createSiblingVector(key, numSiblings);
01365 
01366     if (result == NULL) {
01367         *err = true;
01368         return false;
01369     }
01370 
01371     if (result->contains(node.key)) {
01372         delete result;
01373         *err = false;
01374         return true;
01375     } else {
01376         delete result;
01377         *err = true;
01378         return false;
01379     }
01380 
01381     /*
01382       const NodeHandle& dest = leafSet->getDestinationNode(key);
01383       if (!dest.isUnspecified()) {
01384       *err = false;
01385       return true;
01386       } else {
01387      
01388       *err = true;
01389       return false;
01390       }
01391     */
01392 }

AbstractLookup * Pastry::createLookup ( const BaseOverlayMessage *  msg = NULL  )  [protected, virtual]

01615 {
01616     PastryFindNodeExtData* findNodeExt =
01617         new PastryFindNodeExtData("findNodeExt");
01618     
01619     if (msg) {
01620         const PastryMessage* pmsg = 
01621             dynamic_cast<const PastryMessage*>(msg->encapsulatedMsg());
01622         if ((pmsg) && (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN)) {
01623             const PastryJoinMessage* jmsg =
01624                 check_and_cast<const PastryJoinMessage*>(pmsg);
01625             findNodeExt->setSendStateTo(jmsg->getSendStateTo());
01626             findNodeExt->setJoinHopCount(1);
01627         }
01628     }
01629     findNodeExt->setLength(PASTRYFINDNODEEXTDATA_L);
01630     
01631     /*
01632     AbstractLookup* newLookup =
01633         new BaseLookup(this, baseLookupConfig, findNodeExt);
01634     lookups.insert(newLookup);
01635     */
01636     
01637     AbstractLookup* newLookup = BaseOverlay::createLookup(msg, findNodeExt);
01638     
01639     delete findNodeExt;
01640     return newLookup;
01641 }

bool Pastry::forwardMessageRecursive ( const TransportAddress dest,
BaseRouteMessage *  msg 
) [private, 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.

00661 {
00662     if (dest == thisNode) {
00663         //std::cout << "!" << std::endl;
00664         return true;
00665     }
00666     PastryMessage* pmsg
00667         = dynamic_cast<PastryMessage*>(msg->encapsulatedMsg());
00668     if ( pmsg && (dest != thisNode) ) {
00669         if (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN) {
00670             PastryJoinMessage* jmsg = check_and_cast<PastryJoinMessage*>(pmsg);
00671             RECORD_STATS(joinSeen++; joinBytesSeen += jmsg->byteLength());
00672             sendStateTables(jmsg->getSendStateTo(), PASTRY_STATE_JOIN,
00673                             jmsg->getJoinHopCount(), false);
00674             jmsg->setJoinHopCount(jmsg->getJoinHopCount() + 1);
00675         }
00676     }
00677 
00678     if (recFwdQueue.find(dest) != recFwdQueue.end()) {
00679         // rare case, other message for same next hop is pending:
00680         // send the message and hope it isn't lost.
00681         //sendMessageToUDP(dest, msg);
00682         return true;
00683     }
00684 
00685     assert(msg->controlInfo());
00686     //std::cout << (void*)msg->controlInfo()
00687     //          << " " << (void*)dynamic_cast<BaseRouteMessage*>(msg->dup())->controlInfo()
00688     //          << std::endl;
00689     bool send = false;
00690     if (optimisticForward) {
00691         // forward now:
00692         //sendMessageToUDP(dest, msg);
00693         send = true;
00694         if (! avoidDuplicates) {
00695             // and keep copy for possible retry:                        
00696             recFwdQueue[dest] = static_cast<BaseRouteMessage*>(msg->dup());
00697         }
00698     } else {        
00699         // keep message in queue (forward later)
00700         recFwdQueue[dest] = msg;
00701     }
00702     pingNode(dest, pingTimeout, pingRetries, "PING next hop");
00703     
00704     return send;
00705 }

void Pastry::doJoinUpdate ( void   )  [private]

send updated state to all nodes when entering ready state

00708 {
00709     // send "update" state message to all nodes who sent us their state
00710     // during INIT, remove these from notifyList so they don't get our
00711     // state twice
00712     std::vector<TransportAddress>::iterator nListPos;
00713     if (!stReceived.empty()) {
00714         for (std::vector<PastryStateMsgHandle>::iterator it =
00715                  stReceived.begin(); it != stReceived.end(); it++) {
00716             sendStateTables(it->msg->getSender(), PASTRY_STATE_UPDATE,
00717                             it->msg->getTimestamp());
00718             nListPos = find(notifyList.begin(), notifyList.end(),
00719                             it->msg->getSender());
00720             if (nListPos != notifyList.end()) {
00721                 notifyList.erase(nListPos);
00722             }
00723             delete it->msg;
00724             delete it->prox;
00725         }
00726         stReceived.clear();
00727     }
00728 
00729     // send a normal STATE message to all remaining known nodes
00730     for (std::vector<TransportAddress>::iterator it =
00731              notifyList.begin(); it != notifyList.end(); it++) {
00732         if (*it != thisNode) sendStateTables(*it);
00733     }
00734     notifyList.clear();
00735 
00736     updateTooltip();
00737 }

void Pastry::doSecondStage ( void   )  [private]

do the second stage of initialization as described in the paper

00740 {
00741     parentModule()->parentModule()->bubble("entering SECOND STAGE");
00742     // "second stage" for locality:
00743     notifyList.clear();
00744     routingTable->dumpToVector(notifyList);
00745     neighborhoodSet->dumpToVector(notifyList);
00746     sort(notifyList.begin(), notifyList.end());
00747     notifyList.erase(unique(notifyList.begin(), notifyList.end()),
00748                      notifyList.end());
00749     for (std::vector<TransportAddress>::iterator it = notifyList.begin();
00750          it != notifyList.end(); it++) {
00751         if (*it == thisNode) continue;
00752         EV << "second stage: requesting state from " << *it << endl;
00753         PastryStateRequestMessage* msg =
00754             new PastryStateRequestMessage("STATE_REQUEST");
00755         msg->setSignaling(true);
00756         msg->setPastryMsgType(PASTRY_MSG_SREQ);
00757         msg->setSendStateTo(thisNode);
00758         msg->setLength(PASTRYSREQ_L(msg));
00759         RECORD_STATS(stateReqSent++; stateReqBytesSent +=
00760                      msg->byteLength());
00761         sendMessageToUDP(*it, msg);
00762     }
00763     notifyList.clear();
00764 }

void Pastry::purgeVectors ( void   )  [private]

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

00160 {
00161     // purge pending state messages
00162     if (!stReceived.empty()) {
00163         for (std::vector<PastryStateMsgHandle>::iterator it =
00164                  stReceived.begin(); it != stReceived.end(); it++) {
00165             // check whether one of the pointers is a duplicate of stateCache
00166             if (it->msg == stateCache.msg) {
00167                 stateCache.msg = NULL;
00168                 stateCache.prox = NULL;
00169             }
00170             delete it->msg;
00171             delete it->prox;
00172         }
00173         stReceived.clear();
00174     }
00175 
00176     // purge notify list:
00177     notifyList.clear();
00178 
00179     // purge Ping Cache:
00180     pingCache.clear();
00181 
00182     // purge Queue for messages to be forwarded in recursive mode:
00183     for (std::map<TransportAddress, BaseRouteMessage*>::iterator i =
00184              recFwdQueue.begin(); i != recFwdQueue.end(); i++) {
00185         delete i->second;
00186     }
00187     recFwdQueue.clear();
00188 
00189     // purge Queue for processing multiple STATE messages:
00190     while (! stateCacheQueue.empty()) {
00191         delete stateCacheQueue.front().msg;
00192         stateCacheQueue.pop();
00193     }
00194 
00195     // delete cached state message:
00196     if (stateCache.msg) {
00197         delete stateCache.msg;
00198         stateCache.msg = NULL;
00199         delete stateCache.prox;
00200         stateCache.prox = NULL;
00201     }
00202 
00203     // purge vector of waiting sendState messages:
00204     if (! sendStateWait.empty()) {
00205         for (std::vector<PastrySendState*>::iterator it =
00206                  sendStateWait.begin(); it != sendStateWait.end(); it++) {
00207             if ( (*it)->isScheduled() ) cancelEvent(*it);
00208             delete *it;
00209         }
00210         sendStateWait.clear();
00211     }
00212 }

void Pastry::prePing ( const PastryStateMessage *  stateMsg  )  [private]

ping all nodes in a given state message.

this is called when a state message arrives while another one is still being processed.

00834 {
00835     int i;
00836     int rt_size;
00837     int ls_size;
00838     int ns_size;
00839     const NodeHandle* node;
00840     PastryPingCache::iterator it;
00841     PastryPingCacheEntry pce;
00842     simtime_t now;
00843 
00844     now = simTime();
00845     pce.inserted = now;
00846     pce.rtt = PASTRY_PROX_PENDING;
00847     rt_size = stateMsg->getRoutingTableArraySize();
00848     ls_size = stateMsg->getLeafSetArraySize();
00849     ns_size = stateMsg->getNeighborhoodSetArraySize();
00850 
00851     for (i = 0; i < rt_size + ls_size + ns_size; i++) {
00852         if (i < rt_size)
00853             node = &(stateMsg->getRoutingTable(i));
00854         else if (i < (rt_size + ls_size) )
00855             node = &(stateMsg->getLeafSet(i - rt_size));
00856         else
00857             node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00858 
00859         if (node->isUnspecified()) continue;
00860         if (*node == thisNode) continue;
00861         if (node->key == thisNode.key) {
00862             /*
00863             cerr << "Pastry Warning: Other node with same key found, "
00864                 "restarting!" << endl;
00865             opp_error("TODO: Other node with same key found...");
00866             joinOverlay(); //segfault
00867             return;
00868             */
00869             continue;
00870         }
00871         if (((it = pingCache.find(node->ip)) != pingCache.end()) &&
00872             ((now - it->second.inserted) < pingCacheExpireTime)) {
00873             // proximity known or ping already pending
00874             continue;
00875         }
00876 
00877         // update pingCache
00878         pingCache[node->ip] = pce;
00879 
00880         // send ping
00881         pingNode(*node, pingTimeout, pingRetries, "PING received state");
00882     }
00883 }

void Pastry::pingNodes ( void   )  [private]

ping all nodes in the pastry state message pointed to by private member stateCache

00886 {
00887     int i;
00888     int rt_size;
00889     int ls_size;
00890     int ns_size;
00891     const NodeHandle* node;
00892     std::vector<simtime_t>::iterator proxPos;
00893     PastryPingCache::iterator it;
00894     PastryPingCacheEntry pce;
00895     simtime_t now;
00896 
00897     now = simTime();
00898     pce.inserted = now;
00899     pce.rtt = PASTRY_PROX_PENDING;
00900 
00901     stateCache.prox = new PastryStateMsgProximity();
00902 
00903     rt_size = stateCache.msg->getRoutingTableArraySize();
00904     stateCache.prox->pr_rt.clear();
00905     stateCache.prox->pr_rt.resize(rt_size, PASTRY_PROX_PENDING);
00906 
00907     ls_size = stateCache.msg->getLeafSetArraySize();
00908     stateCache.prox->pr_ls.clear();
00909     stateCache.prox->pr_ls.resize(ls_size, PASTRY_PROX_PENDING);
00910 
00911     ns_size = stateCache.msg->getNeighborhoodSetArraySize();
00912     stateCache.prox->pr_ns.clear();
00913     stateCache.prox->pr_ns.resize(ns_size, PASTRY_PROX_PENDING);
00914 
00915     for (i = 0; i < rt_size + ls_size + ns_size; i++) {
00916         if (i < rt_size) {
00917             node = &(stateCache.msg->getRoutingTable(i));
00918             proxPos = stateCache.prox->pr_rt.begin() + i;
00919         } else if ( i < (rt_size + ls_size) ) {
00920             node = &(stateCache.msg->getLeafSet(i - rt_size));
00921             proxPos = stateCache.prox->pr_ls.begin() + (i - rt_size);
00922         } else {
00923             node = &(stateCache.msg->getNeighborhoodSet(i - rt_size - ls_size));
00924             proxPos = stateCache.prox->pr_ns.begin() + (i - rt_size - ls_size);
00925         }
00926 
00927         // proximity is undefined for unspecified nodes:
00928         if (node->isUnspecified()) {
00929             *proxPos = PASTRY_PROX_UNDEF;
00930         }
00931 
00932         // and 0 for own node:
00933         else if (*node == thisNode) {
00934             *proxPos = 0;
00935         }
00936         /*
00937         else if (node->key == thisNode.key) {
00938             cerr << "Pastry Warning: Other node with same key found, "
00939                 "restarting!" << endl;
00940             joinOverlay();
00941             return;
00942         }
00943         */
00944 
00945         // else determine real value:
00946         else {
00947             if ((it = pingCache.find(node->ip)) != pingCache.end()) {
00948                 if ((now - it->second.inserted) < pingCacheExpireTime) {
00949                     *proxPos = it->second.rtt;
00950                     //if (debugOutput) {
00951                     //EV << "Pastry: pingCache HIT" << endl;
00952                     //}
00953                     continue;
00954                 } else {
00955                     if (debugOutput) {
00956                         EV << "Pastry: pingCache OUTDATED" << endl;
00957                     }
00958                     pingCache.erase(it);
00959                 }
00960             } else if (debugOutput) {
00961                 EV << "Pastry: pingCache MISS" << endl;
00962             }
00963 
00964             // update pingCache
00965             pingCache[node->ip] = pce;
00966 
00967             // send ping
00968             pingNode(*node, pingTimeout, pingRetries, "PING received state");
00969         }
00970     }
00971     checkProxCache();
00972 }

void Pastry::determineAliveTable ( const PastryStateMessage *  stateMsg  )  [private]

change the aliveTable to match the given stateMsg.

each node that's knowm to be dead from our pingCache gets a value of PASTRY_PROX_INFINITE, all other nodes just get a value of 1

00975 {
00976     int i;
00977     int rt_size;
00978     int ls_size;
00979     int ns_size;
00980     const IPvXAddress* ip;
00981     std::vector<simtime_t>::iterator tblPos;
00982     PastryPingCache::iterator it;
00983     simtime_t now;
00984 
00985     now = simTime();
00986 
00987     rt_size = stateMsg->getRoutingTableArraySize();
00988     aliveTable.pr_rt.clear();
00989     aliveTable.pr_rt.resize(rt_size, 1);
00990 
00991     ls_size = stateMsg->getLeafSetArraySize();
00992     aliveTable.pr_ls.clear();
00993     aliveTable.pr_ls.resize(ls_size, 1);
00994 
00995     ns_size = stateMsg->getNeighborhoodSetArraySize();
00996     aliveTable.pr_ns.clear();
00997     aliveTable.pr_ns.resize(ns_size, 1);
00998 
00999     for (i = 0; i < rt_size + ls_size + ns_size; i++) {
01000         if (i < rt_size) {
01001             ip = &(stateMsg->getRoutingTable(i).ip);
01002             tblPos = aliveTable.pr_rt.begin() + i;
01003         } else if ( i < (rt_size + ls_size) ) {
01004             ip = &(stateMsg->getLeafSet(i - rt_size).ip);
01005             tblPos = aliveTable.pr_ls.begin() + (i - rt_size);
01006         } else {
01007             ip = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size).ip);
01008             tblPos = aliveTable.pr_ns.begin() + (i - rt_size - ls_size);
01009         }
01010 
01011         if (((it = pingCache.find(*ip)) != pingCache.end()) &&
01012             (it->second.rtt == PASTRY_PROX_INFINITE) &&
01013             ((now - it->second.inserted) < pingCacheExpireTime)) {
01014             *tblPos = PASTRY_PROX_INFINITE;
01015         }
01016     }
01017 }

void Pastry::checkProxCache ( void   )  [private]

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

01020 {
01021     simtime_t now = simTime();
01022 
01023     // no cached STATE message?
01024     if (!(stateCache.msg && stateCache.prox)) return;
01025 
01026     // no entries in stateCache.prox?
01027     if (stateCache.prox->pr_rt.empty()) return;
01028     if (stateCache.prox->pr_ls.empty()) return;
01029     if (stateCache.prox->pr_ns.empty()) return;
01030 
01031     // some entries not yet determined?
01032     if (find(stateCache.prox->pr_rt.begin(), stateCache.prox->pr_rt.end(),
01033              PASTRY_PROX_PENDING) != stateCache.prox->pr_rt.end()
01034         ) return;
01035     if (find(stateCache.prox->pr_ls.begin(), stateCache.prox->pr_ls.end(),
01036              PASTRY_PROX_PENDING) != stateCache.prox->pr_ls.end()
01037         ) return;
01038     if (find(stateCache.prox->pr_ns.begin(), stateCache.prox->pr_ns.end(),
01039              PASTRY_PROX_PENDING) != stateCache.prox->pr_ns.end()
01040         ) return;
01041 
01042     if (state == JOIN) {
01043         // save pointer to proximity vectors:
01044         stReceivedPos->prox = stateCache.prox;
01045 
01046         // collected proximities for all STATE messages?
01047         if (++stReceivedPos == stReceived.end()) {
01048             stateCache.msg = NULL;
01049             stateCache.prox = NULL;
01050             if (debugOutput) {
01051                 EV << "Pastry: [JOIN] starting to build own state from "
01052                    << stReceived.size() << " received state messages..."
01053                    << endl;
01054                 EV << "Pastry: [JOIN] initializing NeighborhoodSet from "
01055                 << stReceived.front().msg->getJoinHopCount() << ". hop"
01056                 << endl;
01057             }
01058             if (!neighborhoodSet->mergeState( stReceived.front().msg,
01059                                              *stReceived.front().prox )) {
01060                 EV << "Pastry: Error initializing own neighborhoodSet while "
01061                     "joining! Restarting ..." << endl;
01062                 joinOverlay();
01063                 return;
01064             }
01065             if (debugOutput) {
01066                 EV << "Pastry: [JOIN] initializing LeafSet from "
01067                 << stReceived.back().msg->getJoinHopCount() << ". hop" << endl;
01068             }
01069             if (!leafSet->mergeState( stReceived.back().msg,
01070                                      *stReceived.back().prox )) {
01071                 EV << "Pastry: Error initializing own leafSet while "
01072                     "joining! Restarting ..." << endl;
01073                 joinOverlay();
01074                 return;
01075             }
01076             if (debugOutput) {
01077                 EV << "Pastry: [JOIN] initializing RoutingTable from all hops"
01078                    << endl;
01079             }
01080             if (!routingTable->initStateFromHandleVector(stReceived)) {
01081                 EV << "Pastry: Error initializing own routingTable "
01082                     "while joining! Restarting ..." << endl;
01083                 joinOverlay();
01084                 return;
01085             }
01086             lastStateChange = now;
01087             newLeafs();
01088             changeState(READY);
01089         } else {
01090             // process next state message in vector:
01091             stateCache = *stReceivedPos;
01092             pingNodes();
01093         }
01094     } else {
01095         // state == READY
01096 
01097         if (stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) {
01098             // try to repair routingtable based on repair message:
01099             const TransportAddress& askRt =
01100                 routingTable->repair(stateCache.msg, *stateCache.prox);
01101             if (! askRt.isUnspecified()) {
01102                 //std::cout << "RT needs to be repaired!" << std::endl;
01103                 sendRepairRequest(askRt);
01104             }
01105 
01106             // while not really known, it's safe to assume that a repair
01107             // message changed our state:
01108             lastStateChange = now;
01109         } else {
01110             if (stateCache.outdatedUpdate) {
01111                 // send another STATE message on outdated state update:
01112                 sendStateDelayed(stateCache.msg->getSender());
01113             } else {//hack
01114 
01115                 // merge info in own state tables
01116                 // except leafset (was already handled in handleStateMessage)
01117                 if (neighborhoodSet->mergeState(stateCache.msg, *stateCache.prox))
01118                     lastStateChange = now;
01119 
01120                 if (routingTable->mergeState(stateCache.msg, *stateCache.prox))
01121                     lastStateChange = now;
01122             }
01123         }
01124 
01125         updateTooltip();
01126 
01127         // if state message was not an update, send one back:
01128         if (stateCache.msg->getPastryStateMsgType() != PASTRY_STATE_UPDATE &&
01129             (alwaysSendUpdate || lastStateChange == now)) {//hack
01130             sendStateTables(stateCache.msg->getSender(), PASTRY_STATE_UPDATE,
01131                             stateCache.msg->getTimestamp());
01132         }
01133 
01134         delete stateCache.msg;
01135         stateCache.msg = NULL;
01136         delete stateCache.prox;
01137         stateCache.prox = NULL;
01138 
01139         // process next queued message:
01140         if (! stateCacheQueue.empty()) {
01141             stateCache = stateCacheQueue.front();
01142             stateCacheQueue.pop();
01143             pingNodes();
01144         }
01145     }
01146 }

void Pastry::sendRepairRequest ( const TransportAddress ask  )  [private]

send a repair request to a given node

Parameters:
ask request repair from this node
01226 {
01227     //std::cout << thisNode << " --> " << ask
01228     //<< " sendRepairRequest() @ " << simTime() << std::endl;
01229     if (ask.isUnspecified())
01230         opp_error("Pastry::sendRepairRequest(): asked for repair from "
01231                   "unspecified node!");
01232 
01233     PastryRepairRequestMessage* msg = new PastryRepairRequestMessage("REPAIR_REQUEST");
01234     msg->setPastryMsgType(PASTRY_MSG_RREQ);
01235     msg->setSignaling(true);
01236     msg->setSendStateTo(thisNode);
01237     msg->setLength(PASTRYRREQ_L(msg));
01238     RECORD_STATS(repairReqSent++; repairReqBytesSent += msg->byteLength());
01239     sendMessageToUDP(ask, msg);
01240 }

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.

01243 {
01244     //std::cout << "handleFailedNode()" << std::endl;
01245     if (state != READY) {
01246         return false;
01247     }
01248 
01249     if (failed.isUnspecified())
01250         opp_error("Pastry::handleFailedNode(): failed is unspecified!");
01251 
01252     const TransportAddress& lsAsk = leafSet->failedNode(failed);
01253     const TransportAddress& rtAsk = routingTable->failedNode(failed);
01254     neighborhoodSet->failedNode(failed);
01255     //assert(lsAsk.isUnspecified() || rtAsk.isUnspecified() || lsAsk != rtAsk);
01256 
01257     if (! lsAsk.isUnspecified()) {
01258         //std::cout << thisNode << ": " << failed << " failed: LS needs to be repaired!" << std::endl;
01259         sendRepairRequest(lsAsk);
01260     }
01261     if (! rtAsk.isUnspecified() &&
01262         (lsAsk.isUnspecified() ||
01263          lsAsk != rtAsk)) sendRepairRequest(rtAsk);
01264 
01265     newLeafs();
01266 
01267     if (lsAsk.isUnspecified() && (! leafSet->isValid())) {
01268         EV << "Pastry: lost connection to the network, trying to re-join."
01269            << endl;
01270         joinOverlay();
01271         return false;
01272     }
01273 
01274     return true;
01275 }

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.

00226 {
00227     changeState(INIT);
00228 
00229     if (bootstrapNode.isUnspecified()) {
00230         // no existing pastry network -> first node of a new one
00231         changeState(READY);
00232     } else {
00233         // join existing pastry network
00234         changeState(JOIN);
00235     }
00236 }

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

Reimplemented from BaseOverlay.

00239 {
00240     thisNode.key = OverlayKey::random();
00241     //cbr
00242 }

void Pastry::newLeafs ( void   )  [private]

Pastry API: send newLeafs() to application if enabled.

00215 {
00216     if (! enableNewLeafs) return;
00217 
00218     PastryNewLeafsMessage* msg = leafSet->getNewLeafsMessage();
00219     if (msg) {
00220         send(msg, "to_app");
00221         EV << "Pastry: newLeafs() called." << endl;
00222     }
00223 }


Friends And Related Function Documentation

friend class PastryLeafSet [friend]


Member Data Documentation

int Pastry::joins [protected]

int Pastry::joinTries [protected]

int Pastry::joinPartial [protected]

int Pastry::joinSeen [protected]

int Pastry::joinBytesSeen [protected]

int Pastry::joinReceived [protected]

int Pastry::joinBytesReceived [protected]

int Pastry::joinSent [protected]

int Pastry::joinBytesSent [protected]

int Pastry::stateSent [protected]

int Pastry::stateBytesSent [protected]

int Pastry::stateReceived [protected]

int Pastry::stateBytesReceived [protected]

int Pastry::repairReqSent [protected]

int Pastry::repairReqBytesSent [protected]

int Pastry::repairReqReceived [protected]

int Pastry::repairReqBytesReceived [protected]

int Pastry::stateReqSent [protected]

int Pastry::stateReqBytesSent [protected]

int Pastry::stateReqReceived [protected]

int Pastry::stateReqBytesReceived [protected]

int Pastry::totalLookups [protected]

int Pastry::responsibleLookups [protected]

int Pastry::routingTableLookups [protected]

int Pastry::closerNodeLookups [protected]

int Pastry::closerNodeLookupsFromNeighborhood [protected]

PastryRoutingTable* Pastry::routingTable [private]

PastryLeafSet* Pastry::leafSet [private]

PastryNeighborhoodSet* Pastry::neighborhoodSet [private]

uint Pastry::bitsPerDigit [private]

uint Pastry::numberOfLeaves [private]

uint Pastry::numberOfNeighbors [private]

uint Pastry::pingRetries [private]

double Pastry::pingTimeout [private]

double Pastry::readyWaitAmount [private]

double Pastry::joinTimeoutAmount [private]

double Pastry::secondStageWaitAmount [private]

double Pastry::pingCacheExpireTime [private]

double Pastry::repairTimeout [private]

double Pastry::ringCheckInterval [private]

double Pastry::sendStateWaitAmount [private]

bool Pastry::enableNewLeafs [private]

bool Pastry::optimizeLookup [private]

bool Pastry::optimisticForward [private]

bool Pastry::avoidDuplicates [private]

bool Pastry::partialJoinPath [private]

bool Pastry::useRegularNextHop [private]

bool Pastry::alwaysSendUpdate [private]

bool Pastry::coordBasedRouting [private]

uint Pastry::numCoordDigits [private]

uint Pastry::CBRstartAtDigit [private]

uint Pastry::CBRstopAtDigit [private]

NodeHandle Pastry::bootstrapNode [private]

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

State messages to process during join.

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

std::vector<TransportAddress> Pastry::notifyList [private]

List of nodes to notify after join.

PastryStateMsgHandle Pastry::stateCache [private]

Handle for processing a single state message.

std::queue<PastryStateMsgHandle> Pastry::stateCacheQueue [private]

Queue of state messages waiting to be processed in READY state.

PastryStateMsgProximity Pastry::aliveTable [private]

Early update of leaf set: helper structure for marking known-dead nodes.

PastryPingCache Pastry::pingCache [private]

caches RPC Ping RTTs

Reimplemented from BaseRpc.

std::map<TransportAddress, BaseRouteMessage*> Pastry::recFwdQueue [private]

Queue of messages to be forwarded in recursive routing mode.

uint Pastry::joinHopCount [private]

cMessage* Pastry::joinTimeout [private]

cMessage* Pastry::readyWait [private]

cMessage* Pastry::secondStageWait [private]

cMessage* Pastry::joinUpdateWait [private]

cMessage* Pastry::ringCheck [private]

std::vector<PastrySendState*> Pastry::sendStateWait [private]

simtime_t Pastry::lastStateChange [private]


The documentation for this class was generated from the following files:
Generated on Thu Apr 17 13:19:30 2008 for ITM OverSim by  doxygen 1.5.3