@@ -106,6 +106,9 @@ impl CompressedArchiveSnapshotter {
106
106
}
107
107
108
108
fn snapshot < T : TarAppender > ( & self , filepath : & Path , appender : T ) -> StdResult < OngoingSnapshot > {
109
+ let temporary_archive_path = self
110
+ . ongoing_snapshot_directory
111
+ . join ( filepath. with_extension ( "tmp" ) ) ;
109
112
let archive_path = self . ongoing_snapshot_directory . join ( filepath) ;
110
113
if let Some ( archive_dir) = archive_path. parent ( ) {
111
114
fs:: create_dir_all ( archive_dir) . with_context ( || {
@@ -115,17 +118,33 @@ impl CompressedArchiveSnapshotter {
115
118
)
116
119
} ) ?;
117
120
}
118
- let filesize = self . create_and_verify_archive ( & archive_path, appender) . inspect_err ( |_err| {
119
- if archive_path. exists ( ) {
120
- if let Err ( remove_error) = fs:: remove_file ( & archive_path) {
121
- warn ! (
122
- self . logger, " > Post snapshotter.snapshot failure, could not remove temporary archive" ;
123
- "archive_path" => archive_path. display( ) ,
124
- "error" => remove_error
125
- ) ;
121
+ let filesize = self
122
+ . create_and_verify_archive ( & temporary_archive_path, appender)
123
+ . inspect_err ( |_err| {
124
+ if temporary_archive_path. exists ( ) {
125
+ if let Err ( remove_error) = fs:: remove_file ( & temporary_archive_path) {
126
+ warn ! (
127
+ self . logger, " > Post snapshotter.snapshot failure, could not remove temporary archive" ;
128
+ "archive_path" => temporary_archive_path. display( ) ,
129
+ "error" => remove_error
130
+ ) ;
131
+ }
126
132
}
127
- }
128
- } ) . with_context ( || format ! ( "CompressedArchiveSnapshotter can not create and verify archive: '{}'" , archive_path. display( ) ) ) ?;
133
+ } )
134
+ . with_context ( || {
135
+ format ! (
136
+ "CompressedArchiveSnapshotter can not create and verify archive: '{}'" ,
137
+ archive_path. display( )
138
+ )
139
+ } ) ?;
140
+
141
+ fs:: rename ( & temporary_archive_path, & archive_path) . with_context ( || {
142
+ format ! (
143
+ "CompressedArchiveSnapshotter can not rename temporary archive: '{}' to final archive: '{}'" ,
144
+ temporary_archive_path. display( ) ,
145
+ archive_path. display( )
146
+ )
147
+ } ) ?;
129
148
130
149
Ok ( OngoingSnapshot {
131
150
filepath : archive_path,
@@ -331,6 +350,8 @@ mod tests {
331
350
332
351
use mithril_common:: digesters:: DummyCardanoDbBuilder ;
333
352
353
+ use mithril_common:: test_utils:: assert_equivalent;
354
+
334
355
use crate :: services:: snapshotter:: test_tools:: * ;
335
356
use crate :: test_tools:: TestLogger ;
336
357
use crate :: ZstandardCompressionParameters ;
@@ -412,6 +433,47 @@ mod tests {
412
433
assert_eq ! ( vec![ "other-process.file" . to_string( ) ] , remaining_files) ;
413
434
}
414
435
436
+ #[ test]
437
+ fn should_not_delete_an_alreay_existing_archive_with_same_name_if_snapshotting_fail ( ) {
438
+ let test_dir = get_test_directory (
439
+ "should_not_delete_an_alreay_existing_archive_with_same_name_if_snapshotting_fail" ,
440
+ ) ;
441
+ let pending_snapshot_directory = test_dir. join ( "pending_snapshot" ) ;
442
+ let db_directory = test_dir. join ( "db" ) ;
443
+
444
+ let snapshotter = Arc :: new (
445
+ CompressedArchiveSnapshotter :: new (
446
+ db_directory,
447
+ pending_snapshot_directory. clone ( ) ,
448
+ SnapshotterCompressionAlgorithm :: Gzip ,
449
+ TestLogger :: stdout ( ) ,
450
+ )
451
+ . unwrap ( ) ,
452
+ ) ;
453
+
454
+ // this file should not be deleted by the archive creation
455
+ create_file ( & pending_snapshot_directory, "other-process.file" ) ;
456
+ create_file ( & pending_snapshot_directory, "whatever.tar.gz" ) ;
457
+ // an already existing temporary archive file should be deleted
458
+ create_file ( & pending_snapshot_directory, "whatever.tar.tmp" ) ;
459
+
460
+ let _ = snapshotter
461
+ . snapshot_all ( Path :: new ( "whatever.tar.gz" ) )
462
+ . expect_err ( "Snapshotter::snapshot should fail if the db is empty." ) ;
463
+ let remaining_files: Vec < String > = fs:: read_dir ( & pending_snapshot_directory)
464
+ . unwrap ( )
465
+ . map ( |f| f. unwrap ( ) . file_name ( ) . to_str ( ) . unwrap ( ) . to_owned ( ) )
466
+ . collect ( ) ;
467
+
468
+ assert_equivalent (
469
+ vec ! [
470
+ "other-process.file" . to_string( ) ,
471
+ "whatever.tar.gz" . to_string( ) ,
472
+ ] ,
473
+ remaining_files,
474
+ ) ;
475
+ }
476
+
415
477
#[ test]
416
478
fn should_create_a_valid_archive_with_gzip_snapshotter ( ) {
417
479
let test_dir = get_test_directory ( "should_create_a_valid_archive_with_gzip_snapshotter" ) ;
0 commit comments