Pastry overlay module. More...
#include <Pastry.h>
Public Member Functions | |
virtual | ~Pastry () |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | handleTimerEvent (cMessage *msg) |
virtual void | handleUDPMessage (BaseOverlayMessage *msg) |
Processes messages from underlay. | |
void | handleStateMessage (PastryStateMessage *msg) |
processes state messages, merging with own state tables | |
virtual void | pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt) |
Protected Member Functions | |
virtual void | purgeVectors (void) |
delete all information/messages caching vectors, used for restarting overlay or finish() | |
virtual void | changeState (int toState) |
changes node state | |
virtual bool | recursiveRoutingHook (const TransportAddress &dest, BaseRouteMessage *msg) |
Hook for forwarded message in recursive lookup mode. | |
void | iterativeJoinHook (BaseOverlayMessage *msg, bool incrHopCount) |
Protected Attributes | |
std::vector< PastryStateMsgHandle > | stReceived |
State messages to process during join. | |
std::vector < PastryStateMsgHandle > ::iterator | stReceivedPos |
std::vector< TransportAddress > | notifyList |
List of nodes to notify after join. | |
Private Member Functions | |
void | clearVectors () |
void | doSecondStage (void) |
do the second stage of initialization as described in the paper | |
void | doRoutingTableMaintenance () |
periodic routing table maintenance requests the corresponding routing table row from one node in each row | |
bool | handleFailedNode (const TransportAddress &failed) |
notifies leafset and routingtable of a failed node and sends out a repair request if possible | |
void | checkProxCache (void) |
checks whether proxCache is complete, takes appropriate actions depending on the protocol state | |
void | processState (void) |
bool | mergeState (void) |
void | endProcessingState (void) |
void | doJoinUpdate (void) |
send updated state to all nodes when entering ready state | |
virtual void | joinOverlay () |
Join the overlay with a given nodeID in thisNode.key. | |
Private Attributes | |
simtime_t | secondStageInterval |
simtime_t | routingTableMaintenanceInterval |
simtime_t | discoveryTimeoutAmount |
bool | partialJoinPath |
int | depth |
int | updateCounter |
bool | minimalJoinState |
bool | useDiscovery |
bool | useSecondStage |
bool | sendStateAtLeafsetRepair |
bool | pingBeforeSecondStage |
bool | overrideOldPastry |
bool | overrideNewPastry |
cMessage * | secondStageWait |
cMessage * | ringCheck |
cMessage * | discoveryTimeout |
cMessage * | repairTaskTimeout |
Pastry overlay module.
Definition at line 54 of file Pastry.h.
Pastry::~Pastry | ( | ) | [virtual] |
Definition at line 41 of file Pastry.cc.
00042 { 00043 // destroy self timer messages 00044 cancelAndDelete(readyWait); 00045 cancelAndDelete(joinUpdateWait); 00046 cancelAndDelete(secondStageWait); 00047 if (useDiscovery) cancelAndDelete(discoveryTimeout); 00048 if (routingTableMaintenanceInterval > 0) cancelAndDelete(repairTaskTimeout); 00049 00050 clearVectors(); 00051 }
void Pastry::changeState | ( | int | toState | ) | [protected, virtual] |
changes node state
toState | state to change to |
Reimplemented from BasePastry.
Definition at line 149 of file Pastry.cc.
Referenced by checkProxCache(), handleStateMessage(), handleTimerEvent(), and joinOverlay().
00150 { 00151 if (readyWait->isScheduled()) cancelEvent(readyWait); 00152 baseChangeState(toState); 00153 00154 switch (toState) { 00155 case INIT: 00156 cancelAllRpcs(); 00157 purgeVectors(); 00158 break; 00159 00160 case DISCOVERY: 00161 state = DISCOVERY; 00162 //nearNode = bootstrapNode; 00163 nearNodeRtt = MAXTIME; 00164 pingNode(bootstrapNode, discoveryTimeoutAmount, 0, 00165 NULL, "PING bootstrapNode in discovery mode", 00166 NULL, PING_DISCOVERY, UDP_TRANSPORT); //TODO 00167 sendRequest(bootstrapNode, PASTRY_REQ_LEAFSET); //TODO should be an RPC 00168 depth = -1; 00169 00170 // schedule join timer for discovery algorithm 00171 cancelEvent(joinTimeout); 00172 scheduleAt(simTime() + joinTimeoutAmount, joinTimeout); 00173 00174 break; 00175 00176 case JOINING_2: { 00177 joinHopCount = 0; 00178 PastryJoinMessage* msg = new PastryJoinMessage("JOIN-Request"); 00179 //TODO add timestamp to join msg 00180 msg->setPastryMsgType(PASTRY_MSG_JOIN); 00181 msg->setStatType(MAINTENANCE_STAT); 00182 msg->setSendStateTo(thisNode); 00183 msg->setBitLength(PASTRYJOIN_L(msg)); 00184 RECORD_STATS(joinSent++; joinBytesSent += msg->getByteLength()); 00185 std::vector<TransportAddress> sourceRoute; 00186 sourceRoute.push_back(nearNode); 00187 sendToKey(thisNode.getKey(), msg, 0/*1*/, sourceRoute); 00188 } 00189 break; 00190 00191 case READY: 00192 // determine list of all known nodes as notifyList 00193 notifyList.clear(); 00194 leafSet->dumpToVector(notifyList); 00195 routingTable->dumpToVector(notifyList); 00196 sort(notifyList.begin(), notifyList.end()); 00197 notifyList.erase(unique(notifyList.begin(), notifyList.end()), 00198 notifyList.end()); 00199 00200 // schedule update 00201 cancelEvent(joinUpdateWait); 00202 scheduleAt(simTime() + 0.0001, joinUpdateWait); 00203 00204 // schedule second stage 00205 if (secondStageInterval > 0) { 00206 cancelEvent(secondStageWait); 00207 scheduleAt(simTime() + secondStageInterval, secondStageWait); 00208 } 00209 00210 // schedule routing table maintenance task 00211 if (routingTableMaintenanceInterval > 0) { 00212 cancelEvent(repairTaskTimeout); 00213 scheduleAt(simTime() + routingTableMaintenanceInterval, repairTaskTimeout); 00214 } 00215 00216 break; 00217 } 00218 }
void Pastry::checkProxCache | ( | void | ) | [private, virtual] |
checks whether proxCache is complete, takes appropriate actions depending on the protocol state
Implements BasePastry.
Definition at line 765 of file Pastry.cc.
00766 { 00767 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00768 << " (" << thisNode.getKey().toString(16) << ")]" 00769 << endl; 00770 00771 // no cached STATE message? 00772 assert(stateCache.msg || !stateCache.prox); 00773 if (!stateCache.msg) return; 00774 00775 // no entries in stateCache.prox? 00776 if (stateCache.prox->pr_rt.empty() && 00777 stateCache.prox->pr_ls.empty() && 00778 stateCache.prox->pr_ns.empty()) 00779 throw new cRuntimeError("ERROR in Pastry: stateCache.prox empty!"); 00780 00781 /* 00782 //debug 00783 for (uint i = 0; i < stateCache.prox->pr_rt.size(); ++i) { 00784 if (stateCache.prox->pr_rt[i] == -3) 00785 EV << stateCache.msg->getRoutingTable(i).getAddress() << " "; 00786 } 00787 for (uint i = 0; i < stateCache.prox->pr_ls.size(); ++i) { 00788 if (stateCache.prox->pr_ls[i] == -3) 00789 EV << stateCache.msg->getLeafSet(i).getAddress() << " "; 00790 } 00791 for (uint i = 0; i < stateCache.prox->pr_ns.size(); ++i) { 00792 if (stateCache.prox->pr_ns[i] == -3) 00793 EV << stateCache.msg->getNeighborhoodSet(i).getAddress() << " "; 00794 } 00795 EV << endl; 00796 */ 00797 00798 // some entries not yet determined? 00799 if ((find(stateCache.prox->pr_rt.begin(), stateCache.prox->pr_rt.end(), 00800 PASTRY_PROX_PENDING) != stateCache.prox->pr_rt.end()) || 00801 (find(stateCache.prox->pr_ls.begin(), stateCache.prox->pr_ls.end(), 00802 PASTRY_PROX_PENDING) != stateCache.prox->pr_ls.end()) || 00803 (find(stateCache.prox->pr_ns.begin(), stateCache.prox->pr_ns.end(), 00804 PASTRY_PROX_PENDING) != stateCache.prox->pr_ns.end())) { 00805 //std::cout << "pending" << std::endl; 00806 return; 00807 } 00808 00809 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00810 << " (" << thisNode.getKey().toString(16) << ")]\n" 00811 << " all proximities for current STATE message from " 00812 << stateCache.msg->getSender().getAddress() 00813 << " collected!" 00814 << endl; 00815 /* 00816 //debug 00817 if (stateCache.prox != NULL) { 00818 std::vector<PastryStateMsgHandle>::iterator it; 00819 for (it = stReceived.begin(); it != stReceived.end(); ++it) { 00820 if (it->prox == NULL) { 00821 EV << ". " << endl; 00822 continue; 00823 } 00824 for (uint i = 0; i < it->prox->pr_rt.size(); ++i) { 00825 EV << it->prox->pr_rt[i] << " "; 00826 } 00827 for (uint i = 0; i < it->prox->pr_ls.size(); ++i) { 00828 EV << it->prox->pr_ls[i] << " "; 00829 } 00830 for (uint i = 0; i < it->prox->pr_ns.size(); ++i) { 00831 EV << it->prox->pr_ns[i] << " "; 00832 } 00833 EV << endl; 00834 } 00835 EV << endl; 00836 } else EV << "NULL" << endl; 00837 */ 00838 00839 simtime_t now = simTime(); 00840 00841 if (state == JOINING_2) { 00842 // save pointer to proximity vectors (it is NULL until now): 00843 stReceivedPos->prox = stateCache.prox; 00844 00845 // collected proximities for all STATE messages? 00846 if (++stReceivedPos == stReceived.end()) { 00847 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00848 << " (" << thisNode.getKey().toString(16) << ")]\n" 00849 << " proximities for all STATE messages collected!" 00850 << endl; 00851 stateCache.msg = NULL; 00852 stateCache.prox = NULL; 00853 if (debugOutput) { 00854 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00855 << " (" << thisNode.getKey().toString(16) << ")]\n" 00856 << " [JOIN] starting to build own state from " 00857 << stReceived.size() << " received state messages..." 00858 << endl; 00859 } 00860 if (mergeState()) { 00861 changeState(READY); 00862 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00863 << " (" << thisNode.getKey().toString(16) << ")]\n" 00864 << " changeState(READY) called" 00865 << endl; 00866 } else { 00867 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00868 << " (" << thisNode.getKey().toString(16) << ")]\n" 00869 << " Error initializing while joining! Restarting ..." 00870 << endl; 00871 joinOverlay(); 00872 } 00873 00874 } else { 00875 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00876 << " (" << thisNode.getKey().toString(16) << ")]\n" 00877 << " NOT all proximities for all STATE messages collected!" 00878 << endl; 00879 /* 00880 for (uint32_t i = 0; i < stReceived.size(); ++i) { 00881 EV << ((i == 0) ? " " : " | "); 00882 std::cout << ((i == 0) ? " " : " | "); 00883 if (stReceived[i].msg == stReceivedPos->msg) { 00884 EV << "*"; 00885 std::cout << "*"; 00886 } 00887 EV << stReceived[i].msg << " " << stReceived[i].prox; 00888 std::cout << stReceived[i].msg << " " << stReceived[i].prox; 00889 } 00890 EV << endl; 00891 std::cout << std::endl; 00892 */ 00893 00894 // process next state message in vector: 00895 if (stReceivedPos->msg == NULL) 00896 throw cRuntimeError("stReceivedPos->msg = NULL"); 00897 stateCache = *stReceivedPos; 00898 if (stateCache.msg == NULL) 00899 throw cRuntimeError("msg = NULL"); 00900 processState(); 00901 } 00902 } else { 00903 // state == READY 00904 if (stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) { 00905 // try to repair routingtable based on repair message: 00906 const TransportAddress& askRt = 00907 routingTable->repair(stateCache.msg, stateCache.prox); 00908 if (! askRt.isUnspecified()) { 00909 sendRequest(askRt, PASTRY_REQ_REPAIR); 00910 } 00911 00912 // while not really known, it's safe to assume that a repair 00913 // message changed our state: 00914 lastStateChange = now; 00915 } else { 00916 if (stateCache.outdatedUpdate) { 00917 // send another STATE message on outdated state update: 00918 updateCounter++; 00919 sendStateDelayed(stateCache.msg->getSender()); 00920 } else { 00921 // merge info in own state tables 00922 // except leafset (was already handled in handleStateMessage) 00923 if (neighborhoodSet->mergeState(stateCache.msg, stateCache.prox)) 00924 lastStateChange = now; 00925 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00926 << " (" << thisNode.getKey().toString(16) << ")]\n" 00927 << " Merging nodes into routing table" 00928 << endl; 00929 if (routingTable->mergeState(stateCache.msg, stateCache.prox)) { 00930 lastStateChange = now; 00931 EV << "[Pastry::checkProxCache() @ " << thisNode.getAddress() 00932 << " (" << thisNode.getKey().toString(16) << ")]\n" 00933 << " Merged nodes into routing table" 00934 << endl; 00935 } 00936 } 00937 } 00938 updateTooltip(); 00939 00940 endProcessingState(); 00941 } 00942 }
void Pastry::clearVectors | ( | ) | [private] |
Definition at line 53 of file Pastry.cc.
Referenced by purgeVectors(), and ~Pastry().
00054 { 00055 // purge pending state messages 00056 if (!stReceived.empty()) { 00057 for (std::vector<PastryStateMsgHandle>::iterator it = 00058 stReceived.begin(); it != stReceived.end(); it++) { 00059 // check whether one of the pointers is a duplicate of stateCache 00060 if (it->msg == stateCache.msg) stateCache.msg = NULL; 00061 if (it->prox == stateCache.prox) stateCache.prox = NULL; 00062 delete it->msg; 00063 delete it->prox; 00064 } 00065 stReceived.clear(); 00066 stReceivedPos = stReceived.end(); 00067 } 00068 00069 // purge notify list: 00070 notifyList.clear(); 00071 }
void Pastry::doJoinUpdate | ( | void | ) | [private] |
send updated state to all nodes when entering ready state
Definition at line 617 of file Pastry.cc.
Referenced by handleTimerEvent().
00618 { 00619 // send "update" state message to all nodes who sent us their state 00620 // during INIT, remove these from notifyList so they don't get our 00621 // state twice 00622 std::vector<TransportAddress>::iterator nListPos; 00623 if (!stReceived.empty()) { 00624 for (std::vector<PastryStateMsgHandle>::iterator it = 00625 stReceived.begin(); it != stReceived.end(); ++it) { 00626 simtime_t timestamp = it->msg->getTimestamp(); 00627 sendStateTables(it->msg->getSender(), PASTRY_STATE_UPDATE, 00628 ×tamp); 00629 nListPos = find(notifyList.begin(), notifyList.end(), 00630 it->msg->getSender()); 00631 if (nListPos != notifyList.end()) { 00632 notifyList.erase(nListPos); 00633 } 00634 delete it->msg; 00635 delete it->prox; 00636 } 00637 stReceived.clear(); 00638 } 00639 00640 // send a normal STATE message to all remaining known nodes 00641 for (std::vector<TransportAddress>::iterator it = 00642 notifyList.begin(); it != notifyList.end(); it++) { 00643 if (*it != thisNode) sendStateTables(*it, PASTRY_STATE_JOINUPDATE); 00644 } 00645 notifyList.clear(); 00646 00647 updateTooltip(); 00648 }
void Pastry::doRoutingTableMaintenance | ( | ) | [private] |
periodic routing table maintenance requests the corresponding routing table row from one node in each row
Definition at line 696 of file Pastry.cc.
Referenced by handleTimerEvent().
00697 { 00698 for (int i = 0; i < routingTable->getLastRow(); i++) { 00699 const TransportAddress& ask4row = routingTable->getRandomNode(i); 00700 00701 if ((!ask4row.isUnspecified()) && (ask4row != thisNode)) { 00702 PastryRoutingRowRequestMessage* msg = 00703 new PastryRoutingRowRequestMessage("ROWREQ"); 00704 msg->setPastryMsgType(PASTRY_MSG_ROWREQ); 00705 msg->setStatType(MAINTENANCE_STAT); 00706 msg->setSendStateTo(thisNode); 00707 msg->setRow(i + 1); 00708 msg->setBitLength(PASTRYRTREQ_L(msg)); 00709 00710 RECORD_STATS(routingTableReqSent++; 00711 routingTableReqBytesSent += msg->getByteLength()); 00712 00713 sendMessageToUDP(ask4row, msg); 00714 } else { 00715 EV << "[Pastry::doRoutingTableMaintenance() @ " 00716 << thisNode.getAddress() 00717 << " (" << thisNode.getKey().toString(16) << ")]\n" 00718 << " could not send Message to Node in Row" << i 00719 << endl; 00720 } 00721 } 00722 }
void Pastry::doSecondStage | ( | void | ) | [private] |
do the second stage of initialization as described in the paper
Definition at line 650 of file Pastry.cc.
Referenced by handleTimerEvent().
00651 { 00652 getParentModule()->getParentModule()->bubble("entering SECOND STAGE"); 00653 00654 // probe nodes in local state 00655 if (leafSet->isValid()) { 00656 PastryStateMessage* stateMsg = new PastryStateMessage("STATE"); 00657 stateMsg->setPastryMsgType(PASTRY_MSG_STATE); 00658 stateMsg->setStatType(MAINTENANCE_STAT); 00659 stateMsg->setPastryStateMsgType(PASTRY_STATE_STD); 00660 stateMsg->setSender(thisNode); 00661 routingTable->dumpToStateMessage(stateMsg); 00662 leafSet->dumpToStateMessage(stateMsg); 00663 neighborhoodSet->dumpToStateMessage(stateMsg); 00664 //stateMsg->setBitLength(PASTRYSTATE_L(stateMsg)); 00665 PastryStateMsgHandle handle(stateMsg); 00666 00667 if (!stateCache.msg) { 00668 stateCache = handle; 00669 processState(); 00670 } else { 00671 stateCacheQueue.push(handle); 00672 prePing(stateMsg); 00673 } 00674 } 00675 00676 // "second stage" for locality: 00677 notifyList.clear(); 00678 routingTable->dumpToVector(notifyList); 00679 neighborhoodSet->dumpToVector(notifyList); 00680 sort(notifyList.begin(), notifyList.end()); 00681 notifyList.erase(unique(notifyList.begin(), notifyList.end()), 00682 notifyList.end()); 00683 for (std::vector<TransportAddress>::iterator it = notifyList.begin(); 00684 it != notifyList.end(); it++) { 00685 if (*it == thisNode) continue; 00686 EV << "[Pastry::doSecondStage() @ " << thisNode.getAddress() 00687 << " (" << thisNode.getKey().toString(16) << ")]\n" 00688 << " second stage: requesting state from " << *it 00689 << endl; 00690 sendRequest(*it, PASTRY_REQ_STATE); 00691 } 00692 notifyList.clear(); 00693 }
void Pastry::endProcessingState | ( | void | ) | [private] |
Definition at line 944 of file Pastry.cc.
Referenced by checkProxCache(), and processState().
00945 { 00946 // if state message was not an update, send one back: 00947 if (stateCache.msg && 00948 stateCache.msg->getPastryStateMsgType() != PASTRY_STATE_UPDATE && 00949 (alwaysSendUpdate || lastStateChange == simTime()) && 00950 thisNode != stateCache.msg->getSender()) {//hack 00951 simtime_t timestamp = stateCache.msg->getTimestamp(); 00952 sendStateTables(stateCache.msg->getSender(), PASTRY_STATE_UPDATE, 00953 ×tamp); 00954 } 00955 00956 delete stateCache.msg; 00957 stateCache.msg = NULL; 00958 delete stateCache.prox; 00959 stateCache.prox = NULL; 00960 00961 // process next queued message: 00962 if (! stateCacheQueue.empty()) { 00963 stateCache = stateCacheQueue.front(); 00964 stateCacheQueue.pop(); 00965 processState(); 00966 } //TODO get rid of the delayed update messages... 00967 /*else { 00968 std::cout << thisNode.getAddress() << "\t" << simTime() 00969 << " all states processed (" 00970 << updateCounter << ")" << std::endl; 00971 updateCounter = 0; 00972 }*/ 00973 }
bool Pastry::handleFailedNode | ( | const TransportAddress & | failed | ) | [private, virtual] |
notifies leafset and routingtable of a failed node and sends out a repair request if possible
failed | the failed node |
Reimplemented from BaseOverlay.
Definition at line 725 of file Pastry.cc.
Referenced by handleUDPMessage(), and recursiveRoutingHook().
00726 { 00727 if (state != READY) { 00728 return false; 00729 } 00730 bool wasValid = leafSet->isValid(); 00731 00732 //std::cout << thisNode.getAddress() << " is handling failed node: " 00733 // << failed.getAddress() << std::endl; 00734 if (failed.isUnspecified()) 00735 opp_error("Pastry::handleFailedNode(): failed is unspecified!"); 00736 00737 const TransportAddress& lsAsk = leafSet->failedNode(failed); 00738 const TransportAddress& rtAsk = routingTable->failedNode(failed); 00739 neighborhoodSet->failedNode(failed); 00740 00741 if (! lsAsk.isUnspecified()) { 00742 newLeafs(); 00743 if (sendStateAtLeafsetRepair) sendRequest(lsAsk, PASTRY_REQ_REPAIR); 00744 else sendRequest(lsAsk, PASTRY_REQ_LEAFSET); 00745 } 00746 if (! rtAsk.isUnspecified() && 00747 (lsAsk.isUnspecified() || 00748 lsAsk != rtAsk)) sendRequest(rtAsk, PASTRY_REQ_REPAIR); 00749 00750 if (wasValid && lsAsk.isUnspecified() && (! leafSet->isValid())) { 00751 EV << "[Pastry::handleFailedNode() @ " << thisNode.getAddress() 00752 << " (" << thisNode.getKey().toString(16) << ")]\n" 00753 << " lost connection to the network, trying to re-join." 00754 << endl; 00755 //std::cout << thisNode.getAddress() 00756 // << " Pastry: lost connection to the network, trying to re-join." 00757 // << std::endl; 00758 join(); 00759 return false; 00760 } 00761 00762 return true; 00763 }
void Pastry::handleStateMessage | ( | PastryStateMessage * | msg | ) | [virtual] |
processes state messages, merging with own state tables
msg | the pastry state message |
Implements BasePastry.
Definition at line 1071 of file Pastry.cc.
Referenced by handleUDPMessage().
01072 { 01073 if (debugOutput) { 01074 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01075 << " (" << thisNode.getKey().toString(16) << ")]\n" 01076 << " new STATE message to process " 01077 << static_cast<void*>(msg) << " in state " << 01078 ((state == READY)?"READY":((state == JOINING_2)?"JOIN":"INIT")) 01079 << endl; 01080 if (state == JOINING_2) { 01081 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01082 << " (" << thisNode.getKey().toString(16) << ")]\n" 01083 << " *** own joinHopCount: " << joinHopCount << endl 01084 << " *** already received: " << stReceived.size() << endl 01085 << " *** last-hop flag: " 01086 << (msg->getLastHop() ? "true" : "false") << endl 01087 << " *** msg joinHopCount: " 01088 << msg->getJoinHopCount() << endl; 01089 } 01090 } 01091 if (state == INIT || state == DISCOVERY) { 01092 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01093 << " (" << thisNode.getKey().toString(16) << ")]\n" 01094 << " can't handle state messages until at least reaching JOIN state." 01095 << endl; 01096 delete msg; 01097 return; 01098 } 01099 01100 PastryStateMsgHandle handle(msg); 01101 01102 // in JOIN state, store all received state Messages, need them later: 01103 if (state == JOINING_2) { 01104 //std::cout << simTime() << " " << thisNode.getAddress() << " " 01105 // << msg->getJoinHopCount() 01106 // << (msg->getLastHop() ? " *" : "") << std::endl; 01107 01108 if (msg->getPastryStateMsgType() != PASTRY_STATE_JOIN) { 01109 delete msg; 01110 return; 01111 } 01112 01113 if (joinHopCount && stReceived.size() == joinHopCount) { 01114 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01115 << " (" << thisNode.getKey().toString(16) << ")]\n" 01116 << " Warning: dropping state message received after " 01117 << "all needed state messages were collected in JOIN state." 01118 << endl; 01119 delete msg; 01120 return; 01121 } 01122 01123 stReceived.push_back(handle); 01124 if (pingBeforeSecondStage && proximityNeighborSelection) prePing(msg); 01125 01126 if (msg->getLastHop()) { 01127 if (joinTimeout->isScheduled()) { 01128 //std::cout << simTime() << " " << thisNode.getAddress() 01129 //<< " cancelEvent(joinTimeout), received:" 01130 //<< stReceived.size() << ", hopcount:" << joinHopCount << std::endl; 01131 cancelEvent(joinTimeout); 01132 } 01133 /*if (msg->getSender().getKey() == thisNode.getKey()) { 01134 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01135 << " (" << thisNode.getKey().toString(16) << ")]\n" 01136 << " Error: OverlayKey already in use, restarting!" 01137 << endl; 01138 //std::cout << "Pastry: Error: OverlayKey already in use, restarting!" 01139 // << std::endl; 01140 joinOverlay(); 01141 return; 01142 }*/ 01143 01144 if (joinHopCount) { 01145 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01146 << " (" << thisNode.getKey().toString(16) << ")]\n" 01147 << " Error: received a second `last' state message! Restarting ..." 01148 << endl; 01149 //std::cout << thisNode.getAddress() << "Pastry: Error: received a second `last' state message! " 01150 // "Restarting ..." << std::endl; 01151 joinOverlay(); 01152 return; 01153 } 01154 01155 joinHopCount = msg->getJoinHopCount(); 01156 //std::cout << stReceived.size() << " " << joinHopCount << std::endl; 01157 if (stReceived.size() < joinHopCount) { 01158 // some states still missing: 01159 cancelEvent(readyWait); 01160 scheduleAt(simTime() + readyWaitAmount, readyWait); 01161 //std::cout << simTime() << " " << thisNode.getAddress() << " readyWait scheduled!" << std::endl; 01162 } 01163 } 01164 01165 if (joinHopCount) { 01166 if (stReceived.size() > joinHopCount) { 01167 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01168 << " (" << thisNode.getKey().toString(16) << ")]\n" 01169 << " Error: too many state messages received in JOIN state! (" 01170 << stReceived.size() << " > " << joinHopCount << ") Restarting ..." 01171 << endl; 01172 //std::cout << " failed!" << std::endl; 01173 joinOverlay(); 01174 return; 01175 } 01176 if (stReceived.size() == joinHopCount) { 01177 // all state messages are here, sort by hopcount: 01178 sort(stReceived.begin(), stReceived.end(), 01179 stateMsgIsSmaller); 01180 01181 // start pinging the nodes found in the first state message: 01182 stReceivedPos = stReceived.begin(); 01183 stateCache = *stReceivedPos; 01184 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01185 << " (" << thisNode.getKey().toString(16) << ")]\n" 01186 << " have all STATE messages, now pinging nodes." 01187 << endl; 01188 if (pingBeforeSecondStage && proximityNeighborSelection) { 01189 pingNodes(); 01190 } else { 01191 mergeState(); // JOINING / stateCache 01192 //endProcessingState(); //no way 01193 stateCache.msg = NULL; 01194 changeState(READY); 01195 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01196 << " (" << thisNode.getKey().toString(16) << ")]\n" 01197 << " changeState(READY) called" 01198 << endl; 01199 } 01200 01201 // cancel timeout: 01202 if (readyWait->isScheduled()) cancelEvent(readyWait); 01203 } else { 01204 //TODO occasionally, here we got a wrong hop count in 01205 // iterative mode due to more than one it. lookup during join 01206 // procedure 01207 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01208 << " (" << thisNode.getKey().toString(16) << ")]\n" 01209 << " Still need some STATE messages." 01210 << endl; 01211 } 01212 01213 } 01214 return; 01215 } 01216 01217 if (debugOutput) { 01218 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01219 << " (" << thisNode.getKey().toString(16) << ")]\n" 01220 << " handling STATE message" 01221 << endl; 01222 EV << " type: " << ((msg->getPastryStateMsgType() 01223 == PASTRY_STATE_UPDATE) ? "update" 01224 :"standard") 01225 << endl; 01226 if (msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE) { 01227 EV << " msg timestamp: " << 01228 msg->getTimestamp() << endl; 01229 EV << " last state change: " << 01230 lastStateChange << endl; 01231 } 01232 } 01233 01234 if (((msg->getPastryStateMsgType() == PASTRY_STATE_UPDATE)) 01235 && (msg->getTimestamp() <= lastStateChange)) { 01236 // if we received an update based on our outdated state, 01237 // mark handle for retrying later: 01238 EV << "[Pastry::handleStateMessage() @ " << thisNode.getAddress() 01239 << " (" << thisNode.getKey().toString(16) << ")]\n" 01240 << " outdated state from " << msg->getSender() 01241 << endl; 01242 handle.outdatedUpdate = true; 01243 } 01244 01245 // determine aliveTable to prevent leafSet from merging nodes that are 01246 // known to be dead: 01247 determineAliveTable(msg); 01248 01249 if (msg->getPastryStateMsgType() == PASTRY_STATE_REPAIR) { 01250 // try to repair leafset based on repair message right now 01251 const TransportAddress& askLs = leafSet->repair(msg, &aliveTable); 01252 if (! askLs.isUnspecified()) { 01253 sendRequest(askLs, PASTRY_REQ_REPAIR); 01254 } 01255 01256 // while not really known, it's safe to assume that a repair 01257 // message changed our state: 01258 lastStateChange = simTime(); 01259 newLeafs(); 01260 } else if (leafSet->mergeState(msg, &aliveTable)) { 01261 // merged state into leafset right now 01262 lastStateChange = simTime(); 01263 newLeafs(); 01264 updateTooltip(); 01265 } 01266 // in READY state, only ping nodes to get proximity metric: 01267 if (!stateCache.msg) { 01268 // no state message is processed right now, start immediately: 01269 stateCache = handle; 01270 processState(); 01271 } else { 01272 if (proximityNeighborSelection && (pingBeforeSecondStage || 01273 msg->getPastryStateMsgType() == PASTRY_STATE_STD)) { 01274 // enqueue message for later processing: 01275 stateCacheQueue.push(handle); 01276 prePing(msg); 01277 } else { 01278 bool temp = true; 01279 if (!neighborhoodSet->mergeState(msg, NULL)) { 01280 temp = false; 01281 } 01282 if (!leafSet->mergeState(msg, NULL)) { 01283 temp = false; 01284 } else { 01285 newLeafs(); 01286 } 01287 if (!routingTable->mergeState(msg, NULL)) { 01288 temp = false; 01289 } 01290 if (temp) lastStateChange = simTime(); 01291 delete msg; 01292 } 01293 } 01294 }
void Pastry::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Reimplemented from BaseRpc.
Definition at line 243 of file Pastry.cc.
00244 { 00245 00246 if (msg == joinTimeout) { 00247 EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress() 00248 << " (" << thisNode.getKey().toString(16) << ")]\n" 00249 << " timeout expired, restarting..." 00250 << endl; 00251 join(); 00252 } else if (msg == readyWait) { 00253 if (partialJoinPath) { 00254 RECORD_STATS(joinPartial++); 00255 sort(stReceived.begin(), stReceived.end(), stateMsgIsSmaller); 00256 00257 // start pinging the nodes found in the first state message: 00258 stReceivedPos = stReceived.begin(); 00259 stateCache = *stReceivedPos; 00260 EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress() 00261 << " (" << thisNode.getKey().toString(16) << ")]\n" 00262 << " joining despite some missing STATE messages." 00263 << endl; 00264 processState(); 00265 } else { 00266 EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress() 00267 << " (" << thisNode.getKey().toString(16) << ")]\n" 00268 << " timeout waiting for missing state messages" 00269 << " in JOIN state, restarting..." 00270 << endl; 00271 joinOverlay(); 00272 } 00273 } else if (msg == joinUpdateWait) { 00274 EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress() 00275 << " (" << thisNode.getKey().toString(16) << ")]\n" 00276 << " sending state updates to all nodes." 00277 << endl; 00278 doJoinUpdate(); 00279 } else if (msg == secondStageWait) { 00280 EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress() 00281 << " (" << thisNode.getKey().toString(16) << ")]\n" 00282 << " sending STATE requests to all nodes in" 00283 << " second stage of initialization." 00284 << endl; 00285 doSecondStage(); 00286 } else if (msg->isName("sendStateWait")) { 00287 PastrySendState* sendStateMsg = check_and_cast<PastrySendState*>(msg); 00288 00289 std::vector<PastrySendState*>::iterator pos = 00290 std::find(sendStateWait.begin(), sendStateWait.end(), 00291 sendStateMsg); 00292 if (pos != sendStateWait.end()) sendStateWait.erase(pos); 00293 00294 sendStateTables(sendStateMsg->getDest()); 00295 delete sendStateMsg; 00296 } else if (msg == discoveryTimeout) { 00297 if ((depth == 0) && (nearNodeImproved)) { 00298 depth++; //repeat last step if closer node was found 00299 } 00300 if ((depth == 0) || (pingedNodes < 1)) { 00301 changeState(JOINING_2); 00302 } else { 00303 PastryRoutingRowRequestMessage* msg = 00304 new PastryRoutingRowRequestMessage("ROWREQ"); 00305 msg->setPastryMsgType(PASTRY_MSG_ROWREQ); 00306 msg->setStatType(MAINTENANCE_STAT); 00307 msg->setSendStateTo(thisNode); 00308 msg->setRow(depth); 00309 msg->setBitLength(PASTRYRTREQ_L(msg)); 00310 RECORD_STATS(routingTableReqSent++; 00311 routingTableReqBytesSent += msg->getByteLength()); 00312 sendMessageToUDP(nearNode, msg); 00313 } 00314 } else if (msg == repairTaskTimeout) { 00315 EV << "[Pastry::handleTimerEvent() @ " << thisNode.getAddress() 00316 << " (" << thisNode.getKey().toString(16) << ")]\n" 00317 << " starting routing table maintenance" 00318 << endl; 00319 doRoutingTableMaintenance(); 00320 scheduleAt(simTime() + routingTableMaintenanceInterval, 00321 repairTaskTimeout); 00322 } 00323 }
void Pastry::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Processes messages from underlay.
msg | Message from UDP |
Reimplemented from BaseOverlay.
Definition at line 325 of file Pastry.cc.
00326 { 00327 PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg); 00328 uint32_t type = pastryMsg->getPastryMsgType(); 00329 00330 if (debugOutput) { 00331 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00332 << " (" << thisNode.getKey().toString(16) << ")]\n" 00333 << " incoming message of type "; 00334 switch(type) { 00335 case PASTRY_MSG_STD: 00336 EV << "PASTRY_MSG_STD"; 00337 break; 00338 case PASTRY_MSG_JOIN: 00339 EV << "PASTRY_MSG_JOIN"; 00340 break; 00341 case PASTRY_MSG_STATE: 00342 EV << "PASTRY_MSG_STATE"; 00343 break; 00344 case PASTRY_MSG_LEAFSET: 00345 EV << "PASTRY_MSG_LEAFSET"; 00346 break; 00347 case PASTRY_MSG_ROWREQ: 00348 EV << "PASTRY_MSG_ROWREQ"; 00349 break; 00350 case PASTRY_MSG_RROW: 00351 EV << "PASTRY_MSG_RROW"; 00352 break; 00353 case PASTRY_MSG_REQ: 00354 EV << "PASTRY_MSG_REQ"; 00355 break; 00356 default: 00357 EV << "UNKNOWN (" << type <<")"; 00358 break; 00359 } 00360 EV << endl; 00361 } 00362 00363 switch (type) { 00364 case PASTRY_MSG_STD: 00365 opp_error("Pastry received PastryMessage of unknown type!"); 00366 break; 00367 00368 case PASTRY_MSG_JOIN: { 00369 PastryJoinMessage* jmsg = 00370 check_and_cast<PastryJoinMessage*>(pastryMsg); 00371 RECORD_STATS(joinReceived++; joinBytesReceived += 00372 jmsg->getByteLength()); 00373 if (state != READY) { 00374 if (jmsg->getSendStateTo() == thisNode) { 00375 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00376 << " (" << thisNode.getKey().toString(16) << ")]\n" 00377 << " PastryJoinMessage received by originator!" 00378 << endl; 00379 } else { 00380 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00381 << " (" << thisNode.getKey().toString(16) << ")]\n" 00382 << " received join message before reaching " 00383 << "READY state, dropping message!" 00384 << endl; 00385 } 00386 } 00387 else if (jmsg->getSendStateTo() == thisNode) { 00388 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00389 << " (" << thisNode.getKey().toString(16) << ")]\n" 00390 << " PastryJoinMessage gets dropped because it is " 00391 << "outdated and has been received by originator!" 00392 << endl; 00393 } else { 00394 OverlayCtrlInfo* overlayCtrlInfo 00395 = check_and_cast<OverlayCtrlInfo*>(jmsg->getControlInfo()); 00396 00397 uint32_t joinHopCount = overlayCtrlInfo->getHopCount(); 00398 if ((joinHopCount > 1) && 00399 ((defaultRoutingType == ITERATIVE_ROUTING) || 00400 (defaultRoutingType == EXHAUSTIVE_ITERATIVE_ROUTING))) 00401 joinHopCount--; 00402 00403 // remove node from state if it is rejoining 00404 handleFailedNode(jmsg->getSendStateTo()); 00405 00406 sendStateTables(jmsg->getSendStateTo(), 00407 (minimalJoinState ? 00408 PASTRY_STATE_MINJOIN : PASTRY_STATE_JOIN), 00409 joinHopCount, true); 00410 } 00411 00412 delete jmsg; 00413 } 00414 break; 00415 00416 case PASTRY_MSG_LEAFSET: { 00417 PastryLeafsetMessage* lmsg = 00418 check_and_cast<PastryLeafsetMessage*>(pastryMsg); 00419 RECORD_STATS(leafsetReceived++; leafsetBytesReceived += 00420 lmsg->getByteLength()); 00421 00422 if (state == DISCOVERY) { 00423 uint32_t lsSize = lmsg->getLeafSetArraySize(); 00424 const NodeHandle* node; 00425 pingedNodes = 0; 00426 00427 for (uint32_t i = 0; i < lsSize; i++) { 00428 node = &(lmsg->getLeafSet(i)); 00429 // unspecified nodes not considered 00430 if ( !(node->isUnspecified()) ) { 00431 pingNode(*node, discoveryTimeoutAmount, 0, 00432 NULL, "PING received leafs for nearest node", 00433 NULL, -1, UDP_TRANSPORT);//TODO 00434 pingedNodes++; 00435 } 00436 } 00437 00438 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00439 << " (" << thisNode.getKey().toString(16) << ")]\n" 00440 << " received leafset, waiting for pings" 00441 << endl; 00442 00443 if (discoveryTimeout->isScheduled()) cancelEvent(discoveryTimeout); 00444 scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout); 00445 delete lmsg; 00446 } else if (state == READY) { 00447 handleLeafsetMessage(lmsg, false); 00448 } else { 00449 delete lmsg; 00450 } 00451 } 00452 break; 00453 00454 case PASTRY_MSG_ROWREQ: { 00455 PastryRoutingRowRequestMessage* rtrmsg = 00456 check_and_cast<PastryRoutingRowRequestMessage*>(pastryMsg); 00457 RECORD_STATS(routingTableReqReceived++; routingTableReqBytesReceived += 00458 rtrmsg->getByteLength()); 00459 if (state == READY) 00460 if (rtrmsg->getRow() == -1) 00461 sendRoutingRow(rtrmsg->getSendStateTo(), routingTable->getLastRow()); 00462 else if (rtrmsg->getRow() > routingTable->getLastRow()) 00463 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00464 << " (" << thisNode.getKey().toString(16) << ")]\n" 00465 << " received request for nonexistent routing" 00466 << "table row, dropping message!" 00467 << endl; 00468 else sendRoutingRow(rtrmsg->getSendStateTo(), rtrmsg->getRow()); 00469 else 00470 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00471 << " (" << thisNode.getKey().toString(16) << ")]\n" 00472 << " received routing table request before reaching " 00473 << "READY state, dropping message!" 00474 << endl; 00475 delete rtrmsg; 00476 } 00477 break; 00478 00479 case PASTRY_MSG_RROW: { 00480 PastryRoutingRowMessage* rtmsg = 00481 check_and_cast<PastryRoutingRowMessage*>(pastryMsg); 00482 RECORD_STATS(routingTableReceived++; routingTableBytesReceived += 00483 rtmsg->getByteLength()); 00484 00485 if (state == DISCOVERY) { 00486 uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize(); 00487 const NodeHandle* node; 00488 if (depth == -1) { 00489 depth = rtmsg->getRow(); 00490 } 00491 pingedNodes = 0; 00492 nearNodeImproved = false; 00493 00494 if (depth > 0) { 00495 for (uint32_t i = 0; i < nodesPerRow; i++) { 00496 node = &(rtmsg->getRoutingTable(i)); 00497 // unspecified nodes not considered 00498 if ( !(node->isUnspecified()) ) { 00499 // we look for best connection here, so Timeout is short and there are no retries 00500 pingNode(*node, discoveryTimeoutAmount, 0, NULL, 00501 "PING received routing table for nearest node", 00502 NULL, -1, UDP_TRANSPORT); //TODO 00503 pingedNodes++; 00504 } 00505 } 00506 depth--; 00507 } 00508 EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress() 00509 << " (" << thisNode.getKey().toString(16) << ")]\n" 00510 << " received routing table, waiting for pings" 00511 << endl; 00512 if (discoveryTimeout->isScheduled()) { 00513 cancelEvent(discoveryTimeout); 00514 } 00515 scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout); 00516 } 00517 00518 else if (state == READY) { 00519 00520 uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize(); 00521 PastryStateMessage* stateMsg; 00522 00523 stateMsg = new PastryStateMessage("STATE"); 00524 stateMsg->setTimestamp(rtmsg->getTimestamp()); 00525 stateMsg->setPastryMsgType(PASTRY_MSG_STATE); 00526 stateMsg->setStatType(MAINTENANCE_STAT); 00527 stateMsg->setSender(rtmsg->getSender()); 00528 stateMsg->setLeafSetArraySize(0); 00529 stateMsg->setNeighborhoodSetArraySize(0); 00530 stateMsg->setRoutingTableArraySize(nodesPerRow); 00531 00532 for (uint32_t i = 0; i < nodesPerRow; i++) { 00533 stateMsg->setRoutingTable(i, rtmsg->getRoutingTable(i)); 00534 } 00535 00536 handleStateMessage(stateMsg); 00537 } 00538 00539 delete rtmsg; 00540 } 00541 break; 00542 00543 case PASTRY_MSG_REQ: { 00544 PastryRequestMessage* lrmsg = 00545 check_and_cast<PastryRequestMessage*>(pastryMsg); 00546 handleRequestMessage(lrmsg); 00547 } 00548 break; 00549 00550 case PASTRY_MSG_STATE: { 00551 PastryStateMessage* stateMsg = 00552 check_and_cast<PastryStateMessage*>(msg); 00553 RECORD_STATS(stateReceived++; stateBytesReceived += 00554 stateMsg->getByteLength()); 00555 handleStateMessage(stateMsg); 00556 } 00557 break; 00558 } 00559 }
void Pastry::initializeOverlay | ( | int | stage | ) | [virtual] |
Initializes derived-class-attributes.
Initializes derived-class-attributes, called by BaseOverlay::initialize(). By default this method is called once. If more stages are needed one can overload numInitStages() and add more stages.
stage | the init stage |
Reimplemented from BaseOverlay.
Definition at line 80 of file Pastry.cc.
00081 { 00082 if ( stage != MIN_STAGE_OVERLAY ) 00083 return; 00084 00085 // Pastry provides KBR services 00086 kbr = true; 00087 00088 baseInit(); 00089 00090 useDiscovery = par("useDiscovery"); 00091 pingBeforeSecondStage = par("pingBeforeSecondStage"); 00092 secondStageInterval = par("secondStageWait"); 00093 discoveryTimeoutAmount = par("discoveryTimeoutAmount"); 00094 routingTableMaintenanceInterval = par("routingTableMaintenanceInterval"); 00095 sendStateAtLeafsetRepair = par("sendStateAtLeafsetRepair"); 00096 partialJoinPath = par("partialJoinPath"); 00097 readyWaitAmount = par("readyWait"); 00098 minimalJoinState = par("minimalJoinState"); 00099 00100 overrideOldPastry = par("overrideOldPastry"); 00101 overrideNewPastry = par("overrideNewPastry"); 00102 00103 if (overrideOldPastry) { 00104 //useSecondStage = true; 00105 //secondStageInterval = ???; 00106 useDiscovery = false; 00107 sendStateAtLeafsetRepair = true; 00108 routingTableMaintenanceInterval = 0; 00109 } 00110 00111 if (overrideNewPastry) { 00112 //useSecondStage = false; 00113 secondStageInterval = 0; 00114 useDiscovery = true; 00115 discoveryTimeoutAmount = 0.4; 00116 routingTableMaintenanceInterval = 60; 00117 sendStateAtLeafsetRepair = false; 00118 } 00119 00120 joinTimeout = new cMessage("joinTimeout"); 00121 readyWait = new cMessage("readyWait"); 00122 secondStageWait = new cMessage("secondStageWait"); 00123 joinUpdateWait = new cMessage("joinUpdateWait"); 00124 00125 discoveryTimeout = 00126 (useDiscovery ? new cMessage("discoveryTimeout") : NULL); 00127 repairTaskTimeout = 00128 ((routingTableMaintenanceInterval > 0) ? 00129 new cMessage("repairTaskTimeout") : NULL); 00130 00131 updateCounter = 0; 00132 }
void Pastry::iterativeJoinHook | ( | BaseOverlayMessage * | msg, | |
bool | incrHopCount | |||
) | [protected, virtual] |
Reimplemented from BasePastry.
Definition at line 591 of file Pastry.cc.
00592 { 00593 PastryFindNodeExtData* findNodeExt = NULL; 00594 if (msg && msg->hasObject("findNodeExt")) { 00595 findNodeExt = 00596 check_and_cast<PastryFindNodeExtData*>(msg-> 00597 getObject("findNodeExt")); 00598 } 00599 // Send state tables on any JOIN message we see: 00600 if (findNodeExt) { 00601 const TransportAddress& stateRecipient = 00602 findNodeExt->getSendStateTo(); 00603 if (!stateRecipient.isUnspecified()) { 00604 RECORD_STATS(joinSeen++); 00605 sendStateTables(stateRecipient, 00606 minimalJoinState ? 00607 PASTRY_STATE_MINJOIN : PASTRY_STATE_JOIN, 00608 findNodeExt->getJoinHopCount(), false); 00609 } 00610 if (incrHopCount) { 00611 findNodeExt->setJoinHopCount(findNodeExt->getJoinHopCount() + 1); 00612 } 00613 } 00614 }
void Pastry::joinOverlay | ( | ) | [private, virtual] |
Join the overlay with a given nodeID in thisNode.key.
Join the overlay with a given nodeID in thisNode.key. This method may be called by an application to join the overlay with a specific nodeID. It is also called if the node's IP address changes.
Reimplemented from BaseOverlay.
Definition at line 134 of file Pastry.cc.
Referenced by checkProxCache(), handleStateMessage(), and handleTimerEvent().
00135 { 00136 changeState(INIT); 00137 00138 if (bootstrapNode.isUnspecified()) { 00139 // no existing pastry network -> first node of a new one 00140 changeState(READY); 00141 } else { 00142 // join existing pastry network 00143 nearNode = bootstrapNode; 00144 if (useDiscovery) changeState(DISCOVERY); 00145 else changeState(JOINING_2); 00146 } 00147 }
bool Pastry::mergeState | ( | void | ) | [private] |
Definition at line 975 of file Pastry.cc.
Referenced by checkProxCache(), handleStateMessage(), and processState().
00976 { 00977 bool ret = true; 00978 00979 if (state == JOINING_2) { 00980 // building initial state 00981 if (debugOutput) { 00982 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 00983 << " (" << thisNode.getKey().toString(16) << ")]\n" 00984 << " [JOIN] starting to build own state from " 00985 << stReceived.size() << " received state messages..." 00986 << endl; 00987 } 00988 if (stateCache.msg && 00989 stateCache.msg->getNeighborhoodSetArraySize() > 0) { 00990 if (debugOutput) { 00991 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 00992 << " (" << thisNode.getKey().toString(16) << ")]\n" 00993 << " [JOIN] initializing NeighborhoodSet from " 00994 << stReceived.front().msg->getJoinHopCount() << ". hop" 00995 << endl; 00996 } 00997 if (!neighborhoodSet->mergeState(stReceived.front().msg, 00998 stReceived.front().prox )) { 00999 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 01000 << " (" << thisNode.getKey().toString(16) << ")]\n" 01001 << " Error initializing own neighborhoodSet" 01002 << " while joining! Restarting ..." 01003 << endl; 01004 ret = false; 01005 } 01006 } 01007 if (debugOutput) { 01008 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 01009 << " (" << thisNode.getKey().toString(16) << ")]\n" 01010 << " [JOIN] initializing LeafSet from " 01011 << stReceived.back().msg->getJoinHopCount() << ". hop" 01012 << endl; 01013 } 01014 01015 //assert(!stateCache.msg || stateCache.msg->getLeafSetArraySize() > 0); 01016 01017 if (!leafSet->mergeState(stReceived.back().msg, 01018 stReceived.back().prox )) { 01019 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 01020 << " (" << thisNode.getKey().toString(16) << ")]\n" 01021 << " Error initializing own leafSet while joining!" 01022 << " Restarting ..." 01023 << endl; 01024 //std::cout << "Pastry: Error initializing own leafSet while " 01025 // "joining! Restarting ..." << std::endl; 01026 ret = false; 01027 } else { 01028 newLeafs(); 01029 } 01030 if (debugOutput) { 01031 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 01032 << " (" << thisNode.getKey().toString(16) << ")]\n" 01033 << " [JOIN] initializing RoutingTable from all hops" 01034 << endl; 01035 } 01036 01037 assert(!stateCache.msg || 01038 stateCache.msg->getRoutingTableArraySize() > 0); 01039 01040 if (!routingTable->initStateFromHandleVector(stReceived)) { 01041 EV << "[Pastry::mergeState() @ " << thisNode.getAddress() 01042 << " (" << thisNode.getKey().toString(16) << ")]\n" 01043 << " Error initializing own routingTable while joining!" 01044 << " Restarting ..." 01045 << endl; 01046 //std::cout << "Pastry: Error initializing own routingTable " 01047 // "while joining! Restarting ..." << std::endl; 01048 01049 ret = false; 01050 } 01051 } else if (state == READY) { 01052 // merging single state (stateCache.msg) 01053 if ((stateCache.msg->getNeighborhoodSetArraySize() > 0) && 01054 (!neighborhoodSet->mergeState(stateCache.msg, NULL))) { 01055 ret = false; 01056 } 01057 if (!leafSet->mergeState(stateCache.msg, NULL)) { 01058 ret = false; 01059 } else { 01060 newLeafs(); 01061 } 01062 if (!routingTable->mergeState(stateCache.msg, NULL)) { 01063 ret = false; 01064 } 01065 } 01066 01067 if (ret) lastStateChange = simTime(); 01068 return ret; 01069 }
void Pastry::pingResponse | ( | PingResponse * | pingResponse, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [virtual] |
Reimplemented from BasePastry.
Definition at line 221 of file Pastry.cc.
00224 { 00225 if (state == DISCOVERY) { 00226 EV << "[Pastry::pingResponse() @ " << thisNode.getAddress() 00227 << " (" << thisNode.getKey().toString(16) << ")]\n" 00228 << " Pong (or Ping-context from NeighborCache) received (from " 00229 << pingResponse->getSrcNode().getAddress() << ") in DISCOVERY mode" 00230 << endl; 00231 00232 if (nearNodeRtt > rtt) { 00233 nearNode = pingResponse->getSrcNode(); 00234 nearNodeRtt = rtt; 00235 nearNodeImproved = true; 00236 } 00237 } else { 00238 BasePastry::pingResponse(pingResponse, context, rpcId, rtt); 00239 } 00240 }
void Pastry::processState | ( | void | ) | [private] |
Definition at line 1296 of file Pastry.cc.
Referenced by checkProxCache(), doSecondStage(), endProcessingState(), handleStateMessage(), and handleTimerEvent().
01297 { 01298 if (proximityNeighborSelection && (pingBeforeSecondStage || 01299 stateCache.msg->getPastryStateMsgType() == PASTRY_STATE_STD)) { 01300 pingNodes(); 01301 } else { 01302 mergeState(); 01303 endProcessingState(); 01304 } 01305 }
void Pastry::purgeVectors | ( | void | ) | [protected, virtual] |
delete all information/messages caching vectors, used for restarting overlay or finish()
Reimplemented from BasePastry.
Definition at line 73 of file Pastry.cc.
Referenced by changeState().
00074 { 00075 clearVectors(); 00076 00077 BasePastry::purgeVectors(); 00078 }
bool Pastry::recursiveRoutingHook | ( | const TransportAddress & | dest, | |
BaseRouteMessage * | msg | |||
) | [protected, virtual] |
Hook for forwarded message in recursive lookup mode.
This hook is called just before a message is forwarded to a next hop or if the message is at its destination just before it is sent to the app. Default implementation just returns true. This hook can for example be used to detect failed nodes and call handleFailedNode() before the actual forwarding takes place.
dest | destination node | |
msg | message to send |
Reimplemented from BaseOverlay.
Definition at line 562 of file Pastry.cc.
00564 { 00565 if (dest == thisNode) { 00566 return true; 00567 } 00568 00569 PastryMessage* pmsg = 00570 dynamic_cast<PastryMessage*>(msg->getEncapsulatedPacket()); 00571 00572 if (pmsg && pmsg->getPastryMsgType() == PASTRY_MSG_JOIN) { 00573 PastryJoinMessage* jmsg = static_cast<PastryJoinMessage*>(pmsg); 00574 if (jmsg->getSendStateTo() != thisNode) { 00575 RECORD_STATS(joinSeen++; joinBytesSeen += jmsg->getByteLength()); 00576 // remove node from state if it is rejoining 00577 handleFailedNode(jmsg->getSendStateTo()); 00578 00579 sendStateTables(jmsg->getSendStateTo(), 00580 minimalJoinState ? 00581 PASTRY_STATE_MINJOIN : PASTRY_STATE_JOIN, 00582 check_and_cast<OverlayCtrlInfo*>(msg->getControlInfo()) 00583 ->getHopCount(), false); 00584 } 00585 } 00586 00587 // forward now: 00588 return true; 00589 }
int Pastry::depth [private] |
Definition at line 110 of file Pastry.h.
Referenced by changeState(), handleTimerEvent(), and handleUDPMessage().
cMessage* Pastry::discoveryTimeout [private] |
Definition at line 125 of file Pastry.h.
Referenced by handleTimerEvent(), handleUDPMessage(), initializeOverlay(), and ~Pastry().
simtime_t Pastry::discoveryTimeoutAmount [private] |
Definition at line 107 of file Pastry.h.
Referenced by changeState(), handleUDPMessage(), and initializeOverlay().
bool Pastry::minimalJoinState [private] |
Definition at line 114 of file Pastry.h.
Referenced by handleUDPMessage(), initializeOverlay(), iterativeJoinHook(), and recursiveRoutingHook().
std::vector<TransportAddress> Pastry::notifyList [protected] |
List of nodes to notify after join.
Definition at line 99 of file Pastry.h.
Referenced by changeState(), clearVectors(), doJoinUpdate(), and doSecondStage().
bool Pastry::overrideNewPastry [private] |
Definition at line 121 of file Pastry.h.
Referenced by initializeOverlay().
bool Pastry::overrideOldPastry [private] |
Definition at line 120 of file Pastry.h.
Referenced by initializeOverlay().
bool Pastry::partialJoinPath [private] |
Definition at line 108 of file Pastry.h.
Referenced by handleTimerEvent(), and initializeOverlay().
bool Pastry::pingBeforeSecondStage [private] |
Definition at line 118 of file Pastry.h.
Referenced by handleStateMessage(), initializeOverlay(), and processState().
cMessage* Pastry::repairTaskTimeout [private] |
Definition at line 126 of file Pastry.h.
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Pastry().
cMessage* Pastry::ringCheck [private] |
simtime_t Pastry::routingTableMaintenanceInterval [private] |
Definition at line 106 of file Pastry.h.
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Pastry().
simtime_t Pastry::secondStageInterval [private] |
Definition at line 105 of file Pastry.h.
Referenced by changeState(), and initializeOverlay().
cMessage* Pastry::secondStageWait [private] |
Definition at line 123 of file Pastry.h.
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Pastry().
bool Pastry::sendStateAtLeafsetRepair [private] |
Definition at line 117 of file Pastry.h.
Referenced by handleFailedNode(), and initializeOverlay().
std::vector<PastryStateMsgHandle> Pastry::stReceived [protected] |
State messages to process during join.
Definition at line 93 of file Pastry.h.
Referenced by checkProxCache(), clearVectors(), doJoinUpdate(), handleStateMessage(), handleTimerEvent(), and mergeState().
std::vector<PastryStateMsgHandle>::iterator Pastry::stReceivedPos [protected] |
Definition at line 94 of file Pastry.h.
Referenced by checkProxCache(), clearVectors(), handleStateMessage(), and handleTimerEvent().
int Pastry::updateCounter [private] |
Definition at line 112 of file Pastry.h.
Referenced by checkProxCache(), and initializeOverlay().
bool Pastry::useDiscovery [private] |
Definition at line 115 of file Pastry.h.
Referenced by initializeOverlay(), joinOverlay(), and ~Pastry().
bool Pastry::useSecondStage [private] |