feat(scheduler): working default record-dir, improved REPL output, job ID formatting

- Change default record_dir from /var/log/xce/ to /tmp (always exists)
- Add mkdir(record_dir, 0755) at startup for custom --record-dir paths
- Split validation_error_text into 6 distinct per-errno messages
- Accept human-readable job IDs in 'info job' via parse_jobid()
- Add 'info jobs' command to list all jobs in sim REPL
- Format job IDs with fmt_jobid() for xce_test-consistent output
- Replace printf with fprintf(stdout, ...) in all REPL files
  to bypass -Wl,--wrap=printf linker interception
This commit is contained in:
Rongsong Shen 2026-08-10 09:48:10 +00:00
parent d9d0613598
commit c705cadadc
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
8 changed files with 164 additions and 94 deletions

View file

@ -299,12 +299,17 @@ static char* validation_error_text(int rc)
{ {
switch (rc) { switch (rc) {
case -EINVAL: case -EINVAL:
case -ENAMETOOLONG:
case -ENOENT:
case -ENOTDIR:
case -EACCES:
case -EEXIST:
return "invalid record file name"; return "invalid record file name";
case -ENOENT:
return "record directory not found";
case -ENOTDIR:
return "record directory path is not a directory";
case -EACCES:
return "permission denied accessing record file";
case -EEXIST:
return "a non-file entry with this name already exists";
case -ENAMETOOLONG:
return "record file path too long";
default: default:
return NULL; return NULL;
} }

View file

@ -89,7 +89,7 @@ static struct argp_option options[] = {
* alongside the rest of normal-mode's flags, same argp pass as above. */ * alongside the rest of normal-mode's flags, same argp pass as above. */
{ "record-dir", OPT_RECORD_DIR, "DIR", 0, { "record-dir", OPT_RECORD_DIR, "DIR", 0,
"Directory for scheduler session recordings " "Directory for scheduler session recordings "
"(default: /var/log/xce/)" }, "(default: /tmp)" },
{ 0 } { 0 }
}; };
@ -184,7 +184,7 @@ int main(int argc, char* argv[])
/* Req 5 AC 10 (scheduler-core spec, task 9.1): default recording /* Req 5 AC 10 (scheduler-core spec, task 9.1): default recording
* directory when --record-dir is not given -- see scheduler.h's * directory when --record-dir is not given -- see scheduler.h's
* xce_scheduler_t.record_dir field comment. */ * xce_scheduler_t.record_dir field comment. */
char* record_dir = "/var/log/xce/"; char* record_dir = "/tmp";
xce_client_config_t config; xce_client_config_t config;
xce_cluster_config_t cluster_cfg = { 0 }; xce_cluster_config_t cluster_cfg = { 0 };
const xce_cluster_config_t* cluster_cfg_ptr = NULL; const xce_cluster_config_t* cluster_cfg_ptr = NULL;
@ -208,6 +208,16 @@ int main(int argc, char* argv[])
record_dir = arguments.record_dir; record_dir = arguments.record_dir;
} }
/* Ensure the recording directory exists. Best-effort: sched_validate_
* record_filename() will still fail with a clear message if the dir
* can't be resolved after this. Silently succeeds when it already
* exists (the default /tmp always does). */
if (mkdir(record_dir, 0755) != 0 && errno != EEXIST) {
WARN("cannot create record directory %s: %s -- recording will "
"fail until the directory exists",
record_dir, strerror(errno));
}
mylog_init(logfile, loglevel, logsize, logcount); mylog_init(logfile, loglevel, logsize, logcount);
/* Req 5 AC 9 "Mode selection" / Req 5 AC 13 "Simulation mode startup" /* Req 5 AC 9 "Mode selection" / Req 5 AC 13 "Simulation mode startup"

View file

@ -180,9 +180,9 @@ static void repl_print_banner(const xce_sched_sim_driver_t* sim)
{ {
int njobs = repl_count_jobs((xce_sched_core_t*)&(sim->core)); int njobs = repl_count_jobs((xce_sched_core_t*)&(sim->core));
printf("[sim] loaded: %d jobs, snapshot @ ts=%llu\n", njobs, fprintf(stdout, "[sim] loaded: %d jobs, snapshot @ ts=%llu\n", njobs,
(unsigned long long)sim->snapshot_ts); (unsigned long long)sim->snapshot_ts);
printf("[sim] ready. type 'help' for commands.\n"); fprintf(stdout, "[sim] ready. type 'help' for commands.\n");
} }
/* /*
@ -193,28 +193,29 @@ static void repl_print_banner(const xce_sched_sim_driver_t* sim)
*/ */
static void repl_print_help(void) static void repl_print_help(void)
{ {
printf("[sim] available commands:\n"); fprintf(stdout, "[sim] available commands:\n");
printf(" step [N] Advance N sessions (default 1), pause after.\n"); fprintf(stdout, " step [N] Advance N sessions (default 1), pause after.\n");
printf(" continue Run until next breakpoint hit or EOF.\n"); fprintf(stdout, " continue Run until next breakpoint hit or EOF.\n");
printf(" quit Exit the scheduler immediately.\n"); fprintf(stdout, " quit Exit the scheduler immediately.\n");
printf(" help Print this help listing.\n"); fprintf(stdout, " help Print this help listing.\n");
printf(" break <EVENT_TYPE> [key=value ...] Set a breakpoint.\n"); fprintf(stdout, " break <EVENT_TYPE> [key=value ...] Set a breakpoint.\n");
printf(" info break List breakpoints.\n"); fprintf(stdout, " info break List breakpoints.\n");
printf(" delete <id>|all Delete breakpoint(s).\n"); fprintf(stdout, " delete <id>|all Delete breakpoint(s).\n");
printf(" info session Simulation position.\n"); fprintf(stdout, " info session Simulation position.\n");
printf(" info job <jobid> Dump one job.\n"); fprintf(stdout, " info job <jobid> Dump one job.\n");
printf(" info queue <name>|all Dump queue(s).\n"); fprintf(stdout, " info jobs List all job IDs.\n");
printf(" info worker <name>|all Dump worker(s).\n"); fprintf(stdout, " info queue <name>|all Dump queue(s).\n");
printf(" info resource <name>|all Dump resource(s).\n"); fprintf(stdout, " info worker <name>|all Dump worker(s).\n");
printf(" info summary Quick overview.\n"); fprintf(stdout, " info resource <name>|all Dump resource(s).\n");
printf(" snapshot [FILE] Write a standalone " fprintf(stdout, " info summary Quick overview.\n");
fprintf(stdout, " snapshot [FILE] Write a standalone "
"snapshot.\n"); "snapshot.\n");
printf(" set speed <N> Set simulation speed.\n"); fprintf(stdout, " set speed <N> Set simulation speed.\n");
printf(" set output <FILE>|off Start/stop writing " fprintf(stdout, " set output <FILE>|off Start/stop writing "
"decisions.\n"); "decisions.\n");
printf(" set verify on|off Toggle decision " fprintf(stdout, " set verify on|off Toggle decision "
"verification.\n"); "verification.\n");
printf(" info config Show sim parameters.\n"); fprintf(stdout, " info config Show sim parameters.\n");
} }
/* /*
@ -281,7 +282,7 @@ static bool repl_cmd_step(xce_sched_sim_driver_t* sim, const char* line)
endptr++; endptr++;
} }
if ((endptr == rest) || (*endptr != '\0') || (n <= 0)) { if ((endptr == rest) || (*endptr != '\0') || (n <= 0)) {
printf("[sim] step: N must be a positive integer -- usage: " fprintf(stdout, "[sim] step: N must be a positive integer -- usage: "
"step [N]\n"); "step [N]\n");
return false; return false;
} }
@ -344,7 +345,7 @@ static bool repl_dispatch(xce_sched_sim_driver_t* sim, const char* line)
return repl_cmd_set(sim, line); return repl_cmd_set(sim, line);
} }
printf("[sim] unknown command: '%s' (type 'help' for a list)\n", cmd); fprintf(stdout, "[sim] unknown command: '%s' (type 'help' for a list)\n", cmd);
return false; return false;
} }

View file

@ -466,17 +466,17 @@ bool repl_cmd_break(xce_sched_sim_driver_t* sim, const char* line)
int i; int i;
if (ntok < 2) { if (ntok < 2) {
printf("[sim] break: usage: break <EVENT_TYPE> [key=value ...]\n"); fprintf(stdout, "[sim] break: usage: break <EVENT_TYPE> [key=value ...]\n");
return false; return false;
} }
if (!repl_bp_kind_from_token(tokens[1], &kind)) { if (!repl_bp_kind_from_token(tokens[1], &kind)) {
printf("[sim] break: unrecognized event type '%s'\n", tokens[1]); fprintf(stdout, "[sim] break: unrecognized event type '%s'\n", tokens[1]);
return false; return false;
} }
bp = (xce_repl_breakpoint_t*)calloc(1, sizeof(*bp)); bp = (xce_repl_breakpoint_t*)calloc(1, sizeof(*bp));
if (bp == NULL) { if (bp == NULL) {
printf("[sim] break: out of memory\n"); fprintf(stdout, "[sim] break: out of memory\n");
return false; return false;
} }
bp->kind = kind; bp->kind = kind;
@ -487,7 +487,7 @@ bool repl_cmd_break(xce_sched_sim_driver_t* sim, const char* line)
xce_repl_filter_t* grown; xce_repl_filter_t* grown;
if ((eq == NULL) || (eq == tokens[i])) { if ((eq == NULL) || (eq == tokens[i])) {
printf("[sim] break: malformed filter '%s' -- expected " fprintf(stdout, "[sim] break: malformed filter '%s' -- expected "
"key=value\n", "key=value\n",
tokens[i]); tokens[i]);
repl_breakpoint_free(bp); repl_breakpoint_free(bp);
@ -498,7 +498,7 @@ bool repl_cmd_break(xce_sched_sim_driver_t* sim, const char* line)
grown = (xce_repl_filter_t*)realloc( grown = (xce_repl_filter_t*)realloc(
bp->filters, (size_t)(bp->nfilters + 1) * sizeof(*(bp->filters))); bp->filters, (size_t)(bp->nfilters + 1) * sizeof(*(bp->filters)));
if (grown == NULL) { if (grown == NULL) {
printf("[sim] break: out of memory\n"); fprintf(stdout, "[sim] break: out of memory\n");
repl_breakpoint_free(bp); repl_breakpoint_free(bp);
return false; return false;
} }
@ -510,17 +510,17 @@ bool repl_cmd_break(xce_sched_sim_driver_t* sim, const char* line)
bp->id = ++(sim->repl_state->next_bp_id); bp->id = ++(sim->repl_state->next_bp_id);
if (!repl_breakpoints_append(sim->repl_state, bp)) { if (!repl_breakpoints_append(sim->repl_state, bp)) {
printf("[sim] break: out of memory\n"); fprintf(stdout, "[sim] break: out of memory\n");
(sim->repl_state->next_bp_id)--; (sim->repl_state->next_bp_id)--;
repl_breakpoint_free(bp); repl_breakpoint_free(bp);
return false; return false;
} }
printf("[sim] breakpoint %d set: %s", bp->id, bp->token); fprintf(stdout, "[sim] breakpoint %d set: %s", bp->id, bp->token);
for (i = 0; i < bp->nfilters; i++) { for (i = 0; i < bp->nfilters; i++) {
printf(" %s=%s", bp->filters[i].key, bp->filters[i].value); fprintf(stdout, " %s=%s", bp->filters[i].key, bp->filters[i].value);
} }
printf("\n"); fprintf(stdout, "\n");
return false; /* setting a breakpoint never hands control back */ return false; /* setting a breakpoint never hands control back */
} }
@ -535,7 +535,7 @@ bool repl_cmd_delete(xce_sched_sim_driver_t* sim, const char* line)
int ntok = repl_split_tokens(line, tokens, XCE_REPL_MAX_TOKENS); int ntok = repl_split_tokens(line, tokens, XCE_REPL_MAX_TOKENS);
if (ntok < 2) { if (ntok < 2) {
printf("[sim] delete: usage: delete <id>|all\n"); fprintf(stdout, "[sim] delete: usage: delete <id>|all\n");
return false; return false;
} }
@ -543,7 +543,7 @@ bool repl_cmd_delete(xce_sched_sim_driver_t* sim, const char* line)
int n = sim->repl_state->nbreakpoints; int n = sim->repl_state->nbreakpoints;
repl_breakpoints_clear(sim->repl_state); repl_breakpoints_clear(sim->repl_state);
printf("[sim] deleted %d breakpoint(s)\n", n); fprintf(stdout, "[sim] deleted %d breakpoint(s)\n", n);
return false; return false;
} }
@ -551,9 +551,9 @@ bool repl_cmd_delete(xce_sched_sim_driver_t* sim, const char* line)
int id = atoi(tokens[1]); int id = atoi(tokens[1]);
if (!repl_breakpoint_remove(sim->repl_state, id)) { if (!repl_breakpoint_remove(sim->repl_state, id)) {
printf("[sim] delete: no breakpoint with id %d\n", id); fprintf(stdout, "[sim] delete: no breakpoint with id %d\n", id);
} else { } else {
printf("[sim] breakpoint %d deleted\n", id); fprintf(stdout, "[sim] breakpoint %d deleted\n", id);
} }
} }
@ -587,7 +587,7 @@ void xce_repl_on_event(xce_sched_sim_driver_t* sim, xce_core_event_t* ev)
bp = repl_find_event_breakpoint(rs, ev); bp = repl_find_event_breakpoint(rs, ev);
if (bp != NULL) { if (bp != NULL) {
printf("[sim] hit breakpoint %d @ event #%llu: %s\n", bp->id, fprintf(stdout, "[sim] hit breakpoint %d @ event #%llu: %s\n", bp->id,
(unsigned long long)rs->event_index, bp->token); (unsigned long long)rs->event_index, bp->token);
repl_command_loop(sim); repl_command_loop(sim);
} }
@ -621,7 +621,7 @@ void xce_repl_on_begin_round(xce_sched_sim_driver_t* sim, uint64_t begin_round)
bp = repl_find_begin_round_breakpoint(rs); bp = repl_find_begin_round_breakpoint(rs);
if (bp != NULL) { if (bp != NULL) {
printf("[sim] hit breakpoint %d @ BEGIN_ROUND round=%llu\n", bp->id, fprintf(stdout, "[sim] hit breakpoint %d @ BEGIN_ROUND round=%llu\n", bp->id,
(unsigned long long)begin_round); (unsigned long long)begin_round);
repl_command_loop(sim); repl_command_loop(sim);
} }
@ -662,7 +662,7 @@ void xce_repl_on_decision(xce_sched_sim_driver_t* sim, xce_decision_t* d)
bp = repl_find_decision_breakpoint(&(sim->core), rs, d); bp = repl_find_decision_breakpoint(&(sim->core), rs, d);
if (bp != NULL) { if (bp != NULL) {
printf("[sim] hit breakpoint %d @ decision: %s jobid=%llu\n", bp->id, fprintf(stdout, "[sim] hit breakpoint %d @ decision: %s jobid=%llu\n", bp->id,
decision_op_name(d->op), (unsigned long long)decision_jobid(d)); decision_op_name(d->op), (unsigned long long)decision_jobid(d));
repl_command_loop(sim); repl_command_loop(sim);
} }

