BootstrapList.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <BaseApp.h>
00025 #include <BootstrapList.h>
00026 #include <GlobalNodeList.h>
00027 #include <BaseOverlay.h>
00028 #include <UnderlayConfiguratorAccess.h>
00029 #include <ZeroconfConnector.h>
00030 #include <CommonMessages_m.h>
00031 #include <hashWatch.h>
00032
00033 #include <fstream>
00034 #include <iostream>
00035
00036 using namespace std;
00037
00038 Define_Module(BootstrapList);
00039
00040 std::ostream& operator<<(std::ostream& os, const BootstrapNodeHandle* n)
00041 {
00042 if (n == NULL) {
00043 os << "<NULL>";
00044 return os;
00045 }
00046
00047 if (n->isUnspecified()) {
00048 os << "<unspec>";
00049 } else {
00050 os << n->getAddress() << ":" << n->getPort() << " " << n->getKey()
00051 << " last ping:" << n->getLastPing()
00052 << " prio:" << n->getNodePrio();
00053 }
00054
00055 return os;
00056 };
00057
00058
00059 BootstrapList::BootstrapList()
00060 {
00061 zeroconfConnector = NULL;
00062 timerMsg = NULL;
00063 }
00064
00065
00066 BootstrapList::~BootstrapList()
00067 {
00068 cancelAndDelete(timerMsg);
00069 }
00070
00071
00072 void BootstrapList::initializeApp(int stage)
00073 {
00074 if (stage != MIN_STAGE_COMPONENTS) {
00075 return;
00076 }
00077
00078 mergeOverlayPartitions = par("mergeOverlayPartitions");
00079 maintainList = par("maintainList");
00080
00081 if (getParentModule()->getParentModule()->getSubmodule("zeroconfConnector", 0)) {
00082 zeroconfConnector = check_and_cast<ZeroconfConnector *>(getParentModule()->
00083 getParentModule()->getSubmodule("zeroconfConnector", 0));
00084 if (!zeroconfConnector->isEnabled()) {
00085 zeroconfConnector = NULL;
00086 }
00087 }
00088
00089
00090 if (zeroconfConnector) {
00091 ifstream nodeListFile("nodelist.dat", ios::in);
00092 if (!nodeListFile) {
00093 EV << "[BootstrapList::initializeApp() @ " << overlay->getThisNode().getAddress()
00094 << " (" << overlay->getThisNode().getKey() << ")]\n"
00095 << " nodelist.dat not found"
00096 << endl;
00097 } else {
00098 char address[16];
00099 int port;
00100 string key;
00101 BootstrapNodeHandle *node;
00102
00103 while (nodeListFile >> address >> port >> key) {
00104 node = new BootstrapNodeHandle(OverlayKey(key, 16),
00105 IPvXAddress(address), port,
00106 CACHE);
00107 if (node)
00108 insertBootstrapCandidate(*node);
00109 }
00110 nodeListFile.close();
00111
00112
00113 if (bootstrapList.size()) sendReadyMessage();
00114 }
00115 } else {
00116 sendReadyMessage();
00117 }
00118
00119 WATCH_UNORDERED_MAP(bootstrapList);
00120
00121 if (maintainList) {
00122 timerMsg = new cMessage("BootstrapListTimer");
00123 scheduleAt(simTime() + timerInterval, timerMsg);
00124 }
00125 }
00126
00127
00128 void BootstrapList::handleTimerEvent(cMessage *msg)
00129 {
00130 if (msg == timerMsg) {
00131 handleBootstrapListTimerExpired();
00132 scheduleAt(simTime() + timerInterval, msg);
00133 } else {
00134 throw cRuntimeError("BootstrapList::handleTimerEvent(): "
00135 "Received unknown self-message!");
00136 }
00137 }
00138
00139 void BootstrapList::handleBootstrapListTimerExpired()
00140 {
00141 simtime_t current = simTime();
00142 BootstrapNodeHandle *node;
00143 BootstrapNodeSet::iterator iter;
00144
00145 for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) {
00146 node = iter->second;
00147 if (timerInterval <= SIMTIME_DBL(current - node->getLastPing())) {
00148 pingNode(*node);
00149 }
00150 }
00151 }
00152
00153
00154 void BootstrapList::handleRpcResponse(BaseResponseMessage* msg,
00155 cPolymorphic* context,
00156 int rpcId, simtime_t rtt)
00157 {
00158 RPC_SWITCH_START(msg)
00159 RPC_ON_RESPONSE(Lookup) {
00160 handleLookupResponse(_LookupResponse);
00161 EV << "[BootstrapList::handleRpcResponse() @ "
00162 << overlay->getThisNode().getAddress()
00163 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00164 << " Lookup RPC Response received: id=" << rpcId << "\n"
00165 << " msg=" << *_LookupResponse << " rtt=" << rtt
00166 << endl;
00167 }
00168 RPC_SWITCH_END( )
00169 }
00170
00171 void BootstrapList::handleLookupResponse(LookupResponse* msg)
00172 {
00173 EV << "[BootstrapList::handleLookupResponse() @ "
00174 << overlay->getThisNode().getAddress()
00175 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00176 << " Lookup response for key " << msg->getKey()<< " : ";
00177
00178 if (msg->getIsValid()) {
00179 for (uint32_t i=0; i<msg->getSiblingsArraySize(); i++) {
00180 if (msg->getSiblings(i).getKey() == msg->getKey()) {
00181 EV << "Key " << msg->getSiblings(i)
00182 << "belongs to a local node." << endl;
00183 return;
00184 }
00185 }
00186
00187 EV << "New partition discovered, going to join." << endl;
00188 BootstrapNodeSet::iterator iter;
00189 for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) {
00190 if (iter->second->getKey() == msg->getKey())
00191 overlay->joinForeignPartition(*iter->second);
00192 }
00193
00194 } else {
00195 EV << "failed" << endl;
00196 }
00197
00198 return;
00199 }
00200
00201
00202 void BootstrapList::pingResponse(PingResponse* pingResponse,
00203 cPolymorphic* context,
00204 int rpcId, simtime_t rtt)
00205 {
00206 NodeHandle &srcNode = pingResponse->getSrcNode();
00207 BootstrapNodeSet::iterator iter;
00208
00209 EV << "[BootstrapList::pingResponse() @ " << overlay->getThisNode().getAddress()
00210 << " (" << overlay->getThisNode().getKey() << ")]\n"
00211 << " Ping response from node " << srcNode
00212 << " with rtt " << rtt << endl;
00213
00214
00215 if (!srcNode.isUnspecified())
00216 if ((iter = bootstrapList.find(srcNode)) != bootstrapList.end())
00217 iter->second->setLastPing(simTime());
00218
00219 return;
00220 }
00221
00222
00223 void BootstrapList::pingTimeout(PingCall* pingCall,
00224 const TransportAddress& dest,
00225 cPolymorphic* context,
00226 int rpcId)
00227 {
00228 EV << "[BootstrapList::pingTimeout() @ " << overlay->getThisNode().getAddress()
00229 << " (" << overlay->getThisNode().getKey() << ")]\n"
00230 << " Ping timeout for node " << dest << endl;
00231
00232 removeBootstrapCandidate(dest);
00233 }
00234
00235
00236 const TransportAddress BootstrapList::getBootstrapNode()
00237 {
00238 if (!maintainList) {
00239
00240 return overlay->globalNodeList->getRandomNode(0, true, true);
00241
00242 } else {
00243 const NodeHandle *bootstrapNode = &NodeHandle::UNSPECIFIED_NODE;
00244 int i, j = 0;
00245
00246
00247 if (!bootstrapList.empty()) {
00248 i = intrand(bootstrapList.size());
00249 BootstrapNodeSet::iterator iter = bootstrapList.begin();
00250
00251 while (j < i) {
00252 iter++;
00253 j++;
00254 }
00255
00256 bootstrapNode = (NodeHandle *)iter->second;
00257 } else {
00258
00259 if (!zeroconfConnector)
00260 bootstrapNode = &overlay->globalNodeList->
00261 getBootstrapNode(overlay->getThisNode());
00262 }
00263 return *bootstrapNode;
00264 }
00265 }
00266
00267
00268 void BootstrapList::locateBootstrapNode(const NodeHandle& node)
00269 {
00270 Enter_Method_Silent();
00271
00272 if ((overlay->getState() == BaseOverlay::READY) && (!node.isUnspecified())
00273 && mergeOverlayPartitions) {
00274 LookupCall* call = new LookupCall();
00275 call->setBitLength(0);
00276 call->setKey(node.getKey());
00277 call->setNumSiblings(overlay->getMaxNumSiblings());
00278 sendInternalRpcCall(OVERLAY_COMP, call);
00279 }
00280
00281 return;
00282 }
00283
00284
00285 bool BootstrapList::insertBootstrapCandidate(const NodeHandle& node,
00286 BootstrapNodePrioType prio)
00287 {
00288 Enter_Method_Silent();
00289
00290 BootstrapNodeSet::iterator iter;
00291 BootstrapNodeHandle *bootstrapNode;
00292
00293
00294 if ((iter = bootstrapList.find(node)) != bootstrapList.end()) {
00295 iter->second->setLastPing(simTime());
00296 iter->second->setNodePrio(prio);
00297
00298 return true;
00299 }
00300
00301 if ((bootstrapNode = new BootstrapNodeHandle(node, prio))) {
00302 bootstrapNode->setLastPing(simTime());
00303 bootstrapList.insert(NodePair(*bootstrapNode, bootstrapNode));
00304 }
00305
00306 locateBootstrapNode(node);
00307
00308 return false;
00309 }
00310
00311
00312 bool BootstrapList::insertBootstrapCandidate(BootstrapNodeHandle& node)
00313 {
00314 Enter_Method_Silent();
00315
00316 BootstrapNodeSet::iterator iter;
00317
00318 node.setLastPing(simTime());
00319
00320
00321 if ((iter = bootstrapList.find(node)) != bootstrapList.end()) {
00322 iter->second->setLastPing(node.getLastPing());
00323 iter->second->setNodePrio(node.getNodePrio());
00324
00325 return true;
00326 }
00327
00328 bootstrapList.insert(NodePair(node, &node));
00329 locateBootstrapNode(node);
00330
00331 return false;
00332 }
00333
00334
00335 void BootstrapList::removeBootstrapCandidate(const TransportAddress& addr)
00336 {
00337 BootstrapNodeSet::iterator iter;
00338 BootstrapNodeHandle* bootstrapNode;
00339
00340 if (!addr.isUnspecified()) {
00341 if ((iter = bootstrapList.find(addr)) != bootstrapList.end()) {
00342 bootstrapNode = iter->second;
00343 bootstrapList.erase(iter);
00344 delete bootstrapNode;
00345 }
00346 }
00347
00348 return;
00349 }
00350
00351
00352 void BootstrapList::removeBootstrapNode(const NodeHandle& node)
00353 {
00354 overlay->globalNodeList->removePeer(node);
00355
00356
00357
00358 if (zeroconfConnector) {
00359 zeroconfConnector->revokeService();
00360 }
00361 }
00362
00363
00364 void BootstrapList::registerBootstrapNode(const NodeHandle& node)
00365 {
00366 globalNodeList->registerPeer(node);
00367
00368
00369
00370 if (zeroconfConnector) {
00371 zeroconfConnector->announceService(node);
00372 }
00373 }
00374
00375
00376 void BootstrapList::finishApp()
00377 {
00378
00379
00380 if (zeroconfConnector) {
00381 ofstream nodeListFile("nodelist.dat", ios::out|ios::trunc);
00382 if (!nodeListFile) {
00383 std::cerr << "nodelist.dat could not be opened" << endl;
00384 } else {
00385 for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00386 iter != bootstrapList.end(); iter++) {
00387 nodeListFile << iter->second->getAddress().str() << ' '
00388 << iter->second->getPort() << ' '
00389 << iter->second->getKey().toString(16) << '\n';
00390 }
00391 nodeListFile.close();
00392 }
00393 }
00394
00395
00396 for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00397 iter != bootstrapList.end(); iter++) {
00398 delete iter->second;
00399 }
00400
00401 bootstrapList.clear();
00402 }