Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
Willemt Raft
Commits
e4c4029e
Commit
e4c4029e
authored
Nov 06, 2015
by
Willem Thiart
Browse files
Prevent dupe entries
Thanks to @ar104 for help with this fix!
parent
591973e3
Changes
2
Show whitespace changes
Inline
Side-by-side
src/raft_server.c
View file @
e4c4029e
...
@@ -283,18 +283,27 @@ int raft_recv_appendentries(
...
@@ -283,18 +283,27 @@ int raft_recv_appendentries(
/* 3. If an existing entry conflicts with a new one (same index
/* 3. If an existing entry conflicts with a new one (same index
but different terms), delete the existing entry and all that
but different terms), delete the existing entry and all that
follow it (§5.3) */
follow it (§5.3) */
int
has_mismatch
=
0
,
i
;
int
i
;
for
(
i
=
0
;
i
<
ae
->
n_entries
;
i
++
)
for
(
i
=
0
;
i
<
ae
->
n_entries
;
i
++
)
{
{
msg_entry_t
*
cmd
=
&
ae
->
entries
[
i
];
msg_entry_t
*
ety
=
&
ae
->
entries
[
i
];
int
index
=
ae
->
prev_log_idx
+
1
+
i
;
int
ety_index
=
ae
->
prev_log_idx
+
1
+
i
;
raft_entry_t
*
e2
=
raft_get_entry_from_idx
(
me_
,
index
);
raft_entry_t
*
existing_ety
=
raft_get_entry_from_idx
(
me_
,
ety_index
);
if
(
!
e2
)
if
(
existing_ety
&&
existing_ety
->
term
!=
ety
->
term
)
break
;
/* reached end of log */
{
if
(
e2
&&
e2
->
term
!=
cmd
->
term
)
log_delete
(
me
->
log
,
ety_index
);
has_mismatch
=
1
;
break
;
if
(
has_mismatch
)
}
log_delete
(
me
->
log
,
index
);
else
if
(
!
existing_ety
)
break
;
}
/* Pick up remainder in case of mismatch or missing existing entry */
for
(;
i
<
ae
->
n_entries
;
i
++
)
{
int
e
=
raft_append_entry
(
me_
,
&
ae
->
entries
[
i
]);
if
(
-
1
==
e
)
goto
fail
;
}
}
/* 4. If leaderCommit > commitIndex, set commitIndex =
/* 4. If leaderCommit > commitIndex, set commitIndex =
...
@@ -309,31 +318,19 @@ int raft_recv_appendentries(
...
@@ -309,31 +318,19 @@ int raft_recv_appendentries(
raft_become_follower
(
me_
);
raft_become_follower
(
me_
);
raft_set_current_term
(
me_
,
ae
->
term
);
raft_set_current_term
(
me_
,
ae
->
term
);
/* update current leader because we accepted appendentries from it */
/* update current leader because we accepted appendentries from it */
me
->
current_leader
=
node
;
me
->
current_leader
=
node
;
/* append all entries to log */
for
(
i
=
0
;
i
<
ae
->
n_entries
;
i
++
)
{
msg_entry_t
*
cmd
=
&
ae
->
entries
[
i
];
raft_entry_t
ety
;
ety
.
term
=
cmd
->
term
;
ety
.
id
=
cmd
->
id
;
memcpy
(
&
ety
.
data
,
&
cmd
->
data
,
sizeof
(
raft_entry_data_t
));
int
e
=
raft_append_entry
(
me_
,
&
ety
);
if
(
-
1
==
e
)
{
__log
(
me_
,
"AE failure; couldn't append entry"
);
r
->
success
=
0
;
return
-
1
;
}
}
r
->
success
=
1
;
r
->
success
=
1
;
r
->
current_idx
=
raft_get_current_idx
(
me_
);
r
->
current_idx
=
raft_get_current_idx
(
me_
);
r
->
first_idx
=
ae
->
prev_log_idx
+
1
;
r
->
first_idx
=
ae
->
prev_log_idx
+
1
;
return
0
;
return
0
;
fail:
__log
(
me_
,
"AE failure; couldn't append entry"
);
r
->
success
=
0
;
return
-
1
;
}
}
static
int
__should_grant_vote
(
raft_server_private_t
*
me
,
msg_requestvote_t
*
vr
)
static
int
__should_grant_vote
(
raft_server_private_t
*
me
,
msg_requestvote_t
*
vr
)
...
...
tests/test_server.c
View file @
e4c4029e
...
@@ -801,6 +801,44 @@ void TestRaft_follower_recv_appendentries_add_new_entries_not_already_in_log(
...
@@ -801,6 +801,44 @@ void TestRaft_follower_recv_appendentries_add_new_entries_not_already_in_log(
CuAssertTrue
(
tc
,
2
==
raft_get_log_count
(
r
));
CuAssertTrue
(
tc
,
2
==
raft_get_log_count
(
r
));
}
}
void
TestRaft_follower_recv_appendentries_does_not_add_dupe_entries_already_in_log
(
CuTest
*
tc
)
{
void
*
r
=
raft_new
();
raft_add_node
(
r
,
(
void
*
)
1
,
1
);
raft_add_node
(
r
,
(
void
*
)
2
,
0
);
raft_set_current_term
(
r
,
1
);
msg_appendentries_t
ae
;
msg_appendentries_response_t
aer
;
memset
(
&
ae
,
0
,
sizeof
(
msg_appendentries_t
));
ae
.
term
=
1
;
ae
.
prev_log_idx
=
0
;
ae
.
prev_log_term
=
1
;
/* include 1 entry */
msg_entry_t
e
[
2
];
memset
(
&
e
,
0
,
sizeof
(
msg_entry_t
)
*
2
);
e
[
0
].
id
=
1
;
ae
.
entries
=
e
;
ae
.
n_entries
=
1
;
memset
(
&
aer
,
0
,
sizeof
(
aer
));
raft_recv_appendentries
(
r
,
1
,
&
ae
,
&
aer
);
memset
(
&
aer
,
0
,
sizeof
(
aer
));
raft_recv_appendentries
(
r
,
1
,
&
ae
,
&
aer
);
/* still successful even when no raft_append_entry() happened! */
CuAssertTrue
(
tc
,
1
==
aer
.
success
);
CuAssertIntEquals
(
tc
,
1
,
raft_get_log_count
(
r
));
/* lets get the server to append 2 now! */
e
[
1
].
id
=
2
;
ae
.
n_entries
=
2
;
memset
(
&
aer
,
0
,
sizeof
(
aer
));
raft_recv_appendentries
(
r
,
1
,
&
ae
,
&
aer
);
CuAssertTrue
(
tc
,
1
==
aer
.
success
);
CuAssertIntEquals
(
tc
,
2
,
raft_get_log_count
(
r
));
}
/* If leaderCommit > commitidx, set commitidx =
/* If leaderCommit > commitidx, set commitidx =
* min(leaderCommit, last log idx) */
* min(leaderCommit, last log idx) */
void
TestRaft_follower_recv_appendentries_set_commitidx_to_prevLogIdx
(
void
TestRaft_follower_recv_appendentries_set_commitidx_to_prevLogIdx
(
...
...
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