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
2c89514f
Unverified
Commit
2c89514f
authored
Aug 16, 2018
by
Willem
Committed by
GitHub
Aug 16, 2018
Browse files
Merge pull request #86 from yossigo/feat/snapshot-nonblocking-apply
Allow entries to apply during snapshot
parents
ff0c70ae
ed56e88d
Changes
5
Hide whitespace changes
Inline
Side-by-side
include/raft.h
View file @
2c89514f
...
...
@@ -39,6 +39,9 @@ typedef enum {
RAFT_STATE_LEADER
}
raft_state_e
;
/** Allow entries to apply while taking a snapshot */
#define RAFT_SNAPSHOT_NONBLOCKING_APPLY 1
typedef
enum
{
/**
* Regular log type.
...
...
@@ -802,10 +805,14 @@ int raft_entry_is_cfg_change(raft_entry_t* ety);
* - not apply log entries
* - not start elections
*
* If the RAFT_SNAPSHOT_NONBLOCKING_APPLY flag is specified, log entries will
* be applied during snapshot. The FSM must isolate the snapshot state and
* guarantee these changes do not affect it.
*
* @return 0 on success
*
**/
int
raft_begin_snapshot
(
raft_server_t
*
me_
);
int
raft_begin_snapshot
(
raft_server_t
*
me_
,
int
flags
);
/** Stop snapshotting.
*
...
...
@@ -841,6 +848,11 @@ raft_index_t raft_get_snapshot_entry_idx(raft_server_t *me_);
**/
int
raft_snapshot_is_in_progress
(
raft_server_t
*
me_
);
/** Check if entries can be applied now (no snapshot in progress, or
* RAFT_SNAPSHOT_NONBLOCKING_APPLY specified).
**/
int
raft_is_apply_allowed
(
raft_server_t
*
me_
);
/** Remove the first log entry.
* This should be used for compacting logs.
* @return 0 on success
...
...
include/raft_private.h
View file @
2c89514f
...
...
@@ -73,6 +73,7 @@ typedef struct {
int
connected
;
int
snapshot_in_progress
;
int
snapshot_flags
;
/* Last compacted snapshot */
raft_index_t
snapshot_last_idx
;
...
...
src/raft_server.c
View file @
2c89514f
...
...
@@ -248,7 +248,7 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period)
}
if
(
me
->
last_applied_idx
<
raft_get_commit_idx
(
me_
)
&&
!
raft_
snapshot_is_in_progress
(
me_
))
raft_
is_apply_allowed
(
me_
))
{
int
e
=
raft_apply_all
(
me_
);
if
(
0
!=
e
)
...
...
@@ -728,7 +728,7 @@ int raft_recv_entry(raft_server_t* me_,
/* Multi-threading: need to fail here because user might be
* snapshotting membership settings. */
if
(
raft_
snapshot_is_in_progress
(
me_
))
if
(
!
raft_
is_apply_allowed
(
me_
))
return
RAFT_ERR_SNAPSHOT_IN_PROGRESS
;
}
...
...
@@ -810,7 +810,7 @@ int raft_apply_entry(raft_server_t* me_)
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
if
(
raft_
snapshot_is_in_progress
(
me_
))
if
(
!
raft_
is_apply_allowed
(
me_
))
return
-
1
;
/* Don't apply after the commit_idx */
...
...
@@ -1096,7 +1096,7 @@ int raft_msg_entry_response_committed(raft_server_t* me_,
int
raft_apply_all
(
raft_server_t
*
me_
)
{
if
(
raft_
snapshot_is_in_progress
(
me_
))
if
(
!
raft_
is_apply_allowed
(
me_
))
return
0
;
while
(
raft_get_last_applied_idx
(
me_
)
<
raft_get_commit_idx
(
me_
))
...
...
@@ -1253,7 +1253,7 @@ raft_index_t raft_get_num_snapshottable_logs(raft_server_t *me_)
return
raft_get_commit_idx
(
me_
)
-
log_get_base
(
me
->
log
);
}
int
raft_begin_snapshot
(
raft_server_t
*
me_
)
int
raft_begin_snapshot
(
raft_server_t
*
me_
,
int
flags
)
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
...
...
@@ -1277,6 +1277,7 @@ int raft_begin_snapshot(raft_server_t *me_)
raft_set_snapshot_metadata
(
me_
,
ety
->
term
,
snapshot_target
);
me
->
snapshot_in_progress
=
1
;
me
->
snapshot_flags
=
flags
;
__log
(
me_
,
NULL
,
"begin snapshot sli:%d slt:%d slogs:%d
\n
"
,
...
...
src/raft_server_properties.c
View file @
2c89514f
...
...
@@ -235,6 +235,12 @@ int raft_snapshot_is_in_progress(raft_server_t *me_)
return
((
raft_server_private_t
*
)
me_
)
->
snapshot_in_progress
;
}
int
raft_is_apply_allowed
(
raft_server_t
*
me_
)
{
return
(
!
raft_snapshot_is_in_progress
(
me_
)
||
(((
raft_server_private_t
*
)
me_
)
->
snapshot_flags
&
RAFT_SNAPSHOT_NONBLOCKING_APPLY
));
}
raft_entry_t
*
raft_get_last_applied_entry
(
raft_server_t
*
me_
)
{
raft_server_private_t
*
me
=
(
raft_server_private_t
*
)
me_
;
...
...
tests/test_snapshotting.c
View file @
2c89514f
...
...
@@ -108,10 +108,10 @@ void TestRaft_leader_begin_snapshot_fails_if_no_logs_to_compact(CuTest * tc)
ety
.
id
=
2
;
raft_recv_entry
(
r
,
&
ety
,
&
cr
);
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
CuAssertIntEquals
(
tc
,
-
1
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
-
1
,
raft_begin_snapshot
(
r
,
0
));
raft_set_commit_idx
(
r
,
1
);
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
0
));
}
void
TestRaft_leader_will_not_apply_entry_if_snapshot_is_in_progress
(
CuTest
*
tc
)
...
...
@@ -145,7 +145,7 @@ void TestRaft_leader_will_not_apply_entry_if_snapshot_is_in_progress(CuTest * tc
raft_set_commit_idx
(
r
,
1
);
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
0
));
CuAssertIntEquals
(
tc
,
1
,
raft_get_last_applied_idx
(
r
));
raft_set_commit_idx
(
r
,
2
);
CuAssertIntEquals
(
tc
,
-
1
,
raft_apply_entry
(
r
));
...
...
@@ -198,7 +198,7 @@ void TestRaft_leader_snapshot_begin_fails_if_less_than_2_logs_to_compact(CuTest
raft_recv_entry
(
r
,
&
ety
,
&
cr
);
raft_set_commit_idx
(
r
,
1
);
CuAssertIntEquals
(
tc
,
1
,
raft_get_log_count
(
r
));
CuAssertIntEquals
(
tc
,
-
1
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
-
1
,
raft_begin_snapshot
(
r
,
0
));
}
void
TestRaft_leader_snapshot_end_succeeds_if_log_compacted
(
CuTest
*
tc
)
...
...
@@ -235,7 +235,7 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted(CuTest * tc)
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
CuAssertIntEquals
(
tc
,
1
,
raft_get_num_snapshottable_logs
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
0
));
raft_entry_t
*
_ety
;
int
i
=
raft_get_first_entry_idx
(
r
);
...
...
@@ -286,7 +286,7 @@ void TestRaft_leader_snapshot_end_succeeds_if_log_compacted2(CuTest * tc)
CuAssertIntEquals
(
tc
,
3
,
raft_get_log_count
(
r
));
CuAssertIntEquals
(
tc
,
2
,
raft_get_num_snapshottable_logs
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
0
));
raft_entry_t
*
_ety
;
int
i
=
raft_get_first_entry_idx
(
r
);
...
...
@@ -333,7 +333,7 @@ void TestRaft_joinee_needs_to_get_snapshot(CuTest * tc)
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
CuAssertIntEquals
(
tc
,
1
,
raft_get_num_snapshottable_logs
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
0
));
CuAssertIntEquals
(
tc
,
1
,
raft_get_last_applied_idx
(
r
));
CuAssertIntEquals
(
tc
,
-
1
,
raft_apply_entry
(
r
));
CuAssertIntEquals
(
tc
,
1
,
raft_get_last_applied_idx
(
r
));
...
...
@@ -572,13 +572,52 @@ void TestRaft_recv_entry_fails_if_snapshot_in_progress(CuTest* tc)
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
raft_set_commit_idx
(
r
,
1
);
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
));
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
0
));
ety
.
id
=
3
;
ety
.
type
=
RAFT_LOGTYPE_ADD_NODE
;
CuAssertIntEquals
(
tc
,
RAFT_ERR_SNAPSHOT_IN_PROGRESS
,
raft_recv_entry
(
r
,
&
ety
,
&
cr
));
}
void
TestRaft_recv_entry_succeeds_if_snapshot_nonblocking_apply_is_set
(
CuTest
*
tc
)
{
raft_cbs_t
funcs
=
{
.
send_appendentries
=
__raft_send_appendentries
,
};
void
*
r
=
raft_new
();
raft_set_callbacks
(
r
,
&
funcs
,
NULL
);
msg_entry_response_t
cr
;
raft_add_node
(
r
,
NULL
,
1
,
1
);
raft_add_node
(
r
,
NULL
,
2
,
0
);
/* I am the leader */
raft_set_state
(
r
,
RAFT_STATE_LEADER
);
CuAssertIntEquals
(
tc
,
0
,
raft_get_log_count
(
r
));
/* entry message */
msg_entry_t
ety
=
{};
ety
.
id
=
1
;
ety
.
data
.
buf
=
"entry"
;
ety
.
data
.
len
=
strlen
(
"entry"
);
/* receive entry */
raft_recv_entry
(
r
,
&
ety
,
&
cr
);
ety
.
id
=
2
;
raft_recv_entry
(
r
,
&
ety
,
&
cr
);
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
raft_set_commit_idx
(
r
,
1
);
CuAssertIntEquals
(
tc
,
0
,
raft_begin_snapshot
(
r
,
RAFT_SNAPSHOT_NONBLOCKING_APPLY
));
ety
.
id
=
3
;
ety
.
type
=
RAFT_LOGTYPE_ADD_NODE
;
CuAssertIntEquals
(
tc
,
0
,
raft_recv_entry
(
r
,
&
ety
,
&
cr
));
}
void
TestRaft_follower_recv_appendentries_is_successful_when_previous_log_idx_equals_snapshot_last_idx
(
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