Skip to content

Commit

Permalink
client: Use a RAFT_TRANSFER event to transfer leadership
Browse files Browse the repository at this point in the history
Signed-off-by: Free Ekanayaka <free@ekanayaka.io>
  • Loading branch information
freeekanayaka committed Dec 21, 2023
1 parent 2a5e7d6 commit 2e0de4f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 9 deletions.
4 changes: 4 additions & 0 deletions include/raft.h
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,10 @@ struct raft_event
{
raft_id server_id;
} catch_up;
struct
{
raft_id server_id;
} transfer;
};
};

Expand Down
53 changes: 44 additions & 9 deletions src/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,48 @@ static raft_id clientSelectTransferee(struct raft *r)
return 0;
}

int ClientTransfer(struct raft *r, raft_id server_id)
{
const struct raft_server *server;
unsigned i;
int rv;

if (server_id == 0) {
server_id = clientSelectTransferee(r);
if (server_id == 0) {
rv = RAFT_NOTFOUND;
ErrMsgPrintf(r->errmsg, "there's no other voting server");
goto err;
}
}

server = configurationGet(&r->configuration, server_id);
if (server == NULL || server->id == r->id || server->role != RAFT_VOTER) {
rv = RAFT_BADID;
ErrMsgFromCode(r->errmsg, rv);
goto err;
}

/* If this follower is up-to-date, we can send it the TimeoutNow message
* right away. */
i = configurationIndexOf(&r->configuration, server->id);
assert(i < r->configuration.n);

if (progressIsUpToDate(r, i)) {
rv = membershipLeadershipTransferStart(r);
if (rv != 0) {
r->transfer = NULL;
goto err;
}
}

return 0;

err:
assert(rv != 0);
return rv;
}

int raft_transfer(struct raft *r,
struct raft_transfer *req,
raft_id id,
Expand Down Expand Up @@ -529,16 +571,9 @@ int raft_transfer(struct raft *r,

membershipLeadershipTransferInit(r, req, id, cb);

if (progressIsUpToDate(r, i)) {
rv = membershipLeadershipTransferStart(r);
if (rv != 0) {
r->transfer = NULL;
goto err;
}
}

event.type = RAFT_TRANSFER;
event.time = r->io->time(r->io);
event.type = RAFT_TRANSFER;
event.transfer.server_id = id;

rv = LegacyForwardToRaftIo(r, &event);
if (rv != 0) {
Expand Down
3 changes: 3 additions & 0 deletions src/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ int ClientSubmit(struct raft *r, struct raft_entry *entries, unsigned n);
/* Start catching-up the given server. */
void ClientCatchUp(struct raft *r, raft_id server_id);

/* Start transferring leadership to the given server. */
int ClientTransfer(struct raft *r, raft_id server_id);

#endif /* CLIENT_H_ */
3 changes: 3 additions & 0 deletions src/raft.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ int raft_step(struct raft *r,
ClientCatchUp(r, event->catch_up.server_id);
rv = 0;
break;
case RAFT_TRANSFER:
rv = ClientTransfer(r, event->transfer.server_id);
break;
default:
rv = 0;
break;
Expand Down

0 comments on commit 2e0de4f

Please sign in to comment.