BasePastry Class Reference

#include <BasePastry.h>

Inheritance diagram for BasePastry:

BaseOverlay BaseRpc TopologyVis RpcListener Bamboo Pastry

List of all members.

Public Member Functions

virtual void pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt)
void pingTimeout (PingCall *call, const TransportAddress &dest, cPolymorphic *context, int rpcId)
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().
virtual void handleAppMessage (BaseOverlayMessage *msg)
 processes messages from application
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.
virtual void handleStateMessage (PastryStateMessage *msg)=0
 processes state messages, merging with own state tables
virtual void finishOverlay ()
 collects statistical data in derived class
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 (RoutingType routingType=DEFAULT_ROUTING, const BaseOverlayMessage *msg=NULL, const cObject *dummy=NULL, bool appLookup=false)
 Creates an abstract iterative lookup instance.

Public 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
int leafsetReqSent
int leafsetReqBytesSent
int leafsetReqReceived
int leafsetReqBytesReceived
int leafsetSent
int leafsetBytesSent
int leafsetReceived
int leafsetBytesReceived
int routingTableReqSent
int routingTableReqBytesSent
int routingTableReqReceived
int routingTableReqBytesReceived
int routingTableSent
int routingTableBytesSent
int routingTableReceived
int routingTableBytesReceived
uint rowToAsk

Protected Types

enum  StateObject { ROUTINGTABLE, LEAFSET, NEIGHBORHOODSET }

Protected Member Functions

virtual void changeState (int toState)
 changes node state
virtual void checkProxCache (void)=0
 checks whether proxCache is complete, takes appropriate actions depending on the protocol state
virtual bool forwardMessageRecursive (const TransportAddress &dest, BaseRouteMessage *msg)
 Hook for forwarded message in recursive lookup mode.
void purgeVectors (void)
 delete all information/messages caching vectors, used for restarting overlay or finish()
void baseInit (void)
 initializes parameters and variables used in both Bamboo and Pastry
void baseChangeState (int)
 changes node state, but leaves specific behavour, scheduling tasks in particular, to the inheriting protocols
void doRoutingTableMaintenance ()
 periodic routing table maintenance requests the corresponding routing table row from one node in each row
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 sendRequest (const TransportAddress &ask, int type)
 send a request to a given node
void sendLeafset (const TransportAddress &tell, bool pull=false)
 send the leafset to a node
void sendRoutingRow (const TransportAddress &tell, int row)
 send a row of the routing table to a node
void handleRequestMessage (PastryRequestMessage *msg)
 processes state messages, merging with own state tables
void handleLeafsetMessage (PastryLeafsetMessage *msg, bool mergeSender=false)
 processes leafset messages, merging with own state tables
void setOwnNodeID ()
 Overlay implementations can overwrite this virtual method to set a specific nodeID.
void newLeafs (void)
 Pastry API: send newLeafs() to application if enabled.

Protected Attributes

uint bitsPerDigit
uint numberOfLeaves
uint numberOfNeighbors
uint pingRetries
double timeoutPing
double readyWaitAmount
double joinTimeoutAmount
double pingCacheExpireTime
double repairTimeout
double sendStateWaitAmount
bool enableNewLeafs
bool useRegularNextHop
bool alwaysSendUpdate
bool optimizeLookup
bool optimisticForward
bool avoidDuplicates
bool partialJoinPath
bool coordBasedRouting
uint numCoordDigits
uint CBRstartAtDigit
uint CBRstopAtDigit
double nearNodeRtt
double repairTaskTimeoutAmount
uint unspecNodes
uint pingedNodes
bool nearNodeImproved
bool sendPullFlag
bool useDiscovery
bool periodicMaintenance
TransportAddressleaf2ask
NodeHandle bootstrapNode
NodeHandle nearNode
simtime_t lastStateChange
std::vector< PastryStateMsgHandlestReceived
 State messages to process during join.
std::vector
< PastryStateMsgHandle >
::iterator 
stReceivedPos
std::vector< TransportAddressnotifyList
 List of nodes to notify after join.
PastryStateMsgHandle stateCache
 Handle for processing a single state message.
std::queue< PastryStateMsgHandlestateCacheQueue
 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.
std::map< TransportAddress,
BaseRouteMessage * > 
recFwdQueue
 Queue of messages to be forwarded in recursive routing mode.
uint joinHopCount
cMessage * joinTimeout
cMessage * readyWait
cMessage * joinUpdateWait
std::vector< PastrySendState * > sendStateWait
cMessage * repairTaskTimeout
PastryRoutingTableroutingTable
PastryLeafSetleafSet
PastryNeighborhoodSetneighborhoodSet

Friends

class PastryLeafSet

Classes

struct  PingContext


Member Enumeration Documentation

enum BasePastry::StateObject [protected]

Enumerator:
ROUTINGTABLE 
LEAFSET 
NEIGHBORHOODSET 
00307     {
00308         ROUTINGTABLE,
00309         LEAFSET,
00310         NEIGHBORHOODSET
00311     };


Member Function Documentation

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

Reimplemented from BaseRpc.

00452 {
00453     const NodeHandle& src = msg->getSrcNode();
00454     assert(!src.isUnspecified());
00455 
00456     // a node with the an equal ID has responded
00457     if ((src.key == thisNode.key) && (src.ip != thisNode.ip)) {
00458         EV << "a node with the an equal ID has responded, rejoining" << endl;
00459         delete context;
00460         joinOverlay();
00461         return;
00462     }
00463 
00464     //const NodeHandle* node;
00465     if (context != NULL && stateCache.msg && stateCache.prox) {
00466         PingContext* pingContext = check_and_cast<PingContext*>(context);
00467         if (pingContext->nonce != stateCache.nonce) {
00468             throw new cRuntimeError("response doesn't fit stateCache");
00469         }
00470         switch (pingContext->stateObject) {
00471             case ROUTINGTABLE: {
00472                 /*node = &(stateCache.msg->getRoutingTable(pingContext->index));
00473                 if((node->isUnspecified()) || (*node != src)) {
00474                     std::cout << simTime() << " " << thisNode.ip << " rt: state from "
00475                               << stateCache.msg->getSender().ip << " *** failed: node "
00476                               << node->ip << " src " << src.ip << std::endl;
00477                     break;
00478                 }*/
00479                 *(stateCache.prox->pr_rt.begin() + pingContext->index) = rtt;
00480                 break;
00481             }
00482             case LEAFSET: {
00483                 /*node = &(stateCache.msg->getLeafSet(pingContext->index));
00484                 if ((node->isUnspecified()) || (*node != src)) {
00485                     std::cout << simTime() << " " << thisNode.ip << " ls: state from "
00486                               << stateCache.msg->getSender().ip << " *** failed: node "
00487                               << node->ip << " src " << src.ip << std::endl;
00488                     break;
00489                 }*/
00490                 *(stateCache.prox->pr_ls.begin() + pingContext->index) = rtt;
00491                 break;
00492             }
00493             case NEIGHBORHOODSET: {
00494                 /*node = &(stateCache.msg->getNeighborhoodSet(pingContext->index));
00495                 if((node->isUnspecified()) || (*node != src)) {
00496                     std::cout << simTime() << " " << thisNode.ip << " ns: state from "
00497                               << stateCache.msg->getSender().ip << " *** failed: node "
00498                               << node->ip << " src " << src.ip << std::endl;
00499                     break;
00500                 }*/
00501                 *(stateCache.prox->pr_ns.begin() + pingContext->index) = rtt;
00502                 break;
00503             }
00504             default: {
00505                 throw new cRuntimeError("wrong state object type!");
00506             }
00507         }
00508     }
00509 
00510     delete context;
00511 
00512     checkProxCache();
00513 
00514     std::map<TransportAddress, BaseRouteMessage*>::iterator pos;
00515     if ((pos = recFwdQueue.find(src)) != recFwdQueue.end()) {
00516         // send message
00517         if (!optimisticForward) {
00518             sendMessageToUDP(pos->first, pos->second);
00519         } else if (!avoidDuplicates) {
00520             delete pos->second;
00521         }
00522         recFwdQueue.erase(pos);
00523     }
00524 }

