UnderlayConfigurator.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 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 <omnetpp.h>
00025 #include <GlobalNodeListAccess.h>
00026 #include <ChurnGeneratorAccess.h>
00027 #include <GlobalStatisticsAccess.h>
00028 
00029 #include "UnderlayConfigurator.h"
00030 
00031 const int32_t UnderlayConfigurator::NUM_COLORS=8;
00032 const char* UnderlayConfigurator::colorNames[] = {
00033      "red", "green", "yellow", "brown", "grey", "violet", "pink", "orange"};
00034 
00035 
00036 UnderlayConfigurator::UnderlayConfigurator()
00037 {
00038     endSimulationTimer = NULL;
00039     endSimulationNotificationTimer = NULL;
00040     endTransitionTimer = NULL;
00041     initFinishedTime.tv_sec = 0;
00042     initFinishedTime.tv_usec = 0;
00043 }
00044 
00045 UnderlayConfigurator::~UnderlayConfigurator()
00046 {
00047     cancelAndDelete(endSimulationNotificationTimer);
00048     cancelAndDelete(endSimulationTimer);
00049     cancelAndDelete(endTransitionTimer);
00050 }
00051 
00052 int UnderlayConfigurator::numInitStages() const
00053 {
00054     return MAX_STAGE_UNDERLAY + 1;
00055 }
00056 
00057 void UnderlayConfigurator::initialize(int stage)
00058 {
00059     if (stage == MIN_STAGE_UNDERLAY) {
00060         gracefulLeaveDelay = par("gracefulLeaveDelay");
00061         gracefulLeaveProbability = par("gracefulLeaveProbability");
00062 
00063         transitionTime = par("transitionTime");
00064         measurementTime = par("measurementTime");
00065 
00066         globalNodeList = GlobalNodeListAccess().get();
00067         globalStatistics = GlobalStatisticsAccess().get();
00068 
00069         endSimulationNotificationTimer =
00070             new cMessage("endSimulationNotificationTimer");
00071         endSimulationTimer = new cMessage("endSimulationTimer");
00072         endTransitionTimer = new cMessage("endTransitionTimer");
00073 
00074         gettimeofday(&initStartTime, NULL);
00075         init = true;
00076         simulationEndingSoon = false;
00077         initCounter = 0;
00078 
00079         firstNodeId = -1;
00080         WATCH(firstNodeId);
00081         WATCH(overlayTerminalCount);
00082     }
00083 
00084     if (stage >= MIN_STAGE_UNDERLAY && stage <= MAX_STAGE_UNDERLAY) {
00085         initializeUnderlay(stage);
00086     }
00087 
00088     if (stage == MAX_STAGE_UNDERLAY) {
00089         // Create churn generators
00090         NodeType t;
00091         t.typeID = 0;
00092 
00093         std::vector<std::string> churnGeneratorTypes =
00094             cStringTokenizer(par("churnGeneratorTypes"), " ").asVector();
00095         std::vector<std::string> terminalTypes =
00096             cStringTokenizer(par("terminalTypes"), " ").asVector();
00097 
00098         if (terminalTypes.size() != 1
00099                 && churnGeneratorTypes.size() != terminalTypes.size())
00100         {
00101             opp_error("UnderlayConfigurator.initialize(): "
00102                       "terminalTypes size does not match churnGenerator size");
00103         }
00104 
00105         for (std::vector<std::string>::iterator it =
00106                 churnGeneratorTypes.begin(); it != churnGeneratorTypes.end(); ++it) {
00107 
00108             cModuleType* genType = cModuleType::get(it->c_str());
00109 
00110             if (genType == NULL) {
00111                 throw cRuntimeError((std::string("UnderlayConfigurator::"
00112                    "initialize(): invalid churn generator: ") + *it).c_str());
00113             }
00114 
00115             ChurnGenerator* gen = check_and_cast<ChurnGenerator*>
00116                                 (genType->create("churnGenerator",
00117                                                  getParentModule(),
00118                                                  t.typeID + 1, t.typeID));
00119 
00120             // check threshold for noChurnThreshold hack
00121             gen->finalizeParameters();
00122 
00123             if ((*it == "oversim.common.LifetimeChurn" ||
00124                  *it == "oversim.common.ParetoChurn") &&
00125                 ((double)gen->par("noChurnThreshold") > 0) &&
00126                 ((double)gen->par("lifetimeMean") >=
00127                  (double)gen->par("noChurnThreshold"))) {
00128                 gen->callFinish();
00129                 gen->deleteModule();
00130                 cModuleType* genType =
00131                     cModuleType::get("oversim.common.NoChurn");
00132                 gen = check_and_cast<ChurnGenerator*>
00133                         (genType->create("churnGenerator", getParentModule(),
00134                                          t.typeID + 1, t.typeID));
00135                 gen->finalizeParameters();
00136                 EV << "[UnderlayConfigurator::initialize()]\n"
00137                    << "    churnGenerator[" << t.typeID
00138                    << "]: \"oversim.common.NoChurn\" is used instead of \""
00139                    << *it << "\"!\n    (lifetimeMean exceeds noChurnThreshold)"
00140                    << endl;
00141             }
00142 
00143             // Add it to the list of generators and initialize it
00144             churnGenerator.push_back(gen);
00145             t.terminalType = (terminalTypes.size() == 1) ?
00146                 terminalTypes[0] :
00147                 terminalTypes[it - churnGeneratorTypes.begin()];
00148 
00149             gen->setNodeType(t);
00150             gen->buildInside();
00151             t.typeID++;
00152         }
00153     }
00154 }
00155 
00156 void UnderlayConfigurator::initFinished()
00157 {
00158     Enter_Method_Silent();
00159 
00160     if (++initCounter == churnGenerator.size() || !churnGenerator.size()) {
00161         init = false;
00162         gettimeofday(&initFinishedTime, NULL);
00163 
00164         scheduleAt(simTime() + transitionTime,
00165                 endTransitionTimer);
00166 
00167         if (measurementTime >= 0) {
00168             scheduleAt(simTime() + transitionTime + measurementTime,
00169                        endSimulationTimer);
00170 
00171             if ((transitionTime + measurementTime) < gracefulLeaveDelay) {
00172                 throw cRuntimeError("UnderlayConfigurator::initFinished():"
00173                                         " gracefulLeaveDelay must be bigger "
00174                                         "than transitionTime + measurementTime!");
00175             }
00176 
00177             scheduleAt(simTime() + transitionTime + measurementTime
00178                     - gracefulLeaveDelay,
00179                     endSimulationNotificationTimer);
00180         }
00181         consoleOut("INIT phase finished");
00182     }
00183 }
00184 
00185 void UnderlayConfigurator::handleMessage(cMessage* msg)
00186 {
00187     if (msg == endSimulationNotificationTimer) {
00188         simulationEndingSoon = true;
00189         // globalNodeList->sendNotificationToAllPeers(NF_OVERLAY_NODE_LEAVE);
00190     } else if (msg == endSimulationTimer) {
00191         endSimulation();
00192     } else if (msg == endTransitionTimer) {
00193         consoleOut("transition time finished");
00194         globalStatistics->startMeasuring();
00195     } else {
00196         handleTimerEvent(msg);
00197     }
00198 }
00199 
00200 void UnderlayConfigurator::handleTimerEvent(cMessage* msg)
00201 {
00202     delete msg;
00203 }
00204 
00205 void UnderlayConfigurator::finish()
00206 {
00207     finishUnderlay();
00208 }
00209 
00210 void UnderlayConfigurator::finishUnderlay()
00211 {
00212     //...
00213 }
00214 
00215 void UnderlayConfigurator::consoleOut(const std::string& text)
00216 {
00217     if (!ev.isGUI()) {
00218         struct timeval now, diff;
00219         gettimeofday(&now, NULL);
00220         diff = timeval_substract(now, initStartTime);
00221 
00222         std::stringstream ss;
00223         std::string line1(71, '*');
00224         std::string line2(71, '*');
00225 
00226         ss << "   " << text << "   ";
00227         line1.replace(35 - ss.str().size() / 2,
00228                       ss.str().size(),
00229                       ss.str());
00230         ss.str("");
00231 
00232         ss << "   (sim time: " << simTime()
00233            << ", real time: " << diff.tv_sec
00234            << "." << diff.tv_usec << ")   ";
00235         line2.replace(35 - ss.str().size() / 2,
00236                       ss.str().size(),
00237                       ss.str());
00238 
00239         std::cout << "\n" << line1 << "\n"
00240                   << line2 << "\n" << std::endl;
00241     } else {
00242         EV << "[UnderlayConfigurator::consoleOut()] " << text;
00243     }
00244 }
00245 
00246 ChurnGenerator* UnderlayConfigurator::getChurnGenerator(int typeID)
00247 {
00248     Enter_Method_Silent();
00249 
00250     return churnGenerator[typeID];
00251 }
00252 
00253 uint8_t UnderlayConfigurator::getChurnGeneratorNum()
00254 {
00255     Enter_Method_Silent();
00256 
00257     return churnGenerator.size();
00258 }