Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions codes/codes-workload-config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (C) 2013 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/

#ifndef CODES_WORKLOAD_CONFIG_H
#define CODES_WORKLOAD_CONFIG_H

/**
* @file codes-workload-config.h
*
* Apply synthetic-workload parameters from a loaded config to a model main's
* option globals, with command-line precedence.
*
* The YAML front-end compiles a `workload:` shortcut or a single all-nodes
* `jobs:` entry into a WORKLOAD section (see the config compiler). A synthetic
* main calls the helpers below once, after configuration_load()/
* codes_mapping_setup(), passing each of the ROSS options it registered
* (`traffic`, `num_messages`, `arrival_time`, `payload_size`) together with that
* option's compiled-in default. For each knob the precedence is:
*
* command line > config (WORKLOAD section) > the model's built-in default
*
* Command-line detection follows the same pattern codes_mapping uses for the
* simulation end time: ROSS records no "was this option set" flag, so the helper
* compares the current global against the registered default. An unchanged value
* means the command line did not set it, so a configured value may take over; any
* other value is treated as a command-line override and left untouched. The edge
* case is the same as end_time's: passing a value equal to the default on the
* command line is indistinguishable from omitting it, so the config wins there.
*
* A legacy `.conf` run carries no WORKLOAD section, so every apply is a no-op and
* the model keeps its command-line/default behavior exactly as before.
*/

#ifdef __cplusplus
extern "C" {
#endif

/**
* Maps a friendly traffic-pattern name (as written in a YAML `workload:` block)
* to the value of a model main's own traffic enum. Each main supplies its own
* table because the pattern set and the enum values differ per model (only
* "uniform" is universally 1).
*/
struct codes_workload_traffic_name {
const char* name; /**< friendly name, e.g. "uniform" (NULL terminates a table) */
int value; /**< the main's traffic enum value for that pattern */
};

/**
* True (non-zero) if the loaded config carries a WORKLOAD section -- i.e. a YAML
* `workload:`/`jobs:` config. Legacy `.conf` configs have none.
*/
int codes_workload_config_present(void);

/**
* Abort (via tw_error) if the loaded config carries a JOBS section -- an explicit
* multi-job placement (see the config compiler). The synthetic mains generate a
* single global traffic pattern and cannot yet execute per-job placement, so
* running such a config would silently ignore it. The config still compiles and
* validates; this makes a main that cannot honor it fail loudly with guidance
* rather than misrun. A no-op for a single-workload (WORKLOAD-section) or legacy
* config. @p model_name names the model in the diagnostic.
*/
void codes_workload_config_check_unsupported_jobs(const char* model_name);

/**
* Apply an integer WORKLOAD key to @p val unless the command line already set it.
*
* @param key the WORKLOAD key name (e.g. "num_messages", "payload_size").
* @param val the option global; overwritten only when it still equals
* @p cli_default and the config provides @p key.
* @param cli_default the option's registered default (the command-line sentinel).
*/
void codes_workload_config_apply_int(const char* key, int* val, int cli_default);

/**
* Apply a floating-point WORKLOAD key to @p val unless the command line already
* set it. Semantics match codes_workload_config_apply_int (used for
* `arrival_time`, resolved to nanoseconds by the compiler).
*/
void codes_workload_config_apply_double(const char* key, double* val, double cli_default);

/**
* Apply WORKLOAD/traffic (a friendly pattern name) to @p val unless the command
* line already set it, mapping the name through @p names (a table terminated by a
* `{NULL, 0}` entry). A no-op if @p val already differs from @p cli_default or no
* traffic is configured. Aborts via tw_error if the configured name is not in
* @p names, naming the offending value.
*/
void codes_workload_config_apply_traffic(int* val, int cli_default,
const struct codes_workload_traffic_name* names);

#ifdef __cplusplus
}
#endif

#endif /* CODES_WORKLOAD_CONFIG_H */
28 changes: 27 additions & 1 deletion codes/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define SRC_COMMON_MODELCONFIG_CONFIGFILE_H

#include <stddef.h> /* size_t */
#include <stdio.h> /* FILE (cf_equal_report) */
#include <stdlib.h>

#ifdef __cplusplus
Expand Down Expand Up @@ -94,9 +95,34 @@ struct ConfigVTable {
* */
int cf_dump(struct ConfigVTable* cf, SectionHandle h, char** err);

/* Compare two config trees: return true if equal, false if not */
/**
* Compare two config trees for equality.
*
* Equality is structural and **order-insensitive**: the two trees are equal when
* they hold the same named sections and keys with the same values, regardless of
* the order entries were written -- because the config store keys every lookup by
* name (sections case-insensitively, keys case-sensitively) and never by
* position. The value *list* of a key is compared as an ordered tuple, so a
* list-valued key such as `modelnet_order` must match value-for-value in order.
*
* @return 1 if the trees are equal, 0 otherwise.
*/
int cf_equal(struct ConfigVTable* h1, struct ConfigVTable* h2);

/**
* Like cf_equal(), but on inequality writes a human-readable description of every
* divergence -- each under its `section/key` path, saying whether an entry is
* missing from one side, is a key on one side and a section on the other, or has
* differing values -- to @p report. Pass a NULL @p report for the same result
* with no output (identical to cf_equal). Intended for tests and diagnostics, so
* a failed comparison points at the exact section/key that diverged rather than
* only reporting that the trees differ.
*
* @param report stream to write the divergence report to, or NULL for none.
* @return 1 if the trees are equal, 0 otherwise.
*/
int cf_equal_report(struct ConfigVTable* h1, struct ConfigVTable* h2, FILE* report);

static inline int cf_free(struct ConfigVTable* cf) {
if (!cf)
return 1;
Expand Down
Loading
Loading