#include <Bamboo.h>

Public Member Functions | |
| virtual | ~Bamboo () |
| 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 | |
Protected Member Functions | |
| void | lookupFinished (AbstractLookup *lookup) |
| virtual void | changeState (int toState) |
| changes node state | |
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 | |
| simtime_t | leafsetMaintenanceInterval |
| simtime_t | globalTuningInterval |
| cMessage * | leafsetMaintenanceTimer |
| cMessage * | globalTuningTimer |
| cMessage * | localTuningTimer |
Friends | |
| class | BambooLookupListener |
Definition at line 53 of file Bamboo.h.
| Bamboo::~Bamboo | ( | ) | [virtual] |
Definition at line 40 of file Bamboo.cc.
00041 { 00042 // destroy self timer messages 00043 cancelAndDelete(localTuningTimer); 00044 cancelAndDelete(leafsetMaintenanceTimer); 00045 cancelAndDelete(globalTuningTimer); 00046 }
| void Bamboo::changeState | ( | int | toState | ) | [protected, virtual] |
changes node state
| toState | state to change to |
Reimplemented from BasePastry.
Definition at line 85 of file Bamboo.cc.
Referenced by checkProxCache(), and joinOverlay().
00086 { 00087 baseChangeState(toState); 00088 00089 switch (toState) { 00090 case INIT: 00091 00092 break; 00093 00094 case DISCOVERY: 00095 00096 break; 00097 00098 case JOINING_2: 00099 00100 { 00101 PastryLeafsetMessage* msg = new PastryLeafsetMessage("Leafset"); 00102 msg->setPastryMsgType(PASTRY_MSG_LEAFSET_PULL); 00103 msg->setStatType(MAINTENANCE_STAT); 00104 msg->setSender(thisNode); 00105 msg->setSendStateTo(thisNode); 00106 leafSet->dumpToStateMessage(msg); 00107 msg->setBitLength(PASTRYLEAFSET_L(msg)); 00108 RECORD_STATS(leafsetSent++; leafsetBytesSent += msg->getByteLength()); 00109 std::vector<TransportAddress> sourceRoute; 00110 sourceRoute.push_back(bootstrapNode); 00111 sendToKey(thisNode.getKey(), msg, 0/*1*/, sourceRoute); 00112 00113 if (joinTimeout->isScheduled()) cancelEvent(joinTimeout); 00114 scheduleAt(simTime() + joinTimeoutAmount, joinTimeout); 00115 } 00116 00117 break; 00118 00119 case READY: 00120 00121 // schedule routing table maintenance task 00122 cancelEvent(localTuningTimer); 00123 scheduleAt(simTime() + routingTableMaintenanceInterval, localTuningTimer); 00124 00125 cancelEvent(leafsetMaintenanceTimer); 00126 //scheduleAt(simTime() + leafsetMaintenanceInterval, leafsetMaintenanceTimer); 00127 scheduleAt(simTime() + 0.2 /* 200ms */, leafsetMaintenanceTimer); 00128 00129 cancelEvent(globalTuningTimer); 00130 scheduleAt(simTime() + globalTuningInterval, globalTuningTimer); 00131 00132 break; 00133 } 00134 }
| void Bamboo::checkProxCache | ( | void | ) | [private, virtual] |
checks whether proxCache is complete, takes appropriate actions depending on the protocol state
Implements BasePastry.
Definition at line 404 of file Bamboo.cc.
00405 { 00406 if (state == JOINING_2) { 00407 changeState(READY); 00408 return; 00409 } 00410 00411 // state == READY 00412 simtime_t now = simTime(); 00413 00414 // no cached STATE message? 00415 if (!(stateCache.msg && stateCache.prox)) return; 00416 00417 // some entries not yet determined? 00418 if (find(stateCache.prox->pr_rt.begin(), stateCache.prox->pr_rt.end(), 00419 PASTRY_PROX_PENDING) != stateCache.prox->pr_rt.end()) return; 00420 if (find(stateCache.prox->pr_ls.begin(), stateCache.prox->pr_ls.end(), 00421 PASTRY_PROX_PENDING) != stateCache.prox->pr_ls.end()) return; 00422 if (find(stateCache.prox->pr_ns.begin(), stateCache.prox->pr_ns.end(), 00423 PASTRY_PROX_PENDING) != stateCache.prox->pr_ns.end()) return; 00424 00425 // merge info in own state tables 00426 // except leafset (was already handled in handleStateMessage) 00427 if (neighborhoodSet->mergeState(stateCache.msg, stateCache.prox)) 00428 lastStateChange = now; 00429 EV << "[Bamboo::checkProxCache()]\n" 00430 << " Merging nodes into routing table." 00431 << endl; 00432 if (routingTable->mergeState(stateCache.msg, stateCache.prox)) { 00433 lastStateChange = now; 00434 EV << "[Bamboo::checkProxCache()]\n" 00435 << " Merged nodes into routing table." 00436 << endl; 00437 } 00438 00439 updateTooltip(); 00440 00441 delete stateCache.msg; 00442 stateCache.msg = NULL; 00443 delete stateCache.prox; 00444 stateCache.prox = NULL; 00445 00446 // process next queued message: 00447 if (! stateCacheQueue.empty()) { 00448 stateCache = stateCacheQueue.front(); 00449 stateCacheQueue.pop(); 00450 pingNodes(); 00451 } 00452 00453 }
| void Bamboo::doGlobalTuning | ( | void | ) | [private] |
periodically repairs the routing table by performing random lookups
Definition at line 335 of file Bamboo.cc.
Referenced by handleTimerEvent().
00336 { 00337 /*int digit = 0; 00338 int lastRow = routingTable->getLastRow(); 00339 00340 int* choices = new int[lastRow + 1]; 00341 int sum = 0; 00342 00343 for (int i = 0; i < lastRow; ++i) { 00344 sum += (choices[i] = lastRow - i); 00345 } 00346 00347 int rval = intuniform(0, sum); 00348 00349 while (true) { 00350 rval -= choices [digit]; 00351 if (rval <= 0) 00352 break; 00353 ++digit; 00354 } 00355 delete[] choices;*/ 00356 00357 int digit = getNextRowToMaintain(); 00358 00359 // would be a better alternative 00360 //OverlayKey OverlayKey::randomSuffix(uint pos) const; 00361 00362 uint32_t maxDigitIndex = OverlayKey::getLength() - bitsPerDigit; 00363 uint32_t maxKeyIndex = OverlayKey::getLength() - 1; 00364 OverlayKey newKey = OverlayKey::random(); 00365 while (newKey.getBitRange(maxDigitIndex - digit * bitsPerDigit, bitsPerDigit) == 00366 thisNode.getKey().getBitRange(maxDigitIndex - digit * bitsPerDigit, bitsPerDigit)) { 00367 //std::cout << std::hex << newKey.getBitRange(maxDigitIndex - digit * bitsPerDigit, bitsPerDigit) << " "; 00368 newKey = OverlayKey::random(); 00369 } 00370 00371 assert(digit * bitsPerDigit < OverlayKey::getLength()); 00372 for (uint16_t i = 0; i < digit * bitsPerDigit; ++i) { 00373 newKey[maxKeyIndex - i] = thisNode.getKey().getBit(maxKeyIndex - i); 00374 } 00375 00376 createLookup()->lookup(newKey, 1, 0, 0, new BambooLookupListener(this)); 00377 //std::cout << lastRow << " " << digit << " " << thisNode.key << " -> " << newKey << std::endl; 00378 }
| void Bamboo::doLeafsetMaintenance | ( | void | ) | [private] |
periodically repairs the leafset by pushing it to and pulling it from from a random live leafset node
Definition at line 324 of file Bamboo.cc.
Referenced by handleTimerEvent().
00325 { 00326 const TransportAddress& ask = leafSet->getRandomNode(); 00327 if (!ask.isUnspecified()) { 00328 sendLeafset(ask, true); 00329 EV << "[Bamboo::doLeafsetMaintenance()]\n" 00330 << " leafset maintenance: pulling leafset from " 00331 << ask << endl; 00332 } 00333 }
| 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.
Definition at line 380 of file Bamboo.cc.
00381 { 00382 if (state != READY) { 00383 return false; 00384 } 00385 00386 if (failed.isUnspecified()) 00387 opp_error("Bamboo::handleFailedNode(): failed is unspecified!"); 00388 00389 const TransportAddress& lsAsk = leafSet->failedNode(failed); 00390 routingTable->failedNode(failed); 00391 neighborhoodSet->failedNode(failed); 00392 00393 if (lsAsk.isUnspecified() && (! leafSet->isValid())) { 00394 EV << "[Bamboo::handleFailedNode()]\n" 00395 << " lost connection to the network, trying to re-join." 00396 << endl; 00397 join(); 00398 return false; 00399 } 00400 00401 return true; 00402 }
| void Bamboo::handleStateMessage | ( | PastryStateMessage * | msg | ) | [virtual] |
processes state messages, merging with own state tables
| msg | the pastry state message |
Implements BasePastry.
Definition at line 455 of file Bamboo.cc.
Referenced by handleUDPMessage().
00456 { 00457 if (debugOutput) { 00458 EV << "[Bamboo::handleStateMessage() @ " << thisNode.getAddress() 00459 << " (" << thisNode.getKey().toString(16) << ")]\n" 00460 << " new STATE message to process " 00461 << static_cast<void*>(msg) << " in state " 00462 << ((state == READY)?"READY":((state == JOINING_2)?"JOIN":"INIT")) 00463 << endl; 00464 } 00465 00466 if (state == INIT) { 00467 EV << "[Bamboo::handleStateMessage() @ " << thisNode.getAddress() 00468 << " (" << thisNode.getKey().toString(16) << ")]\n" 00469 << " can't handle state messages until at least reaching JOIN state." 00470 << endl; 00471 delete msg; 00472 return; 00473 } 00474 00475 PastryStateMsgHandle handle(msg); 00476 00477 if (state == JOINING_2) { 00478 determineAliveTable(msg); 00479 leafSet->mergeState(msg, &aliveTable); 00480 // merged state into leafset right now 00481 lastStateChange = simTime(); 00482 newLeafs(); 00483 updateTooltip(); 00484 00485 // no state message is processed right now, start immediately: 00486 stateCache = handle; 00487 pingNodes(); 00488 00489 return; 00490 } 00491 00492 // determine aliveTable to prevent leafSet from merging nodes that are 00493 // known to be dead: 00494 determineAliveTable(msg); 00495 if (leafSet->mergeState(msg, &aliveTable)) { 00496 // merged state into leafset right now 00497 lastStateChange = simTime(); 00498 newLeafs(); 00499 updateTooltip(); 00500 } 00501 // in READY state, only ping nodes to get proximity metric: 00502 if (!stateCache.msg) { 00503 // no state message is processed right now, start immediately: 00504 stateCache = handle; 00505 pingNodes(); 00506 } else { 00507 // enqueue message for later processing: 00508 stateCacheQueue.push(handle); 00509 prePing(msg); 00510 } 00511 }
| void Bamboo::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Reimplemented from BaseRpc.
Definition at line 136 of file Bamboo.cc.
00137 { 00138 if (msg == joinTimeout) { 00139 EV << "[Bamboo::handleTimerEvent() @ " << thisNode.getAddress() 00140 << " (" << thisNode.getKey().toString(16) << ")]\n" 00141 << " join timeout expired, restarting..." 00142 << endl; 00143 join(); 00144 } else if (msg == localTuningTimer) { 00145 EV << "[Bamboo::handleTimerEvent() @ " << thisNode.getAddress() 00146 << " (" << thisNode.getKey().toString(16) << ")]\n" 00147 << " starting local tuning " 00148 << "(aka neighbor's neighbors / routing table maintenance)" 00149 << endl; 00150 doRoutingTableMaintenance(); 00151 scheduleAt(simTime() + routingTableMaintenanceInterval, localTuningTimer); 00152 } else if (msg == leafsetMaintenanceTimer) { 00153 EV << "[Bamboo::handleTimerEvent() @ " << thisNode.getAddress() 00154 << " (" << thisNode.getKey().toString(16) << ")]\n" 00155 << " starting leafset maintenance" 00156 << endl; 00157 doLeafsetMaintenance(); 00158 scheduleAt(simTime() + leafsetMaintenanceInterval, 00159 leafsetMaintenanceTimer); 00160 } else if (msg == globalTuningTimer) { 00161 EV << "[Bamboo::handleTimerEvent() @ " << thisNode.getAddress() 00162 << " (" << thisNode.getKey().toString(16) << ")]\n" 00163 << " starting global tuning" 00164 << endl; 00165 doGlobalTuning(); 00166 scheduleAt(simTime() + globalTuningInterval, globalTuningTimer); 00167 } 00168 }
| void Bamboo::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Processes messages from underlay.
| msg | Message from UDP |
Reimplemented from BaseOverlay.
Definition at line 170 of file Bamboo.cc.
00171 { 00172 PastryMessage* pastryMsg = check_and_cast<PastryMessage*>(msg); 00173 uint32_t type = pastryMsg->getPastryMsgType(); 00174 00175 if (debugOutput) { 00176 EV << "[Bamboo::handleUDPMessage() @ " << thisNode.getAddress() 00177 << " (" << thisNode.getKey().toString(16) << ")]\n" 00178 << " incoming message of type "; 00179 switch(type) { 00180 case PASTRY_MSG_STD: 00181 EV << "PASTRY_MSG_STD"; 00182 break; 00183 case PASTRY_MSG_JOIN: 00184 EV << "PASTRY_MSG_JOIN"; 00185 break; 00186 case PASTRY_MSG_STATE: 00187 EV << "PASTRY_MSG_STATE"; 00188 break; 00189 case PASTRY_MSG_LEAFSET: 00190 EV << "PASTRY_MSG_LEAFSET"; 00191 break; 00192 case PASTRY_MSG_LEAFSET_PULL: 00193 EV << "PASTRY_MSG_LEAFSET_PULL"; 00194 break; 00195 case PASTRY_MSG_ROWREQ: 00196 EV << "PASTRY_MSG_ROWREQ"; 00197 break; 00198 case PASTRY_MSG_RROW: 00199 EV << "PASTRY_MSG_RROW"; 00200 break; 00201 case PASTRY_MSG_REQ: 00202 EV << "PASTRY_MSG_REQ"; 00203 break; 00204 default: 00205 EV << "UNKNOWN (" << type <<")"; 00206 break; 00207 } 00208 EV << endl; 00209 } 00210 00211 switch (type) { 00212 case PASTRY_MSG_STD: 00213 opp_error("Pastry received PastryMessage of unknown type!"); 00214 break; 00215 case PASTRY_MSG_JOIN: 00216 00217 break; 00218 00219 case PASTRY_MSG_LEAFSET: { 00220 PastryLeafsetMessage* lmsg = 00221 check_and_cast<PastryLeafsetMessage*>(pastryMsg); 00222 RECORD_STATS(leafsetReceived++; leafsetBytesReceived += 00223 lmsg->getByteLength()); 00224 00225 if (state == JOINING_2) { 00226 cancelEvent(joinTimeout); 00227 } 00228 00229 if ((state == JOINING_2) || (state == READY)) { 00230 handleLeafsetMessage(lmsg, true); 00231 } else { 00232 delete lmsg; 00233 } 00234 } 00235 break; 00236 00237 case PASTRY_MSG_LEAFSET_PULL: { 00238 PastryLeafsetMessage* lmsg = 00239 check_and_cast<PastryLeafsetMessage*>(pastryMsg); 00240 RECORD_STATS(leafsetReceived++; leafsetBytesReceived += 00241 lmsg->getByteLength()); 00242 00243 if (state == READY) { 00244 00245 sendLeafset(lmsg->getSendStateTo()); 00246 handleLeafsetMessage(lmsg, true); 00247 00248 } else { 00249 delete lmsg; 00250 } 00251 } 00252 break; 00253 00254 case PASTRY_MSG_ROWREQ: { 00255 00256 PastryRoutingRowRequestMessage* rtrmsg = 00257 check_and_cast<PastryRoutingRowRequestMessage*>(pastryMsg); 00258 RECORD_STATS(routingTableReqReceived++; routingTableReqBytesReceived += 00259 rtrmsg->getByteLength()); 00260 if (state == READY) 00261 if (rtrmsg->getRow() == -1) 00262 sendRoutingRow(rtrmsg->getSendStateTo(), routingTable->getLastRow()); 00263 else if (rtrmsg->getRow() > routingTable->getLastRow()) 00264 EV << "[Bamboo::handleUDPMessage() @ " << thisNode.getAddress() 00265 << " (" << thisNode.getKey().toString(16) << ")]\n" 00266 << " received request for nonexistent routing" 00267 << "table row, dropping message!" << endl; 00268 else sendRoutingRow(rtrmsg->getSendStateTo(), rtrmsg->getRow()); 00269 else 00270 EV << "[Bamboo::handleUDPMessage() @ " << thisNode.getAddress() 00271 << " (" << thisNode.getKey().toString(16) << ")]\n" 00272 << " received routing table request before reaching " 00273 << "READY state, dropping message!" << endl; 00274 delete rtrmsg; 00275 } 00276 break; 00277 00278 case PASTRY_MSG_RROW: { 00279 PastryRoutingRowMessage* rtmsg = 00280 check_and_cast<PastryRoutingRowMessage*>(pastryMsg); 00281 RECORD_STATS(routingTableReceived++; routingTableBytesReceived += 00282 rtmsg->getByteLength()); 00283 00284 if (state == READY) { 00285 // create state message to probe all nodes from row message 00286 PastryStateMessage* stateMsg = new PastryStateMessage("STATE"); 00287 stateMsg->setTimestamp(rtmsg->getTimestamp()); 00288 stateMsg->setPastryMsgType(PASTRY_MSG_STATE); 00289 stateMsg->setStatType(MAINTENANCE_STAT); 00290 stateMsg->setSender(rtmsg->getSender()); 00291 stateMsg->setLeafSetArraySize(0); 00292 stateMsg->setNeighborhoodSetArraySize(0); 00293 stateMsg->setRoutingTableArraySize(rtmsg->getRoutingTableArraySize()); 00294 00295 for (uint32_t i = 0; i < rtmsg->getRoutingTableArraySize(); i++) { 00296 stateMsg->setRoutingTable(i, rtmsg->getRoutingTable(i)); 00297 } 00298 00299 handleStateMessage(stateMsg); 00300 } 00301 00302 delete rtmsg; 00303 } 00304 break; 00305 00306 case PASTRY_MSG_REQ: { 00307 PastryRequestMessage* lrmsg = 00308 check_and_cast<PastryRequestMessage*>(pastryMsg); 00309 handleRequestMessage(lrmsg); 00310 } 00311 break; 00312 00313 case PASTRY_MSG_STATE: { 00314 PastryStateMessage* stateMsg = 00315 check_and_cast<PastryStateMessage*>(msg); 00316 RECORD_STATS(stateReceived++; stateBytesReceived += 00317 stateMsg->getByteLength()); 00318 handleStateMessage(stateMsg); 00319 } 00320 break; 00321 } 00322 }
| 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.
Definition at line 48 of file Bamboo.cc.
00049 { 00050 if ( stage != MIN_STAGE_OVERLAY ) 00051 return; 00052 00053 // Bamboo provides KBR services 00054 kbr = true; 00055 00056 baseInit(); 00057 00058 routingTableMaintenanceInterval = par("repairTaskTimeoutAmount"); 00059 leafsetMaintenanceInterval = par("leafsetMaintenanceTimeoutAmount"); 00060 globalTuningInterval = par("globalTuningTimeoutAmount"); 00061 00062 joinTimeout = new cMessage("joinTimeout"); 00063 //joinUpdateWait = new cMessage("joinUpdateWait"); 00064 00065 localTuningTimer = new cMessage("repairTaskTimer"); 00066 leafsetMaintenanceTimer = new cMessage("leafsetMaintenanceTimer"); 00067 globalTuningTimer = new cMessage("globalTuningTimer"); 00068 00069 sendPullFlag = true; 00070 }
| 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.
Definition at line 72 of file Bamboo.cc.
00073 { 00074 changeState(INIT); 00075 00076 if (bootstrapNode.isUnspecified()) { 00077 // no existing pastry network -> first node of a new one 00078 changeState(READY); 00079 } else { 00080 // join existing pastry network 00081 changeState(JOINING_2); 00082 } 00083 }
| void Bamboo::lookupFinished | ( | AbstractLookup * | lookup | ) | [protected, virtual] |
Implements LookupListener.
Definition at line 513 of file Bamboo.cc.
Referenced by BambooLookupListener::lookupFinished().
00514 { 00515 EV << "[Bamboo::lookupFinished()]\n"; 00516 if (lookup->isValid()) { 00517 EV << " Lookup successful" << endl; 00518 const NodeVector& result = lookup->getResult(); 00519 if (result[0] != thisNode) { 00520 // Global Tuning PING 00521 Prox prox = neighborCache->getProx(result[0], NEIGHBORCACHE_DEFAULT, 00522 PING_SINGLE_NODE, this, NULL); 00523 if (prox != Prox::PROX_UNKNOWN) { 00524 routingTable->mergeNode(result[0], prox.proximity); 00525 } 00526 } 00527 } else { 00528 EV << " Lookup failed" << endl; 00529 } 00530 }
friend class BambooLookupListener [friend] |
simtime_t Bamboo::globalTuningInterval [private] |
Definition at line 86 of file Bamboo.h.
Referenced by changeState(), handleTimerEvent(), and initializeOverlay().
cMessage* Bamboo::globalTuningTimer [private] |
Definition at line 89 of file Bamboo.h.
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Bamboo().
simtime_t Bamboo::leafsetMaintenanceInterval [private] |
cMessage* Bamboo::leafsetMaintenanceTimer [private] |
Definition at line 88 of file Bamboo.h.
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Bamboo().
cMessage* Bamboo::localTuningTimer [private] |
Definition at line 90 of file Bamboo.h.
Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Bamboo().
1.5.8