@@ -19,6 +19,20 @@ fn find_ledger_dir(path_to_walk: &Path) -> Option<PathBuf> {
19
19
. map ( |e| e. into_path ( ) )
20
20
}
21
21
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
+
22
36
/// Represent an ledger file in a Cardano node database directory
23
37
#[ derive( Debug , PartialEq , Eq , Clone ) ]
24
38
pub enum LedgerStateSnapshot {
@@ -31,6 +45,15 @@ pub enum LedgerStateSnapshot {
31
45
/// The filename
32
46
filename : OsString ,
33
47
} ,
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
+ } ,
34
57
}
35
58
36
59
/// [LedgerStateSnapshot::list_all_in_dir] related errors.
@@ -42,6 +65,15 @@ pub enum LedgerStateSnapshotListingError {
42
65
}
43
66
44
67
impl 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
+
45
77
/// `LedgerStateSnapshot::Legacy` factory
46
78
pub fn legacy ( path : PathBuf , slot_number : SlotNumber , filename : OsString ) -> Self {
47
79
Self :: Legacy {
@@ -51,6 +83,15 @@ impl LedgerStateSnapshot {
51
83
}
52
84
}
53
85
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
+
54
95
/// Convert a path to a [LedgerStateSnapshot] if it satisfies the constraints.
55
96
///
56
97
/// The constraints are:
@@ -62,11 +103,19 @@ impl LedgerStateSnapshot {
62
103
. to_string_lossy ( )
63
104
. parse :: < u64 > ( )
64
105
. 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
+ }
70
119
} )
71
120
. ok ( )
72
121
} )
@@ -85,7 +134,7 @@ impl LedgerStateSnapshot {
85
134
. min_depth ( 1 )
86
135
. max_depth ( 1 )
87
136
. into_iter ( )
88
- . filter_entry ( |e| e . file_type ( ) . is_file ( ) )
137
+ . filter_entry ( |e| is_ledger_state_snapshot ( e . path ( ) ) )
89
138
. filter_map ( |file| file. ok ( ) )
90
139
{
91
140
if let Some ( ledger_file) = LedgerStateSnapshot :: from_path ( path. path ( ) ) {
@@ -103,13 +152,23 @@ impl LedgerStateSnapshot {
103
152
pub fn get_files_relative_path ( & self ) -> Vec < PathBuf > {
104
153
match self {
105
154
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
+ }
106
164
}
107
165
}
108
166
109
167
/// Return the slot number when this snapshot was taken
110
168
pub fn slot_number ( & self ) -> SlotNumber {
111
169
match self {
112
- LedgerStateSnapshot :: Legacy { slot_number, .. } => * slot_number,
170
+ LedgerStateSnapshot :: Legacy { slot_number, .. }
171
+ | LedgerStateSnapshot :: InMemory { slot_number, .. } => * slot_number,
113
172
}
114
173
}
115
174
}
@@ -205,4 +264,141 @@ mod tests {
205
264
assert_eq ! ( vec![ "123" , "124" ] , extract_filenames( & ledger_files) ) ;
206
265
}
207
266
}
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
+ }
208
404
}
0 commit comments