@@ -43,7 +43,7 @@ struct SstableStreamIterator {
43
43
/// Counts the time used for IO.
44
44
stats_ptr : Arc < AtomicU64 > ,
45
45
46
- // For debugging
46
+ /// For key sanity check of divided SST and debugging
47
47
sstable_info : SstableInfo ,
48
48
}
49
49
@@ -77,6 +77,22 @@ impl SstableStreamIterator {
77
77
}
78
78
}
79
79
80
+ async fn prune_from_valid_block_iter ( & mut self ) -> HummockResult < ( ) > {
81
+ while let Some ( block_iter) = self . block_iter . as_mut ( ) {
82
+ if self
83
+ . sstable_info
84
+ . get_table_ids ( )
85
+ . binary_search ( & block_iter. table_id ( ) . table_id )
86
+ . is_ok ( )
87
+ {
88
+ return Ok ( ( ) ) ;
89
+ } else {
90
+ self . next_block ( ) . await ?;
91
+ }
92
+ }
93
+ Ok ( ( ) )
94
+ }
95
+
80
96
/// Initialises the iterator by moving it to the first KV-pair in the stream's first block where
81
97
/// key >= `seek_key`. If that block does not contain such a KV-pair, the iterator continues to
82
98
/// the first KV-pair of the next block. If `seek_key` is not given, the iterator will move to
@@ -98,7 +114,7 @@ impl SstableStreamIterator {
98
114
}
99
115
}
100
116
101
- Ok ( ( ) )
117
+ self . prune_from_valid_block_iter ( ) . await
102
118
}
103
119
104
120
/// Loads a new block, creates a new iterator for it, and stores that iterator in
@@ -147,6 +163,7 @@ impl SstableStreamIterator {
147
163
block_iter. next ( ) ;
148
164
if !block_iter. is_valid ( ) {
149
165
self . next_block ( ) . await ?;
166
+ self . prune_from_valid_block_iter ( ) . await ?;
150
167
}
151
168
152
169
Ok ( ( ) )
@@ -226,11 +243,12 @@ impl ConcatSstableIterator {
226
243
/// Resets the iterator, loads the specified SST, and seeks in that SST to `seek_key` if given.
227
244
async fn seek_idx (
228
245
& mut self ,
229
- idx : usize ,
246
+ mut idx : usize ,
230
247
seek_key : Option < FullKey < & [ u8 ] > > ,
231
248
) -> HummockResult < ( ) > {
232
249
self . sstable_iter . take ( ) ;
233
- let seek_key: Option < FullKey < & [ u8 ] > > = match ( seek_key, self . key_range . left . is_empty ( ) ) {
250
+ let mut seek_key: Option < FullKey < & [ u8 ] > > = match ( seek_key, self . key_range . left . is_empty ( ) )
251
+ {
234
252
( Some ( seek_key) , false ) => match seek_key. cmp ( & FullKey :: decode ( & self . key_range . left ) ) {
235
253
Ordering :: Less | Ordering :: Equal => Some ( FullKey :: decode ( & self . key_range . left ) ) ,
236
254
Ordering :: Greater => Some ( seek_key) ,
@@ -240,14 +258,14 @@ impl ConcatSstableIterator {
240
258
( None , false ) => Some ( FullKey :: decode ( & self . key_range . left ) ) ,
241
259
} ;
242
260
243
- if idx < self . tables . len ( ) {
261
+ while idx < self . tables . len ( ) {
244
262
let table_info = & self . tables [ idx] ;
245
263
let table = self
246
264
. sstable_store
247
265
. sstable ( table_info, & mut self . stats )
248
266
. await ?;
249
267
let block_metas = & table. value ( ) . meta . block_metas ;
250
- let start_index = match seek_key {
268
+ let mut start_index = match seek_key {
251
269
None => 0 ,
252
270
Some ( seek_key) => {
253
271
// start_index points to the greatest block whose smallest_key <= seek_key.
@@ -268,32 +286,61 @@ impl ConcatSstableIterator {
268
286
) != Ordering :: Greater
269
287
} )
270
288
} ;
271
- if end_index <= start_index {
272
- return Ok ( ( ) ) ;
273
- }
274
-
275
- let stats_ptr = self . stats . remote_io_time . clone ( ) ;
276
- let now = Instant :: now ( ) ;
277
-
278
- let block_stream = self
279
- . sstable_store
280
- . get_stream ( table. value ( ) , Some ( start_index) )
281
- . await ?;
282
-
283
- // Determine time needed to open stream.
284
- let add = ( now. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ) . ceil ( ) ;
285
- stats_ptr. fetch_add ( add as u64 , atomic:: Ordering :: Relaxed ) ;
286
289
287
- let mut sstable_iter = SstableStreamIterator :: new (
288
- table_info,
289
- block_stream,
290
- end_index - start_index,
291
- & self . stats ,
292
- ) ;
293
- sstable_iter. seek ( seek_key) . await ?;
290
+ while start_index < end_index {
291
+ let start_block_table_id = block_metas[ start_index] . table_id ( ) ;
292
+ if table_info
293
+ . get_table_ids ( )
294
+ . binary_search ( & start_block_table_id. table_id )
295
+ . is_ok ( )
296
+ {
297
+ break ;
298
+ } else {
299
+ start_index +=
300
+ & block_metas[ ( start_index + 1 ) ..] . partition_point ( |block_meta| {
301
+ block_meta. table_id ( ) == start_block_table_id
302
+ } ) + 1 ;
303
+ }
304
+ }
294
305
295
- self . sstable_iter = Some ( sstable_iter) ;
306
+ let found = if end_index <= start_index {
307
+ false
308
+ } else {
309
+ let stats_ptr = self . stats . remote_io_time . clone ( ) ;
310
+ let now = Instant :: now ( ) ;
311
+
312
+ let block_stream = self
313
+ . sstable_store
314
+ . get_stream ( table. value ( ) , Some ( start_index) )
315
+ . await ?;
316
+
317
+ // Determine time needed to open stream.
318
+ let add = ( now. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ) . ceil ( ) ;
319
+ stats_ptr. fetch_add ( add as u64 , atomic:: Ordering :: Relaxed ) ;
320
+
321
+ let mut sstable_iter = SstableStreamIterator :: new (
322
+ table_info,
323
+ block_stream,
324
+ end_index - start_index,
325
+ & self . stats ,
326
+ ) ;
327
+ sstable_iter. seek ( seek_key) . await ?;
328
+
329
+ if sstable_iter. is_valid ( ) {
330
+ self . sstable_iter = Some ( sstable_iter) ;
331
+ true
332
+ } else {
333
+ false
334
+ }
335
+ } ;
296
336
self . cur_idx = idx;
337
+
338
+ if found {
339
+ return Ok ( ( ) ) ;
340
+ } else {
341
+ idx += 1 ;
342
+ seek_key = None ;
343
+ }
297
344
}
298
345
Ok ( ( ) )
299
346
}
@@ -383,7 +430,8 @@ mod tests {
383
430
use crate :: hummock:: iterator:: test_utils:: mock_sstable_store;
384
431
use crate :: hummock:: iterator:: HummockIterator ;
385
432
use crate :: hummock:: test_utils:: {
386
- default_builder_opt_for_test, gen_test_sstable, test_key_of, test_value_of, TEST_KEYS_COUNT ,
433
+ default_builder_opt_for_test, gen_test_sstable_and_info, test_key_of, test_value_of,
434
+ TEST_KEYS_COUNT ,
387
435
} ;
388
436
use crate :: hummock:: value:: HummockValue ;
389
437
@@ -394,15 +442,15 @@ mod tests {
394
442
for object_id in 0 ..3 {
395
443
let start_index = object_id * TEST_KEYS_COUNT ;
396
444
let end_index = ( object_id + 1 ) * TEST_KEYS_COUNT ;
397
- let table = gen_test_sstable (
445
+ let ( _table , table_info ) = gen_test_sstable_and_info (
398
446
default_builder_opt_for_test ( ) ,
399
447
object_id as u64 ,
400
448
( start_index..end_index)
401
449
. map ( |i| ( test_key_of ( i) , HummockValue :: put ( test_value_of ( i) ) ) ) ,
402
450
sstable_store. clone ( ) ,
403
451
)
404
452
. await ;
405
- table_infos. push ( table . get_sstable_info ( ) ) ;
453
+ table_infos. push ( table_info ) ;
406
454
}
407
455
let start_index = 5000 ;
408
456
let end_index = 25000 ;
@@ -494,15 +542,15 @@ mod tests {
494
542
for object_id in 0 ..3 {
495
543
let start_index = object_id * TEST_KEYS_COUNT + TEST_KEYS_COUNT / 2 ;
496
544
let end_index = ( object_id + 1 ) * TEST_KEYS_COUNT ;
497
- let table = gen_test_sstable (
545
+ let ( _table , table_info ) = gen_test_sstable_and_info (
498
546
default_builder_opt_for_test ( ) ,
499
547
object_id as u64 ,
500
548
( start_index..end_index)
501
549
. map ( |i| ( test_key_of ( i) , HummockValue :: put ( test_value_of ( i) ) ) ) ,
502
550
sstable_store. clone ( ) ,
503
551
)
504
552
. await ;
505
- table_infos. push ( table . get_sstable_info ( ) ) ;
553
+ table_infos. push ( table_info ) ;
506
554
}
507
555
508
556
// Test seek_idx. Result is dominated by given seek key rather than key range.
@@ -536,7 +584,9 @@ mod tests {
536
584
let block_1_second_key = iter. key ( ) . to_vec ( ) ;
537
585
// Use a big enough seek key and result in invalid iterator.
538
586
let seek_key = test_key_of ( 30001 ) ;
539
- iter. seek_idx ( 0 , Some ( seek_key. to_ref ( ) ) ) . await . unwrap ( ) ;
587
+ iter. seek_idx ( table_infos. len ( ) - 1 , Some ( seek_key. to_ref ( ) ) )
588
+ . await
589
+ . unwrap ( ) ;
540
590
assert ! ( !iter. is_valid( ) ) ;
541
591
542
592
// Test seek_idx. Result is dominated by key range rather than given seek key.
0 commit comments