Commit 01e1b599 authored by Yossi Gottlieb's avatar Yossi Gottlieb
Browse files

Merge remote-tracking branch 'upstream/master'

parents 25df21a1 296c7e0b
...@@ -21,12 +21,13 @@ SHAREDEXT = dylib ...@@ -21,12 +21,13 @@ SHAREDEXT = dylib
CFLAGS += -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/ CFLAGS += -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/
CFLAGS += -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include CFLAGS += -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include
CFLAGS += $(ASANFLAGS) CFLAGS += $(ASANFLAGS)
CFLAGS += -Wno-nullability-completeness
else else
SHAREDFLAGS = -shared SHAREDFLAGS = -shared
SHAREDEXT = so SHAREDEXT = so
endif endif
OBJECTS = raft_server.o raft_server_properties.o raft_node.o raft_log.o OBJECTS = src/raft_server.o src/raft_server_properties.o src/raft_node.o src/raft_log.o
all: static shared all: static shared
...@@ -58,10 +59,23 @@ tests: src/raft_server.c src/raft_server_properties.c src/raft_log.c src/raft_no ...@@ -58,10 +59,23 @@ tests: src/raft_server.c src/raft_server_properties.c src/raft_log.c src/raft_no
./tests_main ./tests_main
gcov raft_server.c gcov raft_server.c
.PHONY: fuzzer_tests .PHONY: test_fuzzer
fuzzer_tests: test_fuzzer:
python tests/log_fuzzer.py python tests/log_fuzzer.py
.PHONY: tests_full
tests_full:
make clean
make tests
make test_fuzzer
make test_virtraft
.PHONY: test_virtraft
test_virtraft:
cp src/*.c virtraft/deps/raft/
cp include/*.h virtraft/deps/raft/
cd virtraft; make clean; make; make tests
.PHONY: amalgamation .PHONY: amalgamation
amalgamation: amalgamation:
./scripts/amalgamate.sh > raft.h ./scripts/amalgamate.sh > raft.h
...@@ -72,7 +86,7 @@ infer: do_infer ...@@ -72,7 +86,7 @@ infer: do_infer
.PHONY: do_infer .PHONY: do_infer
do_infer: do_infer:
make clean make clean
infer -- make static infer -- make
clean: clean:
@rm -f $(TEST_DIR)/main_test.c *.o $(GCOV_OUTPUT); \ @rm -f $(TEST_DIR)/main_test.c *.o $(GCOV_OUTPUT); \
......
...@@ -40,7 +40,7 @@ typedef struct ...@@ -40,7 +40,7 @@ typedef struct
void* raft; void* raft;
} log_private_t; } log_private_t;
int mod(int a, int b) static int mod(int a, int b)
{ {
int r = a % b; int r = a % b;
return r < 0 ? r + b : r; return r < 0 ? r + b : r;
......
...@@ -233,7 +233,6 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period) ...@@ -233,7 +233,6 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period)
if (me->request_timeout <= me->timeout_elapsed) if (me->request_timeout <= me->timeout_elapsed)
raft_send_appendentries_all(me_); raft_send_appendentries_all(me_);
} }
else if (me->election_timeout_rand <= me->timeout_elapsed && else if (me->election_timeout_rand <= me->timeout_elapsed &&
/* Don't become the leader when building snapshots or bad things will /* Don't become the leader when building snapshots or bad things will
* happen when we get a client request */ * happen when we get a client request */
...@@ -251,7 +250,7 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period) ...@@ -251,7 +250,7 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period)
if (me->last_applied_idx < raft_get_commit_idx(me_) && if (me->last_applied_idx < raft_get_commit_idx(me_) &&
!raft_snapshot_is_in_progress(me_)) !raft_snapshot_is_in_progress(me_))
{ {
int e = raft_apply_entry(me_); int e = raft_apply_all(me_);
if (0 != e) if (0 != e)
return e; return e;
} }
...@@ -445,9 +444,15 @@ int raft_recv_appendentries( ...@@ -445,9 +444,15 @@ int raft_recv_appendentries(
__log(me_, node, "AE term doesn't match prev_term (ie. %d vs %d) ci:%d comi:%d lcomi:%d pli:%d", __log(me_, node, "AE term doesn't match prev_term (ie. %d vs %d) ci:%d comi:%d lcomi:%d pli:%d",
ety->term, ae->prev_log_term, raft_get_current_idx(me_), ety->term, ae->prev_log_term, raft_get_current_idx(me_),
raft_get_commit_idx(me_), ae->leader_commit, ae->prev_log_idx); raft_get_commit_idx(me_), ae->leader_commit, ae->prev_log_idx);
if (ae->prev_log_idx <= raft_get_commit_idx(me_))
{
/* Should never happen; something is seriously wrong! */
__log(me_, node, "AE prev conflicts with committed entry");
e = RAFT_ERR_SHUTDOWN;
goto out;
}
/* Delete all the following log entries because they don't match */ /* Delete all the following log entries because they don't match */
e = raft_delete_entry_from_idx(me_, e = raft_delete_entry_from_idx(me_, ae->prev_log_idx);
max(ae->prev_log_idx, ae->leader_commit + 1));
goto out; goto out;
} }
} }
...@@ -464,8 +469,17 @@ int raft_recv_appendentries( ...@@ -464,8 +469,17 @@ int raft_recv_appendentries(
raft_entry_t* ety = &ae->entries[i]; raft_entry_t* ety = &ae->entries[i];
int ety_index = ae->prev_log_idx + 1 + i; int ety_index = ae->prev_log_idx + 1 + i;
raft_entry_t* existing_ety = raft_get_entry_from_idx(me_, ety_index); raft_entry_t* existing_ety = raft_get_entry_from_idx(me_, ety_index);
if (existing_ety && existing_ety->term != ety->term && me->commit_idx < ety_index) if (existing_ety && existing_ety->term != ety->term)
{ {
if (ety_index <= raft_get_commit_idx(me_))
{
/* Should never happen; something is seriously wrong! */
__log(me_, node, "AE entry conflicts with committed entry ci:%d comi:%d lcomi:%d pli:%d",
raft_get_current_idx(me_), raft_get_commit_idx(me_),
ae->leader_commit, ae->prev_log_idx);
e = RAFT_ERR_SHUTDOWN;
goto out;
}
e = raft_delete_entry_from_idx(me_, ety_index); e = raft_delete_entry_from_idx(me_, ety_index);
if (0 != e) if (0 != e)
goto out; goto out;
...@@ -1291,7 +1305,7 @@ int raft_begin_load_snapshot( ...@@ -1291,7 +1305,7 @@ int raft_begin_load_snapshot(
if (last_included_index == -1) if (last_included_index == -1)
return -1; return -1;
if (last_included_index == 0 || last_included_index == 0) if (last_included_index == 0 || last_included_term == 0)
return -1; return -1;
/* loading the snapshot will break cluster safety */ /* loading the snapshot will break cluster safety */
......
...@@ -43,6 +43,16 @@ int __raft_applylog( ...@@ -43,6 +43,16 @@ int __raft_applylog(
return 0; return 0;
} }
int __raft_applylog_shutdown(
raft_server_t* raft,
void *udata,
raft_entry_t *ety,
int idx
)
{
return RAFT_ERR_SHUTDOWN;
}
int __raft_send_requestvote(raft_server_t* raft, int __raft_send_requestvote(raft_server_t* raft,
void* udata, void* udata,
raft_node_t* node, raft_node_t* node,
...@@ -464,6 +474,37 @@ void TestRaft_server_increment_lastApplied_when_lastApplied_lt_commitidx( ...@@ -464,6 +474,37 @@ void TestRaft_server_increment_lastApplied_when_lastApplied_lt_commitidx(
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r)); CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
} }
void TestRaft_user_applylog_error_propogates_to_periodic(
CuTest* tc)
{
raft_cbs_t funcs = {
.persist_term = __raft_persist_term,
.applylog = __raft_applylog_shutdown,
};
void *r = raft_new();
raft_set_callbacks(r, &funcs, NULL);
/* must be follower */
raft_set_state(r, RAFT_STATE_FOLLOWER);
raft_set_current_term(r, 1);
raft_set_last_applied_idx(r, 0);
/* need at least one entry */
raft_entry_t ety = {};
ety.term = 1;
ety.id = 1;
ety.data.buf = "aaa";
ety.data.len = 3;
raft_append_entry(r, &ety);
raft_set_commit_idx(r, 1);
/* let time lapse */
CuAssertIntEquals(tc, RAFT_ERR_SHUTDOWN, raft_periodic(r, 1));
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
}
void TestRaft_server_apply_entry_increments_last_applied_idx(CuTest* tc) void TestRaft_server_apply_entry_increments_last_applied_idx(CuTest* tc)
{ {
raft_cbs_t funcs = { raft_cbs_t funcs = {
...@@ -3134,10 +3175,6 @@ void TestRaft_leader_recv_appendentries_response_do_not_increase_commit_idx_beca ...@@ -3134,10 +3175,6 @@ void TestRaft_leader_recv_appendentries_response_do_not_increase_commit_idx_beca
raft_recv_appendentries_response(r, raft_get_node(r, 3), &aer); raft_recv_appendentries_response(r, raft_get_node(r, 3), &aer);
CuAssertIntEquals(tc, 3, raft_get_commit_idx(r)); CuAssertIntEquals(tc, 3, raft_get_commit_idx(r));
raft_periodic(r, 1); raft_periodic(r, 1);
CuAssertIntEquals(tc, 1, raft_get_last_applied_idx(r));
raft_periodic(r, 1);
CuAssertIntEquals(tc, 2, raft_get_last_applied_idx(r));
raft_periodic(r, 1);
CuAssertIntEquals(tc, 3, raft_get_last_applied_idx(r)); CuAssertIntEquals(tc, 3, raft_get_last_applied_idx(r));
} }
......
...@@ -369,6 +369,22 @@ void TestRaft_follower_load_from_snapshot(CuTest * tc) ...@@ -369,6 +369,22 @@ void TestRaft_follower_load_from_snapshot(CuTest * tc)
CuAssertIntEquals(tc, 7, raft_get_commit_idx(r)); CuAssertIntEquals(tc, 7, raft_get_commit_idx(r));
} }
void TestRaft_follower_load_from_snapshot_fails_if_term_is_0(CuTest * tc)
{
raft_cbs_t funcs = {
};
void *r = raft_new();
raft_set_callbacks(r, &funcs, NULL);
raft_add_node(r, NULL, 1, 1);
raft_add_node(r, NULL, 2, 0);
raft_set_state(r, RAFT_STATE_FOLLOWER);
CuAssertIntEquals(tc, 0, raft_get_log_count(r));
CuAssertIntEquals(tc, -1, raft_begin_load_snapshot(r, 0, 5));
}
void TestRaft_follower_load_from_snapshot_fails_if_already_loaded(CuTest * tc) void TestRaft_follower_load_from_snapshot_fails_if_already_loaded(CuTest * tc)
{ {
raft_cbs_t funcs = { raft_cbs_t funcs = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment