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_APP) {
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
00114 WATCH_UNORDERED_MAP(bootstrapList);
00115
00116 if (maintainList) {
00117 timerMsg = new cMessage("BootstrapListTimer");
00118 scheduleAt(simTime() + timerInterval, timerMsg);
00119 }
00120 }
00121
00122
00123 void BootstrapList::handleTimerEvent(cMessage *msg)
00124 {
00125 if (msg == timerMsg) {
00126 handleBootstrapListTimerExpired();
00127 scheduleAt(simTime() + timerInterval, msg);
00128 } else {
00129 throw cRuntimeError("BootstrapList::handleTimerEvent(): "
00130 "Received unknown self-message!");
00131 }
00132 }
00133
00134 void BootstrapList::handleBootstrapListTimerExpired()
00135 {
00136 simtime_t current = simTime();
00137 BootstrapNodeHandle *node;
00138 BootstrapNodeSet::iterator iter;
00139
00140 for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) {
00141 node = iter->second;
00142 if (timerInterval <= SIMTIME_DBL(current - node->getLastPing())) {
00143 pingNode(*node);
00144 }
00145 }
00146 }
00147
00148
00149 void BootstrapList::handleRpcResponse(BaseResponseMessage* msg,
00150 cPolymorphic* context,
00151 int rpcId, simtime_t rtt)
00152 {
00153 RPC_SWITCH_START(msg)
00154 RPC_ON_RESPONSE(Lookup) {
00155 handleLookupResponse(_LookupResponse);
00156 EV << "[BootstrapList::handleRpcResponse() @ "
00157 << overlay->getThisNode().getAddress()
00158 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00159 << " Lookup RPC Response received: id=" << rpcId << "\n"
00160 << " msg=" << *_LookupResponse << " rtt=" << rtt
00161 << endl;
00162 }
00163 RPC_SWITCH_END( )
00164 }
00165
00166 void BootstrapList::handleLookupResponse(LookupResponse* msg)
00167 {
00168 EV << "[BootstrapList::handleLookupResponse() @ "
00169 << overlay->getThisNode().getAddress()
00170 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00171 << " Lookup response for key " << msg->getKey()<< " : ";
00172
00173 if (msg->getIsValid()) {
00174 for (uint32_t i=0; i<msg->getSiblingsArraySize(); i++) {
00175 if (msg->getSiblings(i).getKey() == msg->getKey()) {
00176 EV << "Key " << msg->getSiblings(i)
00177 << "belongs to a local node." << endl;
00178 return;
00179 }
00180 }
00181
00182 EV << "New partition discovered, going to join." << endl;
00183 BootstrapNodeSet::iterator iter;
00184 for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) {
00185 if (iter->second->getKey() == msg->getKey())
00186 overlay->joinForeignPartition(*iter->second);
00187 }
00188
00189 } else {
00190 EV << "failed" << endl;
00191 }
00192
00193 return;
00194 }
00195
00196
00197 void BootstrapList::pingResponse(PingResponse* pingResponse,
00198 cPolymorphic* context,
00199 int rpcId, simtime_t rtt)
00200 {
00201 NodeHandle &srcNode = pingResponse->getSrcNode();
00202 BootstrapNodeSet::iterator iter;
00203
00204 EV << "[BootstrapList::pingResponse() @ " << overlay->getThisNode().getAddress()
00205 << " (" << overlay->getThisNode().getKey() << ")]\n"
00206 << " Ping response from node " << srcNode
00207 << " with rtt " << rtt << endl;
00208
00209
00210 if (!srcNode.isUnspecified())
00211 if ((iter = bootstrapList.find(srcNode)) != bootstrapList.end())
00212 iter->second->setLastPing(simTime());
00213
00214 return;
00215 }
00216
00217
00218 void BootstrapList::pingTimeout(PingCall* pingCall,
00219 const TransportAddress& dest,
00220 cPolymorphic* context,
00221 int rpcId)
00222 {
00223 EV << "[BootstrapList::pingTimeout() @ " << overlay->getThisNode().getAddress()
00224 << " (" << overlay->getThisNode().getKey() << ")]\n"
00225 << " Ping timeout for node " << dest << endl;
00226
00227 removeBootstrapCandidate(dest);
00228 }
00229
00230
00231 const TransportAddress BootstrapList::getBootstrapNode()
00232 {
00233 if (!maintainList) {
00234
00235
00236 return overlay->globalNodeList->getBootstrapNode();
00237 } else {
00238 const NodeHandle *bootstrapNode = &NodeHandle::UNSPECIFIED_NODE;
00239 int i, j = 0;
00240
00241
00242 if (!bootstrapList.empty()) {
00243 i = intrand(bootstrapList.size());
00244 BootstrapNodeSet::iterator iter = bootstrapList.begin();
00245
00246 while (j < i) {
00247 iter++;
00248 j++;
00249 }
00250
00251 bootstrapNode = (NodeHandle *)iter->second;
00252 } else {
00253
00254 if (!zeroconfConnector)
00255 bootstrapNode = &overlay->globalNodeList->
00256 getBootstrapNode(overlay->getThisNode());
00257 }
00258 return *bootstrapNode;
00259 }
00260 }
00261
00262
00263 void BootstrapList::locateBootstrapNode(const NodeHandle& node)
00264 {
00265 Enter_Method_Silent();
00266
00267 if ((overlay->getState() == BaseOverlay::READY) && (!node.isUnspecified())
00268 && mergeOverlayPartitions) {
00269 LookupCall* call = new LookupCall();
00270 call->setBitLength(0);
00271 call->setKey(node.getKey());
00272 call->setNumSiblings(overlay->getMaxNumSiblings());
00273 sendInternalRpcCall(OVERLAY_COMP, call);
00274 }
00275
00276 return;
00277 }
00278
00279
00280 bool BootstrapList::insertBootstrapCandidate(const NodeHandle& node,
00281 BootstrapNodePrioType prio)
00282 {
00283 Enter_Method_Silent();
00284
00285 BootstrapNodeSet::iterator iter;
00286 BootstrapNodeHandle *bootstrapNode;
00287
00288
00289 if ((iter = bootstrapList.find(node)) != bootstrapList.end()) {
00290 iter->second->setLastPing(simTime());
00291 iter->second->setNodePrio(prio);
00292
00293 return true;
00294 }
00295
00296 if ((bootstrapNode = new BootstrapNodeHandle(node, prio))) {
00297 bootstrapNode->setLastPing(simTime());
00298 bootstrapList.insert(NodePair(*bootstrapNode, bootstrapNode));
00299 }
00300
00301 locateBootstrapNode(node);
00302
00303 return false;
00304 }
00305
00306
00307 bool BootstrapList::insertBootstrapCandidate(BootstrapNodeHandle& node)
00308 {
00309 Enter_Method_Silent();
00310
00311 BootstrapNodeSet::iterator iter;
00312
00313 node.setLastPing(simTime());
00314
00315
00316 if ((iter = bootstrapList.find(node)) != bootstrapList.end()) {
00317 iter->second->setLastPing(node.getLastPing());
00318 iter->second->setNodePrio(node.getNodePrio());
00319
00320 return true;
00321 }
00322
00323 bootstrapList.insert(NodePair(node, &node));
00324 locateBootstrapNode(node);
00325
00326 return false;
00327 }
00328
00329
00330 void BootstrapList::removeBootstrapCandidate(const TransportAddress& addr)
00331 {
00332 BootstrapNodeSet::iterator iter;
00333 BootstrapNodeHandle* bootstrapNode;
00334
00335 if (!addr.isUnspecified()) {
00336 if ((iter = bootstrapList.find(addr)) != bootstrapList.end()) {
00337 bootstrapNode = iter->second;
00338 bootstrapList.erase(iter);
00339 delete bootstrapNode;
00340 }
00341 }
00342
00343 return;
00344 }
00345
00346
00347 void BootstrapList::removeBootstrapNode(const NodeHandle& node)
00348 {
00349 overlay->globalNodeList->removePeer(node);
00350
00351
00352
00353 if (zeroconfConnector) {
00354 zeroconfConnector->revokeService();
00355 }
00356 }
00357
00358
00359 void BootstrapList::registerBootstrapNode(const NodeHandle& node)
00360 {
00361 globalNodeList->registerPeer(node);
00362
00363
00364
00365 if (zeroconfConnector) {
00366 zeroconfConnector->announceService(node);
00367 }
00368 }
00369
00370
00371 void BootstrapList::finishApp()
00372 {
00373
00374
00375 if (zeroconfConnector) {
00376 ofstream nodeListFile("nodelist.dat", ios::out|ios::trunc);
00377 if (!nodeListFile) {
00378 std::cerr << "nodelist.dat could not be opened" << endl;
00379 } else {
00380 for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00381 iter != bootstrapList.end(); iter++) {
00382 nodeListFile << iter->second->getAddress().str() << ' '
00383 << iter->second->getPort() << ' '
00384 << iter->second->getKey().toString(16) << '\n';
00385 }
00386 nodeListFile.close();
00387 }
00388 }
00389
00390
00391 for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00392 iter != bootstrapList.end(); iter++) {
00393 delete iter->second;
00394 }
00395
00396 bootstrapList.clear();
00397 }