#include <GlobalTraceManager.h>
If trace includes user action, send actions to application
Public Member Functions | |
void | handleMessage (cMessage *msg) |
void | initialize (int stage) |
Protected Member Functions | |
void | readNextBlock () |
void | scheduleNextEvent (double time, int nodeId, char *buf, int line) |
void | createNode (int nodeId) |
void | deleteNode (int nodeId) |
cGate * | getAppGateById (int nodeId) |
Protected Attributes | |
UnderlayConfigurator * | underlayConfigurator |
BootstrapOracle * | bootstrapOracle |
pointer to BootstrapOracle | |
Private Attributes | |
int | fd |
int | filesize |
int | chunksize |
int | remain |
int | marginsize |
int | offset |
char * | buf |
char * | start |
cMessage * | nextRead |
Static Private Attributes | |
static const int | readPages = 32 |
void GlobalTraceManager::handleMessage | ( | cMessage * | msg | ) |
00151 { 00152 if (!msg->isSelfMessage()) { 00153 delete msg; 00154 return; 00155 } else if ( msg == nextRead ) { 00156 readNextBlock(); 00157 return; 00158 } 00159 00160 GlobalTraceManagerMessage* traceMsg = check_and_cast<GlobalTraceManagerMessage*>(msg); 00161 00162 if (strstr(traceMsg->name(), "JOIN") == traceMsg->name()) { 00163 createNode(traceMsg->getInternalNodeId()); 00164 } else if (strstr(traceMsg->name(), "LEAVE") == traceMsg->name()) { 00165 deleteNode(traceMsg->getInternalNodeId()); 00166 } else if (strstr(traceMsg->name(), "CONNECT_NODETYPES") == traceMsg->name()) { 00167 std::vector<std::string> strVec = cStringTokenizer(msg->name()).asVector(); 00168 00169 if (strVec.size() != 3) { 00170 throw new cException("GlobalTraceManager::" 00171 "handleMessage(): Invalid command"); 00172 } 00173 00174 int firstNodeType = atoi(strVec[1].c_str()); 00175 int secondNodeType = atoi(strVec[2].c_str()); 00176 00177 bootstrapOracle->connectNodeTypes(firstNodeType, secondNodeType); 00178 } else if (strstr(traceMsg->name(), "DISCONNECT_NODETYPES") == traceMsg->name()) { 00179 std::vector<std::string> strVec = cStringTokenizer(msg->name()).asVector(); 00180 00181 if (strVec.size() != 3) { 00182 throw new cException("GlobalTraceManager::" 00183 "handleMessage(): Invalid command"); 00184 } 00185 00186 int firstNodeType = atoi(strVec[1].c_str()); 00187 int secondNodeType = atoi(strVec[2].c_str()); 00188 00189 bootstrapOracle->disconnectNodeTypes(firstNodeType, secondNodeType); 00190 } else if (strstr(traceMsg->name(), "MERGE_BOOTSTRAPNODES") == traceMsg->name()) { 00191 std::vector<std::string> strVec = cStringTokenizer(msg->name()).asVector(); 00192 00193 if (strVec.size() != 4) { 00194 throw new cException("GlobalTraceManager::" 00195 "handleMessage(): Invalid command"); 00196 } 00197 00198 int toPartition = atoi(strVec[1].c_str()); 00199 int fromPartition = atoi(strVec[2].c_str()); 00200 int numNodes = atoi(strVec[3].c_str()); 00201 00202 bootstrapOracle->mergeBootstrapNodes(toPartition, fromPartition, numNodes); 00203 } else { 00204 sendDirect(msg, 0, getAppGateById(traceMsg->getInternalNodeId())); 00205 return; // don't delete Message 00206 } 00207 00208 delete msg; 00209 }
void GlobalTraceManager::initialize | ( | int | stage | ) |
00029 { 00030 Enter_Method_Silent(); 00031 00032 // Nothing to do for us if there is no traceFile 00033 if (strlen(par("traceFile")) == 0) 00034 return; 00035 00036 underlayConfigurator = UnderlayConfiguratorAccess().get(); 00037 bootstrapOracle = BootstrapOracleAccess().get(); 00038 00039 offset = 0; 00040 00041 // Open file and get size 00042 fd = open(par("traceFile"), O_RDONLY); 00043 00044 if (!fd) { 00045 throw new cException(("Cant open file " + std::string(par("traceFile")) + 00046 std::string(strerror(errno))).c_str()); 00047 } 00048 00049 struct stat filestat; 00050 00051 if (fstat(fd, &filestat)) { 00052 throw new cException(("Error calling stat: " + std::string(strerror(errno))).c_str()); 00053 } 00054 00055 filesize = filestat.st_size; 00056 remain = filesize; 00057 EV << "Succesfully opened trace file " << std::string(par("traceFile")) 00058 << ". Size: " << filesize; 00059 00060 nextRead = new cMessage("NextRead"); 00061 scheduleAt(0, nextRead); 00062 00063 }
void GlobalTraceManager::readNextBlock | ( | ) | [protected] |
00066 { 00067 double time = -1; 00068 int nodeID; 00069 char* bufend; 00070 int line = 1; 00071 00072 if ( remain > 0 ) { 00073 // If rest of the file is bigger than maximal chunk size, set chunksize 00074 // to max; the last mapped page is used as margin. 00075 // Else map the whole remainder od the file at a time, no margin is needed 00076 // in this case 00077 chunksize = remain < getpagesize()*readPages ? remain : getpagesize()*readPages; 00078 marginsize = remain == chunksize ? 0 : getpagesize(); 00079 00080 start = (char*) mmap(0, chunksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, filesize - remain); 00081 if (start == MAP_FAILED) { 00082 throw new cException(("Error mapping file to memory:" + 00083 std::string(strerror(errno))).c_str()); 00084 } 00085 00086 buf = start + offset; 00087 // While the read pointer has not reached the margin, continue parsing 00088 while( buf < start + chunksize - marginsize) { // FIXME: Assuming max line length of getpagesize() 00089 00090 time = strtod(buf, &bufend); 00091 if (bufend==buf) { 00092 throw new cException("Error parsing file: Expected time as double"); 00093 } 00094 buf = bufend; 00095 00096 nodeID = strtol(buf, &bufend, 0); 00097 if (bufend==buf) { 00098 throw new cException("Error parsing file: Expected ID as long int"); 00099 } 00100 buf = bufend; 00101 00102 while( isspace(buf[0]) ) buf++; 00103 00104 bufend = strchr(buf, '\n'); 00105 if (!bufend) { 00106 throw new cException("Error parsing file: Missing command or no newline at end of line!"); 00107 } 00108 bufend[0]='\0'; 00109 scheduleNextEvent(time, nodeID, buf, line++); 00110 buf += strlen(buf)+1; 00111 00112 while( isspace(buf[0]) ) buf++; 00113 } 00114 00115 // Compute offset for the next read 00116 offset = (buf - start) - (chunksize - marginsize); 00117 remain -= chunksize - marginsize; 00118 munmap( start, chunksize ); 00119 } 00120 if (time > 0) { 00121 scheduleAt(time, nextRead); 00122 } else { 00123 // FIXME: Schedule simulation end? 00124 } 00125 }
void GlobalTraceManager::scheduleNextEvent | ( | double | time, | |
int | nodeId, | |||
char * | buf, | |||
int | line | |||
) | [protected] |
00128 { 00129 GlobalTraceManagerMessage* msg; 00130 00131 msg = new GlobalTraceManagerMessage(buf); 00132 00133 msg->setInternalNodeId(nodeId); 00134 msg->setLineNumber(line); 00135 scheduleAt(time, msg); 00136 }
void GlobalTraceManager::createNode | ( | int | nodeId | ) | [protected] |
00139 { 00140 check_and_cast<TraceChurn*>(underlayConfigurator->getChurnGenerator(0)) 00141 ->createNode(nodeId); 00142 }
void GlobalTraceManager::deleteNode | ( | int | nodeId | ) | [protected] |
00145 { 00146 check_and_cast<TraceChurn*>(underlayConfigurator->getChurnGenerator(0)) 00147 ->deleteNode(nodeId); 00148 }
cGate * GlobalTraceManager::getAppGateById | ( | int | nodeId | ) | [protected] |
00211 { 00212 return check_and_cast<TraceChurn*>(underlayConfigurator->getChurnGenerator(0)) 00213 ->getAppGateById(nodeId); 00214 }
BootstrapOracle* GlobalTraceManager::bootstrapOracle [protected] |
pointer to BootstrapOracle
int GlobalTraceManager::fd [private] |
int GlobalTraceManager::filesize [private] |
int GlobalTraceManager::chunksize [private] |
int GlobalTraceManager::remain [private] |
int GlobalTraceManager::marginsize [private] |
int GlobalTraceManager::offset [private] |
char* GlobalTraceManager::buf [private] |
char * GlobalTraceManager::start [private] |
const int GlobalTraceManager::readPages = 32 [static, private] |
cMessage* GlobalTraceManager::nextRead [private] |