@ -6,9 +6,10 @@
# ifndef ROCKSDB_LITE
# include "db/forward_iterator.h"
# include <limits>
# include <string>
# include <utility>
# include <limits>
# include "db/db_impl.h"
# include "db/db_iter.h"
# include "db/column_family.h"
@ -37,12 +38,16 @@ class LevelIterator : public Iterator {
assert ( file_index < files_ . size ( ) ) ;
if ( file_index ! = file_index_ ) {
file_index_ = file_index ;
Reset ( ) ;
}
valid_ = false ;
}
void Reset ( ) {
assert ( file_index_ < files_ . size ( ) ) ;
file_iter_ . reset ( cfd_ - > table_cache ( ) - > NewIterator (
read_options_ , * ( cfd_ - > soptions ( ) ) , cfd_ - > internal_comparator ( ) ,
files_ [ file_index_ ] - > fd , nullptr /* table_reader_ptr */ , false ) ) ;
}
valid_ = false ;
}
void SeekToLast ( ) override {
status_ = Status : : NotSupported ( " LevelIterator::SeekToLast() " ) ;
valid_ = false ;
@ -63,12 +68,15 @@ class LevelIterator : public Iterator {
assert ( file_iter_ ! = nullptr ) ;
file_iter_ - > Seek ( internal_key ) ;
valid_ = file_iter_ - > Valid ( ) ;
assert ( valid_ ) ;
}
void Next ( ) override {
assert ( valid_ ) ;
file_iter_ - > Next ( ) ;
while ( ! file_iter_ - > Valid ( ) ) {
for ( ; ; ) {
if ( file_iter_ - > status ( ) . IsIncomplete ( ) | | file_iter_ - > Valid ( ) ) {
valid_ = ! file_iter_ - > status ( ) . IsIncomplete ( ) ;
return ;
}
if ( file_index_ + 1 > = files_ . size ( ) ) {
valid_ = false ;
return ;
@ -76,7 +84,6 @@ class LevelIterator : public Iterator {
SetFileIndex ( file_index_ + 1 ) ;
file_iter_ - > SeekToFirst ( ) ;
}
valid_ = file_iter_ - > Valid ( ) ;
}
Slice key ( ) const override {
assert ( valid_ ) ;
@ -160,6 +167,8 @@ void ForwardIterator::SeekToFirst() {
if ( sv_ = = nullptr | |
sv_ - > version_number ! = cfd_ - > GetSuperVersionNumber ( ) ) {
RebuildIterators ( ) ;
} else if ( status_ . IsIncomplete ( ) ) {
ResetIncompleteIterators ( ) ;
}
SeekInternal ( Slice ( ) , true ) ;
}
@ -168,6 +177,8 @@ void ForwardIterator::Seek(const Slice& internal_key) {
if ( sv_ = = nullptr | |
sv_ - > version_number ! = cfd_ - > GetSuperVersionNumber ( ) ) {
RebuildIterators ( ) ;
} else if ( status_ . IsIncomplete ( ) ) {
ResetIncompleteIterators ( ) ;
}
SeekInternal ( internal_key , false ) ;
}
@ -211,7 +222,15 @@ void ForwardIterator::SeekInternal(const Slice& internal_key,
}
l0_iters_ [ i ] - > Seek ( internal_key ) ;
}
if ( l0_iters_ [ i ] - > Valid ( ) ) {
if ( l0_iters_ [ i ] - > status ( ) . IsIncomplete ( ) ) {
// if any of the immutable iterators is incomplete (no-io option was
// used), we are unable to reliably find the smallest key
assert ( read_options_ . read_tier = = kBlockCacheTier ) ;
status_ = l0_iters_ [ i ] - > status ( ) ;
valid_ = false ;
return ;
} else if ( l0_iters_ [ i ] - > Valid ( ) ) {
immutable_min_heap_ . push ( l0_iters_ [ i ] ) ;
}
}
@ -280,7 +299,14 @@ void ForwardIterator::SeekInternal(const Slice& internal_key,
level_iters_ [ level - 1 ] - > SetFileIndex ( f_idx ) ;
seek_to_first ? level_iters_ [ level - 1 ] - > SeekToFirst ( ) :
level_iters_ [ level - 1 ] - > Seek ( internal_key ) ;
if ( level_iters_ [ level - 1 ] - > Valid ( ) ) {
if ( level_iters_ [ level - 1 ] - > status ( ) . IsIncomplete ( ) ) {
// see above
assert ( read_options_ . read_tier = = kBlockCacheTier ) ;
status_ = level_iters_ [ level - 1 ] - > status ( ) ;
valid_ = false ;
return ;
} else if ( level_iters_ [ level - 1 ] - > Valid ( ) ) {
immutable_min_heap_ . push ( level_iters_ [ level - 1 ] ) ;
}
}
@ -320,9 +346,17 @@ void ForwardIterator::Next() {
}
current_ - > Next ( ) ;
if ( current_ - > Valid ( ) & & current_ ! = mutable_iter_ ) {
if ( current_ ! = mutable_iter_ ) {
if ( current_ - > status ( ) . IsIncomplete ( ) ) {
assert ( read_options_ . read_tier = = kBlockCacheTier ) ;
status_ = current_ - > status ( ) ;
valid_ = false ;
return ;
} else if ( current_ - > Valid ( ) ) {
immutable_min_heap_ . push ( current_ ) ;
}
}
UpdateCurrent ( ) ;
}
@ -389,6 +423,29 @@ void ForwardIterator::RebuildIterators() {
is_prev_set_ = false ;
}
void ForwardIterator : : ResetIncompleteIterators ( ) {
const auto & l0_files = sv_ - > current - > files_ [ 0 ] ;
for ( uint32_t i = 0 ; i < l0_iters_ . size ( ) ; + + i ) {
assert ( i < l0_files . size ( ) ) ;
if ( ! l0_iters_ [ i ] - > status ( ) . IsIncomplete ( ) ) {
continue ;
}
delete l0_iters_ [ i ] ;
l0_iters_ [ i ] = cfd_ - > table_cache ( ) - > NewIterator (
read_options_ , * cfd_ - > soptions ( ) , cfd_ - > internal_comparator ( ) ,
l0_files [ i ] - > fd ) ;
}
for ( auto * level_iter : level_iters_ ) {
if ( level_iter & & level_iter - > status ( ) . IsIncomplete ( ) ) {
level_iter - > Reset ( ) ;
}
}
current_ = nullptr ;
is_prev_set_ = false ;
}
void ForwardIterator : : UpdateCurrent ( ) {
if ( immutable_min_heap_ . empty ( ) & & ! mutable_iter_ - > Valid ( ) ) {
current_ = nullptr ;
@ -417,7 +474,7 @@ void ForwardIterator::UpdateCurrent() {
}
bool ForwardIterator : : NeedToSeekImmutable ( const Slice & target ) {
if ( ! is_prev_set_ ) {
if ( ! valid_ | | ! is_prev_set_ ) {
return true ;
}
Slice prev_key = prev_key_ . GetKey ( ) ;