BootstrapList.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2008 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     // load local cache list only when using SingleHostUnderlayConfigurator
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             //TODO
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     // update the lastPing field of the source node
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     // destination does not answer, remove it from the list
00232     removeBootstrapCandidate(dest);
00233 }
00234 
00235 
00236 const TransportAddress BootstrapList::getBootstrapNode()
00237 {
00238     if (!maintainList) {
00239         // TODO: add a parameter to return malicious bootstrap nodes also
00240         return overlay->globalNodeList->getRandomNode(0, true, true);
00241         // return overlay->globalNodeList->getBootstrapNode();
00242     } else {
00243         const NodeHandle *bootstrapNode = &NodeHandle::UNSPECIFIED_NODE;
00244         int i, j = 0;
00245 
00246         // pick a random node from the list
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             // if the list empty, get a bootstrap node from GlobalNodeList
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     // if node already in the list, update its lastPing and nodePrio fields
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     // if node already in the list, update its lastPing and nodePrio fields
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     // at this point, we consider this node not being able to provide the
00356     // boot service anymore, therefore we have to revoke
00357     // the service via zeroconfConnector
00358     if (zeroconfConnector) {
00359         zeroconfConnector->revokeService();
00360     }
00361 }
00362 
00363 
00364 void BootstrapList::registerBootstrapNode(const NodeHandle& node)
00365 {
00366     globalNodeList->registerPeer(node);
00367 
00368     // at this point, we consider this node as booted and therefore have to
00369     // announce the boot service for it via zeroconfConnector
00370     if (zeroconfConnector) {
00371         zeroconfConnector->announceService(node);
00372     }
00373 }
00374 
00375 
00376 void BootstrapList::finishApp()
00377 {
00378     // dump the list of bootstrap nodes into the local cache only when
00379     // using SingleHostUnderlayConfigurator
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     // delete all bootstrap nodes and clear the list
00396     for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00397          iter != bootstrapList.end(); iter++) {
00398         delete iter->second;
00399     }
00400 
00401     bootstrapList.clear();
00402 }
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3