@ -234,14 +234,17 @@ class MemTableInserter : public WriteBatch::Handler {
public :
public :
SequenceNumber sequence_ ;
SequenceNumber sequence_ ;
ColumnFamilyMemTables * cf_mems_ ;
ColumnFamilyMemTables * cf_mems_ ;
bool recovery_ ;
uint64_t log_number_ ;
uint64_t log_number_ ;
DBImpl * db_ ;
DBImpl * db_ ;
const bool dont_filter_deletes_ ;
const bool dont_filter_deletes_ ;
MemTableInserter ( SequenceNumber sequence , ColumnFamilyMemTables * cf_mems ,
MemTableInserter ( SequenceNumber sequence , ColumnFamilyMemTables * cf_mems ,
uint64_t log_number , DB * db , const bool dont_filter_deletes )
bool recovery , uint64_t log_number , DB * db ,
const bool dont_filter_deletes )
: sequence_ ( sequence ) ,
: sequence_ ( sequence ) ,
cf_mems_ ( cf_mems ) ,
cf_mems_ ( cf_mems ) ,
recovery_ ( recovery ) ,
log_number_ ( log_number ) ,
log_number_ ( log_number ) ,
db_ ( reinterpret_cast < DBImpl * > ( db ) ) ,
db_ ( reinterpret_cast < DBImpl * > ( db ) ) ,
dont_filter_deletes_ ( dont_filter_deletes ) {
dont_filter_deletes_ ( dont_filter_deletes ) {
@ -251,19 +254,39 @@ class MemTableInserter : public WriteBatch::Handler {
}
}
}
}
bool IgnoreUpdate ( ) {
bool SeekToColumnFamily ( uint32_t column_family_id , Status * s ) {
return log_number_ ! = 0 & & log_number_ < cf_mems_ - > GetLogNumber ( ) ;
}
virtual Status PutCF ( uint32_t column_family_id , const Slice & key ,
const Slice & value ) {
bool found = cf_mems_ - > Seek ( column_family_id ) ;
bool found = cf_mems_ - > Seek ( column_family_id ) ;
if ( recovery_ & & ( ! found | | log_number_ < cf_mems_ - > GetLogNumber ( ) ) ) {
// if in recovery envoronment:
// * If column family was not found, it might mean that the WAL write
// batch references to the column family that was dropped after the
// insert. We don't want to fail the whole write batch in that case -- we
// just ignore the update.
// * If log_number_ < cf_mems_->GetLogNumber(), this means that column
// family already contains updates from this log. We can't apply updates
// twice because of update-in-place or merge workloads -- ignore the
// update
* s = Status : : OK ( ) ;
return false ;
}
if ( ! found ) {
if ( ! found ) {
return Status : : InvalidArgument (
assert ( ! recovery_ ) ;
// If the column family was not found in non-recovery enviornment
// (client's write code-path), we have to fail the write and return
// the failure status to the client.
* s = Status : : InvalidArgument (
" Invalid column family specified in write batch " ) ;
" Invalid column family specified in write batch " ) ;
return false ;
}
}
if ( IgnoreUpdate ( ) ) {
return true ;
return Status : : OK ( ) ;
}
virtual Status PutCF ( uint32_t column_family_id , const Slice & key ,
const Slice & value ) {
Status seek_status ;
if ( ! SeekToColumnFamily ( column_family_id , & seek_status ) ) {
+ + sequence_ ;
return seek_status ;
}
}
MemTable * mem = cf_mems_ - > GetMemTable ( ) ;
MemTable * mem = cf_mems_ - > GetMemTable ( ) ;
const Options * options = cf_mems_ - > GetFullOptions ( ) ;
const Options * options = cf_mems_ - > GetFullOptions ( ) ;
@ -315,13 +338,10 @@ class MemTableInserter : public WriteBatch::Handler {
virtual Status MergeCF ( uint32_t column_family_id , const Slice & key ,
virtual Status MergeCF ( uint32_t column_family_id , const Slice & key ,
const Slice & value ) {
const Slice & value ) {
bool found = cf_mems_ - > Seek ( column_family_id ) ;
Status seek_status ;
if ( ! found ) {
if ( ! SeekToColumnFamily ( column_family_id , & seek_status ) ) {
return Status : : InvalidArgument (
+ + sequence_ ;
" Invalid column family specified in write batch " ) ;
return seek_status ;
}
if ( IgnoreUpdate ( ) ) {
return Status : : OK ( ) ;
}
}
MemTable * mem = cf_mems_ - > GetMemTable ( ) ;
MemTable * mem = cf_mems_ - > GetMemTable ( ) ;
const Options * options = cf_mems_ - > GetFullOptions ( ) ;
const Options * options = cf_mems_ - > GetFullOptions ( ) ;
@ -387,13 +407,10 @@ class MemTableInserter : public WriteBatch::Handler {
}
}
virtual Status DeleteCF ( uint32_t column_family_id , const Slice & key ) {
virtual Status DeleteCF ( uint32_t column_family_id , const Slice & key ) {
bool found = cf_mems_ - > Seek ( column_family_id ) ;
Status seek_status ;
if ( ! found ) {
if ( ! SeekToColumnFamily ( column_family_id , & seek_status ) ) {
return Status : : InvalidArgument (
+ + sequence_ ;
" Invalid column family specified in write batch " ) ;
return seek_status ;
}
if ( IgnoreUpdate ( ) ) {
return Status : : OK ( ) ;
}
}
MemTable * mem = cf_mems_ - > GetMemTable ( ) ;
MemTable * mem = cf_mems_ - > GetMemTable ( ) ;
const Options * options = cf_mems_ - > GetFullOptions ( ) ;
const Options * options = cf_mems_ - > GetFullOptions ( ) ;
@ -421,10 +438,10 @@ class MemTableInserter : public WriteBatch::Handler {
Status WriteBatchInternal : : InsertInto ( const WriteBatch * b ,
Status WriteBatchInternal : : InsertInto ( const WriteBatch * b ,
ColumnFamilyMemTables * memtables ,
ColumnFamilyMemTables * memtables ,
uint64_t log_number , DB * db ,
bool recovery , uint64_t log_number ,
const bool dont_filter_deletes ) {
DB * db , const bool dont_filter_deletes ) {
MemTableInserter inserter ( WriteBatchInternal : : Sequence ( b ) , memtables ,
MemTableInserter inserter ( WriteBatchInternal : : Sequence ( b ) , memtables ,
log_number , db , dont_filter_deletes ) ;
recovery , log_number , db , dont_filter_deletes ) ;
return b - > Iterate ( & inserter ) ;
return b - > Iterate ( & inserter ) ;
}
}