From a147865048ecfd5e44e9a3aa7c0bbc4fd1283abd Mon Sep 17 00:00:00 2001 From: soruh Date: Thu, 3 Aug 2023 04:40:31 +0200 Subject: [PATCH] fix copy --- src/lib.rs | 43 +++++++++++++++++++++++++++++++------------ src/transaction.rs | 2 +- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ef3b10b..ff811a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -232,6 +232,12 @@ impl RawFilePointer { } impl FileRange { + fn start(self) -> RawFilePointer { + self.start + } + fn end(self) -> RawFilePointer { + self.start + (self.len() - 1) + } fn len(&self) -> u64 { self.len.get() } @@ -426,9 +432,24 @@ impl Db { // TODO: fix pls #[track_caller] - unsafe fn copy(&mut self, from: FileRange, to: FileRange) { - let (head, tail) = self.map.split_at_mut(to.start.0.get() as usize); - tail[0..to.len() as usize].copy_from_slice(&head[from.as_range()]); + unsafe fn copy_nonoverlapping(&mut self, from: FileRange, to: FileRange) { + let len = from.len(); + println!("copy from {from:?} to {to:?} ({len})",); + + // intervals must be non-overlapping and of the same size + assert!(!from.as_range().contains(&(to.start().0.get() as usize))); + assert!(!from.as_range().contains(&(to.end().0.get() as usize))); + assert!(!to.as_range().contains(&(from.start().0.get() as usize))); + assert!(!to.as_range().contains(&(from.end().0.get() as usize))); + assert_eq!(from.len(), to.len()); + + if from.start > to.start { + let (head, tail) = self.map.split_at_mut(from.start.0.get() as usize); + head[to.as_range()].copy_from_slice(&tail[0..len as usize]); + } else { + let (head, tail) = self.map.split_at_mut(to.start.0.get() as usize); + tail[0..len as usize].copy_from_slice(&head[from.as_range()]); + } } #[track_caller] @@ -841,7 +862,6 @@ mod tests { let mut snapshots = VecDeque::new(); for i in 0..20 { - dbg!(i); db.transaction(|transaction| { let root = transaction.root(); @@ -892,6 +912,12 @@ mod tests { root }); + snapshots.push_back(db.create_reader().state.get()); + if snapshots.len() > 10 { + drop(snapshots.pop_front()); + db.free_old_epochs() + } + validate_db(&db, |snaphot, coverage| { coverage.set_allocated(snaphot.root.range()); let data = snaphot.read(snaphot.root); @@ -902,12 +928,6 @@ mod tests { next = snaphot.read(next).next; } }); - - snapshots.push_back(db.create_reader().state.get()); - if snapshots.len() > 10 { - drop(snapshots.pop_front()); - db.free_old_epochs() - } } // TODO: allocate some variably sized strings @@ -1259,9 +1279,8 @@ mod tests { f(snapshot, &mut coverage); - print!("{}", coverage.print()); - if !coverage.all_covered() { + print!("{}", coverage.print()); panic!("space in the file was lost..."); } } diff --git a/src/transaction.rs b/src/transaction.rs index 16f586f..e7bf2ad 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -77,7 +77,7 @@ impl<'t, R> TransactionHandle<'t, R> { } else { let (new, _) = self.allocate_range(range.len()); - self.db.copy(range, new); + self.db.copy_nonoverlapping(range, new); let res = self.replaced.insert( new.start,