1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #include <memory>
7 #include "rocksdb/slice.h"
8 #include "rocksdb/merge_operator.h"
9 #include "utilities/merge_operators.h"
10 
11 using namespace ROCKSDB_NAMESPACE;
12 
13 namespace { // anonymous namespace
14 
15 // A merge operator that mimics Put semantics
16 // Since this merge-operator will not be used in production,
17 // it is implemented as a non-associative merge operator to illustrate the
18 // new interface and for testing purposes. (That is, we inherit from
19 // the MergeOperator class rather than the AssociativeMergeOperator
20 // which would be simpler in this case).
21 //
22 // From the client-perspective, semantics are the same.
23 class PutOperator : public MergeOperator {
24  public:
FullMerge(const Slice &,const Slice *,const std::deque<std::string> & operand_sequence,std::string * new_value,Logger *) const25   bool FullMerge(const Slice& /*key*/, const Slice* /*existing_value*/,
26                  const std::deque<std::string>& operand_sequence,
27                  std::string* new_value, Logger* /*logger*/) const override {
28     // Put basically only looks at the current/latest value
29     assert(!operand_sequence.empty());
30     assert(new_value != nullptr);
31     new_value->assign(operand_sequence.back());
32     return true;
33   }
34 
PartialMerge(const Slice &,const Slice &,const Slice & right_operand,std::string * new_value,Logger *) const35   bool PartialMerge(const Slice& /*key*/, const Slice& /*left_operand*/,
36                     const Slice& right_operand, std::string* new_value,
37                     Logger* /*logger*/) const override {
38     new_value->assign(right_operand.data(), right_operand.size());
39     return true;
40   }
41 
42   using MergeOperator::PartialMergeMulti;
PartialMergeMulti(const Slice &,const std::deque<Slice> & operand_list,std::string * new_value,Logger *) const43   bool PartialMergeMulti(const Slice& /*key*/,
44                          const std::deque<Slice>& operand_list,
45                          std::string* new_value,
46                          Logger* /*logger*/) const override {
47     new_value->assign(operand_list.back().data(), operand_list.back().size());
48     return true;
49   }
50 
Name() const51   const char* Name() const override { return "PutOperator"; }
52 };
53 
54 class PutOperatorV2 : public PutOperator {
FullMerge(const Slice &,const Slice *,const std::deque<std::string> &,std::string *,Logger *) const55   bool FullMerge(const Slice& /*key*/, const Slice* /*existing_value*/,
56                  const std::deque<std::string>& /*operand_sequence*/,
57                  std::string* /*new_value*/,
58                  Logger* /*logger*/) const override {
59     assert(false);
60     return false;
61   }
62 
FullMergeV2(const MergeOperationInput & merge_in,MergeOperationOutput * merge_out) const63   bool FullMergeV2(const MergeOperationInput& merge_in,
64                    MergeOperationOutput* merge_out) const override {
65     // Put basically only looks at the current/latest value
66     assert(!merge_in.operand_list.empty());
67     merge_out->existing_operand = merge_in.operand_list.back();
68     return true;
69   }
70 };
71 
72 } // end of anonymous namespace
73 
74 namespace ROCKSDB_NAMESPACE {
75 
CreateDeprecatedPutOperator()76 std::shared_ptr<MergeOperator> MergeOperators::CreateDeprecatedPutOperator() {
77   return std::make_shared<PutOperator>();
78 }
79 
CreatePutOperator()80 std::shared_ptr<MergeOperator> MergeOperators::CreatePutOperator() {
81   return std::make_shared<PutOperatorV2>();
82 }
83 }  // namespace ROCKSDB_NAMESPACE
84