@@ -14,34 +14,34 @@ use std::path::{Path, PathBuf};
14
14
15
15
use anyhow:: Context ;
16
16
17
- use mithril_common:: digesters:: immutable_trio_names;
17
+ use mithril_common:: digesters:: { immutable_trio_names, IMMUTABLE_DIR } ;
18
18
use mithril_common:: entities:: ImmutableFileNumber ;
19
19
use mithril_common:: StdResult ;
20
20
21
21
const BASE_ERROR : & str = "Unexpected downloaded file check failed" ;
22
22
23
23
/// Tool to check and remove unexpected files when downloading and unpacking Mithril archives
24
24
pub struct UnexpectedDownloadedFileVerifier {
25
- dir_to_check : PathBuf ,
25
+ target_cardano_db_dir : PathBuf ,
26
26
immutable_files_range_to_expect : RangeInclusive < ImmutableFileNumber > ,
27
27
}
28
28
29
29
/// List of expected files after downloading and unpacking, yielded by `UnexpectedDownloadedFileVerifier::compute_expected_state_after_download`
30
30
pub struct ExpectedFilesAfterDownload {
31
- dir_to_check : PathBuf ,
31
+ target_immutable_files_dir : PathBuf ,
32
32
expected_files : HashSet < PathBuf > ,
33
33
}
34
34
35
35
impl UnexpectedDownloadedFileVerifier {
36
36
/// `UnexpectedDownloadedFileVerifier` factory
37
37
pub fn new < P : AsRef < Path > > (
38
- dir_to_check : P ,
38
+ target_cardano_db_dir : P ,
39
39
network_kind : & str ,
40
40
include_ancillary : bool ,
41
41
last_downloaded_immutable_file_number : ImmutableFileNumber ,
42
42
) -> Self {
43
43
Self {
44
- dir_to_check : dir_to_check . as_ref ( ) . to_path_buf ( ) ,
44
+ target_cardano_db_dir : target_cardano_db_dir . as_ref ( ) . to_path_buf ( ) ,
45
45
immutable_files_range_to_expect : compute_immutable_files_range_to_expect (
46
46
network_kind,
47
47
include_ancillary,
@@ -50,32 +50,42 @@ impl UnexpectedDownloadedFileVerifier {
50
50
}
51
51
}
52
52
53
+ fn target_immutable_files_dir ( & self ) -> PathBuf {
54
+ self . target_cardano_db_dir . join ( IMMUTABLE_DIR )
55
+ }
56
+
53
57
/// Compute the expected state of the folder after download finish
54
58
pub async fn compute_expected_state_after_download (
55
59
& self ,
56
60
) -> StdResult < ExpectedFilesAfterDownload > {
57
- let dir_to_check = self . dir_to_check . to_path_buf ( ) ;
61
+ let immutable_files_dir = self . target_immutable_files_dir ( ) ;
58
62
let immutable_files_range_to_expect = self . immutable_files_range_to_expect . clone ( ) ;
59
63
// target databases can be quite large, avoid blocking the main thread
60
64
let expected_files = tokio:: task:: spawn_blocking ( move || -> StdResult < HashSet < PathBuf > > {
61
- let mut files: HashSet < PathBuf > = std:: fs:: read_dir ( & dir_to_check)
62
- . with_context ( || format ! ( "Failed to read directory {}" , dir_to_check. display( ) ) ) ?
63
- . flat_map ( |e| e. map ( |e| e. path ( ) ) )
64
- . collect ( ) ;
65
+ let mut files: HashSet < PathBuf > = if immutable_files_dir. exists ( ) {
66
+ std:: fs:: read_dir ( & immutable_files_dir)
67
+ . with_context ( || {
68
+ format ! ( "Failed to read directory {}" , immutable_files_dir. display( ) )
69
+ } ) ?
70
+ . flat_map ( |e| e. map ( |e| e. path ( ) ) )
71
+ . collect ( )
72
+ } else {
73
+ HashSet :: new ( )
74
+ } ;
65
75
66
76
// Complete the list with all rightfully downloaded immutable files
67
77
for immutable_file_name in
68
78
immutable_files_range_to_expect. flat_map ( immutable_trio_names)
69
79
{
70
- files. insert ( dir_to_check . join ( immutable_file_name) ) ;
80
+ files. insert ( immutable_files_dir . join ( immutable_file_name) ) ;
71
81
}
72
82
Ok ( files)
73
83
} )
74
84
. await ?
75
85
. with_context ( || BASE_ERROR ) ?;
76
86
77
87
Ok ( ExpectedFilesAfterDownload {
78
- dir_to_check : self . dir_to_check . clone ( ) ,
88
+ target_immutable_files_dir : self . target_immutable_files_dir ( ) ,
79
89
expected_files,
80
90
} )
81
91
}
@@ -105,7 +115,7 @@ impl ExpectedFilesAfterDownload {
105
115
/// *Note: removed directories names are suffixed with a "/"*
106
116
pub async fn remove_unexpected_files ( self ) -> StdResult < Vec < String > > {
107
117
tokio:: task:: spawn_blocking ( move || {
108
- let unexpected_entries: Vec < _ > = std:: fs:: read_dir ( & self . dir_to_check )
118
+ let unexpected_entries: Vec < _ > = std:: fs:: read_dir ( & self . target_immutable_files_dir )
109
119
. with_context ( || BASE_ERROR ) ?
110
120
. flatten ( )
111
121
. filter ( |f| !self . expected_files . contains ( & f. path ( ) . to_path_buf ( ) ) )
@@ -159,6 +169,12 @@ mod tests {
159
169
160
170
use super :: * ;
161
171
172
+ fn create_immutable_files_dir ( parent_dir : & Path ) -> PathBuf {
173
+ let immutable_files_dir = parent_dir. join ( IMMUTABLE_DIR ) ;
174
+ create_dir ( & immutable_files_dir) . unwrap ( ) ;
175
+ immutable_files_dir
176
+ }
177
+
162
178
fn create_immutable_trio ( dir : & Path , immutable_file_number : ImmutableFileNumber ) {
163
179
for immutable_file_name in immutable_trio_names ( immutable_file_number) {
164
180
File :: create ( dir. join ( immutable_file_name) ) . unwrap ( ) ;
@@ -201,8 +217,10 @@ mod tests {
201
217
use super :: * ;
202
218
203
219
#[ tokio:: test]
204
- async fn when_dir_empty_return_empty_if_immutable_files_range_is_empty ( ) {
220
+ async fn when_dir_empty_return_empty_if_immutable_files_dir_does_not_exist_and_range_is_empty (
221
+ ) {
205
222
let temp_dir = temp_dir_create ! ( ) ;
223
+ create_immutable_files_dir ( & temp_dir) ;
206
224
let existing_files =
207
225
UnexpectedDownloadedFileVerifier :: new ( & temp_dir, "network" , false , 0 )
208
226
. compute_expected_state_after_download ( )
@@ -213,7 +231,20 @@ mod tests {
213
231
}
214
232
215
233
#[ tokio:: test]
216
- async fn when_dir_empty_return_immutables_trios_if_immutable_files_range_is_not_empty ( ) {
234
+ async fn when_dir_empty_return_empty_if_immutable_files_dir_exist_and_range_is_empty ( ) {
235
+ let temp_dir = temp_dir_create ! ( ) ;
236
+ let existing_files =
237
+ UnexpectedDownloadedFileVerifier :: new ( & temp_dir, "network" , false , 0 )
238
+ . compute_expected_state_after_download ( )
239
+ . await
240
+ . unwrap ( ) ;
241
+
242
+ assert_eq ! ( existing_files. expected_files, HashSet :: <PathBuf >:: new( ) ) ;
243
+ }
244
+
245
+ #[ tokio:: test]
246
+ async fn when_immutable_files_dir_does_not_exist_return_immutables_trios_if_immutable_files_range_is_not_empty (
247
+ ) {
217
248
let temp_dir = temp_dir_create ! ( ) ;
218
249
let existing_files =
219
250
UnexpectedDownloadedFileVerifier :: new ( & temp_dir, "network" , false , 1 )
@@ -224,21 +255,43 @@ mod tests {
224
255
assert_eq ! (
225
256
existing_files. expected_files,
226
257
HashSet :: from( [
227
- temp_dir. join( "00001.chunk" ) ,
228
- temp_dir. join( "00001.primary" ) ,
229
- temp_dir. join( "00001.secondary" ) ,
258
+ temp_dir. join( IMMUTABLE_DIR ) . join ( "00001.chunk" ) ,
259
+ temp_dir. join( IMMUTABLE_DIR ) . join ( "00001.primary" ) ,
260
+ temp_dir. join( IMMUTABLE_DIR ) . join ( "00001.secondary" ) ,
230
261
] )
231
262
) ;
232
263
}
233
264
234
265
#[ tokio:: test]
235
- async fn add_existing_files_and_dirs ( ) {
266
+ async fn when_immutable_files_dir_empty_return_immutables_trios_if_immutable_files_range_is_not_empty (
267
+ ) {
236
268
let temp_dir = temp_dir_create ! ( ) ;
237
- create_dir ( temp_dir. join ( "dir_1" ) ) . unwrap ( ) ;
238
- create_dir ( temp_dir. join ( "dir_2" ) ) . unwrap ( ) ;
239
- File :: create ( temp_dir. join ( "file_1.txt" ) ) . unwrap ( ) ;
240
- File :: create ( temp_dir. join ( "file_2.txt" ) ) . unwrap ( ) ;
241
- File :: create ( temp_dir. join ( "dir_2" ) . join ( "file_3.txt" ) ) . unwrap ( ) ;
269
+ let immutable_files_dir = create_immutable_files_dir ( & temp_dir) ;
270
+ let existing_files =
271
+ UnexpectedDownloadedFileVerifier :: new ( & temp_dir, "network" , false , 1 )
272
+ . compute_expected_state_after_download ( )
273
+ . await
274
+ . unwrap ( ) ;
275
+
276
+ assert_eq ! (
277
+ existing_files. expected_files,
278
+ HashSet :: from( [
279
+ immutable_files_dir. join( "00001.chunk" ) ,
280
+ immutable_files_dir. join( "00001.primary" ) ,
281
+ immutable_files_dir. join( "00001.secondary" ) ,
282
+ ] )
283
+ ) ;
284
+ }
285
+
286
+ #[ tokio:: test]
287
+ async fn add_existing_files_and_dirs_from_immutable_files_dir_to_expected_files ( ) {
288
+ let temp_dir = temp_dir_create ! ( ) ;
289
+ let immutable_files_dir = create_immutable_files_dir ( & temp_dir) ;
290
+ create_dir ( immutable_files_dir. join ( "dir_1" ) ) . unwrap ( ) ;
291
+ create_dir ( immutable_files_dir. join ( "dir_2" ) ) . unwrap ( ) ;
292
+ File :: create ( immutable_files_dir. join ( "file_1.txt" ) ) . unwrap ( ) ;
293
+ File :: create ( immutable_files_dir. join ( "file_2.txt" ) ) . unwrap ( ) ;
294
+ File :: create ( immutable_files_dir. join ( "dir_2" ) . join ( "file_3.txt" ) ) . unwrap ( ) ;
242
295
243
296
let existing_files =
244
297
UnexpectedDownloadedFileVerifier :: new ( & temp_dir, "network" , false , 0 )
@@ -249,10 +302,10 @@ mod tests {
249
302
assert_eq ! (
250
303
existing_files. expected_files,
251
304
HashSet :: from( [
252
- temp_dir . join( "dir_1" ) ,
253
- temp_dir . join( "dir_2" ) ,
254
- temp_dir . join( "file_1.txt" ) ,
255
- temp_dir . join( "file_2.txt" ) ,
305
+ immutable_files_dir . join( "dir_1" ) ,
306
+ immutable_files_dir . join( "dir_2" ) ,
307
+ immutable_files_dir . join( "file_1.txt" ) ,
308
+ immutable_files_dir . join( "file_2.txt" ) ,
256
309
] )
257
310
) ;
258
311
}
@@ -267,7 +320,7 @@ mod tests {
267
320
async fn when_dir_empty_do_nothing_and_return_none ( ) {
268
321
let temp_dir = temp_dir_create ! ( ) ;
269
322
let existing_before = ExpectedFilesAfterDownload {
270
- dir_to_check : temp_dir. clone ( ) ,
323
+ target_immutable_files_dir : temp_dir. clone ( ) ,
271
324
expected_files : HashSet :: new ( ) ,
272
325
} ;
273
326
@@ -282,7 +335,7 @@ mod tests {
282
335
create_dir ( temp_dir. join ( "dir_1" ) ) . unwrap ( ) ;
283
336
File :: create ( temp_dir. join ( "file_1.txt" ) ) . unwrap ( ) ;
284
337
let existing_before = ExpectedFilesAfterDownload {
285
- dir_to_check : temp_dir. clone ( ) ,
338
+ target_immutable_files_dir : temp_dir. clone ( ) ,
286
339
expected_files : HashSet :: from ( [
287
340
temp_dir. join ( "file_1.txt" ) ,
288
341
temp_dir. join ( "dir_1" ) ,
@@ -299,7 +352,7 @@ mod tests {
299
352
) {
300
353
let temp_dir = temp_dir_create ! ( ) ;
301
354
let existing_before = ExpectedFilesAfterDownload {
302
- dir_to_check : temp_dir. clone ( ) ,
355
+ target_immutable_files_dir : temp_dir. clone ( ) ,
303
356
expected_files : HashSet :: new ( ) ,
304
357
} ;
305
358
@@ -331,8 +384,9 @@ mod tests {
331
384
let temp_dir = temp_dir_create ! ( ) ;
332
385
let verifier = UnexpectedDownloadedFileVerifier :: new ( & temp_dir, "network" , false , 19999 ) ;
333
386
387
+ let immutable_files_dir = create_immutable_files_dir ( & temp_dir) ;
334
388
for immutable_file_number in 0 ..=30000 {
335
- create_immutable_trio ( & temp_dir , immutable_file_number) ;
389
+ create_immutable_trio ( & immutable_files_dir , immutable_file_number) ;
336
390
}
337
391
338
392
let now = Instant :: now ( ) ;
0 commit comments