GlobalTraceManager.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 <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <fcntl.h>
00027 #include <errno.h>
00028 #ifndef _WIN32
00029 #include <sys/mman.h>
00030 #endif
00031 
00032 #include <UnderlayConfiguratorAccess.h>
00033 #include <GlobalNodeListAccess.h>
00034 #include <GlobalTraceManager_m.h>
00035 #include <TraceChurn.h>
00036 
00037 #include "GlobalTraceManager.h"
00038 
00039 Define_Module(GlobalTraceManager);
00040 
00041 void GlobalTraceManager::initialize(int stage)
00042 {
00043     Enter_Method_Silent();
00044 
00045     // Nothing to do for us if there is no traceFile
00046     if (strlen(par("traceFile")) == 0)
00047         return;
00048 
00049     underlayConfigurator = UnderlayConfiguratorAccess().get();
00050     globalNodeList = GlobalNodeListAccess().get();
00051 
00052     offset = 0;
00053 
00054     // Open file and get size
00055     fd = open(par("traceFile"), O_RDONLY);
00056 
00057     if (!fd) {
00058         throw cRuntimeError(("Can't open file " + par("traceFile").stdstringValue() +
00059                 std::string(strerror(errno))).c_str());
00060     }
00061 
00062     struct stat filestat;
00063 
00064     if (fstat(fd, &filestat)) {
00065         throw cRuntimeError(("Error calling stat: " + std::string(strerror(errno))).c_str());
00066     }
00067 
00068     filesize = filestat.st_size;
00069     remain = filesize;
00070     EV << "[GlobalTraceManager::initialize()]\n"
00071        << "    Successfully opened trace file " << par("traceFile").stdstringValue()
00072        << ". Size: " << filesize
00073        << endl;
00074 
00075     nextRead = new cMessage("NextRead");
00076     scheduleAt(0, nextRead);
00077 
00078 }
00079 
00080 GlobalTraceManager::GlobalTraceManager()
00081 {
00082     nextRead = NULL;
00083 }
00084 
00085 GlobalTraceManager::~GlobalTraceManager()
00086 {
00087     cancelAndDelete(nextRead);
00088 }
00089 
00090 void GlobalTraceManager::readNextBlock()
00091 {
00092 #ifdef _WIN32
00093         // TODO: port for MINGW
00094         throw cRuntimeError("GlobalTraceManager::readNextBlock():"
00095                         "Not available on WIN32 yet!");
00096 #else
00097         double time = -1;
00098     int nodeID;
00099     char* bufend;
00100     int line = 1;
00101 
00102     if (remain > 0) {
00103         // If rest of the file is bigger than maximal chunk size, set chunksize
00104         // to max; the last mapped page is used as margin.
00105         // Else map the whole remainder of the file at a time, no margin is needed
00106         // in this case
00107         chunksize = remain < getpagesize()*readPages ? remain : getpagesize()*readPages;
00108         marginsize = remain == chunksize ? 0 : getpagesize();
00109 
00110         start = (char*) mmap(0, chunksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, filesize - remain);
00111 
00112         if (start == MAP_FAILED) {
00113             throw cRuntimeError(("Error mapping file to memory:" +
00114                     std::string(strerror(errno))).c_str());
00115         }
00116 
00117         buf = start + offset;
00118         // While the read pointer has not reached the margin, continue parsing
00119         while( buf < start + chunksize - marginsize) { // FIXME: Assuming max line length of getpagesize()
00120 
00121             time = strtod(buf, &bufend);
00122             if (bufend==buf) {
00123                 throw cRuntimeError("Error parsing file: Expected time as double");
00124             }
00125             buf = bufend;
00126 
00127             nodeID = strtol(buf, &bufend, 0);
00128             if (bufend==buf) {
00129                 throw cRuntimeError("Error parsing file: Expected ID as long int");
00130             }
00131             buf = bufend;
00132 
00133             while( isspace(buf[0]) ) buf++;
00134 
00135             bufend = strchr(buf, '\n');
00136             if (!bufend) {
00137                 throw cRuntimeError("Error parsing file: Missing command or no newline at end of line!");
00138             }
00139             bufend[0]='\0';
00140             scheduleNextEvent(time, nodeID, buf, line++);
00141             buf += strlen(buf)+1;
00142 
00143             while( isspace(buf[0]) ) buf++;
00144         }
00145 
00146         // Compute offset for the next read
00147         offset = (buf - start) - (chunksize - marginsize);
00148         remain -= chunksize - marginsize;
00149         munmap( start, chunksize );
00150     }
00151 
00152     if (time > 0) {
00153         scheduleAt(time, nextRead);
00154     } else {
00155         // TODO: Schedule simulation end?
00156     }
00157 #endif
00158 }
00159 
00160 void GlobalTraceManager::scheduleNextEvent(double time, int nodeId, char* buf, int line)
00161 {
00162     GlobalTraceManagerMessage* msg = new GlobalTraceManagerMessage(buf);
00163 
00164     msg->setInternalNodeId(nodeId);
00165     msg->setLineNumber(line);
00166     scheduleAt(time, msg);
00167 }
00168 
00169 void GlobalTraceManager::createNode(int nodeId)
00170 {
00171     check_and_cast<TraceChurn*>(underlayConfigurator->getChurnGenerator(0))
00172                                                             ->createNode(nodeId);
00173 }
00174 
00175 void GlobalTraceManager::deleteNode(int nodeId)
00176 {
00177     // TODO: calculate proper deletion time with *.underlayConfigurator.gracefulLeaveDelay
00178     check_and_cast<TraceChurn*>(underlayConfigurator->getChurnGenerator(0))
00179                                                             ->deleteNode(nodeId);
00180 }
00181 
00182 void GlobalTraceManager::handleMessage(cMessage* msg)
00183 {
00184     if (!msg->isSelfMessage()) {
00185         delete msg;
00186         return;
00187     } else if ( msg == nextRead ) {
00188         readNextBlock();
00189         return;
00190     }
00191 
00192     GlobalTraceManagerMessage* traceMsg = check_and_cast<GlobalTraceManagerMessage*>(msg);
00193 
00194     if (strstr(traceMsg->getName(), "JOIN") == traceMsg->getName()) {
00195         createNode(traceMsg->getInternalNodeId());
00196     } else if (strstr(traceMsg->getName(), "LEAVE") == traceMsg->getName()) {
00197         deleteNode(traceMsg->getInternalNodeId());
00198     } else if (strstr(traceMsg->getName(), "CONNECT_NODETYPES") == traceMsg->getName()) {
00199         std::vector<std::string> strVec = cStringTokenizer(msg->getName()).asVector();
00200 
00201         if (strVec.size() != 3) {
00202             throw cRuntimeError("GlobalTraceManager::"
00203                                  "handleMessage(): Invalid command");
00204         }
00205 
00206         int firstNodeType = atoi(strVec[1].c_str());
00207         int secondNodeType = atoi(strVec[2].c_str());
00208 
00209         globalNodeList->connectNodeTypes(firstNodeType, secondNodeType);
00210     } else if (strstr(traceMsg->getName(), "DISCONNECT_NODETYPES") == traceMsg->getName()) {
00211         std::vector<std::string> strVec = cStringTokenizer(msg->getName()).asVector();
00212 
00213         if (strVec.size() != 3) {
00214             throw cRuntimeError("GlobalTraceManager::"
00215                                  "handleMessage(): Invalid command");
00216         }
00217 
00218         int firstNodeType = atoi(strVec[1].c_str());
00219         int secondNodeType = atoi(strVec[2].c_str());
00220 
00221         globalNodeList->disconnectNodeTypes(firstNodeType, secondNodeType);
00222     } else if (strstr(traceMsg->getName(), "MERGE_BOOTSTRAPNODES") == traceMsg->getName()) {
00223         std::vector<std::string> strVec = cStringTokenizer(msg->getName()).asVector();
00224 
00225         if (strVec.size() != 4) {
00226             throw cRuntimeError("GlobalTraceManager::"
00227                                  "handleMessage(): Invalid command");
00228         }
00229 
00230         int toPartition = atoi(strVec[1].c_str());
00231         int fromPartition = atoi(strVec[2].c_str());
00232         int numNodes = atoi(strVec[3].c_str());
00233 
00234         globalNodeList->mergeBootstrapNodes(toPartition, fromPartition, numNodes);
00235     } else {
00236         sendDirect(msg, getAppGateById(traceMsg->getInternalNodeId()));
00237         return; // don't delete Message
00238     }
00239 
00240     delete msg;
00241 }
00242 
00243 cGate* GlobalTraceManager::getAppGateById(int nodeId) {
00244     return check_and_cast<TraceChurn*>(underlayConfigurator->getChurnGenerator(0))
00245                                                                 ->getAppGateById(nodeId);
00246 }
00247 
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3