feat(scheduler-core): add controller-side OPCode_schedAdmin dispatch (task 10.1)

Adds the spec's one and only src/controller/ change: a new
case OPCode_schedAdmin in myreq_handler() (cluster.c) that mirrors the
existing OPCode_upgradeConfig case -- primary-only gate, explicit reply
on every path, stateless pass-through with no WAL entry.

Forwards to the scheduler via a new xce_schedadmin_req() (async send,
mirrors xce_fetchfile_req) and blocks the vtask thread on a condvar with
a 5s deadline while holding c->sched.lock for the round-trip, matching
this spec's own research-phase design decision (parity with
OPCode_upgradeConfig's no-RBAC posture, blocking wait accepted for
low-frequency admin traffic). A new branch in the existing
OPCode_reply case demuxes the scheduler's SchedAdminReply to a
process-global single-slot pending-waiter mechanism, serialized by
c->sched.lock, matching job.c's existing fetchfile-proxy pattern.

Adversarial review independently traced double-free/cleanup, the
timeout/signal race, and reply-opcode demux correctness against source;
found and a follow-up round closed a narrow-window leak via a carefully
lock-ordered unlock->unregister->relock sequence (avoiding an AB-BA
inversion against schedadmin_signal()'s lock acquisition order).

New test_sched_admin_dispatch.c drives the real myreq_handler via the
existing myreq_handler_for_test seam: not-primary rejection (proven via
a poison-pointer sched.ep that would crash if forwarding were ever
attempted), not-connected rejection, and a genuine two-thread round-trip
test exercising the real signal/demux path.

Controller suite 3/3 (1090/1090 assertions), scheduler suite 26/26
unaffected, clang-format clean.
This commit is contained in:
Rongsong Shen 2026-08-06 03:38:42 +00:00
parent 2d533e652e
commit 045be6b3d6
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
7 changed files with 598 additions and 3 deletions

View file

@ -71,6 +71,15 @@ extern int xce_set_pend_reason_req(endpoint_t*, xce_preason_set_t*);
extern int xce_clear_reason_req(endpoint_t*, xce_clear_reason_t*);
extern int xce_fetchfile_req(endpoint_t*, xce_fetchfile_t*);
/*
* xce_schedadmin_req: send OPCode_schedAdmin (SchedAdminRequest) to `ep` --
* the async send half of task 10.1's controller->scheduler forward. Mirrors
* xce_fetchfile_req above exactly. The caller (myreq_handler, cluster.c)
* blocks separately for the matching SchedAdminReply; this function only
* enqueues the request, it does not wait.
*/
extern int xce_schedadmin_req(endpoint_t*, sched_admin_req_t*);
/*
* xce_replconfigpush_req_raw: send OP_replConfigPush carrying raw byte arrays.
* Bypasses the encode_ReplConfigPushRequest_ptr path (which maps sha256/bytes