[ares] harden snapshotting

This commit is contained in:
Philip Monk 2023-02-12 17:59:46 -07:00
parent f16c194098
commit dd4dc625bd
2 changed files with 40 additions and 28 deletions

View File

@ -31,11 +31,10 @@ pub fn serf() -> io::Result<()> {
let ref mut stack = NockStack::new(8 << 10 << 10, 0);
let ref mut newt = Newt::new();
let mut snap_number; // Last valid snapshot number.
let mut event_number;
let mut arvo;
(event_number, arvo, snap_number) = load(stack, snap_path.clone()).unwrap_or((0, D(0), 0));
(event_number, arvo) = load(stack, snap_path.clone()).unwrap_or((0, D(0)));
let mug = mug_u32(stack, arvo);
newt.ripe(stack, event_number, mug as u64);
@ -58,8 +57,7 @@ pub fn serf() -> io::Result<()> {
tas!(b"save") => {
// XX what is eve for?
eprintln!("save");
snap_number = if snap_number == 0 { 1 } else { 0 };
save(stack, snap_path.clone(), snap_number, event_number, arvo);
save(stack, snap_path.clone(), event_number, arvo);
}
tas!(b"meld") => eprintln!("meld"),
tas!(b"pack") => eprintln!("pack"),
@ -121,10 +119,10 @@ pub fn serf() -> io::Result<()> {
Ok(())
}
pub fn slam(stack: &mut NockStack, newt: &mut Newt, arvo: Noun, axis: u64, ovo: Noun) -> Noun {
pub fn slam(stack: &mut NockStack, newt: &mut Newt, core: Noun, axis: u64, ovo: Noun) -> Noun {
let pul = Cell::new_tuple(stack, &[D(9), D(axis), D(0), D(2)]).as_noun();
let sam = Cell::new_tuple(stack, &[D(6), D(0), D(7)]).as_noun();
let fol = Cell::new_tuple(stack, &[D(8), pul, D(9), D(2), D(10), sam, D(0), D(2)]).as_noun();
let sub = Cell::new_tuple(stack, &[arvo, ovo]).as_noun();
let sub = Cell::new_tuple(stack, &[core, ovo]).as_noun();
interpret(stack, &mut Some(newt), sub, fol)
}

View File

@ -24,13 +24,14 @@ use std::path::PathBuf;
use std::ptr::copy_nonoverlapping;
use std::ptr::write_bytes;
pub fn save(
stack: &mut NockStack,
mut snap_path: PathBuf,
snap_number: u8,
event_number: u64,
arvo: Noun,
) {
pub fn save(stack: &mut NockStack, mut snap_path: PathBuf, event_number: u64, arvo: Noun) {
// Find the latest valid snapshot, and write to the other file.
let prev_snap = if let Ok((prev_snap, _, _)) = latest_snapshot(stack, snap_path.clone()) {
prev_snap
} else {
0
};
let snap_number = if prev_snap == 0 { 1 } else { 0 };
snap_path.push(format!("snapshot-{}.snap", snap_number));
let jammed_arvo = jam(stack, arvo);
@ -71,23 +72,41 @@ pub fn save(
state.size() << 3,
);
out_map.flush().unwrap();
// This appears to match c3/portable.h: fdatasync for linux, fcntl with F_FULLFSYNC for for
// macos, and fsync for some other platforms.
f.sync_data().unwrap();
};
}
pub fn load(stack: &mut NockStack, snap_path: PathBuf) -> io::Result<(u64, Noun, u8)> {
pub fn load(stack: &mut NockStack, snap_path: PathBuf) -> io::Result<(u64, Noun)> {
let (_num, event_number, state) = latest_snapshot(stack, snap_path)?;
let jammed_arvo =
unsafe { IndirectAtom::new_raw(stack, state.size() - 1, state.data_pointer().add(1)) };
let arvo = cue(stack, jammed_arvo.as_atom());
Ok((event_number, arvo))
}
fn latest_snapshot(
stack: &mut NockStack,
snap_path: PathBuf,
) -> io::Result<(u8, u64, IndirectAtom)> {
let res0 = load_snapshot(stack, snap_path.clone(), 0);
let res1 = load_snapshot(stack, snap_path.clone(), 1);
match (res0, res1) {
(Ok((event_number_0, arvo_0)), Ok((event_number_1, arvo_1))) => {
(Ok((event_number_0, state_0)), Ok((event_number_1, state_1))) => {
if event_number_0 > event_number_1 {
Ok((event_number_0, arvo_0, 0))
Ok((0, event_number_0, state_0))
} else {
Ok((event_number_1, arvo_1, 1))
Ok((1, event_number_1, state_1))
}
}
(Ok((event_number_0, arvo_0)), Err(_)) => Ok((event_number_0, arvo_0, 0)),
(Err(_), Ok((event_number_1, arvo_1))) => Ok((event_number_1, arvo_1, 1)),
(Ok((event_number_0, state_0)), Err(_)) => Ok((0, event_number_0, state_0)),
(Err(_), Ok((event_number_1, state_1))) => Ok((1, event_number_1, state_1)),
(Err(_), Err(_)) => Err(io::Error::new(
io::ErrorKind::NotFound,
"no valid snapshot found",
@ -99,7 +118,7 @@ fn load_snapshot(
stack: &mut NockStack,
mut snap_path: PathBuf,
number: u8,
) -> io::Result<(u64, Noun)> {
) -> io::Result<(u64, IndirectAtom)> {
snap_path.push(format!("snapshot-{}.snap", number));
eprintln!("\rload: snapshot at {:?}", snap_path);
@ -108,7 +127,7 @@ fn load_snapshot(
let in_len = f.metadata().unwrap().len() - 8;
let word_len = (in_len + 7) >> 3;
let (event_number, jammed) = unsafe {
let (event_number, state) = unsafe {
let in_map = Mmap::map(&f).unwrap();
let in_ptr = in_map.as_ptr();
let (mut state, dest) = IndirectAtom::new_raw_mut(stack, word_len as usize);
@ -128,13 +147,8 @@ fn load_snapshot(
));
}
let event_number = *state.data_pointer();
let jammed =
IndirectAtom::new_raw(stack, word_len as usize - 1, state.data_pointer().add(1));
(event_number, jammed)
(*state.data_pointer(), state)
};
let arvo = cue(stack, jammed.as_atom());
Ok((event_number, arvo))
Ok((event_number, state))
}