#include <Pastry.h>
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 NodeVector * | findNode (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 AbstractLookup * | createLookup (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 | |
PastryRoutingTable * | routingTable |
PastryLeafSet * | leafSet |
PastryNeighborhoodSet * | neighborhoodSet |
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 |
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 }
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.
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.
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.
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.
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.
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
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] |
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.
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. |
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.
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().
Reimplemented from BaseOverlay.
void Pastry::changeState | ( | int | toState | ) | [protected, virtual] |
changes node state
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
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
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.
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 |
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.
dest | destination node | |
msg | message to send |
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
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
failed | the failed node |
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 }
friend class PastryLeafSet [friend] |
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] |
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] |