fix(ha-bootstrap): wire OP_requestVote RPC through standard Request envelope

The vote_request_thread was sending raw capnp(RequestVoteRequest) bytes
but the server-side iomgr decodes every incoming packet as a Request
struct. This caused the term field (uint64) to be misread as the opcode
field (uint16), so vote RPCs were silently misrouted (term=1 → OPCode_reply,
term=2 → OPCode_hello) and no node ever got a vote from its peers.

Fix:
- controller.capnp: add requestvotemsg @27 to Request.body and
  requestvotereplymsg @14 to RequestReply.data
- typemap.h: move request_vote_req_t/reply_t before xce_request_t;
  add requestvotemsg/requestvotereplymsg to body/data unions
- ha.c: rewrite vote_request_thread send/recv to use xce_encode()
  wrapper and decode outer Request→inner RequestReply on receive
- cluster.c: add case OPCode_requestVote handler calling
  handle_request_vote() and replying via xce_reply()

All 188 unit tests pass.
This commit is contained in:
Rongsong Shen 2026-05-29 17:01:59 +00:00
parent e25d2cc645
commit 6753b364c8
4 changed files with 100 additions and 58 deletions

View file

@ -281,6 +281,34 @@ static int myreq_handler(vtask_t* task)
case OPCode_clrpreason:
rc = do_clr_preason(c, ep, &request);
break;
case OPCode_requestVote: {
request_vote_req_t *vrq = request.body.requestvotemsg;
uint64_t cand_tag = vrq ? vrq->config_tag : 0;
uint64_t cand_lsn = vrq ? vrq->last_log_lsn : 0;
uint64_t cand_term = vrq ? vrq->term : 0;
uint64_t my_tag = c->myconf->config_version_tag;
uint64_t my_lsn = (uint64_t)atomic_load_explicit(
&c->ha.applied_lsn, memory_order_acquire);
int granted = handle_request_vote(
&c->ha, cand_term, vrq ? vrq->candidate_id : "",
cand_tag, cand_lsn, my_tag, my_lsn,
0 /* in_catch_up_flag: not implemented here */);
request_vote_reply_t vr_rep;
memset(&vr_rep, 0, sizeof(vr_rep));
vr_rep.term = (uint64_t)atomic_load_explicit(
&c->ha.term, memory_order_acquire);
vr_rep.vote_granted = (granted > 0) ? 1 : 0;
vr_rep.peer_config_tag = my_tag;
vr_rep.peer_last_log_lsn = my_lsn;
reply.status = 0;
reply.data_which = RequestReply_data_requestvotereplymsg;
reply.data.requestvotereplymsg = &vr_rep;
xce_reply(ep, c->myhost, &reply);
rc = 0;
break;
}
case OPCode_replConfig:
rc = handle_config_request(c, ep, &request);
break;