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
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