@ -6,11 +6,12 @@
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
// found in the LICENSE file. See the AUTHORS file for names of contributors.
# include "table/merger.h"
# include "table/merger.h"
# include <string>
# include <vector>
# include <vector>
# include "db/dbformat.h"
# include "db/pinned_iterators_manager.h"
# include "db/pinned_iterators_manager.h"
# include "rocksdb/comparator.h"
# include "rocksdb/comparator.h"
# include "rocksdb/iterator.h"
# include "rocksdb/iterator.h"
@ -20,6 +21,7 @@
# include "table/iterator_wrapper.h"
# include "table/iterator_wrapper.h"
# include "util/arena.h"
# include "util/arena.h"
# include "util/autovector.h"
# include "util/autovector.h"
# include "util/coding.h"
# include "util/heap.h"
# include "util/heap.h"
# include "util/perf_context_imp.h"
# include "util/perf_context_imp.h"
# include "util/stop_watch.h"
# include "util/stop_watch.h"
@ -37,12 +39,14 @@ const size_t kNumIterReserve = 4;
class MergingIterator : public InternalIterator {
class MergingIterator : public InternalIterator {
public :
public :
MergingIterator ( const Comparator * comparator , InternalIterator * * children ,
MergingIterator ( const Comparator * comparator , InternalIterator * * children ,
int n , bool is_arena_mode )
int n , bool is_arena_mode ,
const SliceTransform * const prefix_extractor )
: is_arena_mode_ ( is_arena_mode ) ,
: is_arena_mode_ ( is_arena_mode ) ,
comparator_ ( comparator ) ,
comparator_ ( comparator ) ,
current_ ( nullptr ) ,
current_ ( nullptr ) ,
direction_ ( kForward ) ,
direction_ ( kForward ) ,
minHeap_ ( comparator_ ) ,
minHeap_ ( comparator_ ) ,
prefix_extractor_ ( prefix_extractor ) ,
pinned_iters_mgr_ ( nullptr ) {
pinned_iters_mgr_ ( nullptr ) {
children_ . resize ( n ) ;
children_ . resize ( n ) ;
for ( int i = 0 ; i < n ; i + + ) {
for ( int i = 0 ; i < n ; i + + ) {
@ -109,8 +113,8 @@ class MergingIterator : public InternalIterator {
PERF_TIMER_GUARD ( seek_child_seek_time ) ;
PERF_TIMER_GUARD ( seek_child_seek_time ) ;
child . Seek ( target ) ;
child . Seek ( target ) ;
}
}
PERF_COUNTER_ADD ( seek_child_seek_count , 1 ) ;
PERF_COUNTER_ADD ( seek_child_seek_count , 1 ) ;
if ( child . Valid ( ) ) {
if ( child . Valid ( ) ) {
PERF_TIMER_GUARD ( seek_min_heap_time ) ;
PERF_TIMER_GUARD ( seek_min_heap_time ) ;
minHeap_ . push ( & child ) ;
minHeap_ . push ( & child ) ;
@ -125,7 +129,6 @@ class MergingIterator : public InternalIterator {
virtual void Next ( ) override {
virtual void Next ( ) override {
assert ( Valid ( ) ) ;
assert ( Valid ( ) ) ;
// Ensure that all children are positioned after key().
// Ensure that all children are positioned after key().
// If we are moving in the forward direction, it is already
// If we are moving in the forward direction, it is already
// true for all of the non-current children since current_ is
// true for all of the non-current children since current_ is
@ -136,15 +139,32 @@ class MergingIterator : public InternalIterator {
ClearHeaps ( ) ;
ClearHeaps ( ) ;
for ( auto & child : children_ ) {
for ( auto & child : children_ ) {
if ( & child ! = current_ ) {
if ( & child ! = current_ ) {
if ( prefix_extractor_ = = nullptr ) {
child . Seek ( key ( ) ) ;
child . Seek ( key ( ) ) ;
} else {
// only for prefix_seek_mode
// we should not call Seek() here
if ( child . Valid ( ) ) {
child . Next ( ) ;
} else {
child . SeekToFirst ( ) ;
}
}
if ( child . Valid ( ) & & comparator_ - > Equal ( key ( ) , child . key ( ) ) ) {
if ( child . Valid ( ) & & comparator_ - > Equal ( key ( ) , child . key ( ) ) ) {
child . Next ( ) ;
child . Next ( ) ;
}
}
}
}
if ( child . Valid ( ) ) {
if ( child . Valid ( ) ) {
bool skip_iter =
prefix_extractor_ ! = nullptr & &
prefix_extractor_ - > InDomain ( ExtractUserKey ( child . key ( ) ) ) & &
prefix_extractor_ - > Transform ( ExtractUserKey ( child . key ( ) ) ) ! =
Slice ( * prefix_ ) ;
if ( & child = = current_ | | ! skip_iter ) {
minHeap_ . push ( & child ) ;
minHeap_ . push ( & child ) ;
}
}
}
}
}
direction_ = kForward ;
direction_ = kForward ;
// The loop advanced all non-current children to be > key() so current_
// The loop advanced all non-current children to be > key() so current_
// should still be strictly the smallest key.
// should still be strictly the smallest key.
@ -182,7 +202,12 @@ class MergingIterator : public InternalIterator {
InitMaxHeap ( ) ;
InitMaxHeap ( ) ;
for ( auto & child : children_ ) {
for ( auto & child : children_ ) {
if ( & child ! = current_ ) {
if ( & child ! = current_ ) {
if ( prefix_extractor_ = = nullptr ) {
child . Seek ( key ( ) ) ;
child . Seek ( key ( ) ) ;
} else {
// only for prefix_seek_mode
// we should not call Seek() here
}
if ( child . Valid ( ) ) {
if ( child . Valid ( ) ) {
// Child is at first entry >= key(). Step back one to be < key()
// Child is at first entry >= key(). Step back one to be < key()
TEST_SYNC_POINT_CALLBACK ( " MergeIterator::Prev:BeforePrev " , & child ) ;
TEST_SYNC_POINT_CALLBACK ( " MergeIterator::Prev:BeforePrev " , & child ) ;
@ -193,10 +218,18 @@ class MergingIterator : public InternalIterator {
child . SeekToLast ( ) ;
child . SeekToLast ( ) ;
}
}
}
}
if ( child . Valid ( ) ) {
if ( child . Valid ( ) ) {
bool skip_iter =
prefix_extractor_ ! = nullptr & &
prefix_extractor_ - > InDomain ( ExtractUserKey ( child . key ( ) ) ) & &
prefix_extractor_ - > Transform ( ExtractUserKey ( child . key ( ) ) ) ! =
Slice ( * prefix_ ) ;
if ( & child = = current_ | | ! skip_iter ) {
maxHeap_ - > push ( & child ) ;
maxHeap_ - > push ( & child ) ;
}
}
}
}
}
direction_ = kReverse ;
direction_ = kReverse ;
// Note that we don't do assert(current_ == CurrentReverse()) here
// Note that we don't do assert(current_ == CurrentReverse()) here
// because it is possible to have some keys larger than the seek-key
// because it is possible to have some keys larger than the seek-key
@ -263,6 +296,17 @@ class MergingIterator : public InternalIterator {
current_ - > IsValuePinned ( ) ;
current_ - > IsValuePinned ( ) ;
}
}
virtual void ResetPrefix ( const Slice * prefix ) override {
if ( prefix = = nullptr ) {
prefix_ . reset ( ) ;
return ;
}
if ( ! prefix_ ) {
prefix_ . reset ( new std : : string ) ;
}
* prefix_ = prefix - > ToString ( ) ;
}
private :
private :
// Clears heaps for both directions, used when changing direction or seeking
// Clears heaps for both directions, used when changing direction or seeking
void ClearHeaps ( ) ;
void ClearHeaps ( ) ;
@ -288,7 +332,9 @@ class MergingIterator : public InternalIterator {
// Max heap is used for reverse iteration, which is way less common than
// Max heap is used for reverse iteration, which is way less common than
// forward. Lazily initialize it to save memory.
// forward. Lazily initialize it to save memory.
std : : unique_ptr < MergerMaxIterHeap > maxHeap_ ;
std : : unique_ptr < MergerMaxIterHeap > maxHeap_ ;
const SliceTransform * const prefix_extractor_ ;
PinnedIteratorsManager * pinned_iters_mgr_ ;
PinnedIteratorsManager * pinned_iters_mgr_ ;
std : : unique_ptr < std : : string > prefix_ ;
IteratorWrapper * CurrentForward ( ) const {
IteratorWrapper * CurrentForward ( ) const {
assert ( direction_ = = kForward ) ;
assert ( direction_ = = kForward ) ;
@ -315,9 +361,9 @@ void MergingIterator::InitMaxHeap() {
}
}
}
}
InternalIterator * NewMergingIterator ( const Comparator * cmp ,
InternalIterator * NewMergingIterator (
InternalIterator * * list , int n ,
const Comparator * cmp , InternalIterator * * list , int n , Arena * arena ,
Arena * arena ) {
const SliceTransform * const prefix_extractor ) {
assert ( n > = 0 ) ;
assert ( n > = 0 ) ;
if ( n = = 0 ) {
if ( n = = 0 ) {
return NewEmptyInternalIterator ( arena ) ;
return NewEmptyInternalIterator ( arena ) ;
@ -325,20 +371,21 @@ InternalIterator* NewMergingIterator(const Comparator* cmp,
return list [ 0 ] ;
return list [ 0 ] ;
} else {
} else {
if ( arena = = nullptr ) {
if ( arena = = nullptr ) {
return new MergingIterator ( cmp , list , n , false ) ;
return new MergingIterator ( cmp , list , n , false , prefix_extractor ) ;
} else {
} else {
auto mem = arena - > AllocateAligned ( sizeof ( MergingIterator ) ) ;
auto mem = arena - > AllocateAligned ( sizeof ( MergingIterator ) ) ;
return new ( mem ) MergingIterator ( cmp , list , n , true ) ;
return new ( mem ) MergingIterator ( cmp , list , n , true , prefix_extractor ) ;
}
}
}
}
}
}
MergeIteratorBuilder : : MergeIteratorBuilder ( const Comparator * comparator ,
MergeIteratorBuilder : : MergeIteratorBuilder (
Arena * a )
const Comparator * comparator , Arena * a ,
const SliceTransform * const prefix_extractor )
: first_iter ( nullptr ) , use_merging_iter ( false ) , arena ( a ) {
: first_iter ( nullptr ) , use_merging_iter ( false ) , arena ( a ) {
auto mem = arena - > AllocateAligned ( sizeof ( MergingIterator ) ) ;
auto mem = arena - > AllocateAligned ( sizeof ( MergingIterator ) ) ;
merge_iter = new ( mem ) MergingIterator ( comparator , nullptr , 0 , true ) ;
merge_iter =
new ( mem ) MergingIterator ( comparator , nullptr , 0 , true , prefix_extractor ) ;
}
}
void MergeIteratorBuilder : : AddIterator ( InternalIterator * iter ) {
void MergeIteratorBuilder : : AddIterator ( InternalIterator * iter ) {