YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/version_set_test.cc
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
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
24
#include <string>
25
26
#include <gtest/gtest.h>
27
28
#include "yb/rocksdb/db/version_set.h"
29
#include "yb/rocksdb/env.h"
30
31
#include "yb/rocksdb/util/testutil.h"
32
33
namespace rocksdb {
34
35
class GenerateLevelFilesBriefTest : public RocksDBTest {
36
 public:
37
  std::vector<FileMetaData*> files_;
38
  LevelFilesBrief file_level_;
39
  Arena arena_;
40
41
3
  GenerateLevelFilesBriefTest() { }
42
43
3
  ~GenerateLevelFilesBriefTest() {
44
8
    for (size_t i = 0; i < files_.size(); i++) {
45
5
      delete files_[i];
46
5
    }
47
3
  }
48
49
  void Add(const char* smallest, const char* largest,
50
           SequenceNumber smallest_seq = 100,
51
5
           SequenceNumber largest_seq = 100) {
52
5
    FileMetaData* f = new FileMetaData;
53
5
    f->fd = FileDescriptor(files_.size() + 1, 0, 0, 0);
54
5
    f->smallest = MakeFileBoundaryValues(smallest, smallest_seq, kTypeValue);
55
5
    f->largest = MakeFileBoundaryValues(largest, largest_seq, kTypeValue);
56
5
    files_.push_back(f);
57
5
  }
58
59
3
  int Compare() {
60
3
    int diff = 0;
61
8
    for (size_t i = 0; i < files_.size(); i++) {
62
5
      if (file_level_.files[i].fd.GetNumber() != files_[i]->fd.GetNumber()) {
63
0
        diff++;
64
0
      }
65
5
    }
66
3
    return diff;
67
3
  }
68
};
69
70
1
TEST_F(GenerateLevelFilesBriefTest, Empty) {
71
1
  DoGenerateLevelFilesBrief(&file_level_, files_, &arena_);
72
1
  ASSERT_EQ(0u, file_level_.num_files);
73
1
  ASSERT_EQ(0, Compare());
74
1
}
75
76
1
TEST_F(GenerateLevelFilesBriefTest, Single) {
77
1
  Add("p", "q");
78
1
  DoGenerateLevelFilesBrief(&file_level_, files_, &arena_);
79
1
  ASSERT_EQ(1u, file_level_.num_files);
80
1
  ASSERT_EQ(0, Compare());
81
1
}
82
83
1
TEST_F(GenerateLevelFilesBriefTest, Multiple) {
84
1
  Add("150", "200");
85
1
  Add("200", "250");
86
1
  Add("300", "350");
87
1
  Add("400", "450");
88
1
  DoGenerateLevelFilesBrief(&file_level_, files_, &arena_);
89
1
  ASSERT_EQ(4u, file_level_.num_files);
90
1
  ASSERT_EQ(0, Compare());
91
1
}
92
93
class CountingLogger : public Logger {
94
 public:
95
6
  CountingLogger() : log_count(0) {}
96
  using Logger::Logv;
97
21
  void Logv(const char* format, va_list ap) override { log_count++; }
98
  int log_count;
99
};
100
101
Options GetOptionsWithNumLevels(int num_levels,
102
6
                                std::shared_ptr<CountingLogger> logger) {
103
6
  Options opt;
104
6
  opt.num_levels = num_levels;
105
6
  opt.info_log = logger;
106
6
  return opt;
107
6
}
108
109
class VersionStorageInfoTest : public RocksDBTest {
110
 public:
111
  const Comparator* ucmp_;
112
  InternalKeyComparatorPtr icmp_;
113
  std::shared_ptr<CountingLogger> logger_;
114
  Options options_;
115
  ImmutableCFOptions ioptions_;
116
  MutableCFOptions mutable_cf_options_;
117
  VersionStorageInfo vstorage_;
118
119
  VersionStorageInfoTest()
120
      : ucmp_(BytewiseComparator()),
121
        icmp_(std::make_shared<InternalKeyComparator>(ucmp_)),
122
        logger_(new CountingLogger()),
123
        options_(GetOptionsWithNumLevels(6, logger_)),
124
        ioptions_(options_),
125
        mutable_cf_options_(options_, ioptions_),
126
6
        vstorage_(icmp_, ucmp_, 6, kCompactionStyleLevel, nullptr) {}
127
128
6
  ~VersionStorageInfoTest() {
129
42
    for (int i = 0; i < vstorage_.num_levels(); i++) {
130
33
      for (auto* f : vstorage_.LevelFiles(i)) {
131
33
        if (--f->refs == 0) {
132
33
          delete f;
133
33
        }
134
33
      }
135
36
    }
136
6
  }
137
138
  void Add(int level, uint32_t file_number, const char* smallest,
139
33
           const char* largest, uint64_t file_size = 0) {
140
33
    assert(level < vstorage_.num_levels());
141
33
    FileMetaData* f = new FileMetaData;
142
33
    f->fd = FileDescriptor(file_number, 0, file_size, 64);
143
33
    f->smallest = MakeFileBoundaryValues(smallest, 0, kTypeValue);
144
33
    f->largest = MakeFileBoundaryValues(largest, 0, kTypeValue);
145
33
    f->compensated_file_size = file_size;
146
33
    f->refs = 0;
147
33
    f->num_entries = 0;
148
33
    f->num_deletions = 0;
149
33
    vstorage_.AddFile(level, f);
150
33
  }
151
};
152
153
1
TEST_F(VersionStorageInfoTest, MaxBytesForLevelStatic) {
154
1
  ioptions_.level_compaction_dynamic_level_bytes = false;
155
1
  mutable_cf_options_.max_bytes_for_level_base = 10;
156
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 5;
157
1
  Add(4, 100U, "1", "2");
158
1
  Add(5, 101U, "1", "2");
159
160
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
161
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(1), 10U);
162
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 50U);
163
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 250U);
164
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 1250U);
165
166
1
  ASSERT_EQ(0, logger_->log_count);
