feat(scheduler-allocation): wire unsatisfiable-resreq cache into dispatch
Wrap sched_make_primary_alloc_() -- the single choke point all three primary-resreq shapes (standalone, compound-nested, alter-nested via compound delegation) already funnel through -- with a cache lookup before allocation and a cache insert on exhaustion. On a hit, pend the job immediately via the same make_pendreason()/add_job_preason() path every exhaustion case already uses, without invoking either allocator (Req 7.3, 7.4, 7.5). A nested primary has no real per-primary schedobj, so sched_primary_cache_obj_() synthesizes one on the stack per dispatch for cache-key purposes; verified memory-safe since alloc_cache.c's build_key_() copies the fingerprint/identity by value synchronously before the stack frame unwinds. Log bug-1768 (compound/alter-nested primaries never get real slot/rusage availability checks -- seqjob/parjob's prepare_allocation hooks no-op whenever ctx->schedobj->tag != XCE_RESREQ_PRIMARY) and bug-1769 (sched_make_alter_allocation() type-confuses xce_compound_schedobj_t* as xce_sched_obj_t*, a ~112-byte heap over-read, currently untested). Both are pre-existing and out of this feature's scope; discovered and confirmed while building this task's dispatch tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XYdtrEWWZfKRRGED7raEYg
This commit is contained in:
parent
9d23060b76
commit
5c022d0b4f
6 changed files with 1015 additions and 5 deletions
|
|
@ -72,7 +72,7 @@
|
|||
- _Requirements: 4.3_
|
||||
|
||||
- [ ] 5. Integration: dispatch and cache wiring
|
||||
- [ ] 5.1 (P) Wire the unsatisfiable-resreq cache around the allocator dispatch
|
||||
- [x] 5.1 (P) Wire the unsatisfiable-resreq cache around the allocator dispatch
|
||||
- Before running full allocation for a primary resource request (whether the job's own request is a primary, or one nested inside a compound or an alternative), look up its fingerprint in the cache; on a hit, pend the job immediately using the stored reason category without invoking either allocator
|
||||
- When an allocator exhausts every candidate plan, populate the cache with the job's fingerprint and the resulting reason category before pending the job
|
||||
- Observable: a job sharing an identical fingerprint and identity with a previously-exhausted job is pended immediately with the same reason category, without either allocator running
|
||||
|
|
@ -118,3 +118,7 @@
|
|||
- (4.2) `sched_host_iter_next()`'s pre-filter reads `ctx->alloc_req.host` (which `sched_check_host_satisfy()` trivially passes when `count==0`), but nothing primes it per-bucket — a fresh per-bucket host_iter scan must reset `ctx->alloc_req.host` to empty at the top of each bucket's scan (`parjob_allocator.c`'s `parjob_try_plan_()`) or it can inherit a stale want from a differently-sized prior bucket. This is SAFE, not an oversell risk: `sched_try_alloc_on_host_()` always calls `plugin_prepare_allocation()` (which repopulates `.host` from the bucket's real `ctx->nslots`) before its own authoritative `sched_check_host_satisfy()` — the reset only makes the pre-filter a one-time-per-bucket no-op, never wrong. Task 5.x (cache/dispatch wiring) doesn't touch this path, but any future allocator built on `host_iter.c` with a multi-bucket loop should reset `ctx->alloc_req.host` the same way.
|
||||
- (4.2) `parjob_allocator.c`'s `my_alloc()` guards `primary->maxTasks <= 1 → return 0` (matching Req 4 AC1's literal `maxTasks > 1` precondition) — required because a snapshot-restored job with an unpopulated `maxTasks==0` (bug-1767's pre-existing, out-of-scope gap in `snapshot_load.c`) fails seqjob's `maxTasks != 1` guard (task 3.1) and falls through to parjob; without this guard parjob's now-real `my_alloc()` creates a `ctx->reason` where the old inert stub never did, corrupting unrelated snapshot-regression assertions. Causally verified (temporarily disabled, confirmed the exact predicted failure, restored).
|
||||
- (4.2) The multi-host allocation merge (task 4.3's stated scope: "merge every claimed bucket's host allocation into a single job allocation record") is already implemented and verified as part of 4.2 — `make_job_alloc()` takes a plain runtime-sized `xce_host_alloc_t**` array, and `my_alloc()` already builds/passes it with `nhosts == nclaimed == plan->nbuckets` on every full-plan success. Task 4.3 may only need targeted verification of the job-level shared-resource-computed-once property, not new implementation — check before dispatching a full implementer round.
|
||||
- (5.1) `sched_make_primary_alloc_()` (`scheduler.c`) is the single choke point for ALL primary-resreq dispatch shapes — standalone, compound-nested, and (transitively, via `sched_make_alter_allocation()`'s delegation to `sched_make_compound_allocation()`) alter-nested. Any future dispatch-level change (cache, mode-switching, etc.) belongs there, not in the three callers.
|
||||
- (5.1) A nested primary (inside a COMPOUND/ALTER) has no real per-primary `xce_sched_obj_t`; `sched_primary_cache_obj_()` synthesizes one on the stack per dispatch for cache-key purposes. This is memory-safe (verified line-by-line): `alloc_cache.c`'s `build_key_()` copies the fingerprint and identity fields by value synchronously during the call, before the stack frame unwinds — no pointer into the caller's stack locals is ever retained.
|
||||
- (5.1) Req 7.5's "same reason category" is only exercisable in the degenerate all-zero case today: no code path anywhere in the scheduler sets `xce_job_preason_t.main_reason` to a nonzero value except this task's own new `sched_pend_from_cached_reason_()` — every existing allocator-exhaustion path only sets host/resource sub-reasons via `add_job_preason()`. If a future task wants to prove genuine (non-degenerate) category propagation, it needs a path that actually produces a nonzero `main_reason` first.
|
||||
- (5.1) Two significant, pre-existing, out-of-scope bugs were discovered and confirmed during this task's review, logged as bug-1768 (compound/alter-nested primaries never have real slot/rusage availability checked — `seqjob_prepare_allocation()`/`parjob_prepare_allocation()` both no-op when `ctx->schedobj->tag != XCE_RESREQ_PRIMARY`) and bug-1769 (`sched_make_alter_allocation()` type-confuses `xce_compound_schedobj_t*` as `xce_sched_obj_t*`, a ~112-byte heap over-read, currently completely untested — the existing test believed to cover ALTER dispatch actually parses as PRIMARY per the resreq grammar). Neither is in this feature's scope to fix; both need dedicated follow-up.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue