Skip to content

Commit 14d42e4

Browse files
committed
Fix: Load mebmership since last_applied, not last_membership.index on startup
Modify `StorageHelper::last_membership_in_log()` to scan the log starting from the last applied index rather than the index of the last applied membership log. This change reduces unnecessary I/O operations during startup, previously caused by scanning from an incorrect starting point.
1 parent d396eda commit 14d42e4

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

openraft/src/storage/helper.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,9 @@ where
192192
///
193193
/// Thus a raft node will only need to store at most two recent membership logs.
194194
pub async fn get_membership(&mut self) -> Result<MembershipState<C::NodeId, C::Node>, StorageError<C::NodeId>> {
195-
let (_, sm_mem) = self.state_machine.applied_state().await?;
195+
let (last_applied, sm_mem) = self.state_machine.applied_state().await?;
196196

197-
let sm_mem_next_index = sm_mem.log_id().next_index();
198-
199-
let log_mem = self.last_membership_in_log(sm_mem_next_index).await?;
197+
let log_mem = self.last_membership_in_log(last_applied.next_index()).await?;
200198
tracing::debug!(membership_in_sm=?sm_mem, membership_in_log=?log_mem, "RaftStorage::get_membership");
201199

202200
// There 2 membership configs in logs.
@@ -234,6 +232,9 @@ where
234232
let st = self.log_store.get_log_state().await?;
235233

236234
let mut end = st.last_log_id.next_index();
235+
236+
tracing::info!("load membership from log: [{}..{})", since_index, end);
237+
237238
let start = std::cmp::max(st.last_purged_log_id.next_index(), since_index);
238239
let step = 64;
239240

openraft/src/testing/suite.rs

+58-3
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ where
8585
run_fut(run_test(builder, Self::last_membership_in_log_multi_step))?;
8686
run_fut(run_test(builder, Self::get_membership_initial))?;
8787
run_fut(run_test(builder, Self::get_membership_from_log_and_empty_sm))?;
88-
run_fut(run_test(builder, Self::get_membership_from_log_and_sm))?;
88+
run_fut(run_test(builder, Self::get_membership_from_empty_log_and_sm))?;
89+
run_fut(run_test(builder, Self::get_membership_from_log_le_sm_last_applied))?;
90+
run_fut(run_test(builder, Self::get_membership_from_log_gt_sm_last_applied_1))?;
91+
run_fut(run_test(builder, Self::get_membership_from_log_gt_sm_last_applied_2))?;
8992
run_fut(run_test(builder, Self::get_initial_state_without_init))?;
9093
run_fut(run_test(builder, Self::get_initial_state_membership_from_log_and_sm))?;
9194
run_fut(run_test(builder, Self::get_initial_state_with_state))?;
@@ -259,7 +262,10 @@ where
259262
Ok(())
260263
}
261264

262-
pub async fn get_membership_from_log_and_sm(mut store: LS, mut sm: SM) -> Result<(), StorageError<C::NodeId>> {
265+
pub async fn get_membership_from_empty_log_and_sm(
266+
mut store: LS,
267+
mut sm: SM,
268+
) -> Result<(), StorageError<C::NodeId>> {
263269
tracing::info!("--- no log, read membership from state machine");
264270
{
265271
apply(&mut sm, [
@@ -279,10 +285,31 @@ where
279285
mem_state.effective().membership(),
280286
);
281287
}
288+
Ok(())
289+
}
282290

291+
pub async fn get_membership_from_log_le_sm_last_applied(
292+
mut store: LS,
293+
mut sm: SM,
294+
) -> Result<(), StorageError<C::NodeId>> {
283295
tracing::info!("--- membership presents in log, but smaller than last_applied, read from state machine");
284296
{
285-
append(&mut store, [membership_ent_0::<C>(1, 1, btreeset! {1,2,3})]).await?;
297+
apply(&mut sm, [
298+
blank_ent_0::<C>(1, 1),
299+
membership_ent_0::<C>(1, 2, btreeset! {3,4,5}),
300+
blank_ent_0::<C>(1, 3),
301+
blank_ent_0::<C>(1, 4),
302+
])
303+
.await?;
304+
305+
// Intentionally append a membership entry that does not match the state machine,
306+
// in order to see which membership is loaded.
307+
append(&mut store, [
308+
blank_ent_0::<C>(1, 1),
309+
blank_ent_0::<C>(1, 2),
310+
membership_ent_0::<C>(1, 3, btreeset! {1,2,3}),
311+
])
312+
.await?;
286313

287314
let mem_state = StorageHelper::new(&mut store, &mut sm).get_membership().await?;
288315

@@ -295,10 +322,23 @@ where
295322
mem_state.effective().membership(),
296323
);
297324
}
325+
Ok(())
326+
}
298327

328+
pub async fn get_membership_from_log_gt_sm_last_applied_1(
329+
mut store: LS,
330+
mut sm: SM,
331+
) -> Result<(), StorageError<C::NodeId>> {
299332
tracing::info!("--- membership presents in log and > sm.last_applied, read from log");
300333
{
334+
apply(&mut sm, [
335+
blank_ent_0::<C>(1, 1),
336+
membership_ent_0::<C>(1, 2, btreeset! {3,4,5}),
337+
])
338+
.await?;
339+
301340
append(&mut store, [
341+
membership_ent_0::<C>(1, 1, btreeset! {1,2,3}),
302342
blank_ent_0::<C>(1, 2),
303343
membership_ent_0::<C>(1, 3, btreeset! {7,8,9}),
304344
])
@@ -315,10 +355,25 @@ where
315355
mem_state.effective().membership(),
316356
);
317357
}
358+
Ok(())
359+
}
318360

361+
pub async fn get_membership_from_log_gt_sm_last_applied_2(
362+
mut store: LS,
363+
mut sm: SM,
364+
) -> Result<(), StorageError<C::NodeId>> {
319365
tracing::info!("--- two membership present in log and > sm.last_applied, read 2 from log");
320366
{
367+
apply(&mut sm, [
368+
blank_ent_0::<C>(1, 1),
369+
membership_ent_0::<C>(1, 2, btreeset! {3,4,5}),
370+
])
371+
.await?;
372+
321373
append(&mut store, [
374+
membership_ent_0::<C>(1, 1, btreeset! {1,2,3}),
375+
blank_ent_0::<C>(1, 2),
376+
membership_ent_0::<C>(1, 3, btreeset! {7,8,9}),
322377
blank_ent_0::<C>(1, 4),
323378
membership_ent_0::<C>(1, 5, btreeset! {10,11}),
324379
])

0 commit comments

Comments
 (0)