167
1
}
168
169
1
TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamic) {
170
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
171
1
  mutable_cf_options_.max_bytes_for_level_base = 1000;
172
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 5;
173
1
  Add(5, 1U, "1", "2", 500U);
174
175
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
176
1
  ASSERT_EQ(0, logger_->log_count);
177
1
  ASSERT_EQ(vstorage_.base_level(), 5);
178
179
1
  Add(5, 2U, "3", "4", 550U);
180
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
181
1
  ASSERT_EQ(0, logger_->log_count);
182
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 210U);
183
1
  ASSERT_EQ(vstorage_.base_level(), 4);
184
185
1
  Add(4, 3U, "3", "4", 550U);
186
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
187
1
  ASSERT_EQ(0, logger_->log_count);
188
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 210U);
189
1
  ASSERT_EQ(vstorage_.base_level(), 4);
190
191
1
  Add(3, 4U, "3", "4", 250U);
192
1
  Add(3, 5U, "5", "7", 300U);
193
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
194
1
  ASSERT_EQ(1, logger_->log_count);
195
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 1005U);
196
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 201U);
197
1
  ASSERT_EQ(vstorage_.base_level(), 3);
198
199
1
  Add(1, 6U, "3", "4", 5U);
200
1
  Add(1, 7U, "8", "9", 5U);
201
1
  logger_->log_count = 0;
202
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
203
1
  ASSERT_EQ(1, logger_->log_count);
204
1
  ASSERT_GT(vstorage_.MaxBytesForLevel(4), 1005U);
205
1
  ASSERT_GT(vstorage_.MaxBytesForLevel(3), 1005U);
206
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 1005U);
207
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(1), 201U);
208
1
  ASSERT_EQ(vstorage_.base_level(), 1);
209
1
}
210
211
1
TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicLotsOfData) {
212
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
213
1
  mutable_cf_options_.max_bytes_for_level_base = 100;
214
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 2;
215
1
  Add(0, 1U, "1", "2", 50U);
216
1
  Add(1, 2U, "1", "2", 50U);
217
1
  Add(2, 3U, "1", "2", 500U);
218
1
  Add(3, 4U, "1", "2", 500U);
219
1
  Add(4, 5U, "1", "2", 1700U);
220
1
  Add(5, 6U, "1", "2", 500U);
221
222
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
223
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 800U);
224
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 400U);
225
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 200U);
226
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(1), 100U);
227
1
  ASSERT_EQ(vstorage_.base_level(), 1);
228
1
  ASSERT_EQ(0, logger_->log_count);
229
1
}
230
231
1
TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicLargeLevel) {
232
1
  uint64_t kOneGB = 1000U * 1000U * 1000U;
233
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
234
1
  mutable_cf_options_.max_bytes_for_level_base = 10U * kOneGB;
235
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
236
1
  Add(0, 1U, "1", "2", 50U);
237
1
  Add(3, 4U, "1", "2", 32U * kOneGB);
238
1
  Add(4, 5U, "1", "2", 500U * kOneGB);
239
1
  Add(5, 6U, "1", "2", 3000U * kOneGB);
240
241
1
  vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
242
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(5), 3000U * kOneGB);
243
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 300U * kOneGB);
244
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 30U * kOneGB);
245
1
  ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 3U * kOneGB);
246
1
  ASSERT_EQ(vstorage_.base_level(), 2);
247
1
  ASSERT_EQ(0, logger_->log_count);
248
1
}
249
250
1
TEST_F(VersionStorageInfoTest, EstimateLiveDataSize) {
251
  // Test whether the overlaps are detected as expected
252
1
  Add(1, 1U, "4", "7", 1U);  // Perfect overlap with last level
253
1
  Add(2, 2U, "3", "5", 1U);  // Partial overlap with last level
254
1
  Add(2, 3U, "6", "8", 1U);  // Partial overlap with last level
255
1
  Add(3, 4U, "1", "9", 1U);  // Contains range of last level
256
1
  Add(4, 5U, "4", "5", 1U);  // Inside range of last level
257
1
  Add(4, 5U, "6", "7", 1U);  // Inside range of last level
258
1
  Add(5, 6U, "4", "7", 10U);
259
1
  ASSERT_EQ(10U, vstorage_.EstimateLiveDataSize());
260
1
}
261
262
1
TEST_F(VersionStorageInfoTest, EstimateLiveDataSize2) {
263
1
  Add(0, 1U, "9", "9", 1U);  // Level 0 is not ordered
264
1
  Add(0, 1U, "5", "6", 1U);  // Ignored because of [5,6] in l1
265
1
  Add(1, 1U, "1", "2", 1U);  // Ignored because of [2,3] in l2
266
1
  Add(1, 2U, "3", "4", 1U);  // Ignored because of [2,3] in l2
267
1
  Add(1, 3U, "5", "6", 1U);
268
1
  Add(2, 4U, "2", "3", 1U);
269
1
  Add(3, 5U, "7", "8", 1U);
270
1
  ASSERT_EQ(4U, vstorage_.EstimateLiveDataSize());
271
1
}
272
273
class FindLevelFileTest : public RocksDBTest {
274
 public:
275
  LevelFilesBrief file_level_;
276
  bool disjoint_sorted_files_;
277
  Arena arena_;
278
279
6
  FindLevelFileTest() : disjoint_sorted_files_(true) { }
280
281
6
  ~FindLevelFileTest() {
282
6
  }
283
284
6
  void LevelFileInit(size_t num = 0) {
285
6
    char* mem = arena_.AllocateAligned(num * sizeof(FdWithBoundaries));
286
6
    file_level_.files = reinterpret_cast<FdWithBoundaries*>(mem);
287
6
    file_level_.num_files = 0;
288
6
  }
289
290
  void Add(const char* smallest, const char* largest,
291
           SequenceNumber smallest_seq = 100,
292
12
           SequenceNumber largest_seq = 100) {
293
    // add to file_level_
294
12
    size_t num = file_level_.num_files;
295
12
    FileMetaData meta;
296
12
    meta.fd = FileDescriptor(num + 1, 0, 0, 0);
297
12
    meta.smallest.key = InternalKey(smallest, smallest_seq, kTypeValue);
298
12
    meta.largest.key = InternalKey(largest, largest_seq, kTypeValue);
299
12
    new (file_level_.files + num) FdWithBoundaries(&arena_, meta);
300
12
    file_level_.num_files++;
301
12
  }
302
303
24
  int Find(const char* key) {
304
24
    InternalKey target(key, 100, kTypeValue);
305
24
    InternalKeyComparator cmp(BytewiseComparator());
306
24
    return FindFile(cmp, file_level_, target.Encode());
307
24
  }
308
309
64
  bool Overlaps(const char* smallest, const char* largest) {
310
64
    InternalKeyComparator cmp(BytewiseComparator());
311
50
    Slice s(smallest != nullptr ? smallest : "");
312
53
    Slice l(largest != nullptr ? largest : "");
313
64
    return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, file_level_,
314
50
                                 (smallest != nullptr ? &s : nullptr),
315
53
                                 (largest != nullptr ? &l : nullptr));
316
64
  }
