Skip to content

Commit

Permalink
Support Merge for wide-column entities during point lookups (facebook…
Browse files Browse the repository at this point in the history
…#10916)

Summary:
The patch adds `Merge` support for wide-column entities to the point lookup
APIs, i.e. `Get`, `MultiGet`, `GetEntity`, and `GetMergeOperands`. (I plan to
update the iterator and compaction logic in separate PRs.) In terms of semantics,
the `Merge` operation is applied to the default (anonymous) column; any other
columns in the entity are unaffected.

Pull Request resolved: facebook#10916

Test Plan: `make check`

Reviewed By: riversand963

Differential Revision: D40962311

Pulled By: ltamasi

fbshipit-source-id: 244bc9d172be1af2f204796b2f89104e4d2fa373
  • Loading branch information
ltamasi authored and facebook-github-bot committed Nov 3, 2022
1 parent cc8c8f6 commit 941d834
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 93 deletions.
38 changes: 23 additions & 15 deletions db/memtable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1090,20 +1090,6 @@ static bool SaveValue(void* arg, const char* entry) {
return false;
}
case kTypeWideColumnEntity: {
if (!s->do_merge) {
*(s->status) = Status::NotSupported(
"GetMergeOperands not supported for wide-column entities");
*(s->found_final_value) = true;
return false;
}

if (*(s->merge_in_progress)) {
*(s->status) = Status::NotSupported(
"Merge not supported for wide-column entities");
*(s->found_final_value) = true;
return false;
}

if (s->inplace_update_support) {
s->mem->GetLock(s->key->user_key())->ReadLock();
}
Expand All @@ -1112,7 +1098,29 @@ static bool SaveValue(void* arg, const char* entry) {

*(s->status) = Status::OK();

if (s->value) {
if (!s->do_merge) {
// Preserve the value with the goal of returning it as part of
// raw merge operands to the user

Slice value_of_default;
*(s->status) = WideColumnSerialization::GetValueOfDefaultColumn(
v, value_of_default);

if (s->status->ok()) {
merge_context->PushOperand(
value_of_default,
s->inplace_update_support == false /* operand_pinned */);
}
} else if (*(s->merge_in_progress)) {
assert(s->do_merge);

if (s->value || s->columns) {
*(s->status) = MergeHelper::TimedFullMergeWithEntity(
merge_operator, s->key->user_key(), v,
merge_context->GetOperands(), s->value, s->columns, s->logger,
s->statistics, s->clock, nullptr /* result_operand */, true);
}
} else if (s->value) {
Slice value_of_default;
*(s->status) = WideColumnSerialization::GetValueOfDefaultColumn(
v, value_of_default);
Expand Down
65 changes: 65 additions & 0 deletions db/merge_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "db/blob/prefetch_buffer_collection.h"
#include "db/compaction/compaction_iteration_stats.h"
#include "db/dbformat.h"
#include "db/wide/wide_column_serialization.h"
#include "monitoring/perf_context_imp.h"
#include "monitoring/statistics.h"
#include "port/likely.h"
Expand Down Expand Up @@ -140,6 +141,70 @@ Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
return Status::OK();
}

Status MergeHelper::TimedFullMergeWithEntity(
const MergeOperator* merge_operator, const Slice& key, Slice base_entity,
const std::vector<Slice>& operands, std::string* value,
PinnableWideColumns* columns, Logger* logger, Statistics* statistics,
SystemClock* clock, Slice* result_operand, bool update_num_ops_stats) {
assert(value || columns);
assert(!value || !columns);

WideColumns base_columns;

{
const Status s =
WideColumnSerialization::Deserialize(base_entity, base_columns);
if (!s.ok()) {
return s;
}
}

const bool has_default_column =
!base_columns.empty() && base_columns[0].name() == kDefaultWideColumnName;

Slice value_of_default;
if (has_default_column) {
value_of_default = base_columns[0].value();
}

std::string result;

{
const Status s = TimedFullMerge(
merge_operator, key, &value_of_default, operands, &result, logger,
statistics, clock, result_operand, update_num_ops_stats);
if (!s.ok()) {
return s;
}
}

if (value) {
*value = std::move(result);
return Status::OK();
}

assert(columns);

std::string output;

if (has_default_column) {
base_columns[0].value() = result;

const Status s = WideColumnSerialization::Serialize(base_columns, output);
if (!s.ok()) {
return s;
}
} else {
const Status s =
WideColumnSerialization::Serialize(result, base_columns, output);
if (!s.ok()) {
return s;
}
}

return columns->SetWideColumnValue(output);
}

// PRE: iter points to the first merge type entry
// POST: iter points to the first entry beyond the merge process (or the end)
// keys_, operands_ are updated to reflect the merge result.
Expand Down
8 changes: 8 additions & 0 deletions db/merge_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "rocksdb/env.h"
#include "rocksdb/merge_operator.h"
#include "rocksdb/slice.h"
#include "rocksdb/wide_columns.h"
#include "util/stop_watch.h"

namespace ROCKSDB_NAMESPACE {
Expand Down Expand Up @@ -65,6 +66,13 @@ class MergeHelper {
Slice* result_operand = nullptr,
bool update_num_ops_stats = false);

static Status TimedFullMergeWithEntity(
const MergeOperator* merge_operator, const Slice& key, Slice base_entity,
const std::vector<Slice>& operands, std::string* value,
PinnableWideColumns* columns, Logger* logger, Statistics* statistics,
SystemClock* clock, Slice* result_operand = nullptr,
bool update_num_ops_stats = false);

// During compaction, merge entries until we hit
// - a corrupted key
// - a Put/Delete,
Expand Down
4 changes: 0 additions & 4 deletions db/version_set.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2366,10 +2366,6 @@ void Version::Get(const ReadOptions& read_options, const LookupKey& k,
"Encounter unexpected blob index. Please open DB with "
"ROCKSDB_NAMESPACE::blob_db::BlobDB instead.");
return;
case GetContext::kUnexpectedWideColumnEntity:
*status =
Status::NotSupported("Encountered unexpected wide-column entity");
return;
}
f = fp.GetNextFile();
}
Expand Down
5 changes: 0 additions & 5 deletions db/version_set_sync_and_async.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,6 @@ DEFINE_SYNC_AND_ASYNC(Status, Version::MultiGetFromSST)
"ROCKSDB_NAMESPACE::blob_db::BlobDB instead.");
file_range.MarkKeyDone(iter);
continue;
case GetContext::kUnexpectedWideColumnEntity:
*status =
Status::NotSupported("Encountered unexpected wide-column entity");
file_range.MarkKeyDone(iter);
continue;
}
}

Expand Down
Loading

0 comments on commit 941d834

Please sign in to comment.