22// This source code is licensed under both the Apache 2.0 and MIT License
33// (found in the LICENSE-* files in the repository)
44
5- use super :: { range:: Range , value_block:: CachePolicy } ;
5+ use super :: { range:: Range , value_block:: CachePolicy , Segment } ;
66use crate :: { level_manifest:: level:: Level , InternalValue , UserKey } ;
77use std:: { ops:: Bound , sync:: Arc } ;
88
@@ -14,6 +14,7 @@ pub struct LevelReader {
1414 lo_reader : Option < Range > ,
1515 hi_reader : Option < Range > ,
1616 cache_policy : CachePolicy ,
17+ prefix_hash : Option < ( u64 , u64 ) > ,
1718}
1819
1920impl LevelReader {
@@ -22,6 +23,7 @@ impl LevelReader {
2223 level : Arc < Level > ,
2324 range : & ( Bound < UserKey > , Bound < UserKey > ) ,
2425 cache_policy : CachePolicy ,
26+ prefix_hash : Option < ( u64 , u64 ) > ,
2527 ) -> Self {
2628 assert ! ( !level. is_empty( ) , "level reader cannot read empty level" ) ;
2729
@@ -36,10 +38,17 @@ impl LevelReader {
3638 lo_reader : None ,
3739 hi_reader : None ,
3840 cache_policy,
41+ prefix_hash,
3942 } ;
4043 } ;
4144
42- Self :: from_indexes ( level, range, ( Some ( lo) , Some ( hi) ) , cache_policy)
45+ Self :: from_indexes (
46+ level,
47+ range,
48+ ( Some ( lo) , Some ( hi) ) ,
49+ cache_policy,
50+ prefix_hash,
51+ )
4352 }
4453
4554 #[ must_use]
@@ -48,6 +57,7 @@ impl LevelReader {
4857 range : & ( Bound < UserKey > , Bound < UserKey > ) ,
4958 ( lo, hi) : ( Option < usize > , Option < usize > ) ,
5059 cache_policy : CachePolicy ,
60+ prefix_hash : Option < ( u64 , u64 ) > ,
5161 ) -> Self {
5262 let lo = lo. unwrap_or_default ( ) ;
5363 let hi = hi. unwrap_or ( level. len ( ) - 1 ) ;
@@ -71,8 +81,14 @@ impl LevelReader {
7181 lo_reader : Some ( lo_reader) ,
7282 hi_reader,
7383 cache_policy,
84+ prefix_hash,
7485 }
7586 }
87+
88+ fn may_segment_contain_hash ( & self , segment : & Segment ) -> bool {
89+ self . prefix_hash
90+ . map_or ( true , |hash| segment. may_contain_hash ( hash) )
91+ }
7692}
7793
7894impl Iterator for LevelReader {
@@ -87,24 +103,20 @@ impl Iterator for LevelReader {
87103
88104 // NOTE: Lo reader is empty, get next one
89105 self . lo_reader = None ;
90- self . lo += 1 ;
91-
92- if self . lo < self . hi {
93- self . lo_reader = Some (
94- self . segments
95- . get ( self . lo )
96- . expect ( "should exist" )
97- . iter ( )
98- . cache_policy ( self . cache_policy ) ,
99- ) ;
100- }
101- } else if let Some ( hi_reader) = & mut self . hi_reader {
106+ } else if self . lo == self . hi {
102107 // NOTE: We reached the hi marker, so consume from it instead
103108 //
104109 // If it returns nothing, it is empty, so we are done
105- return hi_reader. next ( ) ;
110+ return self . hi_reader . as_mut ( ) . and_then ( |r| r . next ( ) ) ;
106111 } else {
107- return None ;
112+ self . lo += 1 ;
113+
114+ if self . lo < self . hi {
115+ let segment = self . segments . get ( self . lo ) . expect ( "should exist" ) ;
116+ if self . may_segment_contain_hash ( segment) {
117+ self . lo_reader = Some ( segment. iter ( ) . cache_policy ( self . cache_policy ) ) ;
118+ }
119+ }
108120 }
109121 }
110122 }
@@ -118,26 +130,22 @@ impl DoubleEndedIterator for LevelReader {
118130 return Some ( item) ;
119131 }
120132
121- // NOTE: Hi reader is empty, get orev one
133+ // NOTE: Hi reader is empty, get the previous one
122134 self . hi_reader = None ;
123- self . hi -= 1 ;
124-
125- if self . lo < self . hi {
126- self . hi_reader = Some (
127- self . segments
128- . get ( self . hi )
129- . expect ( "should exist" )
130- . iter ( )
131- . cache_policy ( self . cache_policy ) ,
132- ) ;
133- }
134- } else if let Some ( lo_reader) = & mut self . lo_reader {
135+ } else if self . lo == self . hi {
135136 // NOTE: We reached the lo marker, so consume from it instead
136137 //
137138 // If it returns nothing, it is empty, so we are done
138- return lo_reader. next_back ( ) ;
139+ return self . lo_reader . as_mut ( ) . and_then ( |r| r . next_back ( ) ) ;
139140 } else {
140- return None ;
141+ self . hi -= 1 ;
142+
143+ if self . lo < self . hi {
144+ let segment = self . segments . get ( self . hi ) . expect ( "should exist" ) ;
145+ if self . may_segment_contain_hash ( segment) {
146+ self . hi_reader = Some ( segment. iter ( ) . cache_policy ( self . cache_policy ) ) ;
147+ }
148+ }
141149 }
142150 }
143151 }
@@ -187,8 +195,12 @@ mod tests {
187195
188196 #[ allow( clippy:: unwrap_used) ]
189197 {
190- let multi_reader =
191- LevelReader :: new ( level. clone ( ) , & ( Unbounded , Unbounded ) , CachePolicy :: Read ) ;
198+ let multi_reader = LevelReader :: new (
199+ level. clone ( ) ,
200+ & ( Unbounded , Unbounded ) ,
201+ CachePolicy :: Read ,
202+ None ,
203+ ) ;
192204
193205 let mut iter = multi_reader. flatten ( ) ;
194206
@@ -208,8 +220,12 @@ mod tests {
208220
209221 #[ allow( clippy:: unwrap_used) ]
210222 {
211- let multi_reader =
212- LevelReader :: new ( level. clone ( ) , & ( Unbounded , Unbounded ) , CachePolicy :: Read ) ;
223+ let multi_reader = LevelReader :: new (
224+ level. clone ( ) ,
225+ & ( Unbounded , Unbounded ) ,
226+ CachePolicy :: Read ,
227+ None ,
228+ ) ;
213229
214230 let mut iter = multi_reader. rev ( ) . flatten ( ) ;
215231
@@ -229,7 +245,8 @@ mod tests {
229245
230246 #[ allow( clippy:: unwrap_used) ]
231247 {
232- let multi_reader = LevelReader :: new ( level, & ( Unbounded , Unbounded ) , CachePolicy :: Read ) ;
248+ let multi_reader =
249+ LevelReader :: new ( level, & ( Unbounded , Unbounded ) , CachePolicy :: Read , None ) ;
233250
234251 let mut iter = multi_reader. flatten ( ) ;
235252
0 commit comments