Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
RedisLabs Raft
Commits
75b01044
Commit
75b01044
authored
Nov 13, 2015
by
Willem Thiart
Browse files
Fixed partitions created by rogue leaders
Thanks to @ar104 for helping me with the fix!
parent
f563e205
Changes
3
Show whitespace changes
Inline
Side-by-side
src/raft_server.c
View file @
75b01044
...
...
@@ -126,7 +126,6 @@ void raft_become_follower(raft_server_t* me_)
{
__log
(
me_
,
"becoming follower"
);
raft_set_state
(
me_
,
RAFT_STATE_FOLLOWER
);
raft_vote
(
me_
,
-
1
);
}
int
raft_periodic
(
raft_server_t
*
me_
,
int
msec_since_last_period
)
...
...
@@ -171,13 +170,20 @@ int raft_recv_appendentries_response(raft_server_t* me_,
node
,
r
->
success
==
1
?
"success"
:
"fail"
,
r
->
current_idx
,
r
->
first_idx
);
// TODO: should force invalid leaders to stepdown
if
(
!
raft_is_leader
(
me_
))
return
-
1
;
raft_node_t
*
p
=
raft_get_node
(
me_
,
node
);
/* If response contains term T > currentTerm: set currentTerm = T
and convert to follower (§5.3) */
if
(
me
->
current_term
<
r
->
term
)
{
raft_set_current_term
(
me_
,
r
->
term
);
raft_become_follower
(
me_
);
return
0
;
}
if
(
0
==
r
->
success
)
{
/* If AppendEntries fails because of log inconsistency:
...
...
@@ -350,7 +356,10 @@ int raft_recv_requestvote(raft_server_t* me_, int node, msg_requestvote_t* vr,
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
if
(
raft_get_current_term
(
me_
)
<
vr
->
term
)
{
raft_set_current_term
(
me_
,
vr
->
term
);
raft_become_follower
(
me_
);
}
if
(
__should_grant_vote
(
me
,
vr
))
{
...
...
@@ -430,7 +439,8 @@ int raft_recv_entry(raft_server_t* me_, int node, msg_entry_t* e,
/* Only send new entries.
* Don't send the entry to peers who are behind, to prevent them from
* becomming congested. */
if
(
me
->
nodeid
!=
i
)
{
if
(
me
->
nodeid
!=
i
)
{
int
next_idx
=
raft_node_get_next_idx
(
raft_get_node
(
me_
,
i
));
int
last_log_idx
=
raft_get_current_idx
(
me_
);
if
(
next_idx
==
last_log_idx
)
...
...
src/raft_server_properties.c
View file @
75b01044
...
...
@@ -71,9 +71,13 @@ int raft_get_voted_for(raft_server_t* me_)
void
raft_set_current_term
(
raft_server_t
*
me_
,
const
int
term
)
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
if
(
me
->
current_term
<
term
)
{
me
->
current_term
=
term
;
me
->
voted_for
=
-
1
;
if
(
me
->
cb
.
persist_term
)
me
->
cb
.
persist_term
(
me_
,
me
->
udata
,
term
);
}
}
int
raft_get_current_term
(
raft_server_t
*
me_
)
...
...
tests/test_server.c
View file @
75b01044
...
...
@@ -511,6 +511,7 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
raft_add_node
(
r
,
(
void
*
)
2
,
0
);
raft_become_candidate
(
r
);
raft_set_current_term
(
r
,
1
);
CuAssertIntEquals
(
tc
,
0
,
raft_get_voted_for
(
r
));
/* current term is less than term */
msg_requestvote_t
rv
;
...
...
@@ -519,7 +520,9 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
rv
.
last_log_idx
=
1
;
msg_requestvote_response_t
rvr
;
raft_recv_requestvote
(
r
,
1
,
&
rv
,
&
rvr
);
CuAssertTrue
(
tc
,
1
==
raft_is_follower
(
r
));
CuAssertIntEquals
(
tc
,
1
,
raft_is_follower
(
r
));
CuAssertIntEquals
(
tc
,
2
,
raft_get_current_term
(
r
));
CuAssertIntEquals
(
tc
,
1
,
raft_get_voted_for
(
r
));
}
/* If votedFor is null or candidateId, and candidate's log is at
...
...
@@ -552,13 +555,13 @@ void TestRaft_follower_becomes_follower_is_follower(CuTest * tc)
CuAssertTrue
(
tc
,
raft_is_follower
(
r
));
}
void
TestRaft_follower_becomes_follower_clear
s
_voted_for
(
CuTest
*
tc
)
void
TestRaft_follower_becomes_follower_
does_not_
clear_voted_for
(
CuTest
*
tc
)
{
void
*
r
=
raft_new
();
raft_vote
(
r
,
1
);
CuAssertTrue
(
tc
,
1
==
raft_get_voted_for
(
r
));
raft_become_follower
(
r
);
CuAssertTrue
(
tc
,
-
1
==
raft_get_voted_for
(
r
));
CuAssertTrue
(
tc
,
1
==
raft_get_voted_for
(
r
));
}
/* 5.1 */
...
...
@@ -1219,8 +1222,10 @@ void TestRaft_candidate_recv_appendentries_frm_leader_results_in_follower(
raft_add_node
(
r
,
(
void
*
)
2
,
0
);
raft_set_state
(
r
,
RAFT_STATE_CANDIDATE
);
raft_vote
(
r
,
0
);
CuAssertTrue
(
tc
,
0
==
raft_is_follower
(
r
));
CuAssertTrue
(
tc
,
-
1
==
raft_get_current_leader
(
r
));
CuAssertTrue
(
tc
,
0
==
raft_get_current_term
(
r
));
/* receive recent appendentries */
msg_appendentries_t
ae
;
...
...
@@ -1232,6 +1237,8 @@ void TestRaft_candidate_recv_appendentries_frm_leader_results_in_follower(
CuAssertTrue
(
tc
,
1
==
raft_is_follower
(
r
));
/* after accepting a leader, it's available as the last known leader */
CuAssertTrue
(
tc
,
1
==
raft_get_current_leader
(
r
));
CuAssertTrue
(
tc
,
1
==
raft_get_current_term
(
r
));
CuAssertTrue
(
tc
,
-
1
==
raft_get_voted_for
(
r
));
}
/* Candidate 5.2 */
...
...
@@ -1662,16 +1669,16 @@ void TestRaft_leader_recv_appendentries_response_increase_commit_idx_when_majori
raft_send_appendentries
(
r
,
0
);
raft_send_appendentries
(
r
,
1
);
/* receive mock success responses */
aer
.
term
=
5
;
aer
.
term
=
1
;
aer
.
success
=
1
;
aer
.
current_idx
=
2
;
aer
.
first_idx
=
2
;
raft_recv_appendentries_response
(
r
,
0
,
&
aer
);
raft_recv_appendentries_response
(
r
,
1
,
&
aer
);
/* leader will now have majority followers who have appended this log */
CuAssert
True
(
tc
,
2
==
raft_get_commit_idx
(
r
));
CuAssert
IntEquals
(
tc
,
2
,
raft_get_commit_idx
(
r
));
raft_periodic
(
r
,
1
);
CuAssert
True
(
tc
,
2
==
raft_get_last_applied_idx
(
r
));
CuAssert
IntEquals
(
tc
,
2
,
raft_get_last_applied_idx
(
r
));
}
void
TestRaft_leader_recv_appendentries_response_retry_only_if_leader
(
CuTest
*
tc
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment