YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/rocksdb/metadata.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 the BSD-style license found in the
3
// LICENSE file in the root directory of this source tree. An additional grant
4
// of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
21
#ifndef YB_ROCKSDB_METADATA_H
22
#define YB_ROCKSDB_METADATA_H
23
24
#include <stdint.h>
25
26
#include <limits>
27
#include <string>
28
#include <vector>
29
30
#include <boost/container/small_vector.hpp>
31
32
#include "yb/common/hybrid_time.h"
33
34
#include "yb/gutil/casts.h"
35
36
#include "yb/util/clone_ptr.h"
37
#include "yb/util/slice.h"
38
#include "yb/util/enums.h"
39
40
#include "yb/rocksdb/types.h"
41
42
namespace google { namespace protobuf {
43
class Any;
44
}
45
}
46
47
namespace yb {
48
class OpIdPB;
49
}
50
51
namespace rocksdb {
52
struct ColumnFamilyMetaData;
53
struct LevelMetaData;
54
struct SstFileMetaData;
55
56
// The metadata that describes a column family.
57
struct ColumnFamilyMetaData {
58
470
  ColumnFamilyMetaData() : size(0), name("") {}
59
  ColumnFamilyMetaData(const std::string& _name, uint64_t _size,
60
                       const std::vector<LevelMetaData>&& _levels)
61
      : size(_size),
62
        name(_name),
63
0
        levels(_levels) {}
64
65
  // The size of this column family in bytes, which is equal to the sum of
66
  // the file size of its "levels".
67
  uint64_t size = 0;
68
  // The number of files in this column family.
69
  size_t file_count = 0;
70
  // The name of the column family.
71
  std::string name;
72
  // The metadata of all levels in this column family.
73
  std::vector<LevelMetaData> levels;
74
};
75
76
// The metadata that describes a level.
77
struct LevelMetaData {
78
  LevelMetaData(int _level, uint64_t _size,
79
                const std::vector<SstFileMetaData>&& _files)
80
      : level(_level),
81
        size(_size),
82
2.20k
        files(_files) {}
83
84
  // The level which this meta data describes.
85
  const int level = 0;
86
  // The size of this level in bytes, which is equal to the sum of
87
  // the file size of its "files".
88
  const uint64_t size = 0;
89
  // The metadata of all sst files in this level.
90
  const std::vector<SstFileMetaData> files;
91
};
92
93
class UserFrontier;
94
95
// Frontier should be copyable, but should still preserve its polymorphic nature. We cannot use
96
// shared_ptr here, because we are planning to modify the copied value. If we used shared_ptr and
97
// modified the copied value, the original value would also change.
98
typedef yb::clone_ptr<UserFrontier> UserFrontierPtr;
99
100
void UpdateUserFrontier(UserFrontierPtr* value, const UserFrontierPtr& update,
101
                        UpdateUserValueType type);
102
void UpdateUserFrontier(UserFrontierPtr* value, UserFrontierPtr&& update,
103
                        UpdateUserValueType type);
104
105
// When writing a batch of RocksDB records, the user could specify "frontier" values of that batch,
106
// such as smallest/largest Raft OpId or smallest/largest HybridTime of records in that batch. We
107
// maintain these values for each SSTable file and whole DB. This class defines an abstract
108
// interface for a single user frontier, i.e. only smallest values or only largest values, but all
109
// types of these values together as a tuple (e.g. OpId / hybrid time / etc.) See
110
// consensus_frontier.h for a concrete example.
111
class UserFrontier {
112
 public:
113
  virtual std::unique_ptr<UserFrontier> Clone() const = 0;
114
  virtual std::string ToString() const = 0;
115
  virtual void ToPB(google::protobuf::Any* pb) const = 0;
116
  virtual bool Equals(const UserFrontier& rhs) const = 0;
117
118
  // Updates the user frontier with the new values from rhs.
119
  virtual void Update(const UserFrontier& rhs, UpdateUserValueType type) = 0;
120
121
  // Checks if the given update is valid, i.e. that it does not move the fields of the frontier
122
  // (such as OpId / hybrid time) in the direction opposite to that indicated by
123
  // UpdateUserValueType. A "largest" update should only increase fields, and a "smallest" should
124
  // only decrease them. Fields that are not set in rhs are not checked.
125
  virtual bool IsUpdateValid(const UserFrontier& rhs, UpdateUserValueType type) const = 0;
126
127
  // Should return value that will be passed to iterator replacer.
128
  virtual Slice Filter() const = 0;
129
130
  // Returns true if this frontier dominates another frontier, i.e. if we update this frontier
131
  // with the values from the other one in the direction specified by update_type, nothing will
132
  // change. This is used to check invariants.
133
  bool Dominates(const UserFrontier& rhs, UpdateUserValueType update_type) const;
134
135
  virtual void FromOpIdPBDeprecated(const yb::OpIdPB& op_id) = 0;
136
  virtual void FromPB(const google::protobuf::Any& pb) = 0;
137
138
35.4M
  virtual ~UserFrontier() {}
139
140
  static void Update(const UserFrontier* rhs, UpdateUserValueType type, UserFrontierPtr* out);
141
};
142
143
8
inline bool operator==(const UserFrontier& lhs, const UserFrontier& rhs) {
144
8
  return lhs.Equals(rhs);
145
8
}
146
147
0
inline bool operator!=(const UserFrontier& lhs, const UserFrontier& rhs) {
148
0
  return !lhs.Equals(rhs);
149
0
}
150
151
6
inline std::ostream& operator<<(std::ostream& out, const UserFrontier& frontier) {
152
6
  return out << frontier.ToString();
153
6
}
154
155
// Abstract interface to a pair of user defined frontiers - smallest and largest.
156
class UserFrontiers {
157
 public:
158
  virtual std::unique_ptr<UserFrontiers> Clone() const = 0;
159
  std::string ToString() const;
160
  virtual const UserFrontier& Smallest() const = 0;
161
  virtual const UserFrontier& Largest() const = 0;
162
163
  virtual void MergeFrontiers(const UserFrontiers& rhs) = 0;
164
165
12.6M
  virtual ~UserFrontiers() {}
166
};
167
168
template<class Frontier>
169
class UserFrontiersBase : public rocksdb::UserFrontiers {
170
 public:
171
11.7k
  const rocksdb::UserFrontier& Smallest() const override { return smallest_; }
172
2.49M
  const rocksdb::UserFrontier& Largest() const override { return largest_; }
173
174
23.6M
  Frontier& Smallest() { return smallest_; }
175
32.4M
  Frontier& Largest() { return largest_; }
176
177
90.5k
  std::unique_ptr<rocksdb::UserFrontiers> Clone() const override {
178
90.5k
    return std::make_unique<UserFrontiersBase>(*this);
179
90.5k
  }
Unexecuted instantiation: rocksdb::UserFrontiersBase<rocksdb::test::TestUserFrontier>::Clone() const
rocksdb::UserFrontiersBase<yb::docdb::ConsensusFrontier>::Clone() const
Line
Count
Source
177
90.5k
  std::unique_ptr<rocksdb::UserFrontiers> Clone() const override {
178
90.5k
    return std::make_unique<UserFrontiersBase>(*this);
179
90.5k
  }
180
181
11.5M
  void MergeFrontiers(const UserFrontiers& pre_rhs) override {
182
11.5M
    const auto& rhs = down_cast<const UserFrontiersBase&>(pre_rhs);
183
11.5M
    smallest_.Update(rhs.smallest_, rocksdb::UpdateUserValueType::kSmallest);
184
11.5M
    largest_.Update(rhs.largest_, rocksdb::UpdateUserValueType::kLargest);
185
11.5M
  }
Unexecuted instantiation: rocksdb::UserFrontiersBase<rocksdb::test::TestUserFrontier>::MergeFrontiers(rocksdb::UserFrontiers const&)
rocksdb::UserFrontiersBase<yb::docdb::ConsensusFrontier>::MergeFrontiers(rocksdb::UserFrontiers const&)
Line
Count
Source
181
11.5M
  void MergeFrontiers(const UserFrontiers& pre_rhs) override {
182
11.5M
    const auto& rhs = down_cast<const UserFrontiersBase&>(pre_rhs);
183
11.5M
    smallest_.Update(rhs.smallest_, rocksdb::UpdateUserValueType::kSmallest);
184
11.5M
    largest_.Update(rhs.largest_, rocksdb::UpdateUserValueType::kLargest);
185
11.5M
  }
186
187
 private:
188
  Frontier smallest_;
189
  Frontier largest_;
190
};
191
192
inline bool operator==(const UserFrontiers& lhs, const UserFrontiers& rhs) {
193
  return lhs.Smallest() == rhs.Smallest() && lhs.Largest() == rhs.Largest();
194
}
195
196
typedef uint32_t UserBoundaryTag;
197
198
class UserBoundaryValue {
199
 public:
200
  virtual UserBoundaryTag Tag() = 0;
201
  virtual yb::Slice Encode() = 0;
202
  virtual int CompareTo(const UserBoundaryValue& rhs) = 0;
203
 protected:
204
151M
  ~UserBoundaryValue() {}
205
};
206
207
typedef std::shared_ptr<UserBoundaryValue> UserBoundaryValuePtr;
208
typedef boost::container::small_vector_base<UserBoundaryValuePtr> UserBoundaryValues;
209
210
struct FileBoundaryValuesBase {
211
  SequenceNumber seqno; // Boundary sequence number in file.
212
  UserFrontierPtr user_frontier;
213
  // We expect that there will be just a few user values, so use small_vector for it.
214
  boost::container::small_vector<UserBoundaryValuePtr, 10> user_values;
215
216
  std::string ToString() const;
217
};
218
219
template<class KeyType>
220
struct FileBoundaryValues : FileBoundaryValuesBase {
221
  KeyType key; // Boundary key in the file.
222
};
223
224
inline UserBoundaryValuePtr UserValueWithTag(const UserBoundaryValues& values,
225
151M
                                             UserBoundaryTag tag) {
226
251M
  for (const auto& value : values) {
227
251M
    if (value->Tag() == tag)
228
151M
      return value;
229
251M
  }
230
18.4E
  return UserBoundaryValuePtr();
231
151M
}
232
233
inline void UpdateUserValue(UserBoundaryValues* values,
234
                            const UserBoundaryValuePtr& new_value,
235
301M
                            UpdateUserValueType type) {
236
301M
  int compare_sign = static_cast<int>(type);
237
301M
  auto tag = new_value->Tag();
238
502M
  for (auto& value : *values) {
239
502M
    if (value->Tag() == tag) {
240
301M
      if (value->CompareTo(*new_value) * compare_sign > 0) {
241
8.14M
        value = new_value;
242
8.14M
      }
243
301M
      return;
244
301M
    }
245
502M
  }
246
18.4E
  values->push_back(new_value);
247
18.4E
}
248
249
// The metadata that describes a SST fileset.
250
struct SstFileMetaData {
251
  typedef FileBoundaryValues<std::string> BoundaryValues;
252
253
384k
  SstFileMetaData() {}
254
  SstFileMetaData(const std::string& _file_name,
255
                  const std::string& _path,
256
                  uint64_t _total_size,
257
                  uint64_t _base_size,
258
                  uint64_t _uncompressed_size,
259
                  const BoundaryValues& _smallest,
260
                  const BoundaryValues& _largest,
261
                  bool _being_compacted)
262
      : total_size(_total_size),
263
        base_size(_base_size),
264
        uncompressed_size(_uncompressed_size),
265
        name(_file_name),
266
        db_path(_path),
267
        smallest(_smallest),
268
        largest(_largest),
269
5.14k
        being_compacted(_being_compacted) {
270
5.14k
  }
271
272
  // Total file(s) (metadata and data (aka s-block) files) size in bytes.
273
  uint64_t total_size = 0;
274
  // Base file size in bytes.
275
  uint64_t base_size = 0;
276
  // Total uncompressed size in bytes.
277
  uint64_t uncompressed_size = 0;
278
  // The name of the file.
279
  std::string name;
280
  // The full path where the file locates.
281
  std::string db_path;
282
283
  BoundaryValues smallest;
284
  BoundaryValues largest;
285
  bool imported = false;
286
  bool being_compacted = false; // true if the file is currently being compacted.
287
};
288
289
// The full set of metadata associated with each SST file.
290
struct LiveFileMetaData : SstFileMetaData {
291
  std::string column_family_name;  // Name of the column family
292
  int level;                       // Level at which this file resides.
293
294
  std::string ToString() const;
295
};
296
297
}  // namespace rocksdb
298
299
#endif  // YB_ROCKSDB_METADATA_H