use tracing::{instrument, Span};
use super::shared_mem::SharedMemory;
use crate::Result;
#[derive(Clone)]
pub(super) struct SharedMemorySnapshot {
snapshot: Vec<u8>,
}
impl SharedMemorySnapshot {
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
pub(super) fn new<S: SharedMemory>(shared_mem: &mut S) -> Result<Self> {
let snapshot = shared_mem.with_exclusivity(|e| e.copy_all_to_vec())??;
Ok(Self { snapshot })
}
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
pub(super) fn replace_snapshot<S: SharedMemory>(&mut self, shared_mem: &mut S) -> Result<()> {
self.snapshot = shared_mem.with_exclusivity(|e| e.copy_all_to_vec())??;
Ok(())
}
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
pub(super) fn restore_from_snapshot<S: SharedMemory>(
&mut self,
shared_mem: &mut S,
) -> Result<()> {
shared_mem.with_exclusivity(|e| e.copy_from_slice(self.snapshot.as_slice(), 0))?
}
}
#[cfg(test)]
mod tests {
use hyperlight_common::mem::PAGE_SIZE_USIZE;
use crate::mem::shared_mem::ExclusiveSharedMemory;
#[test]
fn restore_replace() {
let mut data1 = vec![b'a', b'b', b'c'];
data1.resize_with(PAGE_SIZE_USIZE, || 0);
let data2 = data1.iter().map(|b| b + 1).collect::<Vec<u8>>();
let mut gm = ExclusiveSharedMemory::new(PAGE_SIZE_USIZE).unwrap();
gm.copy_from_slice(data1.as_slice(), 0).unwrap();
let mut snap = super::SharedMemorySnapshot::new(&mut gm).unwrap();
{
assert_eq!(data1, gm.copy_all_to_vec().unwrap());
}
{
gm.copy_from_slice(data2.as_slice(), 0).unwrap();
assert_eq!(data2, gm.copy_all_to_vec().unwrap());
snap.restore_from_snapshot(&mut gm).unwrap();
assert_eq!(data1, gm.copy_all_to_vec().unwrap());
}
{
gm.copy_from_slice(data2.as_slice(), 0).unwrap();
assert_eq!(data2, gm.copy_all_to_vec().unwrap());
snap.replace_snapshot(&mut gm).unwrap();
assert_eq!(data2, gm.copy_all_to_vec().unwrap());
snap.restore_from_snapshot(&mut gm).unwrap();
assert_eq!(data2, gm.copy_all_to_vec().unwrap());
}
}
}