Skip to content

Commit e501361

Browse files
authored
Bump to v0.4.3 (#231)
* raft: leader respond to learner read index message (#220) Signed-off-by: nolouch <nolouch@gmail.com> * Bump to v0.4.3 Signed-off-by: Neil Shen <overvenus@gmail.com>
1 parent 3b41216 commit e501361

File tree

7 files changed

+103
-16
lines changed

7 files changed

+103
-16
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.4.3 - 2019-05-08
2+
3+
- Leader responds to learner read index message. (https://github.com/pingcap/raft-rs/pull/220)
4+
15
# 0.4.2 - 2019-04-29
26

37
- Fix potential two leaders at the same term when transferring leader. (https://github.com/pingcap/raft-rs/pull/225)

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "raft"
3-
version = "0.4.2"
3+
version = "0.4.3"
44
authors = ["The TiKV Project Developers"]
55
license = "Apache-2.0"
66
keywords = ["raft", "distributed-systems", "ha"]

benches/benches.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ mod suites;
1212
pub const DEFAULT_RAFT_SETS: [(usize, usize); 4] = [(0, 0), (3, 1), (5, 2), (7, 3)];
1313

1414
fn main() {
15-
criterion::init_logging();
1615
let mut c = Criterion::default()
1716
// Configure defaults before overriding with args.
1817
.warm_up_time(Duration::from_millis(500))

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ For more information, check out an [example](examples/single_mem_node/main.rs#L1
261261
*/
262262

263263
#![cfg_attr(not(feature = "cargo-clippy"), allow(unknown_lints))]
264-
#![cfg_attr(feature = "cargo-clippy", feature(tool_lints))]
265264
#![deny(missing_docs)]
266265

267266
#[cfg(feature = "failpoint")]

src/raft.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ impl<T: Storage> Raft<T> {
679679

680680
self.election_elapsed = 0;
681681
let m = new_message(INVALID_ID, MessageType::MsgHup, Some(self.id));
682-
self.step(m).is_ok();
682+
let _ = self.step(m);
683683
true
684684
}
685685

@@ -695,7 +695,7 @@ impl<T: Storage> Raft<T> {
695695
if self.check_quorum {
696696
let m = new_message(INVALID_ID, MessageType::MsgCheckQuorum, Some(self.id));
697697
has_ready = true;
698-
self.step(m).is_ok();
698+
let _ = self.step(m);
699699
}
700700
if self.state == StateRole::Leader && self.lead_transferee.is_some() {
701701
self.abort_leader_transfer()
@@ -710,7 +710,7 @@ impl<T: Storage> Raft<T> {
710710
self.heartbeat_elapsed = 0;
711711
has_ready = true;
712712
let m = new_message(INVALID_ID, MessageType::MsgBeat, Some(self.id));
713-
self.step(m).is_ok();
713+
let _ = self.step(m);
714714
}
715715
has_ready
716716
}
@@ -794,7 +794,7 @@ impl<T: Storage> Raft<T> {
794794
}
795795

796796
fn num_pending_conf(&self, ents: &[Entry]) -> usize {
797-
ents.into_iter()
797+
ents.iter()
798798
.filter(|e| e.get_entry_type() == EntryType::EntryConfChange)
799799
.count()
800800
}
@@ -1486,11 +1486,23 @@ impl<T: Storage> Raft<T> {
14861486
}
14871487
}
14881488
} else {
1489-
let rs = ReadState {
1490-
index: self.raft_log.committed,
1491-
request_ctx: m.take_entries()[0].take_data(),
1492-
};
1493-
self.read_states.push(rs);
1489+
// there is only one voting member (the leader) in the cluster
1490+
if m.get_from() == INVALID_ID || m.get_from() == self.id {
1491+
// from leader itself
1492+
let rs = ReadState {
1493+
index: self.raft_log.committed,
1494+
request_ctx: m.take_entries()[0].take_data(),
1495+
};
1496+
self.read_states.push(rs);
1497+
} else {
1498+
// from learner member
1499+
let mut to_send = Message::default();
1500+
to_send.set_to(m.get_from());
1501+
to_send.set_msg_type(MessageType::MsgReadIndexResp);
1502+
to_send.set_index(self.raft_log.committed);
1503+
to_send.set_entries(m.take_entries());
1504+
self.send(to_send);
1505+
}
14941506
}
14951507
return Ok(());
14961508
}

src/raw_node.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ impl<T: Storage> RawNode<T> {
443443
m.set_msg_type(MessageType::MsgUnreachable);
444444
m.set_from(id);
445445
// we don't care if it is ok actually
446-
self.raft.step(m).is_ok();
446+
let _ = self.raft.step(m);
447447
}
448448

449449
/// ReportSnapshot reports the status of the sent snapshot.
@@ -454,15 +454,15 @@ impl<T: Storage> RawNode<T> {
454454
m.set_from(id);
455455
m.set_reject(rej);
456456
// we don't care if it is ok actually
457-
self.raft.step(m).is_ok();
457+
let _ = self.raft.step(m);
458458
}
459459

460460
/// TransferLeader tries to transfer leadership to the given transferee.
461461
pub fn transfer_leader(&mut self, transferee: u64) {
462462
let mut m = Message::new();
463463
m.set_msg_type(MessageType::MsgTransferLeader);
464464
m.set_from(transferee);
465-
self.raft.step(m).is_ok();
465+
let _ = self.raft.step(m);
466466
}
467467

468468
/// ReadIndex requests a read state. The read state will be set in ready.
@@ -475,7 +475,7 @@ impl<T: Storage> RawNode<T> {
475475
let mut e = Entry::new();
476476
e.set_data(rctx);
477477
m.set_entries(RepeatedField::from_vec(vec![e]));
478-
self.raft.step(m).is_ok();
478+
let _ = self.raft.step(m);
479479
}
480480

481481
/// Returns the store as an immutable reference.

tests/integration_cases/test_raft.rs

+73
Original file line numberDiff line numberDiff line change
@@ -2205,6 +2205,79 @@ fn test_read_only_option_safe() {
22052205
}
22062206
}
22072207

2208+
#[test]
2209+
fn test_read_only_with_learner() {
2210+
setup_for_test();
2211+
let a = new_test_learner_raft(1, vec![1], vec![2], 10, 1, new_storage());
2212+
let b = new_test_learner_raft(2, vec![1], vec![2], 10, 1, new_storage());
2213+
2214+
let mut nt = Network::new(vec![Some(a), Some(b)]);
2215+
2216+
// we can not let system choose the value of randomizedElectionTimeout
2217+
// otherwise it will introduce some uncertainty into this test case
2218+
// we need to ensure randomizedElectionTimeout > electionTimeout here
2219+
let b_election_timeout = nt.peers[&2].get_election_timeout();
2220+
nt.peers
2221+
.get_mut(&2)
2222+
.unwrap()
2223+
.set_randomized_election_timeout(b_election_timeout + 1);
2224+
2225+
for _ in 0..b_election_timeout {
2226+
nt.peers.get_mut(&2).unwrap().tick();
2227+
}
2228+
nt.send(vec![new_message(1, 1, MessageType::MsgHup, 0)]);
2229+
2230+
assert_eq!(nt.peers[&1].state, StateRole::Leader);
2231+
assert_eq!(nt.peers[&2].state, StateRole::Follower);
2232+
2233+
let mut tests = vec![
2234+
(1, 10, 11, "ctx1"),
2235+
(2, 10, 21, "ctx2"),
2236+
(1, 10, 31, "ctx3"),
2237+
(2, 10, 41, "ctx4"),
2238+
];
2239+
2240+
for (i, (id, proposals, wri, wctx)) in tests.drain(..).enumerate() {
2241+
for _ in 0..proposals {
2242+
nt.send(vec![new_message(1, 1, MessageType::MsgPropose, 1)]);
2243+
}
2244+
2245+
let e = new_entry(0, 0, Some(wctx));
2246+
nt.send(vec![new_message_with_entries(
2247+
id,
2248+
id,
2249+
MessageType::MsgReadIndex,
2250+
vec![e],
2251+
)]);
2252+
2253+
let read_states: Vec<ReadState> = nt
2254+
.peers
2255+
.get_mut(&id)
2256+
.unwrap()
2257+
.read_states
2258+
.drain(..)
2259+
.collect();
2260+
assert_eq!(
2261+
read_states.is_empty(),
2262+
false,
2263+
"#{}: read_states is empty, want non-empty",
2264+
i
2265+
);
2266+
let rs = &read_states[0];
2267+
assert_eq!(
2268+
rs.index, wri,
2269+
"#{}: read_index = {}, want {}",
2270+
i, rs.index, wri
2271+
);
2272+
let vec_wctx = wctx.as_bytes().to_vec();
2273+
assert_eq!(
2274+
rs.request_ctx, vec_wctx,
2275+
"#{}: request_ctx = {:?}, want {:?}",
2276+
i, rs.request_ctx, vec_wctx
2277+
);
2278+
}
2279+
}
2280+
22082281
#[test]
22092282
fn test_read_only_option_lease() {
22102283
setup_for_test();

0 commit comments

Comments
 (0)