feat(scheduler-core): define new event payload types (task 7.2)
Adds JobStateChangeEvent (jobid/oldState/newState/exitCode) and JobUpdateEvent (jobid/changedFields/job: Job) to controller.capnp, matching design.md's spec verbatim. JobUpdateEvent.job reuses the existing full 12-field Job/xce_job_t record, verified distinct from the narrower SchedJob struct sharing the same mapname. Extends ReplayEvent.body's union (task 7.1) with jobStateChange@10/ jobUpdate@11 -- the only two valid next ordinals, since capnp requires strictly sequential ordinals with no gaps across a struct and task 7.1 deliberately stopped at @9. Existing @0-@9 fields and every other struct in the schema are byte-identical. Deep round-trip tests in test_e2e_capnp.c exercise every field with non-default values, including the 3-level nested Job substructs (submitData/allocs/pidinfo/pendreason). JOB_F_* bitmask bit values deliberately left undefined -- a later task's job, not this schema-only one's. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019dw5WnN3DXStaEaPYfACU1
This commit is contained in:
parent
68a6196517
commit
755230705c
4 changed files with 295 additions and 4 deletions
|
|
@ -165,12 +165,13 @@
|
||||||
- _Verified: 2026-08-04 — ReplayCluster/ReplayHeader/SnapshotEntry/ReplayEvent/SessionSummary/ReplaySession added fully; SnapshotData (empty {}) and ReplayDecision ({ts only}) added as compiler-mandated placeholders task 7.3 fills in (real fields for SnapshotData wholesale-replaced, a body union appended to ReplayDecision at new ordinals) since capnp's $C.codecgen has no per-struct opt-out from requiring the mapname'd C type to exist. ReplayEvent's union deliberately holds only the 9 members with pre-existing backing types (configPush/jobsPush/workersPush/resourcesPush/resvalsFull/resvalsDelta/queueUpdate/jobRusage/endSession); jobStateChange/jobUpdate deferred to task 7.2 as new ordinals — proven compiler-mandatory (not stylistic) by review, which independently confirmed capnp rejects both the AC 20 pseudocode's literal union syntax and any ordinal gap. Round-trip test (test_e2e_capnp.c) proven real via full clean rebuild (deleted+regenerated controller.capnp.{c,h}) both by implementer and reviewer. Full project build clean (controller/apiserver-CGO/scheduler/worker/xceadmin), 1075/1075 controller_unit_test passing, review APPROVED first pass with reviewer going beyond implementer's own verification (real capn_resolve()-omission and placeholder-removal breakage reproduced firsthand). Zero existing structs/fields touched._
|
- _Verified: 2026-08-04 — ReplayCluster/ReplayHeader/SnapshotEntry/ReplayEvent/SessionSummary/ReplaySession added fully; SnapshotData (empty {}) and ReplayDecision ({ts only}) added as compiler-mandated placeholders task 7.3 fills in (real fields for SnapshotData wholesale-replaced, a body union appended to ReplayDecision at new ordinals) since capnp's $C.codecgen has no per-struct opt-out from requiring the mapname'd C type to exist. ReplayEvent's union deliberately holds only the 9 members with pre-existing backing types (configPush/jobsPush/workersPush/resourcesPush/resvalsFull/resvalsDelta/queueUpdate/jobRusage/endSession); jobStateChange/jobUpdate deferred to task 7.2 as new ordinals — proven compiler-mandatory (not stylistic) by review, which independently confirmed capnp rejects both the AC 20 pseudocode's literal union syntax and any ordinal gap. Round-trip test (test_e2e_capnp.c) proven real via full clean rebuild (deleted+regenerated controller.capnp.{c,h}) both by implementer and reviewer. Full project build clean (controller/apiserver-CGO/scheduler/worker/xceadmin), 1075/1075 controller_unit_test passing, review APPROVED first pass with reviewer going beyond implementer's own verification (real capn_resolve()-omission and placeholder-removal breakage reproduced firsthand). Zero existing structs/fields touched._
|
||||||
- _Depends: 6_
|
- _Depends: 6_
|
||||||
|
|
||||||
- [ ] 7.2 Define new event payload types
|
- [x] 7.2 Define new event payload types
|
||||||
- Add the two genuinely new event payload message types (job state-change delta, job update delta with embedded full record) to the wire schema; every other event payload type reuses an existing wire message already used elsewhere in the schema
|
- Add the two genuinely new event payload message types (job state-change delta, job update delta with embedded full record) to the wire schema; every other event payload type reuses an existing wire message already used elsewhere in the schema
|
||||||
- Observable: encoding a job state-change event and a job update event and decoding them back yields field-for-field equality with the original values
|
- Observable: encoding a job state-change event and a job update event and decoding them back yields field-for-field equality with the original values
|
||||||
- _Requirements: 5.20_
|
- _Requirements: 5.20_
|
||||||
- _Depends: 7.1_
|
- _Depends: 7.1_
|
||||||
- _Boundary: ReplayFormat — not (P): 7.2/7.3/7.4 all edit the same schema file (controller.capnp); run sequentially to avoid concurrent edits to one file, even though each adds a logically disjoint set of structs_
|
- _Boundary: ReplayFormat — not (P): 7.2/7.3/7.4 all edit the same schema file (controller.capnp); run sequentially to avoid concurrent edits to one file, even though each adds a logically disjoint set of structs_
|
||||||
|
- _Verified: 2026-08-04 — JobStateChangeEvent/JobUpdateEvent added to controller.capnp matching design.md's spec verbatim; JobUpdateEvent.job correctly reuses the full 12-field Job/xce_job_t record (not the narrower SchedJob sharing the same mapname — verified by field list). ReplayEvent.body's union extended with jobStateChange@10/jobUpdate@11, the only two valid next ordinals per task 7.1's baseline (capnp requires no gaps) — confirmed via a from-scratch capnp regeneration. Existing @0-@9 fields byte-identical. Deep round-trip tests (non-default values throughout, including 3-level nested Job substructs) prove the Observable; JOB_F_* bitmask values deliberately left undefined (later task's job). 1077/1077 controller_unit_test, full project build clean, review APPROVED first pass._
|
||||||
|
|
||||||
- [ ] 7.3 Define decision payload types and the snapshot schema
|
- [ ] 7.3 Define decision payload types and the snapshot schema
|
||||||
- Add the dispatch, pend, and preempt decision payload message types, reusing existing allocation and pend-reason wire messages where they already carry the needed fields
|
- Add the dispatch, pend, and preempt decision payload message types, reusing existing allocation and pend-reason wire messages where they already carry the needed fields
|
||||||
|
|
|
||||||
|
|
@ -545,6 +545,248 @@ static void test_session_summary_round_trip(void)
|
||||||
printf("test_session_summary_round_trip: PASS\n");
|
printf("test_session_summary_round_trip: PASS\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Test 9: JobStateChangeEvent round-trip (scheduler-core task 7.2, */
|
||||||
|
/* Req 5 AC 20) -- the first of the two genuinely new ReplayEvent.body */
|
||||||
|
/* payload types. Uses the encode_X/decode_X codec bridge (Test 6's */
|
||||||
|
/* pattern) since job_state_change_event_t is a real, fully-scalar C */
|
||||||
|
/* struct with no Data fields -- unlike the frame-only replay-envelope */
|
||||||
|
/* types in Tests 7-8, which have no live C struct yet. */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static void test_job_state_change_event_round_trip(void)
|
||||||
|
{
|
||||||
|
job_state_change_event_t src;
|
||||||
|
memset(&src, 0, sizeof(src));
|
||||||
|
src.jobid = 42424ULL;
|
||||||
|
src.old_state = 2u;
|
||||||
|
src.new_state = 8u;
|
||||||
|
src.exit_code = -7;
|
||||||
|
|
||||||
|
struct capn c;
|
||||||
|
capn_init_malloc(&c);
|
||||||
|
struct capn_segment *cs = capn_root(&c).seg;
|
||||||
|
|
||||||
|
JobStateChangeEvent_ptr p;
|
||||||
|
encode_JobStateChangeEvent_ptr(cs, &p, &src);
|
||||||
|
capn_setp(capn_root(&c), 0, p.p);
|
||||||
|
|
||||||
|
int64_t sz = capn_size(&c);
|
||||||
|
TEST_ASSERT_TRUE(sz > 0);
|
||||||
|
uint8_t *buf = (uint8_t *)malloc((size_t)sz);
|
||||||
|
TEST_ASSERT_NOT_NULL(buf);
|
||||||
|
capn_write_mem(&c, buf, (size_t)sz, 0);
|
||||||
|
capn_free(&c);
|
||||||
|
|
||||||
|
struct capn d;
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, capn_init_mem(&d, buf, (size_t)sz, 0));
|
||||||
|
JobStateChangeEvent_ptr dp;
|
||||||
|
dp.p = capn_getp(capn_root(&d), 0, 1);
|
||||||
|
struct JobStateChangeEvent wire;
|
||||||
|
read_JobStateChangeEvent(&wire, dp);
|
||||||
|
job_state_change_event_t dst;
|
||||||
|
memset(&dst, 0, sizeof(dst));
|
||||||
|
decode_JobStateChangeEvent(&dst, &wire);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(42424ULL, dst.jobid);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(2u, dst.old_state);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(8u, dst.new_state);
|
||||||
|
TEST_ASSERT_EQUAL_INT32(-7, dst.exit_code);
|
||||||
|
|
||||||
|
capn_free(&d);
|
||||||
|
free(buf);
|
||||||
|
printf("test_job_state_change_event_round_trip: PASS\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Test 10: JobUpdateEvent round-trip (scheduler-core task 7.2, */
|
||||||
|
/* Req 5 AC 20) -- the second genuinely new ReplayEvent.body payload */
|
||||||
|
/* type. `job` embeds the FULL updated record by reusing the */
|
||||||
|
/* pre-existing Job/xce_job_t struct; populated non-trivially, including*/
|
||||||
|
/* nested submit/allocs/pidinfo/pend_reasons (incl. the HostAlloc/ */
|
||||||
|
/* ResAlloc list-of-pointers two levels down), to prove the whole tree */
|
||||||
|
/* round-trips through encode_Job_ptr/decode_Job_ptr -- the same nested-*/
|
||||||
|
/* pointer codec chain already proven for xce_job_submit_t->submit in */
|
||||||
|
/* Test 6, now exercised for Job's full field set. */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static void test_job_update_event_round_trip(void)
|
||||||
|
{
|
||||||
|
/* Innermost: one HostAlloc with one ResAlloc. */
|
||||||
|
xce_alloc_t res_alloc;
|
||||||
|
memset(&res_alloc, 0, sizeof(res_alloc));
|
||||||
|
res_alloc.resname = "cpu";
|
||||||
|
res_alloc.reserve = "resv1";
|
||||||
|
res_alloc.instid = 42ULL;
|
||||||
|
res_alloc.value = 4.0;
|
||||||
|
res_alloc.from = 500ULL;
|
||||||
|
res_alloc.duration = 3600LL;
|
||||||
|
xce_alloc_t *res_allocs[1] = { &res_alloc };
|
||||||
|
|
||||||
|
xce_host_alloc_t host_alloc;
|
||||||
|
memset(&host_alloc, 0, sizeof(host_alloc));
|
||||||
|
host_alloc.host = "hostA";
|
||||||
|
host_alloc.nallocs = 1;
|
||||||
|
host_alloc.allocs = res_allocs;
|
||||||
|
xce_host_alloc_t *host_allocs[1] = { &host_alloc };
|
||||||
|
|
||||||
|
xce_job_alloc_t job_alloc;
|
||||||
|
memset(&job_alloc, 0, sizeof(job_alloc));
|
||||||
|
job_alloc.jobid = 8001ULL;
|
||||||
|
job_alloc.nhosts = 1;
|
||||||
|
job_alloc.allocs = host_allocs;
|
||||||
|
job_alloc.nres_shared = 0;
|
||||||
|
job_alloc.allocs_shared = NULL;
|
||||||
|
|
||||||
|
job_submit_data_t submit;
|
||||||
|
memset(&submit, 0, sizeof(submit));
|
||||||
|
submit.queue = "normal";
|
||||||
|
submit.user = "alice";
|
||||||
|
submit.mintasks = 2u;
|
||||||
|
submit.maxtasks = 8u;
|
||||||
|
submit.start_info = NULL;
|
||||||
|
submit.job_name = "update-test-job";
|
||||||
|
submit.project_name = "proj-x";
|
||||||
|
submit.user_group = "grp-x";
|
||||||
|
submit.job_description = "job update event round-trip test";
|
||||||
|
submit.resreq = "select=2";
|
||||||
|
|
||||||
|
unsigned int pids[2] = { 111u, 222u };
|
||||||
|
unsigned int pgids[1] = { 333u };
|
||||||
|
job_pidinfo_t pidinfo;
|
||||||
|
memset(&pidinfo, 0, sizeof(pidinfo));
|
||||||
|
pidinfo.jobid = 8001ULL;
|
||||||
|
pidinfo.npids = 2;
|
||||||
|
pidinfo.pids = pids;
|
||||||
|
pidinfo.npgids = 1;
|
||||||
|
pidinfo.pgids = pgids;
|
||||||
|
pidinfo.exdata = "pid-exdata";
|
||||||
|
|
||||||
|
xce_job_preason_t pend_reasons;
|
||||||
|
memset(&pend_reasons, 0, sizeof(pend_reasons));
|
||||||
|
pend_reasons.main_reason = 7;
|
||||||
|
pend_reasons.nhost_reasons = 0;
|
||||||
|
pend_reasons.host_based_reasons = NULL;
|
||||||
|
pend_reasons.nres_reasons = 0;
|
||||||
|
pend_reasons.res_based_reasons = NULL;
|
||||||
|
|
||||||
|
xce_job_t job;
|
||||||
|
memset(&job, 0, sizeof(job));
|
||||||
|
job.jobid = 8001ULL;
|
||||||
|
job.submit = &submit;
|
||||||
|
job.sub_time = 1000;
|
||||||
|
job.queue_time = 2000;
|
||||||
|
job.start_time = 3000;
|
||||||
|
job.finish_time = 4000;
|
||||||
|
job.state = 5u;
|
||||||
|
job.allocs = &job_alloc;
|
||||||
|
job.run_time = 120;
|
||||||
|
job.pidinfo = &pidinfo;
|
||||||
|
job.pend_reasons = &pend_reasons;
|
||||||
|
job.transient_since = 9999ULL;
|
||||||
|
|
||||||
|
job_update_event_t src;
|
||||||
|
memset(&src, 0, sizeof(src));
|
||||||
|
src.jobid = 8001ULL;
|
||||||
|
src.changed_fields = 0x5u;
|
||||||
|
src.job = &job;
|
||||||
|
|
||||||
|
struct capn c;
|
||||||
|
capn_init_malloc(&c);
|
||||||
|
struct capn_segment *cs = capn_root(&c).seg;
|
||||||
|
|
||||||
|
JobUpdateEvent_ptr p;
|
||||||
|
encode_JobUpdateEvent_ptr(cs, &p, &src);
|
||||||
|
capn_setp(capn_root(&c), 0, p.p);
|
||||||
|
|
||||||
|
int64_t sz = capn_size(&c);
|
||||||
|
TEST_ASSERT_TRUE(sz > 0);
|
||||||
|
uint8_t *buf = (uint8_t *)malloc((size_t)sz);
|
||||||
|
TEST_ASSERT_NOT_NULL(buf);
|
||||||
|
capn_write_mem(&c, buf, (size_t)sz, 0);
|
||||||
|
capn_free(&c);
|
||||||
|
|
||||||
|
struct capn d;
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, capn_init_mem(&d, buf, (size_t)sz, 0));
|
||||||
|
JobUpdateEvent_ptr dp;
|
||||||
|
dp.p = capn_getp(capn_root(&d), 0, 1);
|
||||||
|
struct JobUpdateEvent wire;
|
||||||
|
read_JobUpdateEvent(&wire, dp);
|
||||||
|
job_update_event_t dst;
|
||||||
|
memset(&dst, 0, sizeof(dst));
|
||||||
|
decode_JobUpdateEvent(&dst, &wire);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(8001ULL, dst.jobid);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0x5u, dst.changed_fields);
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(8001ULL, dst.job->jobid);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(1000ULL, (uint64_t)dst.job->sub_time);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(2000ULL, (uint64_t)dst.job->queue_time);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(3000ULL, (uint64_t)dst.job->start_time);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(4000ULL, (uint64_t)dst.job->finish_time);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(5u, dst.job->state);
|
||||||
|
TEST_ASSERT_EQUAL_INT(120, dst.job->run_time);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(9999ULL, dst.job->transient_since);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job->submit);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("normal", dst.job->submit->queue);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("alice", dst.job->submit->user);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(2u, dst.job->submit->mintasks);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(8u, dst.job->submit->maxtasks);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("update-test-job", dst.job->submit->job_name);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("proj-x", dst.job->submit->project_name);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("grp-x", dst.job->submit->user_group);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("job update event round-trip test",
|
||||||
|
dst.job->submit->job_description);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("select=2", dst.job->submit->resreq);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job->allocs);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(8001ULL, dst.job->allocs->jobid);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, dst.job->allocs->nhosts);
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job->allocs->allocs);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("hostA", dst.job->allocs->allocs[0]->host);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, dst.job->allocs->allocs[0]->nallocs);
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job->allocs->allocs[0]->allocs);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("cpu",
|
||||||
|
dst.job->allocs->allocs[0]->allocs[0]->resname);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("resv1",
|
||||||
|
dst.job->allocs->allocs[0]->allocs[0]->reserve);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(42ULL,
|
||||||
|
dst.job->allocs->allocs[0]->allocs[0]->instid);
|
||||||
|
/* Unity is built without UNITY_INCLUDE_DOUBLE; compare via float cast
|
||||||
|
* (same pattern as scheduler/testsuite/test.c). */
|
||||||
|
TEST_ASSERT_EQUAL_FLOAT(4.0f,
|
||||||
|
(float)dst.job->allocs->allocs[0]->allocs[0]->value);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(500ULL,
|
||||||
|
dst.job->allocs->allocs[0]->allocs[0]->from);
|
||||||
|
TEST_ASSERT_EQUAL_INT64(3600LL,
|
||||||
|
dst.job->allocs->allocs[0]->allocs[0]->duration);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, dst.job->allocs->nres_shared);
|
||||||
|
TEST_ASSERT_NULL(dst.job->allocs->allocs_shared);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job->pidinfo);
|
||||||
|
TEST_ASSERT_EQUAL_UINT64(8001ULL, dst.job->pidinfo->jobid);
|
||||||
|
TEST_ASSERT_EQUAL_INT(2, dst.job->pidinfo->npids);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(111u, dst.job->pidinfo->pids[0]);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(222u, dst.job->pidinfo->pids[1]);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, dst.job->pidinfo->npgids);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(333u, dst.job->pidinfo->pgids[0]);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("pid-exdata", dst.job->pidinfo->exdata);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dst.job->pend_reasons);
|
||||||
|
TEST_ASSERT_EQUAL_INT(7, dst.job->pend_reasons->main_reason);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, dst.job->pend_reasons->nhost_reasons);
|
||||||
|
TEST_ASSERT_NULL(dst.job->pend_reasons->host_based_reasons);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, dst.job->pend_reasons->nres_reasons);
|
||||||
|
TEST_ASSERT_NULL(dst.job->pend_reasons->res_based_reasons);
|
||||||
|
|
||||||
|
free_JobUpdateEvent(&dst);
|
||||||
|
capn_free(&d);
|
||||||
|
free(buf);
|
||||||
|
printf("test_job_update_event_round_trip: PASS\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Suite entry point */
|
/* Suite entry point */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
@ -562,4 +804,6 @@ void test_e2e_capnp(void)
|
||||||
RUN_TEST(test_data_job_array_variant_round_trip);
|
RUN_TEST(test_data_job_array_variant_round_trip);
|
||||||
RUN_TEST(test_replay_header_snapshot_entry_round_trip);
|
RUN_TEST(test_replay_header_snapshot_entry_round_trip);
|
||||||
RUN_TEST(test_session_summary_round_trip);
|
RUN_TEST(test_session_summary_round_trip);
|
||||||
|
RUN_TEST(test_job_state_change_event_round_trip);
|
||||||
|
RUN_TEST(test_job_update_event_round_trip);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -589,6 +589,28 @@ typedef struct {
|
||||||
sched_snapshot_data_t *data;
|
sched_snapshot_data_t *data;
|
||||||
} replay_snapshot_entry_t;
|
} replay_snapshot_entry_t;
|
||||||
|
|
||||||
|
/* task 7.2 (Req 5 AC 20): the two genuinely new event payload types -- every
|
||||||
|
* other replay_event_t.body variant above reuses a pre-existing wire type
|
||||||
|
* (see controller.capnp's comment at `struct JobStateChangeEvent`). */
|
||||||
|
typedef struct {
|
||||||
|
uint64_t jobid;
|
||||||
|
uint32_t old_state;
|
||||||
|
uint32_t new_state;
|
||||||
|
int32_t exit_code;
|
||||||
|
} job_state_change_event_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t jobid;
|
||||||
|
/* changedFields is a UInt32 bitmask (JOB_F_PRIORITY, JOB_F_QUEUE,
|
||||||
|
* JOB_F_RESREQ per design.md) -- no JOB_F_* constants exist anywhere in
|
||||||
|
* the codebase yet (task 5.1's grep); concrete bit assignments are
|
||||||
|
* task 9+ event-translation/recording code's job, not this schema-only
|
||||||
|
* task's. */
|
||||||
|
uint32_t changed_fields;
|
||||||
|
xce_job_t *job; /* full updated record -- reuses xce_job_t (Job in
|
||||||
|
* controller.capnp) */
|
||||||
|
} job_update_event_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t ts;
|
uint64_t ts;
|
||||||
int body_which;
|
int body_which;
|
||||||
|
|
@ -602,6 +624,8 @@ typedef struct {
|
||||||
xce_queue_t *queue_update;
|
xce_queue_t *queue_update;
|
||||||
xce_job_rusages_t *job_rusage;
|
xce_job_rusages_t *job_rusage;
|
||||||
/* endSession: Void, no storage */
|
/* endSession: Void, no storage */
|
||||||
|
job_state_change_event_t *job_state_change;
|
||||||
|
job_update_event_t *job_update;
|
||||||
} body;
|
} body;
|
||||||
} replay_event_t;
|
} replay_event_t;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1041,12 +1041,32 @@ struct SnapshotEntry $C.mapname("replay_snapshot_entry_t") {
|
||||||
data @1: SnapshotData; # full core state
|
data @1: SnapshotData; # full core state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# task 7.2 (Req 5 AC 20): the two genuinely new event payload types --
|
||||||
|
# every other ReplayEvent.body variant reuses a pre-existing wire struct
|
||||||
|
# (see ReplayEvent's comment block below). jobStateChange/jobUpdate are
|
||||||
|
# added as ReplayEvent.body union members at ordinals 10/11 below.
|
||||||
|
struct JobStateChangeEvent $C.mapname("job_state_change_event_t") {
|
||||||
|
jobid @0: UInt64;
|
||||||
|
oldState @1: UInt32 $C.mapname("old_state");
|
||||||
|
newState @2: UInt32 $C.mapname("new_state");
|
||||||
|
exitCode @3: Int32 $C.mapname("exit_code");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct JobUpdateEvent $C.mapname("job_update_event_t") {
|
||||||
|
jobid @0: UInt64;
|
||||||
|
# bitmask: JOB_F_PRIORITY, JOB_F_QUEUE, JOB_F_RESREQ -- no JOB_F_* constants
|
||||||
|
# exist anywhere in the codebase yet (confirmed by task 5.1's grep); concrete
|
||||||
|
# bit assignments are task 9+ event-translation/recording code's job, not
|
||||||
|
# this schema-only task's.
|
||||||
|
changedFields @1: UInt32 $C.mapname("changed_fields");
|
||||||
|
job @2: Job; # full updated record; reuses existing Job struct
|
||||||
|
}
|
||||||
|
|
||||||
# ReplayEvent.body reuses 7 pre-existing wire structs verbatim (Conf4Sched,
|
# ReplayEvent.body reuses 7 pre-existing wire structs verbatim (Conf4Sched,
|
||||||
# SchedJobData, WorkerData, ResourceData, ResValList x2, QueueConf,
|
# SchedJobData, WorkerData, ResourceData, ResValList x2, QueueConf,
|
||||||
# SchedJobRusages -- verified present in controller.capnp, research.md) plus
|
# SchedJobRusages -- verified present in controller.capnp, research.md) plus
|
||||||
# a Void end-of-recording marker. jobStateChange/jobUpdate (task 7.2) are
|
# a Void end-of-recording marker, plus the two new JobStateChangeEvent/
|
||||||
# added later as new union members at ordinals 10/11, once
|
# JobUpdateEvent structs (task 7.2) above.
|
||||||
# JobStateChangeEvent/JobUpdateEvent exist.
|
|
||||||
struct ReplayEvent $C.mapname("replay_event_t") {
|
struct ReplayEvent $C.mapname("replay_event_t") {
|
||||||
ts @0: UInt64; # logical time
|
ts @0: UInt64; # logical time
|
||||||
body :union $C.mapuniontag("body_which") {
|
body :union $C.mapuniontag("body_which") {
|
||||||
|
|
@ -1059,6 +1079,8 @@ struct ReplayEvent $C.mapname("replay_event_t") {
|
||||||
queueUpdate @7: QueueConf $C.mapname("queue_update");
|
queueUpdate @7: QueueConf $C.mapname("queue_update");
|
||||||
jobRusage @8: SchedJobRusages $C.mapname("job_rusage");
|
jobRusage @8: SchedJobRusages $C.mapname("job_rusage");
|
||||||
endSession @9: Void; # recording stop marker
|
endSession @9: Void; # recording stop marker
|
||||||
|
jobStateChange @10: JobStateChangeEvent $C.mapname("job_state_change");
|
||||||
|
jobUpdate @11: JobUpdateEvent $C.mapname("job_update");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue