summaryrefslogtreecommitdiff
path: root/ovsdb/raft.c
diff options
context:
space:
mode:
authorHan Zhou <hzhou8@ebay.com>2019-08-19 09:29:59 -0700
committerBen Pfaff <blp@ovn.org>2019-08-21 11:30:07 -0700
commit923f01cad678228224ae4fe86466e2f61ab2c9d0 (patch)
treeb2fa82679cd8d695ac0bf3bb54cf75db84bc5c08 /ovsdb/raft.c
parent89771c1e65304b815ec01ec0f11affac01d62169 (diff)
downloadopenvswitch-923f01cad678228224ae4fe86466e2f61ab2c9d0.tar.gz
raft.c: Set candidate_retrying if no leader elected since last election.
candiate_retrying is used to determine if the current node is disconnected from the cluster when the node is in candiate role. However, a node can flap between candidate and follower role before a leader is elected when majority of the cluster is down, so is_connected() will flap, too, which confuses clients. This patch avoids the flapping with the help of a new member had_leader, so that if no leader was elected since last election, we know we are still retrying, and keep as disconnected from the cluster. Signed-off-by: Han Zhou <hzhou8@ebay.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'ovsdb/raft.c')
-rw-r--r--ovsdb/raft.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index 71c5a7e1a..ca86830f3 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -285,8 +285,13 @@ struct raft {
/* Candidates only. Reinitialized at start of election. */
int n_votes; /* Number of votes for me. */
- bool candidate_retrying; /* The first round of election timed-out and it
- is now retrying. */
+
+ /* Followers and candidates only. */
+ bool candidate_retrying; /* The earlier election timed-out and we are
+ now retrying. */
+ bool had_leader; /* There has been leader elected since last
+ election initiated. This is to help setting
+ candidate_retrying. */
};
/* All Raft structures. */
@@ -344,6 +349,7 @@ static bool raft_handle_write_error(struct raft *, struct ovsdb_error *);
static void raft_run_reconfigure(struct raft *);
+static void raft_set_leader(struct raft *, const struct uuid *sid);
static struct raft_server *
raft_find_server(const struct raft *raft, const struct uuid *sid)
{
@@ -996,11 +1002,13 @@ raft_get_sid(const struct raft *raft)
bool
raft_is_connected(const struct raft *raft)
{
- return (!(raft->role == RAFT_CANDIDATE && raft->candidate_retrying)
+ bool ret = (!raft->candidate_retrying
&& !raft->joining
&& !raft->leaving
&& !raft->left
&& !raft->failed);
+ VLOG_DBG("raft_is_connected: %s\n", ret? "true": "false");
+ return ret;
}
/* Returns true if 'raft' is the cluster leader. */
@@ -1615,8 +1623,11 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
}
ovs_assert(raft->role != RAFT_LEADER);
- raft->candidate_retrying = (raft->role == RAFT_CANDIDATE);
raft->role = RAFT_CANDIDATE;
+ /* If there was no leader elected since last election, we know we are
+ * retrying now. */
+ raft->candidate_retrying = !raft->had_leader;
+ raft->had_leader = false;
raft->n_votes = 0;
@@ -2486,6 +2497,14 @@ raft_server_init_leader(struct raft *raft, struct raft_server *s)
}
static void
+raft_set_leader(struct raft *raft, const struct uuid *sid)
+{
+ raft->leader_sid = *sid;
+ raft->had_leader = true;
+ raft->candidate_retrying = false;
+}
+
+static void
raft_become_leader(struct raft *raft)
{
log_all_commands(raft);
@@ -2497,7 +2516,7 @@ raft_become_leader(struct raft *raft)
ovs_assert(raft->role != RAFT_LEADER);
raft->role = RAFT_LEADER;
- raft->leader_sid = raft->sid;
+ raft_set_leader(raft, &raft->sid);
raft_reset_election_timer(raft);
raft_reset_ping_timer(raft);
@@ -2891,7 +2910,7 @@ raft_update_leader(struct raft *raft, const struct uuid *sid)
raft_get_nickname(raft, sid, buf, sizeof buf),
raft->term);
}
- raft->leader_sid = *sid;
+ raft_set_leader(raft, sid);
/* Record the leader to the log. This is not used by the algorithm
* (although it could be, for quick restart), but it is used for