Eliminate some code duplication in MergeHelper (#12121)

Summary:
Pull Request resolved: https://github.com/facebook/rocksdb/pull/12121

The patch eliminates some code duplication by unifying the two sets of `MergeHelper::TimedFullMerge` overloads using variadic templates. It also brings the order of parameters into sync when it comes to the various `TimedFullMerge*` methods.

Reviewed By: jaykorean

Differential Revision: D51862483

fbshipit-source-id: e3f832a6ff89ba34591451655cf11025d0a0d018
This commit is contained in:
Levi Tamasi 2023-12-05 14:07:42 -08:00 committed by Facebook GitHub Bot
parent 2045fe4693
commit 0ebe1614cb
8 changed files with 103 additions and 240 deletions

View File

@ -1293,8 +1293,8 @@ bool DBIter::MergeWithNoBaseValue(const Slice& user_key) {
const Status s = MergeHelper::TimedFullMerge( const Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key, MergeHelper::kNoBaseValue, merge_operator_, user_key, MergeHelper::kNoBaseValue,
merge_context_.GetOperands(), logger_, statistics_, clock_, merge_context_.GetOperands(), logger_, statistics_, clock_,
/* update_num_ops_stats */ true, &saved_value_, &pinned_value_, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
&result_type, /* op_failure_scope */ nullptr); &saved_value_, &pinned_value_, &result_type);
return SetValueAndColumnsFromMergeResult(s, result_type); return SetValueAndColumnsFromMergeResult(s, result_type);
} }
@ -1306,8 +1306,8 @@ bool DBIter::MergeWithPlainBaseValue(const Slice& value,
const Status s = MergeHelper::TimedFullMerge( const Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key, MergeHelper::kPlainBaseValue, value, merge_operator_, user_key, MergeHelper::kPlainBaseValue, value,
merge_context_.GetOperands(), logger_, statistics_, clock_, merge_context_.GetOperands(), logger_, statistics_, clock_,
/* update_num_ops_stats */ true, &saved_value_, &pinned_value_, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
&result_type, /* op_failure_scope */ nullptr); &saved_value_, &pinned_value_, &result_type);
return SetValueAndColumnsFromMergeResult(s, result_type); return SetValueAndColumnsFromMergeResult(s, result_type);
} }
@ -1319,8 +1319,8 @@ bool DBIter::MergeWithWideColumnBaseValue(const Slice& entity,
const Status s = MergeHelper::TimedFullMerge( const Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key, MergeHelper::kWideBaseValue, entity, merge_operator_, user_key, MergeHelper::kWideBaseValue, entity,
merge_context_.GetOperands(), logger_, statistics_, clock_, merge_context_.GetOperands(), logger_, statistics_, clock_,
/* update_num_ops_stats */ true, &saved_value_, &pinned_value_, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
&result_type, /* op_failure_scope */ nullptr); &saved_value_, &pinned_value_, &result_type);
return SetValueAndColumnsFromMergeResult(s, result_type); return SetValueAndColumnsFromMergeResult(s, result_type);
} }

View File

