@ -48,12 +48,13 @@ static void DumpInternalIter(Iterator* iter) {
DBIter : : DBIter ( Env * _env , const ReadOptions & read_options ,
DBIter : : DBIter ( Env * _env , const ReadOptions & read_options ,
const ImmutableCFOptions & cf_options ,
const ImmutableCFOptions & cf_options ,
const MutableCFOptions & mutable_cf_options , const Comparator * cmp ,
const MutableCFOptions & mutable_cf_options ,
InternalIterator * iter , SequenceNumber s , bool arena_mode ,
const Comparator * cmp , InternalIterator * iter , SequenceNumber s ,
uint64_t max_sequential_skip_in_iterations ,
bool arena_mode , uint64_t max_sequential_skip_in_iterations ,
ReadCallback * read_callback , DBImpl * db_impl , ColumnFamilyData * cfd ,
ReadCallback * read_callback , DBImpl * db_impl ,
bool allow_blob )
ColumnFamilyData * cfd , bool allow_blob )
: env_ ( _env ) ,
: prefix_extractor_ ( mutable_cf_options . prefix_extractor . get ( ) ) ,
env_ ( _env ) ,
logger_ ( cf_options . info_log ) ,
logger_ ( cf_options . info_log ) ,
user_comparator_ ( cmp ) ,
user_comparator_ ( cmp ) ,
merge_operator_ ( cf_options . merge_operator ) ,
merge_operator_ ( cf_options . merge_operator ) ,
@ -68,7 +69,9 @@ DBIter::DBIter(Env* _env, const ReadOptions& read_options,
valid_ ( false ) ,
valid_ ( false ) ,
current_entry_is_merged_ ( false ) ,
current_entry_is_merged_ ( false ) ,
is_key_seqnum_zero_ ( false ) ,
is_key_seqnum_zero_ ( false ) ,
prefix_same_as_start_ ( read_options . prefix_same_as_start ) ,
prefix_same_as_start_ ( mutable_cf_options . prefix_extractor
? read_options . prefix_same_as_start
: false ) ,
pin_thru_lifetime_ ( read_options . pin_data ) ,
pin_thru_lifetime_ ( read_options . pin_data ) ,
total_order_seek_ ( read_options . total_order_seek ) ,
total_order_seek_ ( read_options . total_order_seek ) ,
allow_blob_ ( allow_blob ) ,
allow_blob_ ( allow_blob ) ,
@ -79,7 +82,6 @@ DBIter::DBIter(Env* _env, const ReadOptions& read_options,
cfd_ ( cfd ) ,
cfd_ ( cfd ) ,
start_seqnum_ ( read_options . iter_start_seqnum ) {
start_seqnum_ ( read_options . iter_start_seqnum ) {
RecordTick ( statistics_ , NO_ITERATOR_CREATED ) ;
RecordTick ( statistics_ , NO_ITERATOR_CREATED ) ;
prefix_extractor_ = mutable_cf_options . prefix_extractor . get ( ) ;
max_skip_ = max_sequential_skip_in_iterations ;
max_skip_ = max_sequential_skip_in_iterations ;
max_skippable_internal_keys_ = read_options . max_skippable_internal_keys ;
max_skippable_internal_keys_ = read_options . max_skippable_internal_keys ;
if ( pin_thru_lifetime_ ) {
if ( pin_thru_lifetime_ ) {
@ -152,8 +154,13 @@ void DBIter::Next() {
local_stats_ . next_count_ + + ;
local_stats_ . next_count_ + + ;
if ( ok & & iter_ . Valid ( ) ) {
if ( ok & & iter_ . Valid ( ) ) {
Slice prefix ;
if ( prefix_same_as_start_ ) {
assert ( prefix_extractor_ ! = nullptr ) ;
prefix = prefix_ . GetUserKey ( ) ;
}
FindNextUserEntry ( true /* skipping the current user key */ ,
FindNextUserEntry ( true /* skipping the current user key */ ,
prefix_same_as_start_ ) ;
prefix_same_as_start_ ? & prefix : nullptr ) ;
} else {
} else {
is_key_seqnum_zero_ = false ;
is_key_seqnum_zero_ = false ;
valid_ = false ;
valid_ = false ;
@ -164,7 +171,7 @@ void DBIter::Next() {
}
}
}
}
// PRE: saved_key_ has the current user key if skipping
// PRE: saved_key_ has the current user key if skipping_saved_key
// POST: saved_key_ should have the next user key if valid_,
// POST: saved_key_ should have the next user key if valid_,
// if the current entry is a result of merge
// if the current entry is a result of merge
// current_entry_is_merged_ => true
// current_entry_is_merged_ => true
@ -174,17 +181,17 @@ void DBIter::Next() {
// a delete marker or a sequence number higher than sequence_
// a delete marker or a sequence number higher than sequence_
// saved_key_ MUST have a proper user_key before calling this function
// saved_key_ MUST have a proper user_key before calling this function
//
//
// The prefix_check parameter controls whether we check the iterated
// The prefix parameter, if not null, indicates that we need to iterator
// keys against the prefix of the seeked key. Set to false when
// within the prefix, and the iterator needs to be made invalid, if no
// performing a seek without a key (e.g. SeekToFirst). Set to
// more entry for the prefix can be found.
// prefix_same_as_start_ for other iterations.
bool DBIter : : FindNextUserEntry ( bool skipping_saved_key , const Slice * prefix ) {
bool DBIter : : FindNextUserEntry ( bool skipping , bool prefix_check ) {
PERF_TIMER_GUARD ( find_next_user_entry_time ) ;
PERF_TIMER_GUARD ( find_next_user_entry_time ) ;
return FindNextUserEntryInternal ( skipping , prefix_check ) ;
return FindNextUserEntryInternal ( skipping_saved_key , prefix ) ;
}
}
// Actual implementation of DBIter::FindNextUserEntry()
// Actual implementation of DBIter::FindNextUserEntry()
bool DBIter : : FindNextUserEntryInternal ( bool skipping , bool prefix_check ) {
bool DBIter : : FindNextUserEntryInternal ( bool skipping_saved_key ,
const Slice * prefix ) {
// Loop until we hit an acceptable entry to yield
// Loop until we hit an acceptable entry to yield
assert ( iter_ . Valid ( ) ) ;
assert ( iter_ . Valid ( ) ) ;
assert ( status_ . ok ( ) ) ;
assert ( status_ . ok ( ) ) ;
@ -193,9 +200,10 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
// How many times in a row we have skipped an entry with user key less than
// How many times in a row we have skipped an entry with user key less than
// or equal to saved_key_. We could skip these entries either because
// or equal to saved_key_. We could skip these entries either because
// sequence numbers were too high or because skipping = true.
// sequence numbers were too high or because skipping_saved_key = true.
// What saved_key_ contains throughout this method:
// What saved_key_ contains throughout this method:
// - if skipping : saved_key_ contains the key that we need to skip,
// - if skipping_saved_key : saved_key_ contains the key that we need
// to skip,
// and we haven't seen any keys greater than that,
// and we haven't seen any keys greater than that,
// - if num_skipped > 0 : saved_key_ contains the key that we have skipped
// - if num_skipped > 0 : saved_key_ contains the key that we have skipped
// num_skipped times, and we haven't seen any keys
// num_skipped times, and we haven't seen any keys
@ -228,9 +236,10 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
break ;
break ;
}
}
if ( prefix_extractor_ & & prefix_check & &
assert ( prefix = = nullptr | | prefix_extractor_ ! = nullptr ) ;
prefix_extractor_ - > Transform ( ikey_ . user_key )
if ( prefix ! = nullptr & &
. compare ( prefix_start_key_ ) ! = 0 ) {
prefix_extractor_ - > Transform ( ikey_ . user_key ) . compare ( * prefix ) ! = 0 ) {
assert ( prefix_same_as_start_ ) ;
break ;
break ;
}
}
@ -243,14 +252,15 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
// possibly be skipped. This condition can potentially be relaxed to
// possibly be skipped. This condition can potentially be relaxed to
// prev_key.seq <= ikey_.sequence. We are cautious because it will be more
// prev_key.seq <= ikey_.sequence. We are cautious because it will be more
// prone to bugs causing the same user key with the same sequence number.
// prone to bugs causing the same user key with the same sequence number.
if ( ! is_prev_key_seqnum_zero & & skipping & &
if ( ! is_prev_key_seqnum_zero & & skipping_saved_key & &
user_comparator_ . Compare ( ikey_ . user_key , saved_key_ . GetUserKey ( ) ) < =
user_comparator_ . Compare ( ikey_ . user_key , saved_key_ . GetUserKey ( ) ) < =
0 ) {
0 ) {
num_skipped + + ; // skip this entry
num_skipped + + ; // skip this entry
PERF_COUNTER_ADD ( internal_key_skipped_count , 1 ) ;
PERF_COUNTER_ADD ( internal_key_skipped_count , 1 ) ;
} else {
} else {
assert ( ! skipping | | user_comparator_ . Compare (
assert ( ! skipping_saved_key | |
ikey_ . user_key , saved_key_ . GetUserKey ( ) ) > 0 ) ;
user_comparator_ . Compare ( ikey_ . user_key ,
saved_key_ . GetUserKey ( ) ) > 0 ) ;
num_skipped = 0 ;
num_skipped = 0 ;
reseek_done = false ;
reseek_done = false ;
switch ( ikey_ . type ) {
switch ( ikey_ . type ) {
@ -271,7 +281,7 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
saved_key_ . SetUserKey (
saved_key_ . SetUserKey (
ikey_ . user_key , ! pin_thru_lifetime_ | |
ikey_ . user_key , ! pin_thru_lifetime_ | |
! iter_ . iter ( ) - > IsKeyPinned ( ) /* copy */ ) ;
! iter_ . iter ( ) - > IsKeyPinned ( ) /* copy */ ) ;
skipping = true ;
skipping_saved_key = true ;
PERF_COUNTER_ADD ( internal_delete_skipped_count , 1 ) ;
PERF_COUNTER_ADD ( internal_delete_skipped_count , 1 ) ;
}
}
break ;
break ;
@ -289,12 +299,12 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
return true ;
return true ;
} else {
} else {
// this key and all previous versions shouldn't be included,
// this key and all previous versions shouldn't be included,
// skipping
// skipping_saved_key
saved_key_ . SetUserKey (
saved_key_ . SetUserKey (
ikey_ . user_key ,
ikey_ . user_key ,
! pin_thru_lifetime_ | |
! pin_thru_lifetime_ | |
! iter_ . iter ( ) - > IsKeyPinned ( ) /* copy */ ) ;
! iter_ . iter ( ) - > IsKeyPinned ( ) /* copy */ ) ;
skipping = true ;
skipping_saved_key = true ;
}
}
} else {
} else {
saved_key_ . SetUserKey (
saved_key_ . SetUserKey (
@ -304,7 +314,7 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
ikey_ , RangeDelPositioningMode : : kForwardTraversal ) ) {
ikey_ , RangeDelPositioningMode : : kForwardTraversal ) ) {
// Arrange to skip all upcoming entries for this key since
// Arrange to skip all upcoming entries for this key since
// they are hidden by this deletion.
// they are hidden by this deletion.
skipping = true ;
skipping_saved_key = true ;
num_skipped = 0 ;
num_skipped = 0 ;
reseek_done = false ;
reseek_done = false ;
PERF_COUNTER_ADD ( internal_delete_skipped_count , 1 ) ;
PERF_COUNTER_ADD ( internal_delete_skipped_count , 1 ) ;
@ -335,7 +345,7 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
ikey_ , RangeDelPositioningMode : : kForwardTraversal ) ) {
ikey_ , RangeDelPositioningMode : : kForwardTraversal ) ) {
// Arrange to skip all upcoming entries for this key since
// Arrange to skip all upcoming entries for this key since
// they are hidden by this deletion.
// they are hidden by this deletion.
skipping = true ;
skipping_saved_key = true ;
num_skipped = 0 ;
num_skipped = 0 ;
reseek_done = false ;
reseek_done = false ;
PERF_COUNTER_ADD ( internal_delete_skipped_count , 1 ) ;
PERF_COUNTER_ADD ( internal_delete_skipped_count , 1 ) ;
@ -360,13 +370,13 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
// to seek to the target sequence number.
// to seek to the target sequence number.
int cmp =
int cmp =
user_comparator_ . Compare ( ikey_ . user_key , saved_key_ . GetUserKey ( ) ) ;
user_comparator_ . Compare ( ikey_ . user_key , saved_key_ . GetUserKey ( ) ) ;
if ( cmp = = 0 | | ( skipping & & cmp < = 0 ) ) {
if ( cmp = = 0 | | ( skipping_saved_key & & cmp < = 0 ) ) {
num_skipped + + ;
num_skipped + + ;
} else {
} else {
saved_key_ . SetUserKey (
saved_key_ . SetUserKey (
ikey_ . user_key ,
ikey_ . user_key ,
! iter_ . iter ( ) - > IsKeyPinned ( ) | | ! pin_thru_lifetime_ /* copy */ ) ;
! iter_ . iter ( ) - > IsKeyPinned ( ) | | ! pin_thru_lifetime_ /* copy */ ) ;
skipping = false ;
skipping_saved_key = false ;
num_skipped = 0 ;
num_skipped = 0 ;
reseek_done = false ;
reseek_done = false ;
}
}
@ -386,14 +396,14 @@ bool DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
num_skipped = 0 ;
num_skipped = 0 ;
reseek_done = true ;
reseek_done = true ;
std : : string last_key ;
std : : string last_key ;
if ( skipping ) {
if ( skipping_saved_key ) {
// We're looking for the next user-key but all we see are the same
// We're looking for the next user-key but all we see are the same
// user-key with decreasing sequence numbers. Fast forward to
// user-key with decreasing sequence numbers. Fast forward to
// sequence number 0 and type deletion (the smallest type).
// sequence number 0 and type deletion (the smallest type).
AppendInternalKey ( & last_key , ParsedInternalKey ( saved_key_ . GetUserKey ( ) ,
AppendInternalKey ( & last_key , ParsedInternalKey ( saved_key_ . GetUserKey ( ) ,
0 , kTypeDeletion ) ) ;
0 , kTypeDeletion ) ) ;
// Don't set skipping = false because we may still see more user-keys
// Don't set skipping_saved_key = false because we may still see more
// equal to saved_key_.
// user-keys equal to saved_key_.
} else {
} else {
// We saw multiple entries with this user key and sequence numbers
// We saw multiple entries with this user key and sequence numbers
// higher than sequence_. Fast forward to sequence_.
// higher than sequence_. Fast forward to sequence_.
@ -534,8 +544,14 @@ void DBIter::Prev() {
}
}
}
}
if ( ok ) {
if ( ok ) {
PrevInternal ( ) ;
Slice prefix ;
if ( prefix_same_as_start_ ) {
assert ( prefix_extractor_ ! = nullptr ) ;
prefix = prefix_ . GetUserKey ( ) ;
}
}
PrevInternal ( prefix_same_as_start_ ? & prefix : nullptr ) ;
}
if ( statistics_ ! = nullptr ) {
if ( statistics_ ! = nullptr ) {
local_stats_ . prev_count_ + + ;
local_stats_ . prev_count_ + + ;
if ( valid_ ) {
if ( valid_ ) {
@ -613,15 +629,17 @@ bool DBIter::ReverseToBackward() {
return FindUserKeyBeforeSavedKey ( ) ;
return FindUserKeyBeforeSavedKey ( ) ;
}
}
void DBIter : : PrevInternal ( ) {
void DBIter : : PrevInternal ( const Slice * prefix ) {
while ( iter_ . Valid ( ) ) {
while ( iter_ . Valid ( ) ) {
saved_key_ . SetUserKey (
saved_key_ . SetUserKey (
ExtractUserKey ( iter_ . key ( ) ) ,
ExtractUserKey ( iter_ . key ( ) ) ,
! iter_ . iter ( ) - > IsKeyPinned ( ) | | ! pin_thru_lifetime_ /* copy */ ) ;
! iter_ . iter ( ) - > IsKeyPinned ( ) | | ! pin_thru_lifetime_ /* copy */ ) ;
if ( prefix_extractor_ & & prefix_same_as_start_ & &
assert ( prefix = = nullptr | | prefix_extractor_ ! = nullptr ) ;
if ( prefix ! = nullptr & &
prefix_extractor_ - > Transform ( saved_key_ . GetUserKey ( ) )
prefix_extractor_ - > Transform ( saved_key_ . GetUserKey ( ) )
. compare ( prefix_start_key_ ) ! = 0 ) {
. compare ( * prefix ) ! = 0 ) {
assert ( prefix_same_as_start_ ) ;
// Current key does not have the same prefix as start
// Current key does not have the same prefix as start
valid_ = false ;
valid_ = false ;
return ;
return ;
@ -1047,120 +1065,152 @@ bool DBIter::IsVisible(SequenceNumber sequence) {
}
}
}
}
void DBIter : : Seek ( const Slice & target ) {
void DBIter : : SetSavedKeyToSeekTarget ( const Slice & target ) {
PERF_CPU_TIMER_GUARD ( iter_seek_cpu_nanos , env_ ) ;
StopWatch sw ( env_ , statistics_ , DB_SEEK ) ;
status_ = Status : : OK ( ) ;
ReleaseTempPinnedData ( ) ;
ResetInternalKeysSkippedCounter ( ) ;
is_key_seqnum_zero_ = false ;
is_key_seqnum_zero_ = false ;
SequenceNumber seq = sequence_ ;
SequenceNumber seq = sequence_ ;
saved_key_ . Clear ( ) ;
saved_key_ . Clear ( ) ;
saved_key_ . SetInternalKey ( target , seq ) ;
saved_key_ . SetInternalKey ( target , seq ) ;
# ifndef ROCKSDB_LITE
if ( db_impl_ ! = nullptr & & cfd_ ! = nullptr ) {
db_impl_ - > TraceIteratorSeek ( cfd_ - > GetID ( ) , target ) ;
}
# endif // ROCKSDB_LITE
if ( iterate_lower_bound_ ! = nullptr & &
if ( iterate_lower_bound_ ! = nullptr & &
user_comparator_ . Compare ( saved_key_ . GetUserKey ( ) , * iterate_lower_bound_ ) <
user_comparator_ . Compare ( saved_key_ . GetUserKey ( ) , * iterate_lower_bound_ ) <
0 ) {
0 ) {
// Seek key is smaller than the lower bound.
saved_key_ . Clear ( ) ;
saved_key_ . Clear ( ) ;
saved_key_ . SetInternalKey ( * iterate_lower_bound_ , seq ) ;
saved_key_ . SetInternalKey ( * iterate_lower_bound_ , seq ) ;
}
}
}
void DBIter : : SetSavedKeyToSeekForPrevTarget ( const Slice & target ) {
is_key_seqnum_zero_ = false ;
saved_key_ . Clear ( ) ;
// now saved_key is used to store internal key.
saved_key_ . SetInternalKey ( target , 0 /* sequence_number */ ,
kValueTypeForSeekForPrev ) ;
if ( iterate_upper_bound_ ! = nullptr & &
user_comparator_ . Compare ( saved_key_ . GetUserKey ( ) ,
* iterate_upper_bound_ ) > = 0 ) {
saved_key_ . Clear ( ) ;
saved_key_ . SetInternalKey ( * iterate_upper_bound_ , kMaxSequenceNumber ) ;
}
}
void DBIter : : Seek ( const Slice & target ) {
PERF_CPU_TIMER_GUARD ( iter_seek_cpu_nanos , env_ ) ;
StopWatch sw ( env_ , statistics_ , DB_SEEK ) ;
# ifndef ROCKSDB_LITE
if ( db_impl_ ! = nullptr & & cfd_ ! = nullptr ) {
db_impl_ - > TraceIteratorSeek ( cfd_ - > GetID ( ) , target ) ;
}
# endif // ROCKSDB_LITE
status_ = Status : : OK ( ) ;
ReleaseTempPinnedData ( ) ;
ResetInternalKeysSkippedCounter ( ) ;
// Seek the inner iterator based on the target key.
{
{
PERF_TIMER_GUARD ( seek_internal_seek_time ) ;
PERF_TIMER_GUARD ( seek_internal_seek_time ) ;
SetSavedKeyToSeekTarget ( target ) ;
iter_ . Seek ( saved_key_ . GetInternalKey ( ) ) ;
iter_ . Seek ( saved_key_ . GetInternalKey ( ) ) ;
range_del_agg_ . InvalidateRangeDelMapPositions ( ) ;
range_del_agg_ . InvalidateRangeDelMapPositions ( ) ;
}
RecordTick ( statistics_ , NUMBER_DB_SEEK ) ;
RecordTick ( statistics_ , NUMBER_DB_SEEK ) ;
if ( iter_ . Valid ( ) ) {
}
if ( prefix_extractor_ & & prefix_same_as_start_ ) {
if ( ! iter_ . Valid ( ) ) {
prefix_start_key_ = prefix_extractor_ - > Transform ( target ) ;
valid_ = false ;
return ;
}
}
direction_ = kForward ;
direction_ = kForward ;
// Now the inner iterator is placed to the target position. From there,
// we need to find out the next key that is visible to the user.
//
ClearSavedValue ( ) ;
ClearSavedValue ( ) ;
FindNextUserEntry ( false /* not skipping */ , prefix_same_as_start_ ) ;
if ( prefix_same_as_start_ ) {
// The case where the iterator needs to be invalidated if it has exausted
// keys within the same prefix of the seek key.
assert ( prefix_extractor_ ! = nullptr ) ;
Slice target_prefix ;
target_prefix = prefix_extractor_ - > Transform ( target ) ;
FindNextUserEntry ( false /* not skipping saved_key */ ,
& target_prefix /* prefix */ ) ;
if ( valid_ ) {
// Remember the prefix of the seek key for the future Prev() call to
// check.
prefix_ . SetUserKey ( target_prefix ) ;
}
} else {
FindNextUserEntry ( false /* not skipping saved_key */ , nullptr ) ;
}
if ( ! valid_ ) {
if ( ! valid_ ) {
prefix_start_key_ . clear ( ) ;
return ;
}
}
// Updating stats and perf context counters.
if ( statistics_ ! = nullptr ) {
if ( statistics_ ! = nullptr ) {
if ( valid_ ) {
// Decrement since we don't want to count this key as skipped
// Decrement since we don't want to count this key as skipped
RecordTick ( statistics_ , NUMBER_DB_SEEK_FOUND ) ;
RecordTick ( statistics_ , NUMBER_DB_SEEK_FOUND ) ;
RecordTick ( statistics_ , ITER_BYTES_READ , key ( ) . size ( ) + value ( ) . size ( ) ) ;
RecordTick ( statistics_ , ITER_BYTES_READ , key ( ) . size ( ) + value ( ) . size ( ) ) ;
PERF_COUNTER_ADD ( iter_read_bytes , key ( ) . size ( ) + value ( ) . size ( ) ) ;
}
}
} else {
valid_ = false ;
}
if ( valid_ & & prefix_extractor_ & & prefix_same_as_start_ ) {
prefix_start_buf_ . SetUserKey ( prefix_start_key_ ) ;
prefix_start_key_ = prefix_start_buf_ . GetUserKey ( ) ;
}
}
PERF_COUNTER_ADD ( iter_read_bytes , key ( ) . size ( ) + value ( ) . size ( ) ) ;
}
}
void DBIter : : SeekForPrev ( const Slice & target ) {
void DBIter : : SeekForPrev ( const Slice & target ) {
PERF_CPU_TIMER_GUARD ( iter_seek_cpu_nanos , env_ ) ;
PERF_CPU_TIMER_GUARD ( iter_seek_cpu_nanos , env_ ) ;
StopWatch sw ( env_ , statistics_ , DB_SEEK ) ;
StopWatch sw ( env_ , statistics_ , DB_SEEK ) ;
# ifndef ROCKSDB_LITE
if ( db_impl_ ! = nullptr & & cfd_ ! = nullptr ) {
db_impl_ - > TraceIteratorSeekForPrev ( cfd_ - > GetID ( ) , target ) ;
}
# endif // ROCKSDB_LITE
status_ = Status : : OK ( ) ;
status_ = Status : : OK ( ) ;
ReleaseTempPinnedData ( ) ;
ReleaseTempPinnedData ( ) ;
ResetInternalKeysSkippedCounter ( ) ;
ResetInternalKeysSkippedCounter ( ) ;
is_key_seqnum_zero_ = false ;
saved_key_ . Clear ( ) ;
// now saved_key is used to store internal key.
saved_key_ . SetInternalKey ( target , 0 /* sequence_number */ ,
kValueTypeForSeekForPrev ) ;
if ( iterate_upper_bound_ ! = nullptr & &
user_comparator_ . Compare ( saved_key_ . GetUserKey ( ) ,
* iterate_upper_bound_ ) > = 0 ) {
saved_key_ . Clear ( ) ;
saved_key_ . SetInternalKey ( * iterate_upper_bound_ , kMaxSequenceNumber ) ;
}
// Seek the inner iterator based on the target key.
{
{
PERF_TIMER_GUARD ( seek_internal_seek_time ) ;
PERF_TIMER_GUARD ( seek_internal_seek_time ) ;
SetSavedKeyToSeekForPrevTarget ( target ) ;
iter_ . SeekForPrev ( saved_key_ . GetInternalKey ( ) ) ;
iter_ . SeekForPrev ( saved_key_ . GetInternalKey ( ) ) ;
range_del_agg_ . InvalidateRangeDelMapPositions ( ) ;
range_del_agg_ . InvalidateRangeDelMapPositions ( ) ;
}
# ifndef ROCKSDB_LITE
if ( db_impl_ ! = nullptr & & cfd_ ! = nullptr ) {
db_impl_ - > TraceIteratorSeekForPrev ( cfd_ - > GetID ( ) , target ) ;
}
# endif // ROCKSDB_LITE
RecordTick ( statistics_ , NUMBER_DB_SEEK ) ;
RecordTick ( statistics_ , NUMBER_DB_SEEK ) ;
if ( iter_ . Valid ( ) ) {
}
if ( prefix_extractor_ & & prefix_same_as_start_ ) {
if ( ! iter_ . Valid ( ) ) {
prefix_start_key_ = prefix_extractor_ - > Transform ( target ) ;
valid_ = false ;
return ;
}
}
direction_ = kReverse ;
direction_ = kReverse ;
// Now the inner iterator is placed to the target position. From there,
// we need to find out the first key that is visible to the user in the
// backward direction.
ClearSavedValue ( ) ;
ClearSavedValue ( ) ;
PrevInternal ( ) ;
if ( prefix_same_as_start_ ) {
if ( ! valid_ ) {
// The case where the iterator needs to be invalidated if it has exausted
prefix_start_key_ . clear ( ) ;
// keys within the same prefix of the seek key.
}
assert ( prefix_extractor_ ! = nullptr ) ;
if ( statistics_ ! = nullptr ) {
Slice target_prefix ;
target_prefix = prefix_extractor_ - > Transform ( target ) ;
PrevInternal ( & target_prefix ) ;
if ( valid_ ) {
if ( valid_ ) {
RecordTick ( statistics_ , NUMBER_DB_SEEK_FOUND ) ;
// Remember the prefix of the seek key for the future Prev() call to
RecordTick ( statistics_ , ITER_BYTES_READ , key ( ) . size ( ) + value ( ) . size ( ) ) ;
// check.
PERF_COUNTER_ADD ( iter_read_bytes , key ( ) . size ( ) + value ( ) . size ( ) ) ;
prefix_ . SetUserKey ( target_prefix ) ;
}
}
}
} else {
} else {
valid_ = false ;
PrevInternal ( nullptr ) ;
}
}
if ( valid_ & & prefix_extractor_ & & prefix_same_as_start_ ) {
prefix_start_buf_ . SetUserKey ( prefix_start_key_ ) ;
// Report stats and perf context.
prefix_start_key_ = prefix_start_buf_ . GetUserKey ( ) ;
if ( statistics_ ! = nullptr & & valid_ ) {
RecordTick ( statistics_ , NUMBER_DB_SEEK_FOUND ) ;
RecordTick ( statistics_ , ITER_BYTES_READ , key ( ) . size ( ) + value ( ) . size ( ) ) ;
PERF_COUNTER_ADD ( iter_read_bytes , key ( ) . size ( ) + value ( ) . size ( ) ) ;
}
}
}
}
@ -1193,7 +1243,8 @@ void DBIter::SeekToFirst() {
saved_key_ . SetUserKey (
saved_key_ . SetUserKey (
ExtractUserKey ( iter_ . key ( ) ) ,
ExtractUserKey ( iter_ . key ( ) ) ,
! iter_ . iter ( ) - > IsKeyPinned ( ) | | ! pin_thru_lifetime_ /* copy */ ) ;
! iter_ . iter ( ) - > IsKeyPinned ( ) | | ! pin_thru_lifetime_ /* copy */ ) ;
FindNextUserEntry ( false /* not skipping */ , false /* no prefix check */ ) ;
FindNextUserEntry ( false /* not skipping saved_key */ ,
nullptr /* no prefix check */ ) ;
if ( statistics_ ! = nullptr ) {
if ( statistics_ ! = nullptr ) {
if ( valid_ ) {
if ( valid_ ) {
RecordTick ( statistics_ , NUMBER_DB_SEEK_FOUND ) ;
RecordTick ( statistics_ , NUMBER_DB_SEEK_FOUND ) ;
@ -1204,10 +1255,9 @@ void DBIter::SeekToFirst() {
} else {
} else {
valid_ = false ;
valid_ = false ;
}
}
if ( valid_ & & prefix_extractor_ & & prefix_same_as_start_ ) {
if ( valid_ & & prefix_same_as_start_ ) {
prefix_start_buf_ . SetUserKey (
assert ( prefix_extractor_ ! = nullptr ) ;
prefix_extractor_ - > Transform ( saved_key_ . GetUserKey ( ) ) ) ;
prefix_ . SetUserKey ( prefix_extractor_ - > Transform ( saved_key_ . GetUserKey ( ) ) ) ;
prefix_start_key_ = prefix_start_buf_ . GetUserKey ( ) ;
}
}
}
}
@ -1217,7 +1267,7 @@ void DBIter::SeekToLast() {
SeekForPrev ( * iterate_upper_bound_ ) ;
SeekForPrev ( * iterate_upper_bound_ ) ;
if ( Valid ( ) & & user_comparator_ . Equal ( * iterate_upper_bound_ , key ( ) ) ) {
if ( Valid ( ) & & user_comparator_ . Equal ( * iterate_upper_bound_ , key ( ) ) ) {
ReleaseTempPinnedData ( ) ;
ReleaseTempPinnedData ( ) ;
PrevInternal ( ) ;
PrevInternal ( nullptr ) ;
}
}
return ;
return ;
}
}
@ -1240,7 +1290,7 @@ void DBIter::SeekToLast() {
iter_ . SeekToLast ( ) ;
iter_ . SeekToLast ( ) ;
range_del_agg_ . InvalidateRangeDelMapPositions ( ) ;
range_del_agg_ . InvalidateRangeDelMapPositions ( ) ;
}
}
PrevInternal ( ) ;
PrevInternal ( nullptr ) ;
if ( statistics_ ! = nullptr ) {
if ( statistics_ ! = nullptr ) {
RecordTick ( statistics_ , NUMBER_DB_SEEK ) ;
RecordTick ( statistics_ , NUMBER_DB_SEEK ) ;
if ( valid_ ) {
if ( valid_ ) {
@ -1249,10 +1299,9 @@ void DBIter::SeekToLast() {
PERF_COUNTER_ADD ( iter_read_bytes , key ( ) . size ( ) + value ( ) . size ( ) ) ;
PERF_COUNTER_ADD ( iter_read_bytes , key ( ) . size ( ) + value ( ) . size ( ) ) ;
}
}
}
}
if ( valid_ & & prefix_extractor_ & & prefix_same_as_start_ ) {
if ( valid_ & & prefix_same_as_start_ ) {
prefix_start_buf_ . SetUserKey (
assert ( prefix_extractor_ ! = nullptr ) ;
prefix_extractor_ - > Transform ( saved_key_ . GetUserKey ( ) ) ) ;
prefix_ . SetUserKey ( prefix_extractor_ - > Transform ( saved_key_ . GetUserKey ( ) ) ) ;
prefix_start_key_ = prefix_start_buf_ . GetUserKey ( ) ;
}
}
}
}