void ConfigManager::shutdown() { lockGraph(); std::vector<CfgNode*> topoNodes = graph->topoSort(); // shutdown modules for (size_t i = 0; i < topoNodes.size(); i++) { Cfg* cfg = topoNodes[i]->getCfg(); msg(MSG_INFO, "shutting down module %s (id=%u)", cfg->getName().c_str(), cfg->getID()); cfg->shutdown(true, true); } // trigger sensorManager to get the final statistics of this Vermont run if (sensorManager) { sensorManager->retrieveStatistics(true); } // disconnect the modules for (size_t i = 0; i < topoNodes.size(); i++) { CfgNode* n = topoNodes[i]; Cfg* cfg = n->getCfg(); // disconnect the module from its sources .. vector<CfgNode*> sources = graph->getSources(n); msg(MSG_INFO, "disconnecting module %s (id=%u)", cfg->getName().c_str(), cfg->getID()); for (size_t k = 0; k < sources.size(); k++) { sources[k]->getCfg()->disconnectInstances(); } } unlockGraph(); }
Graph* Connector::connect(Graph* g) { const std::vector<CfgNode*>& nodes = g->getNodes(); std::map<unsigned int, CfgNode*> id2node = getId2Node(nodes); for (unsigned int i = 0; i < nodes.size(); i++) { CfgNode* fromNode = nodes[i]; Cfg* cfg = fromNode->getCfg(); std::vector<unsigned int> nexts = cfg->getNext(); for (unsigned int j = 0; j < nexts.size(); j++) { CfgNode* toNode = id2node[nexts[j]]; if (toNode == NULL) THROWEXCEPTION("next statement is illegal; there is no node with id=%d", nexts[j]); if (connectNodes) // insert the connection in the graph g->addEdge(fromNode, toNode); msg(MSG_INFO, "Connecting module %s[Id = %d] -> %s[Id = %d]", cfg->getName().c_str(), cfg->getID(), id2node[nexts[j]]->getCfg()->getName().c_str(), id2node[nexts[j]]->getCfg()->getID()); if (connectModules) {// connect the modules DPRINTF("connecting instances"); cfg->connectInstances(toNode->getCfg()); } } } return g; }
void SensorManager::retrieveStatistics(bool ignoreshutdown) { const char* xmlpre = "<vermont>\n\t<sensorData time=\"%s\" host=\"%s\">\n"; const char* xmlpost = "\t</sensorData>\n</vermont>\n"; const char* xmlglobals = "\t\t<%s>%s</%s>\n"; string lockfile = outputFilename + ".lock"; // we must not wait for the graph lock, else there may be a race condition with // the ConfigManager while (!graphIS->tryLockGraph()) { if (smExitFlag) break; timespec timeout = { 0, 200000 }; nanosleep(&timeout, NULL); } if (!ignoreshutdown && smExitFlag) return; const char* openflags = (append ? "a" : "w"); FILE* file = fopen(outputFilename.c_str(), openflags); if (!file) { THROWEXCEPTION("failed to reopen file %s", outputFilename.c_str()); perror("error:"); } time_t curtime = time(0); char curtimestr[100]; ctime_r(&curtime, curtimestr); curtimestr[strlen(curtimestr)-1] = 0; fprintf(file, xmlpre, curtimestr, hostname); char text[100]; snprintf(text, 100, "%u", static_cast<uint32_t>(getpid())); fprintf(file, xmlglobals, "pid", text, "pid"); char lasttimestr[100]; ctime_r(&lasttime, lasttimestr); lasttimestr[strlen(lasttimestr)-1] = 0; fprintf(file, xmlglobals, "lastTime", lasttimestr, "lastTime"); #if defined(__linux__) const char* xmlglobalsuint = "\t\t<%s>%u</%s>\n"; ThreadCPUInterface::SystemInfo si = ThreadCPUInterface::getSystemInfo(); fprintf(file, "\t\t<jiffyFrequency>%llu</jiffyFrequency>\n", hertzValue); fprintf(file, xmlglobalsuint, "processorAmount", si.noCPUs, "processorAmount"); for (uint16_t i=0; i<si.sysJiffies.size(); i++) { double sysutil = (si.sysJiffies[i]-lastSystemInfo.sysJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; double userutil = (si.userJiffies[i]-lastSystemInfo.userJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; fprintf(file, "\t\t<processor id=\"%u\"><util type=\"system\">%.2f</util><util type=\"user\">%.2f</util></processor>\n", i, sysutil, userutil); } fprintf(file, "\t\t<memory><free type=\"bytes\">%llu</free><total type=\"bytes\">%llu</total></memory>\n", si.freeMemory, si.totalMemory); lastSystemInfo = si; #endif //DPRINTF("*** sensor data at %s", ctime(&curtime)); Graph* g = graphIS->getGraph(); vector<CfgNode*> nodes = g->getNodes(); vector<CfgNode*>::iterator iter = nodes.begin(); while (iter != nodes.end()) { Cfg* cfg = (*iter)->getCfg(); Sensor* s = cfg->getInstance(); vector<uint32_t> nextids = cfg->getNext(); writeSensorXML(file, s, cfg->getName().c_str(), cfg->getID(), true, curtime, lasttime, &nextids); iter++; } // iterate through all non-module sensors mutex.lock(); list<SensorEntry>::const_iterator siter = sensors.begin(); while (siter != sensors.end()) { writeSensorXML(file, siter->sensor, siter->name.c_str(), siter->id, false, curtime, lasttime, NULL); siter++; } mutex.unlock(); fprintf(file, "%s", xmlpost); fclose(file); graphIS->unlockGraph(); }
Graph* ConfigManager::reconnect(Graph* g, Graph *old) { Graph *newGraph; Graph *oldGraph; newGraph = g; oldGraph = old; vector<CfgNode*> topoOld = oldGraph->topoSort(); vector<CfgNode*> topoNew = newGraph->topoSort(); /* disconnect all modules */ for (size_t i = 0; i < topoOld.size(); i++) { topoOld[i]->getCfg()->getInstance()->preReconfiguration(); topoOld[i]->getCfg()->disconnectInstances(); msg(MSG_INFO, "Disconnecting instance: %s", topoOld[i]->getCfg()->getName().c_str()); } /* call onReconfiguration1 on all modules */ for (size_t i = 0; i < topoOld.size(); i++) { topoOld[i]->getCfg()->onReconfiguration1(); } /* call preConfiguration2 on all modules */ for (size_t i = 0; i < topoOld.size(); i++) { topoOld[i]->getCfg()->onReconfiguration2(); } // compare the nodes in the old and new graph and search for // (nearly) identical modules which could be reused for (size_t i = 0; i < topoOld.size(); i++) { Cfg* oldCfg = topoOld[i]->getCfg(); for (size_t j = 0; j < topoNew.size(); j++) { Cfg* newCfg = topoNew[j]->getCfg(); if (oldCfg->getID() == newCfg->getID()) { // possible match msg(MSG_INFO, "found a match between %s(id=%d) -> %s(id=%d)", oldCfg->getName().c_str(), oldCfg->getID(), newCfg->getName().c_str(), newCfg->getID()); // check if we could use the same module instance in the new config if (newCfg->deriveFrom(oldCfg)) { msg(MSG_INFO, "reusing %s(id=%d)", oldCfg->getName().c_str(), oldCfg->getID()); newCfg->transferInstance(oldCfg); } else { deleter_list_item delme; delme.c = oldCfg; delme.delete_after = time(NULL) + DELETER_DELAY; // current time + 20 seconds deleter_list.push_back(delme); msg(MSG_INFO, "can't reuse %s(id=%d)", oldCfg->getName().c_str(), oldCfg->getID()); } } } } /* Now that we transfered all module instances which could be reused * into the new graph, we have to build up the new connections * * The Connector will take care to call preConnect for us!!! */ Connector con(false, true); newGraph->accept(&con); return newGraph; }
void SensorManager::collectDataWorker() { time_t lasttime = time(0); char* xmlpre = "<vermont>\n\t<sensorData time=\"%s\" host=\"%s\">\n"; char* xmlpost = "\t</sensorData>\n</vermont>\n"; char* xmlglobals = "\t\t<%s>%s</%s>\n"; if (!graphIS) { THROWEXCEPTION("GraphInstanceSupplier variable graphIS MUST be set when module is started!"); } string lockfile = outputFilename + ".lock"; char hostname[100]; if (gethostname(hostname, 100) != 0) THROWEXCEPTION("failed to get hostname by gethostname()!"); registerCurrentThread(); msg(MSG_FATAL, "SensorManager: checking sensor values every %u seconds", checkInterval); while (!exitFlag) { uint32_t sleepcount = checkInterval*2; uint32_t i = 0; while (i<sleepcount && !exitFlag) { // restart nanosleep with the remaining sleep time // if we got interrupted by a signal timespec req; req.tv_sec = 0; req.tv_nsec = 50000000; while (nanosleep(&req, &req) == -1 && errno == EINTR); i++; } if (exitFlag) break; // we must not wait for the graph lock, else there may be a race condition with // the ConfigManager while (!graphIS->tryLockGraph()) { if (exitFlag) break; timespec timeout = { 0, 200000 }; nanosleep(&timeout, NULL); } if (exitFlag) break; int fdlock = open(lockfile.c_str(), O_CREAT|O_RDONLY); if (fdlock == -1) msg(MSG_DEBUG, "failed to open file %s, error code %d", lockfile.c_str(), errno); if (flock(fdlock, LOCK_EX)!=0) msg(MSG_DEBUG, "failed to activate exclusive lock on file %s (flock())", lockfile.c_str()); FILE* file = fopen(outputFilename.c_str(), "w"); if (!file) { THROWEXCEPTION("failed to reopen file %s", outputFilename.c_str()); perror("error:"); } time_t curtime = time(0); char curtimestr[100]; ctime_r(&curtime, curtimestr); curtimestr[strlen(curtimestr)-1] = 0; fprintf(file, xmlpre, curtimestr, hostname); char text[100]; snprintf(text, 100, "%u", static_cast<uint32_t>(getpid())); fprintf(file, xmlglobals, "pid", text, "pid"); char lasttimestr[100]; ctime_r(&lasttime, lasttimestr); lasttimestr[strlen(lasttimestr)-1] = 0; fprintf(file, xmlglobals, "lastTime", lasttimestr, "lastTime"); #if defined(__linux__) char* xmlglobalsuint = "\t\t<%s>%u</%s>\n"; ThreadCPUInterface::SystemInfo si = ThreadCPUInterface::getSystemInfo(); fprintf(file, xmlglobalsuint, "processorAmount", si.noCPUs, "processorAmount"); for (uint16_t i=0; i<si.sysJiffies.size(); i++) { double sysutil = (si.sysJiffies[i]-lastSystemInfo.sysJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; double userutil = (si.userJiffies[i]-lastSystemInfo.userJiffies[i])/(static_cast<double>(curtime)-lasttime)/hertzValue*100; fprintf(file, "\t\t<processor id=\"%u\"><util type=\"system\">%.2f%%</util><util type=\"user\">%.2f%%</util></processor>\n", i, sysutil, userutil); } fprintf(file, "\t\t<memory><free type=\"bytes\">%llu</free><total type=\"bytes\">%llu</total></memory>\n", si.freeMemory, si.totalMemory); lastSystemInfo = si; #endif DPRINTF("*** sensor data at %s", ctime(&curtime)); Graph* g = graphIS->getGraph(); vector<CfgNode*> nodes = g->getNodes(); vector<CfgNode*>::iterator iter = nodes.begin(); while (iter != nodes.end()) { Cfg* cfg = (*iter)->getCfg(); Sensor* s = cfg->getInstance(); vector<uint32_t> nextids = cfg->getNext(); writeSensorXML(file, s, cfg->getName().c_str(), cfg->getID(), true, curtime, lasttime, &nextids); iter++; } // iterate through all non-module sensors mutex.lock(); list<SensorEntry>::const_iterator siter = sensors.begin(); while (siter != sensors.end()) { writeSensorXML(file, siter->sensor, siter->name.c_str(), siter->id, false, curtime, lasttime, NULL); siter++; } mutex.unlock(); fprintf(file, xmlpost); fclose(file); close(fdlock); lasttime = time(0); graphIS->unlockGraph(); } unregisterCurrentThread(); }
Graph* Connector::connect(Graph* g) { const std::vector<CfgNode*>& nodes = g->getNodes(); std::map<unsigned int, CfgNode*> id2node = getId2Node(nodes); //add a ConnectionQueue to every Module which has more predecessors vector<Cfg*> check; for (unsigned int i = 0; i < nodes.size(); i++) { vector<unsigned int> nexts = nodes[i]->getCfg()->getNext(); for (unsigned int j = 0; j < nexts.size(); j++){ Cfg* successor = id2node[nexts[j]]->getCfg(); bool found = false; for(unsigned int k = 0; k < check.size(); k++){ if(check[k] == successor){ found = true; msg(MSG_INFO, "Creating ConnectionQueue for module %s[Id = %d] because of multiple predecessors", successor->getName().c_str(), successor->getID()); successor->getQueueInstance(true); break; } } if(!found) check.push_back(successor); } } //connect modules for (unsigned int i = 0; i < nodes.size(); i++) { CfgNode* fromNode = nodes[i]; Cfg* cfg = fromNode->getCfg(); std::vector<unsigned int> nexts = cfg->getNext(); if (nexts.size()==0) { cfg->setupWithoutSuccessors(); } else { for (unsigned int j = 0; j < nexts.size(); j++) { CfgNode* toNode = id2node[nexts[j]]; if (toNode == NULL) THROWEXCEPTION("next statement is illegal; there is no node with id=%d", nexts[j]); if (connectNodes) // insert the connection in the graph g->addEdge(fromNode, toNode); msg(MSG_INFO, "Connecting module %s[Id = %d/%08X] -> %s[Id = %d/%08X]", cfg->getName().c_str(), cfg->getID(), cfg->getInstance(), id2node[nexts[j]]->getCfg()->getName().c_str(), id2node[nexts[j]]->getCfg()->getID(), id2node[nexts[j]]->getCfg()->getInstance()); if (connectModules) {// connect the modules DPRINTF("connecting instances"); cfg->connectInstances(toNode->getCfg()); } } } } return g; }