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
Willemt Raft
Commits
1aee978a
Commit
1aee978a
authored
Dec 30, 2015
by
Willem Thiart
Browse files
Add membership changes
parent
1c6cb689
Changes
6
Show whitespace changes
Inline
Side-by-side
include/raft.h
View file @
1aee978a
...
...
@@ -560,6 +560,11 @@ int raft_get_my_id(raft_server_t* me);
* @param[in] node The server to vote for */
void
raft_vote
(
raft_server_t
*
me_
,
raft_node_t
*
node
);
/** Vote for a server.
* This should be used to reload persistent state, ie. the voted-for field.
* @param[in] nodeid The server to vote for by nodeid */
void
raft_vote_for_nodeid
(
raft_server_t
*
me_
,
const
int
nodeid
);
/** Set the current term.
* This should be used to reload persistent state, ie. the current_term field.
* @param[in] term The new current term */
...
...
include/raft_private.h
View file @
1aee978a
...
...
@@ -21,7 +21,7 @@ typedef struct {
/* The candidate the server voted for in its current term,
* or Nil if it hasn't voted for any. */
raft_node_t
*
voted_for
;
int
voted_for
;
/* the log which is replicated */
void
*
log
;
...
...
src/raft_node.c
View file @
1aee978a
...
...
@@ -103,7 +103,6 @@ void raft_node_set_voting(raft_node_t* me_, int voting)
me
->
flags
|=
RAFT_NODE_VOTING
;
else
me
->
flags
&=
~
RAFT_NODE_VOTING
;
}
int
raft_node_is_voting
(
raft_node_t
*
me_
)
...
...
src/raft_server.c
View file @
1aee978a
...
...
@@ -44,7 +44,7 @@ raft_server_t* raft_new()
if
(
!
me
)
return
NULL
;
me
->
current_term
=
0
;
me
->
voted_for
=
NULL
;
me
->
voted_for
=
-
1
;
me
->
timeout_elapsed
=
0
;
me
->
request_timeout
=
200
;
me
->
election_timeout
=
1000
;
...
...
@@ -144,9 +144,7 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period)
}
else
if
(
me
->
election_timeout
<=
me
->
timeout_elapsed
)
{
if
(
1
==
me
->
num_nodes
)
raft_become_leader
(
me_
);
else
if
(
1
<
me
->
num_nodes
)
raft_election_start
(
me_
);
}
...
...
@@ -270,9 +268,6 @@ int raft_recv_appendentries(
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
assert
(
node
);
assert
(
node
!=
me
->
node
);
me
->
timeout_elapsed
=
0
;
if
(
0
<
ae
->
n_entries
)
...
...
@@ -285,11 +280,13 @@ int raft_recv_appendentries(
ae
->
prev_log_term
,
ae
->
n_entries
);
printf
(
"%p %p
\n
"
,
node
,
raft_get_current_leader_node
(
me_
));
r
->
term
=
me
->
current_term
;
if
(
raft_is_candidate
(
me_
)
&&
me
->
current_term
==
ae
->
term
)
{
me
->
voted_for
=
NULL
;
me
->
voted_for
=
-
1
;
raft_become_follower
(
me_
);
}
else
if
(
me
->
current_term
<
ae
->
term
)
...
...
@@ -402,7 +399,7 @@ static int __should_grant_vote(raft_server_private_t* me, msg_requestvote_t* vr)
/* TODO: if voted for is candiate return 1 (if below checks pass) */
/* we've already voted */
if
(
me
->
voted_for
)
if
(
0
<
me
->
voted_for
)
return
0
;
int
current_idx
=
raft_get_current_idx
((
void
*
)
me
);
...
...
@@ -427,9 +424,6 @@ int raft_recv_requestvote(raft_server_t* me_,
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
assert
(
node
);
assert
(
node
!=
me
->
node
);
if
(
raft_get_current_term
(
me_
)
<
vr
->
term
)
{
raft_set_current_term
(
me_
,
vr
->
term
);
...
...
@@ -442,7 +436,7 @@ int raft_recv_requestvote(raft_server_t* me_,
* Both states would have voted for themselves */
assert
(
!
(
raft_is_leader
(
me_
)
||
raft_is_candidate
(
me_
)));
raft_vote
(
me_
,
node
);
raft_vote
_for_nodeid
(
me_
,
vr
->
candidate_id
);
r
->
vote_granted
=
1
;
/* there must be in an election. */
...
...
@@ -662,7 +656,7 @@ void raft_send_appendentries_all(raft_server_t* me_)
me
->
timeout_elapsed
=
0
;
for
(
i
=
0
;
i
<
me
->
num_nodes
;
i
++
)
if
(
me
->
node
!=
me
->
nodes
[
i
]
&&
raft_node_is_voting
(
me
->
nodes
[
i
])
)
if
(
me
->
node
!=
me
->
nodes
[
i
])
raft_send_appendentries
(
me_
,
me
->
nodes
[
i
]);
}
...
...
@@ -702,21 +696,24 @@ int raft_get_nvotes_for_me(raft_server_t* me_)
if
(
raft_node_has_vote_for_me
(
me
->
nodes
[
i
]))
votes
+=
1
;
if
(
me
->
voted_for
==
me
->
node
)
if
(
me
->
voted_for
==
raft_get_nodeid
(
me_
)
)
votes
+=
1
;
return
votes
;
}
void
raft_vote
(
raft_server_t
*
me_
,
raft_node_t
*
node
)
void
raft_vote
_for_nodeid
(
raft_server_t
*
me_
,
const
int
node
id
)
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
assert
(
!
me
->
voted_for
||
node
!=
me
->
voted_for
);
me
->
voted_for
=
node
;
me
->
voted_for
=
nodeid
;
if
(
me
->
cb
.
persist_vote
)
me
->
cb
.
persist_vote
(
me_
,
me
->
udata
,
raft_node_get_id
(
node
));
me
->
cb
.
persist_vote
(
me_
,
me
->
udata
,
nodeid
);
}
void
raft_vote
(
raft_server_t
*
me_
,
raft_node_t
*
node
)
{
raft_vote_for_nodeid
(
me_
,
node
?
raft_node_get_id
(
node
)
:
-
1
);
}
int
raft_msg_entry_response_committed
(
raft_server_t
*
me_
,
...
...
src/raft_server_properties.c
View file @
1aee978a
...
...
@@ -66,9 +66,7 @@ int raft_get_log_count(raft_server_t* me_)
int
raft_get_voted_for
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
if
(
me
->
voted_for
)
return
raft_node_get_id
(
me
->
voted_for
);
return
-
1
;
return
me
->
voted_for
;
}
void
raft_set_current_term
(
raft_server_t
*
me_
,
const
int
term
)
...
...
@@ -77,7 +75,7 @@ void raft_set_current_term(raft_server_t* me_, const int term)
if
(
me
->
current_term
<
term
)
{
me
->
current_term
=
term
;
me
->
voted_for
=
NULL
;
me
->
voted_for
=
-
1
;
if
(
me
->
cb
.
persist_term
)
me
->
cb
.
persist_term
(
me_
,
me
->
udata
,
term
);
}
...
...
tests/test_server.c
View file @
1aee978a
...
...
@@ -581,6 +581,7 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
/* current term is less than term */
msg_requestvote_t
rv
;
memset
(
&
rv
,
0
,
sizeof
(
msg_requestvote_t
));
rv
.
candidate_id
=
2
;
rv
.
term
=
2
;
rv
.
last_log_idx
=
1
;
msg_requestvote_response_t
rvr
;
...
...
@@ -590,6 +591,30 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
CuAssertIntEquals
(
tc
,
2
,
raft_get_voted_for
(
r
));
}
void
TestRaft_server_recv_requestvote_depends_on_candidate_id
(
CuTest
*
tc
)
{
void
*
r
=
raft_new
();
raft_add_node
(
r
,
NULL
,
1
,
1
);
raft_add_node
(
r
,
NULL
,
2
,
0
);
raft_become_candidate
(
r
);
raft_set_current_term
(
r
,
1
);
CuAssertIntEquals
(
tc
,
1
,
raft_get_voted_for
(
r
));
/* current term is less than term */
msg_requestvote_t
rv
;
memset
(
&
rv
,
0
,
sizeof
(
msg_requestvote_t
));
rv
.
candidate_id
=
3
;
rv
.
term
=
2
;
rv
.
last_log_idx
=
1
;
msg_requestvote_response_t
rvr
;
raft_recv_requestvote
(
r
,
NULL
,
&
rv
,
&
rvr
);
CuAssertIntEquals
(
tc
,
1
,
raft_is_follower
(
r
));
CuAssertIntEquals
(
tc
,
2
,
raft_get_current_term
(
r
));
CuAssertIntEquals
(
tc
,
3
,
raft_get_voted_for
(
r
));
}
/* If votedFor is null or candidateId, and candidate's log is at
* least as up-to-date as local log, grant vote (5.2, 5.4) */
void
TestRaft_server_dont_grant_vote_if_we_didnt_vote_for_this_candidate
(
...
...
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