feat(scheduler-core): implement record start/stop lifecycle (task 9.2)
Adds recording-state fields directly to xce_scheduler_t (no new
xce_sched_driver_t type, per task 9.1's precedent). sched_record_start()/
sched_record_stop() implement AC 10: validate via task 9.1's path
validator, open with a TOCTOU-hardened sequence (O_NOFOLLOW, no O_TRUNC,
fstat()+st_nlink==1 check before ftruncate()), snapshot the core, write
ReplayHeader+SnapshotEntry on start, ReplayEvent{endSession} on stop.
driver.c gains boolean-gated recording hooks in
xce_sched_driver_translate_pending_events() (per-event-batch ReplayEvent
writes, new recording_events.c) and xce_sched_driver_run_normal_mode_round()
(per-session ReplaySession writes, new recording_session.c) -- zero I/O/
allocation when inactive.
Two real bugs found and fixed during implementation: bug-1498 (O_TRUNC
would have truncated a hard-linked victim file before the TOCTOU check
could reject it) and bug-1499 (a transient edit dropped
xce_core_signal_go(), causing a 3-way thread deadlock).
test_record_lifecycle.c decodes the full start->events->session->stop
cycle with the real capnp decoders and asserts the exact message
sequence; TOCTOU regression tests use real symlink(2)/link(2) syscalls.
25/25 scheduler suite, clang-format clean.
This commit is contained in:
parent
4e5547ee55
commit
ff8d4f416e
15 changed files with 2110 additions and 36 deletions
|
|
@ -201,6 +201,59 @@ int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Link-satisfying stubs for recording.c/recording_events.c/
|
||||
* recording_session.c's real functions -- as of scheduler-core spec task
|
||||
* 9.2, driver.c's (real, #included above)
|
||||
* xce_sched_driver_translate_pending_events()/
|
||||
* xce_sched_driver_run_normal_mode_round() reference these
|
||||
* unconditionally (the `sched.recording`/`record_ctx != NULL` gates that
|
||||
* decide whether they do real work are runtime checks INSIDE these
|
||||
* functions, not something that removes the call site itself -- the
|
||||
* linker needs the symbol regardless). This file's fixture never sets
|
||||
* `sched.recording` (memset(&sched, 0, ...) below leaves it false), so at
|
||||
* runtime xce_sched_driver_translate_pending_events() calls this stub with
|
||||
* a non-NULL `sched` (record_ctx == &sched, always non-NULL here) but
|
||||
* xce_sched_driver_run_normal_mode_round() never calls
|
||||
* sched_record_session_begin() with `sched.recording == true` -- either
|
||||
* way, these stubs never need to do real work for this file's ordering
|
||||
* proof, which is not about recording. Never links recording.c's real
|
||||
* implementations (they need xce_sched_core_save_snapshot(), snapshot.c,
|
||||
* an even bigger dependency surface this file's own fixture doesn't
|
||||
* otherwise need). */
|
||||
int sched_record_write_events(xce_scheduler_t* sched, xce_core_event_t* events,
|
||||
int n)
|
||||
{
|
||||
(void)sched;
|
||||
(void)events;
|
||||
(void)n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sched_record_session_ctx_t* sched_record_session_begin(xce_scheduler_t* sched,
|
||||
uint64_t begin_round_ts)
|
||||
{
|
||||
(void)sched;
|
||||
(void)begin_round_ts;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sched_record_session_add_decision(sched_record_session_ctx_t* ctx,
|
||||
uint64_t ts, xce_decision_t* decision)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)ts;
|
||||
(void)decision;
|
||||
}
|
||||
|
||||
int sched_record_session_end(xce_scheduler_t* sched,
|
||||
sched_record_session_ctx_t* ctx, uint64_t end_ts)
|
||||
{
|
||||
(void)sched;
|
||||
(void)ctx;
|
||||
(void)end_ts;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Real reimplementation of schedobj.c's sched_resolve_job_picker -- see
|
||||
* file header comment (same rationale/algorithm as test_core_full_cycle.c's
|
||||
* own copy). */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue