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
24f6666a
Commit
24f6666a
authored
Oct 22, 2013
by
willem
Browse files
Passing some tests
parent
0819b2e4
Changes
7
Hide whitespace changes
Inline
Side-by-side
raft.h
View file @
24f6666a
...
...
@@ -137,11 +137,11 @@ typedef void* raft_peer_t;
raft_server_t
*
raft_new
();
void
*
raft_get_voted_for
(
raft_server_t
*
me
);
int
raft_get_voted_for
(
raft_server_t
*
me
);
void
raft_set_external_functions
(
raft_server_t
*
me
,
raft_external_functions_t
*
funcs
,
void
*
caller
);
void
raft_election_start
(
void
*
r
);
void
raft_election_start
(
raft_server_t
*
me
);
void
raft_become_leader
(
raft_server_t
*
me
);
...
...
@@ -216,3 +216,5 @@ int raft_peer_get_next_index(raft_peer_t* peer);
void
raft_peer_set_next_index
(
raft_peer_t
*
peer
,
int
nextIdx
);
void
raft_set_configuration
(
raft_server_t
*
me_
,
raft_peer_configuration_t
*
peers
);
int
raft_votes_is_majority
(
const
int
npeers
,
const
int
nvotes
);
raft_candidate.c
View file @
24f6666a
...
...
@@ -43,10 +43,10 @@ typedef struct {
/* The set of servers from which the candidate has
* received a RequestVote response in this term. */
//
int votes
R
esponded;
int
votes
_r
esponded
;
/* The set of servers from which the candidate has received a vote in this term. */
//
int votes
G
ranted;
int
votes
_g
ranted
;
}
candidate_t
;
...
...
raft_server.c
View file @
24f6666a
...
...
@@ -49,7 +49,7 @@ typedef struct {
/* The candidate the server voted for in its current term,
* or Nil if it hasn't voted for any. */
void
*
voted_for
;
int
voted_for
;
/* the log which is replicated */
void
*
log
;
...
...
@@ -80,9 +80,14 @@ typedef struct {
raft_peer_t
*
peers
;
int
npeers
;
int
election_timeout
;
// hashmap_t* peers;
// int log_Size;
/* who has voted for me */
int
*
votes_for_me
;
}
raft_server_private_t
;
...
...
@@ -107,6 +112,7 @@ raft_server_t* raft_new()
raft_server_private_t
*
me
;
me
=
calloc
(
1
,
sizeof
(
raft_server_private_t
));
me
->
voted_for
=
-
1
;
me
->
current_index
=
0
;
me
->
timeout_elapased
=
0
;
// me->peers = hashmap_new(__peer_hash, __peer_compare, 100);
...
...
@@ -118,15 +124,18 @@ void raft_free(raft_server_t* me_)
free
(
me_
);
}
void
raft_set_state
(
raft_server_t
*
me_
)
void
raft_set_state
(
raft_server_t
*
me_
,
int
state
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
me
->
state
=
state
;
}
int
raft_get_state
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
return
0
;
return
me
->
state
;
}
void
raft_set_external_functions
(
raft_server_t
*
me_
,
raft_external_functions_t
*
funcs
,
void
*
caller
)
...
...
@@ -137,16 +146,19 @@ void raft_set_external_functions(raft_server_t* me_, raft_external_functions_t*
me
->
ext_func
=
funcs
;
}
void
raft_election_start
(
void
*
r
)
void
raft_election_start
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
me
->
timeout_elapased
=
0
;
/* time to throw our hat in */
raft_become_candidate
(
me_
);
}
/**
* Candidate i transitions to leader. */
void
raft_become_leader
(
raft_server_t
*
me_
)
{
raft_set_state
(
me_
,
RAFT_STATE_LEADER
);
}
void
raft_become_candidate
(
raft_server_t
*
me_
)
...
...
@@ -156,8 +168,9 @@ void raft_become_candidate(raft_server_t* me_)
void
*
p
;
int
ii
;
memset
(
me
->
votes_for_me
,
0
,
sizeof
(
int
)
*
me
->
npeers
);
me
->
current_term
+=
1
;
me
->
voted_for
=
me
;
me
->
voted_for
=
0
;
me
->
timeout_elapased
=
0
;
// for (hashmap_iterator(me->peers, &iter);
...
...
@@ -202,7 +215,14 @@ int raft_get_timeout_elapsed(raft_server_t* me_)
int
raft_periodic
(
raft_server_t
*
me_
,
int
msec_since_last_period
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
me
->
timeout_elapased
+=
msec_since_last_period
;
if
(
me
->
election_timeout
<
me
->
timeout_elapased
)
{
raft_election_start
(
me_
);
}
return
0
;
}
...
...
@@ -220,11 +240,56 @@ int raft_recv_appendentries_response(raft_server_t* me_, int peer, msg_appendent
int
raft_recv_requestvote
(
raft_server_t
*
me_
,
int
peer
,
msg_requestvote_t
*
vr
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
msg_requestvote_response_t
r
;
if
(
-
1
==
me
->
voted_for
)
{
r
.
vote_granted
=
0
;
}
else
{
me
->
voted_for
=
peer
;
}
if
(
me
->
ext_func
&&
me
->
ext_func
->
send
)
me
->
ext_func
->
send
(
me
->
caller
,
NULL
,
peer
,
(
void
*
)
&
r
,
sizeof
(
msg_requestvote_response_t
));
return
0
;
}
int
raft_votes_is_majority
(
const
int
npeers
,
const
int
nvotes
)
{
int
half
;
half
=
npeers
/
2
;
return
half
+
1
<=
nvotes
;
}
/**
* @param peer The peer this response was sent by */
int
raft_recv_requestvote_response
(
raft_server_t
*
me_
,
int
peer
,
msg_requestvote_response_t
*
r
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
assert
(
peer
<
me
->
npeers
);
if
(
r
->
term
!=
raft_get_current_term
(
me_
))
return
0
;
if
(
1
==
r
->
vote_granted
)
me
->
votes_for_me
[
peer
]
=
1
;
int
votes
;
votes
=
raft_get_nvotes_for_me
(
me_
);
if
(
raft_votes_is_majority
(
me
->
npeers
,
votes
))
{
raft_become_leader
(
me_
);
}
return
0
;
}
...
...
@@ -234,6 +299,8 @@ void raft_execute_command(raft_server_t* me_)
void
raft_set_election_timeout
(
raft_server_t
*
me_
,
int
millisec
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
me
->
election_timeout
=
millisec
;
}
void
raft_set_request_timeout
(
raft_server_t
*
me_
,
int
millisec
)
...
...
@@ -293,7 +360,7 @@ int raft_get_log_count(raft_server_t* me_)
return
0
;
}
void
*
raft_get_voted_for
(
raft_server_t
*
me_
)
int
raft_get_voted_for
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
return
me
->
voted_for
;
...
...
@@ -331,8 +398,7 @@ int raft_is_follower(raft_server_t* me_)
int
raft_is_leader
(
raft_server_t
*
me_
)
{
return
0
;
return
raft_get_state
(
me_
)
==
RAFT_STATE_LEADER
;
}
int
raft_is_candidate
(
raft_server_t
*
me_
)
...
...
@@ -341,8 +407,20 @@ int raft_is_candidate(raft_server_t* me_)
return
0
;
}
int
raft_get_my_id
(
raft_server_t
*
me_
)
{
return
0
;
}
int
raft_send_requestvote
(
raft_server_t
*
me_
,
int
peer
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
msg_requestvote_t
rv
;
rv
.
term
=
raft_get_current_term
(
me_
);
rv
.
last_log_index
=
raft_get_current_index
(
me_
);
if
(
me
->
ext_func
&&
me
->
ext_func
->
send
)
me
->
ext_func
->
send
(
me
->
caller
,
NULL
,
peer
,
(
void
*
)
&
rv
,
sizeof
(
msg_requestvote_t
));
return
0
;
}
...
...
@@ -385,6 +463,7 @@ void raft_set_configuration(raft_server_t* me_, raft_peer_configuration_t* peers
raft_server_private_t
*
me
=
(
void
*
)
me_
;
int
npeers
=
0
;
/* TODO: one allocation only please */
while
(
peers
->
udata_address
)
{
npeers
++
;
...
...
@@ -393,4 +472,34 @@ void raft_set_configuration(raft_server_t* me_, raft_peer_configuration_t* peers
me
->
peers
[
npeers
-
1
]
=
raft_peer_new
(
peers
);
peers
++
;
}
me
->
votes_for_me
=
calloc
(
npeers
,
sizeof
(
int
));
}
/**
* @return number of peers that this server has */
int
raft_get_npeers
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
return
me
->
npeers
;
}
/**
* @return number of votes this server has received this election */
int
raft_get_nvotes_for_me
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
void
*
)
me_
;
int
i
,
votes
;
for
(
i
=
0
,
votes
=
0
;
i
<
me
->
npeers
;
i
++
)
{
if
(
1
==
me
->
votes_for_me
[
i
])
votes
+=
1
;
}
if
(
raft_get_voted_for
(
me_
)
==
raft_get_my_id
(
me_
))
votes
+=
1
;
return
votes
;
}
test_candidate.c
View file @
24f6666a
...
...
@@ -28,9 +28,10 @@ void TestRaft_follower_becoming_candidate_votes_for_self(CuTest * tc)
r
=
raft_new
();
CuAssertTrue
(
tc
,
NULL
==
raft_get_voted_for
(
r
));
CuAssertTrue
(
tc
,
-
1
==
raft_get_voted_for
(
r
));
raft_become_candidate
(
r
);
CuAssertTrue
(
tc
,
r
==
raft_get_voted_for
(
r
));
CuAssertTrue
(
tc
,
0
==
raft_get_voted_for
(
r
));
CuAssertTrue
(
tc
,
1
==
raft_get_nvotes_for_me
(
r
));
}
/* Candidate 5.2 */
...
...
@@ -39,9 +40,10 @@ void TestRaft_follower_becoming_candidate_resets_election_timeout(CuTest * tc)
void
*
r
;
r
=
raft_new
();
raft_set_election_timeout
(
r
,
1000
);
CuAssertTrue
(
tc
,
0
==
raft_get_timeout_elapsed
(
r
));
raft_periodic
(
r
,
100
);
raft_periodic
(
r
,
100
);
CuAssertTrue
(
tc
,
100
==
raft_get_timeout_elapsed
(
r
));
raft_become_candidate
(
r
);
...
...
@@ -113,15 +115,19 @@ void TestRaft_candidate_election_timeout_and_no_leader_results_in_new_election(C
r
=
raft_new
();
raft_set_configuration
(
r
,
cfg
);
raft_set_external_functions
(
r
,
&
funcs
,
sender
);
raft_set_current_term
(
r
,
1
);
raft_set_state
(
r
,
RAFT_STATE_CANDIDATE
);
raft_periodic
(
r
,
1
);
raft_set_election_timeout
(
r
,
1000
);
raft_recv_requestvote_response
(
r
,
1
,
&
vr
);
CuAssertTrue
(
tc
,
0
==
raft_is_leader
(
r
));
/* now has majority */
raft_recv_requestvote_response
(
r
,
1
,
&
vr
);
CuAssertTrue
(
tc
,
1
==
raft_is_leader
(
r
));
/* server wants to be leader, so becomes candidate */
raft_become_candidate
(
r
);
CuAssertTrue
(
tc
,
1
==
raft_get_current_term
(
r
));
/* clock over (ie. 1000 + 1), causing new election */
raft_periodic
(
r
,
1001
);
CuAssertTrue
(
tc
,
2
==
raft_get_current_term
(
r
));
/* receiving this vote gives the server majority */
// raft_recv_requestvote_response(r,1,&vr);
// CuAssertTrue(tc, 1 == raft_is_leader(r));
}
/* Candidate 5.2 */
...
...
@@ -138,26 +144,36 @@ void TestRaft_candidate_receives_majority_of_votes_becomes_leader(CuTest * tc)
raft_peer_configuration_t
cfg
[]
=
{
{(
-
1
),(
void
*
)
1
},
{(
-
1
),(
void
*
)
2
},
{(
-
1
),(
void
*
)
3
},
{(
-
1
),(
void
*
)
4
},
{(
-
1
),(
void
*
)
5
},
{(
-
1
),
NULL
}};
msg_requestvote_response_t
vr
;
memset
(
&
vr
,
0
,
sizeof
(
msg_requestvote_response_t
));
vr
.
term
=
1
;
vr
.
vote_granted
=
1
;
sender
=
sender_new
();
r
=
raft_new
();
raft_set_configuration
(
r
,
cfg
);
CuAssertTrue
(
tc
,
5
==
raft_get_npeers
(
r
));
raft_set_external_functions
(
r
,
&
funcs
,
sender
);
raft_
set_current_term
(
r
,
1
);
raft_
s
et_
state
(
r
,
RAFT_STATE_CANDIDATE
);
raft_
become_candidate
(
r
);
CuAssertTrue
(
tc
,
1
==
raft_
g
et_
current_term
(
r
)
);
/* a vote for us */
memset
(
&
vr
,
0
,
sizeof
(
msg_requestvote_response_t
));
vr
.
term
=
1
;
vr
.
vote_granted
=
1
;
/* get one vote */
raft_recv_requestvote_response
(
r
,
1
,
&
vr
);
CuAssertTrue
(
tc
,
2
==
raft_get_nvotes_for_me
(
r
));
CuAssertTrue
(
tc
,
0
==
raft_is_leader
(
r
));
/* now has majority */
raft_recv_requestvote_response
(
r
,
1
,
&
vr
);
/* get another vote
* now has majority (ie. 3/5 votes) */
raft_recv_requestvote_response
(
r
,
2
,
&
vr
);
CuAssertTrue
(
tc
,
3
==
raft_get_nvotes_for_me
(
r
));
CuAssertTrue
(
tc
,
1
==
raft_is_leader
(
r
));
}
...
...
@@ -178,29 +194,21 @@ void TestRaft_candidate_will_not_respond_to_voterequest_if_it_has_already_voted(
{(
-
1
),(
void
*
)
2
},
{(
-
1
),
NULL
}};
msg_appendentries_t
ae
;
memset
(
&
ae
,
0
,
sizeof
(
msg_appendentries_t
));
msg_requestvote_response_t
*
rvr
;
msg_requestvote_t
rv
;
memset
(
&
rv
,
0
,
sizeof
(
msg_requestvote_t
));
sender
=
sender_new
();
r
=
raft_new
();
raft_set_configuration
(
r
,
cfg
);
raft_set_election_timeout
(
r
,
1000
);
/* three nodes */
raft_set_external_functions
(
r
,
&
funcs
,
sender
);
raft_set_current_term
(
r
,
1
);
raft_set_state
(
r
,
RAFT_STATE_CANDIDATE
);
//raft_recv_requestvote(
CuAssertTrue
(
tc
,
0
==
raft_is_follower
(
r
));
raft_periodic
(
r
,
1
);
raft_recv_appendentries
(
r
,
1
,
&
ae
);
CuAssertTrue
(
tc
,
1
==
raft_is_follower
(
r
));
raft_vote
(
r
,
1
);
memset
(
&
rv
,
0
,
sizeof
(
msg_requestvote_t
));
raft_recv_requestvote
(
r
,
1
,
&
rv
);
rvr
=
sender_poll_msg
(
sender
);
CuAssertTrue
(
tc
,
0
==
rvr
->
vote_granted
);
}
/* Candidate 5.2 */
...
...
@@ -220,7 +228,6 @@ void TestRaft_candidate_requestvote_includes_logIndex(CuTest * tc)
{(
-
1
),(
void
*
)
2
},
{(
-
1
),
NULL
}};
sender
=
sender_new
();
r
=
raft_new
();
raft_set_configuration
(
r
,
cfg
);
...
...
@@ -266,7 +273,7 @@ void TestRaft_candidate_recv_appendentries_frm_leader_results_in_follower(CuTest
raft_set_external_functions
(
r
,
&
funcs
,
sender
);
raft_set_current_term
(
r
,
1
);
raft_set_state
(
r
,
RAFT_STATE_CANDIDATE
);
CuAssertTrue
(
tc
,
0
==
raft_is_follower
(
r
));
CuAssertTrue
(
tc
,
raft_get_my_id
(
r
)
==
raft_is_follower
(
r
));
raft_periodic
(
r
,
1
);
raft_recv_appendentries
(
r
,
1
,
&
ae
);
...
...
test_leader.c
View file @
24f6666a
...
...
@@ -9,6 +9,16 @@
#include "raft.h"
#include "mock_send_functions.h"
void
TestRaft_leader_becomes_leader_is_leader
(
CuTest
*
tc
)
{
void
*
r
;
r
=
raft_new
();
raft_become_leader
(
r
);
CuAssertTrue
(
tc
,
raft_is_leader
(
r
));
}
/* 5.2 */
void
TestRaft_leader_when_it_becomes_a_leader_sends_empty_appendentries
(
CuTest
*
tc
)
{
...
...
test_server.c
View file @
24f6666a
...
...
@@ -9,6 +9,17 @@
#include "raft.h"
#if 0
void T_estRaft_server_voted_for_records_who_we_voted_for(CuTest * tc)
{
void *r;
r = raft_new();
raft_vote(r,2);
CuAssertTrue(tc, 1 == raft_get_voted_for(r));
}
#endif
void
TestRaft_server_idx_starts_at_1
(
CuTest
*
tc
)
{
void
*
r
;
...
...
@@ -128,3 +139,47 @@ void TestRaft_server_increment_lastApplied_when_lastApplied_lt_commitIndex(CuTes
CuAssertTrue
(
tc
,
5
==
raft_get_lastapplied_index
(
r
));
}
void
TestRaft_server_periodic_elapses_election_timeout
(
CuTest
*
tc
)
{
void
*
r
;
r
=
raft_new
();
/* we don't want to set the timeout to zero */
raft_set_election_timeout
(
r
,
1000
);
CuAssertTrue
(
tc
,
0
==
raft_get_timeout_elapsed
(
r
));
raft_periodic
(
r
,
0
);
CuAssertTrue
(
tc
,
0
==
raft_get_timeout_elapsed
(
r
));
raft_periodic
(
r
,
100
);
CuAssertTrue
(
tc
,
100
==
raft_get_timeout_elapsed
(
r
));
}
void
TestRaft_server_election_timeout_sets_to_zero_when_elapsed_time_greater_than_timeout
(
CuTest
*
tc
)
{
void
*
r
;
r
=
raft_new
();
raft_set_election_timeout
(
r
,
1000
);
/* greater than 1000 */
raft_periodic
(
r
,
2000
);
CuAssertTrue
(
tc
,
0
==
raft_get_timeout_elapsed
(
r
));
}
void
TestRaft_server_cfg_sets_npeers
(
CuTest
*
tc
)
{
void
*
r
;
/* 2 peers */
raft_peer_configuration_t
cfg
[]
=
{
{(
-
1
),(
void
*
)
1
},
{(
-
1
),(
void
*
)
2
},
{(
-
1
),
NULL
}};
r
=
raft_new
();
raft_set_configuration
(
r
,
cfg
);
CuAssertTrue
(
tc
,
2
==
raft_get_npeers
(
r
));
}
test_server_request_vote.c
View file @
24f6666a
...
...
@@ -12,6 +12,54 @@
/* If term > currentTerm, set currentTerm to term (step down if candidate or leader) */
//void TestRaft_when_recv_requestvote_step_down_if_term_is_greater(CuTest * tc)
void
TestRaft_votes_are_majority_is_true
(
CuTest
*
tc
)
{
/* 1 of 3 = lose */
CuAssertTrue
(
tc
,
0
==
raft_votes_is_majority
(
3
,
1
));
/* 2 of 3 = win */
CuAssertTrue
(
tc
,
0
==
raft_votes_is_majority
(
3
,
2
));
/* 2 of 5 = lose */
CuAssertTrue
(
tc
,
0
==
raft_votes_is_majority
(
5
,
2
));
/* 3 of 5 = win */
CuAssertTrue
(
tc
,
0
==
raft_votes_is_majority
(
5
,
3
));
/* 2 of 1?? This is an error */
CuAssertTrue
(
tc
,
0
==
raft_votes_is_majority
(
1
,
2
));
}
void
TestRaft_server_increase_votes_for_me_when_receive_request_vote_response
(
CuTest
*
tc
)
{
void
*
r
;
msg_requestvote_t
rv
;
msg_requestvote_response_t
*
rvr
;
/* 2 peers */
raft_peer_configuration_t
cfg
[]
=
{
{(
-
1
),(
void
*
)
1
},
{(
-
1
),(
void
*
)
2
},
{(
-
1
),
NULL
}};
memset
(
&
rv
,
0
,
sizeof
(
msg_requestvote_response_t
));
rv
.
term
=
1
;
r
=
raft_new
();
raft_set_configuration
(
r
,
cfg
);
raft_set_current_term
(
r
,
1
);
CuAssertTrue
(
tc
,
0
==
raft_get_nvotes_for_me
(
r
));
raft_recv_requestvote
(
r
,
1
,
&
rv
);
CuAssertTrue
(
tc
,
1
==
raft_get_nvotes_for_me
(
r
));
raft_vote
(
r
,
1
);
CuAssertTrue
(
tc
,
2
==
raft_get_nvotes_for_me
(
r
));
}
// Reply false if term < currentTerm (5.1)
void
TestRaft_server_recv_requestvote_reply_false_if_term_less_than_current_term
(
...
...
@@ -89,3 +137,5 @@ void TestRaft_server_dont_grant_vote_if_we_didnt_vote_for_this_candidate(
CuAssertTrue
(
tc
,
0
==
rvr
->
vote_granted
);
}
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