void BasePastry::pingTimeout ( PingCall *  call,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId 
) [virtual]

Reimplemented from BaseRpc.

00729 {
00730     EV << "[BasePastry::pingTimeout() @ " << thisNode.ip
00731        << " (" << thisNode.key.toString(16) << ")]\n"
00732        << "    Ping timeout occurred (" << dest.ip << ")"
00733        << endl;
00734 
00735     // handle failed node
00736     if (state == READY) {
00737         handleFailedNode(dest);
00738         updateTooltip();
00739 
00740         // this could initiate a re-join, exit the handler in that
00741         // case because all local data was erased:
00742         if (state != READY) {
00743             delete context;
00744             return;
00745         }
00746     }
00747 
00748     if (context && stateCache.msg && stateCache.prox &&
00749         msg->isName("PING received state")) { //TODO string compare is inefficient
00750         PingContext* pingContext = check_and_cast<PingContext*>(context);
00751         if (pingContext->nonce != stateCache.nonce) {
00752             throw new cRuntimeError("timeout/call doesn't fit stateCache");
00753         }
00754         //const NodeHandle* node;
00755         switch (pingContext->stateObject) {
00756             case ROUTINGTABLE: {
00757                 /*if (pingContext->index >=
00758                     stateCache.msg->getRoutingTableArraySize()) {
00759                     std::cout << "*** FAILED ***" << std::endl;
00760                     break;
00761                 }
00762                 node = &(stateCache.msg->getRoutingTable(pingContext->index));
00763                 if((node->isUnspecified()) || (dest != *node)) {
00764                     std::cout << msg->getNonce() << " " << simTime() << " " << thisNode.ip << " rt: state from "
00765                     << stateCache.msg->getSender().ip << " *** failed: node "
00766                     << node->ip << " failed dest " << dest.ip << std::endl;
00767                     break;
00768                 }*/
00769                 *(stateCache.prox->pr_rt.begin() + pingContext->index) =
00770                     PASTRY_PROX_INFINITE;
00771                 break;
00772             }
00773             case LEAFSET: {
00774                 /*if (pingContext->index >=
00775                     stateCache.msg->getLeafSetArraySize()) {
00776                     std::cout << "*** FAILED ***" << std::endl;
00777                     break;
00778                 }
00779                 node = &(stateCache.msg->getLeafSet(pingContext->index));
00780                 if((node->isUnspecified()) || (dest != *node)) {
00781                     std::cout << msg->getNonce() << " " << simTime() << " " << thisNode.ip << " ls: state from "
00782                     << stateCache.msg->getSender().ip << " *** failed: node "
00783                     << node->ip << " failed dest " << dest.ip << std::endl;
00784                     break;
00785                 }*/
00786                 *(stateCache.prox->pr_ls.begin() + pingContext->index) =
00787                     PASTRY_PROX_INFINITE;
00788                 break;
00789             }
00790             case NEIGHBORHOODSET: {
00791                 /*if (pingContext->index >=
00792                     stateCache.msg->getNeighborhoodSetArraySize()) {
00793                     std::cout << "*** FAILED ***" << std::endl;
00794                     break;
00795                 }
00796                 node = &(stateCache.msg->getNeighborhoodSet(pingContext->index));
00797                 if((node->isUnspecified()) || (dest != *node)) {
00798                     std::cout << msg->getNonce() << " " << simTime() << " " << thisNode.ip << " ns: state from "
00799                     << stateCache.msg->getSender().ip << " *** failed: node "
00800                     << node->ip << " failed dest " << dest.ip << std::endl;
00801                     break;
00802                 }*/
00803                 *(stateCache.prox->pr_ns.begin() + pingContext->index) =
00804                     PASTRY_PROX_INFINITE;
00805                 break;
00806             }
00807         }
00808         checkProxCache();
00809     }
00810 
00811     delete context;
00812 
00813     if (msg->isName("PING next hop")) {//TODO string compare is inefficient
00814         // handle forward queue entry
00815         std::map<TransportAddress, BaseRouteMessage*>::iterator pos;
00816         if ((pos = recFwdQueue.find(dest)) == recFwdQueue.end()) return;
00817         BaseRouteMessage* rmsg = pos->second;
00818         recFwdQueue.erase(pos);
00819         if (dynamic_cast<PastryJoinMessage*>(rmsg->encapsulatedMsg()) &&
00820                 rmsg->getDestKey() == thisNode.key) {
00821             std::cout << "join timeout -> rejoin!";
00822             changeState(INIT);
00823             return;
00824         }
00825         assert(rmsg->controlInfo());
00826         sendToKey(rmsg->getDestKey(), rmsg);
00827     }
00828 }

int BasePastry::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.

Referenced by findNode().

01135 {
01136     return (int) floor(numberOfLeaves/4.0);
01137 }

int BasePastry::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.

Referenced by findNode().

01140 {
01141     return 10;//TODO
01142 }

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

processes messages from application

Parameters:
msg message from application
01035 {
01036     delete msg;
01037 }

void BasePastry::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Referenced by baseChangeState(), Pastry::checkProxCache(), Bamboo::checkProxCache(), Pastry::doJoinUpdate(), Pastry::handleStateMessage(), Bamboo::handleStateMessage(), and pingTimeout().

01040 {
01041     if (ev.isGUI()) {
01042         std::stringstream ttString;
01043 
01044         // show our predecessor and successor in tooltip
01045         ttString << leafSet->getPredecessor() << endl << thisNode << endl
01046                  << leafSet->getSuccessor();
01047 
01048         parentModule()->parentModule()->displayString().
01049             setTagArg("tt", 0, ttString.str().c_str());
01050         parentModule()->displayString().
01051             setTagArg("tt", 0, ttString.str().c_str());
01052         displayString().setTagArg("tt", 0, ttString.str().c_str());
01053 
01054         // draw arrows:
01055         showOverlayNeighborArrow(leafSet->getSuccessor(), true,
01056                                  "m=m,50,0,50,0;o=red,1");
01057         showOverlayNeighborArrow(leafSet->getPredecessor(), false,
01058                                  "m=m,50,100,50,100;o=green,1");
01059 
01060     }
01061 }

NodeVector * BasePastry::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.

