diff --git a/.kiro/specs/scheduler-dispatch-commit/tasks.md b/.kiro/specs/scheduler-dispatch-commit/tasks.md index ed2ab253..beef5e41 100644 --- a/.kiro/specs/scheduler-dispatch-commit/tasks.md +++ b/.kiro/specs/scheduler-dispatch-commit/tasks.md @@ -1,6 +1,6 @@ # Implementation Plan -- [ ] 1. Foundation: controller-side dispatch-failure classification and durable transition record +- [x] 1. Foundation: controller-side dispatch-failure classification and durable transition record - [x] 1.1 (P) Define the dispatch-failure classification used to decide whether a failed dispatch attempt should retry or fail permanently - Enumerate each distinct way a dispatch attempt to a worker can fail today (worker lookup, worker unavailable, worker not ready, invalid allocation, queue configuration lookup, the dispatch request itself failing), and classify each as either retryable (transient/environmental) or terminal (a locally invalid decision that retrying will not fix) - The classification is a pure decision with no side effects, independently testable against every known failure case without needing a live dispatch attempt @@ -22,7 +22,7 @@ - _Requirements: 4.3_ - _Boundary: Controller Dispatch-Failure Classification (retry-counter data model)_ -- [ ] 2. Core: scheduler transitions a job to running state at dispatch-commit time +- [x] 2. Core: scheduler transitions a job to running state at dispatch-commit time - No dependency on Task 1 — scheduler-side files only, independent of the controller-side foundation work above. - [x] 2.1 (P) Scheduler marks a job as running in the same operation that commits its dispatch decision - When the scheduler commits a decision to dispatch a job, the job's state becomes running immediately, in the same operation that already records the job's resource allocation — not waiting for any later confirmation @@ -38,7 +38,7 @@ - _Requirements: 3.1, 3.2, 4.4_ - _Boundary: Scheduler Dispatch-Failure Handler_ -- [ ] 3. Core: controller transitions a job to running state only once dispatch to the worker succeeds, and resolves failures +- [x] 3. Core: controller transitions a job to running state only once dispatch to the worker succeeds, and resolves failures - Sub-tasks 3.1-3.3 all restructure the same function and share its per-job lock scope, so none of them are marked parallel to each other, regardless of how disjoint their individual concerns look. - [x] 3.1 Controller commits a job's resource allocation and running-state transition together, only on a successful dispatch - The controller's existing (currently unconditional) commit of a job's resource-allocation data becomes conditional on the dispatch request to the worker actually succeeding; the job's state transition to running happens in that same successful outcome, protected against concurrent access to the job record @@ -63,14 +63,14 @@ - _Requirements: 4.1, 4.3, 4.4, 4.5_ - _Depends: 1.1, 1.3, 3.2_ -- [ ] 4. Integration: caller no longer duplicates dispatch-outcome reporting +- [x] 4. Integration: caller no longer duplicates dispatch-outcome reporting - [x] 4.1 Remove the caller's own dispatch-outcome reporting now that resolution owns it - The function that invokes a dispatch attempt for each job in a batch no longer separately reports the outcome itself — reporting is now entirely owned by the dispatch resolution added in Task 3, preventing a failed dispatch from ever producing two different, conflicting outcome reports for the same job - Observable completion: a dispatch failure that resolves as permanent produces exactly one outcome report, not two conflicting ones - _Requirements: 3.1, 4.1, 4.2_ - _Depends: 3.1, 3.2, 3.3_ -- [ ] 5. Validation: end-to-end behavior and regression +- [x] 5. Validation: end-to-end behavior and regression - [x] 5.1 End-to-end test: resource-in-use accounting survives a multi-round gap between dispatch and confirmation - Reproduce bug-1624 directly: dispatch a job, let several rounds pass before the worker confirms it started, and confirm resource-in-use totals reflect the job continuously from the round it was dispatched, matching what a same-round confirmation would have produced - Observable completion: the regression scenario passes, and fails against the pre-change code path if temporarily reverted diff --git a/src/scheduler/src/core_events.c b/src/scheduler/src/core_events.c index 1de9f521..3b3ad060 100644 --- a/src/scheduler/src/core_events.c +++ b/src/scheduler/src/core_events.c @@ -1267,6 +1267,24 @@ int xce_core_push_events(xce_sched_core_t* core, xce_core_event_t* events, } job->rusages = rusages; + /* resource-accounting.md: reconcile the job's "mem" reservation + * charge against this report's real usage. THIS is the actual + * live path (both normal-mode, driver.c, and sim/replay mode, + * sim_loop.c, translate their own rusage events into this same + * XCE_CORE_EVENT_JOB_RUSAGE core-level event) -- schedobj.c's + * sched_apply_job_rusage() duplicates this same job->rusages + * bookkeeping but is itself reachable only from scheduler.c's + * sched_update(), which has no live caller anywhere in this + * codebase (confirmed by grep) and exists only for this file's + * own test suite. A no-op (see resource.c's own doc comments) + * if the job's allocation isn't known yet or spans more than + * one host -- not errors, so not propagated as this handler's + * own result. */ + if (job->accounts != NULL) { + sched_reconcile_job_resource_usage(core, job->accounts, + rusages); + } + if ((picker != NULL) && (picker->picker_iface->on_job_rusage != NULL)) { picker->picker_iface->on_job_rusage(picker, job, rusages); diff --git a/src/scheduler/testsuite/test_admin_request.c b/src/scheduler/testsuite/test_admin_request.c index 2957e1f1..47ee501e 100644 --- a/src/scheduler/testsuite/test_admin_request.c +++ b/src/scheduler/testsuite/test_admin_request.c @@ -120,6 +120,18 @@ void kill_sched_worker(void* arg) { (void)arg; } void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } + +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} void plugin_unregister(void* arg) { (void)arg; } /* Link-satisfying stubs for scheduler.c's sched_publish_dispatch()/ diff --git a/src/scheduler/testsuite/test_core_events.c b/src/scheduler/testsuite/test_core_events.c index e3e20d7a..e333c2a4 100644 --- a/src/scheduler/testsuite/test_core_events.c +++ b/src/scheduler/testsuite/test_core_events.c @@ -58,9 +58,17 @@ /* Pull in the real xce_sched_core_init()/xce_core_push_events() under test * into this TU (white-box #include, same convention as - * test_core_jbuf_capacity_pin.c's `#include "../src/core.c"`). */ + * test_core_jbuf_capacity_pin.c's `#include "../src/core.c"`). + * + * resource.c added (bug-1740, the reconciliation wiring fix): XCE_CORE_ + * EVENT_JOB_RUSAGE now calls sched_reconcile_job_resource_usage() (that + * file), the ONLY live call site anywhere in this codebase -- the whole + * point of this file's own end-to-end test for it is to exercise the REAL + * implementation, not a stub that would silently let the wiring rot again + * unnoticed, exactly as it did the first time. */ #include "../src/core.c" #include "../src/core_events.c" +#include "../src/resource.c" void kill_sched_job(void* arg) { (void)arg; } void kill_sched_queue(void* arg) { (void)arg; } @@ -68,6 +76,19 @@ void kill_sched_worker(void* arg) { (void)arg; } void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* Link-satisfying stubs for resource.c's sched_try_alloc_on_host_() (its + * OWN callees, live in plugin.c/schedobj.c, neither pulled in here) -- same + * two stubs test_resource_accounting.c already establishes needing for the + * identical reason. Never actually invoked: this file's tests never call + * sched_try_alloc_on_hosts()/sched_try_alloc_on_host_(). */ +int plugin_prepare_allocation(void* s, xce_sched_ctx_t* c) +{ + (void)s; (void)c; return 0; +} +int sched_ctx_get_uncomit_host(xvec_t** v, xce_sched_ctx_t* c, int i) +{ + (void)v; (void)c; (void)i; return 0; +} /* dup_val - real reimplementation of snapshot_wire.c's function of the same * name (verbatim logic), needed because core_events.c's RESVALS_FULL/ @@ -1248,6 +1269,128 @@ static void test_job_rusage_applies_state_when_hook_is_null(void) TEST_ASSERT_EQUAL_PTR(&rusages, sched_get_job(&core, 7)->rusages); } +/* + * bug-1740: XCE_CORE_EVENT_JOB_RUSAGE -- the ONLY live production path for + * job rusage, per both the normal-mode driver (driver.c) and the sim/replay + * driver (sim_loop.c), which both translate their own rusage events into + * this exact core-level event type -- must actually drive resource- + * accounting.md's reservation-vs-usage reconciliation. It didn't: the + * reconciliation code was wired into schedobj.c's sched_apply_job_rusage() + * instead, a function with exactly ONE caller anywhere in this codebase + * (scheduler.c's sched_update(), itself confirmed to have NO live caller at + * all -- superseded by this file's own driver-event mechanism, per driver.c's + * own comments: "Replaces sched_update()'s inline handling"). The entire + * reconciliation feature was therefore unreachable in both normal-mode and + * sim/replay operation despite passing every unit test that called its + * functions directly -- exactly the trap of testing a function in isolation + * without a test proving the real event path actually reaches it. Fixed by + * calling sched_reconcile_job_resource_usage() directly from THIS handler. + * This test drives the full path: register "mem", join a worker, dispatch a + * job with a real 4MB "mem" allocation (core_build_job() -> make_job_account() + * populates job->accounts exactly as a genuine dispatch would), then push a + * JOB_RUSAGE report claiming 7MB actual usage (> the 4MB reservation) and + * asserts the OVERAGE (3MB) landed on the account and the pool. + */ +static void test_job_rusage_reconciles_mem_reservation_against_usage(void) +{ + xce_sched_core_t core; + xce_core_event_t event; + xce_resource_t wire_mem; + xce_worker_t wire_worker; + xce_worker_t* worker_ptrs[1]; + xce_sched_worker_t* w; + xce_resource_t* r_mem = NULL; + xce_job_t* job1; + xce_alloc_t* a_mem; + xce_host_alloc_t* h0; + xce_host_alloc_t* hallocs[1]; + xce_job_alloc_t* jalloc; + xce_sched_job_t* tracked; + xce_rusage_t ru; + xce_rusage_t* ru_ptrs[1]; + xce_job_rusages_t rusages; + int rc; + int idx[1]; + float val[1]; + + fixture_init(&core, &g_full_plugin); + + memset(&wire_mem, 0, sizeof(wire_mem)); + wire_mem.name = "mem"; + TEST_ASSERT_NOT_NULL(makeResource(core.resmgr, &wire_mem)); + TEST_ASSERT_TRUE(key_find(core.resmgr, (void*)"mem", (void**)&r_mem) >= 0); + TEST_ASSERT_NOT_NULL(r_mem); + + memset(&wire_worker, 0, sizeof(wire_worker)); + wire_worker.name = "hostA"; + wire_worker.nresvals_to_sched = 0; + worker_ptrs[0] = &wire_worker; + + memset(&event, 0, sizeof(event)); + event.type = XCE_CORE_EVENT_WORKERS_PUSH; + event.u.workers_push.nworkers = 1; + event.u.workers_push.workers = worker_ptrs; + rc = xce_core_push_events(&core, &event, 1); + TEST_ASSERT_EQUAL_INT(0, rc); + + w = sched_get_worker(&core, "hostA"); + TEST_ASSERT_NOT_NULL(w); + + /* Dispatch job 77 with a real 4MB "mem" allocation on hostA -- exactly + * what a genuine DISPATCH decision's job->allocs would carry. */ + a_mem = make_alloc((char*)"mem", NULL, 0, 4.0f, 0); + h0 = make_host_alloc((char*)"hostA", 1, make_allocs(1, a_mem)); + hallocs[0] = h0; + jalloc = make_job_alloc(77, 1, make_host_allocs(1, hallocs[0])); + + job1 = make_job(77, JOB_STAT_RUN, "normal", "alice", "proj1"); + job1->allocs = jalloc; + + memset(&event, 0, sizeof(event)); + event.type = XCE_CORE_EVENT_JOBS_PUSH; + event.u.jobs_push.njobs = 1; + event.u.jobs_push.jobs = &job1; + rc = xce_core_push_events(&core, &event, 1); + TEST_ASSERT_EQUAL_INT(0, rc); + + tracked = sched_get_job(&core, 77); + TEST_ASSERT_NOT_NULL(tracked); + TEST_ASSERT_NOT_NULL(tracked->accounts); + + /* Sanity: the reservation charge landed at dispatch time (before any + * rusage tick), matching sched_charge_account()'s existing behavior. */ + idx[0] = r_mem->idx; + get_resvals(&(w->resInUse), 1, idx, val); + TEST_ASSERT_EQUAL_FLOAT(4.0f, val[0]); + + /* Now the worker reports job 77's REAL usage: 7MB, exceeding the 4MB + * reservation. */ + memset(&ru, 0, sizeof(ru)); + ru.resname = (char*)"memory_rss"; + ru.value = 7.0f; + ru_ptrs[0] = &ru; + + memset(&rusages, 0, sizeof(rusages)); + rusages.jobid = 77; + rusages.count = 1; + rusages.usages = ru_ptrs; + + memset(&event, 0, sizeof(event)); + event.type = XCE_CORE_EVENT_JOB_RUSAGE; + event.u.job_rusage.jobid = 77; + event.u.job_rusage.rusages = &rusages; + rc = xce_core_push_events(&core, &event, 1); + TEST_ASSERT_EQUAL_INT(0, rc); + + /* The overage (3MB) must now be reflected both on the account and in + * the pool -- the whole point of this test: this ONLY happens if the + * live event handler actually calls the reconciliation code. */ + TEST_ASSERT_EQUAL_FLOAT( + 3.0f, (float)tracked->accounts->accounts[0]->accounts[0]->used); + get_resvals(&(w->resInUse), 1, idx, val); + TEST_ASSERT_EQUAL_FLOAT(7.0f, val[0]); +} + /* CONFIG_PUSH must decompose the pushed xce_conf4sched_t's embedded * queues[]/resources[]/resvals[] arrays into core state -- not just store * the config pointer and bump configver (Req 5 AC 4's CONFIG_PUSH row: @@ -1413,6 +1556,7 @@ int main(void) RUN_TEST(test_workers_push_twice_updates_existing_worker_in_place); RUN_TEST(test_workers_push_with_null_val_does_not_clobber_existing_resval); RUN_TEST(test_job_rusage_applies_state_when_hook_is_null); + RUN_TEST(test_job_rusage_reconciles_mem_reservation_against_usage); RUN_TEST(test_config_push_decomposes_queues_resources_and_resvals); RUN_TEST(test_push_events_rejects_with_ebusy_when_session_active_no_mutation); RUN_TEST(test_push_events_null_core_returns_einval); diff --git a/src/scheduler/testsuite/test_core_full_cycle.c b/src/scheduler/testsuite/test_core_full_cycle.c index 353f83a6..405e6eef 100644 --- a/src/scheduler/testsuite/test_core_full_cycle.c +++ b/src/scheduler/testsuite/test_core_full_cycle.c @@ -135,6 +135,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* dup_val - real reimplementation of snapshot_wire.c's function of the same * name (verbatim logic), needed because core_events.c's RESVALS_FULL/ * RESVALS_DELTA handlers now call it (bug-1585 fix) and this file's diff --git a/src/scheduler/testsuite/test_driver_decision_cb.c b/src/scheduler/testsuite/test_driver_decision_cb.c index 919a3243..42e0b503 100644 --- a/src/scheduler/testsuite/test_driver_decision_cb.c +++ b/src/scheduler/testsuite/test_driver_decision_cb.c @@ -68,6 +68,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* dup_val - real reimplementation of snapshot_wire.c's function of the same * name (verbatim logic), needed because core_events.c's RESVALS_FULL/ * RESVALS_DELTA handlers now call it (bug-1585 fix) and this file's diff --git a/src/scheduler/testsuite/test_driver_session_ordering.c b/src/scheduler/testsuite/test_driver_session_ordering.c index 3e5c89e1..4791a108 100644 --- a/src/scheduler/testsuite/test_driver_session_ordering.c +++ b/src/scheduler/testsuite/test_driver_session_ordering.c @@ -168,6 +168,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* dup_val - real reimplementation of snapshot_wire.c's function of the same * name (verbatim logic), needed because core_events.c's RESVALS_FULL/ * RESVALS_DELTA handlers now call it (bug-1585 fix) and this file's diff --git a/src/scheduler/testsuite/test_driver_translate.c b/src/scheduler/testsuite/test_driver_translate.c index b3a61a0d..c256eee3 100644 --- a/src/scheduler/testsuite/test_driver_translate.c +++ b/src/scheduler/testsuite/test_driver_translate.c @@ -66,6 +66,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* dup_val - real reimplementation of snapshot_wire.c's function of the same * name (verbatim logic), needed because core_events.c's RESVALS_FULL/ * RESVALS_DELTA handlers now call it (bug-1585 fix) and this file's diff --git a/src/scheduler/testsuite/test_record_lifecycle.c b/src/scheduler/testsuite/test_record_lifecycle.c index 93888b85..723c3480 100644 --- a/src/scheduler/testsuite/test_record_lifecycle.c +++ b/src/scheduler/testsuite/test_record_lifecycle.c @@ -113,6 +113,19 @@ void kill_sched_resval(xce_val_t* val) { (void)val; } * invoked (no worker is ever added here). */ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; this fixture never populates job->accounts, so the real body is + * never reached -- link-satisfying stub only, same rationale as every + * other stub in this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* Link-satisfying stubs for scheduler.c's sched_publish_dispatch()/ * sched_publish_pend_reason() -- never actually invoked (this fixture * pushes no jobs, so the driver's decision-drain loop never observes a diff --git a/src/scheduler/testsuite/test_repl_breakpoints_inspection.c b/src/scheduler/testsuite/test_repl_breakpoints_inspection.c index 9c8dd252..8a60b8a2 100644 --- a/src/scheduler/testsuite/test_repl_breakpoints_inspection.c +++ b/src/scheduler/testsuite/test_repl_breakpoints_inspection.c @@ -99,6 +99,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, diff --git a/src/scheduler/testsuite/test_repl_equivalence.c b/src/scheduler/testsuite/test_repl_equivalence.c index ed607af7..e21fd068 100644 --- a/src/scheduler/testsuite/test_repl_equivalence.c +++ b/src/scheduler/testsuite/test_repl_equivalence.c @@ -148,6 +148,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, diff --git a/src/scheduler/testsuite/test_repl_execution_control.c b/src/scheduler/testsuite/test_repl_execution_control.c index 25ddd108..17db471a 100644 --- a/src/scheduler/testsuite/test_repl_execution_control.c +++ b/src/scheduler/testsuite/test_repl_execution_control.c @@ -113,6 +113,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, diff --git a/src/scheduler/testsuite/test_repl_snapshot_params.c b/src/scheduler/testsuite/test_repl_snapshot_params.c index 656d7a2c..d00f4d18 100644 --- a/src/scheduler/testsuite/test_repl_snapshot_params.c +++ b/src/scheduler/testsuite/test_repl_snapshot_params.c @@ -77,6 +77,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, diff --git a/src/scheduler/testsuite/test_resval_ownership.c b/src/scheduler/testsuite/test_resval_ownership.c index 3186eab0..fd6c2af1 100644 --- a/src/scheduler/testsuite/test_resval_ownership.c +++ b/src/scheduler/testsuite/test_resval_ownership.c @@ -107,6 +107,18 @@ void kill_sched_resval(xce_val_t* val) free_Value(val); } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* REAL implementation -- snapshot_wire.c:37 verbatim. This is the fix under * test: core_events.c's RESVALS_FULL/RESVALS_DELTA handlers must dup_val() * before zarray_put() so the zarray owns an independent copy, not the same diff --git a/src/scheduler/testsuite/test_sim_alt_events.c b/src/scheduler/testsuite/test_sim_alt_events.c index 26e7f3ad..bb3d4c24 100644 --- a/src/scheduler/testsuite/test_sim_alt_events.c +++ b/src/scheduler/testsuite/test_sim_alt_events.c @@ -108,6 +108,19 @@ void kill_sched_resval(xce_val_t* val) { (void)val; } void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; this fixture never populates job->accounts, so the real body is + * never reached -- link-satisfying stub only, same rationale as every + * other stub in this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, xlist_t* limits) { diff --git a/src/scheduler/testsuite/test_sim_equivalence.c b/src/scheduler/testsuite/test_sim_equivalence.c index 1680f8ae..05272af6 100644 --- a/src/scheduler/testsuite/test_sim_equivalence.c +++ b/src/scheduler/testsuite/test_sim_equivalence.c @@ -175,6 +175,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* core_reset_workers()'s (core_session.c) linker dependency -- never * invoked (no worker is ever added here). */ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } diff --git a/src/scheduler/testsuite/test_sim_event_loop.c b/src/scheduler/testsuite/test_sim_event_loop.c index c8d48752..5a80d32f 100644 --- a/src/scheduler/testsuite/test_sim_event_loop.c +++ b/src/scheduler/testsuite/test_sim_event_loop.c @@ -122,6 +122,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* core_reset_workers()'s (core_session.c) linker dependency -- see * test_core_full_cycle.c's own file header comment for the same stub; * never invoked (no worker is ever added here). */ diff --git a/src/scheduler/testsuite/test_sim_record_output.c b/src/scheduler/testsuite/test_sim_record_output.c index 62a438aa..01d29a7e 100644 --- a/src/scheduler/testsuite/test_sim_record_output.c +++ b/src/scheduler/testsuite/test_sim_record_output.c @@ -93,6 +93,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, diff --git a/src/scheduler/testsuite/test_sim_session_ordering.c b/src/scheduler/testsuite/test_sim_session_ordering.c index 1861bb73..8f1a1a21 100644 --- a/src/scheduler/testsuite/test_sim_session_ordering.c +++ b/src/scheduler/testsuite/test_sim_session_ordering.c @@ -162,6 +162,19 @@ void kill_sched_resval(xce_val_t* val) { (void)val; } * invoked (no worker is ever added here). */ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; this fixture never populates job->accounts, so the real body is + * never reached -- link-satisfying stub only, same rationale as every + * other stub in this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* plugin_prepare_allocation()'s (plugin.c) linker dependency -- never * invoked (this fixture never drives real resource-matching allocation -- * same rationale test_sim_equivalence.c's own copy documents). */ diff --git a/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c b/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c index 39862082..6cf1044c 100644 --- a/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c +++ b/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c @@ -117,6 +117,20 @@ void kill_sched_resval(xce_val_t* val) { (void)val; } * added here). */ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; this fixture's own scenario keeps job->accounts NULL by design + * (see this file's own header comment), so the real body is never reached + * -- link-satisfying stub only, same rationale as every other stub in this + * block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* plugin_prepare_allocation()'s (plugin.c, the "limit" plugin category) * linker dependency -- never invoked (this file never drives real * allocation). */ diff --git a/src/scheduler/testsuite/test_sim_verify.c b/src/scheduler/testsuite/test_sim_verify.c index ee91fd9d..17bdf9e3 100644 --- a/src/scheduler/testsuite/test_sim_verify.c +++ b/src/scheduler/testsuite/test_sim_verify.c @@ -113,6 +113,18 @@ void kill_sched_user(void* arg) { (void)arg; } void kill_sched_project(void* arg) { (void)arg; } void kill_sched_resval(xce_val_t* val) { (void)val; } +/* resource-accounting.md's reconciliation (resource.c, not linked here -- + * this file only #includes core_events.c). core_events.c's + * XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts != + * NULL; link-satisfying stub only, same rationale as every other stub in + * this block (see test_job_update.c's identical stub). */ +int sched_reconcile_job_resource_usage(xce_sched_core_t* c, + xce_job_account_t* a, + xce_job_rusages_t* r) +{ + (void)c; (void)a; (void)r; return 0; +} + /* core_reset_workers()'s (core_session.c) linker dependency -- same stub * test_sim_event_loop.c/test_core_full_cycle.c already establish; never * invoked (no worker is ever added here). */