#include <Pastry.h>
Inheritance diagram for Pastry:
Public Member Functions | |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | handleTimerEvent (cMessage *msg) |
handles self-messages | |
virtual void | handleUDPMessage (BaseOverlayMessage *msg) |
processes messages from underlay | |
virtual void | handleRpc (BaseCallMessage *msg) |
process RPC messages | |
virtual void | handleRpcResponse (BaseResponseMessage *msg, int rpcId, simtime_t rtt) |
process RPC responses | |
virtual void | handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcID) |
handle RPC timeouts | |
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 statisticts | |
virtual void | receiveChangeNotification (int category, cPolymorphic *details) |
callback-method for events at the NotificationBoard | |
virtual void | updateTooltip () |
updates information shown in tk-environment | |
virtual NodeVector * | findNode (const OverlayKey &key, BaseOverlayMessage *msg) |
implement the findNode call | |
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 | |
virtual bool | isResponsible (const OverlayKey &key) |
Query if the node knowns the k-neighborhood for a key. | |
virtual AbstractLookup * | createLookup (const BaseRouteMessage *msg=NULL) |
Creates a abstract iterative lookup instance. | |
Protected Attributes | |
int | joins |
int | joinTries |
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 |
Private Member Functions | |
virtual void | forwardMessageRecursive (const TransportAddress &dest, BaseRouteMessage *msg) |
Hook for forwarded message in recursive lookup mode. | |
void | rpcPing (PingCall *call) |
handle "Ping" RPC | |
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 | pingNodes (void) |
ping all nodes in the routing table and neighborhood set of the pastry state message pointed to by private member stateCache | |
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 | |
void | reJoin (void) |
try to re-join the network after a lost connection | |
void | newLeafs (void) |
Pastry API: send newLeafs() to application if enabled. | |
Private Attributes | |
PastryRoutingTable * | routingTable |
PastryLeafSet * | leafSet |
PastryNeighborhoodSet * | neighborhoodSet |
uint | state |
uint | bitsPerDigit |
uint | numberOfLeaves |
uint | numberOfNeighbors |
double | readyWaitAmount |
double | joinTimeoutAmount |
double | secondStageWaitAmount |
double | pingCacheExpireTime |
double | repairTimeout |
double | ringCheckInterval |
bool | enableNewLeafs |
bool | optimizeLookup |
bool | optimisticForward |
bool | avoidDuplicates |
NodeHandle | bootstrapNode |
std::vector< PastryStateMessage * > | stReceived |
std::vector< TransportAddress > | notifyList |
PastryStateMessage * | stateCache |
cQueue | stateCacheQueue |
PastryStateMsgProximity | proxCache |
std::vector< PastryStateMsgProximity > | stateReceivedProximities |
PastryPingCache | pingCache |
std::map< TransportAddress, BaseRouteMessage * > | recFwdQueue |
uint | joinHopCount |
cMessage * | joinTimeout |
cMessage * | readyWait |
cMessage * | secondStageWait |
cMessage * | ringCheck |
simtime_t | lastStateChange |
void Pastry::changeState | ( | int | toState | ) | [protected, virtual] |
changes node state
toState | state to change to |
00223 { 00224 if (ringCheck->isScheduled()) cancelEvent(ringCheck); 00225 00226 switch (toState) 00227 { 00228 case INIT: 00229 00230 state = INIT; 00231 00232 if (!thisNode.key.isUnspecified()) 00233 bootstrapOracle->removePeer(thisNode); 00234 00235 if (joinTimeout->isScheduled()) cancelEvent(joinTimeout); 00236 if (readyWait->isScheduled()) cancelEvent(readyWait); 00237 00238 purgeVectors(); 00239 00240 thisNode.key = OverlayKey::random(); 00241 callUpdate(thisNode, true); 00242 bootstrapNode = bootstrapOracle->getBootstrapNode(); 00243 00244 routingTable->initializeTable(bitsPerDigit, repairTimeout, 00245 thisNode); 00246 leafSet->initializeSet(numberOfLeaves, repairTimeout, thisNode); 00247 neighborhoodSet->initializeSet(numberOfNeighbors, thisNode); 00248 00249 updateTooltip(); 00250 lastStateChange = simTime(); 00251 00252 parentModule()->parentModule()->bubble("entering INIT state"); 00253 00254 break; 00255 00256 case JOIN: 00257 00258 state = JOIN; 00259 joinHopCount = 0; 00260 00261 { 00262 PastryJoinMessage* msg = new PastryJoinMessage("JOIN-Request"); 00263 msg->setPastryMsgType(PASTRY_MSG_JOIN); 00264 msg->setSignaling(true); 00265 msg->setJoinHopCount(1); 00266 msg->setSendStateTo(thisNode); 00267 msg->setLength(PASTRYJOIN_L(msg)); 00268 RECORD_STATS(joinSent++; joinBytesSent += msg->byteLength()); 00269 sendToKey(thisNode.key, msg, 0, bootstrapNode); 00270 } 00271 00272 cancelEvent(joinTimeout); 00273 scheduleAt(simTime()+joinTimeoutAmount, joinTimeout); 00274 00275 updateTooltip(); 00276 parentModule()->parentModule()->bubble("entering JOIN state"); 00277 00278 RECORD_STATS(joinTries++); 00279 00280 break; 00281 00282 case READY: 00283 00284 state = READY; 00285 if (ringCheckInterval > 0) 00286 { 00287 scheduleAt(simTime()+ringCheckInterval, ringCheck); 00288 } 00289 00290 bootstrapOracle->registerPeer(thisNode); 00291 00292 // if we are the first node in the network, there's nothing else 00293 // to do 00294 if (bootstrapNode.isUnspecified()) 00295 { 00296 RECORD_STATS(joinTries++); 00297 RECORD_STATS(joins++); 00298 setReadyIcon(true); 00299 return; 00300 } 00301 00302 // determine list of all known nodes as notifyList 00303 notifyList.clear(); 00304 leafSet->dumpToVector(notifyList); 00305 routingTable->dumpToVector(notifyList); 00306 sort(notifyList.begin(), notifyList.end()); 00307 notifyList.erase(unique(notifyList.begin(), notifyList.end()), 00308 notifyList.end()); 00309 00310 // send "update" state message to all nodes who sent us their state 00311 // during INIT, remove these from notifyList so they don't get our 00312 // state twice 00313 std::vector<TransportAddress>::iterator nListPos; 00314 if (!stReceived.empty()) 00315 { 00316 for (std::vector<PastryStateMessage*>::iterator it = 00317 stReceived.begin(); it != stReceived.end(); it++) 00318 { 00319 sendStateTables((*it)->getSender(), PASTRY_STATE_UPDATE, 00320 (*it)->getTimestamp()); 00321 nListPos = find(notifyList.begin(), notifyList.end(), 00322 (*it)->getSender()); 00323 if (nListPos != notifyList.end()) 00324 { 00325 notifyList.erase(nListPos); 00326 } 00327 if (debugOutput) 00328 { 00329 EV << "Pastry::changeState() deleting STATE message " 00330 << static_cast<void*>(*it) << endl; 00331 } 00332 delete *it; 00333 } 00334 stReceived.clear(); 00335 } 00336 00337 // send a normal STATE message to all remaining known nodes 00338 for (std::vector<TransportAddress>::iterator it = 00339 notifyList.begin(); it != notifyList.end(); it++) 00340 { 00341 if (*it != thisNode) sendStateTables(*it); 00342 } 00343 00344 updateTooltip(); 00345 parentModule()->parentModule()->bubble("entering READY state"); 00346 00347 // schedule second stage 00348 cancelEvent(secondStageWait); 00349 scheduleAt(simTime() + secondStageWaitAmount, secondStageWait); 00350 00351 RECORD_STATS(joins++); 00352 00353 break; 00354 } 00355 setReadyIcon(state == READY); 00356 }
void Pastry::checkProxCache | ( | void | ) | [private] |
checks whether proxCache is complete, takes appropriate actions depending on the protocol state
00862 { 00863 simtime_t now = simTime(); 00864 00865 // no cached STATE message? 00866 if (!stateCache) return; 00867 00868 // no entries in proxCache? 00869 if (proxCache.pr_rt.empty()) return; 00870 if (proxCache.pr_ls.empty()) return; 00871 if (proxCache.pr_ns.empty()) return; 00872 00873 // some entries not yet determined? 00874 if (find(proxCache.pr_rt.begin(), proxCache.pr_rt.end(), 00875 PASTRY_PROX_PENDING) != proxCache.pr_rt.end() 00876 ) return; 00877 if (find(proxCache.pr_ls.begin(), proxCache.pr_ls.end(), 00878 PASTRY_PROX_PENDING) != proxCache.pr_ls.end() 00879 ) return; 00880 if (find(proxCache.pr_ns.begin(), proxCache.pr_ns.end(), 00881 PASTRY_PROX_PENDING) != proxCache.pr_ns.end() 00882 ) return; 00883 00884 if (state == JOIN) 00885 { 00886 stateReceivedProximities.push_back(proxCache); 00887 proxCache.pr_rt.clear(); 00888 proxCache.pr_ls.clear(); 00889 proxCache.pr_ns.clear(); 00890 00891 // collected proximities for all STATE messages? 00892 if (stateReceivedProximities.size() == stReceived.size()) 00893 { 00894 stateCache = NULL; 00895 if (debugOutput) 00896 { 00897 EV << "Pastry: [JOIN] starting to build own state from " 00898 << stReceived.size() << " received state messages..." 00899 << endl; 00900 EV << "Pastry: [JOIN] initializing NeighborhoodSet from " 00901 << stReceived.front()->getJoinHopCount() << ". hop" 00902 << endl; 00903 } 00904 if (!neighborhoodSet->mergeState(stReceived.front(), 00905 stateReceivedProximities.front())) 00906 { 00907 EV << "Pastry: Error initializing own neighborhoodSet while " 00908 "joining! Restarting ..." << endl; 00909 changeState(INIT); 00910 changeState(JOIN); 00911 return; 00912 } 00913 if (debugOutput) 00914 { 00915 EV << "Pastry: [JOIN] initializing LeafSet from " 00916 << stReceived.back()->getJoinHopCount() << ". hop" << endl; 00917 } 00918 if (!leafSet->mergeState(stReceived.back(), 00919 stateReceivedProximities.back())) 00920 { 00921 EV << "Pastry: Error initializing own leafSet while " 00922 "joining! Restarting ..." << endl; 00923 changeState(INIT); 00924 changeState(JOIN); 00925 return; 00926 } 00927 if (debugOutput) 00928 { 00929 EV << "Pastry: [JOIN] initializing RoutingTable from all hops" 00930 << endl; 00931 } 00932 if (!routingTable->initStateFromMsgVector( 00933 stReceived, stateReceivedProximities)) 00934 { 00935 EV << "Pastry: Error initializing own routingTable " 00936 "while joining! Restarting ..." << endl; 00937 changeState(INIT); 00938 changeState(JOIN); 00939 return; 00940 } 00941 lastStateChange = now; 00942 newLeafs(); 00943 changeState(READY); 00944 } 00945 else 00946 { 00947 // process next state message in vector: 00948 stateCache = *(stReceived.begin() + 00949 stateReceivedProximities.size()); 00950 pingNodes(); 00951 } 00952 } 00953 else 00954 { 00955 // state == READY 00956 00957 if (debugOutput) 00958 { 00959 EV << "Pastry: handling STATE message" << endl; 00960 EV << " type: " << 00961 ((stateCache->getPastryStateMsgType() == PASTRY_STATE_UPDATE)? 00962 "update":"standard") << endl; 00963 if (stateCache->getPastryStateMsgType() == PASTRY_STATE_UPDATE) 00964 { 00965 EV << " msg timestamp: " << 00966 stateCache->getTimestamp() << endl; 00967 EV << " last state change: " << 00968 lastStateChange << endl; 00969 } 00970 } 00971 00972 if (stateCache->getPastryStateMsgType() == PASTRY_STATE_REPAIR) 00973 { 00974 // try to repair own states based on repair message: 00975 const TransportAddress& askRt = 00976 routingTable->repair(stateCache, proxCache); 00977 if (! askRt.isUnspecified()) sendRepairRequest(askRt); 00978 00979 const TransportAddress& askLs = 00980 leafSet->repair(stateCache, proxCache); 00981 if (! askLs.isUnspecified()) sendRepairRequest(askLs); 00982 00983 // while not really known, it's safe to assume that a repair 00984 // message changed our state: 00985 lastStateChange = now; 00986 newLeafs(); 00987 } 00988 else if ((stateCache->getPastryStateMsgType() == PASTRY_STATE_UPDATE) 00989 && (stateCache->getTimestamp() < lastStateChange)) 00990 { 00991 // if we received an update based on our outdated state, 00992 // send new state message: 00993 EV << "Pastry: outdated state from " << stateCache->getSender() 00994 << endl; 00995 sendStateTables(stateCache->getSender()); 00996 } 00997 else 00998 { 00999 // merge info in own state tables: 01000 if (neighborhoodSet->mergeState(stateCache, proxCache)) 01001 lastStateChange = now; 01002 01003 if (leafSet->mergeState(stateCache, proxCache)) 01004 lastStateChange = now; 01005 01006 if (routingTable->mergeState(stateCache, proxCache)) 01007 lastStateChange = now; 01008 01009 newLeafs(); 01010 } 01011 01012 updateTooltip(); 01013 01014 // if state message was not an update, send one back: 01015 if (stateCache->getPastryStateMsgType() != PASTRY_STATE_UPDATE) 01016 { 01017 sendStateTables(stateCache->getSender(), PASTRY_STATE_UPDATE, 01018 stateCache->getTimestamp()); 01019 } 01020 01021 if (debugOutput) 01022 { 01023 EV << "Pastry::checkProxCache() deleting STATE message " 01024 << static_cast<void*>(stateCache) << endl; 01025 } 01026 delete stateCache; 01027 stateCache = NULL; 01028 proxCache.pr_rt.clear(); 01029 01030 // process next queued message: 01031 if (! stateCacheQueue.empty()) 01032 { 01033 stateCache = (PastryStateMessage*) stateCacheQueue.pop(); 01034 pingNodes(); 01035 } 01036 } 01037 }
AbstractLookup * Pastry::createLookup | ( | const BaseRouteMessage * | msg = NULL |
) | [protected, virtual] |
Creates a abstract iterative lookup instance.
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. |
Reimplemented from BaseOverlay.
01407 { 01408 PastryFindNodeExtData* findNodeExt = 01409 new PastryFindNodeExtData("findNodeExt"); 01410 01411 if (msg) 01412 { 01413 const PastryMessage* pmsg = dynamic_cast<const PastryMessage*>( 01414 msg->encapsulatedMsg()); 01415 if ((pmsg) && (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN)) 01416 { 01417 const PastryJoinMessage* jmsg = 01418 check_and_cast<const PastryJoinMessage*>(pmsg); 01419 findNodeExt->setSendStateTo(jmsg->getSendStateTo()); 01420 findNodeExt->setJoinHopCount(1); 01421 } 01422 } 01423 findNodeExt->setLength(PASTRYFINDNODEEXTDATA_L); 01424 AbstractLookup* newLookup = new BaseLookup(this, 01425 baseLookupConfig, findNodeExt); 01426 lookups.insert(newLookup); 01427 delete findNodeExt; 01428 return newLookup; 01429 }
void Pastry::doSecondStage | ( | void | ) | [private] |
do the second stage of initialization as described in the paper
00664 { 00665 // "second stage" for locality: 00666 notifyList.clear(); 00667 routingTable->dumpToVector(notifyList); 00668 neighborhoodSet->dumpToVector(notifyList); 00669 sort(notifyList.begin(), notifyList.end()); 00670 notifyList.erase(unique(notifyList.begin(), notifyList.end()), 00671 notifyList.end()); 00672 for (std::vector<TransportAddress>::iterator it = notifyList.begin(); 00673 it != notifyList.end(); it++) 00674 { 00675 if (*it == thisNode) continue; 00676 EV << "second stage: requesting state from " << *it << endl; 00677 PastryStateRequestMessage* msg = 00678 new PastryStateRequestMessage("SREQ"); 00679 msg->setSignaling(true); 00680 msg->setPastryMsgType(PASTRY_MSG_SREQ); 00681 msg->setSendStateTo(thisNode); 00682 msg->setLength(PASTRYSREQ_L(msg)); 00683 RECORD_STATS(stateReqSent++; stateReqBytesSent += 00684 msg->byteLength()); 00685 sendMessageToUDP(*it, msg); 00686 } 00687 }
NodeVector * Pastry::findNode | ( | const OverlayKey & | key, | |
BaseOverlayMessage * | msg | |||
) | [virtual] |
implement the findNode call
key | the destination key | |
msg | the message to route |
Reimplemented from BaseOverlay.
01308 { 01309 NodeVector* nextHop = new NodeVector(1); 01310 const NodeHandle* next; 01311 PastryFindNodeExtData* findNodeExt = NULL; 01312 if (msg && msg->hasObject("findNodeExt")) 01313 { 01314 findNodeExt = check_and_cast<PastryFindNodeExtData*>( 01315 msg->getObject("findNodeExt")); 01316 } 01317 01318 if (state != READY) 01319 { 01320 return nextHop; 01321 } 01322 else if (key.isUnspecified() || leafSet->isClosestNode(key)) 01323 { 01324 nextHop->add(thisNode); 01325 if ((! key.isUnspecified()) && (findNodeExt)) 01326 { 01327 // final hop of a JOIN message, send state tables: 01328 const TransportAddress& stateRecipient = 01329 findNodeExt->getSendStateTo(); 01330 if (!stateRecipient.isUnspecified()) 01331 { 01332 sendStateTables(stateRecipient, PASTRY_STATE_JOIN, 01333 findNodeExt->getJoinHopCount(), true); 01334 } 01335 } 01336 } 01337 else 01338 { 01339 // Send state tables on any JOIN message we see: 01340 if (findNodeExt) 01341 { 01342 const TransportAddress& stateRecipient = 01343 findNodeExt->getSendStateTo(); 01344 if (!stateRecipient.isUnspecified()) 01345 { 01346 RECORD_STATS(joinSeen++); 01347 sendStateTables(stateRecipient, PASTRY_STATE_JOIN, 01348 findNodeExt->getJoinHopCount(), false); 01349 } 01350 } 01351 01352 next = &(leafSet->getDestinationNode(key)); 01353 01354 if (next->isUnspecified()) 01355 next = &(routingTable->lookupNextHop(key)); 01356 01357 if (next->isUnspecified()) 01358 { 01359 // call findCloserNode() on all state objects 01360 01361 if (optimizeLookup) 01362 { 01363 const NodeHandle* tmp; 01364 next = &(routingTable->findCloserNode(key, true)); 01365 tmp = &(neighborhoodSet->findCloserNode(key, true)); 01366 01367 if ((! tmp->isUnspecified()) && 01368 (leafSet->isCloser(*tmp, key, *next))) 01369 { 01370 next = tmp; 01371 } 01372 01373 tmp = &(leafSet->findCloserNode(key, true)); 01374 if ((! tmp->isUnspecified()) && 01375 (leafSet->isCloser(*tmp, key, *next))) 01376 { 01377 next = tmp; 01378 } 01379 } 01380 else 01381 { 01382 next = &(routingTable->findCloserNode(key)); 01383 01384 if (next->isUnspecified()) 01385 next = &(neighborhoodSet->findCloserNode(key)); 01386 01387 if (next->isUnspecified()) 01388 next = &(leafSet->findCloserNode(key)); 01389 } 01390 } 01391 01392 if (!next->isUnspecified()) 01393 { 01394 if (findNodeExt) 01395 { 01396 findNodeExt->setJoinHopCount( 01397 findNodeExt->getJoinHopCount() + 1); 01398 } 01399 nextHop->add(*next); 01400 } 01401 } 01402 01403 return nextHop; 01404 }
void Pastry::finishOverlay | ( | ) | [virtual] |
collects statisticts
Reimplemented from BaseOverlay.
01261 { 01262 // collect statistics 01263 01264 recordScalar("Pastry: Successful Joins", joins); 01265 recordScalar("Pastry: overall join tries", joinTries); 01266 recordScalar("Pastry: JOIN Messages seen", joinSeen); 01267 recordScalar("Pastry: bytes of JOIN Messages seen", joinBytesSeen); 01268 recordScalar("Pastry: JOIN Messages received", joinReceived); 01269 recordScalar("Pastry: bytes of JOIN Messages received", 01270 joinBytesReceived); 01271 recordScalar("Pastry: JOIN Messages sent", joinSent); 01272 recordScalar("Pastry: bytes of JOIN Messages sent", joinBytesSent); 01273 recordScalar("Pastry: STATE Messages sent", stateSent); 01274 recordScalar("Pastry: bytes of STATE Messages sent", stateBytesSent); 01275 recordScalar("Pastry: STATE Messages received", stateReceived); 01276 recordScalar("Pastry: bytes of STATE Messages received", 01277 stateBytesReceived); 01278 recordScalar("Pastry: REPAIR Requests sent", repairReqSent); 01279 recordScalar("Pastry: bytes of REPAIR Requests sent", 01280 repairReqBytesSent); 01281 recordScalar("Pastry: REPAIR Requests received", repairReqReceived); 01282 recordScalar("Pastry: bytes of REPAIR Requests received", 01283 repairReqBytesReceived); 01284 recordScalar("Pastry: STATE Requests sent", stateReqSent); 01285 recordScalar("Pastry: bytes of STATE Requests sent", stateReqBytesSent); 01286 recordScalar("Pastry: STATE Requests received", stateReqReceived); 01287 recordScalar("Pastry: bytes of STATE Requests received", 01288 stateReqBytesReceived); 01289 01290 // destroy self timer messages 01291 if (joinTimeout->isScheduled()) cancelEvent(joinTimeout); 01292 if (readyWait->isScheduled()) cancelEvent(readyWait); 01293 if (secondStageWait->isScheduled()) cancelEvent(secondStageWait); 01294 if (ringCheck->isScheduled()) cancelEvent(ringCheck); 01295 01296 delete joinTimeout; 01297 delete readyWait; 01298 delete secondStageWait; 01299 delete ringCheck; 01300 01301 purgeVectors(); 01302 01303 // remove this node from the bootstrap list 01304 if (!thisNode.key.isUnspecified()) bootstrapOracle->removePeer(thisNode); 01305 }
void Pastry::forwardMessageRecursive | ( | const TransportAddress & | dest, | |
BaseRouteMessage * | msg | |||
) | [private, virtual] |
Hook for forwarded message in recursive lookup mode.
Default implementation just calls sendMessageToUDP(). 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.
00609 { 00610 PastryMessage* pmsg = dynamic_cast<PastryMessage*>( 00611 msg->encapsulatedMsg()); 00612 if ( pmsg && (dest != thisNode) ) 00613 { 00614 if (pmsg->getPastryMsgType() == PASTRY_MSG_JOIN) 00615 { 00616 PastryJoinMessage* jmsg = check_and_cast<PastryJoinMessage*>(pmsg); 00617 RECORD_STATS(joinSeen++; joinBytesSeen += jmsg->byteLength()); 00618 sendStateTables(jmsg->getSendStateTo(), PASTRY_STATE_JOIN, 00619 jmsg->getJoinHopCount(), false); 00620 jmsg->setJoinHopCount(jmsg->getJoinHopCount() + 1); 00621 } 00622 } 00623 00624 if (recFwdQueue.find(dest) != recFwdQueue.end()) 00625 { 00626 // rare case, other message for same next hop is pending: 00627 // send the message and hope it isn't lost. 00628 sendMessageToUDP(dest, msg); 00629 return; 00630 } 00631 00632 if (optimisticForward) 00633 { 00634 // forward now: 00635 sendMessageToUDP(dest, msg); 00636 if (! avoidDuplicates) 00637 { 00638 // and keep copy for possible retry: 00639 recFwdQueue[dest] = static_cast<BaseRouteMessage*>(msg->dup()); 00640 } 00641 } 00642 else 00643 { 00644 // keep message in queue (forward later) 00645 recFwdQueue[dest] = msg; 00646 } 00647 sendRpcMessage(dest, new PingCall("PING next hop"), 00648 NULL, OverlayKey::UNSPECIFIED_KEY, -1, 5.0, 2); 00649 }
void Pastry::handleAppMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
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.
01133 { 01134 if (state != READY) 01135 { 01136 return false; 01137 } 01138 01139 if (failed.isUnspecified()) 01140 opp_error("Pastry::handleFailedNode(): failed is unspecified!"); 01141 01142 const TransportAddress& lsAsk = leafSet->failedNode(failed); 01143 const TransportAddress& rtAsk = routingTable->failedNode(failed); 01144 neighborhoodSet->failedNode(failed); 01145 01146 if (! lsAsk.isUnspecified()) sendRepairRequest(lsAsk); 01147 if (! rtAsk.isUnspecified()) sendRepairRequest(rtAsk); 01148 01149 newLeafs(); 01150 01151 if (lsAsk.isUnspecified() && (! leafSet->isValid())) 01152 { 01153 EV << "Pastry: lost connection to the network, trying to re-join." 01154 << endl; 01155 reJoin(); 01156 } 01157 01158 return true; 01159 }
void Pastry::handleRpc | ( | BaseCallMessage * | msg | ) | [virtual] |
process RPC messages
msg | the RPC call message |
Reimplemented from BaseOverlay.
00652 { 00653 RPC_SWITCH_START(msg) 00654 RPC_DELEGATE(Ping, rpcPing); 00655 RPC_SWITCH_END() 00656 }
void Pastry::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
int | rpcId, | |||
simtime_t | rtt | |||
) | [virtual] |
process RPC responses
msg | the RPC response message | |
rpcId | the RPC identifier | |
rtt | round-trip time |
Reimplemented from RpcListener.
00691 { 00692 const NodeHandle& src = msg->getSrcNode(); 00693 const NodeHandle* node; 00694 int i; 00695 int n; 00696 PastryPingCacheEntry pce; 00697 std::map<TransportAddress, BaseRouteMessage*>::iterator pos; 00698 00699 RPC_SWITCH_START(msg) 00700 RPC_ON_RESPONSE(Ping) 00701 { 00702 if (stateCache) 00703 { 00704 // insert into pingCache 00705 pce.inserted = simTime(); 00706 pce.rtt = rtt; 00707 pingCache[src.ip] = pce; 00708 00709 // look for node in routing table of processed state message: 00710 n = stateCache->getRoutingTableArraySize(); 00711 for (i = 0; i < n; i++) 00712 { 00713 node = &(stateCache->getRoutingTable(i)); 00714 if ((!node->isUnspecified()) && (*node == src)) 00715 *(proxCache.pr_rt.begin()+i) = rtt; 00716 } 00717 00718 // look for node in leaf set of processed state message: 00719 n = stateCache->getLeafSetArraySize(); 00720 for (i = 0; i < n; i++) 00721 { 00722 node = &(stateCache->getLeafSet(i)); 00723 if ((!node->isUnspecified()) && (*node == src)) 00724 *(proxCache.pr_ls.begin()+i) = rtt; 00725 } 00726 00727 // look for node in neighb. set of processed state message: 00728 n = stateCache->getNeighborhoodSetArraySize(); 00729 for (i = 0; i < n; i++) 00730 { 00731 node = &(stateCache->getNeighborhoodSet(i)); 00732 if ((!node->isUnspecified()) && (*node == src)) 00733 *(proxCache.pr_ns.begin()+i) = rtt; 00734 } 00735 00736 checkProxCache(); 00737 } 00738 00739 if ((pos = recFwdQueue.find(src)) != recFwdQueue.end()) 00740 { 00741 // insert into pingCache 00742 pce.inserted = simTime(); 00743 pce.rtt = rtt; 00744 pingCache[src.ip] = pce; 00745 00746 // send message 00747 if (!optimisticForward) 00748 { 00749 sendMessageToUDP(pos->first, pos->second); 00750 } 00751 else if (!avoidDuplicates) 00752 { 00753 delete pos->second; 00754 } 00755 recFwdQueue.erase(pos); 00756 } 00757 00758 break; 00759 } 00760 RPC_SWITCH_END() 00761 }
void Pastry::handleRpcTimeout | ( | BaseCallMessage * | msg, | |
const TransportAddress & | dest, | |||
int | rpcID | |||
) | [virtual] |
handle RPC timeouts
msg | the RPC call that timed out | |
dest | the destination node of the RPC call | |
rpcID | the RPC identifier |
Reimplemented from RpcListener.
01041 { 01042 const NodeHandle* node; 01043 int i; 01044 int n; 01045 PastryPingCacheEntry pce; 01046 std::map<TransportAddress, BaseRouteMessage*>::iterator pos; 01047 01048 // update ping cache: 01049 pce.inserted = simTime(); 01050 pce.rtt = PASTRY_PROX_INFINITE; 01051 pingCache[dest.ip] = pce; 01052 01053 RPC_SWITCH_START(msg) 01054 RPC_ON_CALL(Ping) 01055 { 01056 EV << "Pastry: Ping timeout occured." << endl; 01057 01058 if (msg->isName("PING ring check")) 01059 { 01060 // direct neighbor on the ring found dead: 01061 handleFailedNode(dest); 01062 break; 01063 } 01064 01065 if (stateCache && msg->isName("PING received state")) 01066 { 01067 // look for node in routing table of processed state message: 01068 n = stateCache->getRoutingTableArraySize(); 01069 for (i = 0; i < n; i++) 01070 { 01071 node = &(stateCache->getRoutingTable(i)); 01072 if ((!node->isUnspecified()) && (node->ip == dest.ip)) 01073 *(proxCache.pr_rt.begin() + i) = PASTRY_PROX_INFINITE; 01074 } 01075 01076 // look for node in leaf set of processed state message: 01077 n = stateCache->getLeafSetArraySize(); 01078 for (i = 0; i < n; i++) 01079 { 01080 node = &(stateCache->getLeafSet(i)); 01081 if ((!node->isUnspecified()) && (node->ip == dest.ip)) 01082 *(proxCache.pr_ls.begin() + i) = PASTRY_PROX_INFINITE; 01083 } 01084 01085 // look for node in neighborhood set of processed state message: 01086 n = stateCache->getNeighborhoodSetArraySize(); 01087 for (i = 0; i < n; i++) 01088 { 01089 node = &(stateCache->getNeighborhoodSet(i)); 01090 if ((!node->isUnspecified()) && (node->ip == dest.ip)) 01091 *(proxCache.pr_ns.begin() + i) = PASTRY_PROX_INFINITE; 01092 } 01093 checkProxCache(); 01094 } 01095 01096 if (msg->isName("PING next hop")) 01097 { 01098 // handle failed node: 01099 handleFailedNode(dest); 01100 01101 // this could initiate a re-join, exit the handler in that 01102 // case because all local data was erased: 01103 if (state != READY) break; 01104 01105 // handle forward queue entry 01106 if ((pos = recFwdQueue.find(dest)) == recFwdQueue.end()) break; 01107 BaseRouteMessage* rmsg = pos->second; 01108 recFwdQueue.erase(pos); 01109 sendToKey(rmsg->getDestKey(), rmsg); 01110 } 01111 01112 break; 01113 } 01114 RPC_SWITCH_END() 01115 }
void Pastry::handleStateMessage | ( | PastryStateMessage * | msg | ) |
processes state messages, merging with own state tables
msg | the pastry state message |
00493 { 00494 if (debugOutput) 00495 { 00496 EV << "Pastry::handleStateMessage() new STATE message to process " 00497 << static_cast<void*>(msg) << " in state " << 00498 ((state == READY)?"READY":((state == JOIN)?"JOIN":"INIT")) 00499 << endl; 00500 if (state == JOIN) 00501 { 00502 EV << " *** own joinHopCount: " << joinHopCount << endl; 00503 EV << " *** already received: " << stReceived.size() << endl; 00504 EV << " *** last-hop flag: " << msg->getLastHop() << endl; 00505 EV << " *** msg joinHopCount: " 00506 << msg->getJoinHopCount() << endl; 00507 } 00508 } 00509 if (state == INIT) 00510 { 00511 EV << "Pastry: can't handle state messages until at least reaching " 00512 "JOIN state." << endl; 00513 if (debugOutput) 00514 { 00515 EV << "Pastry::handleStateMessage() deleting STATE message " 00516 << static_cast<void*>(msg) << endl; 00517 } 00518 delete msg; 00519 return; 00520 } 00521 00522 // in JOIN state, store all received state Messages, need them later: 00523 if (state == JOIN) 00524 { 00525 if (joinHopCount && stReceived.size() == joinHopCount) 00526 { 00527 EV << "Pastry: Warning: dropping state message received after " 00528 "all needed state messages were collected in JOIN state." 00529 << endl; 00530 if (debugOutput) 00531 { 00532 EV << "Pastry::handleStateMessage() deleting STATE message " 00533 << static_cast<void*>(msg) << endl; 00534 } 00535 delete msg; 00536 return; 00537 } 00538 00539 stReceived.push_back(msg); 00540 00541 if (msg->getLastHop()) 00542 { 00543 if (joinTimeout->isScheduled()) cancelEvent(joinTimeout); 00544 00545 if (joinHopCount) 00546 { 00547 EV << "Pastry: Error: received a second `last' state message! " 00548 "Restarting ..." << endl; 00549 changeState(INIT); 00550 changeState(JOIN); 00551 return; 00552 } 00553 00554 joinHopCount = msg->getJoinHopCount(); 00555 if (stReceived.size() < joinHopCount) 00556 { 00557 // some states still missing: 00558 cancelEvent(readyWait); 00559 scheduleAt(simTime()+readyWaitAmount, readyWait); 00560 } 00561 } 00562 00563 if (joinHopCount) 00564 { 00565 if (stReceived.size() > joinHopCount) 00566 { 00567 EV << "Pastry: Error: too many state messages received in " 00568 "JOIN state! Restarting ..." << endl; 00569 changeState(INIT); 00570 changeState(JOIN); 00571 return; 00572 } 00573 if (stReceived.size() == joinHopCount) 00574 { 00575 // all state messages are here, sort by hopcount: 00576 sort(stReceived.begin(), stReceived.end(), 00577 stateMsgIsSmaller); 00578 00579 // start pinging the nodes found in the first state message: 00580 stateReceivedProximities.clear(); 00581 stateCache = stReceived.front(); 00582 EV << "Pastry: have all STATE messages, now pinging nodes." 00583 << endl; 00584 pingNodes(); 00585 00586 // cancel timeout: 00587 if (readyWait->isScheduled()) cancelEvent(readyWait); 00588 } 00589 } 00590 return; 00591 } 00592 00593 // in READY state, only ping nodes to get proximity metric: 00594 if (!stateCache) 00595 { 00596 // no state message is processed right now, start immediately: 00597 stateCache = msg; 00598 pingNodes(); 00599 } 00600 else 00601 { 00602 // enqueue message for later processing: 00603 stateCacheQueue.insert(msg); 00604 } 00605 }
void Pastry::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
handles self-messages
msg | the self-message |
Reimplemented from BaseOverlay.
00359 { 00360 00361 if (msg->isName("joinTimeout")) 00362 { 00363 EV << "Pastry: join timeout expired, restarting..." << endl; 00364 changeState(INIT); 00365 changeState(JOIN); 00366 } 00367 else if (msg->isName("readyWait")) 00368 { 00369 EV << "Pastry: timeout waiting for missing state messages in JOIN " 00370 "state, restarting..." << endl; 00371 changeState(INIT); 00372 changeState(JOIN); 00373 } 00374 else if (msg->isName("secondStageWait")) 00375 { 00376 EV << "Pastry: sending STATE requests to all nodes in second stage " 00377 "of initialization." << endl; 00378 doSecondStage(); 00379 } 00380 else if (msg->isName("ringCheck")) 00381 { 00382 if (state == READY) 00383 { 00384 // ping direct neighbors on the ring: 00385 const NodeHandle& pred = leafSet->getPredecessor(); 00386 const NodeHandle& succ = leafSet->getSuccessor(); 00387 if (! pred.isUnspecified()) 00388 { 00389 sendRpcMessage(pred, new PingCall("PING ring check"), 00390 NULL, OverlayKey::UNSPECIFIED_KEY, -1, 5.0, 2); 00391 } 00392 if (! succ.isUnspecified()) 00393 { 00394 sendRpcMessage(succ, new PingCall("PING ring check"), 00395 NULL, OverlayKey::UNSPECIFIED_KEY, -1, 5.0, 2); 00396 } 00397 } 00398 scheduleAt(simTime()+ringCheckInterval, ringCheck); 00399 } 00400 }
void Pastry::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
processes messages from underlay
msg | message from UDP |
Implements BaseOverlay.
00403 { 00404 PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg); 00405 uint type = pastryMsg->getPastryMsgType(); 00406 00407 if (debugOutput) 00408 { 00409 EV << "Pastry: incoming message of type "; 00410 switch(type) 00411 { 00412 case PASTRY_MSG_STD: EV << "PASTRY_MSG_STD"; break; 00413 case PASTRY_MSG_JOIN: EV << "PASTRY_MSG_JOIN"; break; 00414 case PASTRY_MSG_STATE: EV << "PASTRY_MSG_STATE"; break; 00415 case PASTRY_MSG_RREQ: EV << "PASTRY_MSG_RREQ"; break; 00416 case PASTRY_MSG_SREQ: EV << "PASTRY_MSG_SREQ"; break; 00417 default: EV << "UNKNOWN (" << type <<")"; break; 00418 } 00419 EV << endl; 00420 } 00421 00422 switch (type) 00423 { 00424 case PASTRY_MSG_STD: 00425 opp_error("Pastry received PastryMessage of unknown type!"); 00426 break; 00427 00428 case PASTRY_MSG_JOIN: 00429 { 00430 PastryJoinMessage* jmsg = 00431 check_and_cast<PastryJoinMessage*>(pastryMsg); 00432 RECORD_STATS(joinReceived++; joinBytesReceived += 00433 jmsg->byteLength()); 00434 if (! iterativeLookup) 00435 { 00436 // in iterative lookup mode, this is handled by findNode() 00437 if (state == READY) 00438 sendStateTables(jmsg->getSendStateTo(), 00439 PASTRY_STATE_JOIN, jmsg->getJoinHopCount(), 00440 true); 00441 else 00442 EV << "Pastry: received join message before reaching " 00443 << "READY state, dropping message!" << endl; 00444 } 00445 delete jmsg; 00446 } 00447 break; 00448 00449 case PASTRY_MSG_RREQ: 00450 { 00451 PastryRepairRequestMessage* rrmsg = 00452 check_and_cast<PastryRepairRequestMessage*>(pastryMsg); 00453 RECORD_STATS(repairReqReceived++; repairReqBytesReceived += 00454 rrmsg->byteLength()); 00455 if (state == READY) 00456 sendStateTables(rrmsg->getSendStateTo(), 00457 PASTRY_STATE_REPAIR); 00458 else 00459 EV << "Pastry: received repair request before reaching " 00460 << "READY state, dropping message!" << endl; 00461 delete rrmsg; 00462 } 00463 break; 00464 00465 case PASTRY_MSG_SREQ: 00466 { 00467 PastryStateRequestMessage* srmsg = 00468 check_and_cast<PastryStateRequestMessage*>(pastryMsg); 00469 RECORD_STATS(stateReqReceived++; stateReqBytesReceived += 00470 srmsg->byteLength()); 00471 if (state == READY) 00472 sendStateTables(srmsg->getSendStateTo()); 00473 else 00474 EV << "Pastry: received state request before reaching " 00475 << "READY state, dropping message!" << endl; 00476 delete srmsg; 00477 } 00478 break; 00479 00480 case PASTRY_MSG_STATE: 00481 { 00482 PastryStateMessage* stateMsg = 00483 check_and_cast<PastryStateMessage*>(msg); 00484 RECORD_STATS(stateReceived++; stateBytesReceived += 00485 stateMsg->byteLength()); 00486 handleStateMessage(stateMsg); 00487 } 00488 break; 00489 } 00490 }
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.
00037 { 00038 if ( stage != MIN_STAGE_OVERLAY ) 00039 return; 00040 00041 bitsPerDigit = par("bitsPerDigit"); 00042 numberOfLeaves = par("numberOfLeaves"); 00043 numberOfNeighbors = par("numberOfNeighbors"); 00044 joinTimeoutAmount = par("joinTimeout"); 00045 readyWaitAmount = par("readyWait"); 00046 secondStageWaitAmount = par("secondStageWait"); 00047 pingCacheExpireTime = par("pingCacheExpireTime"); 00048 repairTimeout = par("repairTimeout"); 00049 enableNewLeafs = par("enableNewLeafs"); 00050 optimizeLookup = par("optimizeLookup"); 00051 optimisticForward = par("optimisticForward"); 00052 avoidDuplicates = par("avoidDuplicates"); 00053 ringCheckInterval = par("ringCheckInterval"); 00054 00055 if (numberOfLeaves % 2) 00056 { 00057 EV << "Pastry: Warning: numberOfLeaves must be even - adding 1."; 00058 numberOfLeaves++; 00059 } 00060 00061 routingTable = check_and_cast<PastryRoutingTable*> 00062 (parentModule()->submodule("pastryRoutingTable")); 00063 leafSet = check_and_cast<PastryLeafSet*> 00064 (parentModule()->submodule("pastryLeafSet")); 00065 neighborhoodSet = check_and_cast<PastryNeighborhoodSet*> 00066 (parentModule()->submodule("pastryNeighborhoodSet")); 00067 00068 joinTimeout = new cMessage("joinTimeout"); 00069 readyWait = new cMessage("readyWait"); 00070 secondStageWait = new cMessage("secondStageWait"); 00071 ringCheck = new cMessage("ringCheck"); 00072 00073 stateCache = NULL; 00074 00075 // initialize statistics 00076 joins = 0; 00077 joinTries = 0; 00078 joinSeen = 0; 00079 joinReceived = 0; 00080 joinSent = 0; 00081 stateSent = 0; 00082 stateReceived = 0; 00083 repairReqSent = 0; 00084 repairReqReceived = 0; 00085 stateReqSent = 0; 00086 stateReqReceived = 0; 00087 00088 joinBytesSeen = 0; 00089 joinBytesReceived = 0; 00090 joinBytesSent = 0; 00091 stateBytesSent = 0; 00092 stateBytesReceived = 0; 00093 repairReqBytesSent = 0; 00094 repairReqBytesReceived = 0; 00095 stateReqBytesSent = 0; 00096 stateReqBytesReceived = 0; 00097 00098 WATCH(joins); 00099 WATCH(joinTries); 00100 WATCH(joinSeen); 00101 WATCH(joinBytesSeen); 00102 WATCH(joinReceived); 00103 WATCH(joinBytesReceived); 00104 WATCH(joinSent); 00105 WATCH(joinBytesSent); 00106 WATCH(stateSent); 00107 WATCH(stateBytesSent); 00108 WATCH(stateReceived); 00109 WATCH(stateBytesReceived); 00110 WATCH(repairReqSent); 00111 WATCH(repairReqBytesSent); 00112 WATCH(repairReqReceived); 00113 WATCH(repairReqBytesReceived); 00114 WATCH(stateReqSent); 00115 WATCH(stateReqBytesSent); 00116 WATCH(stateReqReceived); 00117 WATCH(stateReqBytesReceived); 00118 WATCH(lastStateChange); 00119 WATCH(proxCache); 00120 WATCH_VECTOR(stateReceivedProximities); 00121 00122 00123 changeState(INIT); 00124 00125 if (bootstrapNode.isUnspecified()) 00126 { 00127 changeState(READY); 00128 } 00129 else 00130 { 00131 changeState(JOIN); 00132 } 00133 }
bool Pastry::isResponsible | ( | const OverlayKey & | key | ) | [protected, virtual] |
Query if the node knowns the k-neighborhood for a key.
Query if the node knowns the complete k-neighborhood for the given key. Usually these are all nodes, that are responsible for the key. If there is no k-neighborhood in a specific overlay protocol, this method simply returns true, if the node is responsible for the key.
key | destination key |
Reimplemented from BaseOverlay.
01218 { 01219 if (leafSet->isClosestNode(key)) return true; 01220 const NodeHandle& dest = leafSet->getDestinationNode(key); 01221 return (! dest.isUnspecified()); 01222 }
void Pastry::newLeafs | ( | void | ) | [private] |
Pastry API: send newLeafs() to application if enabled.
00195 { 00196 if (! enableNewLeafs) return; 00197 00198 PastryNewLeafsMessage* msg = leafSet->getNewLeafsMessage(); 00199 if (msg) 00200 { 00201 send(msg, "to_app"); 00202 EV << "Pastry: newLeafs() called." << endl; 00203 } 00204 }
void Pastry::pingNodes | ( | void | ) | [private] |
ping all nodes in the routing table and neighborhood set of the pastry state message pointed to by private member stateCache
00764 { 00765 int i; 00766 int rt_size; 00767 int ls_size; 00768 int ns_size; 00769 const NodeHandle* node; 00770 std::vector<simtime_t>::iterator proxPos; 00771 PingCall* call; 00772 PastryPingCache::iterator it; 00773 00774 rt_size = stateCache->getRoutingTableArraySize(); 00775 proxCache.pr_rt.clear(); 00776 proxCache.pr_rt.resize(rt_size, PASTRY_PROX_PENDING); 00777 00778 ls_size = stateCache->getLeafSetArraySize(); 00779 proxCache.pr_ls.clear(); 00780 proxCache.pr_ls.resize(ls_size, PASTRY_PROX_PENDING); 00781 00782 ns_size = stateCache->getNeighborhoodSetArraySize(); 00783 proxCache.pr_ns.clear(); 00784 proxCache.pr_ns.resize(ns_size, PASTRY_PROX_PENDING); 00785 00786 std::vector<OverlayKey>* pinged = new std::vector<OverlayKey>; 00787 pinged->reserve(rt_size + ls_size + ns_size); 00788 std::vector<OverlayKey>::iterator pingedPos; 00789 00790 for (i = 0; i < rt_size + ls_size + ns_size; i++) 00791 { 00792 if (i < rt_size) 00793 { 00794 node = &(stateCache->getRoutingTable(i)); 00795 proxPos = proxCache.pr_rt.begin() + i; 00796 } 00797 else if ( i < (rt_size + ls_size) ) 00798 { 00799 node = &(stateCache->getLeafSet(i - rt_size)); 00800 proxPos = proxCache.pr_ls.begin() + (i - rt_size); 00801 } 00802 else 00803 { 00804 node = &(stateCache->getNeighborhoodSet(i - rt_size - ls_size)); 00805 proxPos = proxCache.pr_ns.begin() + (i - rt_size - ls_size); 00806 } 00807 00808 // proximity is undefined for unspecified nodes: 00809 if (node->isUnspecified()) 00810 { 00811 *proxPos = PASTRY_PROX_UNDEF; 00812 } 00813 00814 // and 0 for own node: 00815 else if (*node == thisNode) 00816 { 00817 *proxPos = 0; 00818 } 00819 00820 // else determine real value: 00821 else 00822 { 00823 if ((it = pingCache.find(node->ip)) != pingCache.end()) 00824 { 00825 if ((simTime() - it->second.inserted) < pingCacheExpireTime) 00826 { 00827 *proxPos = it->second.rtt; 00828 if (debugOutput) 00829 { 00830 EV << "Pastry: pingCache HIT" << endl; 00831 } 00832 continue; 00833 } 00834 else 00835 { 00836 if (debugOutput) 00837 { 00838 EV << "Pastry: pingCache OUTDATED" << endl; 00839 } 00840 pingCache.erase(it); 00841 } 00842 } 00843 else if (debugOutput) 00844 { 00845 EV << "Pastry: pingCache MISS" << endl; 00846 } 00847 if ((pingedPos = find(pinged->begin(), pinged->end(), node->key)) 00848 == pinged->end()) 00849 { 00850 pinged->push_back(node->key); 00851 call = new PingCall("PING received state"); 00852 sendRpcMessage(*node, call, NULL, 00853 OverlayKey::UNSPECIFIED_KEY, -1, 5.0, 2); 00854 } 00855 } 00856 } 00857 delete pinged; 00858 checkProxCache(); 00859 }
void Pastry::purgeVectors | ( | void | ) | [private] |
delete all information/messages caching vectors, used for restarting overlay or finish()
00136 { 00137 PastryStateMessage* stateMsg; 00138 00139 // purge pending state messages 00140 if (!stReceived.empty()) 00141 { 00142 for (std::vector<PastryStateMessage*>::iterator it = 00143 stReceived.begin(); it != stReceived.end(); it++) 00144 { 00145 // check whether one of the pointers is a duplicate of stateCache 00146 if (*it == stateCache) stateCache = NULL; 00147 if (debugOutput) 00148 { 00149 EV << "Pastry::purgeVectors() deleting STATE message " 00150 << static_cast<void*>(*it) << endl; 00151 } 00152 delete *it; 00153 } 00154 stReceived.clear(); 00155 } 00156 00157 // purge notify list: 00158 notifyList.clear(); 00159 00160 // purge Ping Cache: 00161 pingCache.clear(); 00162 00163 // purge proximity cache for received state messages: 00164 stateReceivedProximities.clear(); 00165 00166 // purge Queue for messages to be forwarded in recursive mode: 00167 for (std::map<TransportAddress, BaseRouteMessage*>::iterator i = 00168 recFwdQueue.begin(); i != recFwdQueue.end(); i++) 00169 { 00170 delete i->second; 00171 } 00172 recFwdQueue.clear(); 00173 00174 // purge Queue for processing multiple STATE messages: 00175 while (! stateCacheQueue.empty()) 00176 { 00177 stateMsg = (PastryStateMessage*) stateCacheQueue.pop(); 00178 delete stateMsg; 00179 } 00180 00181 // delete cached state message: 00182 if (stateCache) 00183 { 00184 if (debugOutput) 00185 { 00186 EV << "Pastry::purgeVectors() deleting STATE message " 00187 << static_cast<void*>(stateCache) << endl; 00188 } 00189 delete stateCache; 00190 stateCache = NULL; 00191 } 00192 }
void Pastry::receiveChangeNotification | ( | int | category, | |
cPolymorphic * | details | |||
) | [virtual] |
void Pastry::reJoin | ( | void | ) | [private] |
try to re-join the network after a lost connection
00207 { 00208 if (ringCheck->isScheduled()) cancelEvent(ringCheck); 00209 if (joinTimeout->isScheduled()) cancelEvent(joinTimeout); 00210 if (readyWait->isScheduled()) cancelEvent(readyWait); 00211 bootstrapOracle->removePeer(thisNode); 00212 purgeVectors(); 00213 bootstrapNode = bootstrapOracle->getBootstrapNode(); 00214 routingTable->initializeTable(bitsPerDigit, repairTimeout, thisNode); 00215 leafSet->initializeSet(numberOfLeaves, repairTimeout, thisNode); 00216 neighborhoodSet->initializeSet(numberOfNeighbors, thisNode); 00217 updateTooltip(); 00218 lastStateChange = simTime(); 00219 changeState(JOIN); 00220 }
void Pastry::rpcPing | ( | PingCall * | call | ) | [private] |
handle "Ping" RPC
call | the RPC call message |
00659 { 00660 sendRpcResponse(call, new PingResponse("PING response")); 00661 }
void Pastry::sendRepairRequest | ( | const TransportAddress & | ask | ) | [private] |
send a repair request to a given node
ask | request repair from this node |
01118 { 01119 if (ask.isUnspecified()) 01120 opp_error("Pastry::sendRepairRequest(): asked for repair from " 01121 "unspecified node!"); 01122 01123 PastryRepairRequestMessage* msg = new PastryRepairRequestMessage("RREQ"); 01124 msg->setPastryMsgType(PASTRY_MSG_RREQ); 01125 msg->setSignaling(true); 01126 msg->setSendStateTo(thisNode); 01127 msg->setLength(PASTRYRREQ_L(msg)); 01128 RECORD_STATS(repairReqSent++; repairReqBytesSent += msg->byteLength()); 01129 sendMessageToUDP(ask, msg); 01130 }
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 |
01162 { 01163 int hops = 0; 01164 bool last = false; 01165 simtime_t timestamp = 0; 01166 01167 if ((type == PASTRY_STATE_JOIN) || (type == PASTRY_STATE_UPDATE)) 01168 { 01169 // additional parameters needed: 01170 va_list ap; 01171 va_start(ap, type); 01172 if (type == PASTRY_STATE_JOIN) 01173 { 01174 hops = va_arg(ap, int); 01175 last = static_cast<bool>(va_arg(ap, int)); 01176 } 01177 else 01178 { 01179 timestamp = va_arg(ap, simtime_t); 01180 } 01181 va_end(ap); 01182 } 01183 01184 // create new state message and fill in standard content: 01185 PastryStateMessage* stateMsg = new PastryStateMessage("STATE"); 01186 stateMsg->setPastryMsgType(PASTRY_MSG_STATE); 01187 stateMsg->setSignaling(true); 01188 stateMsg->setPastryStateMsgType(type); 01189 stateMsg->setSender(thisNode); 01190 routingTable->dumpToStateMessage(stateMsg); 01191 leafSet->dumpToStateMessage(stateMsg); 01192 neighborhoodSet->dumpToStateMessage(stateMsg); 01193 01194 // special fields for some types: 01195 if (type == PASTRY_STATE_JOIN) 01196 { 01197 stateMsg->setJoinHopCount(hops); 01198 stateMsg->setLastHop(last); 01199 } 01200 01201 if (type == PASTRY_STATE_UPDATE) 01202 { 01203 EV << "Pastry: sending state (update) to " << destination << endl; 01204 stateMsg->setTimestamp(timestamp); 01205 } 01206 else 01207 { 01208 EV << "Pastry: sending state (standard) to " << destination << endl; 01209 stateMsg->setTimestamp(simTime()); 01210 } 01211 01212 stateMsg->setLength(PASTRYSTATE_L(stateMsg)); 01213 RECORD_STATS(stateSent++; stateBytesSent += stateMsg->byteLength()); 01214 sendMessageToUDP(destination, stateMsg); 01215 }
void Pastry::updateTooltip | ( | ) | [virtual] |
updates information shown in tk-environment
01230 { 01231 if (ev.isGUI()) { 01232 std::stringstream ttString; 01233 01234 // show our predecessor and successor in tooltip 01235 ttString << leafSet->getPredecessor() << endl << thisNode << endl 01236 << leafSet->getSuccessor(); 01237 01238 parentModule()->parentModule()->displayString(). 01239 setTagArg("tt", 0, ttString.str().c_str()); 01240 parentModule()->displayString(). 01241 setTagArg("tt", 0, ttString.str().c_str()); 01242 displayString().setTagArg("tt", 0, ttString.str().c_str()); 01243 01244 // draw arrows: 01245 showOverlayNeighborArrow(leafSet->getSuccessor(), true, 01246 "m=m,50,0,50,0;o=red,1"); 01247 showOverlayNeighborArrow(leafSet->getPredecessor(), false, 01248 "m=m,50,100,50,100;o=green,1"); 01249 01250 } 01251 }
bool Pastry::avoidDuplicates [private] |
uint Pastry::bitsPerDigit [private] |
NodeHandle Pastry::bootstrapNode [private] |
bool Pastry::enableNewLeafs [private] |
int Pastry::joinBytesReceived [protected] |
int Pastry::joinBytesSeen [protected] |
int Pastry::joinBytesSent [protected] |
uint Pastry::joinHopCount [private] |
int Pastry::joinReceived [protected] |
int Pastry::joins [protected] |
int Pastry::joinSeen [protected] |
int Pastry::joinSent [protected] |
cMessage* Pastry::joinTimeout [private] |
double Pastry::joinTimeoutAmount [private] |
int Pastry::joinTries [protected] |
simtime_t Pastry::lastStateChange [private] |
PastryLeafSet* Pastry::leafSet [private] |
PastryNeighborhoodSet* Pastry::neighborhoodSet [private] |
std::vector<TransportAddress> Pastry::notifyList [private] |
uint Pastry::numberOfLeaves [private] |
uint Pastry::numberOfNeighbors [private] |
bool Pastry::optimisticForward [private] |
bool Pastry::optimizeLookup [private] |
PastryPingCache Pastry::pingCache [private] |
double Pastry::pingCacheExpireTime [private] |
PastryStateMsgProximity Pastry::proxCache [private] |
cMessage* Pastry::readyWait [private] |
double Pastry::readyWaitAmount [private] |
std::map<TransportAddress, BaseRouteMessage*> Pastry::recFwdQueue [private] |
int Pastry::repairReqBytesReceived [protected] |
int Pastry::repairReqBytesSent [protected] |
int Pastry::repairReqReceived [protected] |
int Pastry::repairReqSent [protected] |
double Pastry::repairTimeout [private] |
cMessage* Pastry::ringCheck [private] |
double Pastry::ringCheckInterval [private] |
PastryRoutingTable* Pastry::routingTable [private] |
cMessage* Pastry::secondStageWait [private] |
double Pastry::secondStageWaitAmount [private] |
uint Pastry::state [private] |
int Pastry::stateBytesReceived [protected] |
int Pastry::stateBytesSent [protected] |
PastryStateMessage* Pastry::stateCache [private] |
cQueue Pastry::stateCacheQueue [private] |
int Pastry::stateReceived [protected] |
std::vector<PastryStateMsgProximity> Pastry::stateReceivedProximities [private] |
int Pastry::stateReqBytesReceived [protected] |
int Pastry::stateReqBytesSent [protected] |
int Pastry::stateReqReceived [protected] |
int Pastry::stateReqSent [protected] |
int Pastry::stateSent [protected] |
std::vector<PastryStateMessage*> Pastry::stReceived [private] |