@ -1061,8 +1061,8 @@ static bool SaveValue(void* arg, const char* entry) {
merge_operator, s->key->user_key(), merge_operator, s->key->user_key(),
MergeHelper::kPlainBaseValue, v, merge_context->GetOperands(), MergeHelper::kPlainBaseValue, v, merge_context->GetOperands(),
s->logger, s->statistics, s->clock, s->logger, s->statistics, s->clock,
/* update_num_ops_stats */ true, s->value, s->columns, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
/* op_failure_scope */ nullptr); s->value, s->columns);
} }
} else if (s->value) { } else if (s->value) {
s->value->assign(v.data(), v.size()); s->value->assign(v.data(), v.size());
@ -1114,8 +1114,8 @@ static bool SaveValue(void* arg, const char* entry) {
*(s->status) = MergeHelper::TimedFullMerge( *(s->status) = MergeHelper::TimedFullMerge(
merge_operator, s->key->user_key(), MergeHelper::kWideBaseValue, merge_operator, s->key->user_key(), MergeHelper::kWideBaseValue,
v, merge_context->GetOperands(), s->logger, s->statistics, v, merge_context->GetOperands(), s->logger, s->statistics,
s->clock, /* update_num_ops_stats */ true, s->value, s->columns, s->clock, /* update_num_ops_stats */ true,
/* op_failure_scope */ nullptr); /* op_failure_scope */ nullptr, s->value, s->columns);
} }
} else if (s->value) { } else if (s->value) {
Slice value_of_default; Slice value_of_default;
@ -1152,8 +1152,8 @@ static bool SaveValue(void* arg, const char* entry) {
*(s->status) = MergeHelper::TimedFullMerge( *(s->status) = MergeHelper::TimedFullMerge(
merge_operator, s->key->user_key(), MergeHelper::kNoBaseValue, merge_operator, s->key->user_key(), MergeHelper::kNoBaseValue,
merge_context->GetOperands(), s->logger, s->statistics, merge_context->GetOperands(), s->logger, s->statistics,
s->clock, /* update_num_ops_stats */ true, s->value, s->columns, s->clock, /* update_num_ops_stats */ true,
/* op_failure_scope */ nullptr); /* op_failure_scope */ nullptr, s->value, s->columns);
} else { } else {
// We have found a final value (a base deletion) and have newer // We have found a final value (a base deletion) and have newer
// merge operands that we do not intend to merge. Nothing remains // merge operands that we do not intend to merge. Nothing remains
@ -1192,8 +1192,8 @@ static bool SaveValue(void* arg, const char* entry) {
*(s->status) = MergeHelper::TimedFullMerge( *(s->status) = MergeHelper::TimedFullMerge(
merge_operator, s->key->user_key(), MergeHelper::kNoBaseValue, merge_operator, s->key->user_key(), MergeHelper::kNoBaseValue,
merge_context->GetOperands(), s->logger, s->statistics, merge_context->GetOperands(), s->logger, s->statistics,
s->clock, /* update_num_ops_stats */ true, s->value, s->columns, s->clock, /* update_num_ops_stats */ true,
/* op_failure_scope */ nullptr); /* op_failure_scope */ nullptr, s->value, s->columns);
} }
*(s->found_final_value) = true; *(s->found_final_value) = true;

View File

@ -12,7 +12,6 @@
#include "db/blob/prefetch_buffer_collection.h" #include "db/blob/prefetch_buffer_collection.h"
#include "db/compaction/compaction_iteration_stats.h" #include "db/compaction/compaction_iteration_stats.h"
#include "db/dbformat.h" #include "db/dbformat.h"
#include "db/wide/wide_column_serialization.h"
#include "db/wide/wide_columns_helper.h" #include "db/wide/wide_columns_helper.h"
#include "logging/logging.h" #include "logging/logging.h"
#include "monitoring/perf_context_imp.h" #include "monitoring/perf_context_imp.h"
@ -111,9 +110,9 @@ Status MergeHelper::TimedFullMergeImpl(
const MergeOperator* merge_operator, const Slice& key, const MergeOperator* merge_operator, const Slice& key,
MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value, MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value,
const std::vector<Slice>& operands, Logger* logger, Statistics* statistics, const std::vector<Slice>& operands, Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats, std::string* result, SystemClock* clock, bool update_num_ops_stats,
Slice* result_operand, ValueType* result_type, MergeOperator::OpFailureScope* op_failure_scope, std::string* result,
MergeOperator::OpFailureScope* op_failure_scope) { Slice* result_operand, ValueType* result_type) {
assert(result); assert(result);
assert(result_type); assert(result_type);
@ -173,9 +172,9 @@ Status MergeHelper::TimedFullMergeImpl(
const MergeOperator* merge_operator, const Slice& key, const MergeOperator* merge_operator, const Slice& key,
MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value, MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value,
const std::vector<Slice>& operands, Logger* logger, Statistics* statistics, const std::vector<Slice>& operands, Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats, std::string* result_value, SystemClock* clock, bool update_num_ops_stats,
PinnableWideColumns* result_entity, MergeOperator::OpFailureScope* op_failure_scope, std::string* result_value,
MergeOperator::OpFailureScope* op_failure_scope) { PinnableWideColumns* result_entity) {
assert(result_value || result_entity); assert(result_value || result_entity);
assert(!result_value || !result_entity); assert(!result_value || !result_entity);
@ -245,141 +244,6 @@ Status MergeHelper::TimedFullMergeImpl(
op_failure_scope, std::move(visitor)); op_failure_scope, std::move(visitor));
} }
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, NoBaseValueTag,
const std::vector<Slice>& operands, Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats, std::string* result,
Slice* result_operand, ValueType* result_type,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value;
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result, result_operand,
result_type, op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, PlainBaseValueTag,
const Slice& value, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result, Slice* result_operand, ValueType* result_type,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value(value);
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result, result_operand,
result_type, op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag,
const Slice& entity, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result, Slice* result_operand, ValueType* result_type,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value;
Slice entity_copy(entity);
WideColumns existing_columns;
const Status s =
WideColumnSerialization::Deserialize(entity_copy, existing_columns);
if (!s.ok()) {
return s;
}
existing_value = std::move(existing_columns);
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result, result_operand,
result_type, op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag,
const WideColumns& columns, const std::vector<Slice>& operands,
Logger* logger, Statistics* statistics, SystemClock* clock,
bool update_num_ops_stats, std::string* result, Slice* result_operand,
ValueType* result_type, MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value(columns);
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result, result_operand,
result_type, op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, NoBaseValueTag,
const std::vector<Slice>& operands, Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats, std::string* result_value,
PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value;
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result_value, result_entity,
op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, PlainBaseValueTag,
const Slice& value, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result_value, PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value(value);
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result_value, result_entity,
op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag,
const Slice& entity, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result_value, PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value;
Slice entity_copy(entity);
WideColumns existing_columns;
const Status s =
WideColumnSerialization::Deserialize(entity_copy, existing_columns);
if (!s.ok()) {
return s;
}
existing_value = std::move(existing_columns);
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result_value, result_entity,
op_failure_scope);
}
Status MergeHelper::TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag,
const WideColumns& columns, const std::vector<Slice>& operands,
Logger* logger, Statistics* statistics, SystemClock* clock,
bool update_num_ops_stats, std::string* result_value,
PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope) {
MergeOperator::MergeOperationInputV3::ExistingValue existing_value(columns);
return TimedFullMergeImpl(merge_operator, key, std::move(existing_value),
operands, logger, statistics, clock,
update_num_ops_stats, result_value, result_entity,
op_failure_scope);
}
// PRE: iter points to the first merge type entry // PRE: iter points to the first merge type entry
// POST: iter points to the first entry beyond the merge process (or the end) // POST: iter points to the first entry beyond the merge process (or the end)
// keys_, operands_ are updated to reflect the merge result. // keys_, operands_ are updated to reflect the merge result.
@ -519,14 +383,14 @@ Status MergeHelper::MergeUntil(InternalIterator* iter,
s = TimedFullMerge(user_merge_operator_, ikey.user_key, kNoBaseValue, s = TimedFullMerge(user_merge_operator_, ikey.user_key, kNoBaseValue,
merge_context_.GetOperands(), logger_, stats_, merge_context_.GetOperands(), logger_, stats_,
clock_, /* update_num_ops_stats */ false, clock_, /* update_num_ops_stats */ false,
&merge_result, /* result_operand */ nullptr, &op_failure_scope, &merge_result,
&merge_result_type, &op_failure_scope); /* result_operand */ nullptr, &merge_result_type);
} else if (ikey.type == kTypeValue) { } else if (ikey.type == kTypeValue) {
s = TimedFullMerge(user_merge_operator_, ikey.user_key, kPlainBaseValue, s = TimedFullMerge(user_merge_operator_, ikey.user_key, kPlainBaseValue,
iter->value(), merge_context_.GetOperands(), logger_, iter->value(), merge_context_.GetOperands(), logger_,
stats_, clock_, /* update_num_ops_stats */ false, stats_, clock_, /* update_num_ops_stats */ false,
&merge_result, /* result_operand */ nullptr, &op_failure_scope, &merge_result,
&merge_result_type, &op_failure_scope); /* result_operand */ nullptr, &merge_result_type);
} else if (ikey.type == kTypeBlobIndex) { } else if (ikey.type == kTypeBlobIndex) {
BlobIndex blob_index; BlobIndex blob_index;
@ -559,20 +423,20 @@ Status MergeHelper::MergeUntil(InternalIterator* iter,
s = TimedFullMerge(user_merge_operator_, ikey.user_key, kPlainBaseValue, s = TimedFullMerge(user_merge_operator_, ikey.user_key, kPlainBaseValue,
blob_value, merge_context_.GetOperands(), logger_, blob_value, merge_context_.GetOperands(), logger_,
stats_, clock_, /* update_num_ops_stats */ false, stats_, clock_, /* update_num_ops_stats */ false,
&merge_result, /* result_operand */ nullptr, &op_failure_scope, &merge_result,
&merge_result_type, &op_failure_scope); /* result_operand */ nullptr, &merge_result_type);
} else if (ikey.type == kTypeWideColumnEntity) { } else if (ikey.type == kTypeWideColumnEntity) {
s = TimedFullMerge(user_merge_operator_, ikey.user_key, kWideBaseValue, s = TimedFullMerge(user_merge_operator_, ikey.user_key, kWideBaseValue,
iter->value(), merge_context_.GetOperands(), logger_, iter->value(), merge_context_.GetOperands(), logger_,
stats_, clock_, /* update_num_ops_stats */ false, stats_, clock_, /* update_num_ops_stats */ false,
&merge_result, /* result_operand */ nullptr, &op_failure_scope, &merge_result,
&merge_result_type, &op_failure_scope); /* result_operand */ nullptr, &merge_result_type);
} else { } else {
s = TimedFullMerge(user_merge_operator_, ikey.user_key, kNoBaseValue, s = TimedFullMerge(user_merge_operator_, ikey.user_key, kNoBaseValue,
merge_context_.GetOperands(), logger_, stats_, merge_context_.GetOperands(), logger_, stats_,
clock_, /* update_num_ops_stats */ false, clock_, /* update_num_ops_stats */ false,
&merge_result, /* result_operand */ nullptr, &op_failure_scope, &merge_result,
&merge_result_type, &op_failure_scope); /* result_operand */ nullptr, &merge_result_type);
} }
// We store the result in keys_.back() and operands_.back() // We store the result in keys_.back() and operands_.back()
@ -714,9 +578,9 @@ Status MergeHelper::MergeUntil(InternalIterator* iter,
MergeOperator::OpFailureScope op_failure_scope; MergeOperator::OpFailureScope op_failure_scope;
s = TimedFullMerge(user_merge_operator_, orig_ikey.user_key, kNoBaseValue, s = TimedFullMerge(user_merge_operator_, orig_ikey.user_key, kNoBaseValue,
merge_context_.GetOperands(), logger_, stats_, clock_, merge_context_.GetOperands(), logger_, stats_, clock_,
/* update_num_ops_stats */ false, &merge_result, /* update_num_ops_stats */ false, &op_failure_scope,
/* result_operand */ nullptr, &merge_result_type, &merge_result,
&op_failure_scope); /* result_operand */ nullptr, &merge_result_type);
if (s.ok()) { if (s.ok()) {
// The original key encountered // The original key encountered
// We are certain that keys_ is not empty here (see assertions couple of // We are certain that keys_ is not empty here (see assertions couple of

View File

@ -12,6 +12,7 @@
#include "db/merge_context.h" #include "db/merge_context.h"
#include "db/range_del_aggregator.h" #include "db/range_del_aggregator.h"
#include "db/snapshot_checker.h" #include "db/snapshot_checker.h"
#include "db/wide/wide_column_serialization.h"
#include "rocksdb/compaction_filter.h" #include "rocksdb/compaction_filter.h"
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/merge_operator.h" #include "rocksdb/merge_operator.h"
@ -60,74 +61,73 @@ class MergeHelper {
struct WideBaseValueTag {}; struct WideBaseValueTag {};
static constexpr WideBaseValueTag kWideBaseValue{}; static constexpr WideBaseValueTag kWideBaseValue{};
// Variants that expose the merge result directly (in serialized form for wide template <typename... ResultTs>
// columns) as well as its value type. Used by iterator and compaction.
static Status TimedFullMerge(const MergeOperator* merge_operator, static Status TimedFullMerge(const MergeOperator* merge_operator,
const Slice& key, NoBaseValueTag, const Slice& key, NoBaseValueTag,
const std::vector<Slice>& operands, const std::vector<Slice>& operands,
Logger* logger, Statistics* statistics, Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats, SystemClock* clock, bool update_num_ops_stats,
std::string* result, Slice* result_operand, MergeOperator::OpFailureScope* op_failure_scope,
ValueType* result_type, ResultTs... results) {
MergeOperator::OpFailureScope* op_failure_scope); MergeOperator::MergeOperationInputV3::ExistingValue existing_value;
return TimedFullMergeImpl(
merge_operator, key, std::move(existing_value), operands, logger,
statistics, clock, update_num_ops_stats, op_failure_scope, results...);
}
template <typename... ResultTs>
static Status TimedFullMerge( static Status TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, PlainBaseValueTag, const MergeOperator* merge_operator, const Slice& key, PlainBaseValueTag,
const Slice& value, const std::vector<Slice>& operands, Logger* logger, const Slice& value, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats, Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result, Slice* result_operand, ValueType* result_type, MergeOperator::OpFailureScope* op_failure_scope, ResultTs... results) {
MergeOperator::OpFailureScope* op_failure_scope); MergeOperator::MergeOperationInputV3::ExistingValue existing_value(value);
return TimedFullMergeImpl(
merge_operator, key, std::move(existing_value), operands, logger,
statistics, clock, update_num_ops_stats, op_failure_scope, results...);
}
template <typename... ResultTs>
static Status TimedFullMerge( static Status TimedFullMerge(
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag, const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag,
const Slice& entity, const std::vector<Slice>& operands, Logger* logger, const Slice& entity, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats, Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result, Slice* result_operand, ValueType* result_type, MergeOperator::OpFailureScope* op_failure_scope, ResultTs... results) {
MergeOperator::OpFailureScope* op_failure_scope); MergeOperator::MergeOperationInputV3::ExistingValue existing_value;
static Status TimedFullMerge( Slice entity_copy(entity);
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag, WideColumns existing_columns;
const WideColumns& columns, const std::vector<Slice>& operands,
Logger* logger, Statistics* statistics, SystemClock* clock,
bool update_num_ops_stats, std::string* result, Slice* result_operand,
ValueType* result_type, MergeOperator::OpFailureScope* op_failure_scope);
// Variants that expose the merge result translated to the form requested by const Status s =
// the client. (For example, if the result is a wide-column structure but the WideColumnSerialization::Deserialize(entity_copy, existing_columns);
// client requested the results in plain-value form, the value of the default if (!s.ok()) {
// column is returned.) Used by point lookups. return s;
static Status TimedFullMerge(const MergeOperator* merge_operator, }
const Slice& key, NoBaseValueTag,
const std::vector<Slice>& operands,
Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats,
std::string* result_value,
PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope);
static Status TimedFullMerge( existing_value = std::move(existing_columns);
const MergeOperator* merge_operator, const Slice& key, PlainBaseValueTag,
const Slice& value, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result_value, PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope);
static Status TimedFullMerge( return TimedFullMergeImpl(
const MergeOperator* merge_operator, const Slice& key, WideBaseValueTag, merge_operator, key, std::move(existing_value), operands, logger,
const Slice& entity, const std::vector<Slice>& operands, Logger* logger, statistics, clock, update_num_ops_stats, op_failure_scope, results...);
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats, }
std::string* result_value, PinnableWideColumns* result_entity,
MergeOperator::OpFailureScope* op_failure_scope);
template <typename... ResultTs>
static Status TimedFullMerge(const MergeOperator* merge_operator, static Status TimedFullMerge(const MergeOperator* merge_operator,
const Slice& key, WideBaseValueTag, const Slice& key, WideBaseValueTag,
const WideColumns& columns, const WideColumns& columns,
const std::vector<Slice>& operands, const std::vector<Slice>& operands,
Logger* logger, Statistics* statistics, Logger* logger, Statistics* statistics,
SystemClock* clock, bool update_num_ops_stats, SystemClock* clock, bool update_num_ops_stats,
std::string* result_value, MergeOperator::OpFailureScope* op_failure_scope,
PinnableWideColumns* result_entity, ResultTs... results) {
MergeOperator::OpFailureScope* op_failure_scope); MergeOperator::MergeOperationInputV3::ExistingValue existing_value(columns);
return TimedFullMergeImpl(
merge_operator, key, std::move(existing_value), operands, logger,
statistics, clock, update_num_ops_stats, op_failure_scope, results...);
}
// During compaction, merge entries until we hit // During compaction, merge entries until we hit
// - a corrupted key // - a corrupted key
@ -271,21 +271,27 @@ class MergeHelper {
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats, Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
MergeOperator::OpFailureScope* op_failure_scope, Visitor&& visitor); MergeOperator::OpFailureScope* op_failure_scope, Visitor&& visitor);
// Variant that exposes the merge result directly (in serialized form for wide
// columns) as well as its value type. Used by iterator and compaction.
static Status TimedFullMergeImpl( static Status TimedFullMergeImpl(
const MergeOperator* merge_operator, const Slice& key, const MergeOperator* merge_operator, const Slice& key,
MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value, MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value,
const std::vector<Slice>& operands, Logger* logger, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats, Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result, Slice* result_operand, ValueType* result_type, MergeOperator::OpFailureScope* op_failure_scope, std::string* result,
MergeOperator::OpFailureScope* op_failure_scope); Slice* result_operand, ValueType* result_type);
// Variant that exposes the merge result translated into the form requested by
// the client. (For example, if the result is a wide-column structure but the
// client requested the results in plain-value form, the value of the default
// column is returned.) Used by point lookups.
static Status TimedFullMergeImpl( static Status TimedFullMergeImpl(
const MergeOperator* merge_operator, const Slice& key, const MergeOperator* merge_operator, const Slice& key,
MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value, MergeOperator::MergeOperationInputV3::ExistingValue&& existing_value,
const std::vector<Slice>& operands, Logger* logger, const std::vector<Slice>& operands, Logger* logger,
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats, Statistics* statistics, SystemClock* clock, bool update_num_ops_stats,
std::string* result_value, PinnableWideColumns* result_entity, MergeOperator::OpFailureScope* op_failure_scope,
MergeOperator::OpFailureScope* op_failure_scope); std::string* result_value, PinnableWideColumns* result_entity);
}; };
// MergeOutputIterator can be used to iterate over the result of a merge. // MergeOutputIterator can be used to iterate over the result of a merge.

