feat(ha-config-bootstrap): implement dispatch gate (task 3.3)

- errnox.h: add E_XCE_NOT_READY and E_XCE_STANDBY error codes with
  extern int XCE_ERR_NOT_READY / XCE_ERR_STANDBY runtime variables
- ha.h: declare ha_dispatch_gate(ha_state_t *, int opcode)
- ha.c: define XCE_ERR_* variables; initialize heartbeat_seen semaphore
  and primary_ctrl_fd = -1 in ha_init(); sem_destroy in ha_fini();
  implement ha_dispatch_gate() with allowlist for CTRL_INIT/CTRL_ELECTING
  (only OP_requestVote and OP_probeConfigTag pass) and CTRL_STANDBY
  (replication, election, and housekeeping ops pass; primary-only ops
  return -XCE_ERR_STANDBY)
- cluster.c: wire ha_dispatch_gate() in myreq_handler() before opcode
  switch; gate failure sends error reply and returns early

All 393 unit tests pass. Satisfies requirements 1.3 and 1.4.
This commit is contained in:
Rongsong Shen 2026-05-28 05:50:42 +00:00
parent 6272fc8eb2
commit 72776f18ff
5 changed files with 106 additions and 1 deletions

View file

@ -192,6 +192,17 @@ static int myreq_handler(vtask_t* task)
init_reply_by_req(&reply, &request);
/* Dispatch gate: reject ops not allowed in current FSM state (req 1.3, 1.4) */
rc = ha_dispatch_gate(&c->ha, request.opcode);
if (rc != 0) {
reply.status = rc;
reply.data_which = RequestReply_data_nodata;
xce_reply(ep, c->myhost, &reply);
free_Request(&request);
free(raw_pkt_copy);
return rc;
}
switch (request.opcode) {
case OPCode_shutdown:
reply.status = 0;