fix(ha): fix config replication to standbys; add replConfigPush handler

- config_repl.c: add handle_repl_config_push — standby handler for
  OPCode_replConfigPush. Verifies SHA-256, saves blob to disk via
  conf_save_config, reloads via load_primary_config, ACKs primary.
- config_repl.h: declare handle_repl_config_push.
- cluster.c: dispatch OPCode_replConfigPush to handle_repl_config_push;
  populate c->myhost_info.name from myconf->name (ctrl-1/ctrl-2/ctrl-3)
  instead of the static "controller" placeholder.
- ha.c: fix raft_cb_become_leader push_config_to_standbys call to pass
  real config bytes and tag read from disk (was NULL/0 — standbys got
  empty push and never saved config).
- typemap.h: add raw_sha256/raw_bytes/raw_bytes_len fields to
  repl_config_push_req_t (mirrors upgrade_config_req_t pattern).
- request.c: pre-extract List(UInt8) sha256/bytes from OPCode_replConfigPush
  before capn_free() in xce_decode(); free them in xce_free_request().
- helper.c: add all HA/replication opcode names to xce_request_op_name
  so "unknown opcode 30" becomes "replConfigPush" in logs.
- cluster_def.h: add embedded myhost_info field to cluster_t struct.
- ha.h: declare ha_start_primary_heartbeat; remove dead
  ha_find_and_connect_to_primary declaration.
This commit is contained in:
Rongsong Shen 2026-06-01 05:56:16 +00:00
parent d00d3bb051
commit 3d076ccda6
8 changed files with 191 additions and 8 deletions

View file

@ -148,6 +148,38 @@ char* xce_request_op_name(xce_request_t* req)
return "setpreason";
case OPCode_clrpreason:
return "clrpreason";
case OPCode_heartbeat:
return "heartbeat";
case OPCode_redirect:
return "redirect";
case OPCode_steppingDown:
return "steppingDown";
case OPCode_replEntry:
return "replEntry";
case OPCode_replAck:
return "replAck";
case OPCode_replSnapshot:
return "replSnapshot";
case OPCode_replCatchUpDone:
return "replCatchUpDone";
case OPCode_replConfig:
return "replConfig";
case OPCode_replConfigPush:
return "replConfigPush";
case OPCode_upgradeConfig:
return "upgradeConfig";
case OPCode_upgradeConfigAck:
return "upgradeConfigAck";
case OPCode_requestVote:
return "requestVote";
case OPCode_probeConfigTag:
return "probeConfigTag";
case OPCode_walAck:
return "walAck";
case OPCode_walCatchupEntry:
return "walCatchupEntry";
case OPCode_snapshotTransfer:
return "snapshotTransfer";
default:
break;
}

View file

@ -119,6 +119,45 @@ int xce_decode(io_packet_t* pkt, xce_request_t* req)
}
}
/* OPCode_replConfigPush: same List(UInt8) issue — pre-extract raw bytes. */
if (rq.opcode == OPCode_replConfigPush
&& req->body_which == Request_body_replconfigpushrequestmsg
&& req->body.replconfigpushrequestmsg != NULL) {
repl_config_push_req_t *rcpr = req->body.replconfigpushrequestmsg;
ReplConfigPushRequest_ptr r_ptr = rq.body.replconfigpushrequestmsg;
/* sha256 */
{
Data_ptr dp = ReplConfigPushRequest_get_sha256(r_ptr);
capn_list8 sha_list; sha_list.p = dp.p;
if (sha_list.p.type != CAPN_NULL && capn_len(sha_list) > 0) {
int slen = capn_len(sha_list);
uint8_t *sbuf = (uint8_t *)malloc((size_t)slen);
if (sbuf && capn_getv8(sha_list, 0, sbuf, slen) == slen)
rcpr->raw_sha256 = sbuf;
else
free(sbuf);
}
}
/* bytes */
{
Data_ptr dp = ReplConfigPushRequest_get_bytes(r_ptr);
capn_list8 bytes_list; bytes_list.p = dp.p;
if (bytes_list.p.type != CAPN_NULL && capn_len(bytes_list) > 0) {
int blen = capn_len(bytes_list);
uint8_t *bbuf = (uint8_t *)malloc((size_t)blen);
if (bbuf && capn_getv8(bytes_list, 0, bbuf, blen) == blen) {
rcpr->raw_bytes = bbuf;
rcpr->raw_bytes_len = (size_t)blen;
} else {
free(bbuf);
}
}
}
}
TRACE("%s request op %d seq %ld from %s", __func__, req->opcode, req->seq,
REQUEST_FROM(req));
capn_free(&c);
@ -150,7 +189,7 @@ void xce_free_request(xce_request_t *req)
if (req == NULL)
return;
/* Free raw_* fields that the generated free_UpgradeConfigRequest skips */
/* Free raw_* fields that the generated free_*Request skips */
if (req->body_which == Request_body_upgradeconfigrequestmsg
&& req->body.upgradeconfigrequestmsg != NULL) {
upgrade_config_req_t *ucr = req->body.upgradeconfigrequestmsg;
@ -161,6 +200,16 @@ void xce_free_request(xce_request_t *req)
ucr->raw_bytes_len = 0;
}
if (req->body_which == Request_body_replconfigpushrequestmsg
&& req->body.replconfigpushrequestmsg != NULL) {
repl_config_push_req_t *rcpr = req->body.replconfigpushrequestmsg;
free(rcpr->raw_sha256);
rcpr->raw_sha256 = NULL;
free(rcpr->raw_bytes);
rcpr->raw_bytes = NULL;
rcpr->raw_bytes_len = 0;
}
free_Request(req);
}