@@ -19,6 +19,20 @@ fn find_ledger_dir(path_to_walk: &Path) -> Option<PathBuf> {
1919 . map ( |e| e. into_path ( ) )
2020}
2121
22+ fn is_ledger_state_snapshot ( path : & Path ) -> bool {
23+ if path. is_dir ( ) {
24+ path. join ( LedgerStateSnapshot :: IN_MEMORY_META ) . exists ( )
25+ && path. join ( LedgerStateSnapshot :: IN_MEMORY_STATE ) . exists ( )
26+ && path. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) . exists ( )
27+ && path
28+ . join ( LedgerStateSnapshot :: IN_MEMORY_TABLES )
29+ . join ( LedgerStateSnapshot :: IN_MEMORY_TVAR )
30+ . exists ( )
31+ } else {
32+ path. is_file ( )
33+ }
34+ }
35+
2236/// Represent an ledger file in a Cardano node database directory
2337#[ derive( Debug , PartialEq , Eq , Clone ) ]
2438pub enum LedgerStateSnapshot {
@@ -31,6 +45,15 @@ pub enum LedgerStateSnapshot {
3145 /// The filename
3246 filename : OsString ,
3347 } ,
48+ /// Snapshot of an UTxO-HD in-memory ledger state
49+ InMemory {
50+ /// The path to the ledger file
51+ path : PathBuf ,
52+ /// The ledger file slot number
53+ slot_number : SlotNumber ,
54+ /// Name of the ledger state folder
55+ folder_name : OsString ,
56+ } ,
3457}
3558
3659/// [LedgerStateSnapshot::list_all_in_dir] related errors.
@@ -42,6 +65,15 @@ pub enum LedgerStateSnapshotListingError {
4265}
4366
4467impl LedgerStateSnapshot {
68+ /// Filename of the in-memory ledger snapshot 'meta' file
69+ pub const IN_MEMORY_META : & ' static str = "meta" ;
70+ /// Filename of the in-memory ledger snapshot 'state' file
71+ pub const IN_MEMORY_STATE : & ' static str = "state" ;
72+ /// Directory name of the in-memory ledger snapshot 'tables' folder
73+ pub const IN_MEMORY_TABLES : & ' static str = "tables" ;
74+ /// Filename of the in-memory ledger snapshot 'tables/tvar' file
75+ pub const IN_MEMORY_TVAR : & ' static str = "tvar" ;
76+
4577 /// `LedgerStateSnapshot::Legacy` factory
4678 pub fn legacy ( path : PathBuf , slot_number : SlotNumber , filename : OsString ) -> Self {
4779 Self :: Legacy {
@@ -51,6 +83,15 @@ impl LedgerStateSnapshot {
5183 }
5284 }
5385
86+ /// `LedgerStateSnapshot::InMemory` factory
87+ pub fn in_memory ( path : PathBuf , slot_number : SlotNumber , folder_name : OsString ) -> Self {
88+ Self :: InMemory {
89+ path,
90+ slot_number,
91+ folder_name,
92+ }
93+ }
94+
5495 /// Convert a path to a [LedgerStateSnapshot] if it satisfies the constraints.
5596 ///
5697 /// The constraints are:
@@ -62,11 +103,19 @@ impl LedgerStateSnapshot {
62103 . to_string_lossy ( )
63104 . parse :: < u64 > ( )
64105 . map ( |number| {
65- Self :: legacy (
66- path. to_path_buf ( ) ,
67- SlotNumber ( number) ,
68- filename. to_os_string ( ) ,
69- )
106+ if path. is_dir ( ) {
107+ Self :: in_memory (
108+ path. to_path_buf ( ) ,
109+ SlotNumber ( number) ,
110+ filename. to_os_string ( ) ,
111+ )
112+ } else {
113+ Self :: legacy (
114+ path. to_path_buf ( ) ,
115+ SlotNumber ( number) ,
116+ filename. to_os_string ( ) ,
117+ )
118+ }
70119 } )
71120 . ok ( )
72121 } )
@@ -85,7 +134,7 @@ impl LedgerStateSnapshot {
85134 . min_depth ( 1 )
86135 . max_depth ( 1 )
87136 . into_iter ( )
88- . filter_entry ( |e| e . file_type ( ) . is_file ( ) )
137+ . filter_entry ( |e| is_ledger_state_snapshot ( e . path ( ) ) )
89138 . filter_map ( |file| file. ok ( ) )
90139 {
91140 if let Some ( ledger_file) = LedgerStateSnapshot :: from_path ( path. path ( ) ) {
@@ -103,13 +152,23 @@ impl LedgerStateSnapshot {
103152 pub fn get_files_relative_path ( & self ) -> Vec < PathBuf > {
104153 match self {
105154 LedgerStateSnapshot :: Legacy { filename, .. } => vec ! [ PathBuf :: from( filename) ] ,
155+ LedgerStateSnapshot :: InMemory { folder_name, .. } => {
156+ vec ! [
157+ PathBuf :: from( folder_name) . join( Self :: IN_MEMORY_META ) ,
158+ PathBuf :: from( folder_name) . join( Self :: IN_MEMORY_STATE ) ,
159+ PathBuf :: from( folder_name)
160+ . join( Self :: IN_MEMORY_TABLES )
161+ . join( Self :: IN_MEMORY_TVAR ) ,
162+ ]
163+ }
106164 }
107165 }
108166
109167 /// Return the slot number when this snapshot was taken
110168 pub fn slot_number ( & self ) -> SlotNumber {
111169 match self {
112- LedgerStateSnapshot :: Legacy { slot_number, .. } => * slot_number,
170+ LedgerStateSnapshot :: Legacy { slot_number, .. }
171+ | LedgerStateSnapshot :: InMemory { slot_number, .. } => * slot_number,
113172 }
114173 }
115174}
@@ -205,4 +264,141 @@ mod tests {
205264 assert_eq ! ( vec![ "123" , "124" ] , extract_filenames( & ledger_files) ) ;
206265 }
207266 }
267+
268+ // UTxO-HD in-memory rules:
269+ // - a folder named after the slot number at which the snapshots are taken (same naming convention as
270+ // legacy state snapshot)
271+ // - contains three files, with one in a subfolder:
272+ // - "/meta"
273+ // - "/state"
274+ // - "/tables/tvar"
275+ mod utxo_hd_in_memory_ledger_state {
276+ use std:: fs:: create_dir_all;
277+
278+ use super :: * ;
279+
280+ #[ test]
281+ fn list_all_ledger_state_should_not_include_utxo_hd_folder_that_does_not_contains_meta_state_or_tvar_files (
282+ ) {
283+ let target_dir = temp_dir_create ! ( ) ;
284+ let ledger_dir = create_ledger_dir ( & target_dir) ;
285+
286+ let ledger_empty_dir = ledger_dir. join ( "000" ) ;
287+ create_dir ( & ledger_empty_dir) . unwrap ( ) ;
288+
289+ let ledger_with_missing_meta_files = ledger_dir. join ( "100" ) ;
290+ create_dir_all (
291+ ledger_with_missing_meta_files. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
292+ )
293+ . unwrap ( ) ;
294+ create_fake_files (
295+ & ledger_with_missing_meta_files,
296+ & [ LedgerStateSnapshot :: IN_MEMORY_STATE ] ,
297+ ) ;
298+ create_fake_files (
299+ & ledger_with_missing_meta_files. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
300+ & [ LedgerStateSnapshot :: IN_MEMORY_TVAR ] ,
301+ ) ;
302+
303+ let ledger_with_missing_state_files = ledger_dir. join ( "200" ) ;
304+ create_dir_all (
305+ ledger_with_missing_state_files. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
306+ )
307+ . unwrap ( ) ;
308+ create_fake_files (
309+ & ledger_with_missing_state_files,
310+ & [ LedgerStateSnapshot :: IN_MEMORY_META ] ,
311+ ) ;
312+ create_fake_files (
313+ & ledger_with_missing_meta_files. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
314+ & [ LedgerStateSnapshot :: IN_MEMORY_TVAR ] ,
315+ ) ;
316+
317+ let ledger_with_missing_tvar_files = ledger_dir. join ( "300" ) ;
318+ create_dir_all (
319+ ledger_with_missing_tvar_files. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
320+ )
321+ . unwrap ( ) ;
322+ create_fake_files (
323+ & ledger_with_missing_tvar_files,
324+ & [
325+ LedgerStateSnapshot :: IN_MEMORY_STATE ,
326+ LedgerStateSnapshot :: IN_MEMORY_META ,
327+ ] ,
328+ ) ;
329+
330+ let ledger_with_missing_table_folder = ledger_dir. join ( "400" ) ;
331+ create_dir ( & ledger_with_missing_table_folder) . unwrap ( ) ;
332+ create_fake_files (
333+ & ledger_with_missing_table_folder,
334+ & [
335+ LedgerStateSnapshot :: IN_MEMORY_STATE ,
336+ LedgerStateSnapshot :: IN_MEMORY_META ,
337+ ] ,
338+ ) ;
339+
340+ let result = LedgerStateSnapshot :: list_all_in_dir ( & target_dir) . unwrap ( ) ;
341+
342+ assert_eq ! ( Vec :: <LedgerStateSnapshot >:: new( ) , result) ;
343+ }
344+
345+ #[ test]
346+ fn list_all_ledger_state_with_valid_utxo_hd_folder_structure ( ) {
347+ let target_dir = temp_dir_create ! ( ) ;
348+ let ledger_dir = create_ledger_dir ( & target_dir) ;
349+
350+ let ledger_state = ledger_dir. join ( "200" ) ;
351+ create_dir_all ( ledger_state. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ) . unwrap ( ) ;
352+ create_fake_files (
353+ & ledger_state,
354+ & [
355+ LedgerStateSnapshot :: IN_MEMORY_META ,
356+ LedgerStateSnapshot :: IN_MEMORY_STATE ,
357+ ] ,
358+ ) ;
359+ create_fake_files (
360+ & ledger_state. join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
361+ & [ LedgerStateSnapshot :: IN_MEMORY_TVAR ] ,
362+ ) ;
363+
364+ let result = LedgerStateSnapshot :: list_all_in_dir ( & target_dir) . unwrap ( ) ;
365+
366+ assert_eq ! (
367+ vec![ LedgerStateSnapshot :: in_memory(
368+ ledger_state,
369+ SlotNumber ( 200 ) ,
370+ "200" . into( )
371+ ) ] ,
372+ result
373+ ) ;
374+ }
375+
376+ #[ test]
377+ fn get_relative_path_only_list_meta_state_and_tvar_files_even_if_there_are_other_files_in_the_folder (
378+ ) {
379+ let target_dir = temp_dir_create ! ( ) ;
380+ create_dir_all (
381+ target_dir
382+ . join ( "050" )
383+ . join ( LedgerStateSnapshot :: IN_MEMORY_TABLES ) ,
384+ )
385+ . unwrap ( ) ;
386+ let ledger_state = LedgerStateSnapshot :: in_memory (
387+ target_dir. join ( "050" ) ,
388+ SlotNumber ( 50 ) ,
389+ "050" . into ( ) ,
390+ ) ;
391+
392+ assert_eq ! (
393+ vec![
394+ PathBuf :: from( "050" ) . join( LedgerStateSnapshot :: IN_MEMORY_META ) ,
395+ PathBuf :: from( "050" ) . join( LedgerStateSnapshot :: IN_MEMORY_STATE ) ,
396+ PathBuf :: from( "050" )
397+ . join( LedgerStateSnapshot :: IN_MEMORY_TABLES )
398+ . join( LedgerStateSnapshot :: IN_MEMORY_TVAR )
399+ ] ,
400+ ledger_state. get_files_relative_path( ) ,
401+ )
402+ }
403+ }
208404}
0 commit comments