Skip to content

Commit 4b2ac5c

Browse files
committed
add debug assertion to verify checksum + fix failing tests
1 parent 0542328 commit 4b2ac5c

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

libsql-wal/src/segment/current.rs

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -285,23 +285,42 @@ impl<F> CurrentSegment<F> {
285285

286286
if let Some(size_after) = size_after {
287287
if tx.not_empty() {
288-
if let Some(offset) = tx.recompute_checksum {
289-
self.recompute_checksum(offset, tx.next_offset - 1)?;
288+
let new_checksum = if let Some(offset) = tx.recompute_checksum {
289+
self.recompute_checksum(offset, tx.next_offset - 1)?
290+
} else {
291+
tx.current_checksum()
292+
};
293+
294+
#[cfg(debug_assertions)]
295+
{
296+
// ensure that file checksum for that transaction is valid
297+
let from = {
298+
let header = self.header.lock();
299+
if header.last_commited_frame_no() == 0 {
300+
0
301+
} else {
302+
(header.last_commited_frame_no() - header.start_frame_no.get()) as u32
303+
}
304+
};
305+
306+
self.assert_valid_checksum(from, tx.next_offset - 1)?;
290307
}
308+
291309
let last_frame_no = tx.next_frame_no - 1;
292310
let mut header = { *self.header.lock() };
293311
header.last_commited_frame_no = last_frame_no.into();
294312
header.size_after = size_after.into();
295313
header.recompute_checksum();
296314

297315
self.file.write_all_at(header.as_bytes(), 0)?;
316+
// todo: sync if sync mode is EXTRA
298317
// self.file.sync_data().unwrap();
299318
tx.merge_savepoints(&self.index);
300319
// set the header last, so that a transaction does not witness a write before
301320
// it's actually committed.
302321
*self.header.lock() = header;
303322
self.current_checksum
304-
.store(tx.current_checksum(), Ordering::Relaxed);
323+
.store(new_checksum, Ordering::Relaxed);
305324

306325
tx.is_commited = true;
307326

@@ -343,7 +362,7 @@ impl<F> CurrentSegment<F> {
343362
F: FileExt,
344363
B: IoBufMut + Send + 'static,
345364
{
346-
let byte_offset = dbg!(frame_offset(dbg!(offset)));
365+
let byte_offset = frame_offset(offset);
347366
self.file.read_exact_at_async(buf, byte_offset).await
348367
}
349368

@@ -501,14 +520,14 @@ impl<F> CurrentSegment<F> {
501520
(stream, replicated_until, db_size)
502521
}
503522

504-
fn recompute_checksum(&self, start_offset: u32, until_offset: u32) -> Result<()>
523+
fn recompute_checksum(&self, start_offset: u32, until_offset: u32) -> Result<u32>
505524
where F: FileExt
506525
{
507526
let mut current_checksum = if start_offset == 0 {
508527
self.header.lock().salt.get()
509528
} else {
510529
// we get the checksum from the frame just before the the start offset
511-
let frame_offset = checked_frame_offset(start_offset - 1);
530+
let frame_offset = checked_frame_offset((start_offset - 1));
512531
let mut out = U32::new(0);
513532
self.file.read_exact_at(out.as_bytes_mut(), frame_offset)?;
514533
out.get()
@@ -522,6 +541,31 @@ impl<F> CurrentSegment<F> {
522541
self.file.write_all_at(&current_checksum.to_le_bytes(), frame_offset)?;
523542
}
524543

544+
Ok(current_checksum)
545+
}
546+
547+
/// test fuction to ensure checksum integrity
548+
#[cfg(debug_assertions)]
549+
#[track_caller]
550+
fn assert_valid_checksum(&self, from: u32, until: u32) -> Result<()>
551+
where F: FileExt
552+
{
553+
let mut frame: Box<CheckedFrame> = CheckedFrame::new_box_zeroed();
554+
let mut current_checksum = if from != 0 {
555+
let offset = checked_frame_offset(from - 1);
556+
self.file.read_exact_at(frame.as_bytes_mut(), offset)?;
557+
frame.checksum.get()
558+
} else {
559+
self.header.lock().salt.get()
560+
};
561+
562+
for i in from..=until {
563+
let offset = checked_frame_offset(i);
564+
self.file.read_exact_at(frame.as_bytes_mut(), offset)?;
565+
current_checksum = frame.frame.checksum(current_checksum);
566+
assert_eq!(current_checksum, frame.checksum.get(), "invalid checksum at offset {i}");
567+
}
568+
525569
Ok(())
526570
}
527571
}
@@ -915,7 +959,7 @@ mod test {
915959
let mut inner = self.inner.lock();
916960
if !inner.contains_key(path) {
917961
let data = if path.exists() {
918-
std::fs::read(path).map_err(|e| dbg!(e))?
962+
std::fs::read(path)?
919963
} else {
920964
vec![]
921965
};

libsql-wal/src/segment/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ impl SegmentHeader {
7979
return Err(Error::InvalidHeaderVersion);
8080
}
8181

82-
let computed = dbg!(self.checksum());
83-
if computed == dbg!(self.header_cheksum.get()) {
82+
let computed = self.checksum();
83+
if computed == self.header_cheksum.get() {
8484
return Ok(());
8585
} else {
8686
return Err(Error::InvalidHeaderChecksum);

0 commit comments

Comments
 (0)