Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
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
Hide 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_
;
me
->
current_term
=
term
;
if
(
me
->
cb
.
persist_term
)
me
->
cb
.
persist_term
(
me_
,
me
->
udata
,
term
);
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