2
2
// This source code is licensed under both the Apache 2.0 and MIT License
3
3
// (found in the LICENSE-* files in the repository)
4
4
5
- use super :: { range:: Range , value_block:: CachePolicy } ;
5
+ use super :: { range:: Range , value_block:: CachePolicy , Segment } ;
6
6
use crate :: { level_manifest:: level:: Level , InternalValue , UserKey } ;
7
7
use std:: { ops:: Bound , sync:: Arc } ;
8
8
@@ -14,6 +14,7 @@ pub struct LevelReader {
14
14
lo_reader : Option < Range > ,
15
15
hi_reader : Option < Range > ,
16
16
cache_policy : CachePolicy ,
17
+ prefix_hash : Option < ( u64 , u64 ) > ,
17
18
}
18
19
19
20
impl LevelReader {
@@ -22,6 +23,7 @@ impl LevelReader {
22
23
level : Arc < Level > ,
23
24
range : & ( Bound < UserKey > , Bound < UserKey > ) ,
24
25
cache_policy : CachePolicy ,
26
+ prefix_hash : Option < ( u64 , u64 ) > ,
25
27
) -> Self {
26
28
assert ! ( !level. is_empty( ) , "level reader cannot read empty level" ) ;
27
29
@@ -36,10 +38,17 @@ impl LevelReader {
36
38
lo_reader : None ,
37
39
hi_reader : None ,
38
40
cache_policy,
41
+ prefix_hash,
39
42
} ;
40
43
} ;
41
44
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
+ )
43
52
}
44
53
45
54
#[ must_use]
@@ -48,6 +57,7 @@ impl LevelReader {
48
57
range : & ( Bound < UserKey > , Bound < UserKey > ) ,
49
58
( lo, hi) : ( Option < usize > , Option < usize > ) ,
50
59
cache_policy : CachePolicy ,
60
+ prefix_hash : Option < ( u64 , u64 ) > ,
51
61
) -> Self {
52
62
let lo = lo. unwrap_or_default ( ) ;
53
63
let hi = hi. unwrap_or ( level. len ( ) - 1 ) ;
@@ -71,8 +81,14 @@ impl LevelReader {
71
81
lo_reader : Some ( lo_reader) ,
72
82
hi_reader,
73
83
cache_policy,
84
+ prefix_hash,
74
85
}
75
86
}
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
+ }
76
92
}
77
93
78
94
impl Iterator for LevelReader {
@@ -87,24 +103,20 @@ impl Iterator for LevelReader {
87
103
88
104
// NOTE: Lo reader is empty, get next one
89
105
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 {
102
107
// NOTE: We reached the hi marker, so consume from it instead
103
108
//
104
109
// 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 ( ) ) ;
106
111
} 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
+ }
108
120
}
109
121
}
110
122
}
@@ -118,26 +130,22 @@ impl DoubleEndedIterator for LevelReader {
118
130
return Some ( item) ;
119
131
}
120
132
121
- // NOTE: Hi reader is empty, get orev one
133
+ // NOTE: Hi reader is empty, get the previous one
122
134
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 {
135
136
// NOTE: We reached the lo marker, so consume from it instead
136
137
//
137
138
// 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 ( ) ) ;
139
140
} 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
+ }
141
149
}
142
150
}
143
151
}
@@ -187,8 +195,12 @@ mod tests {
187
195
188
196
#[ allow( clippy:: unwrap_used) ]
189
197
{
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
+ ) ;
192
204
193
205
let mut iter = multi_reader. flatten ( ) ;
194
206
@@ -208,8 +220,12 @@ mod tests {
208
220
209
221
#[ allow( clippy:: unwrap_used) ]
210
222
{
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
+ ) ;
213
229
214
230
let mut iter = multi_reader. rev ( ) . flatten ( ) ;
215
231
@@ -229,7 +245,8 @@ mod tests {
229
245
230
246
#[ allow( clippy:: unwrap_used) ]
231
247
{
232
- let multi_reader = LevelReader :: new ( level, & ( Unbounded , Unbounded ) , CachePolicy :: Read ) ;
248
+ let multi_reader =
249
+ LevelReader :: new ( level, & ( Unbounded , Unbounded ) , CachePolicy :: Read , None ) ;
233
250
234
251
let mut iter = multi_reader. flatten ( ) ;
235
252
0 commit comments