01148 {
01149     if ((numRedundantNodes > getMaxNumRedundantNodes()) ||
01150         (numSiblings > getMaxNumSiblings())) {
01151 
01152         opp_error("(Pastry::findNode()) numRedundantNodes or numSiblings "
01153                   "too big!");
01154     }
01155     RECORD_STATS(totalLookups++);
01156 
01157     NodeVector* nextHops = new NodeVector(numRedundantNodes);
01158 
01159     const NodeHandle* next;
01160     PastryFindNodeExtData* findNodeExt = NULL;
01161     if (msg && msg->hasObject("findNodeExt")) {
01162         findNodeExt =
01163             check_and_cast<PastryFindNodeExtData*>(msg->
01164                                                    getObject("findNodeExt"));
01165     }
01166 
01167     if (state != READY) {
01168         return nextHops;
01169     } else if (key.isUnspecified() || leafSet->isClosestNode(key)) {
01170         RECORD_STATS(responsibleLookups++);
01171         nextHops->add(thisNode);
01172     } else {
01173         // Send state tables on any JOIN message we see:
01174         if (findNodeExt) {
01175             const TransportAddress& stateRecipient =
01176                 findNodeExt->getSendStateTo();
01177             if (!stateRecipient.isUnspecified()) {
01178                 RECORD_STATS(joinSeen++);
01179                 sendStateTables(stateRecipient, PASTRY_STATE_JOIN,
01180                                 findNodeExt->getJoinHopCount(), false);
01181             }
01182         }
01183 
01184         next = &(leafSet->getDestinationNode(key));
01185 
01186         if (next->isUnspecified()) {
01187             next = &(routingTable->lookupNextHop(key));
01188             if (!next->isUnspecified()) {
01189                 RECORD_STATS(routingTableLookups++);
01190             }
01191         } else {
01192             RECORD_STATS(responsibleLookups++);
01193         }
01194 
01195         if (next->isUnspecified()) {
01196             RECORD_STATS(closerNodeLookups++);
01197             // call findCloserNode() on all state objects
01198             if (optimizeLookup) {
01199                 const NodeHandle* tmp;
01200                 next = &(routingTable->findCloserNode(key, true));
01201                 tmp = &(neighborhoodSet->findCloserNode(key, true));
01202 
01203                 if ((! tmp->isUnspecified()) &&
01204                     (leafSet->isCloser(*tmp, key, *next))) {
01205                     RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01206                     next = tmp;
01207                 }
01208 
01209                 tmp = &(leafSet->findCloserNode(key, true));
01210                 if ((! tmp->isUnspecified()) &&
01211                     (leafSet->isCloser(*tmp, key, *next))) {
01212                     RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01213                     next = tmp;
01214                 }
01215             } else {
01216                 next = &(routingTable->findCloserNode(key));
01217 
01218                 if (next->isUnspecified()) {
01219                     RECORD_STATS(closerNodeLookupsFromNeighborhood++);
01220                     next = &(neighborhoodSet->findCloserNode(key));
01221                 }
01222 
01223                 if (next->isUnspecified()) {
01224                     RECORD_STATS(closerNodeLookupsFromNeighborhood--);
01225                     next = &(leafSet->findCloserNode(key));
01226                 }
01227             }
01228         }
01229 
01230         if (!next->isUnspecified()) {
01231             if (findNodeExt) {
01232                 findNodeExt->setJoinHopCount(findNodeExt->getJoinHopCount() + 1);
01233             }
01234             nextHops->add(*next);
01235         }
01236     }
01237 
01238     bool err;
01239 
01240     /* if we're a sibling, return all numSiblings */
01241     if (isSiblingFor(thisNode, key, numSiblings, &err)) {
01242         if (err == false) {
01243             delete nextHops;
01244             return  leafSet->createSiblingVector(key, numSiblings);
01245         }
01246     }
01247 
01248     //TODO routingType, too slow, ...
01249     if (/*(nextHops->size() > 0) &&*/ (numRedundantNodes > 1)) {
01250         //memleak... comp should be a ptr and deleted in NodeVector::~NodeVector()...
01251         KeyDistanceComparator<KeyRingMetric> comp(key);
01252         //KeyDistanceComparator<KeyRingMetric>* comp =
01253         //new KeyDistanceComparator<KeyRingMetric>( key );
01254         NodeVector* additionalHops = new NodeVector( numRedundantNodes, &comp );
01255 
01256         routingTable->findCloserNodes(key, additionalHops);
01257         leafSet->findCloserNodes(key, additionalHops);
01258         neighborhoodSet->findCloserNodes(key, additionalHops);
01259 
01260         if (useRegularNextHop && (*additionalHops)[0] != (*nextHops)[0]) {
01261             for (uint i = 0; i < additionalHops->size(); i++) {
01262                 if ((*additionalHops)[i] != (*nextHops)[0])
01263                     nextHops->push_back((*additionalHops)[i]);
01264             }
01265             delete additionalHops;
01266         } else {
01267             delete nextHops;
01268             return additionalHops;
01269         }
01270     }
01271     return nextHops;
01272 }

virtual void BasePastry::handleStateMessage ( PastryStateMessage *  msg  )  [pure virtual]

processes state messages, merging with own state tables

Parameters:
msg the pastry state message

Implemented in Bamboo, and Pastry.

Referenced by handleLeafsetMessage().

void BasePastry::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

01064 {
01065     // remove this node from the bootstrap list
01066     if (!thisNode.key.isUnspecified()) bootstrapList->removeBootstrapNode(thisNode);
01067 
01068     purgeVectors();
01069 
01070     // collect statistics
01071     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01072     if(time == 0) return;
01073 
01074     globalStatistics->addStdDev("Pastry: Successful Joins/s", joins / time);
01075     globalStatistics->addStdDev("Pastry: overall join tries/s", joinTries / time);
01076     globalStatistics->addStdDev("Pastry: joins with missing replies from routing path/s",
01077                                 joinPartial / time);
01078     globalStatistics->addStdDev("Pastry: JOIN Messages seen/s", joinSeen / time);
01079     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages seen/s", joinBytesSeen / time);
01080     globalStatistics->addStdDev("Pastry: JOIN Messages received/s", joinReceived / time);
01081     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages received/s",
01082                                 joinBytesReceived / time);
01083     globalStatistics->addStdDev("Pastry: JOIN Messages sent/s", joinSent / time);
01084     globalStatistics->addStdDev("Pastry: bytes of JOIN Messages sent/s", joinBytesSent / time);
01085     globalStatistics->addStdDev("Pastry: STATE Messages sent/s", stateSent / time);
01086     globalStatistics->addStdDev("Pastry: bytes of STATE Messages sent/s", stateBytesSent / time);
01087     globalStatistics->addStdDev("Pastry: STATE Messages received/s", stateReceived / time);
01088     globalStatistics->addStdDev("Pastry: bytes of STATE Messages received/s",
01089                                 stateBytesReceived / time);
01090     globalStatistics->addStdDev("Pastry: REPAIR Requests sent/s", repairReqSent / time);
01091     globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests sent/s",
01092                                 repairReqBytesSent / time);
01093     globalStatistics->addStdDev("Pastry: REPAIR Requests received/s", repairReqReceived / time);
01094     globalStatistics->addStdDev("Pastry: bytes of REPAIR Requests received/s",
01095                                 repairReqBytesReceived / time);
01096     globalStatistics->addStdDev("Pastry: STATE Requests sent/s", stateReqSent / time);
01097     globalStatistics->addStdDev("Pastry: bytes of STATE Requests sent/s", stateReqBytesSent / time);
01098     globalStatistics->addStdDev("Pastry: STATE Requests received/s", stateReqReceived / time);
01099     globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01100                                 stateReqBytesReceived / time);
01101 
01102     globalStatistics->addStdDev("Pastry: bytes of STATE Requests received/s",
01103                                 stateReqBytesReceived / time);
01104 
01105     globalStatistics->addStdDev("Pastry: total number of lookups", totalLookups);
01106     globalStatistics->addStdDev("Pastry: responsible lookups", responsibleLookups);
01107     globalStatistics->addStdDev("Pastry: lookups in routing table", routingTableLookups);
01108     globalStatistics->addStdDev("Pastry: lookups using closerNode()", closerNodeLookups);
01109     globalStatistics->addStdDev("Pastry: lookups using closerNode() with result from "
01110                                 "neighborhood set", closerNodeLookupsFromNeighborhood);
01111     globalStatistics->addStdDev("Pastry: LEAFSET Requests sent/s", leafsetReqSent / time);
01112     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Requests sent/s", leafsetReqBytesSent / time);
01113     globalStatistics->addStdDev("Pastry: LEAFSET Requests received/s", leafsetReqReceived / time);
01114     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Requests received/s",
01115                                 leafsetReqBytesReceived / time);
01116     globalStatistics->addStdDev("Pastry: LEAFSET Messages sent/s", leafsetSent / time);
01117     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Messages sent/s", leafsetBytesSent / time);
01118     globalStatistics->addStdDev("Pastry: LEAFSET Messages received/s", leafsetReceived / time);
01119     globalStatistics->addStdDev("Pastry: bytes of LEAFSET Messages received/s",
01120                                 leafsetBytesReceived / time);
01121     globalStatistics->addStdDev("Pastry: ROUTING TABLE Requests sent/s", routingTableReqSent / time);
01122     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Requests sent/s", routingTableReqBytesSent / time);
01123     globalStatistics->addStdDev("Pastry: ROUTING TABLE Requests received/s", routingTableReqReceived / time);
01124     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Requests received/s",
01125                                 routingTableReqBytesReceived / time);
01126     globalStatistics->addStdDev("Pastry: ROUTING TABLE Messages sent/s", routingTableSent / time);
01127     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Messages sent/s", routingTableBytesSent / time);
01128     globalStatistics->addStdDev("Pastry: ROUTING TABLE Messages received/s", routingTableReceived / time);
01129     globalStatistics->addStdDev("Pastry: bytes of ROUTING TABLE Messages received/s",
01130                                 routingTableBytesReceived / time);
01131 
01132 }

void BasePastry::sendStateTables ( const TransportAddress destination,
int  type = PASTRY_STATE_STD,
  ... 
)

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

