@@ -11,7 +11,7 @@ use crate::error::AsyncTiffResult;
1111use crate :: metadata:: MetadataFetch ;
1212
1313/// Logic for managing a cache of sequential buffers
14- struct SequentialCache {
14+ struct SequentialBlockCache {
1515 /// Contiguous blocks from offset 0
1616 ///
1717 /// # Invariant
@@ -22,8 +22,8 @@ struct SequentialCache {
2222 len : u64 ,
2323}
2424
25- impl SequentialCache {
26- /// Create a new, empty SequentialCache
25+ impl SequentialBlockCache {
26+ /// Create a new, empty SequentialBlockCache
2727 fn new ( ) -> Self {
2828 Self {
2929 buffers : vec ! [ ] ,
@@ -55,7 +55,8 @@ impl SequentialCache {
5555
5656 // we slice bytes out of *this* block
5757 let start = remaining. start as usize ;
58- let end = ( remaining. end - remaining. start ) . min ( b_len - remaining. start ) as usize ;
58+ let size = ( remaining. end - remaining. start ) . min ( b_len - remaining. start ) as usize ;
59+ let end = start + size;
5960
6061 let chunk = b. slice ( start..end) ;
6162 out_buffers. push ( chunk) ;
@@ -87,35 +88,49 @@ impl SequentialCache {
8788
8889/// A MetadataFetch implementation that caches fetched data in exponentially growing chunks,
8990/// sequentially from the beginning of the file.
90- pub struct ExponentialMetadataCache < F : MetadataFetch > {
91+ pub struct ReadaheadMetadataCache < F : MetadataFetch > {
9192 inner : F ,
92- cache : Arc < Mutex < SequentialCache > > ,
93+ cache : Arc < Mutex < SequentialBlockCache > > ,
94+ initial : u64 ,
95+ multiplier : f64 ,
9396}
9497
95- impl < F : MetadataFetch > ExponentialMetadataCache < F > {
96- /// Create a new ExponentialMetadataCache wrapping the given MetadataFetch
98+ impl < F : MetadataFetch > ReadaheadMetadataCache < F > {
99+ /// Create a new ReadaheadMetadataCache wrapping the given MetadataFetch
97100 pub fn new ( inner : F ) -> AsyncTiffResult < Self > {
98101 Ok ( Self {
99102 inner,
100- cache : Arc :: new ( Mutex :: new ( SequentialCache :: new ( ) ) ) ,
103+ cache : Arc :: new ( Mutex :: new ( SequentialBlockCache :: new ( ) ) ) ,
104+ initial : 32 * 1024 ,
105+ multiplier : 2.0 ,
101106 } )
102107 }
103- }
104108
105- fn next_fetch_size ( existing_len : u64 ) -> u64 {
106- if existing_len == 0 {
107- 64 * 1024
108- } else {
109- existing_len * 2
109+ /// Set the initial fetch size in bytes, otherwise defaults to 32 KiB
110+ pub fn with_initial_size ( mut self , initial : u64 ) -> Self {
111+ self . initial = initial;
112+ self
113+ }
114+
115+ /// Set the multiplier for subsequent fetch sizes, otherwise defaults to 2.0
116+ pub fn with_multiplier ( mut self , multiplier : f64 ) -> Self {
117+ self . multiplier = multiplier;
118+ self
119+ }
120+
121+ fn next_fetch_size ( & self , existing_len : u64 ) -> u64 {
122+ if existing_len == 0 {
123+ self . initial
124+ } else {
125+ ( existing_len as f64 * self . multiplier ) . round ( ) as u64
126+ }
110127 }
111128}
112129
113- impl < F : MetadataFetch + Send + Sync > MetadataFetch for ExponentialMetadataCache < F > {
130+ impl < F : MetadataFetch + Send + Sync > MetadataFetch for ReadaheadMetadataCache < F > {
114131 fn fetch ( & self , range : Range < u64 > ) -> BoxFuture < ' _ , AsyncTiffResult < Bytes > > {
115- let cache = self . cache . clone ( ) ;
116-
117132 Box :: pin ( async move {
118- let mut g = cache. lock ( ) . await ;
133+ let mut g = self . cache . lock ( ) . await ;
119134
120135 // First check if we already have the range cached
121136 if g. contains ( range. start ..range. end ) {
@@ -125,7 +140,7 @@ impl<F: MetadataFetch + Send + Sync> MetadataFetch for ExponentialMetadataCache<
125140 // Compute the correct fetch range
126141 let start_len = g. len ;
127142 let needed = range. end . saturating_sub ( start_len) ;
128- let fetch_size = next_fetch_size ( start_len) . max ( needed) ;
143+ let fetch_size = self . next_fetch_size ( start_len) . max ( needed) ;
129144 let fetch_range = start_len..start_len + fetch_size;
130145
131146 // Perform the fetch while holding mutex
0 commit comments