Commit graph

1983 commits

Author SHA1 Message Date
c89e4e4520
fix(scheduler): release replay-event payloads after the simulator pushes them (bug-1884, part 2)
sim_process_replay_event_message() now hands the decoded replay event to
the caller, which keeps it beside the translated core event and frees it
after xce_core_push_events() with driver.c's release_translated_payload()
rules: a pushed config is kept by the core, and a rusages report is kept
by the job it found. An untranslatable event is freed at once, and events
after the last session are freed at the end. The payloads were an
"accepted leak" per event; exit-time leak on the reproduction replay
75,495 -> 25,807 bytes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:55:34 +00:00
880dc51007
chore(buglog): bug-1884 partial (9b61fd99)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:51:16 +00:00
9b61fd99e4
fix(scheduler): tear down the simulator and the core's registries at exit (bug-1884, part 1)
A batch --sim replay under ASAN exited 1 on 17.2 MB of LeakSanitizer
reports. This removes all but 75 KB:

- sched_sim_driver_fini() (called by main after a clean run) cancels and
  joins the picker/allocator threads like sched_fini(), closes the replay,
  alternate-events and output files, and finalizes the core. The threads'
  ids now live in core.jobpicker/allocator, as in normal mode.
- xce_sched_core_fini() destroys the plugin, job, worker, queue, user and
  project registries and the shared-resource arrays it creates.
- The seqjob/parjob sched_make_allocs() stand-ins set up only lock, nextid
  and the aliased resmgr. Each ran a full xce_sched_core_init(), which also
  replaced the process-wide string and selector tables mid-startup.
- plugin_unregister(), the plugin registry's datakiller, only runs fini_fn;
  it key_del()'d from the registry being destroyed and skipped plugins
  registered with plugin_register_core().
- The limit plugin's usage-instance table used kill_limit as datakiller on
  xce_vres_t records (bad free on destroy); kill_vres now frees the record.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:50:59 +00:00