Referenced by Pastry::checkProxCache(), Pastry::doJoinUpdate(), findNode(), forwardMessageRecursive(), handleRequestMessage(), Pastry::handleTimerEvent(), and Pastry::handleUDPMessage().

00660 {
00661     if (destination.ip == thisNode.ip)
00662         opp_error("Pastry: trying to send state to self!");
00663 
00664     int hops = 0;
00665     bool last = false;
00666     simtime_t timestamp = 0;
00667 
00668     if ((type == PASTRY_STATE_JOIN) || (type == PASTRY_STATE_UPDATE)) {
00669         // additional parameters needed:
00670         va_list ap;
00671         va_start(ap, type);
00672         if (type == PASTRY_STATE_JOIN) {
00673             hops = va_arg(ap, int);
00674             last = static_cast<bool>(va_arg(ap, int));
00675         } else {
00676             timestamp = va_arg(ap, simtime_t);
00677         }
00678         va_end(ap);
00679     }
00680 
00681     // create new state msg and set special fields for some types:
00682     PastryStateMessage* stateMsg;
00683     if (type == PASTRY_STATE_JOIN) {
00684         stateMsg = new PastryStateMessage("STATE (Join)");
00685         stateMsg->setJoinHopCount(hops);
00686         stateMsg->setLastHop(last);
00687         stateMsg->setTimestamp(simTime());
00688     } else if (type == PASTRY_STATE_UPDATE) {
00689         stateMsg = new PastryStateMessage("STATE (Update)");
00690         EV << "Pastry: sending state (update) to " << destination << endl;
00691         stateMsg->setTimestamp(timestamp);
00692     } else if (type == PASTRY_STATE_REPAIR) {
00693         stateMsg = new PastryStateMessage("STATE (Repair)");
00694         stateMsg->setTimestamp(timestamp);
00695         EV << "Pastry: sending state (repair) to " << destination << endl;
00696     } else {
00697         stateMsg = new PastryStateMessage("STATE");
00698         EV << "Pastry: sending state (standard) to " << destination << endl;
00699         stateMsg->setTimestamp(simTime());
00700     }
00701 
00702     // fill in standard content:
00703     stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00704     stateMsg->setStatType(MAINTENANCE_STAT);
00705     stateMsg->setPastryStateMsgType(type);
00706     stateMsg->setSender(thisNode);
00707     routingTable->dumpToStateMessage(stateMsg);
00708     leafSet->dumpToStateMessage(stateMsg);
00709     neighborhoodSet->dumpToStateMessage(stateMsg);
00710 
00711     // send...
00712     stateMsg->setLength(PASTRYSTATE_L(stateMsg));
00713     RECORD_STATS(stateSent++; stateBytesSent += stateMsg->byteLength());
00714     sendMessageToUDP(destination, stateMsg);
00715 }

void BasePastry::sendStateDelayed ( const TransportAddress destination  ) 

send a standard state message with a small delay

Parameters:
destination destination node

Referenced by Pastry::checkProxCache().

00718 {
00719     PastrySendState* selfMsg = new PastrySendState("sendStateWait");
00720     selfMsg->setDest(destination);
00721     sendStateWait.push_back(selfMsg);
00722     scheduleAt(simTime() + sendStateWaitAmount, selfMsg);
00723 }