317
};
318
319
1
TEST_F(FindLevelFileTest, LevelEmpty) {
320
1
  LevelFileInit(0);
321
322
1
  ASSERT_EQ(0, Find("foo"));
323
1
  ASSERT_TRUE(!Overlaps("a", "z"));
324
1
  ASSERT_TRUE(!Overlaps(nullptr, "z"));
325
1
  ASSERT_TRUE(!Overlaps("a", nullptr));
326
1
  ASSERT_TRUE(!Overlaps(nullptr, nullptr));
327
1
}
328
329
1
TEST_F(FindLevelFileTest, LevelSingle) {
330
1
  LevelFileInit(1);
331
332
1
  Add("p", "q");
333
1
  ASSERT_EQ(0, Find("a"));
334
1
  ASSERT_EQ(0, Find("p"));
335
1
  ASSERT_EQ(0, Find("p1"));
336
1
  ASSERT_EQ(0, Find("q"));
337
1
  ASSERT_EQ(1, Find("q1"));
338
1
  ASSERT_EQ(1, Find("z"));
339
340
1
  ASSERT_TRUE(!Overlaps("a", "b"));
341
1
  ASSERT_TRUE(!Overlaps("z1", "z2"));
342
1
  ASSERT_TRUE(Overlaps("a", "p"));
343
1
  ASSERT_TRUE(Overlaps("a", "q"));
344
1
  ASSERT_TRUE(Overlaps("a", "z"));
345
1
  ASSERT_TRUE(Overlaps("p", "p1"));
346
1
  ASSERT_TRUE(Overlaps("p", "q"));
347
1
  ASSERT_TRUE(Overlaps("p", "z"));
348
1
  ASSERT_TRUE(Overlaps("p1", "p2"));
349
1
  ASSERT_TRUE(Overlaps("p1", "z"));
350
1
  ASSERT_TRUE(Overlaps("q", "q"));
351
1
  ASSERT_TRUE(Overlaps("q", "q1"));
352
353
1
  ASSERT_TRUE(!Overlaps(nullptr, "j"));
354
1
  ASSERT_TRUE(!Overlaps("r", nullptr));
355
1
  ASSERT_TRUE(Overlaps(nullptr, "p"));
356
1
  ASSERT_TRUE(Overlaps(nullptr, "p1"));
357
1
  ASSERT_TRUE(Overlaps("q", nullptr));
358
1
  ASSERT_TRUE(Overlaps(nullptr, nullptr));
359
1
}
360
361
1
TEST_F(FindLevelFileTest, LevelMultiple) {
362
1
  LevelFileInit(4);
363
364
1
  Add("150", "200");
365
1
  Add("200", "250");
366
1
  Add("300", "350");
367
1
  Add("400", "450");
368
1
  ASSERT_EQ(0, Find("100"));
369
1
  ASSERT_EQ(0, Find("150"));
370
1
  ASSERT_EQ(0, Find("151"));
371
1
  ASSERT_EQ(0, Find("199"));
372
1
  ASSERT_EQ(0, Find("200"));
373
1
  ASSERT_EQ(1, Find("201"));
374
1
  ASSERT_EQ(1, Find("249"));
375
1
  ASSERT_EQ(1, Find("250"));
376
1
  ASSERT_EQ(2, Find("251"));
377
1
  ASSERT_EQ(2, Find("299"));
378
1
  ASSERT_EQ(2, Find("300"));
379
1
  ASSERT_EQ(2, Find("349"));
380
1
  ASSERT_EQ(2, Find("350"));
381
1
  ASSERT_EQ(3, Find("351"));
382
1
  ASSERT_EQ(3, Find("400"));
383
1
  ASSERT_EQ(3, Find("450"));
384
1
  ASSERT_EQ(4, Find("451"));
385
386
1
  ASSERT_TRUE(!Overlaps("100", "149"));
387
1
  ASSERT_TRUE(!Overlaps("251", "299"));
388
1
  ASSERT_TRUE(!Overlaps("451", "500"));
389
1
  ASSERT_TRUE(!Overlaps("351", "399"));
390
391
1
  ASSERT_TRUE(Overlaps("100", "150"));
392
1
  ASSERT_TRUE(Overlaps("100", "200"));
393
1
  ASSERT_TRUE(Overlaps("100", "300"));
394
1
  ASSERT_TRUE(Overlaps("100", "400"));
395
1
  ASSERT_TRUE(Overlaps("100", "500"));
396
1
  ASSERT_TRUE(Overlaps("375", "400"));
397
1
  ASSERT_TRUE(Overlaps("450", "450"));
398
1
  ASSERT_TRUE(Overlaps("450", "500"));
399
1
}
400
401
1
TEST_F(FindLevelFileTest, LevelMultipleNullBoundaries) {
402
1
  LevelFileInit(4);
403
404
1
  Add("150", "200");
405
1
  Add("200", "250");
406
1
  Add("300", "350");
407
1
  Add("400", "450");
408
1
  ASSERT_TRUE(!Overlaps(nullptr, "149"));
409
1
  ASSERT_TRUE(!Overlaps("451", nullptr));
410
1
  ASSERT_TRUE(Overlaps(nullptr, nullptr));
411
1
  ASSERT_TRUE(Overlaps(nullptr, "150"));
412
1
  ASSERT_TRUE(Overlaps(nullptr, "199"));
413
1
  ASSERT_TRUE(Overlaps(nullptr, "200"));
414
1
  ASSERT_TRUE(Overlaps(nullptr, "201"));
415
1
  ASSERT_TRUE(Overlaps(nullptr, "400"));
416
1
  ASSERT_TRUE(Overlaps(nullptr, "800"));
417
1
  ASSERT_TRUE(Overlaps("100", nullptr));
418
1
  ASSERT_TRUE(Overlaps("200", nullptr));
419
1
  ASSERT_TRUE(Overlaps("449", nullptr));
420
1
  ASSERT_TRUE(Overlaps("450", nullptr));
421
1
}
422
423
1
TEST_F(FindLevelFileTest, LevelOverlapSequenceChecks) {
424
1
  LevelFileInit(1);
425
426
1
  Add("200", "200", 5000, 3000);
427
1
  ASSERT_TRUE(!Overlaps("199", "199"));
428
1
  ASSERT_TRUE(!Overlaps("201", "300"));
429
1
  ASSERT_TRUE(Overlaps("200", "200"));
430
1
  ASSERT_TRUE(Overlaps("190", "200"));
431
1
  ASSERT_TRUE(Overlaps("200", "210"));
432
1
}
433
434
1
TEST_F(FindLevelFileTest, LevelOverlappingFiles) {
435
1
  LevelFileInit(2);
436
437
1
  Add("150", "600");
438
1
  Add("400", "500");
439
1
  disjoint_sorted_files_ = false;
440
1
  ASSERT_TRUE(!Overlaps("100", "149"));
441
1
  ASSERT_TRUE(!Overlaps("601", "700"));
442
1
  ASSERT_TRUE(Overlaps("100", "150"));
443
1
  ASSERT_TRUE(Overlaps("100", "200"));
444
1
  ASSERT_TRUE(Overlaps("100", "300"));
445
1
  ASSERT_TRUE(Overlaps("100", "400"));
446
1
  ASSERT_TRUE(Overlaps("100", "500"));
447
1
  ASSERT_TRUE(Overlaps("375", "400"));
448
1
  ASSERT_TRUE(Overlaps("450", "450"));
449
1
  ASSERT_TRUE(Overlaps("450", "500"));
450
1
  ASSERT_TRUE(Overlaps("450", "700"));
451
1
  ASSERT_TRUE(Overlaps("600", "700"));
452
1
}
453
454
}  // namespace rocksdb
455
456
13.2k
int main(int argc, char** argv) {
457
13.2k
  ::testing::InitGoogleTest(&argc, argv);
458
13.2k
  return RUN_ALL_TESTS();
459
13.2k
}