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
e1569508
Unverified
Commit
e1569508
authored
Oct 03, 2022
by
Hanna Fadida
Committed by
GitHub
Oct 03, 2022
Browse files
clean up add node flows (#147)
parent
4bb63026
Changes
6
Show whitespace changes
Inline
Side-by-side
include/raft.h
View file @
e1569508
...
...
@@ -957,7 +957,7 @@ void raft_set_callbacks(raft_server_t* me, raft_cbs_t* funcs, void* user_data);
* @param[in] is_self Set to 1 if this "node" is this server
* @return
* node if it was successfully added;
* NULL if
the
node already exists */
* NULL if
a voting
node already exists */
raft_node_t
*
raft_add_node
(
raft_server_t
*
me
,
void
*
user_data
,
raft_node_id_t
id
,
int
is_self
);
/** Add a node which does not participate in voting.
...
...
include/raft_private.h
View file @
e1569508
...
...
@@ -85,7 +85,7 @@ struct raft_server {
/* my node ID */
raft_node_t
*
node
;
/* the log which has a voting cfg change, otherwise -1 */
/* the log
index
which has a voting cfg change, otherwise -1 */
raft_index_t
voting_cfg_change_log_idx
;
int
snapshot_in_progress
;
...
...
@@ -160,7 +160,7 @@ void raft_set_last_applied_idx(raft_server_t *me, raft_index_t idx);
void
raft_set_state
(
raft_server_t
*
me
,
int
state
);
raft_node_t
*
raft_node_new
(
void
*
udata
,
raft_node_id_t
id
);
raft_node_t
*
raft_node_new
(
void
*
udata
,
raft_node_id_t
id
,
int
voting
);
void
raft_node_free
(
raft_node_t
*
node
);
...
...
@@ -172,7 +172,7 @@ raft_index_t raft_node_get_next_idx(raft_node_t *node);
void
raft_node_clear_flags
(
raft_node_t
*
node
);
void
raft_node_vote_for_me
(
raft_node_t
*
node
,
int
vote
);
void
raft_node_
set_
vote
d
_for_me
(
raft_node_t
*
node
,
int
vote
);
int
raft_node_has_vote_for_me
(
raft_node_t
*
node
);
...
...
src/raft_node.c
View file @
e1569508
...
...
@@ -37,7 +37,7 @@ struct raft_node {
raft_size_t
snapshot_offset
;
};
raft_node_t
*
raft_node_new
(
void
*
udata
,
raft_node_id_t
id
)
raft_node_t
*
raft_node_new
(
void
*
udata
,
raft_node_id_t
id
,
int
voting
)
{
raft_node_t
*
me
;
...
...
@@ -50,7 +50,7 @@ raft_node_t *raft_node_new(void *udata, raft_node_id_t id)
me
->
next_idx
=
1
;
me
->
match_idx
=
0
;
me
->
id
=
id
;
me
->
flags
=
RAFT_NODE_VOTING
;
raft_node_set_voting
(
me
,
voting
)
;
return
me
;
}
...
...
@@ -128,7 +128,7 @@ void raft_node_clear_flags(raft_node_t *node)
node
->
flags
=
0
;
}
void
raft_node_vote_for_me
(
raft_node_t
*
node
,
const
int
vote
)
void
raft_node_
set_
vote
d
_for_me
(
raft_node_t
*
node
,
int
vote
)
{
if
(
vote
)
{
node
->
flags
|=
RAFT_NODE_VOTED_FOR_ME
;
...
...
src/raft_server.c
View file @
e1569508
...
...
@@ -110,6 +110,7 @@ raft_server_t* raft_new_with_log(const raft_log_impl_t *log_impl, void *log_arg)
me
->
node_transferring_leader_to
=
RAFT_NODE_ID_NONE
;
me
->
auto_flush
=
1
;
me
->
exec_deadline
=
LLONG_MAX
;
me
->
msg_id
=
0
;
raft_update_quorum_meta
(
me
,
me
->
msg_id
);
...
...
@@ -174,7 +175,7 @@ void raft_clear(raft_server_t* me)
me
->
log_impl
->
reset
(
me
->
log
,
1
,
1
);
}
raft_node_t
*
raft_add_node_internal
(
raft_server_t
*
me
,
raft_entry_t
*
ety
,
void
*
udata
,
raft_node_id_t
id
,
int
is_self
)
raft_node_t
*
raft_add_node_internal
(
raft_server_t
*
me
,
raft_entry_t
*
ety
,
void
*
udata
,
raft_node_id_t
id
,
int
is_self
,
int
voting
)
{
if
(
id
==
RAFT_NODE_ID_NONE
)
return
NULL
;
...
...
@@ -183,17 +184,18 @@ raft_node_t* raft_add_node_internal(raft_server_t* me, raft_entry_t *ety, void*
raft_node_t
*
node
=
raft_get_node
(
me
,
id
);
if
(
node
)
{
if
(
!
raft_node_is_voting
(
node
))
/* node can be promoted only from a non voting state into a voting one */
if
(
!
raft_node_is_voting
(
node
)
&&
voting
)
{
raft_node_set_voting
(
node
,
1
);
return
node
;
}
else
/* we shouldn't add a node twice */
/* we shouldn't add a node
with the same voting mode
twice */
return
NULL
;
}
node
=
raft_node_new
(
udata
,
id
);
node
=
raft_node_new
(
udata
,
id
,
voting
);
if
(
!
node
)
return
NULL
;
...
...
@@ -208,8 +210,6 @@ raft_node_t* raft_add_node_internal(raft_server_t* me, raft_entry_t *ety, void*
if
(
is_self
)
me
->
node
=
me
->
nodes
[
me
->
num_nodes
-
1
];
node
=
me
->
nodes
[
me
->
num_nodes
-
1
];
if
(
me
->
cb
.
notify_membership_event
)
{
me
->
cb
.
notify_membership_event
(
me
,
me
->
udata
,
node
,
ety
,
RAFT_MEMBERSHIP_ADD
);
...
...
@@ -218,27 +218,14 @@ raft_node_t* raft_add_node_internal(raft_server_t* me, raft_entry_t *ety, void*
return
node
;
}
static
raft_node_t
*
raft_add_non_voting_node_internal
(
raft_server_t
*
me
,
raft_entry_t
*
ety
,
void
*
udata
,
raft_node_id_t
id
,
int
is_self
)
{
if
(
raft_get_node
(
me
,
id
))
return
NULL
;
raft_node_t
*
node
=
raft_add_node_internal
(
me
,
ety
,
udata
,
id
,
is_self
);
if
(
!
node
)
return
NULL
;
raft_node_set_voting
(
node
,
0
);
return
node
;
}
raft_node_t
*
raft_add_node
(
raft_server_t
*
me
,
void
*
udata
,
raft_node_id_t
id
,
int
is_self
)
{
return
raft_add_node_internal
(
me
,
NULL
,
udata
,
id
,
is_self
);
return
raft_add_node_internal
(
me
,
NULL
,
udata
,
id
,
is_self
,
1
);
}
raft_node_t
*
raft_add_non_voting_node
(
raft_server_t
*
me
,
void
*
udata
,
raft_node_id_t
id
,
int
is_self
)
{
return
raft_add_
non_voting_
node_internal
(
me
,
NULL
,
udata
,
id
,
is_self
);
return
raft_add_node_internal
(
me
,
NULL
,
udata
,
id
,
is_self
,
0
);
}
void
raft_remove_node
(
raft_server_t
*
me
,
raft_node_t
*
node
)
...
...
@@ -287,27 +274,29 @@ void raft_handle_append_cfg_change(raft_server_t* me, raft_entry_t* ety, raft_in
switch
(
ety
->
type
)
{
case
RAFT_LOGTYPE_ADD_NODE
:
node
=
raft_add_node_internal
(
me
,
ety
,
NULL
,
node_id
,
is_self
,
1
);
assert
(
node
);
assert
(
raft_node_is_voting
(
node
));
break
;
case
RAFT_LOGTYPE_ADD_NONVOTING_NODE
:
if
(
!
is_self
)
{
assert
(
!
node
||
!
raft_node_is_voting
(
node
));
if
(
node
&&
!
raft_node_is_active
(
node
))
{
raft_node_set_active
(
node
,
1
);
}
else
if
(
!
node
)
{
node
=
raft_add_
non_voting_
node_internal
(
me
,
ety
,
NULL
,
node_id
,
is_self
);
node
=
raft_add_node_internal
(
me
,
ety
,
NULL
,
node_id
,
is_self
,
0
);
assert
(
node
);
assert
(
!
raft_node_is_voting
(
node
));
}
}
break
;
case
RAFT_LOGTYPE_ADD_NODE
:
node
=
raft_add_node_internal
(
me
,
ety
,
NULL
,
node_id
,
is_self
);
assert
(
node
);
assert
(
raft_node_is_voting
(
node
));
break
;
case
RAFT_LOGTYPE_REMOVE_NODE
:
if
(
node
)
{
raft_node_set_active
(
node
,
0
);
...
...
@@ -332,8 +321,8 @@ void raft_handle_remove_cfg_change(raft_server_t* me, raft_entry_t* ety, const r
switch
(
ety
->
type
)
{
case
RAFT_LOGTYPE_
REMOVE
_NODE
:
raft_node_set_
active
(
node
,
1
);
case
RAFT_LOGTYPE_
ADD
_NODE
:
raft_node_set_
voting
(
node
,
0
);
break
;
case
RAFT_LOGTYPE_ADD_NONVOTING_NODE
:
...
...
@@ -341,8 +330,10 @@ void raft_handle_remove_cfg_change(raft_server_t* me, raft_entry_t* ety, const r
raft_remove_node
(
me
,
node
);
break
;
case
RAFT_LOGTYPE_ADD_NODE
:
raft_node_set_voting
(
node
,
0
);
case
RAFT_LOGTYPE_REMOVE_NODE
:
if
(
node
)
{
raft_node_set_active
(
node
,
1
);
}
break
;
default:
...
...
@@ -351,6 +342,36 @@ void raft_handle_remove_cfg_change(raft_server_t* me, raft_entry_t* ety, const r
}
}
void
raft_handle_apply_cfg_change
(
raft_server_t
*
me
,
raft_entry_t
*
ety
,
raft_index_t
idx
)
{
if
(
!
raft_entry_is_cfg_change
(
ety
))
return
;
if
(
!
me
->
cb
.
get_node_id
)
return
;
raft_node_id_t
node_id
=
me
->
cb
.
get_node_id
(
me
,
me
->
udata
,
ety
,
idx
);
raft_node_t
*
node
=
raft_get_node
(
me
,
node_id
);
switch
(
ety
->
type
)
{
case
RAFT_LOGTYPE_ADD_NODE
:
raft_node_set_addition_committed
(
node
,
1
);
raft_node_set_voting_committed
(
node
,
1
);
raft_node_set_has_sufficient_logs
(
node
,
1
);
break
;
case
RAFT_LOGTYPE_ADD_NONVOTING_NODE
:
raft_node_set_addition_committed
(
node
,
1
);
break
;
case
RAFT_LOGTYPE_REMOVE_NODE
:
if
(
node
)
{
raft_remove_node
(
me
,
node
);
}
break
;
default:
break
;
}
}
int
raft_delete_entry_from_idx
(
raft_server_t
*
me
,
raft_index_t
idx
)
{
assert
(
me
->
commit_idx
<
idx
);
...
...
@@ -475,7 +496,7 @@ int raft_become_leader(raft_server_t *me)
int
raft_become_precandidate
(
raft_server_t
*
me
)
{
for
(
int
i
=
0
;
i
<
me
->
num_nodes
;
i
++
)
{
raft_node_vote_for_me
(
me
->
nodes
[
i
],
0
);
raft_node_
set_
vote
d
_for_me
(
me
->
nodes
[
i
],
0
);
}
raft_set_state
(
me
,
RAFT_STATE_PRECANDIDATE
);
...
...
@@ -505,7 +526,7 @@ int raft_become_candidate(raft_server_t *me)
}
for
(
int
i
=
0
;
i
<
me
->
num_nodes
;
i
++
)
{
raft_node_vote_for_me
(
me
->
nodes
[
i
],
0
);
raft_node_
set_
vote
d
_for_me
(
me
->
nodes
[
i
],
0
);
}
if
(
raft_node_is_voting
(
me
->
node
))
{
...
...
@@ -1110,7 +1131,7 @@ int raft_recv_requestvote_response(raft_server_t *me,
if
(
resp
->
vote_granted
)
{
if
(
node
)
{
raft_node_vote_for_me
(
node
,
1
);
raft_node_
set_
vote
d
_for_me
(
node
,
1
);
}
int
votes
=
raft_get_nvotes_for_me
(
me
);
...
...
@@ -1269,31 +1290,8 @@ int raft_apply_entry(raft_server_t* me)
if
(
idx
==
me
->
voting_cfg_change_log_idx
)
me
->
voting_cfg_change_log_idx
=
-
1
;
if
(
!
raft_entry_is_cfg_change
(
ety
))
goto
exit
;
raft_node_id_t
node_id
=
me
->
cb
.
get_node_id
(
me
,
me
->
udata
,
ety
,
idx
);
raft_node_t
*
node
=
raft_get_node
(
me
,
node_id
);
switch
(
ety
->
type
)
{
case
RAFT_LOGTYPE_ADD_NODE
:
raft_node_set_addition_committed
(
node
,
1
);
raft_node_set_voting_committed
(
node
,
1
);
raft_node_set_has_sufficient_logs
(
node
,
1
);
break
;
case
RAFT_LOGTYPE_ADD_NONVOTING_NODE
:
raft_node_set_addition_committed
(
node
,
1
);
break
;
case
RAFT_LOGTYPE_REMOVE_NODE
:
if
(
node
)
{
raft_remove_node
(
me
,
node
);
}
break
;
default:
break
;
}
exit:
if
(
raft_entry_is_cfg_change
(
ety
))
raft_handle_apply_cfg_change
(
me
,
ety
,
idx
);
raft_entry_release
(
ety
);
return
0
;
...
...
@@ -1730,10 +1728,7 @@ raft_index_t raft_get_first_entry_idx(raft_server_t* me)
{
assert
(
0
<
raft_get_current_idx
(
me
));
if
(
me
->
snapshot_last_idx
==
0
)
return
1
;
return
me
->
snapshot_last_idx
;
return
me
->
log_impl
->
first_idx
(
me
->
log
);
}
raft_index_t
raft_get_num_snapshottable_logs
(
raft_server_t
*
me
)
...
...
tests/test_node.c
View file @
e1569508
...
...
@@ -10,15 +10,9 @@
#include "raft_log.h"
#include "raft_private.h"
void
TestRaft_is_voting_by_default
(
CuTest
*
tc
)
{
raft_node_t
*
p
=
raft_node_new
((
void
*
)
1
,
1
);
CuAssertTrue
(
tc
,
raft_node_is_voting
(
p
));
}
void
TestRaft_node_set_nextIdx
(
CuTest
*
tc
)
{
raft_node_t
*
p
=
raft_node_new
((
void
*
)
1
,
1
);
raft_node_t
*
p
=
raft_node_new
((
void
*
)
1
,
1
,
1
);
raft_node_set_next_idx
(
p
,
3
);
CuAssertTrue
(
tc
,
3
==
raft_node_get_next_idx
(
p
));
}
...
...
@@ -29,7 +23,6 @@ int main(void)
CuString
*
output
=
CuStringNew
();
CuSuite
*
suite
=
CuSuiteNew
();
SUITE_ADD_TEST
(
suite
,
TestRaft_is_voting_by_default
);
SUITE_ADD_TEST
(
suite
,
TestRaft_node_set_nextIdx
);
CuSuiteRun
(
suite
);
...
...
tests/test_server.c
View file @
e1569508
...
...
@@ -3488,6 +3488,7 @@ void TestRaft_leader_recv_appendentries_response_increment_idx_of_node(
/* receive mock success responses */
raft_appendentries_resp_t
aer
;
memset
(
&
aer
,
0
,
sizeof
(
raft_appendentries_resp_t
));
aer
.
term
=
1
;
aer
.
success
=
1
;
aer
.
current_idx
=
0
;
...
...
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