@ -53,13 +53,16 @@ struct WriteBatchWithIndex::Rep {
// In overwrite mode, find the existing entry for the same key and update it
// In overwrite mode, find the existing entry for the same key and update it
// to point to the current entry.
// to point to the current entry.
// Return true if the key is found and updated.
// Return true if the key is found and updated.
bool UpdateExistingEntry ( ColumnFamilyHandle * column_family , const Slice & key ) ;
bool UpdateExistingEntry ( ColumnFamilyHandle * column_family , const Slice & key ,
bool UpdateExistingEntryWithCfId ( uint32_t column_family_id , const Slice & key ) ;
WriteType type ) ;
bool UpdateExistingEntryWithCfId ( uint32_t column_family_id , const Slice & key ,
WriteType type ) ;
// Add the recent entry to the update.
// Add the recent entry to the update.
// In overwrite mode, if key already exists in the index, update it.
// In overwrite mode, if key already exists in the index, update it.
void AddOrUpdateIndex ( ColumnFamilyHandle * column_family , const Slice & key ) ;
void AddOrUpdateIndex ( ColumnFamilyHandle * column_family , const Slice & key ,
void AddOrUpdateIndex ( const Slice & key ) ;
WriteType type ) ;
void AddOrUpdateIndex ( const Slice & key , WriteType type ) ;
// Allocate an index entry pointing to the last entry in the write batch and
// Allocate an index entry pointing to the last entry in the write batch and
// put it to skip list.
// put it to skip list.
@ -75,13 +78,13 @@ struct WriteBatchWithIndex::Rep {
} ;
} ;
bool WriteBatchWithIndex : : Rep : : UpdateExistingEntry (
bool WriteBatchWithIndex : : Rep : : UpdateExistingEntry (
ColumnFamilyHandle * column_family , const Slice & key ) {
ColumnFamilyHandle * column_family , const Slice & key , WriteType type ) {
uint32_t cf_id = GetColumnFamilyID ( column_family ) ;
uint32_t cf_id = GetColumnFamilyID ( column_family ) ;
return UpdateExistingEntryWithCfId ( cf_id , key ) ;
return UpdateExistingEntryWithCfId ( cf_id , key , type ) ;
}
}
bool WriteBatchWithIndex : : Rep : : UpdateExistingEntryWithCfId (
bool WriteBatchWithIndex : : Rep : : UpdateExistingEntryWithCfId (
uint32_t column_family_id , const Slice & key ) {
uint32_t column_family_id , const Slice & key , WriteType type ) {
if ( ! overwrite_key ) {
if ( ! overwrite_key ) {
return false ;
return false ;
}
}
@ -91,9 +94,16 @@ bool WriteBatchWithIndex::Rep::UpdateExistingEntryWithCfId(
iter . Seek ( key ) ;
iter . Seek ( key ) ;
if ( ! iter . Valid ( ) ) {
if ( ! iter . Valid ( ) ) {
return false ;
return false ;
}
} else if ( ! iter . MatchesKey ( column_family_id , key ) ) {
if ( ! iter . MatchesKey ( column_family_id , key ) ) {
return false ;
return false ;
} else {
// Move to the end of this key (NextKey-Prev)
iter . NextKey ( ) ; // Move to the next key
if ( iter . Valid ( ) ) {
iter . Prev ( ) ; // Move back one entry
} else {
iter . SeekToLast ( ) ;
}
}
}
WriteBatchIndexEntry * non_const_entry =
WriteBatchIndexEntry * non_const_entry =
const_cast < WriteBatchIndexEntry * > ( iter . GetRawEntry ( ) ) ;
const_cast < WriteBatchIndexEntry * > ( iter . GetRawEntry ( ) ) ;
@ -101,13 +111,17 @@ bool WriteBatchWithIndex::Rep::UpdateExistingEntryWithCfId(
last_sub_batch_offset = last_entry_offset ;
last_sub_batch_offset = last_entry_offset ;
sub_batch_cnt + + ;
sub_batch_cnt + + ;
}
}
non_const_entry - > offset = last_entry_offset ;
if ( type = = kMergeRecord ) {
return true ;
return false ;
} else {
non_const_entry - > offset = last_entry_offset ;
return true ;
}
}
}
void WriteBatchWithIndex : : Rep : : AddOrUpdateIndex (
void WriteBatchWithIndex : : Rep : : AddOrUpdateIndex (
ColumnFamilyHandle * column_family , const Slice & key ) {
ColumnFamilyHandle * column_family , const Slice & key , WriteType type ) {
if ( ! UpdateExistingEntry ( column_family , key ) ) {
if ( ! UpdateExistingEntry ( column_family , key , type ) ) {
uint32_t cf_id = GetColumnFamilyID ( column_family ) ;
uint32_t cf_id = GetColumnFamilyID ( column_family ) ;
const auto * cf_cmp = GetColumnFamilyUserComparator ( column_family ) ;
const auto * cf_cmp = GetColumnFamilyUserComparator ( column_family ) ;
if ( cf_cmp ! = nullptr ) {
if ( cf_cmp ! = nullptr ) {
@ -117,8 +131,9 @@ void WriteBatchWithIndex::Rep::AddOrUpdateIndex(
}
}
}
}
void WriteBatchWithIndex : : Rep : : AddOrUpdateIndex ( const Slice & key ) {
void WriteBatchWithIndex : : Rep : : AddOrUpdateIndex ( const Slice & key ,
if ( ! UpdateExistingEntryWithCfId ( 0 , key ) ) {
WriteType type ) {
if ( ! UpdateExistingEntryWithCfId ( 0 , key , type ) ) {
AddNewEntry ( 0 ) ;
AddNewEntry ( 0 ) ;
}
}
}
}
@ -190,14 +205,31 @@ Status WriteBatchWithIndex::Rep::ReBuildIndex() {
switch ( tag ) {
switch ( tag ) {
case kTypeColumnFamilyValue :
case kTypeColumnFamilyValue :
case kTypeValue :
case kTypeValue :
found + + ;
if ( ! UpdateExistingEntryWithCfId ( column_family_id , key , kPutRecord ) ) {
AddNewEntry ( column_family_id ) ;
}
break ;
case kTypeColumnFamilyDeletion :
case kTypeColumnFamilyDeletion :
case kTypeDeletion :
case kTypeDeletion :
found + + ;
if ( ! UpdateExistingEntryWithCfId ( column_family_id , key ,
kDeleteRecord ) ) {
AddNewEntry ( column_family_id ) ;
}
break ;
case kTypeColumnFamilySingleDeletion :
case kTypeColumnFamilySingleDeletion :
case kTypeSingleDeletion :
case kTypeSingleDeletion :
found + + ;
if ( ! UpdateExistingEntryWithCfId ( column_family_id , key ,
kSingleDeleteRecord ) ) {
AddNewEntry ( column_family_id ) ;
}
break ;
case kTypeColumnFamilyMerge :
case kTypeColumnFamilyMerge :
case kTypeMerge :
case kTypeMerge :
found + + ;
found + + ;
if ( ! UpdateExistingEntryWithCfId ( column_family_id , key ) ) {
if ( ! UpdateExistingEntryWithCfId ( column_family_id , key , kMergeRecord ) ) {
AddNewEntry ( column_family_id ) ;
AddNewEntry ( column_family_id ) ;
}
}
break ;
break ;
@ -255,22 +287,19 @@ WBWIIterator* WriteBatchWithIndex::NewIterator(
Iterator * WriteBatchWithIndex : : NewIteratorWithBase (
Iterator * WriteBatchWithIndex : : NewIteratorWithBase (
ColumnFamilyHandle * column_family , Iterator * base_iterator ,
ColumnFamilyHandle * column_family , Iterator * base_iterator ,
const ReadOptions * read_options ) {
const ReadOptions * read_options ) {
if ( rep - > overwrite_key = = false ) {
auto wbwiii =
assert ( false ) ;
new WBWIIteratorImpl ( GetColumnFamilyID ( column_family ) , & ( rep - > skip_list ) ,
return nullptr ;
& rep - > write_batch , & rep - > comparator ) ;
}
return new BaseDeltaIterator ( column_family , base_iterator , wbwiii ,
return new BaseDeltaIterator ( base_iterator , NewIterator ( column_family ) ,
GetColumnFamilyUserComparator ( column_family ) ,
GetColumnFamilyUserComparator ( column_family ) ,
read_options ) ;
read_options ) ;
}
}
Iterator * WriteBatchWithIndex : : NewIteratorWithBase ( Iterator * base_iterator ) {
Iterator * WriteBatchWithIndex : : NewIteratorWithBase ( Iterator * base_iterator ) {
if ( rep - > overwrite_key = = false ) {
assert ( false ) ;
return nullptr ;
}
// default column family's comparator
// default column family's comparator
return new BaseDeltaIterator ( base_iterator , NewIterator ( ) ,
auto wbwiii = new WBWIIteratorImpl ( 0 , & ( rep - > skip_list ) , & rep - > write_batch ,
& rep - > comparator ) ;
return new BaseDeltaIterator ( nullptr , base_iterator , wbwiii ,
rep - > comparator . default_comparator ( ) ) ;
rep - > comparator . default_comparator ( ) ) ;
}
}
@ -279,7 +308,7 @@ Status WriteBatchWithIndex::Put(ColumnFamilyHandle* column_family,
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . Put ( column_family , key , value ) ;
auto s = rep - > write_batch . Put ( column_family , key , value ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( column_family , key ) ;
rep - > AddOrUpdateIndex ( column_family , key , kPutRecord ) ;
}
}
return s ;
return s ;
}
}
@ -288,7 +317,7 @@ Status WriteBatchWithIndex::Put(const Slice& key, const Slice& value) {
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . Put ( key , value ) ;
auto s = rep - > write_batch . Put ( key , value ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( key ) ;
rep - > AddOrUpdateIndex ( key , kPutRecord ) ;
}
}
return s ;
return s ;
}
}
@ -298,7 +327,7 @@ Status WriteBatchWithIndex::Delete(ColumnFamilyHandle* column_family,
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . Delete ( column_family , key ) ;
auto s = rep - > write_batch . Delete ( column_family , key ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( column_family , key ) ;
rep - > AddOrUpdateIndex ( column_family , key , kDeleteRecord ) ;
}
}
return s ;
return s ;
}
}
@ -307,7 +336,7 @@ Status WriteBatchWithIndex::Delete(const Slice& key) {
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . Delete ( key ) ;
auto s = rep - > write_batch . Delete ( key ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( key ) ;
rep - > AddOrUpdateIndex ( key , kDeleteRecord ) ;
}
}
return s ;
return s ;
}
}
@ -317,7 +346,7 @@ Status WriteBatchWithIndex::SingleDelete(ColumnFamilyHandle* column_family,
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . SingleDelete ( column_family , key ) ;
auto s = rep - > write_batch . SingleDelete ( column_family , key ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( column_family , key ) ;
rep - > AddOrUpdateIndex ( column_family , key , kSingleDeleteRecord ) ;
}
}
return s ;
return s ;
}
}
@ -326,7 +355,7 @@ Status WriteBatchWithIndex::SingleDelete(const Slice& key) {
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . SingleDelete ( key ) ;
auto s = rep - > write_batch . SingleDelete ( key ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( key ) ;
rep - > AddOrUpdateIndex ( key , kSingleDeleteRecord ) ;
}
}
return s ;
return s ;
}
}
@ -336,7 +365,7 @@ Status WriteBatchWithIndex::Merge(ColumnFamilyHandle* column_family,
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . Merge ( column_family , key , value ) ;
auto s = rep - > write_batch . Merge ( column_family , key , value ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( column_family , key ) ;
rep - > AddOrUpdateIndex ( column_family , key , kMergeRecord ) ;
}
}
return s ;
return s ;
}
}
@ -345,7 +374,7 @@ Status WriteBatchWithIndex::Merge(const Slice& key, const Slice& value) {
rep - > SetLastEntryOffset ( ) ;
rep - > SetLastEntryOffset ( ) ;
auto s = rep - > write_batch . Merge ( key , value ) ;
auto s = rep - > write_batch . Merge ( key , value ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
rep - > AddOrUpdateIndex ( key ) ;
rep - > AddOrUpdateIndex ( key , kMergeRecord ) ;
}
}
return s ;
return s ;
}
}
@ -361,18 +390,18 @@ Status WriteBatchWithIndex::GetFromBatch(ColumnFamilyHandle* column_family,
const Slice & key , std : : string * value ) {
const Slice & key , std : : string * value ) {
Status s ;
Status s ;
WriteBatchWithIndexInternal wbwii ( & options , column_family ) ;
WriteBatchWithIndexInternal wbwii ( & options , column_family ) ;
auto result = wbwii . GetFromBatch ( this , key , value , rep - > overwrite_key , & s ) ;
auto result = wbwii . GetFromBatch ( this , key , value , & s ) ;
switch ( result ) {
switch ( result ) {
case WriteBatchWithIndexInternal : : Result : : kFound :
case WBWIIteratorImpl : : kFound :
case WriteBatchWithIndexInternal : : Result : : kError :
case WBWIIteratorImpl : : kError :
// use returned status
// use returned status
break ;
break ;
case WriteBatchWithIndexInternal : : Result : : kDeleted :
case WBWIIteratorImpl : : kDeleted :
case WriteBatchWithIndexInternal : : Result : : kNotFound :
case WBWIIteratorImpl : : kNotFound :
s = Status : : NotFound ( ) ;
s = Status : : NotFound ( ) ;
break ;
break ;
case WriteBatchWithIndexInternal : : Result : : kMergeInProgress :
case WBWIIteratorImpl : : kMergeInProgress :
s = Status : : MergeInProgress ( ) ;
s = Status : : MergeInProgress ( ) ;
break ;
break ;
default :
default :
@ -440,29 +469,18 @@ Status WriteBatchWithIndex::GetFromBatchAndDB(
// we cannot pin it as otherwise the returned value will not be available
// we cannot pin it as otherwise the returned value will not be available
// after the transaction finishes.
// after the transaction finishes.
std : : string & batch_value = * pinnable_val - > GetSelf ( ) ;
std : : string & batch_value = * pinnable_val - > GetSelf ( ) ;
auto result =
auto result = wbwii . GetFromBatch ( this , key , & batch_value , & s ) ;
wbwii . GetFromBatch ( this , key , & batch_value , rep - > overwrite_key , & s ) ;
if ( result = = WriteBatchWithIndexInternal : : Result : : kFound ) {
if ( result = = WBWIIteratorImpl : : kFound ) {
pinnable_val - > PinSelf ( ) ;
pinnable_val - > PinSelf ( ) ;
return s ;
return s ;
}
} else if ( ! s . ok ( ) | | result = = WBWIIteratorImpl : : kError ) {
if ( result = = WriteBatchWithIndexInternal : : Result : : kDeleted ) {
return Status : : NotFound ( ) ;
}
if ( result = = WriteBatchWithIndexInternal : : Result : : kError ) {
return s ;
return s ;
} else if ( result = = WBWIIteratorImpl : : kDeleted ) {
return Status : : NotFound ( ) ;
}
}
if ( result = = WriteBatchWithIndexInternal : : Result : : kMergeInProgress & &
assert ( result = = WBWIIteratorImpl : : kMergeInProgress | |
rep - > overwrite_key = = true ) {
result = = WBWIIteratorImpl : : kNotFound ) ;
// Since we've overwritten keys, we do not know what other operations are
// in this batch for this key, so we cannot do a Merge to compute the
// result. Instead, we will simply return MergeInProgress.
return Status : : MergeInProgress ( ) ;
}
assert ( result = = WriteBatchWithIndexInternal : : Result : : kMergeInProgress | |
result = = WriteBatchWithIndexInternal : : Result : : kNotFound ) ;
// Did not find key in batch OR could not resolve Merges. Try DB.
// Did not find key in batch OR could not resolve Merges. Try DB.
if ( ! callback ) {
if ( ! callback ) {
@ -477,7 +495,7 @@ Status WriteBatchWithIndex::GetFromBatchAndDB(
}
}
if ( s . ok ( ) | | s . IsNotFound ( ) ) { // DB Get Succeeded
if ( s . ok ( ) | | s . IsNotFound ( ) ) { // DB Get Succeeded
if ( result = = WriteBatchWithIndexInternal : : Result : : kMergeInProgress ) {
if ( result = = WBWIIteratorImpl : : kMergeInProgress ) {
// Merge result from DB with merges in Batch
// Merge result from DB with merges in Batch
std : : string merge_result ;
std : : string merge_result ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
@ -513,7 +531,7 @@ void WriteBatchWithIndex::MultiGetFromBatchAndDB(
autovector < KeyContext , MultiGetContext : : MAX_BATCH_SIZE > key_context ;
autovector < KeyContext , MultiGetContext : : MAX_BATCH_SIZE > key_context ;
autovector < KeyContext * , MultiGetContext : : MAX_BATCH_SIZE > sorted_keys ;
autovector < KeyContext * , MultiGetContext : : MAX_BATCH_SIZE > sorted_keys ;
// To hold merges from the write batch
// To hold merges from the write batch
autovector < std : : pair < Write Batch With Index In tern al : : Result , MergeContext > ,
autovector < std : : pair < WBWIIteratorImp l : : Result , MergeContext > ,
MultiGetContext : : MAX_BATCH_SIZE >
MultiGetContext : : MAX_BATCH_SIZE >
merges ;
merges ;
// Since the lifetime of the WriteBatch is the same as that of the transaction
// Since the lifetime of the WriteBatch is the same as that of the transaction
@ -524,31 +542,22 @@ void WriteBatchWithIndex::MultiGetFromBatchAndDB(
PinnableSlice * pinnable_val = & values [ i ] ;
PinnableSlice * pinnable_val = & values [ i ] ;
std : : string & batch_value = * pinnable_val - > GetSelf ( ) ;
std : : string & batch_value = * pinnable_val - > GetSelf ( ) ;
Status * s = & statuses [ i ] ;
Status * s = & statuses [ i ] ;
auto result = wbwii . GetFromBatch ( this , keys [ i ] , & merge_context ,
auto result =
& batch_value , rep - > overwrite_key , s ) ;
wbwii . GetFromBatch ( this , keys [ i ] , & merge_context , & batch_value , s ) ;
if ( result = = WriteBatchWithIndexInternal : : Result : : kFound ) {
if ( result = = WBWIIteratorImpl : : kFound ) {
pinnable_val - > PinSelf ( ) ;
pinnable_val - > PinSelf ( ) ;
continue ;
continue ;
}
}
if ( result = = WriteBatchWithIndexInternal : : Result : : kDeleted ) {
if ( result = = WBWIIteratorImpl : : kDeleted ) {
* s = Status : : NotFound ( ) ;
* s = Status : : NotFound ( ) ;
continue ;
continue ;
}
}
if ( result = = WriteBatchWithIndexInternal : : Result : : kError ) {
if ( result = = WBWIIteratorImpl : : kError ) {
continue ;
continue ;
}
}
if ( result = = WriteBatchWithIndexInternal : : Result : : kMergeInProgress & &
assert ( result = = WBWIIteratorImpl : : kMergeInProgress | |
rep - > overwrite_key = = true ) {
result = = WBWIIteratorImpl : : kNotFound ) ;
// Since we've overwritten keys, we do not know what other operations are
// in this batch for this key, so we cannot do a Merge to compute the
// result. Instead, we will simply return MergeInProgress.
* s = Status : : MergeInProgress ( ) ;
continue ;
}
assert ( result = = WriteBatchWithIndexInternal : : Result : : kMergeInProgress | |
result = = WriteBatchWithIndexInternal : : Result : : kNotFound ) ;
key_context . emplace_back ( column_family , keys [ i ] , & values [ i ] ,
key_context . emplace_back ( column_family , keys [ i ] , & values [ i ] ,
/*timestamp*/ nullptr , & statuses [ i ] ) ;
/*timestamp*/ nullptr , & statuses [ i ] ) ;
merges . emplace_back ( result , std : : move ( merge_context ) ) ;
merges . emplace_back ( result , std : : move ( merge_context ) ) ;
@ -569,10 +578,9 @@ void WriteBatchWithIndex::MultiGetFromBatchAndDB(
KeyContext & key = * iter ;
KeyContext & key = * iter ;
if ( key . s - > ok ( ) | | key . s - > IsNotFound ( ) ) { // DB Get Succeeded
if ( key . s - > ok ( ) | | key . s - > IsNotFound ( ) ) { // DB Get Succeeded
size_t index = iter - key_context . begin ( ) ;
size_t index = iter - key_context . begin ( ) ;
std : : pair < WriteBatchWithIndexInternal : : Result , MergeContext > &
std : : pair < WBWIIteratorImpl : : Result , MergeContext > & merge_result =
merge_result = merges [ index ] ;
merges [ index ] ;
if ( merge_result . first = =
if ( merge_result . first = = WBWIIteratorImpl : : kMergeInProgress ) {
WriteBatchWithIndexInternal : : Result : : kMergeInProgress ) {
// Merge result from DB with merges in Batch
// Merge result from DB with merges in Batch
if ( key . s - > ok ( ) ) {
if ( key . s - > ok ( ) ) {
* key . s = wbwii . MergeKey ( * key . key , iter - > value , merge_result . second ,
* key . s = wbwii . MergeKey ( * key . key , iter - > value , merge_result . second ,