View file

@ -14,7 +14,7 @@
* see repl_internal.h's own "Why a split at all" section for the full * see repl_internal.h's own "Why a split at all" section for the full
* rationale behind this four-file layout. * rationale behind this four-file layout.
* *
* Owns: `info session`/`info job`/`info queue`/`info worker`/ * Owns: `info session`/`info job`/`info jobs`/`info queue`/`info worker`/
* `info resource`/`info summary`/`info break`/`info config`, and the * `info resource`/`info summary`/`info break`/`info config`, and the
* `repl_cmd_info()` dispatcher repl.c's repl_dispatch() hands off to * `repl_cmd_info()` dispatcher repl.c's repl_dispatch() hands off to
* (repl_internal.h's own extern declaration). `info config` is the * (repl_internal.h's own extern declaration). `info config` is the
@ -99,13 +99,25 @@ static const char* repl_job_state_name(uint32_t state)
*/ */
static void repl_info_job(xce_sched_sim_driver_t* sim, const char* jobid_str) static void repl_info_job(xce_sched_sim_driver_t* sim, const char* jobid_str)
{ {
uint64_t jobid = strtoull(jobid_str, NULL, 10); uint64_t jobid = 0;
xce_sched_job_t* job = sched_get_job(&(sim->core), jobid); int parsed;
xce_sched_job_t* job = NULL;
char* resreq_str = NULL; char* resreq_str = NULL;
char idbuf[64];
/* Accept human-readable "0-7-1786350309-0" format (parse_jobid) or
* raw packed 64-bit integer (strtoull fallback for backward compat). */
parsed = parse_jobid(&jobid, (char*)jobid_str);
if (parsed <= 0) {
jobid = strtoull(jobid_str, NULL, 10);
}
job = sched_get_job(&(sim->core), jobid);
if (job == NULL) { if (job == NULL) {
printf("[sim] info job: no such job %llu\n", fmt_jobid(idbuf, sizeof(idbuf), jobid);
(unsigned long long)jobid); fprintf(stdout, "[sim] info job: no such job %llu (%s)\n",
(unsigned long long)jobid, idbuf);
return; return;
} }
@ -127,9 +139,10 @@ static void repl_info_job(xce_sched_sim_driver_t* sim, const char* jobid_str)
} }
} }
printf("[sim] job %llu: state=%s queue=%s priority=%d queue_time=%lld " fmt_jobid(idbuf, sizeof(idbuf), job->jobid);
fprintf(stdout, "[sim] job %llu (%s): state=%s queue=%s priority=%d queue_time=%lld "
"resreq=%s allocs=%d\n", "resreq=%s allocs=%d\n",
(unsigned long long)job->jobid, repl_job_state_name(job->state), (unsigned long long)job->jobid, idbuf, repl_job_state_name(job->state),
(job->queue != NULL) ? job->queue->name : "(none)", job->priority, (job->queue != NULL) ? job->queue->name : "(none)", job->priority,
(long long)job->queue_time, (long long)job->queue_time,
(resreq_str != NULL) ? resreq_str : "(none)", (resreq_str != NULL) ? resreq_str : "(none)",
@ -138,6 +151,45 @@ static void repl_info_job(xce_sched_sim_driver_t* sim, const char* jobid_str)
FREEUP(resreq_str); FREEUP(resreq_str);
} }
/*
* repl_info_jobs - list all job IDs with a one-line summary per job.
* Iteration mirrors repl_count_jobs() in repl.c. Each line prints the
* packed uint64_t (usable directly in `info job <id>`) plus state and
* queue — compact enough for a few dozen jobs without scrolling off
* screen. */
static void repl_info_jobs(xce_sched_sim_driver_t* sim)
{
xce_sched_core_t* core = &(sim->core);
iterator_t it;
int count = 0;
int rc;
char idbuf[64];
rc = iter_make(&it, core->jobs);
if (rc < 0) {
fprintf(stdout, "[sim] info jobs: cannot iterate job table\n");
return;
}
fprintf(stdout, "[sim] jobs:\n");
for (;;) {
xce_sched_job_t* job = NULL;
rc = iter_next(&it, (void**)&job);
if ((rc < 0) || (rc == RTTI_ITER_NO_DATA) || (job == NULL)) {
break;
}
count++;
fmt_jobid(idbuf, sizeof(idbuf), job->jobid);
fprintf(stdout, " %-25s %s %s\n",
idbuf,
repl_job_state_name(job->state),
(job->queue != NULL) ? job->queue->name : "-");
}
fprintf(stdout, "[sim] info jobs: %d job(s)\n", count);
}
/* /*
* repl_info_queue_one - AC 22's "info queue <name>": "Dump one queue: * repl_info_queue_one - AC 22's "info queue <name>": "Dump one queue:
* priority, state (open/closed), RUNLIMIT, MAX_RUNNING, job_pick_plugin, * priority, state (open/closed), RUNLIMIT, MAX_RUNNING, job_pick_plugin,
@ -157,7 +209,7 @@ static void repl_info_queue_one(xce_sched_sim_driver_t* sim,
xce_sched_job_t* job = NULL; xce_sched_job_t* job = NULL;
int rc; int rc;
printf("[sim] queue %s: priority=%d status=%s RUNLIMIT=n/a " fprintf(stdout, "[sim] queue %s: priority=%d status=%s RUNLIMIT=n/a "
"MAX_RUNNING=n/a job_pick_plugin=%s\n", "MAX_RUNNING=n/a job_pick_plugin=%s\n",
q->name, q->priority, q->name, q->priority,
((q->status & QUEUE_STAT_CLOSED) != 0) ? "closed" : "open", ((q->status & QUEUE_STAT_CLOSED) != 0) ? "closed" : "open",
@ -174,7 +226,7 @@ static void repl_info_queue_one(xce_sched_sim_driver_t* sim,
} }
if ((job->queue != NULL) && (strcmp(job->queue->name, q->name) == 0) if ((job->queue != NULL) && (strcmp(job->queue->name, q->name) == 0)
&& JOB_IS_PEND(job->state)) { && JOB_IS_PEND(job->state)) {
printf("[sim] queued job: jobid=%llu priority=%d\n", fprintf(stdout, "[sim] queued job: jobid=%llu priority=%d\n",
(unsigned long long)job->jobid, job->priority); (unsigned long long)job->jobid, job->priority);
} }
} }
@ -209,7 +261,7 @@ static void repl_info_queue(xce_sched_sim_driver_t* sim, const char* arg)
xce_sched_queue_t* q = sched_get_queue(&(sim->core), (char*)arg); xce_sched_queue_t* q = sched_get_queue(&(sim->core), (char*)arg);
if (q == NULL) { if (q == NULL) {
printf("[sim] info queue: no such queue '%s'\n", arg); fprintf(stdout, "[sim] info queue: no such queue '%s'\n", arg);
return; return;
} }
repl_info_queue_one(sim, q); repl_info_queue_one(sim, q);
@ -243,7 +295,7 @@ static void repl_info_worker_one(xce_sched_sim_driver_t* sim,
int rc; int rc;
int i; int i;
printf("[sim] worker %s: status=%s\n", w->name, fprintf(stdout, "[sim] worker %s: status=%s\n", w->name,
(IS_WORKER_UNAVAIL(w->status)) ? "unavail" : "online"); (IS_WORKER_UNAVAIL(w->status)) ? "unavail" : "online");
rc = iter_make(&it, sim->core.resmgr); rc = iter_make(&it, sim->core.resmgr);
@ -272,7 +324,7 @@ static void repl_info_worker_one(xce_sched_sim_driver_t* sim,
used = ((used_v != NULL) && (used_v->which == XCE_VAL_NUMERIC)) used = ((used_v != NULL) && (used_v->which == XCE_VAL_NUMERIC))
? used_v->u.fvalue ? used_v->u.fvalue
: 0.0; : 0.0;
printf("[sim] resource %s: total=%.2f available=%.2f\n", rname, fprintf(stdout, "[sim] resource %s: total=%.2f available=%.2f\n", rname,
avail + used, avail); avail + used, avail);
} }
free(res_arr); free(res_arr);
@ -295,7 +347,7 @@ static void repl_info_worker_one(xce_sched_sim_driver_t* sim,
if ((ha != NULL) && (ha->host != NULL) if ((ha != NULL) && (ha->host != NULL)
&& (strcmp(ha->host, w->name) == 0)) { && (strcmp(ha->host, w->name) == 0)) {
printf("[sim] assigned job: jobid=%llu\n", fprintf(stdout, "[sim] assigned job: jobid=%llu\n",
(unsigned long long)job->jobid); (unsigned long long)job->jobid);
break; break;
} }
@ -331,7 +383,7 @@ static void repl_info_worker(xce_sched_sim_driver_t* sim, const char* arg)
xce_sched_worker_t* w = sched_get_worker(&(sim->core), (char*)arg); xce_sched_worker_t* w = sched_get_worker(&(sim->core), (char*)arg);
if (w == NULL) { if (w == NULL) {
printf("[sim] info worker: no such worker '%s'\n", arg); fprintf(stdout, "[sim] info worker: no such worker '%s'\n", arg);
return; return;
} }
repl_info_worker_one(sim, w); repl_info_worker_one(sim, w);
@ -426,7 +478,7 @@ static void repl_info_resource_one(xce_sched_sim_driver_t* sim,
iter_destroy(&it); iter_destroy(&it);
} }
printf("[sim] resource %s: valtype=%s total=%.2f available=%.2f " fprintf(stdout, "[sim] resource %s: valtype=%s total=%.2f available=%.2f "
"allocation_count=%d\n", "allocation_count=%d\n",
r->name, r->name,
(r->valtype == XCE_VAL_NUMERIC) (r->valtype == XCE_VAL_NUMERIC)
@ -465,7 +517,7 @@ static void repl_info_resource(xce_sched_sim_driver_t* sim, const char* arg)
int rc = key_find(sim->core.resmgr, (void*)arg, (void**)&r); int rc = key_find(sim->core.resmgr, (void*)arg, (void**)&r);
if (rc <= 0) { if (rc <= 0) {
printf("[sim] info resource: no such resource '%s'\n", arg); fprintf(stdout, "[sim] info resource: no such resource '%s'\n", arg);
return; return;
} }
repl_info_resource_one(sim, r); repl_info_resource_one(sim, r);
@ -553,7 +605,7 @@ static void repl_info_summary(xce_sched_sim_driver_t* sim)
} }
} }
printf("[sim] summary: %d jobs (%d pending, %d running), %d workers " fprintf(stdout, "[sim] summary: %d jobs (%d pending, %d running), %d workers "
"(%d online), %d queues, %d resources\n", "(%d online), %d queues, %d resources\n",
n_jobs, n_pending, n_running, n_workers, n_online, n_queues, n_jobs, n_pending, n_running, n_workers, n_online, n_queues,
n_resources); n_resources);
@ -575,18 +627,18 @@ static void repl_info_session(xce_sched_sim_driver_t* sim)
{ {
xce_sched_repl_state_t* rs = sim->repl_state; xce_sched_repl_state_t* rs = sim->repl_state;
printf("[sim] session: ts=%llu event_index=%llu sessions=%llu\n", fprintf(stdout, "[sim] session: ts=%llu event_index=%llu sessions=%llu\n",
(unsigned long long)xce_core_now(&(sim->core)), (unsigned long long)xce_core_now(&(sim->core)),
(unsigned long long)((rs != NULL) ? rs->event_index : 0), (unsigned long long)((rs != NULL) ? rs->event_index : 0),
(unsigned long long)((rs != NULL) ? rs->session_count : 0)); (unsigned long long)((rs != NULL) ? rs->session_count : 0));
if ((rs != NULL) && (rs->session_count > 0)) { if ((rs != NULL) && (rs->session_count > 0)) {
printf("[sim] last session: round=%llu dispatch=%d pend=%d " fprintf(stdout, "[sim] last session: round=%llu dispatch=%d pend=%d "
"preempt=%d\n", "preempt=%d\n",
(unsigned long long)rs->last_begin_round, rs->last_n_dispatch, (unsigned long long)rs->last_begin_round, rs->last_n_dispatch,
rs->last_n_pend, rs->last_n_preempt); rs->last_n_pend, rs->last_n_preempt);
} else { } else {
printf("[sim] last session: (none yet)\n"); fprintf(stdout, "[sim] last session: (none yet)\n");
} }
} }
@ -618,7 +670,7 @@ static void repl_info_config(xce_sched_sim_driver_t* sim)
output_desc = "(active, path unknown)"; output_desc = "(active, path unknown)";
} }
printf("[sim] config: speed=%llu output=%s verify=%s " fprintf(stdout, "[sim] config: speed=%llu output=%s verify=%s "
"events_processed=%llu current_ts=%llu sessions=%llu\n", "events_processed=%llu current_ts=%llu sessions=%llu\n",
(unsigned long long)sim->sim_speed_num, output_desc, (unsigned long long)sim->sim_speed_num, output_desc,
sim->verify ? "on" : "off", sim->verify ? "on" : "off",
@ -635,19 +687,19 @@ static void repl_info_break(xce_sched_sim_driver_t* sim)
int i, j; int i, j;
if ((rs == NULL) || (rs->nbreakpoints == 0)) { if ((rs == NULL) || (rs->nbreakpoints == 0)) {
printf("[sim] no breakpoints set\n"); fprintf(stdout, "[sim] no breakpoints set\n");
return; return;
} }
printf("[sim] breakpoints:\n"); fprintf(stdout, "[sim] breakpoints:\n");
for (i = 0; i < rs->nbreakpoints; i++) { for (i = 0; i < rs->nbreakpoints; i++) {
xce_repl_breakpoint_t* bp = rs->breakpoints[i]; xce_repl_breakpoint_t* bp = rs->breakpoints[i];
printf("[sim] %d: %s", bp->id, bp->token); fprintf(stdout, "[sim] %d: %s", bp->id, bp->token);
for (j = 0; j < bp->nfilters; j++) { for (j = 0; j < bp->nfilters; j++) {
printf(" %s=%s", bp->filters[j].key, bp->filters[j].value); fprintf(stdout, " %s=%s", bp->filters[j].key, bp->filters[j].value);
} }
printf("\n"); fprintf(stdout, "\n");
} }
} }
@ -666,7 +718,7 @@ bool repl_cmd_info(xce_sched_sim_driver_t* sim, const char* line)
int ntok = repl_split_tokens(line, tokens, XCE_REPL_MAX_TOKENS); int ntok = repl_split_tokens(line, tokens, XCE_REPL_MAX_TOKENS);
if (ntok < 2) { if (ntok < 2) {
printf("[sim] info: usage: info <break|session|config|job|queue|" fprintf(stdout, "[sim] info: usage: info <break|session|config|job|jobs|queue|"
"worker|resource|summary> [arg]\n"); "worker|resource|summary> [arg]\n");
return false; return false;
} }
@ -681,30 +733,32 @@ bool repl_cmd_info(xce_sched_sim_driver_t* sim, const char* line)
repl_info_summary(sim); repl_info_summary(sim);
} else if (strcmp(tokens[1], "job") == 0) { } else if (strcmp(tokens[1], "job") == 0) {
if (ntok < 3) { if (ntok < 3) {
printf("[sim] info job: usage: info job <jobid>\n"); fprintf(stdout, "[sim] info job: usage: info job <jobid>\n");
} else { } else {
repl_info_job(sim, tokens[2]); repl_info_job(sim, tokens[2]);
} }
} else if (strcmp(tokens[1], "jobs") == 0) {
repl_info_jobs(sim);
} else if (strcmp(tokens[1], "queue") == 0) { } else if (strcmp(tokens[1], "queue") == 0) {
if (ntok < 3) { if (ntok < 3) {
printf("[sim] info queue: usage: info queue <name>|all\n"); fprintf(stdout, "[sim] info queue: usage: info queue <name>|all\n");
} else { } else {
repl_info_queue(sim, tokens[2]); repl_info_queue(sim, tokens[2]);
} }
} else if (strcmp(tokens[1], "worker") == 0) { } else if (strcmp(tokens[1], "worker") == 0) {
if (ntok < 3) { if (ntok < 3) {
printf("[sim] info worker: usage: info worker <name>|all\n"); fprintf(stdout, "[sim] info worker: usage: info worker <name>|all\n");
} else { } else {
repl_info_worker(sim, tokens[2]); repl_info_worker(sim, tokens[2]);
} }
} else if (strcmp(tokens[1], "resource") == 0) { } else if (strcmp(tokens[1], "resource") == 0) {
if (ntok < 3) { if (ntok < 3) {
printf("[sim] info resource: usage: info resource <name>|all\n"); fprintf(stdout, "[sim] info resource: usage: info resource <name>|all\n");
} else { } else {
repl_info_resource(sim, tokens[2]); repl_info_resource(sim, tokens[2]);
} }
} else { } else {
printf("[sim] info: unrecognized subcommand '%s'\n", tokens[1]); fprintf(stdout, "[sim] info: unrecognized subcommand '%s'\n", tokens[1]);
} }
return false; return false;

View file

@ -140,7 +140,7 @@ bool repl_cmd_snapshot(xce_sched_sim_driver_t* sim, const char* line)
f = fopen(path, "w"); f = fopen(path, "w");
if (f == NULL) { if (f == NULL) {
printf("[sim] snapshot: failed to open '%s': %s\n", path, fprintf(stdout, "[sim] snapshot: failed to open '%s': %s\n", path,
strerror(errno)); strerror(errno));
return false; return false;
} }
@ -152,11 +152,11 @@ bool repl_cmd_snapshot(xce_sched_sim_driver_t* sim, const char* line)
fclose(f); fclose(f);
if (rc < 0) { if (rc < 0) {
printf("[sim] snapshot: failed writing to '%s': rc=%d\n", path, rc); fprintf(stdout, "[sim] snapshot: failed writing to '%s': rc=%d\n", path, rc);
return false; return false;
} }
printf("[sim] snapshot written: %s (ts=%llu)\n", path, fprintf(stdout, "[sim] snapshot written: %s (ts=%llu)\n", path,
(unsigned long long)ts); (unsigned long long)ts);
return false; return false;
@ -200,13 +200,13 @@ static bool repl_set_speed(xce_sched_sim_driver_t* sim, const char* value)
uint64_t n; uint64_t n;
if (value[0] == '\0') { if (value[0] == '\0') {
printf("[sim] set speed: usage: set speed <N>\n"); fprintf(stdout, "[sim] set speed: usage: set speed <N>\n");
return false; return false;
} }
n = strtoull(value, &endptr, 10); n = strtoull(value, &endptr, 10);
if (*endptr != '\0') { if (*endptr != '\0') {
printf("[sim] set speed: '%s' is not a valid non-negative integer\n", fprintf(stdout, "[sim] set speed: '%s' is not a valid non-negative integer\n",
value); value);
return false; return false;
} }
@ -216,7 +216,7 @@ static bool repl_set_speed(xce_sched_sim_driver_t* sim, const char* value)
sim->sim_speed_num = n; sim->sim_speed_num = n;
sim->sim_speed_den = 1; sim->sim_speed_den = 1;
printf("[sim] speed set to %llu\n", (unsigned long long)n); fprintf(stdout, "[sim] speed set to %llu\n", (unsigned long long)n);
return false; return false;
} }
@ -250,7 +250,7 @@ static bool repl_set_output_off(xce_sched_sim_driver_t* sim)
xce_sched_repl_state_t* rs = sim->repl_state; xce_sched_repl_state_t* rs = sim->repl_state;
if (sim->record_file == NULL) { if (sim->record_file == NULL) {
printf("[sim] set output: already off\n"); fprintf(stdout, "[sim] set output: already off\n");
return false; return false;
} }
@ -261,12 +261,12 @@ static bool repl_set_output_off(xce_sched_sim_driver_t* sim)
if ((rs != NULL) && (rs->output_path != NULL)) { if ((rs != NULL) && (rs->output_path != NULL)) {
uint64_t n = rs->event_index - rs->output_start_event_index; uint64_t n = rs->event_index - rs->output_start_event_index;
printf("[sim] output stopped: %s (%llu event(s) written)\n", fprintf(stdout, "[sim] output stopped: %s (%llu event(s) written)\n",
rs->output_path, (unsigned long long)n); rs->output_path, (unsigned long long)n);
free(rs->output_path); free(rs->output_path);
rs->output_path = NULL; rs->output_path = NULL;
} else { } else {
printf("[sim] output stopped (path/count unavailable -- was opened " fprintf(stdout, "[sim] output stopped (path/count unavailable -- was opened "
"via --sim-output before this REPL session set one)\n"); "via --sim-output before this REPL session set one)\n");
} }
@ -308,7 +308,7 @@ static bool repl_set_output_file(xce_sched_sim_driver_t* sim, const char* path)
f = fopen(path, "w"); f = fopen(path, "w");
if (f == NULL) { if (f == NULL) {
printf("[sim] set output: failed to open '%s': %s\n", path, fprintf(stdout, "[sim] set output: failed to open '%s': %s\n", path,
strerror(errno)); strerror(errno));
return false; return false;
} }
@ -316,7 +316,7 @@ static bool repl_set_output_file(xce_sched_sim_driver_t* sim, const char* path)
ts = xce_core_now(&(sim->core)); ts = xce_core_now(&(sim->core));
rc = sim_record_write_header_and_snapshot(f, &(sim->core), ts); rc = sim_record_write_header_and_snapshot(f, &(sim->core), ts);
if (rc < 0) { if (rc < 0) {
printf("[sim] set output: failed writing header/snapshot to '%s': " fprintf(stdout, "[sim] set output: failed writing header/snapshot to '%s': "
"rc=%d\n", "rc=%d\n",
path, rc); path, rc);
fclose(f); fclose(f);
@ -329,7 +329,7 @@ static bool repl_set_output_file(xce_sched_sim_driver_t* sim, const char* path)
rs->output_start_event_index = rs->event_index; rs->output_start_event_index = rs->event_index;
} }
printf("[sim] output started: %s\n", path); fprintf(stdout, "[sim] output started: %s\n", path);
return false; return false;
} }
@ -345,7 +345,7 @@ bool repl_cmd_set(xce_sched_sim_driver_t* sim, const char* line)
int ntok = repl_split_tokens(line, tokens, XCE_REPL_MAX_TOKENS); int ntok = repl_split_tokens(line, tokens, XCE_REPL_MAX_TOKENS);
if (ntok < 3) { if (ntok < 3) {
printf("[sim] set: usage: set speed <N> | set output <FILE>|off | " fprintf(stdout, "[sim] set: usage: set speed <N> | set output <FILE>|off | "
"set verify on|off\n"); "set verify on|off\n");
return false; return false;
} }
@ -365,14 +365,14 @@ bool repl_cmd_set(xce_sched_sim_driver_t* sim, const char* line)
} else if (strcmp(tokens[2], "off") == 0) { } else if (strcmp(tokens[2], "off") == 0) {
sim->verify = false; sim->verify = false;
} else { } else {
printf("[sim] set verify: usage: set verify on|off\n"); fprintf(stdout, "[sim] set verify: usage: set verify on|off\n");
return false; return false;
} }
printf("[sim] verify set to %s\n", sim->verify ? "on" : "off"); fprintf(stdout, "[sim] verify set to %s\n", sim->verify ? "on" : "off");
return false; return false;
} }
printf("[sim] set: unrecognized parameter '%s'\n", tokens[1]); fprintf(stdout, "[sim] set: unrecognized parameter '%s'\n", tokens[1]);
return false; return false;
} }