bool BasePastry::isSiblingFor ( const NodeHandle node,
const OverlayKey key,
int  numSiblings,
bool *  err 
) [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.

Referenced by findNode().

00989 {
00990     if (key.isUnspecified())
00991         error("Pastry::isSiblingFor(): key is unspecified!");
00992 
00993     if ((numSiblings == 1) && (node == thisNode)) {
00994         if (leafSet->isClosestNode(key)) {
00995             *err = false;
00996             return true;
00997         } else {
00998             *err = false;
00999             return false;
01000         }
01001     }
01002 
01003     NodeVector* result =  leafSet->createSiblingVector(key, numSiblings);
01004 
01005     if (result == NULL) {
01006         *err = true;
01007         return false;
01008     }
01009 
01010     if (result->contains(node.key)) {
01011         delete result;
01012         *err = false;
01013         return true;
01014     } else {
01015         delete result;
01016         *err = true;
01017         return false;
01018     }
01019 
01020     /*
01021       const NodeHandle& dest = leafSet->getDestinationNode(key);
01022       if (!dest.isUnspecified()) {
01023       *err = false;
01024       return true;
01025       } else {
01026 
01027       *err = true;
01028       return false;
01029       }
01030     */
01031 }

AbstractLookup * BasePastry::createLookup ( RoutingType  routingType = DEFAULT_ROUTING,
const BaseOverlayMessage *  msg = NULL,
const cObject *  findNodeExt = NULL,
bool  appLookup = false 
) [virtual]

Creates an abstract iterative lookup instance.

Parameters:
routingType The routing type for this lookup (e.g. recursive/iterative)
msg pointer to the message for which the lookup is created. Derived classes can use it to construct an object with additional info for the lookup class.
findNodeExt object that will be sent with the findNodeCalls
appLookup Set to true, if lookup is triggered by application (for statistics)
Returns:
AbstractLookup* The new lookup instance.

Reimplemented from BaseOverlay.

Referenced by Bamboo::doGlobalTuning().

01277 {
01278     assert(dummy == NULL);
01279     PastryFindNodeExtData* findNodeExt =
01280         new PastryFindNodeExtData("findNodeExt");
01281 
01282     if (msg) {
01283         const PastryMessage* pmsg =
01284             dynamic_cast<const PastryMessage*>(msg->encapsulatedMsg());
01285         if ((pmsg) && (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN)) {
01286             const PastryJoinMessage* jmsg =
01287                 check_and_cast<const PastryJoinMessage*>(pmsg);
01288             findNodeExt->setSendStateTo(jmsg->getSendStateTo());
01289             findNodeExt->setJoinHopCount(1);
01290         }
01291     }
01292     findNodeExt->setLength(PASTRYFINDNODEEXTDATA_L);
01293 
01294     AbstractLookup* newLookup = BaseOverlay::createLookup(routingType,
01295                                                           msg, findNodeExt,
01296                                                           appLookup);
01297 
01298     delete findNodeExt;
01299     return newLookup;
01300 }

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

changes node state

Parameters:
toState state to change to

Reimplemented in Bamboo, and Pastry.

Referenced by baseChangeState(), and pingTimeout().

00338 {
00339 
00340 }

virtual void BasePastry::checkProxCache ( void   )  [protected, pure virtual]

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

Implemented in Bamboo, and Pastry.

Referenced by pingResponse(), and pingTimeout().

bool BasePastry::forwardMessageRecursive ( 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.

00345 {
00346     if (dest == thisNode) {
00347         return true;
00348     }
00349     PastryMessage* pmsg
00350         = dynamic_cast<PastryMessage*>(msg->encapsulatedMsg());
00351     if ( pmsg && (dest != thisNode) ) {
00352         if (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN) {
00353             PastryJoinMessage* jmsg = check_and_cast<PastryJoinMessage*>(pmsg);
00354             RECORD_STATS(joinSeen++; joinBytesSeen += jmsg->byteLength());
00355 //            assert(jmsg->getJoinHopCount() ==
00356 //                   check_and_cast<OverlayCtrlInfo*>(msg->controlInfo())
00357 //                   ->getHopCount());
00358             sendStateTables(jmsg->getSendStateTo(), PASTRY_STATE_JOIN,
00359                             check_and_cast<OverlayCtrlInfo*>(msg->controlInfo())
00360                                                ->getHopCount(),
00361                             /*jmsg->getJoinHopCount(),*/ false);
00362             //jmsg->setJoinHopCount(jmsg->getJoinHopCount() + 1);
00363         }
00364     }
00365 
00366     if (recFwdQueue.find(dest) != recFwdQueue.end()) {
00367         // rare case, other message for same next hop is pending:
00368         // send the message and hope it isn't lost.
00369         return true;
00370     }
00371 
00372     assert(msg->controlInfo());
00373 
00374 //    bool send = false;
00375 //    if (optimisticForward) {
00376 //        // forward now:
00377 //        send = true;
00378 //        if (! avoidDuplicates) {
00379 //            // and keep copy for possible retry:
00380 //            recFwdQueue[dest] = static_cast<BaseRouteMessage*>(msg->dup());
00381 //        }
00382 //    } else {
00383 //        // keep message in queue (forward later)
00384 //        recFwdQueue[dest] = msg;
00385 //    }
00386 //    pingNode(dest, timeoutPing, pingRetries, "PING next hop");
00387 //
00388 //    return send;
00389 
00390     if (optimisticForward) {
00391         // forward now:
00392         return true;
00393     } else {
00394         if (routeMsgAcks) throw new cRuntimeError("!optimisticForward && "
00395                                                   "routeMsgAcks");
00396         // keep message in queue (forward later)
00397         recFwdQueue[dest] = msg;
00398         pingNode(dest, timeoutPing, pingRetries, NULL,
00399                  "PING next hop");
00400 
00401         return false;
00402     }
00403 }

void BasePastry::purgeVectors ( void   )  [protected]

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

Referenced by baseChangeState(), Pastry::changeState(), finishOverlay(), Bamboo::~Bamboo(), and Pastry::~Pastry().

00041 {
00042     // purge pending state messages
00043     if (!stReceived.empty()) {
00044         for (std::vector<PastryStateMsgHandle>::iterator it =
00045                  stReceived.begin(); it != stReceived.end(); it++) {
00046             // check whether one of the pointers is a duplicate of stateCache
00047             if (it->msg == stateCache.msg) {
00048                 stateCache.msg = NULL;
00049                 stateCache.prox = NULL;
00050             }
00051             delete it->msg;
00052             delete it->prox;
00053         }
00054         stReceived.clear();
00055     }
00056 
00057     // purge notify list:
00058     notifyList.clear();
00059 
00060     // purge Queue for messages to be forwarded in recursive mode:
00061     for (std::map<TransportAddress, BaseRouteMessage*>::iterator i =
00062         recFwdQueue.begin(); i != recFwdQueue.end(); i++) {
00063         delete i->second;
00064     }
00065     recFwdQueue.clear();
00066 
00067     // purge Queue for processing multiple STATE messages:
00068     while (! stateCacheQueue.empty()) {
00069         delete stateCacheQueue.front().msg;
00070         stateCacheQueue.pop();
00071     }
00072 
00073     // delete cached state message:
00074     if (stateCache.msg) {
00075         delete stateCache.msg;
00076         stateCache.msg = NULL;
00077         delete stateCache.prox;
00078         stateCache.prox = NULL;
00079     }
00080 
00081     // purge vector of waiting sendState messages:
00082     if (! sendStateWait.empty()) {
00083         for (std::vector<PastrySendState*>::iterator it =
00084                  sendStateWait.begin(); it != sendStateWait.end(); it++) {
00085             if ( (*it)->isScheduled() ) cancelEvent(*it);
00086             delete *it;
00087         }
00088         sendStateWait.clear();
00089     }
00090 }

void BasePastry::baseInit ( void   )  [protected]

initializes parameters and variables used in both Bamboo and Pastry

Referenced by Pastry::initializeOverlay(), and Bamboo::initializeOverlay().

00093 {
00094 
00095     bitsPerDigit = par("bitsPerDigit");
00096     numberOfLeaves = par("numberOfLeaves");
00097     numberOfNeighbors = par("numberOfNeighbors");
00098     joinTimeoutAmount = par("joinTimeout");
00099     readyWaitAmount = par("readyWait");
00100     repairTimeout = par("repairTimeout");
00101     enableNewLeafs = par("enableNewLeafs");
00102     optimizeLookup = par("optimizeLookup");
00103     optimisticForward = par("optimisticForward");
00104     avoidDuplicates = par("avoidDuplicates");
00105     sendStateWaitAmount = par("sendStateWaitAmount");
00106     partialJoinPath = par("partialJoinPath");
00107     timeoutPing = par("pingTimeout");
00108     pingRetries = par("pingRetries");
00109     useRegularNextHop = par("useRegularNextHop");
00110     alwaysSendUpdate = par("alwaysSendUpdate");
00111 
00112     if (!neighborCache->isEnabled()) {
00113         throw new cRuntimeError("NeighborCache is disabled, which is mandatory "
00114                                 "for Pastry/Bamboo. Activate it by setting "
00115                                 "\"**.neighborCache.enableNeighborCache "
00116                                 "= true\" in your omnetpp.ini!");
00117     }
00118     // coordinate-based routing (CBR)
00119     coordBasedRouting = par("coordBasedRouting");
00120     if(coordBasedRouting &&
00121        !dynamic_cast<SimpleNetConfigurator*>(underlayConfigurator)) {
00122         opp_error("Coordinate-based routing currently only"
00123                   " possible in SimpleUnderlay!");
00124     }
00125     numCoordDigits = par("numCoordDigits");
00126     CBRstartAtDigit = par("CBRstartAtDigit");
00127     CBRstopAtDigit = par("CBRstopAtDigit");
00128 
00129     if (numberOfLeaves % 2) {
00130         EV << "Pastry: Warning: numberOfLeaves must be even - adding 1.";
00131         numberOfLeaves++;
00132     }
00133 
00134     routingTable = check_and_cast<PastryRoutingTable*>
00135         (parentModule()->submodule("pastryRoutingTable"));
00136     leafSet = check_and_cast<PastryLeafSet*>
00137         (parentModule()->submodule("pastryLeafSet"));
00138     neighborhoodSet = check_and_cast<PastryNeighborhoodSet*>
00139         (parentModule()->submodule("pastryNeighborhoodSet"));
00140 
00141     stateCache.msg = NULL;
00142     stateCache.prox = NULL;
00143 
00144     rowToAsk = 0;
00145 
00146     // initialize statistics
00147     joins = 0;
00148     joinTries = 0;
00149     joinPartial = 0;
00150     joinSeen = 0;
00151     joinReceived = 0;
00152     joinSent = 0;
00153     stateSent = 0;
00154     stateReceived = 0;
00155     repairReqSent = 0;
00156     repairReqReceived = 0;
00157     stateReqSent = 0;
00158     stateReqReceived = 0;
00159 
00160     joinBytesSeen = 0;
00161     joinBytesReceived = 0;
00162     joinBytesSent = 0;
00163     stateBytesSent = 0;
00164     stateBytesReceived = 0;
00165     repairReqBytesSent = 0;
00166     repairReqBytesReceived = 0;
00167     stateReqBytesSent = 0;
00168     stateReqBytesReceived = 0;
00169 
00170     totalLookups = 0;
00171     responsibleLookups = 0;
00172     routingTableLookups = 0;
00173     closerNodeLookups = 0;
00174     closerNodeLookupsFromNeighborhood = 0;
00175 
00176     leafsetReqSent = 0;
00177     leafsetReqBytesSent = 0;
00178     leafsetReqReceived = 0;
00179     leafsetReqBytesReceived = 0;
00180     leafsetSent = 0;
00181     leafsetBytesSent = 0;
00182     leafsetReceived = 0;
00183     leafsetBytesReceived = 0;
00184 
00185     routingTableReqSent = 0;
00186     routingTableReqBytesSent = 0;
00187     routingTableReqReceived = 0;
00188     routingTableReqBytesReceived = 0;
00189     routingTableSent = 0;
00190     routingTableBytesSent = 0;
00191     routingTableReceived = 0;
00192     routingTableBytesReceived = 0;
00193 
00194     WATCH(joins);
00195     WATCH(joinTries);
00196     WATCH(joinSeen);
00197     WATCH(joinBytesSeen);
00198     WATCH(joinReceived);
00199     WATCH(joinBytesReceived);
00200     WATCH(joinSent);
00201     WATCH(joinBytesSent);
00202     WATCH(stateSent);
00203     WATCH(stateBytesSent);
00204     WATCH(stateReceived);
00205     WATCH(stateBytesReceived);
00206     WATCH(repairReqSent);
00207     WATCH(repairReqBytesSent);
00208     WATCH(repairReqReceived);
00209     WATCH(repairReqBytesReceived);
00210     WATCH(stateReqSent);
00211     WATCH(stateReqBytesSent);
00212     WATCH(stateReqReceived);
00213     WATCH(stateReqBytesReceived);
00214     WATCH(lastStateChange);
00215 
00216     WATCH(leafsetReqSent);
00217     WATCH(leafsetReqBytesSent);
00218     WATCH(leafsetReqReceived);
00219     WATCH(leafsetReqBytesReceived);
00220     WATCH(leafsetSent);
00221     WATCH(leafsetBytesSent);
00222     WATCH(leafsetReceived);
00223     WATCH(leafsetBytesReceived);
00224 
00225     WATCH(routingTableReqSent);
00226     WATCH(routingTableReqBytesSent);
00227     WATCH(routingTableReqReceived);
00228     WATCH(routingTableReqBytesReceived);
00229     WATCH(routingTableSent);
00230     WATCH(routingTableBytesSent);
00231     WATCH(routingTableReceived);
00232     WATCH(routingTableBytesReceived);
00233 
00234 }

void BasePastry::baseChangeState ( int  toState  )  [protected]

changes node state, but leaves specific behavour, scheduling tasks in particular, to the inheriting protocols

Referenced by Pastry::changeState(), and Bamboo::changeState().

00237 {
00238     switch (toState) {
00239     case INIT:
00240 
00241         state = INIT;
00242 
00243         if (!thisNode.key.isUnspecified())
00244             bootstrapList->removeBootstrapNode(thisNode);
00245 
00246         if (joinTimeout->isScheduled()) cancelEvent(joinTimeout);
00247         if (readyWait->isScheduled()) cancelEvent(readyWait);
00248 
00249         purgeVectors();
00250 
00251         bootstrapNode = bootstrapList->getBootstrapNode();
00252 
00253         routingTable->initializeTable(bitsPerDigit, repairTimeout,
00254                                       thisNode);
00255         leafSet->initializeSet(numberOfLeaves, bitsPerDigit,
00256                                repairTimeout, thisNode,
00257                                this);
00258         neighborhoodSet->initializeSet(numberOfNeighbors, bitsPerDigit,
00259                                        thisNode);
00260 
00261         updateTooltip();
00262         lastStateChange = simTime();
00263 
00264         parentModule()->parentModule()->bubble("entering INIT state");
00265 
00266         break;
00267 
00268 
00269     case DISCOVERY:
00270 
00271         break;
00272 
00273     case JOINING_2:
00274         state = JOINING_2;
00275 
00276         // bootstrapNode must be obtained before calling this method,
00277         // for example by calling changeState(INIT)
00278 
00279         if (bootstrapNode.isUnspecified()) {
00280             // no existing pastry network -> first node of a new one
00281             changeState(READY);
00282             return;
00283         }
00284 
00285         cancelEvent(joinTimeout);
00286         scheduleAt(simTime()+joinTimeoutAmount, joinTimeout);
00287 
00288         updateTooltip();
00289         parentModule()->parentModule()->bubble("entering JOIN state");
00290 
00291         RECORD_STATS(joinTries++);
00292 
00293         break;
00294 
00295     case READY:
00296         assert(state != READY);
00297         state = READY;
00298 
00299          //bootstrapList->registerBootstrapNode(thisNode);
00300 
00301         // if we are the first node in the network, there's nothing else
00302         // to do
00303         if (bootstrapNode.isUnspecified()) {
00304             RECORD_STATS(joinTries++);
00305             RECORD_STATS(joins++);
00306             setOverlayReady(true);
00307             return;
00308         }
00309 
00310         parentModule()->parentModule()->bubble("entering READY state");
00311         updateTooltip();
00312         RECORD_STATS(joins++);
00313 
00314         break;
00315     }
00316     setOverlayReady(state == READY);
00317 }

void BasePastry::doRoutingTableMaintenance (  )  [protected]

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

Referenced by Pastry::handleTimerEvent(), and Bamboo::handleTimerEvent().

00406 {
00407 
00408   if (sendPullFlag) {
00409     //static uint rowToAsk = 1;
00410     uint rrows = routingTable->getLastRow();
00411     if (++rowToAsk >= rrows) rowToAsk = 0;
00412     const TransportAddress& ask4row = routingTable->getRandomNode(rowToAsk);
00413 
00414     if ((!ask4row.isUnspecified()) && (ask4row != thisNode)) {
00415 
00416         PastryRoutingRowRequestMessage* msg = new PastryRoutingRowRequestMessage("ROWREQ");
00417 
00418         msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00419         msg->setStatType(MAINTENANCE_STAT);
00420         msg->setSendStateTo(thisNode);
00421         msg->setRow(rowToAsk+1);
00422         msg->setLength(PASTRYRTREQ_L(msg));
00423         RECORD_STATS(routingTableReqSent++; routingTableReqBytesSent += msg->byteLength());
00424         EV << "Bamboo: Sending  Message to Node in Row" << rowToAsk << endl;
00425         sendMessageToUDP(ask4row, msg);
00426     }
00427   } else {
00428 
00429 
00430     for (int i = 0; i < routingTable->getLastRow(); i++) {
00431         const TransportAddress& ask4row = routingTable->getRandomNode(i);
00432 
00433         if ((!ask4row.isUnspecified()) && (ask4row != thisNode)) {
00434 
00435             PastryRoutingRowRequestMessage* msg = new PastryRoutingRowRequestMessage("ROWREQ");
00436 
00437             msg->setPastryMsgType(PASTRY_MSG_ROWREQ);
00438             msg->setStatType(MAINTENANCE_STAT);
00439             msg->setSendStateTo(thisNode);
00440             msg->setRow(i+1);
00441             msg->setLength(PASTRYRTREQ_L(msg));
00442             RECORD_STATS(routingTableReqSent++; routingTableReqBytesSent += msg->byteLength());
00443             sendMessageToUDP(ask4row, msg);
00444         } else EV << "could not send Message to Node in Row" << i << endl;
00445 
00446     }
00447   }
00448 }

void BasePastry::prePing ( const PastryStateMessage *  stateMsg  )  [protected]

ping all nodes in a given state message.

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

Referenced by Pastry::handleStateMessage(), and Bamboo::handleStateMessage().

00527 {
00528     uint rt_size = stateMsg->getRoutingTableArraySize();
00529     uint ls_size = stateMsg->getLeafSetArraySize();
00530     uint ns_size = stateMsg->getNeighborhoodSetArraySize();
00531 
00532     for (uint i = 0; i < rt_size + ls_size + ns_size; i++) {
00533         const NodeHandle* node;
00534         if (i < rt_size) {
00535             node = &(stateMsg->getRoutingTable(i));
00536         }
00537         else if (i < (rt_size + ls_size) ) {
00538             node = &(stateMsg->getLeafSet(i - rt_size));
00539         }
00540         else {
00541             node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00542         }
00543         if ((node->isUnspecified()) || (*node == thisNode)) {
00544             continue;
00545         }
00546         if (node->key == thisNode.key) {
00547             /*
00548             cerr << "Pastry Warning: Other node with same key found, "
00549                 "restarting!" << endl;
00550             opp_error("TODO: Other node with same key found...");
00551             joinOverlay(); //segfault
00552             return;
00553             */
00554             continue;
00555         }
00556         pingNode(*node, timeoutPing, pingRetries, NULL,
00557                  "PING received state");
00558     }
00559 }

void BasePastry::pingNodes ( void   )  [protected]

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

Referenced by Pastry::checkProxCache(), Bamboo::checkProxCache(), Pastry::handleStateMessage(), Bamboo::handleStateMessage(), Pastry::handleTimerEvent(), and Bamboo::handleTimerEvent().

00562 {
00563     if (stateCache.msg == NULL) throw new cRuntimeError("no state msg");
00564 
00565     assert(stateCache.prox == NULL);
00566     stateCache.prox = new PastryStateMsgProximity();
00567 
00568     uint rt_size = stateCache.msg->getRoutingTableArraySize();
00569     //stateCache.prox->pr_rt.clear();
00570     stateCache.prox->pr_rt.resize(rt_size, PASTRY_PROX_UNDEF);
00571 
00572     uint ls_size = stateCache.msg->getLeafSetArraySize();
00573     //stateCache.prox->pr_ls.clear();
00574     stateCache.prox->pr_ls.resize(ls_size, PASTRY_PROX_UNDEF);
00575 
00576     uint ns_size = stateCache.msg->getNeighborhoodSetArraySize();
00577     //stateCache.prox->pr_ns.clear();
00578     stateCache.prox->pr_ns.resize(ns_size, PASTRY_PROX_UNDEF);
00579 
00580     std::vector< std::pair<const NodeHandle*, PingContext*> > nodesToPing;
00581     // set prox state
00582     for (uint i = 0; i < rt_size + ls_size + ns_size; i++) {
00583         const NodeHandle* node;
00584         std::vector<simtime_t>::iterator proxPos;
00585         PingContext* pingContext = NULL;
00586         StateObject stateObject;
00587         uint index;
00588         if (stateCache.msg == NULL) break;
00589         if (i < rt_size) {
00590             node = &(stateCache.msg->getRoutingTable(i));
00591             proxPos = stateCache.prox->pr_rt.begin() + i;
00592             stateObject = ROUTINGTABLE;
00593             index = i;
00594         } else if ( i < (rt_size + ls_size) ) {
00595             node = &(stateCache.msg->getLeafSet(i - rt_size));
00596             proxPos = stateCache.prox->pr_ls.begin() + (i - rt_size);
00597             stateObject = LEAFSET;
00598             index = i - rt_size;
00599         } else {
00600             node = &(stateCache.msg->getNeighborhoodSet(i - rt_size - ls_size));
00601             proxPos = stateCache.prox->pr_ns.begin() + (i - rt_size - ls_size);
00602             stateObject = NEIGHBORHOODSET;
00603             index = i - rt_size - ls_size;
00604         }
00605         // proximity is undefined for unspecified nodes:
00606         if (!node->isUnspecified()) {
00607             if (*node == thisNode) {
00608                 *proxPos = 0;
00609             } else {
00610                 *proxPos = PASTRY_PROX_PENDING;
00611                 pingContext = new PingContext(stateObject, index,
00612                                               stateCache.nonce);
00613                 nodesToPing.push_back(std::make_pair(node, pingContext));
00614             }
00615         }
00616     }
00617     assert(nodesToPing.size() != 0);
00618     // ping nodes
00619     for (uint i = 0; i < nodesToPing.size(); ++i) {
00620         pingNode(*nodesToPing[i].first, timeoutPing, pingRetries,
00621                  nodesToPing[i].second, "PING received state");
00622     }
00623 
00624 }

void BasePastry::determineAliveTable ( const PastryStateMessage *  stateMsg  )  [protected]

change the aliveTable to match the given stateMsg.

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

Referenced by Pastry::handleStateMessage(), and Bamboo::handleStateMessage().

00627 {
00628     uint rt_size = stateMsg->getRoutingTableArraySize();
00629     aliveTable.pr_rt.clear();
00630     aliveTable.pr_rt.resize(rt_size, 1);
00631 
00632     uint ls_size = stateMsg->getLeafSetArraySize();
00633     aliveTable.pr_ls.clear();
00634     aliveTable.pr_ls.resize(ls_size, 1);
00635 
00636     uint ns_size = stateMsg->getNeighborhoodSetArraySize();
00637     aliveTable.pr_ns.clear();
00638     aliveTable.pr_ns.resize(ns_size, 1);
00639 
00640     for (uint i = 0; i < rt_size + ls_size + ns_size; i++) {
00641         const TransportAddress* node;
00642         std::vector<simtime_t>::iterator tblPos;
00643         if (i < rt_size) {
00644             node = &(stateMsg->getRoutingTable(i));
00645             tblPos = aliveTable.pr_rt.begin() + i;
00646         } else if ( i < (rt_size + ls_size) ) {
00647             node = &(stateMsg->getLeafSet(i - rt_size));
00648             tblPos = aliveTable.pr_ls.begin() + (i - rt_size);
00649         } else {
00650             node = &(stateMsg->getNeighborhoodSet(i - rt_size - ls_size));
00651             tblPos = aliveTable.pr_ns.begin() + (i - rt_size - ls_size);
00652         }
00653         if (neighborCache->getAddressRtt(*node) == NEIGHBORSTATE_TIMEOUT) {
00654             *tblPos = PASTRY_PROX_INFINITE;
00655         }
00656     }
00657 }

void BasePastry::sendRequest ( const TransportAddress ask,
int  type 
) [protected]

send a request to a given node

Parameters:
ask request from this node
type specifies the data requested

Referenced by Pastry::changeState(), Pastry::checkProxCache(), Pastry::doSecondStage(), Pastry::handleFailedNode(), and Pastry::handleStateMessage().

00831 {
00832     std::string msgName("Req: ");
00833     switch (type) {
00834     case PASTRY_REQ_REPAIR:
00835         if (ask.isUnspecified())
00836             opp_error("Pastry::sendRequest(): asked for repair from "
00837                   "unspecified node!");
00838         msgName += "Repair";
00839         break;
00840 
00841     case PASTRY_REQ_STATE:
00842         if (ask.isUnspecified())
00843             opp_error("Pastry::sendRequest(): asked for state from "
00844                   "unspecified node!");
00845         msgName += "State";
00846         break;
00847 
00848     case PASTRY_REQ_LEAFSET:
00849         if (ask.isUnspecified())
00850             opp_error("Pastry::sendRequest(): asked for leafset from "
00851                   "unspecified node!");
00852         msgName += "Leafset";
00853         break;
00854     }
00855     PastryRequestMessage* msg = new PastryRequestMessage(msgName.c_str());
00856     msg->setPastryMsgType(PASTRY_MSG_REQ);
00857     msg->setPastryReqType(type);
00858     msg->setStatType(MAINTENANCE_STAT);
00859     msg->setSendStateTo(thisNode);
00860     msg->setLength(PASTRYREQ_L(msg));
00861     sendMessageToUDP(ask, msg);
00862 
00863     switch (type) {
00864     case PASTRY_REQ_REPAIR:
00865         RECORD_STATS(repairReqSent++; repairReqBytesSent += msg->byteLength());
00866         break;
00867 
00868     case PASTRY_REQ_STATE:
00869         RECORD_STATS(stateReqSent++; stateReqBytesSent += msg->byteLength());
00870         break;
00871 
00872     case PASTRY_REQ_LEAFSET:
00873         RECORD_STATS(leafsetReqSent++; leafsetReqBytesSent += msg->byteLength());
00874         break;
00875     }
00876 }

void BasePastry::sendLeafset ( const TransportAddress tell,
bool  pull = false 
) [protected]

send the leafset to a node

Parameters:
tell the node to send to
pull true requests his leafset

Referenced by Bamboo::doLeafsetMaintenance(), handleRequestMessage(), and Bamboo::handleUDPMessage().

00880 {
00881     if (tell.isUnspecified())
00882         opp_error("Pastry::sendLeafset(): send leafset to "
00883                   "unspecified node!");
00884     //if (pull) PastryLeafsetPullMessage* msg = new PastryLeafsetPullMessage("Leafset Pull");
00885     PastryLeafsetMessage* msg = new PastryLeafsetMessage("Leafset");
00886     if (pull) msg->setPastryMsgType(PASTRY_MSG_LEAFSET_PULL);
00887     else msg->setPastryMsgType(PASTRY_MSG_LEAFSET);
00888     msg->setStatType(MAINTENANCE_STAT);
00889     msg->setSender(thisNode);
00890     msg->setSendStateTo(thisNode);
00891     leafSet->dumpToStateMessage(msg);
00892     msg->setLength(PASTRYLEAFSET_L(msg));
00893     RECORD_STATS(leafsetSent++; leafsetBytesSent += msg->byteLength());
00894     sendMessageToUDP(tell, msg);
00895 
00896 
00897 }

void BasePastry::sendRoutingRow ( const TransportAddress tell,
int  row 
) [protected]

send a row of the routing table to a node

Parameters:
tell the node to send to
row the number of the row

Referenced by Pastry::handleUDPMessage(), and Bamboo::handleUDPMessage().

00900 {
00901     if (tell.isUnspecified())
00902         opp_error("Pastry::sendRoutingTable(): asked for routing Table from "
00903                   "unspecified node!");
00904 
00905     PastryRoutingRowMessage* msg = new PastryRoutingRowMessage("Routing Row");
00906     msg->setPastryMsgType(PASTRY_MSG_RROW);
00907     msg->setStatType(MAINTENANCE_STAT);
00908     //msg->setSendStateTo(thisNode);
00909     msg->setSender(thisNode);
00910     msg->setRow(row);
00911     routingTable->dumpRowToMessage(msg, row);
00912     msg->setLength(PASTRYRTABLE_L(msg));
00913     RECORD_STATS(routingTableSent++; routingTableBytesSent += msg->byteLength());
00914     sendMessageToUDP(tell, msg);
00915 }

void BasePastry::handleRequestMessage ( PastryRequestMessage *  msg  )  [protected]

processes state messages, merging with own state tables

Parameters:
msg the pastry state message

Referenced by Pastry::handleUDPMessage(), and Bamboo::handleUDPMessage().

00918 {
00919         uint reqtype = msg->getPastryReqType();
00920         if (reqtype == PASTRY_REQ_REPAIR) {
00921             RECORD_STATS(repairReqReceived++; repairReqBytesReceived +=
00922                          msg->byteLength());
00923             if (state == READY)
00924                 sendStateTables(msg->getSendStateTo(),
00925                                 PASTRY_STATE_REPAIR);
00926             else
00927                 EV << "Pastry: received repair request before reaching "
00928                    << "READY state, dropping message!" << endl;
00929             delete msg;
00930         }
00931         else if (reqtype == PASTRY_REQ_STATE) {
00932             RECORD_STATS(stateReqReceived++; stateReqBytesReceived +=
00933                      msg->byteLength());
00934             if (state == READY)
00935                 sendStateTables(msg->getSendStateTo());
00936             else
00937                 EV << "Pastry: received state request before reaching "
00938                    << "READY state, dropping message!" << endl;
00939             delete msg;
00940         }
00941         else if (PASTRY_REQ_LEAFSET) {
00942             RECORD_STATS(leafsetReqReceived++; leafsetReqBytesReceived +=
00943             msg->byteLength());
00944             if (state == READY) {
00945                  sendLeafset(msg->getSendStateTo());
00946             }
00947             else
00948                 EV << "Pastry: received leafset request before reaching "
00949                    << "READY state, dropping message!" << endl;
00950             delete msg;
00951         }
00952 
00953 }

void BasePastry::handleLeafsetMessage ( PastryLeafsetMessage *  msg,
bool  mergeSender = false 
) [protected]

processes leafset messages, merging with own state tables

Parameters:
msg the pastry state message
mergeSender should the sender also be merged

Referenced by Pastry::handleUDPMessage(), and Bamboo::handleUDPMessage().

00956 {
00957     uint lsSize = msg->getLeafSetArraySize();
00958     PastryStateMessage* stateMsg;
00959 
00960     stateMsg = new PastryStateMessage("STATE");
00961     stateMsg->setTimestamp(msg->getTimestamp());
00962     stateMsg->setPastryMsgType(PASTRY_MSG_STATE);
00963     stateMsg->setStatType(MAINTENANCE_STAT);
00964     stateMsg->setSender(msg->getSender());
00965     stateMsg->setLeafSetArraySize(lsSize);
00966     stateMsg->setNeighborhoodSetArraySize(0);
00967     stateMsg->setRoutingTableArraySize(0);
00968 
00969     for (uint i = 0; i < lsSize; i++) {
00970         stateMsg->setLeafSet(i, msg->getLeafSet(i));
00971     }
00972 
00973     if (mergeSender) {
00974         stateMsg->setLeafSetArraySize(lsSize+1);
00975         stateMsg->setLeafSet(lsSize, msg->getSender());
00976     }
00977 
00978     handleStateMessage(stateMsg);
00979     delete msg;
00980 }

void BasePastry::setOwnNodeID (  )  [protected, virtual]

Overlay implementations can overwrite this virtual method to set a specific nodeID.

The default implementation sets a random nodeID.

Reimplemented from BaseOverlay.

00331 {
00332     thisNode.key = OverlayKey::random();
00333     //cbr
00334 }

void BasePastry::newLeafs ( void   )  [protected]

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

Referenced by Pastry::checkProxCache(), Pastry::handleFailedNode(), Pastry::handleStateMessage(), and Bamboo::handleStateMessage().

00321 {
00322     if (! enableNewLeafs) return;
00323 
00324     PastryNewLeafsMessage* msg = leafSet->getNewLeafsMessage();
00325     if (msg) {
00326         send(msg, "to_app");
00327         EV << "Pastry: newLeafs() called." << endl;
00328     }
00329 }


Friends And Related Function Documentation

friend class PastryLeafSet [friend]


Member Data Documentation

Referenced by baseInit(), findNode(), and finishOverlay().

Referenced by baseInit(), findNode(), and finishOverlay().

Referenced by baseInit(), findNode(), and finishOverlay().

Referenced by baseInit(), findNode(), and finishOverlay().

Referenced by baseInit(), findNode(), and finishOverlay().

uint BasePastry::bitsPerDigit [protected]

Referenced by baseChangeState(), and baseInit().

uint BasePastry::numberOfLeaves [protected]

Referenced by baseChangeState(), and baseInit().

uint BasePastry::pingRetries [protected]

double BasePastry::timeoutPing [protected]

double BasePastry::readyWaitAmount [protected]

double BasePastry::joinTimeoutAmount [protected]

Referenced by baseChangeState(), and baseInit().

double BasePastry::pingCacheExpireTime [protected]

double BasePastry::repairTimeout [protected]

Referenced by baseChangeState(), and baseInit().

double BasePastry::sendStateWaitAmount [protected]

bool BasePastry::enableNewLeafs [protected]

Referenced by baseInit(), and newLeafs().

Referenced by baseInit(), and findNode().

bool BasePastry::alwaysSendUpdate [protected]

Referenced by baseInit(), and Pastry::checkProxCache().

bool BasePastry::optimizeLookup [protected]

Referenced by baseInit(), and findNode().

bool BasePastry::avoidDuplicates [protected]

Referenced by baseInit(), and pingResponse().

bool BasePastry::partialJoinPath [protected]

Referenced by baseInit().

uint BasePastry::numCoordDigits [protected]

Referenced by baseInit().

uint BasePastry::CBRstartAtDigit [protected]

Referenced by baseInit().

uint BasePastry::CBRstopAtDigit [protected]

Referenced by baseInit().

double BasePastry::nearNodeRtt [protected]

Referenced by Pastry::changeState().

uint BasePastry::unspecNodes [protected]

uint BasePastry::pingedNodes [protected]

bool BasePastry::nearNodeImproved [protected]

bool BasePastry::sendPullFlag [protected]

bool BasePastry::useDiscovery [protected]

simtime_t BasePastry::lastStateChange [protected]

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

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

std::vector<TransportAddress> BasePastry::notifyList [protected]

List of nodes to notify after join.

Referenced by Pastry::changeState(), Pastry::doJoinUpdate(), Pastry::doSecondStage(), and purgeVectors().

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

Referenced by Pastry::checkProxCache(), Bamboo::checkProxCache(), Pastry::handleStateMessage(), Bamboo::handleStateMessage(), and purgeVectors().

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

Referenced by determineAliveTable(), Pastry::handleStateMessage(), and Bamboo::handleStateMessage().

std::map<TransportAddress, BaseRouteMessage*> BasePastry::recFwdQueue [protected]

Queue of messages to be forwarded in recursive routing mode.

Referenced by forwardMessageRecursive(), pingResponse(), pingTimeout(), and purgeVectors().

uint BasePastry::joinHopCount [protected]

cMessage* BasePastry::joinTimeout [protected]

cMessage* BasePastry::readyWait [protected]

cMessage* BasePastry::joinUpdateWait [protected]

std::vector<PastrySendState*> BasePastry::sendStateWait [protected]

cMessage* BasePastry::repairTaskTimeout [protected]


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

Generated on Fri Sep 19 13:05:06 2008 for ITM OverSim by  doxygen 1.5.5