@@ -125,7 +125,7 @@ impl KVStoreSync for FilesystemStore {
125
125
}
126
126
127
127
fn remove (
128
- & self , primary_namespace : & str , secondary_namespace : & str , key : & str , lazy : bool ,
128
+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str ,
129
129
) -> Result < ( ) , lightning:: io:: Error > {
130
130
let path = self . inner . get_checked_dest_file_path (
131
131
primary_namespace,
@@ -134,7 +134,7 @@ impl KVStoreSync for FilesystemStore {
134
134
"remove" ,
135
135
) ?;
136
136
let ( inner_lock_ref, version) = self . get_new_version_and_lock_ref ( path. clone ( ) ) ;
137
- self . inner . remove_version ( inner_lock_ref, path, lazy , version)
137
+ self . inner . remove_version ( inner_lock_ref, path, version)
138
138
}
139
139
140
140
fn list (
@@ -334,81 +334,76 @@ impl FilesystemStoreInner {
334
334
}
335
335
336
336
fn remove_version (
337
- & self , inner_lock_ref : Arc < RwLock < u64 > > , dest_file_path : PathBuf , lazy : bool , version : u64 ,
337
+ & self , inner_lock_ref : Arc < RwLock < u64 > > , dest_file_path : PathBuf , version : u64 ,
338
338
) -> lightning:: io:: Result < ( ) > {
339
339
self . execute_locked_write ( inner_lock_ref, dest_file_path. clone ( ) , version, || {
340
340
if !dest_file_path. is_file ( ) {
341
341
return Ok ( ( ) ) ;
342
342
}
343
343
344
- if lazy {
345
- // If we're lazy we just call remove and be done with it.
344
+ // We try our best to persist the updated metadata to ensure
345
+ // atomicity of this call.
346
+ #[ cfg( not( target_os = "windows" ) ) ]
347
+ {
346
348
fs:: remove_file ( & dest_file_path) ?;
347
- } else {
348
- // If we're not lazy we try our best to persist the updated metadata to ensure
349
- // atomicity of this call.
350
- #[ cfg( not( target_os = "windows" ) ) ]
351
- {
352
- fs:: remove_file ( & dest_file_path) ?;
353
349
354
- let parent_directory = dest_file_path. parent ( ) . ok_or_else ( || {
355
- let msg = format ! (
356
- "Could not retrieve parent directory of {}." ,
357
- dest_file_path. display( )
358
- ) ;
359
- std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidInput , msg)
360
- } ) ?;
361
- let dir_file = fs:: OpenOptions :: new ( ) . read ( true ) . open ( parent_directory) ?;
362
- // The above call to `fs::remove_file` corresponds to POSIX `unlink`, whose changes
363
- // to the inode might get cached (and hence possibly lost on crash), depending on
364
- // the target platform and file system.
365
- //
366
- // In order to assert we permanently removed the file in question we therefore
367
- // call `fsync` on the parent directory on platforms that support it.
368
- dir_file. sync_all ( ) ?;
369
- }
370
-
371
- #[ cfg( target_os = "windows" ) ]
372
- {
373
- // Since Windows `DeleteFile` API is not persisted until the last open file handle
374
- // is dropped, and there seemingly is no reliable way to flush the directory
375
- // metadata, we here fall back to use a 'recycling bin' model, i.e., first move the
376
- // file to be deleted to a temporary trash file and remove the latter file
377
- // afterwards.
378
- //
379
- // This should be marginally better, as, according to the documentation,
380
- // `MoveFileExW` APIs should offer stronger persistence guarantees,
381
- // at least if `MOVEFILE_WRITE_THROUGH`/`MOVEFILE_REPLACE_EXISTING` is set.
382
- // However, all this is partially based on assumptions and local experiments, as
383
- // Windows API is horribly underdocumented.
384
- let mut trash_file_path = dest_file_path. clone ( ) ;
385
- let trash_file_ext =
386
- format ! ( "{}.trash" , self . tmp_file_counter. fetch_add( 1 , Ordering :: AcqRel ) ) ;
387
- trash_file_path. set_extension ( trash_file_ext) ;
350
+ let parent_directory = dest_file_path. parent ( ) . ok_or_else ( || {
351
+ let msg = format ! (
352
+ "Could not retrieve parent directory of {}." ,
353
+ dest_file_path. display( )
354
+ ) ;
355
+ std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidInput , msg)
356
+ } ) ?;
357
+ let dir_file = fs:: OpenOptions :: new ( ) . read ( true ) . open ( parent_directory) ?;
358
+ // The above call to `fs::remove_file` corresponds to POSIX `unlink`, whose changes
359
+ // to the inode might get cached (and hence possibly lost on crash), depending on
360
+ // the target platform and file system.
361
+ //
362
+ // In order to assert we permanently removed the file in question we therefore
363
+ // call `fsync` on the parent directory on platforms that support it.
364
+ dir_file. sync_all ( ) ?;
365
+ }
388
366
389
- call ! ( unsafe {
390
- windows_sys:: Win32 :: Storage :: FileSystem :: MoveFileExW (
391
- path_to_windows_str( & dest_file_path) . as_ptr( ) ,
392
- path_to_windows_str( & trash_file_path) . as_ptr( ) ,
393
- windows_sys:: Win32 :: Storage :: FileSystem :: MOVEFILE_WRITE_THROUGH
367
+ #[ cfg( target_os = "windows" ) ]
368
+ {
369
+ // Since Windows `DeleteFile` API is not persisted until the last open file handle
370
+ // is dropped, and there seemingly is no reliable way to flush the directory
371
+ // metadata, we here fall back to use a 'recycling bin' model, i.e., first move the
372
+ // file to be deleted to a temporary trash file and remove the latter file
373
+ // afterwards.
374
+ //
375
+ // This should be marginally better, as, according to the documentation,
376
+ // `MoveFileExW` APIs should offer stronger persistence guarantees,
377
+ // at least if `MOVEFILE_WRITE_THROUGH`/`MOVEFILE_REPLACE_EXISTING` is set.
378
+ // However, all this is partially based on assumptions and local experiments, as
379
+ // Windows API is horribly underdocumented.
380
+ let mut trash_file_path = dest_file_path. clone ( ) ;
381
+ let trash_file_ext =
382
+ format ! ( "{}.trash" , self . tmp_file_counter. fetch_add( 1 , Ordering :: AcqRel ) ) ;
383
+ trash_file_path. set_extension ( trash_file_ext) ;
384
+
385
+ call ! ( unsafe {
386
+ windows_sys:: Win32 :: Storage :: FileSystem :: MoveFileExW (
387
+ path_to_windows_str( & dest_file_path) . as_ptr( ) ,
388
+ path_to_windows_str( & trash_file_path) . as_ptr( ) ,
389
+ windows_sys:: Win32 :: Storage :: FileSystem :: MOVEFILE_WRITE_THROUGH
394
390
| windows_sys:: Win32 :: Storage :: FileSystem :: MOVEFILE_REPLACE_EXISTING ,
395
- )
396
- } ) ?;
397
-
398
- {
399
- // We fsync the trash file in hopes this will also flush the original's file
400
- // metadata to disk.
401
- let trash_file = fs:: OpenOptions :: new ( )
402
- . read ( true )
403
- . write ( true )
404
- . open ( & trash_file_path. clone ( ) ) ?;
405
- trash_file. sync_all ( ) ?;
406
- }
391
+ )
392
+ } ) ?;
407
393
408
- // We're fine if this remove would fail as the trash file will be cleaned up in
409
- // list eventually.
410
- fs:: remove_file ( trash_file_path) . ok ( ) ;
394
+ {
395
+ // We fsync the trash file in hopes this will also flush the original's file
396
+ // metadata to disk.
397
+ let trash_file = fs:: OpenOptions :: new ( )
398
+ . read ( true )
399
+ . write ( true )
400
+ . open ( & trash_file_path. clone ( ) ) ?;
401
+ trash_file. sync_all ( ) ?;
411
402
}
403
+
404
+ // We're fine if this remove would fail as the trash file will be cleaned up in
405
+ // list eventually.
406
+ fs:: remove_file ( trash_file_path) . ok ( ) ;
412
407
}
413
408
414
409
Ok ( ( ) )
@@ -508,7 +503,7 @@ impl KVStore for FilesystemStore {
508
503
}
509
504
510
505
fn remove (
511
- & self , primary_namespace : & str , secondary_namespace : & str , key : & str , lazy : bool ,
506
+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str ,
512
507
) -> Pin < Box < dyn Future < Output = Result < ( ) , lightning:: io:: Error > > + ' static + Send > > {
513
508
let this = Arc :: clone ( & self . inner ) ;
514
509
let path = match this. get_checked_dest_file_path (
@@ -523,11 +518,11 @@ impl KVStore for FilesystemStore {
523
518
524
519
let ( inner_lock_ref, version) = self . get_new_version_and_lock_ref ( path. clone ( ) ) ;
525
520
Box :: pin ( async move {
526
- tokio:: task:: spawn_blocking ( move || {
527
- this . remove_version ( inner_lock_ref , path , lazy , version )
528
- } )
529
- . await
530
- . unwrap_or_else ( |e| Err ( lightning :: io :: Error :: new ( lightning :: io :: ErrorKind :: Other , e ) ) )
521
+ tokio:: task:: spawn_blocking ( move || this . remove_version ( inner_lock_ref , path , version ) )
522
+ . await
523
+ . unwrap_or_else ( |e| {
524
+ Err ( lightning :: io :: Error :: new ( lightning :: io :: ErrorKind :: Other , e ) )
525
+ } )
531
526
} )
532
527
}
533
528
@@ -772,7 +767,7 @@ mod tests {
772
767
let fut1 = async_fs_store. write ( primary_namespace, secondary_namespace, key, data1) ;
773
768
assert_eq ! ( fs_store. state_size( ) , 1 ) ;
774
769
775
- let fut2 = async_fs_store. remove ( primary_namespace, secondary_namespace, key, false ) ;
770
+ let fut2 = async_fs_store. remove ( primary_namespace, secondary_namespace, key) ;
776
771
assert_eq ! ( fs_store. state_size( ) , 1 ) ;
777
772
778
773
let fut3 = async_fs_store. write ( primary_namespace, secondary_namespace, key, data2. clone ( ) ) ;
@@ -799,7 +794,7 @@ mod tests {
799
794
assert_eq ! ( data2, & * read_data) ;
800
795
801
796
// Test remove.
802
- async_fs_store. remove ( primary_namespace, secondary_namespace, key, false ) . await . unwrap ( ) ;
797
+ async_fs_store. remove ( primary_namespace, secondary_namespace, key) . await . unwrap ( ) ;
803
798
804
799
let listed_keys =
805
800
async_fs_store. list ( primary_namespace, secondary_namespace) . await . unwrap ( ) ;
0 commit comments