@ -264,6 +264,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
bg_cv_ ( & mutex_ ) ,
bg_cv_ ( & mutex_ ) ,
mem_rep_factory_ ( options_ . memtable_factory . get ( ) ) ,
mem_rep_factory_ ( options_ . memtable_factory . get ( ) ) ,
mem_ ( new MemTable ( internal_comparator_ , options_ ) ) ,
mem_ ( new MemTable ( internal_comparator_ , options_ ) ) ,
imm_ ( options_ . min_write_buffer_number_to_merge ) ,
logfile_number_ ( 0 ) ,
logfile_number_ ( 0 ) ,
super_version_ ( nullptr ) ,
super_version_ ( nullptr ) ,
super_version_number_ ( 0 ) ,
super_version_number_ ( 0 ) ,
@ -360,7 +361,7 @@ DBImpl::~DBImpl() {
delete mem_ - > Unref ( ) ;
delete mem_ - > Unref ( ) ;
}
}
imm_ . UnrefAll ( & to_delete ) ;
imm_ . current ( ) - > Unref ( & to_delete ) ;
for ( MemTable * m : to_delete ) {
for ( MemTable * m : to_delete ) {
delete m ;
delete m ;
}
}
@ -508,7 +509,7 @@ bool DBImpl::SuperVersion::Unref() {
void DBImpl : : SuperVersion : : Cleanup ( ) {
void DBImpl : : SuperVersion : : Cleanup ( ) {
assert ( refs . load ( std : : memory_order_relaxed ) = = 0 ) ;
assert ( refs . load ( std : : memory_order_relaxed ) = = 0 ) ;
imm . UnrefAll ( & to_delete ) ;
imm - > Unref ( & to_delete ) ;
MemTable * m = mem - > Unref ( ) ;
MemTable * m = mem - > Unref ( ) ;
if ( m ! = nullptr ) {
if ( m ! = nullptr ) {
to_delete . push_back ( m ) ;
to_delete . push_back ( m ) ;
@ -516,13 +517,13 @@ void DBImpl::SuperVersion::Cleanup() {
current - > Unref ( ) ;
current - > Unref ( ) ;
}
}
void DBImpl : : SuperVersion : : Init ( MemTable * new_mem , const MemTableList & new_imm ,
void DBImpl : : SuperVersion : : Init ( MemTable * new_mem , MemTableListVersion * new_imm ,
Version * new_current ) {
Version * new_current ) {
mem = new_mem ;
mem = new_mem ;
imm = new_imm ;
imm = new_imm ;
current = new_current ;
current = new_current ;
mem - > Ref ( ) ;
mem - > Ref ( ) ;
imm . RefAll ( ) ;
imm - > Ref ( ) ;
current - > Ref ( ) ;
current - > Ref ( ) ;
refs . store ( 1 , std : : memory_order_relaxed ) ;
refs . store ( 1 , std : : memory_order_relaxed ) ;
}
}
@ -1221,7 +1222,7 @@ Status DBImpl::FlushMemTableToOutputFile(bool* madeProgress,
mutex_ . AssertHeld ( ) ;
mutex_ . AssertHeld ( ) ;
assert ( imm_ . size ( ) ! = 0 ) ;
assert ( imm_ . size ( ) ! = 0 ) ;
if ( ! imm_ . IsFlushPending ( options_ . min_write_buffer_number_to_merge ) ) {
if ( ! imm_ . IsFlushPending ( ) ) {
Log ( options_ . info_log , " FlushMemTableToOutputFile already in progress " ) ;
Log ( options_ . info_log , " FlushMemTableToOutputFile already in progress " ) ;
Status s = Status : : IOError ( " FlushMemTableToOutputFile already in progress " ) ;
Status s = Status : : IOError ( " FlushMemTableToOutputFile already in progress " ) ;
return s ;
return s ;
@ -1762,8 +1763,7 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
} else if ( shutting_down_ . Acquire_Load ( ) ) {
} else if ( shutting_down_ . Acquire_Load ( ) ) {
// DB is being deleted; no more background compactions
// DB is being deleted; no more background compactions
} else {
} else {
bool is_flush_pending =
bool is_flush_pending = imm_ . IsFlushPending ( ) ;
imm_ . IsFlushPending ( options_ . min_write_buffer_number_to_merge ) ;
if ( is_flush_pending & &
if ( is_flush_pending & &
( bg_flush_scheduled_ < options_ . max_background_flushes ) ) {
( bg_flush_scheduled_ < options_ . max_background_flushes ) ) {
// memtable flush needed
// memtable flush needed
@ -1798,8 +1798,7 @@ void DBImpl::BGWorkCompaction(void* db) {
Status DBImpl : : BackgroundFlush ( bool * madeProgress ,
Status DBImpl : : BackgroundFlush ( bool * madeProgress ,
DeletionState & deletion_state ) {
DeletionState & deletion_state ) {
Status stat ;
Status stat ;
while ( stat . ok ( ) & &
while ( stat . ok ( ) & & imm_ . IsFlushPending ( ) ) {
imm_ . IsFlushPending ( options_ . min_write_buffer_number_to_merge ) ) {
Log ( options_ . info_log ,
Log ( options_ . info_log ,
" BackgroundCallFlush doing FlushMemTableToOutputFile, flush slots available %d " ,
" BackgroundCallFlush doing FlushMemTableToOutputFile, flush slots available %d " ,
options_ . max_background_flushes - bg_flush_scheduled_ ) ;
options_ . max_background_flushes - bg_flush_scheduled_ ) ;
@ -1919,7 +1918,7 @@ Status DBImpl::BackgroundCompaction(bool* madeProgress,
mutex_ . AssertHeld ( ) ;
mutex_ . AssertHeld ( ) ;
// TODO: remove memtable flush from formal compaction
// TODO: remove memtable flush from formal compaction
while ( imm_ . IsFlushPending ( options_ . min_write_buffer_number_to_merge ) ) {
while ( imm_ . IsFlushPending ( ) ) {
Log ( options_ . info_log ,
Log ( options_ . info_log ,
" BackgroundCompaction doing FlushMemTableToOutputFile, compaction slots "
" BackgroundCompaction doing FlushMemTableToOutputFile, compaction slots "
" available %d " ,
" available %d " ,
@ -2325,7 +2324,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
const uint64_t imm_start = env_ - > NowMicros ( ) ;
const uint64_t imm_start = env_ - > NowMicros ( ) ;
LogFlush ( options_ . info_log ) ;
LogFlush ( options_ . info_log ) ;
mutex_ . Lock ( ) ;
mutex_ . Lock ( ) ;
if ( imm_ . IsFlushPending ( options_ . min_write_buffer_number_to_merge ) ) {
if ( imm_ . IsFlushPending ( ) ) {
FlushMemTableToOutputFile ( nullptr , deletion_state ) ;
FlushMemTableToOutputFile ( nullptr , deletion_state ) ;
bg_cv_ . SignalAll ( ) ; // Wakeup MakeRoomForWrite() if necessary
bg_cv_ . SignalAll ( ) ; // Wakeup MakeRoomForWrite() if necessary
}
}
@ -2658,8 +2657,9 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
namespace {
namespace {
struct IterState {
struct IterState {
port : : Mutex * mu ;
port : : Mutex * mu ;
Version * version ;
Version * version = nullptr ;
std : : vector < MemTable * > mem ; // includes both mem_ and imm_
MemTable * mem = nullptr ;
MemTableListVersion * imm = nullptr ;
DBImpl * db ;
DBImpl * db ;
} ;
} ;
@ -2668,15 +2668,16 @@ static void CleanupIteratorState(void* arg1, void* arg2) {
DBImpl : : DeletionState deletion_state ( state - > db - > GetOptions ( ) .
DBImpl : : DeletionState deletion_state ( state - > db - > GetOptions ( ) .
max_write_buffer_number ) ;
max_write_buffer_number ) ;
state - > mu - > Lock ( ) ;
state - > mu - > Lock ( ) ;
for ( unsigned int i = 0 ; i < state - > mem . size ( ) ; i + + ) {
MemTable * m = state - > mem - > Unref ( ) ;
MemTable * m = state - > mem [ i ] - > Unref ( ) ;
if ( m ! = nullptr ) {
if ( m ! = nullptr ) {
deletion_state . memtables_to_free . push_back ( m ) ;
deletion_state . memtables_to_free . push_back ( m ) ;
}
}
}
if ( state - > version ) { // not set for memtable-only iterator
if ( state - > version ) { // not set for memtable-only iterator
state - > version - > Unref ( ) ;
state - > version - > Unref ( ) ;
}
}
if ( state - > imm ) { // not set for memtable-only iterator
state - > imm - > Unref ( & deletion_state . memtables_to_free ) ;
}
// fast path FindObsoleteFiles
// fast path FindObsoleteFiles
state - > db - > FindObsoleteFiles ( deletion_state , false , true ) ;
state - > db - > FindObsoleteFiles ( deletion_state , false , true ) ;
state - > mu - > Unlock ( ) ;
state - > mu - > Unlock ( ) ;
@ -2690,7 +2691,7 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
SequenceNumber * latest_snapshot ) {
SequenceNumber * latest_snapshot ) {
IterState * cleanup = new IterState ;
IterState * cleanup = new IterState ;
MemTable * mutable_mem ;
MemTable * mutable_mem ;
std : : vector < MemTable * > immutable s;
MemTableListVersion * immutable_mem s;
Version * version ;
Version * version ;
// Collect together all needed child iterators for mem
// Collect together all needed child iterators for mem
@ -2699,27 +2700,22 @@ Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
mem_ - > Ref ( ) ;
mem_ - > Ref ( ) ;
mutable_mem = mem_ ;
mutable_mem = mem_ ;
// Collect together all needed child iterators for imm_
// Collect together all needed child iterators for imm_
imm_ . GetMemTables ( & immutables ) ;
immutable_mems = imm_ . current ( ) ;
for ( unsigned int i = 0 ; i < immutables . size ( ) ; i + + ) {
immutable_mems - > Ref ( ) ;
immutables [ i ] - > Ref ( ) ;
}
versions_ - > current ( ) - > Ref ( ) ;
versions_ - > current ( ) - > Ref ( ) ;
version = versions_ - > current ( ) ;
version = versions_ - > current ( ) ;
mutex_ . Unlock ( ) ;
mutex_ . Unlock ( ) ;
std : : vector < Iterator * > list ;
std : : vector < Iterator * > iterator_ list;
list . push_back ( mutable_mem - > NewIterator ( options ) ) ;
iterator_ list. push_back ( mutable_mem - > NewIterator ( options ) ) ;
cleanup - > mem . push_back ( mutable_mem ) ;
cleanup - > mem = mutable_mem ;
cleanup - > imm = immutable_mems ;
// Collect all needed child iterators for immutable memtables
// Collect all needed child iterators for immutable memtables
for ( MemTable * m : immutables ) {
immutable_mems - > AddIterators ( options , & iterator_list ) ;
list . push_back ( m - > NewIterator ( options ) ) ;
cleanup - > mem . push_back ( m ) ;
}
// Collect iterators for files in L0 - Ln
// Collect iterators for files in L0 - Ln
version - > AddIterators ( options , storage_options_ , & list ) ;
version - > AddIterators ( options , storage_options_ , & iterator_list ) ;
Iterator * internal_iter =
Iterator * internal_iter = NewMergingIterator (
NewMergingIterator ( & internal_comparator_ , & list [ 0 ] , list . size ( ) ) ;
& internal_comparator_ , & iterator_ list[ 0 ] , iterator_ list. size ( ) ) ;
cleanup - > version = version ;
cleanup - > version = version ;
cleanup - > mu = & mutex_ ;
cleanup - > mu = & mutex_ ;
cleanup - > db = this ;
cleanup - > db = this ;
@ -2738,19 +2734,15 @@ std::pair<Iterator*, Iterator*> DBImpl::GetTailingIteratorPair(
uint64_t * superversion_number ) {
uint64_t * superversion_number ) {
MemTable * mutable_mem ;
MemTable * mutable_mem ;
std : : vector < MemTable * > immutable s;
MemTableListVersion * immutable_mem s;
Version * version ;
Version * version ;
immutables . reserve ( options_ . max_write_buffer_number ) ;
// get all child iterators and bump their refcounts under lock
// get all child iterators and bump their refcounts under lock
mutex_ . Lock ( ) ;
mutex_ . Lock ( ) ;
mutable_mem = mem_ ;
mutable_mem = mem_ ;
mutable_mem - > Ref ( ) ;
mutable_mem - > Ref ( ) ;
imm_ . GetMemTables ( & immutables ) ;
immutable_mems = imm_ . current ( ) ;
for ( size_t i = 0 ; i < immutables . size ( ) ; + + i ) {
immutable_mems - > Ref ( ) ;
immutables [ i ] - > Ref ( ) ;
}
version = versions_ - > current ( ) ;
version = versions_ - > current ( ) ;
version - > Ref ( ) ;
version - > Ref ( ) ;
if ( superversion_number ! = nullptr ) {
if ( superversion_number ! = nullptr ) {
@ -2760,7 +2752,7 @@ std::pair<Iterator*, Iterator*> DBImpl::GetTailingIteratorPair(
Iterator * mutable_iter = mutable_mem - > NewIterator ( options ) ;
Iterator * mutable_iter = mutable_mem - > NewIterator ( options ) ;
IterState * mutable_cleanup = new IterState ( ) ;
IterState * mutable_cleanup = new IterState ( ) ;
mutable_cleanup - > mem . push_back ( mutable_mem ) ;
mutable_cleanup - > mem = mutable_mem ;
mutable_cleanup - > db = this ;
mutable_cleanup - > db = this ;
mutable_cleanup - > mu = & mutex_ ;
mutable_cleanup - > mu = & mutex_ ;
mutable_iter - > RegisterCleanup ( CleanupIteratorState , mutable_cleanup , nullptr ) ;
mutable_iter - > RegisterCleanup ( CleanupIteratorState , mutable_cleanup , nullptr ) ;
@ -2772,10 +2764,8 @@ std::pair<Iterator*, Iterator*> DBImpl::GetTailingIteratorPair(
Iterator * immutable_iter ;
Iterator * immutable_iter ;
IterState * immutable_cleanup = new IterState ( ) ;
IterState * immutable_cleanup = new IterState ( ) ;
std : : vector < Iterator * > list ;
std : : vector < Iterator * > list ;
for ( MemTable * m : immutables ) {
immutable_mems - > AddIterators ( options , & list ) ;
list . push_back ( m - > NewIterator ( options ) ) ;
immutable_cleanup - > imm = immutable_mems ;
immutable_cleanup - > mem . push_back ( m ) ;
}
version - > AddIterators ( options , storage_options_ , & list ) ;
version - > AddIterators ( options , storage_options_ , & list ) ;
immutable_cleanup - > version = version ;
immutable_cleanup - > version = version ;
immutable_cleanup - > db = this ;
immutable_cleanup - > db = this ;
@ -2832,7 +2822,7 @@ void DBImpl::InstallSuperVersion(DeletionState& deletion_state) {
DBImpl : : SuperVersion * DBImpl : : InstallSuperVersion (
DBImpl : : SuperVersion * DBImpl : : InstallSuperVersion (
SuperVersion * new_superversion ) {
SuperVersion * new_superversion ) {
mutex_ . AssertHeld ( ) ;
mutex_ . AssertHeld ( ) ;
new_superversion - > Init ( mem_ , imm_ , versions_ - > current ( ) ) ;
new_superversion - > Init ( mem_ , imm_ . current ( ) , versions_ - > current ( ) ) ;
SuperVersion * old_superversion = super_version_ ;
SuperVersion * old_superversion = super_version_ ;
super_version_ = new_superversion ;
super_version_ = new_superversion ;
+ + super_version_number_ ;
+ + super_version_number_ ;
@ -2875,7 +2865,7 @@ Status DBImpl::GetImpl(const ReadOptions& options,
if ( get_version - > mem - > Get ( lkey , value , & s , merge_context , options_ ) ) {
if ( get_version - > mem - > Get ( lkey , value , & s , merge_context , options_ ) ) {
// Done
// Done
RecordTick ( options_ . statistics . get ( ) , MEMTABLE_HIT ) ;
RecordTick ( options_ . statistics . get ( ) , MEMTABLE_HIT ) ;
} else if ( get_version - > imm . Get ( lkey , value , & s , merge_context , options_ ) ) {
} else if ( get_version - > imm - > Get ( lkey , value , & s , merge_context , options_ ) ) {
// Done
// Done
RecordTick ( options_ . statistics . get ( ) , MEMTABLE_HIT ) ;
RecordTick ( options_ . statistics . get ( ) , MEMTABLE_HIT ) ;
} else {
} else {
@ -2930,10 +2920,10 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
}
}
MemTable * mem = mem_ ;
MemTable * mem = mem_ ;
MemTableList imm = imm_ ;
MemTableListVersion * imm = imm_ . current ( ) ;
Version * current = versions_ - > current ( ) ;
Version * current = versions_ - > current ( ) ;
mem - > Ref ( ) ;
mem - > Ref ( ) ;
imm . RefAll ( ) ;
imm - > Ref ( ) ;
current - > Ref ( ) ;
current - > Ref ( ) ;
// Unlock while reading from files and memtables
// Unlock while reading from files and memtables
@ -2965,7 +2955,7 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
LookupKey lkey ( keys [ i ] , snapshot ) ;
LookupKey lkey ( keys [ i ] , snapshot ) ;
if ( mem - > Get ( lkey , value , & s , merge_context , options_ ) ) {
if ( mem - > Get ( lkey , value , & s , merge_context , options_ ) ) {
// Done
// Done
} else if ( imm . Get ( lkey , value , & s , merge_context , options_ ) ) {
} else if ( imm - > Get ( lkey , value , & s , merge_context , options_ ) ) {
// Done
// Done
} else {
} else {
current - > Get ( options , lkey , value , & s , & merge_context , & stats , options_ ) ;
current - > Get ( options , lkey , value , & s , & merge_context , & stats , options_ ) ;
@ -2984,7 +2974,7 @@ std::vector<Status> DBImpl::MultiGet(const ReadOptions& options,
MaybeScheduleFlushOrCompaction ( ) ;
MaybeScheduleFlushOrCompaction ( ) ;
}
}
MemTable * m = mem - > Unref ( ) ;
MemTable * m = mem - > Unref ( ) ;
imm . UnrefAll ( & to_delete ) ;
imm - > Unref ( & to_delete ) ;
current - > Unref ( ) ;
current - > Unref ( ) ;
mutex_ . Unlock ( ) ;
mutex_ . Unlock ( ) ;