gint master_run(Master* master) { MAGIC_ASSERT(master); message("loading and initializing simulation data"); /* start loading and initializing simulation data */ _master_loadConfiguration(master); gboolean isSuccess = _master_loadTopology(master); if(!isSuccess) { return 1; } _master_initializeTimeWindows(master); /* the master will be responsible for distributing the actions to the slaves so that * they all have a consistent view of the simulation, topology, etc. * For now we only have one slave so send it everything. */ guint slaveSeed = random_nextUInt(master->random); master->slave = slave_new(master, master->options, master->endTime, slaveSeed); message("registering plugins and hosts"); /* register the components needed by each slave. * this must be done after slaves are available so we can send them messages */ _master_registerPlugins(master); _master_registerHosts(master); message("running simulation"); /* dont buffer log messages in debug mode */ if(options_getLogLevel(master->options) != LOGLEVEL_DEBUG) { message("log message buffering is enabled for efficiency"); logger_setEnableBuffering(logger_getDefault(), TRUE); } /* start running each slave */ slave_run(master->slave); /* only need to disable buffering if it was enabled, otherwise * don't log the message as it may confuse the user. */ if(options_getLogLevel(master->options) != LOGLEVEL_DEBUG) { message("log message buffering is disabled during cleanup"); logger_setEnableBuffering(logger_getDefault(), FALSE); } message("simulation finished, cleaning up now"); return slave_free(master->slave); }
void master_run(Master* master) { MAGIC_ASSERT(master); guint slaveSeed = (guint)random_nextInt(master->random); Slave* slave = slave_new(master, master->config, slaveSeed); /* hook in our logging system. stack variable used to avoid errors * during cleanup below. */ GLogLevelFlags configuredLogLevel = configuration_getLogLevel(master->config); g_log_set_default_handler(logging_handleLog, &(configuredLogLevel)); GDateTime* dt_now = g_date_time_new_now_local(); gchar* dt_format = g_date_time_format(dt_now, "%F %H:%M:%S"); message("Shadow v%s initialized at %s using GLib v%u.%u.%u", SHADOW_VERSION, dt_format, (guint)GLIB_MAJOR_VERSION, (guint)GLIB_MINOR_VERSION, (guint)GLIB_MICRO_VERSION); g_date_time_unref(dt_now); g_free(dt_format); /* store parsed actions from each user-configured simulation script */ GQueue* actions = g_queue_new(); Parser* xmlParser = parser_new(); /* parse built-in examples, or input files */ gboolean success = TRUE; if(master->config->runFileExample) { GString* file = example_getFileExampleContents(); success = parser_parseContents(xmlParser, file->str, file->len, actions); g_string_free(file, TRUE); } else { /* parse all given input XML files */ while(success && g_queue_get_length(master->config->inputXMLFilenames) > 0) { GString* filename = g_queue_pop_head(master->config->inputXMLFilenames); success = parser_parseFile(xmlParser, filename, actions); } } parser_free(xmlParser); /* if there was an error parsing, bounce out */ if(success) { message("successfully parsed Shadow XML input!"); } else { g_queue_free(actions); error("error parsing Shadow XML input!"); } /* * loop through actions that were created from parsing. this will create * all the nodes, networks, applications, etc., and add an application * start event for each node to bootstrap the simulation. Note that the * plug-in libraries themselves are not loaded until a worker needs it, * since each worker will need its own private version. */ while(g_queue_get_length(actions) > 0) { Action* a = g_queue_pop_head(actions); runnable_run(a); runnable_free(a); } g_queue_free(actions); /* start running */ gint nWorkers = configuration_getNWorkerThreads(master->config); debug("starting %i-threaded engine (main + %i workers)", (nWorkers + 1), nWorkers); /* simulation mode depends on configured number of workers */ if(nWorkers > 0) { /* multi threaded, manage the other workers */ master->executeWindowStart = 0; SimulationTime jump = master_getMinTimeJump(master); master->executeWindowEnd = jump; master->nextMinJumpTime = jump; slave_runParallel(slave); } else { /* single threaded, we are the only worker */ master->executeWindowStart = 0; master->executeWindowEnd = G_MAXUINT64; slave_runSerial(slave); } debug("engine finished, cleaning up..."); slave_free(slave); }