use std::io;
use std::path::Path;
use kevy_persist::{layout, load_snapshot, replay_aof};
use crate::config::Config;
use crate::metric::OpenReport;
use kevy_store::Store as Keyspace;
pub(crate) fn restore_one_shard(
dir: &Path,
config: &Config,
i: usize,
store: &mut Keyspace,
report: &mut OpenReport,
) -> io::Result<()> {
#[cfg(not(target_arch = "wasm32"))]
store
.enable_seg_rows(&layout::segs_dir(dir, i))
.map_err(io::Error::other)?;
let snap = layout::snapshot_path(dir, i);
if snap.exists() {
load_snapshot(store, &snap)?;
}
let aof = layout::aof_path(dir, i);
if aof.exists() {
replay_shard_aof(dir, config, i, store, &aof, report)?;
}
#[cfg(not(target_arch = "wasm32"))]
store.sweep_orphan_row_segs();
store.demote_to_watermark();
Ok(())
}
fn replay_shard_aof(
dir: &Path,
config: &Config,
i: usize,
store: &mut Keyspace,
aof: &Path,
report: &mut OpenReport,
) -> io::Result<()> {
let _ = (dir, i);
let mut frames = 0u64;
#[cfg(not(target_arch = "wasm32"))]
let segs_dir = layout::segs_dir(dir, i);
#[cfg(not(target_arch = "wasm32"))]
let mut torn: Option<String> = None;
let apply = |args: kevy_persist::Argv| {
#[cfg(not(target_arch = "wasm32"))]
if let Some(f) = kevy_persist::segmented_frame(&args) {
if let Err(e) = kevy_store::apply_segmented(store, &segs_dir, f) {
torn.get_or_insert(e);
}
return;
}
crate::replay::apply(store, &args);
frames += 1;
if frames.is_multiple_of(kevy_persist::REPLAY_DEMOTE_INTERVAL) {
store.demote_to_watermark();
}
};
let r = if config.metric_sink.is_some() {
kevy_persist::replay_aof_quiet(aof, config.replay_resync, apply)?
} else if config.replay_resync {
kevy_persist::replay_aof_resync(aof, apply)?
} else {
replay_aof(aof, apply)?
};
#[cfg(not(target_arch = "wasm32"))]
if let Some(e) = torn {
return Err(io::Error::other(format!("shard {i}: {e}")));
}
fold_replay_report(report, &r);
Ok(())
}
fn fold_replay_report(report: &mut OpenReport, r: &kevy_persist::ReplayReport) {
report.replayed_commands += r.commands;
report.replayed_bytes += r.replayed_bytes;
report.dropped_bytes += r.dropped_bytes;
report.corrupt |= r.corrupt;
report.resynced_bytes += r.resynced_ranges.iter().map(|(a, b)| b - a).sum::<u64>();
}