5f8d6b5146
chore(gitea-sync): bug-1884 mirrored to Gitea (#335)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:28:06 +00:00
fcd9fc7666
chore(buglog): bug-1884 logged (ASAN --sim exits 1 on exit-time LeakSanitizer report)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:20:55 +00:00
4500ec4669
chore(gitea-sync): bug-1883 closed on Gitea (#334)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:14:19 +00:00
1fb1bcc971
docs(scheduler): parjob bucket-reset comment describes the job-level .host want after bug-1883
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:11:52 +00:00
3c446bef3f
chore(buglog): bug-1883 fixed (c10f32cc)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:09:43 +00:00
c10f32ccd8
fix(scheduler): reset the per-host want at each primary's job-level prepare pass (bug-1883)
A COMPOUND/ALTER job's primaries share one ctx. The job-level prepare pass
reset only alloc_req.shared, and the allocators append their slots want
into alloc_req.host, so a later primary's host pre-filter (and a global
limit on slots) read the previous primary's last per-host want: a 1-task
primary after a 4-task one was filtered on slots:4 and pended although a
host with its one free slot existed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:09:27 +00:00
61f948e601
chore(buglog): bug-1883 logged (Gitea #334)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:01:52 +00:00
674b29c951
chore(gitea-sync): record Gitea sync state for 4 specs and bug-1878..1882
Specs: scheduler-allocator-runner (#67: 317-319), scheduler-sim-decision-trace
(#68: 320, 324, 325), job-status-detail-display (#69: 321-323),
scheduler-sim-discrete-clock (#70: 326-328). Bugs: #329-#333.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 08:01:05 +00:00
196eb90be6
fix(gitea-sync): filter milestone issues with milestones=, adopt phase issues left by an interrupted run
Gitea ignores the singular milestone= query parameter and returns the
newest issues repo-wide, so list_issues() never filtered by milestone:
phase-state updates only saw issues on the first page. Use milestones=.

sync_spec() adopted an existing milestone but always created its three
phase issues, so a run killed between creating an issue and writing
spec.json created duplicates on the next run. Reuse an issue already in
the milestone with the same title.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 07:26:16 +00:00
cdc7b46d2d
chore(spec): libxce-alloc-preason-equality implementation complete (validation GO)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 07:02:49 +00:00
3fba376a37
chore(buglog): bug-1881 fixed; live default-settings replay proof (libxce-alloc-preason-equality 5.3)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 06:49:22 +00:00
4e57bde693
feat(libxce-alloc-preason-equality): replay reproduces the reservation start time (task 5.3)
Add test_sim_replay_reproduces_recorded_alloc_from: a recorded DISPATCH at
an epoch-scale beginRound with a sub-second part replays at the default
simulation settings with no --sim-verify mismatch, and the live allocation's
from equals beginRound in whole seconds. Share the dispatch fixture setup
of the existing tests through two helpers.

Live: 2-round HA soak recordings (11 DISPATCH decisions) replayed with
--sim-verify and no --sim-speed report 0 mismatches.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 06:48:38 +00:00
9fae9ca22a
chore(spec): scheduler-sim-discrete-clock implementation complete (validation GO); unblock libxce-alloc-preason-equality 5.3
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:44:15 +00:00
d9bc36cde3
chore(scheduler-sim-discrete-clock): HA soak with the unmodified --sim-speed=0 caller passes (task 5.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:39:47 +00:00
69e2f07811
chore(scheduler-sim-discrete-clock): full ASAN regression green, 117/117 (task 5.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:31:28 +00:00
d5527c665b
docs(scheduler-sim-discrete-clock): scheduler-core spec drops speed modes, --sim-speed deprecated, REPL speed removed (task 4.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:26:03 +00:00
66435d100d
docs(scheduler-sim-discrete-clock): deployment guide describes the event-driven sim clock and deprecated --sim-speed (task 4.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:21:11 +00:00
aa2bb6d090
feat(scheduler-sim-discrete-clock): remove the simulator speed argument and shadow copy (task 3.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:19:34 +00:00
eb5f339541
feat(scheduler-sim-discrete-clock): retire --sim-speed as a warn-once no-op, end-to-end CLI tests (task 2.3)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 05:06:06 +00:00
05320e777b
feat(scheduler-sim-discrete-clock): remove the REPL speed parameter (task 2.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 04:53:20 +00:00
3a6b503f07
feat(scheduler-sim-discrete-clock): pin the simulation clock so it moves only at recorded timestamps (task 2.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 04:41:14 +00:00
4f653d8fbe
feat(scheduler-sim-discrete-clock): --sim-speed deprecation-warning helper and discrete-clock test binary (task 1.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 04:23:46 +00:00
4b6872d053
docs(spec): scheduler-sim-discrete-clock requirements, design and tasks approved
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 04:16:17 +00:00
51736fa44f
chore(buglog): bug-1881 partial — sim-verify mismatch lines name the first difference; live replay proof pending scheduler-sim-discrete-clock
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 11:16:31 +00:00
dcf3acf32a
feat(libxce-alloc-preason-equality): full ASAN regression green (task 5.2); 5.3 blocked on scheduler-sim-discrete-clock
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 11:11:41 +00:00
a9c984775f
feat(libxce-alloc-preason-equality): drop sim verify tests that duplicate libxce alloc_eq coverage (task 5.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 11:04:19 +00:00
24b057189f
feat(libxce-alloc-preason-equality): sim verify uses public job_alloc_eq and logs the first difference (task 4.3)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 10:58:41 +00:00
69112c2d22
feat(libxce-alloc-preason-equality): recorded dispatch fixtures carry the session-start from (task 4.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 10:44:00 +00:00
6110d12e5a
feat(libxce-alloc-preason-equality): white-box equivalence tests use public job_alloc_eq/job_preason_eq (task 4.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 10:27:46 +00:00
c1960457f8
feat(libxce-alloc-preason-equality): stamp every allocation's from with the deciding session start (task 3.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 10:14:35 +00:00
2d7ba66019
feat(libxce-alloc-preason-equality): record session begin from the session-start clock reading (task 3.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:59:56 +00:00
62d0b8b686
feat(libxce-alloc-preason-equality): full-match job_preason_eq with first-difference description (task 2.2)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:49:57 +00:00
a6cbb323b0
feat(libxce-alloc-preason-equality): public alloc_eq/host_alloc_eq/job_alloc_eq with first-difference description (task 2.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:35:08 +00:00
8f25c1c3f3
feat(libxce-alloc-preason-equality): NULL-safe str_eq helper in libxce utils (task 1.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:21:04 +00:00
094577f245
docs(spec): libxce-alloc-preason-equality tasks approved for implementation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 09:13:29 +00:00
dcf54387ae
docs(spec): libxce-alloc-preason-equality review fixes; new scheduler-sim-discrete-clock spec
libxce-alloc-preason-equality (requirements, design, tasks; not yet approved):
- alloc_eq compares `from` and excludes only instid; the scheduler stamps
  `from` with the deciding session's start, the same clock reading that
  is recorded as beginRound, so a replay reproduces it.
- every comparator takes an optional char** why: a malloc'd description
  of the first difference, owned and freed by the caller; --sim-verify
  mismatch lines print it (resolves bug-1881).
- job_preason_eq is new full-match behavior, not a relocation (bug-1845
  keeps the simulator main-reason-only); the three white-box test files
  switch to it and keep their sim_verify.c include.
- alloc_eq stays separate from merge_job_alloc()'s same_alloc_slot()
  (bug-1863), which does match on instid.

scheduler-sim-discrete-clock (initialized): remove --sim-speed so the
simulator clock moves only at recorded timestamps and a replayed
session_start equals the recorded beginRound exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 08:50:07 +00:00
8f51a4997d
chore(buglog): bug-1882 logged and fixed (f9146864); bug-1881 fix planned in spec libxce-alloc-preason-equality
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 08:50:06 +00:00
f9146864a3
fix(lib,scheduler): allocation constructors and allocators report OOM instead of building NULL-name records (bug-1882)
make_alloc() and make_host_alloc() assigned strdup() results unchecked,
so under memory exhaustion they returned a record whose resname/reserve/
host was NULL; merge_job_alloc()'s same_alloc_slot() (bug-1863) then
strcmp()'d it (ASAN SEGV at xcealloc.c:337). make_alloc() also passed a
NULL resname straight to strdup().
- xcealloc.c: make_alloc()/make_host_alloc() reject a NULL name (EINVAL)
  and check every strdup(), freeing what they built and returning NULL
  (ENOMEM); on failure make_host_alloc()'s caller keeps `allocs`.
  dup_host_alloc() frees its partial copy on failure instead of leaking.
- scheduler.c sched_make_allocs(): a record that cannot be built fails
  the whole array (NULL, ENOMEM) instead of leaving a NULL entry.
- seqjob/parjob my_alloc(): check every constructor; on failure free
  what was built (parjob also rolls back the remaining claims) and
  return -ENOMEM with ctx->alloc NULL -- the caller moves ctx.alloc onto
  the job whatever the rc.

Tests: new xcealloc_oom_test (8, --wrap=strdup) and
sched_make_allocs_oom_test (real scheduler_srcs + --wrap=strdup); a new
-ENOMEM test in the seqjob and parjob allocator suites. All RED before
(SEGV / "Expected NULL" / "Expected -12 Was 1"), GREEN after.
xce-build.sh all asan: 115/115 suites OK, Go tests OK.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 08:49:51 +00:00
c02d8e5cf6
chore(buglog): bug-1878, bug-1879 fixed (aa7fc65a)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 07:36:07 +00:00
aa7fc65a36
fix(controller): cold start elects in ~1.7 s, not ~10 s; ctrlstatus appliedLsn on the primary (bug-1879, bug-1878)
bug-1879: on a fresh HA cluster the config-holding ctrl-1 started its
term-1 election before its peers ran; connect failures count as "no"
votes (bug-1423), so it lost at once and became a follower with no
leader. ctrl-2/ctrl-3 hold no config and are voters only (by design),
so nothing retried until ctrl-1's 10 s standby liveness timeout: every
cold start had no primary for ~10 s.
- ha_note_leaderless() marks a config-holding node that becomes a
  follower with no leader known; the liveness poll then retries the
  election (PreVote) after HA_LEADERLESS_RETRY_MS = 1 s, doubling up to
  heartbeat_timeout_ms. Primary contact or becoming leader clears it.
- ha_heartbeat_is_fresh() answers "no" while leaderless: last_activity
  then only holds the watchdog's arm time, and the failover gates took
  it for a live primary.
Live cold start: primary 1.7 s after the first node started (was ~10 s).

bug-1878: ctrlstatus_fill() reported ha->applied_lsn for every role, a
standby-only counter a primary never advances, so every primary showed
"appliedLsn: 0". A primary now reports persist->last_applied_lsn. The
controller-status design doc's "already correct in every role" note is
corrected.

Tests: 5 new in test_ha_failover_prevote.c, 1 new in test_ctrlstatus.c
(RED: expected 4900, was 0); controller suite 1256/0. HA soaks:
sequential 6 rounds PASS, chaotic 6 rounds PASS (zero divergence, zero
job loss).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 07:35:45 +00:00
16b422e303
chore(buglog): log bug-1880 (sim-verify mismatch on array job dispatches) and bug-1881 (mismatch message hides the diff)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 07:26:50 +00:00
e36c252f6e
chore(buglog): log bug-1878 (ctrlstatus appliedLsn 0 on primary) and bug-1879 (cold boot ~10 s without primary)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 07:12:31 +00:00
f5d4a62841
chore: sync bug-1873 (#316) and refresh #311-#315 to Gitea
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 06:54:26 +00:00
00ef6066e2
chore(buglog): bug-1873 fixed (44173f74); pc13v retest recorded for bug-1872..1877
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 06:53:37 +00:00
4c13412720
chore: sync harness batch and bug-1872/1874-1877 to Gitea (#298-#315)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 04:42:34 +00:00
244148acef
chore(buglog): log bug-1872, bug-1874..1877 fixed (44173f74)
bug-1873 (systemd pid race) is held back until pc13v's environment is recorded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 04:37:51 +00:00
44173f74ae
fix: spurious errors/warnings from a pc13v HA deploy (bug-1872..1877)
- bug-1872 (worker): "Failed to find any disk statistics in
  /proc/diskstats" ERROR every 15 s on an NVMe-only host. The whole-disk
  filter guessed from the name and skipped anything ending in a digit or
  containing 'p' -- every nvmeXnY, mmcblkN, even sdp -- so io was never
  reported. diskstats.h now counts a device only when
  /sys/block/<name>/device exists (real disks; not partitions, loop, dm,
  md, zram), and a host with no disk warns once.
- bug-1873 (worker): "Failed to get worker pid" WARN on job start. MainPID
  reads 0 until systemd has forked the new transient unit; xcecd.c already
  retries, so the miss is DEBUG and the final failure names the unit.
- bug-1874 (scheduler): deprecation WARN for the legacy xce_sched_fcfs on
  every start, though builtin_fcfs is the picker. Registration still wraps
  a job_elect_fn plugin but no longer warns; selecting one warns once.
- bug-1875 (apiserver): "Not running as root -- PAM authentication will not
  work" with the default provider config_file; now only for provider pam.
- bug-1876 (controller): standbys logged "cluster_init_phase2 ... failed
  (rc=-22)" WARN every 3 s while waiting for the primary's config push,
  a state the function itself calls normal. It returns -EAGAIN for that
  wait; callers log it at INFO, other failures still WARN.
- bug-1877 (controller): "WAL/snapshot stored unencrypted" warned without
  looking. persist_path_encrypted() checks fscrypt (statx) and dm-crypt
  (sysfs dm/uuid CRYPT-, through LVM slaves); the warning stays when the
  storage is not shown to be encrypted (e.g. a plain /tmp).

Tests: worker diskstats_test (2 of 4 RED on the old filter with pc13v's
/proc/diskstats), controller test_phase2_cold_boot and
test_persist_encryption, scheduler picker tests, apiserver
TestRootWarning. Full ASAN build: all 113 suites pass (controller 319/0,
harness 141/0).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 04:35:19 +00:00