#include <BootstrapList.h>
The BootstrapList module maintains a list of bootstrap node candidates received from various sources (BootstrapOracle for simulations and Zeroconf for SingleHostUnderlay). This list is also used to detect overlay partitions and triggers the merging process.
Public Member Functions | |
BootstrapList () | |
~BootstrapList () | |
const NodeHandle & | getBootstrapNode (const NodeHandle &node) |
Get a bootstrap node from the bootstrap list. | |
void | locateBootstrapNode (const NodeHandle &node) |
Determine locality of a bootstapnode. | |
bool | insertBootstrapCandidate (const NodeHandle &node, BootstrapNodePrioType prio=DNSSD) |
Inserts a new bootstrap candidate into the bootstrap list. | |
bool | insertBootstrapCandidate (BootstrapNodeHandle &node) |
void | removeBootstrapCandidate (const TransportAddress &addr) |
Remove an unavailable bootstrap candidate from the bootstraplist. | |
void | removeBootstrapNode (const NodeHandle &node) |
const NodeHandle & | getBootstrapNode () |
void | registerBootstrapNode (const NodeHandle &node) |
Protected Member Functions | |
virtual void | pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt) |
virtual void | pingTimeout (PingCall *pingCall, const TransportAddress &dest, cPolymorphic *context, int rpcId) |
virtual CompType | getThisCompType () |
Return the component type of this module. | |
Private Member Functions | |
virtual void | initializeApp (int stage) |
initializes derived class-attributes | |
virtual void | finishApp () |
collects statistical data of derived app | |
void | handleTimerEvent (cMessage *msg) |
processes self-messages | |
void | handleBootstrapListTimerExpired () |
Periodic maintenance method for the bootstrap list. | |
void | handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt) |
This method is called if an RPC response has been received. | |
void | handleLookupResponse (LookupResponse *msg) |
Handle the response for a lookup rpc. | |
Private Attributes | |
BootstrapNodeSet | bootstrapList |
cMessage * | timerMsg |
self-message for periodic maintenance | |
ZeroConfigurator * | zeroConfigurator |
pointer to the ZeroConfigurator module | |
bool | mergeOverlayPartitions |
if true, detect and merge overlay partitions | |
bool | maintainList |
maintain a list of bootstrap candidates and check them periodically | |
Static Private Attributes | |
static const int | timerInterval = 10 |
the interval of the maintenance timer in seconds |
BootstrapList::BootstrapList | ( | ) |
BootstrapList::~BootstrapList | ( | ) |
const NodeHandle& BootstrapList::getBootstrapNode | ( | const NodeHandle & | node | ) |
Get a bootstrap node from the bootstrap list.
If not using SingleHostConfigurator and the list is empty, return a node by asking the BootstrapOracle.
node | the node that needs a bootstrap node |
Referenced by BasePastry::baseChangeState(), Gia::changeState(), Chord::changeState(), Broose::changeState(), Vast::handleJoin(), Gia::handleTimerEvent(), and Kademlia::joinOverlay().
void BootstrapList::locateBootstrapNode | ( | const NodeHandle & | node | ) |
Determine locality of a bootstapnode.
node | the newly discovered bootstrap node |
Referenced by insertBootstrapCandidate().
00260 { 00261 Enter_Method_Silent(); 00262 00263 if ((overlay->getState() == BaseOverlay::READY) && (!node.isUnspecified()) 00264 && mergeOverlayPartitions) { 00265 LookupCall* call = new LookupCall(); 00266 call->setLength(0); 00267 call->setKey(node.key); 00268 call->setNumSiblings(overlay->getMaxNumSiblings()); 00269 sendInternalRpcCall(OVERLAY_COMP, call); 00270 } 00271 00272 return; 00273 }
bool BootstrapList::insertBootstrapCandidate | ( | const NodeHandle & | node, | |
BootstrapNodePrioType | prio = DNSSD | |||
) |
Inserts a new bootstrap candidate into the bootstrap list.
node | the bootstrap candidate | |
prio | priority of the bootstrap node |
Referenced by initializeApp(), and BootstrapOracle::mergeBootstrapNodes().
00278 { 00279 Enter_Method_Silent(); 00280 00281 BootstrapNodeSet::iterator iter; 00282 BootstrapNodeHandle *bootstrapNode; 00283 00284 // if node already in the list, update its lastPing and nodePrio fields 00285 if ((iter = bootstrapList.find(node)) != bootstrapList.end()) { 00286 iter->second->setLastPing(simTime()); 00287 iter->second->setNodePrio(prio); 00288 00289 return true; 00290 } 00291 00292 if ((bootstrapNode = new BootstrapNodeHandle(node, prio))) { 00293 bootstrapNode->setLastPing(simTime()); 00294 bootstrapList.insert(NodePair(*bootstrapNode, bootstrapNode)); 00295 } 00296 00297 locateBootstrapNode(node); 00298 00299 return false; 00300 }
bool BootstrapList::insertBootstrapCandidate | ( | BootstrapNodeHandle & | node | ) |
00304 { 00305 Enter_Method_Silent(); 00306 00307 BootstrapNodeSet::iterator iter; 00308 00309 node.setLastPing(simTime()); 00310 00311 // if node already in the list, update its lastPing and nodePrio fields 00312 if ((iter = bootstrapList.find(node)) != bootstrapList.end()) { 00313 iter->second->setLastPing(node.getLastPing()); 00314 iter->second->setNodePrio(node.getNodePrio()); 00315 00316 return true; 00317 } 00318 00319 bootstrapList.insert(NodePair(node, &node)); 00320 locateBootstrapNode(node); 00321 00322 return false; 00323 }
void BootstrapList::removeBootstrapCandidate | ( | const TransportAddress & | addr | ) |
Remove an unavailable bootstrap candidate from the bootstraplist.
addr | the address of the bootstrap candidate |
Referenced by pingTimeout().
00327 { 00328 BootstrapNodeSet::iterator iter; 00329 BootstrapNodeHandle* bootstrapNode; 00330 00331 if (!addr.isUnspecified()) { 00332 if ((iter = bootstrapList.find(addr)) != bootstrapList.end()) { 00333 bootstrapNode = iter->second; 00334 bootstrapList.erase(iter); 00335 delete bootstrapNode; 00336 } 00337 } 00338 00339 return; 00340 }
void BootstrapList::removeBootstrapNode | ( | const NodeHandle & | node | ) |
Referenced by BasePastry::baseChangeState(), Broose::changeState(), Gia::finishOverlay(), Chord::finishOverlay(), Broose::finishOverlay(), BasePastry::finishOverlay(), Kademlia::joinOverlay(), and BaseOverlay::setOverlayReady().
00344 { 00345 overlay->bootstrapOracle->removePeer(node); 00346 // at this point, we consider this node not being able to provide the 00347 // boot service anymore, therefore we have to revoke 00348 // the service via zeroConfigurator 00349 if (zeroConfigurator) { 00350 zeroConfigurator->revokeService(); 00351 } 00352 }
const NodeHandle & BootstrapList::getBootstrapNode | ( | ) |
00230 { 00231 if (!maintainList) { 00232 return overlay->bootstrapOracle->getBootstrapNode(); 00233 } else { 00234 const NodeHandle *bootstrapNode = &NodeHandle::UNSPECIFIED_NODE; 00235 int i, j = 0; 00236 00237 // pick a random node from the list 00238 if (!bootstrapList.empty()) { 00239 i = intrand(bootstrapList.size()); 00240 BootstrapNodeSet::iterator iter = bootstrapList.begin(); 00241 00242 while (j < i) { 00243 iter++; 00244 j++; 00245 } 00246 00247 bootstrapNode = (NodeHandle *)iter->second; 00248 } else { 00249 // if the list empty, get a bootstrap node from BootstrapOracle 00250 if (!zeroConfigurator) 00251 bootstrapNode = &overlay->bootstrapOracle-> 00252 getBootstrapNode(overlay->getThisNode()); 00253 } 00254 return *bootstrapNode; 00255 } 00256 }
void BootstrapList::registerBootstrapNode | ( | const NodeHandle & | node | ) |
Referenced by BaseOverlay::setOverlayReady().
00356 { 00357 bootstrapOracle->registerPeer(node); 00358 00359 // at this point, we consider this node as booted and therefore have to 00360 // announce the boot service for it via zeroConfigurator 00361 if (zeroConfigurator) { 00362 zeroConfigurator->announceService(node); 00363 } 00364 }
void BootstrapList::pingResponse | ( | PingResponse * | pingResponse, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [protected, virtual] |
Reimplemented from BaseRpc.
00198 { 00199 NodeHandle &srcNode = pingResponse->getSrcNode(); 00200 BootstrapNodeSet::iterator iter; 00201 00202 EV << "[BootstrapList::pingResponse() @ " << overlay->getThisNode().ip 00203 << " (" << overlay->getThisNode().key << ")]\n" 00204 << " Ping response from node " << srcNode 00205 << " with rtt " << rtt << endl; 00206 00207 // update the lastPing field of the source node 00208 if (!srcNode.isUnspecified()) 00209 if ((iter = bootstrapList.find(srcNode)) != bootstrapList.end()) 00210 iter->second->setLastPing(simTime()); 00211 00212 return; 00213 }
void BootstrapList::pingTimeout | ( | PingCall * | pingCall, | |
const TransportAddress & | dest, | |||
cPolymorphic * | context, | |||
int | rpcId | |||
) | [protected, virtual] |
Reimplemented from BaseRpc.
00220 { 00221 EV << "[BootstrapList::pingTimeout() @ " << overlay->getThisNode().ip 00222 << " (" << overlay->getThisNode().key << ")]\n" 00223 << " Ping timeout for node " << dest << endl; 00224 // destination does not answer, remove it from the list 00225 removeBootstrapCandidate(dest); 00226 }
virtual CompType BootstrapList::getThisCompType | ( | ) | [inline, protected, virtual] |
Return the component type of this module.
This method is overloaded by BaseOverlay/BaseApp and returns the appropriate component type of this module.
Reimplemented from BaseApp.
void BootstrapList::initializeApp | ( | int | stage | ) | [private, virtual] |
initializes derived class-attributes
stage | the init stage |
Reimplemented from BaseApp.
00073 { 00074 if (stage != MIN_STAGE_APP) { 00075 return; 00076 } 00077 00078 mergeOverlayPartitions = par("mergeOverlayPartitions"); 00079 maintainList = par("maintainList"); 00080 00081 if (parentModule()->parentModule()->submodule("zeroConfigurator", 0)) { 00082 zeroConfigurator = check_and_cast<ZeroConfigurator *>(parentModule()-> 00083 parentModule()->submodule("zeroConfigurator", 0)); 00084 if (!zeroConfigurator->isEnabled()) { 00085 zeroConfigurator = NULL; 00086 } 00087 } 00088 00089 // load local cache list only when using SingleHostConfigurator 00090 if (zeroConfigurator) { 00091 ifstream nodeListFile("nodelist.dat", ios::in); 00092 if (!nodeListFile) { 00093 EV << "BootstrapList::initializeApp(): nodelist.dat not found" 00094 << endl; 00095 } else { 00096 char address[16]; 00097 int port; 00098 string key; 00099 BootstrapNodeHandle *node; 00100 00101 while (nodeListFile >> address >> port >> key) { 00102 node = new BootstrapNodeHandle(OverlayKey(key, 16), 00103 IPvXAddress(address), port, 00104 CACHE); 00105 if (node) 00106 insertBootstrapCandidate(*node); 00107 } 00108 nodeListFile.close(); 00109 } 00110 } 00111 00112 WATCH_UNORDERED_MAP(bootstrapList); 00113 00114 if (maintainList) { 00115 timerMsg = new cMessage("BootstrapListTimer"); 00116 scheduleAt(simTime() + timerInterval, timerMsg); 00117 } 00118 }
void BootstrapList::finishApp | ( | ) | [private, virtual] |
collects statistical data of derived app
Reimplemented from BaseApp.
00368 { 00369 // dump the list of bootstrap nodes into the local cache only when 00370 // using SingleHostConfigurator 00371 if (zeroConfigurator) { 00372 ofstream nodeListFile("nodelist.dat", ios::out|ios::trunc); 00373 if (!nodeListFile) { 00374 std::cerr << "nodelist.dat could not be opened" << endl; 00375 } else { 00376 for (BootstrapNodeSet::iterator iter = bootstrapList.begin(); 00377 iter != bootstrapList.end(); iter++) { 00378 nodeListFile << iter->second->ip.str() << ' ' 00379 << iter->second->port << ' ' 00380 << iter->second->key.toString(16) << '\n'; 00381 } 00382 nodeListFile.close(); 00383 } 00384 } 00385 00386 // delete all bootstrap nodes and clear the list 00387 for (BootstrapNodeSet::iterator iter = bootstrapList.begin(); 00388 iter != bootstrapList.end(); iter++) { 00389 delete iter->second; 00390 } 00391 00392 bootstrapList.clear(); 00393 }
void BootstrapList::handleTimerEvent | ( | cMessage * | msg | ) | [private, virtual] |
processes self-messages
method to handle self-messages should be overwritten in derived application if needed
msg | self-message |
Reimplemented from BaseApp.
00122 { 00123 if (msg == timerMsg) { 00124 handleBootstrapListTimerExpired(); 00125 scheduleAt(simTime() + timerInterval, msg); 00126 } else { 00127 throw new cException("BootstrapList::handleTimerEvent(): " 00128 "Received unknown self-message!"); 00129 } 00130 }
void BootstrapList::handleBootstrapListTimerExpired | ( | ) | [private] |
Periodic maintenance method for the bootstrap list.
Referenced by handleTimerEvent().
00133 { 00134 simtime_t current = simTime(); 00135 BootstrapNodeHandle *node; 00136 BootstrapNodeSet::iterator iter; 00137 00138 for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) { 00139 node = iter->second; 00140 if (timerInterval <= (current - node->getLastPing())) { 00141 pingNode(*node); 00142 } 00143 } 00144 }
void BootstrapList::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [private, virtual] |
This method is called if an RPC response has been received.
msg | The response message. | |
context | Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code | |
rpcId | The RPC id. | |
rtt | The Round-Trip-Time of this RPC |
Reimplemented from RpcListener.
00150 { 00151 RPC_SWITCH_START(msg) 00152 RPC_ON_RESPONSE(Lookup) { 00153 handleLookupResponse(_LookupResponse); 00154 EV << "[BootstrapList::handleRpcResponse() @ " 00155 << overlay->getThisNode().ip 00156 << " (" << overlay->getThisNode().key.toString(16) << ")]\n" 00157 << " Lookup RPC Response received: id=" << rpcId << "\n" 00158 << " msg=" << *_LookupResponse << " rtt=" << rtt 00159 << endl; 00160 } 00161 RPC_SWITCH_END( ) 00162 }
void BootstrapList::handleLookupResponse | ( | LookupResponse * | msg | ) | [private] |
Handle the response for a lookup rpc.
This is used to detected foreign overlay partitions
msg | The lookup response message |
Referenced by handleRpcResponse().
00165 { 00166 EV << "[BootstrapList::handleLookupResponse() @ " 00167 << overlay->getThisNode().ip 00168 << " (" << overlay->getThisNode().key.toString(16) << ")]\n" 00169 << " Lookup response for key " << msg->getKey()<< " : "; 00170 00171 if (msg->getIsValid()) { 00172 for (uint i=0; i<msg->getSiblingsArraySize(); i++) { 00173 if (msg->getSiblings(i).key == msg->getKey()) { 00174 EV << "Key " << msg->getSiblings(i) 00175 << "belongs to a local node." << endl; 00176 return; 00177 } 00178 } 00179 00180 EV << "New partition discovered, going to join." << endl; 00181 BootstrapNodeSet::iterator iter; 00182 for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) { 00183 if (iter->second->key == msg->getKey()) 00184 overlay->joinForeignPartition(*iter->second); 00185 } 00186 00187 } else { 00188 EV << "failed" << endl; 00189 } 00190 00191 return; 00192 }
BootstrapNodeSet BootstrapList::bootstrapList [private] |
const int BootstrapList::timerInterval = 10 [static, private] |
the interval of the maintenance timer in seconds
Referenced by handleBootstrapListTimerExpired(), handleTimerEvent(), and initializeApp().
cMessage* BootstrapList::timerMsg [private] |
self-message for periodic maintenance
Referenced by BootstrapList(), handleTimerEvent(), initializeApp(), and ~BootstrapList().
ZeroConfigurator* BootstrapList::zeroConfigurator [private] |
pointer to the ZeroConfigurator module
Referenced by BootstrapList(), finishApp(), getBootstrapNode(), initializeApp(), registerBootstrapNode(), and removeBootstrapNode().
bool BootstrapList::mergeOverlayPartitions [private] |
if true, detect and merge overlay partitions
Referenced by initializeApp(), and locateBootstrapNode().
bool BootstrapList::maintainList [private] |
maintain a list of bootstrap candidates and check them periodically
Referenced by getBootstrapNode(), and initializeApp().