mirror of
https://github.com/urbit/ares.git
synced 2024-11-23 00:25:49 +03:00
[ares] extend jam perstistence to use two snapshots
This commit is contained in:
parent
6d51c8c262
commit
b9abb0efe8
@ -26,22 +26,24 @@ const WISH_AXIS: u64 = 10;
|
|||||||
* u3_lord_init in vere to point at this binary and start vere like normal.
|
* u3_lord_init in vere to point at this binary and start vere like normal.
|
||||||
*/
|
*/
|
||||||
pub fn serf() -> io::Result<()> {
|
pub fn serf() -> io::Result<()> {
|
||||||
let pier_path_string = std::env::args()
|
let snap_path_string = std::env::args()
|
||||||
.nth(2)
|
.nth(2)
|
||||||
.ok_or(io::Error::new(io::ErrorKind::Other, "no pier path"))?;
|
.ok_or(io::Error::new(io::ErrorKind::Other, "no pier path"))?;
|
||||||
let mut pier_path = PathBuf::from(pier_path_string);
|
let mut snap_path = PathBuf::from(snap_path_string);
|
||||||
pier_path.push(".urb");
|
snap_path.push(".urb");
|
||||||
pier_path.push("chk");
|
snap_path.push("chk");
|
||||||
create_dir_all(&pier_path)?;
|
create_dir_all(&snap_path)?;
|
||||||
pier_path.push("snapshot.jam");
|
|
||||||
|
|
||||||
let ref mut stack = NockStack::new(8 << 10 << 10, 0);
|
let ref mut stack = NockStack::new(8 << 10 << 10, 0);
|
||||||
let ref mut newt = Newt::new();
|
let ref mut newt = Newt::new();
|
||||||
|
let mut snap_number; // Last valid snapshot number.
|
||||||
|
let mut event_number;
|
||||||
|
let mut arvo;
|
||||||
|
|
||||||
let (mut eve, mut cor) = load(stack, &pier_path).unwrap_or((0, D(0)));
|
(event_number, arvo, snap_number) = load(stack, snap_path.clone()).unwrap_or((0, D(0), 0));
|
||||||
let mug = mug_u32(stack, cor);
|
let mug = mug_u32(stack, arvo);
|
||||||
|
|
||||||
newt.ripe(stack, eve, mug as u64);
|
newt.ripe(stack, event_number, mug as u64);
|
||||||
|
|
||||||
// Can't use for loop because it borrows newt
|
// Can't use for loop because it borrows newt
|
||||||
loop {
|
loop {
|
||||||
@ -61,7 +63,8 @@ pub fn serf() -> io::Result<()> {
|
|||||||
tas!(b"save") => {
|
tas!(b"save") => {
|
||||||
// XX what is eve for?
|
// XX what is eve for?
|
||||||
eprintln!("save");
|
eprintln!("save");
|
||||||
save(stack, &pier_path, eve, cor);
|
snap_number = if snap_number == 0 { 1 } else { 0 };
|
||||||
|
save(stack, snap_path.clone(), snap_number, event_number, arvo);
|
||||||
}
|
}
|
||||||
tas!(b"meld") => eprintln!("meld"),
|
tas!(b"meld") => eprintln!("meld"),
|
||||||
tas!(b"pack") => eprintln!("pack"),
|
tas!(b"pack") => eprintln!("pack"),
|
||||||
@ -71,34 +74,34 @@ pub fn serf() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
tas!(b"peek") => {
|
tas!(b"peek") => {
|
||||||
let sam = raw_slot(writ, 7);
|
let sam = raw_slot(writ, 7);
|
||||||
let res = slam(stack, newt, cor, PEEK_AXIS, sam);
|
let res = slam(stack, newt, arvo, PEEK_AXIS, sam);
|
||||||
newt.peek_done(stack, res);
|
newt.peek_done(stack, res);
|
||||||
}
|
}
|
||||||
tas!(b"play") => {
|
tas!(b"play") => {
|
||||||
let run = if eve == 0 {
|
let run = if event_number == 0 {
|
||||||
// apply lifecycle to first batch
|
// apply lifecycle to first batch
|
||||||
let lit = raw_slot(writ, 7);
|
let lit = raw_slot(writ, 7);
|
||||||
let sub = Cell::new_tuple(stack, &[D(0), D(3)]).as_noun();
|
let sub = Cell::new_tuple(stack, &[D(0), D(3)]).as_noun();
|
||||||
let lyf = Cell::new_tuple(stack, &[D(2), sub, D(0), D(2)]).as_noun();
|
let lyf = Cell::new_tuple(stack, &[D(2), sub, D(0), D(2)]).as_noun();
|
||||||
let gat = interpret(stack, &mut Some(newt), lit, lyf);
|
let gat = interpret(stack, &mut Some(newt), lit, lyf);
|
||||||
cor = raw_slot(gat, 7);
|
arvo = raw_slot(gat, 7);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
|
||||||
// do we need to assert something here?
|
// do we need to assert something here?
|
||||||
// eve = raw_slot(writ, 6).as_direct().unwrap().data();
|
// event_number = raw_slot(writ, 6).as_direct().unwrap().data();
|
||||||
|
|
||||||
let mut lit = raw_slot(writ, 7);
|
let mut lit = raw_slot(writ, 7);
|
||||||
loop {
|
loop {
|
||||||
if let Ok(cell) = lit.as_cell() {
|
if let Ok(cell) = lit.as_cell() {
|
||||||
if run {
|
if run {
|
||||||
let ovo = cell.head();
|
let ovo = cell.head();
|
||||||
let res = slam(stack, newt, cor, POKE_AXIS, ovo).as_cell().unwrap();
|
let res = slam(stack, newt, arvo, POKE_AXIS, ovo).as_cell().unwrap();
|
||||||
cor = res.tail();
|
arvo = res.tail();
|
||||||
}
|
}
|
||||||
eve += 1;
|
event_number += 1;
|
||||||
lit = cell.tail();
|
lit = cell.tail();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -108,13 +111,13 @@ pub fn serf() -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
tas!(b"work") => {
|
tas!(b"work") => {
|
||||||
let ovo = raw_slot(writ, 7);
|
let ovo = raw_slot(writ, 7);
|
||||||
let res = slam(stack, newt, cor, POKE_AXIS, ovo).as_cell().unwrap();
|
let res = slam(stack, newt, arvo, POKE_AXIS, ovo).as_cell().unwrap();
|
||||||
let fec = res.head();
|
let fec = res.head();
|
||||||
cor = res.tail();
|
arvo = res.tail();
|
||||||
|
|
||||||
eve += 1;
|
event_number += 1;
|
||||||
|
|
||||||
newt.work_done(stack, eve, 0, fec);
|
newt.work_done(stack, event_number, 0, fec);
|
||||||
}
|
}
|
||||||
_ => panic!("got message with unknown tag {:?}", tag),
|
_ => panic!("got message with unknown tag {:?}", tag),
|
||||||
};
|
};
|
||||||
@ -123,30 +126,38 @@ pub fn serf() -> io::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slam(stack: &mut NockStack, newt: &mut Newt, cor: Noun, axis: u64, ovo: Noun) -> Noun {
|
pub fn slam(stack: &mut NockStack, newt: &mut Newt, arvo: Noun, axis: u64, ovo: Noun) -> Noun {
|
||||||
let pul = Cell::new_tuple(stack, &[D(9), D(axis), D(0), D(2)]).as_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 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 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, &[cor, ovo]).as_noun();
|
let sub = Cell::new_tuple(stack, &[arvo, ovo]).as_noun();
|
||||||
interpret(stack, &mut Some(newt), sub, fol)
|
interpret(stack, &mut Some(newt), sub, fol)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save(stack: &mut NockStack, snap_path: &PathBuf, eve: u64, cor: Noun) {
|
fn save(
|
||||||
let state = Cell::new(stack, D(eve), cor).as_noun();
|
stack: &mut NockStack,
|
||||||
|
mut snap_path: PathBuf,
|
||||||
|
snap_number: u8,
|
||||||
|
event_number: u64,
|
||||||
|
arvo: Noun,
|
||||||
|
) {
|
||||||
|
snap_path.push(format!("snapshot-{}.snap", snap_number));
|
||||||
|
|
||||||
|
let state = Cell::new(stack, D(event_number), arvo).as_noun();
|
||||||
let mugged = mug(stack, state).as_noun();
|
let mugged = mug(stack, state).as_noun();
|
||||||
let snapshot = Cell::new(stack, mugged, state).as_noun();
|
let snapshot = Cell::new(stack, mugged, state).as_noun();
|
||||||
|
|
||||||
let jammed = jam(stack, snapshot);
|
let jammed = jam(stack, snapshot);
|
||||||
let f_out = OpenOptions::new()
|
let f = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(snap_path)
|
.open(snap_path)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
f_out.set_len((jammed.size() << 3) as u64).unwrap();
|
f.set_len((jammed.size() << 3) as u64).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut out_map = MmapMut::map_mut(&f_out).unwrap();
|
let mut out_map = MmapMut::map_mut(&f).unwrap();
|
||||||
copy_nonoverlapping(
|
copy_nonoverlapping(
|
||||||
jammed.data_pointer() as *mut u8,
|
jammed.data_pointer() as *mut u8,
|
||||||
out_map.as_mut_ptr(),
|
out_map.as_mut_ptr(),
|
||||||
@ -156,12 +167,41 @@ fn save(stack: &mut NockStack, snap_path: &PathBuf, eve: u64, cor: Noun) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load(stack: &mut NockStack, snap_path: &PathBuf) -> io::Result<(u64, Noun)> {
|
fn load(stack: &mut NockStack, snap_path: PathBuf) -> io::Result<(u64, Noun, u8)> {
|
||||||
let f_in = File::open(snap_path)?;
|
let res0 = load_snapshot(stack, snap_path.clone(), 0);
|
||||||
|
let res1 = load_snapshot(stack, snap_path.clone(), 1);
|
||||||
|
|
||||||
let in_len = f_in.metadata().unwrap().len();
|
match (res0, res1) {
|
||||||
|
(Ok((event_number_0, arvo_0)), Ok((event_number_1, arvo_1))) => {
|
||||||
|
if event_number_0 > event_number_1 {
|
||||||
|
Ok((event_number_0, arvo_0, 0))
|
||||||
|
} else {
|
||||||
|
Ok((event_number_1, arvo_1, 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)),
|
||||||
|
(Err(_), Err(_)) => Err(io::Error::new(
|
||||||
|
io::ErrorKind::NotFound,
|
||||||
|
"no valid snapshot found",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_snapshot(
|
||||||
|
stack: &mut NockStack,
|
||||||
|
mut snap_path: PathBuf,
|
||||||
|
number: u8,
|
||||||
|
) -> io::Result<(u64, Noun)> {
|
||||||
|
snap_path.push(format!("snapshot-{}.snap", number));
|
||||||
|
|
||||||
|
eprintln!("\rload: snapshot at {:?}", snap_path);
|
||||||
|
|
||||||
|
let f = File::open(snap_path)?;
|
||||||
|
|
||||||
|
let in_len = f.metadata().unwrap().len();
|
||||||
let jammed = unsafe {
|
let jammed = unsafe {
|
||||||
let in_map = Mmap::map(&f_in).unwrap();
|
let in_map = Mmap::map(&f).unwrap();
|
||||||
let word_len = (in_len + 7) >> 3;
|
let word_len = (in_len + 7) >> 3;
|
||||||
let (mut atom, dest) = IndirectAtom::new_raw_mut(stack, word_len as usize);
|
let (mut atom, dest) = IndirectAtom::new_raw_mut(stack, word_len as usize);
|
||||||
write_bytes(dest.add(word_len as usize - 1), 0, 8);
|
write_bytes(dest.add(word_len as usize - 1), 0, 8);
|
||||||
@ -172,16 +212,18 @@ fn load(stack: &mut NockStack, snap_path: &PathBuf) -> io::Result<(u64, Noun)> {
|
|||||||
|
|
||||||
let snapshot = cue(stack, jammed).as_cell().unwrap();
|
let snapshot = cue(stack, jammed).as_cell().unwrap();
|
||||||
let state = snapshot.tail().as_cell().unwrap();
|
let state = snapshot.tail().as_cell().unwrap();
|
||||||
assert!(
|
if !unsafe {
|
||||||
unsafe {
|
snapshot
|
||||||
mug(stack, state.as_noun())
|
.head()
|
||||||
.as_noun()
|
.raw_equals(mug(stack, state.as_noun()).as_noun())
|
||||||
.raw_equals(snapshot.head())
|
} {
|
||||||
},
|
return Err(io::Error::new(
|
||||||
"snapshot is corrupt"
|
io::ErrorKind::Other,
|
||||||
);
|
"snapshot checksum failed",
|
||||||
let eve = state.head().as_direct().unwrap().data();
|
))
|
||||||
let cor = state.tail();
|
}
|
||||||
|
let event_number = state.head().as_direct().unwrap().data();
|
||||||
|
let arvo = state.tail();
|
||||||
|
|
||||||
Ok((eve, cor))
|
Ok((event_number, arvo))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user