@ -39,14 +39,17 @@ void appendToReplayLog(std::string* replay_log, ValueType type, Slice value) {
} // namespace
} // namespace
GetContext : : GetContext (
GetContext : : GetContext ( const Comparator * ucmp ,
const Comparator * ucmp , const MergeOperator * merge_operator , Logger * logger ,
const MergeOperator * merge_operator , Logger * logger ,
Statistics * statistics , GetState init_state , const Slice & user_key ,
Statistics * statistics , GetState init_state ,
PinnableSlice * pinnable_val , std : : string * timestamp , bool * value_found ,
const Slice & user_key , PinnableSlice * pinnable_val ,
MergeContext * merge_context , bool do_merge ,
std : : string * timestamp , bool * value_found ,
SequenceNumber * _max_covering_tombstone_seq , SystemClock * clock ,
MergeContext * merge_context , bool do_merge ,
SequenceNumber * seq , PinnedIteratorsManager * _pinned_iters_mgr ,
SequenceNumber * _max_covering_tombstone_seq ,
ReadCallback * callback , bool * is_blob_index , uint64_t tracing_get_id )
SystemClock * clock , SequenceNumber * seq ,
PinnedIteratorsManager * _pinned_iters_mgr ,
ReadCallback * callback , bool * is_blob_index ,
uint64_t tracing_get_id , BlobFetcher * blob_fetcher )
: ucmp_ ( ucmp ) ,
: ucmp_ ( ucmp ) ,
merge_operator_ ( merge_operator ) ,
merge_operator_ ( merge_operator ) ,
logger_ ( logger ) ,
logger_ ( logger ) ,
@ -65,7 +68,8 @@ GetContext::GetContext(
callback_ ( callback ) ,
callback_ ( callback ) ,
do_merge_ ( do_merge ) ,
do_merge_ ( do_merge ) ,
is_blob_index_ ( is_blob_index ) ,
is_blob_index_ ( is_blob_index ) ,
tracing_get_id_ ( tracing_get_id ) {
tracing_get_id_ ( tracing_get_id ) ,
blob_fetcher_ ( blob_fetcher ) {
if ( seq_ ) {
if ( seq_ ) {
* seq_ = kMaxSequenceNumber ;
* seq_ = kMaxSequenceNumber ;
}
}
@ -79,11 +83,11 @@ GetContext::GetContext(
bool do_merge , SequenceNumber * _max_covering_tombstone_seq ,
bool do_merge , SequenceNumber * _max_covering_tombstone_seq ,
SystemClock * clock , SequenceNumber * seq ,
SystemClock * clock , SequenceNumber * seq ,
PinnedIteratorsManager * _pinned_iters_mgr , ReadCallback * callback ,
PinnedIteratorsManager * _pinned_iters_mgr , ReadCallback * callback ,
bool * is_blob_index , uint64_t tracing_get_id )
bool * is_blob_index , uint64_t tracing_get_id , BlobFetcher * blob_fetcher )
: GetContext ( ucmp , merge_operator , logger , statistics , init_state , user_key ,
: GetContext ( ucmp , merge_operator , logger , statistics , init_state , user_key ,
pinnable_val , nullptr , value_found , merge_context , do_merge ,
pinnable_val , nullptr , value_found , merge_context , do_merge ,
_max_covering_tombstone_seq , clock , seq , _pinned_iters_mgr ,
_max_covering_tombstone_seq , clock , seq , _pinned_iters_mgr ,
callback , is_blob_index , tracing_get_id ) { }
callback , is_blob_index , tracing_get_id , blob_fetcher ) { }
// Called from TableCache::Get and Table::Get when file/block in which
// Called from TableCache::Get and Table::Get when file/block in which
// key may exist are not there in TableCache/BlockCache respectively. In this
// key may exist are not there in TableCache/BlockCache respectively. In this
@ -250,6 +254,9 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
state_ = kUnexpectedBlobIndex ;
state_ = kUnexpectedBlobIndex ;
return false ;
return false ;
}
}
if ( is_blob_index_ ! = nullptr ) {
* is_blob_index_ = ( type = = kTypeBlobIndex ) ;
}
if ( kNotFound = = state_ ) {
if ( kNotFound = = state_ ) {
state_ = kFound ;
state_ = kFound ;
if ( do_merge_ ) {
if ( do_merge_ ) {
@ -260,7 +267,6 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
} else {
} else {
TEST_SYNC_POINT_CALLBACK ( " GetContext::SaveValue::PinSelf " ,
TEST_SYNC_POINT_CALLBACK ( " GetContext::SaveValue::PinSelf " ,
this ) ;
this ) ;
// Otherwise copy the value
// Otherwise copy the value
pinnable_val_ - > PinSelf ( value ) ;
pinnable_val_ - > PinSelf ( value ) ;
}
}
@ -269,27 +275,44 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
// It means this function is called as part of DB GetMergeOperands
// It means this function is called as part of DB GetMergeOperands
// API and the current value should be part of
// API and the current value should be part of
// merge_context_->operand_list
// merge_context_->operand_list
push_operand ( value , value_pinner ) ;
if ( is_blob_index_ ! = nullptr & & * is_blob_index_ ) {
PinnableSlice pin_val ;
if ( GetBlobValue ( value , & pin_val ) = = false ) {
return false ;
}
Slice blob_value ( pin_val ) ;
push_operand ( blob_value , nullptr ) ;
} else {
push_operand ( value , value_pinner ) ;
}
}
}
} else if ( kMerge = = state_ ) {
} else if ( kMerge = = state_ ) {
assert ( merge_operator_ ! = nullptr ) ;
assert ( merge_operator_ ! = nullptr ) ;
state_ = kFound ;
if ( is_blob_index_ ! = nullptr & & * is_blob_index_ ) {
if ( do_merge_ ) {
PinnableSlice pin_val ;
if ( LIKELY ( pinnable_val_ ! = nullptr ) ) {
if ( GetBlobValue ( value , & pin_val ) = = false ) {
Status merge_status = MergeHelper : : TimedFullMerge (
return false ;
merge_operator_ , user_key_ , & value ,
}
merge_context_ - > GetOperands ( ) , pinnable_val_ - > GetSelf ( ) ,
Slice blob_value ( pin_val ) ;
logger_ , statistics_ , clock_ ) ;
state_ = kFound ;
pinnable_val_ - > PinSelf ( ) ;
if ( do_merge_ ) {
if ( ! merge_status . ok ( ) ) {
Merge ( & blob_value ) ;
state_ = kCorrupt ;
} else {
}
// It means this function is called as part of DB GetMergeOperands
// API and the current value should be part of
// merge_context_->operand_list
push_operand ( blob_value , nullptr ) ;
}
}
} else {
} else {
// It means this function is called as part of DB GetMergeOperands
state_ = kFound ;
// API and the current value should be part of
if ( do_merge_ ) {
// merge_context_->operand_list
Merge ( & value ) ;
push_operand ( value , value_pinner ) ;
} else {
// It means this function is called as part of DB GetMergeOperands
// API and the current value should be part of
// merge_context_->operand_list
push_operand ( value , value_pinner ) ;
}
}
}
}
}
if ( state_ = = kFound ) {
if ( state_ = = kFound ) {
@ -299,9 +322,6 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
timestamp_ - > assign ( ts . data ( ) , ts . size ( ) ) ;
timestamp_ - > assign ( ts . data ( ) , ts . size ( ) ) ;
}
}
}
}
if ( is_blob_index_ ! = nullptr ) {
* is_blob_index_ = ( type = = kTypeBlobIndex ) ;
}
return false ;
return false ;
case kTypeDeletion :
case kTypeDeletion :
@ -315,20 +335,9 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
state_ = kDeleted ;
state_ = kDeleted ;
} else if ( kMerge = = state_ ) {
} else if ( kMerge = = state_ ) {
state_ = kFound ;
state_ = kFound ;
if ( LIKELY ( pinnable_val_ ! = nullptr ) ) {
Merge ( nullptr ) ;
if ( do_merge_ ) {
// If do_merge_ = false then the current value shouldn't be part of
Status merge_status = MergeHelper : : TimedFullMerge (
// merge_context_->operand_list
merge_operator_ , user_key_ , nullptr ,
merge_context_ - > GetOperands ( ) , pinnable_val_ - > GetSelf ( ) ,
logger_ , statistics_ , clock_ ) ;
pinnable_val_ - > PinSelf ( ) ;
if ( ! merge_status . ok ( ) ) {
state_ = kCorrupt ;
}
}
// If do_merge_ = false then the current value shouldn't be part of
// merge_context_->operand_list
}
}
}
return false ;
return false ;
@ -341,20 +350,7 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
merge_operator_ - > ShouldMerge (
merge_operator_ - > ShouldMerge (
merge_context_ - > GetOperandsDirectionBackward ( ) ) ) {
merge_context_ - > GetOperandsDirectionBackward ( ) ) ) {
state_ = kFound ;
state_ = kFound ;
if ( LIKELY ( pinnable_val_ ! = nullptr ) ) {
Merge ( nullptr ) ;
// do_merge_ = true this is the case where this function is called
// as part of DB Get API hence merge operators should be merged.
if ( do_merge_ ) {
Status merge_status = MergeHelper : : TimedFullMerge (
merge_operator_ , user_key_ , nullptr ,
merge_context_ - > GetOperands ( ) , pinnable_val_ - > GetSelf ( ) ,
logger_ , statistics_ , clock_ ) ;
pinnable_val_ - > PinSelf ( ) ;
if ( ! merge_status . ok ( ) ) {
state_ = kCorrupt ;
}
}
}
return false ;
return false ;
}
}
return true ;
return true ;
@ -369,6 +365,35 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
return false ;
return false ;
}
}
void GetContext : : Merge ( const Slice * value ) {
if ( LIKELY ( pinnable_val_ ! = nullptr ) ) {
if ( do_merge_ ) {
Status merge_status = MergeHelper : : TimedFullMerge (
merge_operator_ , user_key_ , value , merge_context_ - > GetOperands ( ) ,
pinnable_val_ - > GetSelf ( ) , logger_ , statistics_ , clock_ ) ;
pinnable_val_ - > PinSelf ( ) ;
if ( ! merge_status . ok ( ) ) {
state_ = kCorrupt ;
}
}
}
}
bool GetContext : : GetBlobValue ( const Slice & blob_index ,
PinnableSlice * blob_value ) {
Status status = blob_fetcher_ - > FetchBlob ( user_key_ , blob_index , blob_value ) ;
if ( ! status . ok ( ) ) {
if ( status . IsIncomplete ( ) ) {
MarkKeyMayExist ( ) ;
return false ;
}
state_ = kCorrupt ;
return false ;
}
* is_blob_index_ = false ;
return true ;
}
void GetContext : : push_operand ( const Slice & value , Cleanable * value_pinner ) {
void GetContext : : push_operand ( const Slice & value , Cleanable * value_pinner ) {
if ( pinned_iters_mgr ( ) & & pinned_iters_mgr ( ) - > PinningEnabled ( ) & &
if ( pinned_iters_mgr ( ) & & pinned_iters_mgr ( ) - > PinningEnabled ( ) & &
value_pinner ! = nullptr ) {
value_pinner ! = nullptr ) {