Coverage Report

Created: 2024-07-27 06:53

/src/rocksdb/db/merge_context.h
Line
Count
Source (jump to first uncovered line)
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
#pragma once
7
#include <algorithm>
8
#include <memory>
9
#include <string>
10
#include <vector>
11
12
#include "rocksdb/db.h"
13
#include "rocksdb/slice.h"
14
15
namespace ROCKSDB_NAMESPACE {
16
17
const std::vector<Slice> empty_operand_list;
18
19
// The merge context for merging a user key.
20
// When doing a Get(), DB will create such a class and pass it when
21
// issuing Get() operation to memtables and version_set. The operands
22
// will be fetched from the context when issuing partial of full merge.
23
class MergeContext {
24
 public:
25
  GetMergeOperandsOptions* get_merge_operands_options = nullptr;
26
27
  // Clear all the operands
28
0
  void Clear() {
29
0
    if (operand_list_) {
30
0
      operand_list_->clear();
31
0
      copied_operands_->clear();
32
0
    }
33
0
  }
34
35
  // Push a merge operand
36
0
  void PushOperand(const Slice& operand_slice, bool operand_pinned = false) {
37
0
    Initialize();
38
0
    SetDirectionBackward();
39
40
0
    if (operand_pinned) {
41
0
      operand_list_->push_back(operand_slice);
42
0
    } else {
43
      // We need to have our own copy of the operand since it's not pinned
44
0
      copied_operands_->emplace_back(
45
0
          new std::string(operand_slice.data(), operand_slice.size()));
46
0
      operand_list_->push_back(*copied_operands_->back());
47
0
    }
48
0
  }
49
50
  // Push back a merge operand
51
  void PushOperandBack(const Slice& operand_slice,
52
0
                       bool operand_pinned = false) {
53
0
    Initialize();
54
0
    SetDirectionForward();
55
56
0
    if (operand_pinned) {
57
0
      operand_list_->push_back(operand_slice);
58
0
    } else {
59
      // We need to have our own copy of the operand since it's not pinned
60
0
      copied_operands_->emplace_back(
61
0
          new std::string(operand_slice.data(), operand_slice.size()));
62
0
      operand_list_->push_back(*copied_operands_->back());
63
0
    }
64
0
  }
65
66
  // return total number of operands in the list
67
0
  size_t GetNumOperands() const {
68
0
    if (!operand_list_) {
69
0
      return 0;
70
0
    }
71
0
    return operand_list_->size();
72
0
  }
73
74
  // Get the operand at the index.
75
0
  Slice GetOperand(int index) const {
76
0
    assert(operand_list_);
77
0
78
0
    SetDirectionForward();
79
0
    return (*operand_list_)[index];
80
0
  }
81
82
  // Same as GetOperandsDirectionForward
83
  //
84
  // Note that the returned reference is only good until another call
85
  // to this MergeContext.  If the returned value is needed for longer,
86
  // a copy must be made.
87
4.48k
  const std::vector<Slice>& GetOperands() const {
88
4.48k
    return GetOperandsDirectionForward();
89
4.48k
  }
90
91
  // Return all the operands in the order as they were merged (passed to
92
  // FullMerge or FullMergeV2)
93
  //
94
  // Note that the returned reference is only good until another call
95
  // to this MergeContext.  If the returned value is needed for longer,
96
  // a copy must be made.
97
4.48k
  const std::vector<Slice>& GetOperandsDirectionForward() const {
98
4.48k
    if (!operand_list_) {
99
4.48k
      return empty_operand_list;
100
4.48k
    }
101
102
0
    SetDirectionForward();
103
0
    return *operand_list_;
104
4.48k
  }
105
106
  // Return all the operands in the reversed order relative to how they were
107
  // merged (passed to FullMerge or FullMergeV2)
108
  //
109
  // Note that the returned reference is only good until another call
110
  // to this MergeContext.  If the returned value is needed for longer,
111
  // a copy must be made.
112
0
  const std::vector<Slice>& GetOperandsDirectionBackward() const {
113
0
    if (!operand_list_) {
114
0
      return empty_operand_list;
115
0
    }
116
117
0
    SetDirectionBackward();
118
0
    return *operand_list_;
119
0
  }
120
121
 private:
122
0
  void Initialize() {
123
0
    if (!operand_list_) {
124
0
      operand_list_.reset(new std::vector<Slice>());
125
0
      copied_operands_.reset(new std::vector<std::unique_ptr<std::string>>());
126
0
    }
127
0
  }
128
129
0
  void SetDirectionForward() const {
130
0
    if (operands_reversed_ == true) {
131
0
      std::reverse(operand_list_->begin(), operand_list_->end());
132
0
      operands_reversed_ = false;
133
0
    }
134
0
  }
135
136
0
  void SetDirectionBackward() const {
137
0
    if (operands_reversed_ == false) {
138
0
      std::reverse(operand_list_->begin(), operand_list_->end());
139
0
      operands_reversed_ = true;
140
0
    }
141
0
  }
142
143
  // List of operands
144
  mutable std::unique_ptr<std::vector<Slice>> operand_list_;
145
  // Copy of operands that are not pinned.
146
  std::unique_ptr<std::vector<std::unique_ptr<std::string>>> copied_operands_;
147
  mutable bool operands_reversed_ = true;
148
};
149
150
}  // namespace ROCKSDB_NAMESPACE