#include <Bamboo.h>
Public Member Functions | |
virtual | ~Bamboo () |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | handleTimerEvent (cMessage *msg) |
Processes "timer" self-messages. | |
virtual void | handleUDPMessage (BaseOverlayMessage *msg) |
Processes messages from underlay. | |
void | handleStateMessage (PastryStateMessage *msg) |
processes state messages, merging with own state tables | |
Protected Member Functions | |
virtual void | changeState (int toState) |
changes node state | |
virtual void | lookupFinished (AbstractLookup *lookup) |
Private Member Functions | |
void | doLeafsetMaintenance (void) |
periodically repairs the leafset by pushing it to and pulling it from from a random live leafset node | |
void | doGlobalTuning (void) |
periodically repairs the routing table by performing random lookups | |
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 | |
virtual void | joinOverlay () |
Join the overlay with a given nodeID in thisNode.key. | |
Private Attributes | |
double | leafsetMaintenanceTimeoutAmount |
double | globalTuningTimeoutAmount |
cMessage * | leafsetMaintenanceTimeout |
cMessage * | globalTuningTimeout |
Friends | |
class | BambooLookupListener |
Bamboo::~Bamboo | ( | ) | [virtual] |
00040 { 00041 00042 // destroy self timer messages 00043 cancelAndDelete(joinTimeout); 00044 cancelAndDelete(readyWait); 00045 cancelAndDelete(repairTaskTimeout); 00046 cancelAndDelete(leafsetMaintenanceTimeout); 00047 cancelAndDelete(globalTuningTimeout); 00048 00049 purgeVectors(); 00050 }
void Bamboo::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.
00070 { 00071 if ( stage != MIN_STAGE_OVERLAY ) 00072 return; 00073 00074 // Bamboo provides KBR services 00075 kbr = true; 00076 00077 baseInit(); 00078 00079 repairTaskTimeoutAmount = par("repairTaskTimeoutAmount"); 00080 leafsetMaintenanceTimeoutAmount = par("leafsetMaintenanceTimeoutAmount"); 00081 globalTuningTimeoutAmount = par("globalTuningTimeoutAmount"); 00082 00083 joinTimeout = new cMessage("joinTimeout"); 00084 readyWait = new cMessage("readyWait"); 00085 //joinUpdateWait = new cMessage("joinUpdateWait"); 00086 00087 repairTaskTimeout = new cMessage("repairTaskTimeout"); 00088 leafsetMaintenanceTimeout = new cMessage("leafsetMaintenanceTimeout"); 00089 globalTuningTimeout = new cMessage("globalTuningTimeout"); 00090 00091 sendPullFlag = true; 00092 00093 }
void Bamboo::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Processes "timer" self-messages.
msg | A self-message |
Reimplemented from BaseOverlay.
00160 { 00161 00162 if (msg->isName("joinTimeout")) { 00163 EV << "Pastry: join timeout expired, restarting..." << endl; 00164 joinOverlay(); 00165 } else if (msg->isName("readyWait")) { 00166 if (partialJoinPath) { 00167 RECORD_STATS(joinPartial++); 00168 sort(stReceived.begin(), stReceived.end(), stateMsgIsSmaller); 00169 00170 // start pinging the nodes found in the first state message: 00171 stReceivedPos = stReceived.begin(); 00172 stateCache = *stReceivedPos; 00173 EV << "Pastry: joining despite some missing STATE messages." 00174 << endl; 00175 pingNodes(); 00176 } else { 00177 EV << "Pastry: timeout waiting for missing state messages in JOIN " 00178 "state, restarting..." << endl; 00179 joinOverlay(); 00180 } 00181 } 00182 else if (msg->isName("repairTaskTimeout")) { 00183 EV << "Pastry: starting routing table maintenance" << endl; 00184 doRoutingTableMaintenance(); 00185 scheduleAt(simTime()+repairTaskTimeoutAmount, repairTaskTimeout); 00186 } 00187 else if (msg->isName("leafsetMaintenanceTimeout")) { 00188 EV << "Pastry: starting leafset maintenance" << endl; 00189 doLeafsetMaintenance(); 00190 scheduleAt(simTime()+leafsetMaintenanceTimeoutAmount, leafsetMaintenanceTimeout); 00191 } 00192 else if (msg->isName("globalTuningTimeout")) { 00193 EV << "Pastry: starting global tuning" << endl; 00194 doGlobalTuning(); 00195 scheduleAt(simTime()+globalTuningTimeoutAmount, globalTuningTimeout); 00196 } 00197 }
void Bamboo::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Processes messages from underlay.
msg | Message from UDP |
Reimplemented from BaseOverlay.
00200 { 00201 PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg); 00202 uint type = pastryMsg->getPastryMsgType(); 00203 00204 if (debugOutput) { 00205 EV << "Pastry: incoming message of type "; 00206 switch(type) { 00207 case PASTRY_MSG_STD: 00208 EV << "PASTRY_MSG_STD"; 00209 break; 00210 case PASTRY_MSG_JOIN: 00211 EV << "PASTRY_MSG_JOIN"; 00212 break; 00213 case PASTRY_MSG_STATE: 00214 EV << "PASTRY_MSG_STATE"; 00215 break; 00216 case PASTRY_MSG_LEAFSET: 00217 EV << "PASTRY_MSG_LEAFSET"; 00218 break; 00219 case PASTRY_MSG_LEAFSET_PULL: 00220 EV << "PASTRY_MSG_LEAFSET_PULL"; 00221 break; 00222 case PASTRY_MSG_ROWREQ: 00223 EV << "PASTRY_MSG_ROWREQ"; 00224 break; 00225 case PASTRY_MSG_RROW: 00226 EV << "PASTRY_MSG_RROW"; 00227 break; 00228 case PASTRY_MSG_REQ: 00229 EV << "PASTRY_MSG_REQ"; 00230 break; 00231 default: 00232 EV << "UNKNOWN (" << type <<")"; 00233 break; 00234 } 00235 EV << endl; 00236 } 00237 00238 switch (type) { 00239 case PASTRY_MSG_STD: 00240 opp_error("Pastry received PastryMessage of unknown type!"); 00241 break; 00242 case PASTRY_MSG_JOIN: 00243 00244 break; 00245 00246 case PASTRY_MSG_LEAFSET: { 00247 PastryLeafsetMessage* lmsg = 00248 check_and_cast<PastryLeafsetMessage*>(pastryMsg); 00249 RECORD_STATS(leafsetReceived++; leafsetBytesReceived += 00250 lmsg->byteLength()); 00251 00252 if (state == JOINING_2) { 00253 cancelEvent(joinTimeout); 00254 } 00255 00256 if ((state == JOINING_2) || (state == READY)) { 00257 handleLeafsetMessage(lmsg, true); 00258 } else { 00259 delete lmsg; 00260 } 00261 } 00262 break; 00263 00264 case PASTRY_MSG_LEAFSET_PULL: { 00265 PastryLeafsetMessage* lmsg = 00266 check_and_cast<PastryLeafsetMessage*>(pastryMsg); 00267 RECORD_STATS(leafsetReceived++; leafsetBytesReceived += 00268 lmsg->byteLength()); 00269 00270 if (state == READY) { 00271 00272 sendLeafset(lmsg->getSendStateTo()); 00273 handleLeafsetMessage(lmsg, true); 00274 00275 } else { 00276 delete lmsg; 00277 } 00278 } 00279 break; 00280 00281 case PASTRY_MSG_ROWREQ: { 00282 00283 PastryRoutingRowRequestMessage* rtrmsg = 00284 check_and_cast<PastryRoutingRowRequestMessage*>(pastryMsg); 00285 RECORD_STATS(routingTableReqReceived++; routingTableReqBytesReceived += 00286 rtrmsg->byteLength()); 00287 if (state == READY) 00288 if (rtrmsg->getRow() == -1) 00289 sendRoutingRow(rtrmsg->getSendStateTo(), routingTable->getLastRow()); 00290 else if (rtrmsg->getRow() > routingTable->getLastRow()) 00291 EV << "Pastry: received request for nonexistent routing" 00292 << "table row, dropping message!" << endl; 00293 else sendRoutingRow(rtrmsg->getSendStateTo(), rtrmsg->getRow()); 00294 else 00295 EV << "Pastry: received routing table request before reaching " 00296 << "READY state, dropping message!" << endl; 00297 delete rtrmsg; 00298 } 00299 break; 00300 00301 case PASTRY_MSG_RROW: { 00302 PastryRoutingRowMessage* rtmsg = 00303 check_and_cast<PastryRoutingRowMessage*>(pastryMsg); 00304 RECORD_STATS(routingTableReceived++; routingTableBytesReceived += 00305 rtmsg->byteLength()); 00306 00307 if (state == READY) { 00308 00309 uint nodesPerRow = routingTable->nodesPerRow; 00310 PastryStateMessage* stateMsg; 00311 00312 stateMsg = new PastryStateMessage("STATE"); 00313 stateMsg->setTimestamp(rtmsg->getTimestamp()); 00314 stateMsg->setPastryMsgType(PASTRY_MSG_STATE); 00315 stateMsg->setStatType(MAINTENANCE_STAT); 00316 stateMsg->setSender(rtmsg->getSender()); 00317 stateMsg->setLeafSetArraySize(0); 00318 stateMsg->setNeighborhoodSetArraySize(0); 00319 stateMsg->setRoutingTableArraySize(nodesPerRow); 00320 00321 for (uint i = 0; i < nodesPerRow; i++) { 00322 stateMsg->setRoutingTable(i, rtmsg->getRoutingTable(i)); 00323 } 00324 00325 handleStateMessage(stateMsg); 00326 } 00327 00328 delete rtmsg; 00329 } 00330 break; 00331 00332 case PASTRY_MSG_REQ: { 00333 PastryRequestMessage* lrmsg = 00334 check_and_cast<PastryRequestMessage*>(pastryMsg); 00335 handleRequestMessage(lrmsg); 00336 } 00337 break; 00338 00339 case PASTRY_MSG_STATE: { 00340 PastryStateMessage* stateMsg = 00341 check_and_cast<PastryStateMessage*>(msg); 00342 RECORD_STATS(stateReceived++; stateBytesReceived += 00343 stateMsg->byteLength()); 00344 handleStateMessage(stateMsg); 00345 } 00346 break; 00347 } 00348 }
void Bamboo::handleStateMessage | ( | PastryStateMessage * | msg | ) | [virtual] |
processes state messages, merging with own state tables
msg | the pastry state message |
Implements BasePastry.
Referenced by handleUDPMessage().
00447 { 00448 if (debugOutput) { 00449 EV << "Pastry::handleStateMessage() new STATE message to process " 00450 << static_cast<void*>(msg) << " in state " << 00451 ((state == READY)?"READY":((state == JOINING_2)?"JOIN":"INIT")) 00452 << endl; 00453 } 00454 00455 if (state == INIT) { 00456 EV << "Pastry: can't handle state messages until at least reaching " 00457 "JOIN state." << endl; 00458 delete msg; 00459 return; 00460 } 00461 00462 PastryStateMsgHandle handle(msg); 00463 00464 if (state == JOINING_2) { 00465 determineAliveTable(msg); 00466 leafSet->mergeState(msg, aliveTable); 00467 // merged state into leafset right now 00468 lastStateChange = simTime(); 00469 newLeafs(); 00470 updateTooltip(); 00471 00472 // no state message is processed right now, start immediately: 00473 stateCache = handle; 00474 pingNodes(); 00475 00476 return; 00477 } 00478 00479 // determine aliveTable to prevent leafSet from merging nodes that are 00480 // known to be dead: 00481 determineAliveTable(msg); 00482 if (leafSet->mergeState(msg, aliveTable)) { 00483 // merged state into leafset right now 00484 lastStateChange = simTime(); 00485 newLeafs(); 00486 updateTooltip(); 00487 } 00488 // in READY state, only ping nodes to get proximity metric: 00489 if (!stateCache.msg) { 00490 // no state message is processed right now, start immediately: 00491 stateCache = handle; 00492 pingNodes(); 00493 } else { 00494 // enqueue message for later processing: 00495 stateCacheQueue.push(handle); 00496 prePing(msg); 00497 } 00498 }
void Bamboo::changeState | ( | int | toState | ) | [protected, virtual] |
changes node state
toState | state to change to |
Reimplemented from BasePastry.
Referenced by checkProxCache(), and joinOverlay().
00109 { 00110 00111 baseChangeState(toState); 00112 00113 switch (toState) { 00114 case INIT: 00115 00116 break; 00117 00118 case DISCOVERY: 00119 00120 break; 00121 00122 case JOINING_2: 00123 00124 { 00125 PastryLeafsetMessage* msg = new PastryLeafsetMessage("Leafset"); 00126 msg->setPastryMsgType(PASTRY_MSG_LEAFSET_PULL); 00127 msg->setStatType(MAINTENANCE_STAT); 00128 msg->setSender(thisNode); 00129 msg->setSendStateTo(thisNode); 00130 leafSet->dumpToStateMessage(msg); 00131 msg->setLength(PASTRYLEAFSET_L(msg)); 00132 RECORD_STATS(leafsetSent++; leafsetBytesSent += msg->byteLength()); 00133 std::vector<TransportAddress> sourceRoute; 00134 sourceRoute.push_back(bootstrapNode); 00135 sendToKey(thisNode.key, msg, 0/*1*/, sourceRoute); 00136 } 00137 00138 break; 00139 00140 case READY: 00141 00142 // schedule routing table maintenance task 00143 cancelEvent(repairTaskTimeout); 00144 scheduleAt(simTime() + repairTaskTimeoutAmount, repairTaskTimeout); 00145 //EV << "local tuning scheduled for " << repairTaskTimeoutAmount << endl; 00146 //leaf2ask = NULL; 00147 00148 cancelEvent(leafsetMaintenanceTimeout); 00149 //scheduleAt(simTime() + leafsetMaintenanceTimeoutAmount, leafsetMaintenanceTimeout); 00150 scheduleAt(simTime() + strToSimtime("200ms"), leafsetMaintenanceTimeout); 00151 00152 cancelEvent(globalTuningTimeout); 00153 scheduleAt(simTime() + globalTuningTimeoutAmount, globalTuningTimeout); 00154 00155 break; 00156 } 00157 }
void Bamboo::lookupFinished | ( | AbstractLookup * | lookup | ) | [protected, virtual] |
00501 { 00502 EV << "[BambooListener::lookupFinished()]\n"; 00503 if (lookup->isValid()) { 00504 EV << " Lookup successful" << endl; 00505 } else { 00506 EV << " Lookup failed" << endl; 00507 } 00508 00509 }
void Bamboo::doLeafsetMaintenance | ( | void | ) | [private] |
periodically repairs the leafset by pushing it to and pulling it from from a random live leafset node
Referenced by handleTimerEvent().
00351 { 00352 00353 const TransportAddress& ask = leafSet->getRandomNode(); 00354 if (!ask.isUnspecified()) { 00355 sendLeafset(ask, true); 00356 EV << "Bamboo: leafset maintenance: pulling leafset from " 00357 << ask << endl; 00358 } 00359 00360 }
void Bamboo::doGlobalTuning | ( | void | ) | [private] |
periodically repairs the routing table by performing random lookups
Referenced by handleTimerEvent().
00363 { 00364 00365 OverlayKey newKey = OverlayKey::random(); 00366 //OverlayKey OverlayKey::randomSuffix ( uint pos ) const 00367 00368 createLookup()->lookup(newKey, 1, 0, 0, 00369 new BambooLookupListener(this)); 00370 00371 }
bool Bamboo::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.
00374 { 00375 if (state != READY) { 00376 return false; 00377 } 00378 00379 if (failed.isUnspecified()) 00380 opp_error("Bamboo::handleFailedNode(): failed is unspecified!"); 00381 00382 const TransportAddress& lsAsk = leafSet->failedNode(failed); 00383 /*const TransportAddress& rtAsk = */routingTable->failedNode(failed); 00384 neighborhoodSet->failedNode(failed); 00385 00386 if (lsAsk.isUnspecified() && (! leafSet->isValid())) { 00387 EV << "Pastry: lost connection to the network, trying to re-join." 00388 << endl; 00389 joinOverlay(); 00390 return false; 00391 } 00392 00393 return true; 00394 }
void Bamboo::checkProxCache | ( | void | ) | [private, virtual] |
checks whether proxCache is complete, takes appropriate actions depending on the protocol state
Implements BasePastry.
00397 { 00398 if (state == JOINING_2) { 00399 changeState(READY); 00400 return; 00401 } 00402 00403 // state == READY 00404 simtime_t now = simTime(); 00405 00406 // no cached STATE message? 00407 if (!(stateCache.msg && stateCache.prox)) return; 00408 00409 // some entries not yet determined? 00410 if (find(stateCache.prox->pr_rt.begin(), stateCache.prox->pr_rt.end(), 00411 PASTRY_PROX_PENDING) != stateCache.prox->pr_rt.end() 00412 ) return; 00413 if (find(stateCache.prox->pr_ls.begin(), stateCache.prox->pr_ls.end(), 00414 PASTRY_PROX_PENDING) != stateCache.prox->pr_ls.end() 00415 ) return; 00416 if (find(stateCache.prox->pr_ns.begin(), stateCache.prox->pr_ns.end(), 00417 PASTRY_PROX_PENDING) != stateCache.prox->pr_ns.end() 00418 ) return; 00419 00420 // merge info in own state tables 00421 // except leafset (was already handled in handleStateMessage) 00422 if (neighborhoodSet->mergeState(stateCache.msg, *stateCache.prox)) 00423 lastStateChange = now; 00424 EV << "Merging nodes into routing table" << endl; 00425 if (routingTable->mergeState(stateCache.msg, *stateCache.prox)) { 00426 lastStateChange = now; 00427 EV << "merged nodes into routing table" << endl; 00428 } 00429 00430 updateTooltip(); 00431 00432 delete stateCache.msg; 00433 stateCache.msg = NULL; 00434 delete stateCache.prox; 00435 stateCache.prox = NULL; 00436 00437 // process next queued message: 00438 if (! stateCacheQueue.empty()) { 00439 stateCache = stateCacheQueue.front(); 00440 stateCacheQueue.pop(); 00441 pingNodes(); 00442 } 00443 00444 }
void Bamboo::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.
Referenced by handleFailedNode(), and handleTimerEvent().
00096 { 00097 changeState(INIT); 00098 00099 if (bootstrapNode.isUnspecified()) { 00100 // no existing pastry network -> first node of a new one 00101 changeState(READY); 00102 } else { 00103 // join existing pastry network 00104 changeState(JOINING_2); 00105 } 00106 }
friend class BambooLookupListener [friend] |
Referenced by doGlobalTuning().
double Bamboo::leafsetMaintenanceTimeoutAmount [private] |
Referenced by handleTimerEvent(), and initializeOverlay().
double Bamboo::globalTuningTimeoutAmount [private] |
Referenced by changeState(), handleTimerEvent(), and initializeOverlay().
cMessage* Bamboo::leafsetMaintenanceTimeout [private] |
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Bamboo().
cMessage* Bamboo::globalTuningTimeout [private] |
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Bamboo().