@@ -32,7 +32,7 @@ use iroh_io::AsyncSliceReader;
32
32
use super :: mutable_mem_storage:: { MutableMemStorage , SizeInfo } ;
33
33
use crate :: {
34
34
store:: BaoBatchWriter ,
35
- util:: { get_limited_slice, MemOrFile , SparseMemFile } ,
35
+ util:: { callback_lock :: CallbackLock , get_limited_slice, FileAndSize , MemOrFile , SparseMemFile } ,
36
36
Hash , IROH_BLOCK_SIZE ,
37
37
} ;
38
38
@@ -81,46 +81,63 @@ struct DataPaths {
81
81
///
82
82
/// For the memory variant, it does reading in a zero copy way, since storage
83
83
/// is already a `Bytes`.
84
- #[ derive( Default , derive_more:: Debug ) ]
85
- pub struct CompleteStorage {
84
+ #[ derive( derive_more:: Debug ) ]
85
+ #[ debug( bound( T : Debug ) ) ]
86
+ pub struct CompleteStorage < T > {
86
87
/// data part, which can be in memory or on disk.
87
88
#[ debug( "{:?}" , data. as_ref( ) . map_mem( |x| x. len( ) ) ) ]
88
- pub data : MemOrFile < Bytes , ( File , u64 ) > ,
89
+ pub data : MemOrFile < Bytes , FileAndSize < T > > ,
89
90
/// outboard part, which can be in memory or on disk.
90
91
#[ debug( "{:?}" , outboard. as_ref( ) . map_mem( |x| x. len( ) ) ) ]
91
- pub outboard : MemOrFile < Bytes , ( File , u64 ) > ,
92
+ pub outboard : MemOrFile < Bytes , FileAndSize < T > > ,
92
93
}
93
94
94
- impl CompleteStorage {
95
+ impl < T > Default for CompleteStorage < T > {
96
+ fn default ( ) -> Self {
97
+ Self {
98
+ data : Default :: default ( ) ,
99
+ outboard : Default :: default ( ) ,
100
+ }
101
+ }
102
+ }
103
+
104
+ impl < T > CompleteStorage < T >
105
+ where
106
+ T : bao_tree:: io:: sync:: ReadAt ,
107
+ {
95
108
/// Read from the data file at the given offset, until end of file or max bytes.
96
109
pub fn read_data_at ( & self , offset : u64 , len : usize ) -> Bytes {
97
110
match & self . data {
98
111
MemOrFile :: Mem ( mem) => get_limited_slice ( mem, offset, len) ,
99
- MemOrFile :: File ( ( file, _size) ) => read_to_end ( file, offset, len) . unwrap ( ) ,
112
+ MemOrFile :: File ( FileAndSize { file, size : _ } ) => {
113
+ read_to_end ( file, offset, len) . unwrap ( )
114
+ }
100
115
}
101
116
}
102
117
103
118
/// Read from the outboard file at the given offset, until end of file or max bytes.
104
119
pub fn read_outboard_at ( & self , offset : u64 , len : usize ) -> Bytes {
105
120
match & self . outboard {
106
121
MemOrFile :: Mem ( mem) => get_limited_slice ( mem, offset, len) ,
107
- MemOrFile :: File ( ( file, _size) ) => read_to_end ( file, offset, len) . unwrap ( ) ,
122
+ MemOrFile :: File ( FileAndSize { file, size : _ } ) => {
123
+ read_to_end ( file, offset, len) . unwrap ( )
124
+ }
108
125
}
109
126
}
110
127
111
128
/// The size of the data file.
112
129
pub fn data_size ( & self ) -> u64 {
113
130
match & self . data {
114
131
MemOrFile :: Mem ( mem) => mem. len ( ) as u64 ,
115
- MemOrFile :: File ( ( _file , size) ) => * size,
132
+ MemOrFile :: File ( FileAndSize { file : _ , size } ) => * size,
116
133
}
117
134
}
118
135
119
136
/// The size of the outboard file.
120
137
pub fn outboard_size ( & self ) -> u64 {
121
138
match & self . outboard {
122
139
MemOrFile :: Mem ( mem) => mem. len ( ) as u64 ,
123
- MemOrFile :: File ( ( _file , size) ) => * size,
140
+ MemOrFile :: File ( FileAndSize { file : _ , size } ) => * size,
124
141
}
125
142
}
126
143
}
@@ -244,7 +261,7 @@ impl FileStorage {
244
261
245
262
/// The storage for a bao file. This can be either in memory or on disk.
246
263
#[ derive( Debug ) ]
247
- pub ( crate ) enum BaoFileStorage {
264
+ pub ( crate ) enum BaoFileStorage < T > {
248
265
/// The entry is incomplete and in memory.
249
266
///
250
267
/// Since it is incomplete, it must be writeable.
@@ -261,16 +278,16 @@ pub(crate) enum BaoFileStorage {
261
278
/// (memory or file).
262
279
///
263
280
/// Writing to this is a no-op, since it is already complete.
264
- Complete ( CompleteStorage ) ,
281
+ Complete ( CompleteStorage < T > ) ,
265
282
}
266
283
267
- impl Default for BaoFileStorage {
284
+ impl < T > Default for BaoFileStorage < T > {
268
285
fn default ( ) -> Self {
269
286
BaoFileStorage :: Complete ( Default :: default ( ) )
270
287
}
271
288
}
272
289
273
- impl BaoFileStorage {
290
+ impl < T > BaoFileStorage < T > {
274
291
/// Take the storage out, leaving an empty storage in its place.
275
292
///
276
293
/// Be careful to put something back in its place, or you will lose data.
@@ -310,11 +327,11 @@ impl BaoFileStorage {
310
327
311
328
/// A weak reference to a bao file handle.
312
329
#[ derive( Debug , Clone ) ]
313
- pub struct BaoFileHandleWeak ( Weak < BaoFileHandleInner > ) ;
330
+ pub struct BaoFileHandleWeak < T > ( Weak < BaoFileHandleInner < T > > ) ;
314
331
315
- impl BaoFileHandleWeak {
332
+ impl < T > BaoFileHandleWeak < T > {
316
333
/// Upgrade to a strong reference if possible.
317
- pub fn upgrade ( & self ) -> Option < BaoFileHandle > {
334
+ pub fn upgrade ( & self ) -> Option < BaoFileHandle < T > > {
318
335
self . 0 . upgrade ( ) . map ( BaoFileHandle )
319
336
}
320
337
@@ -326,15 +343,29 @@ impl BaoFileHandleWeak {
326
343
327
344
/// The inner part of a bao file handle.
328
345
#[ derive( Debug ) ]
329
- pub struct BaoFileHandleInner {
330
- pub ( crate ) storage : RwLock < BaoFileStorage > ,
346
+ pub struct BaoFileHandleInner < T > {
347
+ pub ( crate ) storage : RwLock < BaoFileStorage < T > > ,
331
348
config : Arc < BaoFileConfig > ,
332
349
hash : Hash ,
333
350
}
334
351
335
352
/// A cheaply cloneable handle to a bao file, including the hash and the configuration.
336
- #[ derive( Debug , Clone , derive_more:: Deref ) ]
337
- pub struct BaoFileHandle ( Arc < BaoFileHandleInner > ) ;
353
+ #[ derive( Debug ) ]
354
+ pub struct BaoFileHandle < T > ( Arc < BaoFileHandleInner < T > > ) ;
355
+
356
+ impl < T > Deref for BaoFileHandle < T > {
357
+ type Target = Arc < BaoFileHandleInner < T > > ;
358
+
359
+ fn deref ( & self ) -> & Self :: Target {
360
+ & self . 0
361
+ }
362
+ }
363
+
364
+ impl < T > Clone for BaoFileHandle < T > {
365
+ fn clone ( & self ) -> Self {
366
+ Self ( self . 0 . clone ( ) )
367
+ }
368
+ }
338
369
339
370
pub ( crate ) type CreateCb = Arc < dyn Fn ( & Hash ) -> io:: Result < ( ) > + Send + Sync > ;
340
371
@@ -375,13 +406,18 @@ impl BaoFileConfig {
375
406
376
407
/// A reader for a bao file, reading just the data.
377
408
#[ derive( Debug ) ]
378
- pub struct DataReader ( Option < BaoFileHandle > ) ;
409
+ pub struct DataReader < T > ( Option < BaoFileHandle < T > > ) ;
379
410
380
- async fn with_storage < T , P , F > ( opt : & mut Option < BaoFileHandle > , no_io : P , f : F ) -> io:: Result < T >
411
+ async fn with_storage < T , P , F , H > (
412
+ opt : & mut Option < BaoFileHandle < H > > ,
413
+ no_io : P ,
414
+ f : F ,
415
+ ) -> io:: Result < T >
381
416
where
382
- P : Fn ( & BaoFileStorage ) -> bool + Send + ' static ,
383
- F : FnOnce ( & BaoFileStorage ) -> io:: Result < T > + Send + ' static ,
417
+ P : Fn ( & BaoFileStorage < H > ) -> bool + Send + ' static ,
418
+ F : FnOnce ( & BaoFileStorage < H > ) -> io:: Result < T > + Send + ' static ,
384
419
T : Send + ' static ,
420
+ H : Send + Sync + ' static ,
385
421
{
386
422
let handle = opt
387
423
. take ( )
@@ -410,7 +446,10 @@ where
410
446
res
411
447
}
412
448
413
- impl AsyncSliceReader for DataReader {
449
+ impl < T > AsyncSliceReader for DataReader < T >
450
+ where
451
+ T : Send + Sync + bao_tree:: io:: sync:: ReadAt + ' static ,
452
+ {
414
453
async fn read_at ( & mut self , offset : u64 , len : usize ) -> io:: Result < Bytes > {
415
454
with_storage (
416
455
& mut self . 0 ,
@@ -440,9 +479,12 @@ impl AsyncSliceReader for DataReader {
440
479
441
480
/// A reader for the outboard part of a bao file.
442
481
#[ derive( Debug ) ]
443
- pub struct OutboardReader ( Option < BaoFileHandle > ) ;
482
+ pub struct OutboardReader < T > ( Option < BaoFileHandle < T > > ) ;
444
483
445
- impl AsyncSliceReader for OutboardReader {
484
+ impl < T > AsyncSliceReader for OutboardReader < T >
485
+ where
486
+ T : Send + Sync + bao_tree:: io:: sync:: ReadAt + ' static ,
487
+ {
446
488
async fn read_at ( & mut self , offset : u64 , len : usize ) -> io:: Result < Bytes > {
447
489
with_storage (
448
490
& mut self . 0 ,
@@ -476,7 +518,10 @@ enum HandleChange {
476
518
// later: size verified
477
519
}
478
520
479
- impl BaoFileHandle {
521
+ impl < T > BaoFileHandle < T >
522
+ where
523
+ T : bao_tree:: io:: sync:: ReadAt ,
524
+ {
480
525
/// Create a new bao file handle.
481
526
///
482
527
/// This will create a new file handle with an empty memory storage.
@@ -509,8 +554,8 @@ impl BaoFileHandle {
509
554
pub fn new_complete (
510
555
config : Arc < BaoFileConfig > ,
511
556
hash : Hash ,
512
- data : MemOrFile < Bytes , ( File , u64 ) > ,
513
- outboard : MemOrFile < Bytes , ( File , u64 ) > ,
557
+ data : MemOrFile < Bytes , FileAndSize < T > > ,
558
+ outboard : MemOrFile < Bytes , FileAndSize < T > > ,
514
559
) -> Self {
515
560
let storage = BaoFileStorage :: Complete ( CompleteStorage { data, outboard } ) ;
516
561
Self ( Arc :: new ( BaoFileHandleInner {
@@ -525,7 +570,7 @@ impl BaoFileHandle {
525
570
#[ cfg( feature = "fs-store" ) ]
526
571
pub ( crate ) fn transform (
527
572
& self ,
528
- f : impl FnOnce ( BaoFileStorage ) -> io:: Result < BaoFileStorage > ,
573
+ f : impl FnOnce ( BaoFileStorage < T > ) -> io:: Result < BaoFileStorage < T > > ,
529
574
) -> io:: Result < ( ) > {
530
575
let mut lock = self . storage . write ( ) . unwrap ( ) ;
531
576
let storage = lock. take ( ) ;
@@ -545,15 +590,15 @@ impl BaoFileHandle {
545
590
///
546
591
/// Caution: this is a reader for the unvalidated data file. Reading this
547
592
/// can produce data that does not match the hash.
548
- pub fn data_reader ( & self ) -> DataReader {
593
+ pub fn data_reader ( & self ) -> DataReader < T > {
549
594
DataReader ( Some ( self . clone ( ) ) )
550
595
}
551
596
552
597
/// An AsyncSliceReader for the outboard file.
553
598
///
554
599
/// The outboard file is used to validate the data file. It is not guaranteed
555
600
/// to be complete.
556
- pub fn outboard_reader ( & self ) -> OutboardReader {
601
+ pub fn outboard_reader ( & self ) -> OutboardReader < T > {
557
602
OutboardReader ( Some ( self . clone ( ) ) )
558
603
}
559
604
@@ -567,7 +612,7 @@ impl BaoFileHandle {
567
612
}
568
613
569
614
/// The outboard for the file.
570
- pub fn outboard ( & self ) -> io:: Result < PreOrderOutboard < OutboardReader > > {
615
+ pub fn outboard ( & self ) -> io:: Result < PreOrderOutboard < OutboardReader < T > > > {
571
616
let root = self . hash . into ( ) ;
572
617
let tree = BaoTree :: new ( self . current_size ( ) ?, IROH_BLOCK_SIZE ) ;
573
618
let outboard = self . outboard_reader ( ) ;
@@ -584,7 +629,7 @@ impl BaoFileHandle {
584
629
}
585
630
586
631
/// Create a new writer from the handle.
587
- pub fn writer ( & self ) -> BaoFileWriter {
632
+ pub fn writer ( & self ) -> BaoFileWriter < T > {
588
633
BaoFileWriter ( Some ( self . clone ( ) ) )
589
634
}
590
635
@@ -625,7 +670,7 @@ impl BaoFileHandle {
625
670
}
626
671
627
672
/// Downgrade to a weak reference.
628
- pub fn downgrade ( & self ) -> BaoFileHandleWeak {
673
+ pub fn downgrade ( & self ) -> BaoFileHandleWeak < T > {
629
674
BaoFileHandleWeak ( Arc :: downgrade ( & self . 0 ) )
630
675
}
631
676
}
@@ -676,9 +721,12 @@ impl MutableMemStorage {
676
721
/// It is a BaoFileHandle wrapped in an Option, so that we can take it out
677
722
/// in the future.
678
723
#[ derive( Debug ) ]
679
- pub struct BaoFileWriter ( Option < BaoFileHandle > ) ;
724
+ pub struct BaoFileWriter < T > ( Option < BaoFileHandle < T > > ) ;
680
725
681
- impl BaoBatchWriter for BaoFileWriter {
726
+ impl < T > BaoBatchWriter for BaoFileWriter < T >
727
+ where
728
+ T : Send + Sync + bao_tree:: io:: sync:: ReadAt + ' static ,
729
+ {
682
730
async fn write_batch ( & mut self , size : u64 , batch : Vec < BaoContentItem > ) -> std:: io:: Result < ( ) > {
683
731
let Some ( handle) = self . 0 . take ( ) else {
684
732
return Err ( io:: Error :: new ( io:: ErrorKind :: Other , "deferred batch busy" ) ) ;
@@ -828,7 +876,11 @@ pub mod test_support {
828
876
( outboard. root . into ( ) , chunk_ranges, encoded)
829
877
}
830
878
831
- pub async fn validate ( handle : & BaoFileHandle , original : & [ u8 ] , ranges : & [ Range < u64 > ] ) {
879
+ pub async fn validate (
880
+ handle : & BaoFileHandle < std:: fs:: File > ,
881
+ original : & [ u8 ] ,
882
+ ranges : & [ Range < u64 > ] ,
883
+ ) {
832
884
let mut r = handle. data_reader ( ) ;
833
885
for range in ranges {
834
886
let start = range. start ;
0 commit comments