Slave* slave_new(Master* master, Configuration* config, guint randomSeed) { Slave* slave = g_new0(Slave, 1); MAGIC_INIT(slave); g_mutex_init(&(slave->lock)); g_mutex_init(&(slave->pluginInitLock)); slave->master = master; slave->config = config; slave->random = random_new(randomSeed); slave->rawFrequencyKHz = utility_getRawCPUFrequency(CONFIG_CPU_MAX_FREQ_FILE); if(slave->rawFrequencyKHz == 0) { info("unable to read '%s' for copying", CONFIG_CPU_MAX_FREQ_FILE); } slave->hosts = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); slave->programs = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, (GDestroyNotify)program_free); slave->dns = dns_new(); slave->nWorkers = (guint) configuration_getNWorkerThreads(config); slave->mainThreadWorker = worker_new(slave); slave->cwdPath = g_get_current_dir(); slave->dataPath = g_build_filename(slave->cwdPath, "shadow.data", NULL); slave->hostsPath = g_build_filename(slave->dataPath, "hosts", NULL); if(g_file_test(slave->dataPath, G_FILE_TEST_EXISTS)) { gboolean success = utility_removeAll(slave->dataPath); utility_assert(success); } gchar* templateDataPath = g_build_filename(slave->cwdPath, "shadow.data.template", NULL); if(g_file_test(templateDataPath, G_FILE_TEST_EXISTS)) { gboolean success = utility_copyAll(templateDataPath, slave->dataPath); utility_assert(success); } g_free(templateDataPath); return 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); }