View File

@ -2536,8 +2536,8 @@ void Version::Get(const ReadOptions& read_options, const LookupKey& k,
*status = MergeHelper::TimedFullMerge( *status = MergeHelper::TimedFullMerge(
merge_operator_, user_key, MergeHelper::kNoBaseValue, merge_operator_, user_key, MergeHelper::kNoBaseValue,
merge_context->GetOperands(), info_log_, db_statistics_, clock_, merge_context->GetOperands(), info_log_, db_statistics_, clock_,
/* update_num_ops_stats */ true, value ? value->GetSelf() : nullptr, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
columns, /* op_failure_scope */ nullptr); value ? value->GetSelf() : nullptr, columns);
if (status->ok()) { if (status->ok()) {
if (LIKELY(value != nullptr)) { if (LIKELY(value != nullptr)) {
value->PinSelf(); value->PinSelf();
@ -2782,9 +2782,8 @@ void Version::MultiGet(const ReadOptions& read_options, MultiGetRange* range,
*status = MergeHelper::TimedFullMerge( *status = MergeHelper::TimedFullMerge(
merge_operator_, user_key, MergeHelper::kNoBaseValue, merge_operator_, user_key, MergeHelper::kNoBaseValue,
iter->merge_context.GetOperands(), info_log_, db_statistics_, clock_, iter->merge_context.GetOperands(), info_log_, db_statistics_, clock_,
/* update_num_ops_stats */ true, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
iter->value ? iter->value->GetSelf() : nullptr, iter->columns, iter->value ? iter->value->GetSelf() : nullptr, iter->columns);
/* op_failure_scope */ nullptr);
if (LIKELY(iter->value != nullptr)) { if (LIKELY(iter->value != nullptr)) {
iter->value->PinSelf(); iter->value->PinSelf();
range->AddValueSize(iter->value->size()); range->AddValueSize(iter->value->size());

View File

@ -2545,9 +2545,8 @@ class MemTableInserter : public WriteBatch::Handler {
WideColumnsHelper::GetDefaultColumn(columns), {value}, WideColumnsHelper::GetDefaultColumn(columns), {value},
moptions->info_log, moptions->statistics, moptions->info_log, moptions->statistics,
SystemClock::Default().get(), SystemClock::Default().get(),
/* update_num_ops_stats */ false, &new_value, /* update_num_ops_stats */ false, /* op_failure_scope */ nullptr,
/* result_operand */ nullptr, &new_value_type, &new_value, /* result_operand */ nullptr, &new_value_type);
/* op_failure_scope */ nullptr);
} else { } else {
// `op_failure_scope` (an output parameter) is not provided (set to // `op_failure_scope` (an output parameter) is not provided (set to
// nullptr) since a failure must be propagated regardless of its // nullptr) since a failure must be propagated regardless of its
@ -2556,9 +2555,8 @@ class MemTableInserter : public WriteBatch::Handler {
merge_operator, key, MergeHelper::kWideBaseValue, columns, merge_operator, key, MergeHelper::kWideBaseValue, columns,
{value}, moptions->info_log, moptions->statistics, {value}, moptions->info_log, moptions->statistics,
SystemClock::Default().get(), SystemClock::Default().get(),
/* update_num_ops_stats */ false, &new_value, /* update_num_ops_stats */ false, /* op_failure_scope */ nullptr,
/* result_operand */ nullptr, &new_value_type, &new_value, /* result_operand */ nullptr, &new_value_type);
/* op_failure_scope */ nullptr);
} }
if (!merge_status.ok()) { if (!merge_status.ok()) {

View File

@ -232,7 +232,6 @@ bool GetContext::SaveValue(const ParsedInternalKey& parsed_key,
return true; // to continue to the next seq return true; // to continue to the next seq
} }
if (seq_ != nullptr) { if (seq_ != nullptr) {
// Set the sequence number if it is uninitialized // Set the sequence number if it is uninitialized
if (*seq_ == kMaxSequenceNumber) { if (*seq_ == kMaxSequenceNumber) {
@ -496,9 +495,8 @@ void GetContext::MergeWithNoBaseValue() {
const Status s = MergeHelper::TimedFullMerge( const Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key_, MergeHelper::kNoBaseValue, merge_operator_, user_key_, MergeHelper::kNoBaseValue,
merge_context_->GetOperands(), logger_, statistics_, clock_, merge_context_->GetOperands(), logger_, statistics_, clock_,
/* update_num_ops_stats */ true, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
pinnable_val_ ? pinnable_val_->GetSelf() : nullptr, columns_, pinnable_val_ ? pinnable_val_->GetSelf() : nullptr, columns_);
/* op_failure_scope */ nullptr);
PostprocessMerge(s); PostprocessMerge(s);
} }
@ -512,9 +510,8 @@ void GetContext::MergeWithPlainBaseValue(const Slice& value) {
const Status s = MergeHelper::TimedFullMerge( const Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key_, MergeHelper::kPlainBaseValue, value, merge_operator_, user_key_, MergeHelper::kPlainBaseValue, value,
merge_context_->GetOperands(), logger_, statistics_, clock_, merge_context_->GetOperands(), logger_, statistics_, clock_,
/* update_num_ops_stats */ true, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
pinnable_val_ ? pinnable_val_->GetSelf() : nullptr, columns_, pinnable_val_ ? pinnable_val_->GetSelf() : nullptr, columns_);
/* op_failure_scope */ nullptr);
PostprocessMerge(s); PostprocessMerge(s);
} }
@ -528,9 +525,8 @@ void GetContext::MergeWithWideColumnBaseValue(const Slice& entity) {
const Status s = MergeHelper::TimedFullMerge( const Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key_, MergeHelper::kWideBaseValue, entity, merge_operator_, user_key_, MergeHelper::kWideBaseValue, entity,
merge_context_->GetOperands(), logger_, statistics_, clock_, merge_context_->GetOperands(), logger_, statistics_, clock_,
/* update_num_ops_stats */ true, /* update_num_ops_stats */ true, /* op_failure_scope */ nullptr,
pinnable_val_ ? pinnable_val_->GetSelf() : nullptr, columns_, pinnable_val_ ? pinnable_val_->GetSelf() : nullptr, columns_);
/* op_failure_scope */ nullptr);
PostprocessMerge(s); PostprocessMerge(s);
} }

View File

@ -408,8 +408,8 @@ class WriteBatchWithIndexInternal {
return MergeHelper::TimedFullMerge( return MergeHelper::TimedFullMerge(
ioptions->merge_operator.get(), key, MergeHelper::kNoBaseValue, ioptions->merge_operator.get(), key, MergeHelper::kNoBaseValue,
context.GetOperands(), ioptions->logger, ioptions->stats, context.GetOperands(), ioptions->logger, ioptions->stats,
ioptions->clock, /* update_num_ops_stats */ false, results..., ioptions->clock, /* update_num_ops_stats */ false,
/* op_failure_scope */ nullptr); /* op_failure_scope */ nullptr, results...);
} }
template <typename BaseTag, typename BaseT, typename... ResultTs> template <typename BaseTag, typename BaseT, typename... ResultTs>
@ -432,8 +432,8 @@ class WriteBatchWithIndexInternal {
return MergeHelper::TimedFullMerge( return MergeHelper::TimedFullMerge(
ioptions->merge_operator.get(), key, base_tag, value, ioptions->merge_operator.get(), key, base_tag, value,
context.GetOperands(), ioptions->logger, ioptions->stats, context.GetOperands(), ioptions->logger, ioptions->stats,
ioptions->clock, /* update_num_ops_stats */ false, results..., ioptions->clock, /* update_num_ops_stats */ false,
/* op_failure_scope */ nullptr); /* op_failure_scope */ nullptr, results...);
} }
// If batch contains a value for key, store it in *value and return kFound. // If batch contains a value for key, store it in *value and return kFound.