1
1
use std:: {
2
2
env, fmt,
3
- fs:: { create_dir, read_dir} ,
3
+ fs:: { create_dir, read_dir, remove_dir_all , rename } ,
4
4
path:: { Path , PathBuf } ,
5
5
process:: Command ,
6
6
} ;
@@ -87,6 +87,10 @@ pub struct SnapshotConverterCommand {
87
87
/// UTxO-HD flavor to convert the ledger snapshot to.
88
88
#[ clap( long) ]
89
89
utxo_hd_flavor : UTxOHDFlavor ,
90
+
91
+ /// If set, the converted snapshot replaces the current ledger state in the `db_directory`.
92
+ #[ clap( long) ]
93
+ commit : bool ,
90
94
}
91
95
92
96
impl SnapshotConverterCommand {
@@ -133,6 +137,7 @@ impl SnapshotConverterCommand {
133
137
& distribution_dir,
134
138
& self . cardano_network ,
135
139
& self . utxo_hd_flavor ,
140
+ self . commit ,
136
141
)
137
142
. with_context ( || {
138
143
format ! (
@@ -197,6 +202,7 @@ impl SnapshotConverterCommand {
197
202
distribution_dir : & Path ,
198
203
cardano_network : & CardanoNetwork ,
199
204
utxo_hd_flavor : & UTxOHDFlavor ,
205
+ commit : bool ,
200
206
) -> MithrilResult < ( ) > {
201
207
println ! (
202
208
"Converting ledger state snapshot to '{}' flavor" ,
@@ -223,6 +229,14 @@ impl SnapshotConverterCommand {
223
229
utxo_hd_flavor,
224
230
) ?;
225
231
232
+ if commit {
233
+ Self :: commit_converted_snapshot ( db_dir, & converted_snapshot_path) . with_context (
234
+ || "Failed to overwrite the ledger state with the converted snapshot." ,
235
+ ) ?;
236
+ } else {
237
+ println ! ( "Snapshot location: {}" , converted_snapshot_path. display( ) ) ;
238
+ }
239
+
226
240
Ok ( ( ) )
227
241
}
228
242
@@ -361,18 +375,64 @@ impl SnapshotConverterCommand {
361
375
. parse :: < u64 > ( )
362
376
. with_context ( || format ! ( "Invalid slot number in path filename: {}" , file_name_str) )
363
377
}
378
+
379
+ /// Commits the converted snapshot by replacing the current ledger state snapshots in the database directory.
380
+ fn commit_converted_snapshot (
381
+ db_dir : & Path ,
382
+ converted_snapshot_path : & Path ,
383
+ ) -> MithrilResult < ( ) > {
384
+ let ledger_dir = db_dir. join ( LEDGER_DIR ) ;
385
+ println ! (
386
+ "Upgrading and replacing ledger state in {} with converted snapshot: {}" ,
387
+ ledger_dir. display( ) ,
388
+ converted_snapshot_path. display( )
389
+ ) ;
390
+
391
+ let filename = converted_snapshot_path
392
+ . file_name ( )
393
+ . ok_or_else ( || anyhow ! ( "Missing filename in converted snapshot path" ) ) ?
394
+ . to_string_lossy ( ) ;
395
+
396
+ let ( slot_number, _) = filename
397
+ . split_once ( '_' )
398
+ . ok_or_else ( || anyhow ! ( "Invalid converted snapshot name format: {}" , filename) ) ?;
399
+
400
+ remove_dir_all ( & ledger_dir) . with_context ( || {
401
+ format ! (
402
+ "Failed to remove old ledger state snapshot directory: {}" ,
403
+ ledger_dir. display( )
404
+ )
405
+ } ) ?;
406
+
407
+ create_dir ( & ledger_dir) . with_context ( || {
408
+ format ! (
409
+ "Failed to recreate ledger state snapshot directory: {}" ,
410
+ ledger_dir. display( )
411
+ )
412
+ } ) ?;
413
+
414
+ let destination = ledger_dir. join ( slot_number) ;
415
+ rename ( converted_snapshot_path, & destination) . with_context ( || {
416
+ format ! (
417
+ "Failed to move converted snapshot to ledger directory: {}" ,
418
+ destination. display( )
419
+ )
420
+ } ) ?;
421
+
422
+ Ok ( ( ) )
423
+ }
364
424
}
365
425
366
426
#[ cfg( test) ]
367
427
mod tests {
428
+ use mithril_common:: temp_dir_create;
429
+
368
430
use super :: * ;
369
431
370
432
mod download_cardano_node_distribution {
371
433
use mockall:: predicate:: eq;
372
434
use reqwest:: Url ;
373
435
374
- use mithril_common:: temp_dir_create;
375
-
376
436
use crate :: utils:: { GitHubRelease , MockGitHubReleaseRetriever , MockHttpDownloader } ;
377
437
378
438
use super :: * ;
@@ -742,4 +802,46 @@ mod tests {
742
802
. expect_err ( "Should return error if no valid ledger snapshot directory found" ) ;
743
803
}
744
804
}
805
+
806
+ mod commit_converted_snapshot {
807
+ use std:: fs:: File ;
808
+
809
+ use super :: * ;
810
+
811
+ #[ test]
812
+ fn moves_converted_snapshot_to_ledger_directory ( ) {
813
+ let tmp_dir = temp_dir_create ! ( ) ;
814
+ let ledger_dir = tmp_dir. join ( LEDGER_DIR ) ;
815
+ create_dir ( & ledger_dir) . unwrap ( ) ;
816
+ let previous_snapshot = ledger_dir. join ( "123" ) ;
817
+ File :: create ( & previous_snapshot) . unwrap ( ) ;
818
+
819
+ let converted_snapshot = tmp_dir. join ( "456_lmdb" ) ;
820
+ File :: create ( & converted_snapshot) . unwrap ( ) ;
821
+
822
+ assert ! ( previous_snapshot. exists( ) ) ;
823
+ SnapshotConverterCommand :: commit_converted_snapshot ( & tmp_dir, & converted_snapshot)
824
+ . unwrap ( ) ;
825
+
826
+ assert ! ( !previous_snapshot. exists( ) ) ;
827
+ assert ! ( ledger_dir. join( "456" ) . exists( ) ) ;
828
+ }
829
+
830
+ #[ test]
831
+ fn fails_if_converted_snapshot_has_invalid_filename ( ) {
832
+ let tmp_dir = temp_dir_create ! ( ) ;
833
+ let ledger_dir = tmp_dir. join ( LEDGER_DIR ) ;
834
+ create_dir ( & ledger_dir) . unwrap ( ) ;
835
+ let previous_snapshot = ledger_dir. join ( "123" ) ;
836
+ File :: create ( & previous_snapshot) . unwrap ( ) ;
837
+
838
+ let converted_snapshot = tmp_dir. join ( "456" ) ;
839
+ File :: create ( & converted_snapshot) . unwrap ( ) ;
840
+
841
+ SnapshotConverterCommand :: commit_converted_snapshot ( & tmp_dir, & converted_snapshot)
842
+ . expect_err ( "Should fail if converted snapshot has invalid filename" ) ;
843
+
844
+ assert ! ( previous_snapshot. exists( ) ) ;
845
+ }
846
+ }
745
847
}
0 commit comments