@@ -233,10 +233,11 @@ impl<F> CurrentSegment<F> {
233
233
tracing:: trace!( page_no, "recycling frame" ) ;
234
234
self . file . write_all_at ( page, page_offset ( * offset) ) ?;
235
235
// we overwrote a frame, record that for later rewrite
236
- tx. recompute_checksum = Some ( tx
237
- . recompute_checksum
238
- . map ( |old| old. min ( * offset) )
239
- . unwrap_or ( * offset) ) ;
236
+ tx. recompute_checksum = Some (
237
+ tx. recompute_checksum
238
+ . map ( |old| old. min ( * offset) )
239
+ . unwrap_or ( * offset) ,
240
+ ) ;
240
241
continue ;
241
242
}
242
243
@@ -272,7 +273,8 @@ impl<F> CurrentSegment<F> {
272
273
self . header. lock( ) . start_frame_no. get( ) + offset as u64 ,
273
274
frame_no
274
275
) ;
275
- self . file . write_at_vectored ( slices, checked_frame_offset ( offset) ) ?;
276
+ self . file
277
+ . write_at_vectored ( slices, checked_frame_offset ( offset) ) ?;
276
278
assert ! (
277
279
current_savepoint. index. insert( page_no, offset) . is_none( ) ,
278
280
"existing frames should be recycled"
@@ -290,7 +292,7 @@ impl<F> CurrentSegment<F> {
290
292
} else {
291
293
tx. current_checksum ( )
292
294
} ;
293
-
295
+
294
296
#[ cfg( debug_assertions) ]
295
297
{
296
298
// ensure that file checksum for that transaction is valid
@@ -319,8 +321,7 @@ impl<F> CurrentSegment<F> {
319
321
// set the header last, so that a transaction does not witness a write before
320
322
// it's actually committed.
321
323
* self . header . lock ( ) = header;
322
- self . current_checksum
323
- . store ( new_checksum, Ordering :: Relaxed ) ;
324
+ self . current_checksum . store ( new_checksum, Ordering :: Relaxed ) ;
324
325
325
326
tx. is_commited = true ;
326
327
@@ -521,13 +522,14 @@ impl<F> CurrentSegment<F> {
521
522
}
522
523
523
524
fn recompute_checksum ( & self , start_offset : u32 , until_offset : u32 ) -> Result < u32 >
524
- where F : FileExt
525
+ where
526
+ F : FileExt ,
525
527
{
526
528
let mut current_checksum = if start_offset == 0 {
527
529
self . header . lock ( ) . salt . get ( )
528
530
} else {
529
531
// we get the checksum from the frame just before the the start offset
530
- let frame_offset = checked_frame_offset ( ( start_offset - 1 ) ) ;
532
+ let frame_offset = checked_frame_offset ( start_offset - 1 ) ;
531
533
let mut out = U32 :: new ( 0 ) ;
532
534
self . file . read_exact_at ( out. as_bytes_mut ( ) , frame_offset) ?;
533
535
out. get ( )
@@ -536,9 +538,11 @@ impl<F> CurrentSegment<F> {
536
538
let mut checked_frame: Box < CheckedFrame > = CheckedFrame :: new_box_zeroed ( ) ;
537
539
for offset in start_offset..=until_offset {
538
540
let frame_offset = checked_frame_offset ( offset) ;
539
- self . file . read_exact_at ( checked_frame. as_bytes_mut ( ) , frame_offset) ?;
541
+ self . file
542
+ . read_exact_at ( checked_frame. as_bytes_mut ( ) , frame_offset) ?;
540
543
current_checksum = checked_frame. frame . checksum ( current_checksum) ;
541
- self . file . write_all_at ( & current_checksum. to_le_bytes ( ) , frame_offset) ?;
544
+ self . file
545
+ . write_all_at ( & current_checksum. to_le_bytes ( ) , frame_offset) ?;
542
546
}
543
547
544
548
Ok ( current_checksum)
@@ -548,7 +552,8 @@ impl<F> CurrentSegment<F> {
548
552
#[ cfg( debug_assertions) ]
549
553
#[ track_caller]
550
554
fn assert_valid_checksum ( & self , from : u32 , until : u32 ) -> Result < ( ) >
551
- where F : FileExt
555
+ where
556
+ F : FileExt ,
552
557
{
553
558
let mut frame: Box < CheckedFrame > = CheckedFrame :: new_box_zeroed ( ) ;
554
559
let mut current_checksum = if from != 0 {
@@ -563,7 +568,11 @@ impl<F> CurrentSegment<F> {
563
568
let offset = checked_frame_offset ( i) ;
564
569
self . file . read_exact_at ( frame. as_bytes_mut ( ) , offset) ?;
565
570
current_checksum = frame. frame . checksum ( current_checksum) ;
566
- assert_eq ! ( current_checksum, frame. checksum. get( ) , "invalid checksum at offset {i}" ) ;
571
+ assert_eq ! (
572
+ current_checksum,
573
+ frame. checksum. get( ) ,
574
+ "invalid checksum at offset {i}"
575
+ ) ;
567
576
}
568
577
569
578
Ok ( ( ) )
@@ -902,8 +911,9 @@ mod test {
902
911
// simulate a flush that only flushes half the pages and then fail
903
912
let inner = self . inner ( ) ;
904
913
let inner = inner. lock ( ) ;
905
- let npages = inner. len ( ) / 4096 ;
906
- std:: fs:: write ( & self . path , & inner[ ..4096 * ( npages / 2 ) ] ) ?;
914
+ // just keep 5 pages from the log. The log will be incomplete and frames will be
915
+ // broken.
916
+ std:: fs:: write ( & self . path , & inner[ ..4096 * 5 ] ) ?;
907
917
Err ( io:: Error :: new ( io:: ErrorKind :: BrokenPipe , "" ) )
908
918
}
909
919
@@ -1007,12 +1017,9 @@ mod test {
1007
1017
let shared = env. shared ( "test" ) ;
1008
1018
1009
1019
conn. execute ( "create table test (x)" , ( ) ) . unwrap ( ) ;
1010
- conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1011
- conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1012
- conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1013
- conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1014
- conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1015
- conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1020
+ for _ in 0 ..6 {
1021
+ conn. execute ( "insert into test values (1234)" , ( ) ) . unwrap ( ) ;
1022
+ }
1016
1023
1017
1024
// trigger a flush, that will fail. When we reopen the db, the log should need recovery
1018
1025
// this simulates a crash before flush
@@ -1028,8 +1035,9 @@ mod test {
1028
1035
{
1029
1036
let env = TestEnv :: new_io_and_tmp ( SyncFailBufferIo :: default ( ) , tmp. clone ( ) ) ;
1030
1037
let conn = env. open_conn ( "test" ) ;
1038
+ // the db was recovered: we lost some rows, but it still works
1031
1039
conn. query_row ( "select count(*) from test" , ( ) , |row| {
1032
- dbg ! ( row) ;
1040
+ assert_eq ! ( row. get :: <_ , u32 > ( 0 ) . unwrap ( ) , 2 ) ;
1033
1041
Ok ( ( ) )
1034
1042
} )
1035
1043
. unwrap ( ) ;
0 commit comments