]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /** |
2 | * @author Deon Nicholas (dnicholas@fb.com) | |
3 | * Copyright 2013 Facebook | |
4 | */ | |
5 | ||
6 | #include "stringappend2.h" | |
7 | ||
8 | #include <memory> | |
9 | #include <string> | |
10 | #include <assert.h> | |
11 | ||
12 | #include "rocksdb/slice.h" | |
13 | #include "rocksdb/merge_operator.h" | |
14 | #include "utilities/merge_operators.h" | |
15 | ||
16 | namespace rocksdb { | |
17 | ||
18 | // Constructor: also specify the delimiter character. | |
19 | StringAppendTESTOperator::StringAppendTESTOperator(char delim_char) | |
20 | : delim_(delim_char) { | |
21 | } | |
22 | ||
23 | // Implementation for the merge operation (concatenates two strings) | |
24 | bool StringAppendTESTOperator::FullMergeV2( | |
25 | const MergeOperationInput& merge_in, | |
26 | MergeOperationOutput* merge_out) const { | |
27 | // Clear the *new_value for writing. | |
28 | merge_out->new_value.clear(); | |
29 | ||
30 | if (merge_in.existing_value == nullptr && merge_in.operand_list.size() == 1) { | |
31 | // Only one operand | |
32 | merge_out->existing_operand = merge_in.operand_list.back(); | |
33 | return true; | |
34 | } | |
35 | ||
36 | // Compute the space needed for the final result. | |
37 | size_t numBytes = 0; | |
38 | for (auto it = merge_in.operand_list.begin(); | |
39 | it != merge_in.operand_list.end(); ++it) { | |
40 | numBytes += it->size() + 1; // Plus 1 for the delimiter | |
41 | } | |
42 | ||
43 | // Only print the delimiter after the first entry has been printed | |
44 | bool printDelim = false; | |
45 | ||
46 | // Prepend the *existing_value if one exists. | |
47 | if (merge_in.existing_value) { | |
48 | merge_out->new_value.reserve(numBytes + merge_in.existing_value->size()); | |
49 | merge_out->new_value.append(merge_in.existing_value->data(), | |
50 | merge_in.existing_value->size()); | |
51 | printDelim = true; | |
52 | } else if (numBytes) { | |
53 | merge_out->new_value.reserve( | |
54 | numBytes - 1); // Minus 1 since we have one less delimiter | |
55 | } | |
56 | ||
57 | // Concatenate the sequence of strings (and add a delimiter between each) | |
58 | for (auto it = merge_in.operand_list.begin(); | |
59 | it != merge_in.operand_list.end(); ++it) { | |
60 | if (printDelim) { | |
61 | merge_out->new_value.append(1, delim_); | |
62 | } | |
63 | merge_out->new_value.append(it->data(), it->size()); | |
64 | printDelim = true; | |
65 | } | |
66 | ||
67 | return true; | |
68 | } | |
69 | ||
70 | bool StringAppendTESTOperator::PartialMergeMulti( | |
11fdf7f2 TL |
71 | const Slice& /*key*/, const std::deque<Slice>& /*operand_list*/, |
72 | std::string* /*new_value*/, Logger* /*logger*/) const { | |
7c673cae FG |
73 | return false; |
74 | } | |
75 | ||
76 | // A version of PartialMerge that actually performs "partial merging". | |
77 | // Use this to simulate the exact behaviour of the StringAppendOperator. | |
78 | bool StringAppendTESTOperator::_AssocPartialMergeMulti( | |
11fdf7f2 TL |
79 | const Slice& /*key*/, const std::deque<Slice>& operand_list, |
80 | std::string* new_value, Logger* /*logger*/) const { | |
7c673cae FG |
81 | // Clear the *new_value for writing |
82 | assert(new_value); | |
83 | new_value->clear(); | |
84 | assert(operand_list.size() >= 2); | |
85 | ||
86 | // Generic append | |
87 | // Determine and reserve correct size for *new_value. | |
88 | size_t size = 0; | |
89 | for (const auto& operand : operand_list) { | |
90 | size += operand.size(); | |
91 | } | |
92 | size += operand_list.size() - 1; // Delimiters | |
93 | new_value->reserve(size); | |
94 | ||
95 | // Apply concatenation | |
96 | new_value->assign(operand_list.front().data(), operand_list.front().size()); | |
97 | ||
98 | for (std::deque<Slice>::const_iterator it = operand_list.begin() + 1; | |
99 | it != operand_list.end(); ++it) { | |
100 | new_value->append(1, delim_); | |
101 | new_value->append(it->data(), it->size()); | |
102 | } | |
103 | ||
104 | return true; | |
105 | } | |
106 | ||
107 | const char* StringAppendTESTOperator::Name() const { | |
108 | return "StringAppendTESTOperator"; | |
109 | } | |
110 | ||
111 | ||
112 | std::shared_ptr<MergeOperator> | |
113 | MergeOperators::CreateStringAppendTESTOperator() { | |
114 | return std::make_shared<StringAppendTESTOperator>(','); | |
115 | } | |
116 | ||
117 | } // namespace rocksdb |