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_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     // 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     }
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     // update the lastPing field of the source node
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     // destination does not answer, remove it from the list
00227     removeBootstrapCandidate(dest);
00228 }
00229 
00230 
00231 const TransportAddress BootstrapList::getBootstrapNode()
00232 {
00233     if (!maintainList) {
00234         // TODO: add a parameter to return malicious bootstrap nodes also
00235         // return overlay->globalNodeList->getRandomNode(0, true, PARAMETER);
00236         return overlay->globalNodeList->getBootstrapNode();
00237     } else {
00238         const NodeHandle *bootstrapNode = &NodeHandle::UNSPECIFIED_NODE;
00239         int i, j = 0;
00240 
00241         // pick a random node from the list
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             // if the list empty, get a bootstrap node from GlobalNodeList
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     // if node already in the list, update its lastPing and nodePrio fields
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     // if node already in the list, update its lastPing and nodePrio fields
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     // at this point, we consider this node not being able to provide the
00351     // boot service anymore, therefore we have to revoke
00352     // the service via zeroconfConnector
00353     if (zeroconfConnector) {
00354         zeroconfConnector->revokeService();
00355     }
00356 }
00357 
00358 
00359 void BootstrapList::registerBootstrapNode(const NodeHandle& node)
00360 {
00361     globalNodeList->registerPeer(node);
00362 
00363     // at this point, we consider this node as booted and therefore have to
00364     // announce the boot service for it via zeroconfConnector
00365     if (zeroconfConnector) {
00366         zeroconfConnector->announceService(node);
00367     }
00368 }
00369 
00370 
00371 void BootstrapList::finishApp()
00372 {
00373     // dump the list of bootstrap nodes into the local cache only when
00374     // using SingleHostUnderlayConfigurator
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     // delete all bootstrap nodes and clear the list
00391     for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00392          iter != bootstrapList.end(); iter++) {
00393         delete iter->second;
00394     }
00395 
00396     bootstrapList.clear();
00397 }

Generated on Tue Sep 8 17:26:51 2009 for OverSim by  doxygen 1.5.8