YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/compaction_picker_test.cc
Line
Count
Source
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
#include <limits>
22
#include <string>
23
#include <utility>
24
25
#include <gtest/gtest.h>
26
27
#include "yb/rocksdb/db/compaction_picker.h"
28
#include "yb/rocksdb/db/version_set.h"
29
#include "yb/rocksdb/env.h"
30
31
#include "yb/util/size_literals.h"
32
#include "yb/util/string_util.h"
33
#include "yb/rocksdb/util/testutil.h"
34
35
using namespace yb::size_literals;
36
37
namespace rocksdb {
38
39
class CountingLogger : public Logger {
40
 public:
41
  using Logger::Logv;
42
21
  void Logv(const char* format, va_list ap) override { log_count++; }
43
  size_t log_count;
44
};
45
46
class CompactionPickerTest : public RocksDBTest {
47
 public:
48
  const Comparator* ucmp_;
49
  InternalKeyComparatorPtr icmp_;
50
  Options options_;
51
  ImmutableCFOptions ioptions_;
52
  MutableCFOptions mutable_cf_options_;
53
  LevelCompactionPicker level_compaction_picker;
54
  std::string cf_name_;
55
  CountingLogger logger_;
56
  LogBuffer log_buffer_;
57
  uint32_t file_num_;
58
  CompactionOptionsFIFO fifo_options_;
59
  std::unique_ptr<VersionStorageInfo> vstorage_;
60
  std::vector<std::unique_ptr<FileMetaData>> files_;
61
  // does not own FileMetaData
62
  std::unordered_map<uint32_t, std::pair<FileMetaData*, int>> file_map_;
63
  // input files to compaction process.
64
  std::vector<CompactionInputFiles> input_files_;
65
  int compaction_level_start_;
66
67
  CompactionPickerTest()
68
      : ucmp_(BytewiseComparator()),
69
        icmp_(std::make_shared<InternalKeyComparator>(ucmp_)),
70
        ioptions_(options_),
71
        mutable_cf_options_(options_, ioptions_),
72
        level_compaction_picker(ioptions_, icmp_.get()),
73
        cf_name_("dummy"),
74
        log_buffer_(InfoLogLevel::INFO_LEVEL, &logger_),
75
        file_num_(1),
76
31
        vstorage_(nullptr) {
77
31
    fifo_options_.max_table_files_size = 1;
78
31
    mutable_cf_options_.RefreshDerivedOptions(ioptions_);
79
31
    ioptions_.db_paths.emplace_back("dummy",
80
31
                                    std::numeric_limits<uint64_t>::max());
81
31
  }
82
83
31
  ~CompactionPickerTest() {
84
31
    log_buffer_.FlushBufferToLog();
85
31
  }
86
87
164
  void NewVersionStorage(int num_levels, CompactionStyle style) {
88
164
    DeleteVersionStorage();
89
164
    options_.num_levels = num_levels;
90
164
    vstorage_.reset(new VersionStorageInfo(
91
164
        icmp_, ucmp_, options_.num_levels, style, nullptr));
92
164
    vstorage_->CalculateBaseBytes(ioptions_, mutable_cf_options_);
93
164
  }
94
95
266
  void DeleteVersionStorage() {
96
266
    vstorage_.reset();
97
266
    files_.clear();
98
266
    file_map_.clear();
99
266
    input_files_.clear();
100
266
  }
101
102
  void Add(int level, uint32_t file_number, const char* smallest,
103
           const char* largest, uint64_t file_size = 0, uint32_t path_id = 0,
104
           SequenceNumber smallest_seq = 100,
105
1.30k
           SequenceNumber largest_seq = 100) {
106
1.30k
    assert(level < vstorage_->num_levels());
107
1.30k
    FileMetaData* f = new FileMetaData;
108
    // For large SST use 512 bytes as base file size, for files smaller than 512 bytes use half of
109
    // total size as a base file size.
110
    // Some compaction picker tests are using small files (<512 and even 1-3) bytes, so for these
111
    // files we split them into (file_size / 2) bytes base file and the rest goes to data file.
112
1.16k
    const uint64_t base_file_size = file_size > 512 ? 512 : (file_size / 2);
113
1.30k
    f->fd = FileDescriptor(file_number, path_id, file_size, base_file_size);
114
1.30k
    f->smallest = MakeFileBoundaryValues(smallest, smallest_seq, kTypeValue);
115
1.30k
    f->largest = MakeFileBoundaryValues(largest, largest_seq, kTypeValue);
116
1.30k
    f->compensated_file_size = file_size;
117
1.30k
    f->refs = 0;
118
1.30k
    vstorage_->AddFile(level, f);
119
1.30k
    files_.emplace_back(f);
120
1.30k
    file_map_.insert({file_number, {f, level}});
121
1.30k
  }
122
123
8
  void SetCompactionInputFilesLevels(int level_count, int start_level) {
124
8
    input_files_.resize(level_count);
125
22
    for (int i = 0; i < level_count; ++i) {
126
14
      input_files_[i].level = start_level + i;
127
14
    }
128
8
    compaction_level_start_ = start_level;
129
8
  }
130
131
25
  void AddToCompactionFiles(uint32_t file_number) {
132
25
    auto iter = file_map_.find(file_number);
133
25
    assert(iter != file_map_.end());
134
25
    int level = iter->second.second;
135
25
    assert(level < vstorage_->num_levels());
136
25
    input_files_[level - compaction_level_start_].files.emplace_back(
137
25
        iter->second.first);
138
25
  }
139
140
158
  void UpdateVersionStorageInfo() {
141
158
    vstorage_->CalculateBaseBytes(ioptions_, mutable_cf_options_);
142
158
    vstorage_->UpdateFilesByCompactionPri(mutable_cf_options_);
143
158
    vstorage_->UpdateNumNonEmptyLevels();
144
158
    vstorage_->GenerateFileIndexer();
145
158
    vstorage_->GenerateLevelFilesBrief();
146
158
    vstorage_->ComputeCompactionScore(mutable_cf_options_, fifo_options_);
147
158
    vstorage_->GenerateLevel0NonOverlapping();
148
158
    vstorage_->SetFinalized();
149
158
  }
150
};
151
152
1
TEST_F(CompactionPickerTest, Empty) {
153
1
  NewVersionStorage(6, kCompactionStyleLevel);
154
1
  UpdateVersionStorageInfo();
155
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
156
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
157
1
  ASSERT_TRUE(compaction.get() == nullptr);
158
1
}
159
160
1
TEST_F(CompactionPickerTest, Single) {
161
1
  NewVersionStorage(6, kCompactionStyleLevel);
162
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
163
1
  Add(0, 1U, "p", "q");
164
1
  UpdateVersionStorageInfo();
165
166
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
167
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
168
1
  ASSERT_TRUE(compaction.get() == nullptr);
169
1
}
170
171
1
TEST_F(CompactionPickerTest, Level0Trigger) {
172
1
  NewVersionStorage(6, kCompactionStyleLevel);
173
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
174
1
  Add(0, 1U, "150", "200");
175
1
  Add(0, 2U, "200", "250");
176
177
1
  UpdateVersionStorageInfo();
178
179
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
180
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
181
1
  ASSERT_TRUE(compaction.get() != nullptr);
182
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
183
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
184
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
185
1
}
186
187
1
TEST_F(CompactionPickerTest, Level1Trigger) {
188
1
  NewVersionStorage(6, kCompactionStyleLevel);
189
1
  Add(1, 66U, "150", "200", 1000000000U);
190
1
  UpdateVersionStorageInfo();
191
192
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
193
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
194
1
  ASSERT_TRUE(compaction.get() != nullptr);
195
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
196
1
  ASSERT_EQ(66U, compaction->input(0, 0)->fd.GetNumber());
197
1
}
198
199
1
TEST_F(CompactionPickerTest, Level1Trigger2) {
200
1
  NewVersionStorage(6, kCompactionStyleLevel);
201
1
  Add(1, 66U, "150", "200", 1000000001U);
202
1
  Add(1, 88U, "201", "300", 1000000000U);
203
1
  Add(2, 6U, "150", "179", 1000000000U);
204
1
  Add(2, 7U, "180", "220", 1000000000U);
205
1
  Add(2, 8U, "221", "300", 1000000000U);
206
1
  UpdateVersionStorageInfo();
207
208
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
209
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
210
1
  ASSERT_TRUE(compaction.get() != nullptr);
211
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
212
1
  ASSERT_EQ(2U, compaction->num_input_files(1));
213
1
  ASSERT_EQ(66U, compaction->input(0, 0)->fd.GetNumber());
214
1
  ASSERT_EQ(6U, compaction->input(1, 0)->fd.GetNumber());
215
1
  ASSERT_EQ(7U, compaction->input(1, 1)->fd.GetNumber());
216
1
}
217
218
1
TEST_F(CompactionPickerTest, LevelMaxScore) {
219
1
  NewVersionStorage(6, kCompactionStyleLevel);
220
1
  mutable_cf_options_.target_file_size_base = 10000000;
221
1
  mutable_cf_options_.target_file_size_multiplier = 10;
222
1
  Add(0, 1U, "150", "200", 1000000000U);
223
  // Level 1 score 1.2
224
1
  Add(1, 66U, "150", "200", 6000000U);
225
1
  Add(1, 88U, "201", "300", 6000000U);
226
  // Level 2 score 1.8. File 7 is the largest. Should be picked
227
1
  Add(2, 6U, "150", "179", 60000000U);
228
1
  Add(2, 7U, "180", "220", 60000001U);
229
1
  Add(2, 8U, "221", "300", 60000000U);
230
  // Level 3 score slightly larger than 1
231
1
  Add(3, 26U, "150", "170", 260000000U);
232
1
  Add(3, 27U, "171", "179", 260000000U);
233
1
  Add(3, 28U, "191", "220", 260000000U);
234
1
  Add(3, 29U, "221", "300", 260000000U);
235
1
  UpdateVersionStorageInfo();
236
237
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
238
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
239
1
  ASSERT_TRUE(compaction.get() != nullptr);
240
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
241
1
  ASSERT_EQ(7U, compaction->input(0, 0)->fd.GetNumber());
242
1
}
243
244
1
TEST_F(CompactionPickerTest, NeedsCompactionLevel) {
245
1
  const int kLevels = 6;
246
1
  const int kFileCount = 20;
247
248
6
  for (int level = 0; level < kLevels - 1; ++level) {
249
5
    NewVersionStorage(kLevels, kCompactionStyleLevel);
250
5
    uint64_t file_size = vstorage_->MaxBytesForLevel(level) * 2 / kFileCount;
251
105
    for (int file_count = 1; file_count <= kFileCount; ++file_count) {
252
      // start a brand new version in each test.
253
100
      NewVersionStorage(kLevels, kCompactionStyleLevel);
254
1.15k
      for (int i = 0; i < file_count; ++i) {
255
1.05k
        Add(level, i, ToString((i + 100) * 1000).c_str(),
256
1.05k
            ToString((i + 100) * 1000 + 999).c_str(),
257
1.05k
            file_size, 0, i * 100, i * 100 + 99);
258
1.05k
      }
259
100
      UpdateVersionStorageInfo();
260
100
      ASSERT_EQ(vstorage_->CompactionScoreLevel(0), level);
261
100
      ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()),
262
100
                vstorage_->CompactionScore(0) >= 1);
263
      // release the version storage
264
100
      DeleteVersionStorage();
265
100
    }
266
5
  }
267
1
}
268
269
1
TEST_F(CompactionPickerTest, Level0TriggerDynamic) {
270
1
  int num_levels = ioptions_.num_levels;
271
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
272
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
273
1
  mutable_cf_options_.max_bytes_for_level_base = 200;
274
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
275
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
276
1
  Add(0, 1U, "150", "200");
277
1
  Add(0, 2U, "200", "250");
278
279
1
  UpdateVersionStorageInfo();
280
281
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
282
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
283
1
  ASSERT_TRUE(compaction.get() != nullptr);
284
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
285
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
286
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
287
1
  ASSERT_EQ(1, static_cast<int>(compaction->num_input_levels()));
288
1
  ASSERT_EQ(num_levels - 1, compaction->output_level());
289
1
}
290
291
1
TEST_F(CompactionPickerTest, Level0TriggerDynamic2) {
292
1
  int num_levels = ioptions_.num_levels;
293
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
294
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
295
1
  mutable_cf_options_.max_bytes_for_level_base = 200;
296
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
297
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
298
1
  Add(0, 1U, "150", "200");
299
1
  Add(0, 2U, "200", "250");
300
1
  Add(num_levels - 1, 3U, "200", "250", 300U);
301
302
1
  UpdateVersionStorageInfo();
303
1
  ASSERT_EQ(vstorage_->base_level(), num_levels - 2);
304
305
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
306
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
307
1
  ASSERT_TRUE(compaction.get() != nullptr);
308
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
309
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
310
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
311
1
  ASSERT_EQ(1, static_cast<int>(compaction->num_input_levels()));
312
1
  ASSERT_EQ(num_levels - 2, compaction->output_level());
313
1
}
314
315
1
TEST_F(CompactionPickerTest, Level0TriggerDynamic3) {
316
1
  int num_levels = ioptions_.num_levels;
317
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
318
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
319
1
  mutable_cf_options_.max_bytes_for_level_base = 200;
320
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
321
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
322
1
  Add(0, 1U, "150", "200");
323
1
  Add(0, 2U, "200", "250");
324
1
  Add(num_levels - 1, 3U, "200", "250", 300U);
325
1
  Add(num_levels - 1, 4U, "300", "350", 3000U);
326
327
1
  UpdateVersionStorageInfo();
328
1
  ASSERT_EQ(vstorage_->base_level(), num_levels - 3);
329
330
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
331
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
332
1
  ASSERT_TRUE(compaction.get() != nullptr);
333
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
334
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
335
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
336
1
  ASSERT_EQ(1, static_cast<int>(compaction->num_input_levels()));
337
1
  ASSERT_EQ(num_levels - 3, compaction->output_level());
338
1
}
339
340
1
TEST_F(CompactionPickerTest, Level0TriggerDynamic4) {
341
1
  int num_levels = ioptions_.num_levels;
342
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
343
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
344
1
  mutable_cf_options_.max_bytes_for_level_base = 200;
345
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
346
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
347
1
  Add(0, 1U, "150", "200");
348
1
  Add(0, 2U, "200", "250");
349
1
  Add(num_levels - 1, 3U, "200", "250", 300U);
350
1
  Add(num_levels - 1, 4U, "300", "350", 3000U);
351
1
  Add(num_levels - 3, 5U, "150", "180", 3U);
352
1
  Add(num_levels - 3, 6U, "181", "300", 3U);
353
1
  Add(num_levels - 3, 7U, "400", "450", 3U);
354
355
1
  UpdateVersionStorageInfo();
356
1
  ASSERT_EQ(vstorage_->base_level(), num_levels - 3);
357
358
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
359
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
360
1
  ASSERT_TRUE(compaction.get() != nullptr);
361
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
362
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
363
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
364
1
  ASSERT_EQ(2U, compaction->num_input_files(1));
365
1
  ASSERT_EQ(num_levels - 3, compaction->level(1));
366
1
  ASSERT_EQ(5U, compaction->input(1, 0)->fd.GetNumber());
367
1
  ASSERT_EQ(6U, compaction->input(1, 1)->fd.GetNumber());
368
1
  ASSERT_EQ(2, static_cast<int>(compaction->num_input_levels()));
369
1
  ASSERT_EQ(num_levels - 3, compaction->output_level());
370
1
}
371
372
1
TEST_F(CompactionPickerTest, LevelTriggerDynamic4) {
373
1
  int num_levels = ioptions_.num_levels;
374
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
375
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
376
1
  mutable_cf_options_.max_bytes_for_level_base = 200;
377
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
378
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
379
1
  Add(0, 1U, "150", "200");
380
1
  Add(num_levels - 1, 3U, "200", "250", 300U);
381
1
  Add(num_levels - 1, 4U, "300", "350", 3000U);
382
1
  Add(num_levels - 1, 4U, "400", "450", 3U);
383
1
  Add(num_levels - 2, 5U, "150", "180", 300U);
384
1
  Add(num_levels - 2, 6U, "181", "350", 500U);
385
1
  Add(num_levels - 2, 7U, "400", "450", 200U);
386
387
1
  UpdateVersionStorageInfo();
388
389
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
390
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
391
1
  ASSERT_TRUE(compaction.get() != nullptr);
392
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
393
1
  ASSERT_EQ(6U, compaction->input(0, 0)->fd.GetNumber());
394
1
  ASSERT_EQ(2U, compaction->num_input_files(1));
395
1
  ASSERT_EQ(3U, compaction->input(1, 0)->fd.GetNumber());
396
1
  ASSERT_EQ(4U, compaction->input(1, 1)->fd.GetNumber());
397
1
  ASSERT_EQ(2U, compaction->num_input_levels());
398
1
  ASSERT_EQ(num_levels - 1, compaction->output_level());
399
1
}
400
401
// Universal and FIFO Compactions are not supported in ROCKSDB_LITE
402
#ifndef ROCKSDB_LITE
403
1
TEST_F(CompactionPickerTest, NeedsCompactionUniversal) {
404
1
  NewVersionStorage(1, kCompactionStyleUniversal);
405
1
  UniversalCompactionPicker universal_compaction_picker(
406
1
      ioptions_, icmp_.get());
407
  // must return false when there's no files.
408
1
  ASSERT_EQ(universal_compaction_picker.NeedsCompaction(vstorage_.get()),
409
1
            false);
410
1
  UpdateVersionStorageInfo();
411
412
  // verify the trigger given different number of L0 files.
413
1
  for (int i = 1;
414
9
       i <= mutable_cf_options_.level0_file_num_compaction_trigger * 2; ++i) {
415
8
    NewVersionStorage(1, kCompactionStyleUniversal);
416
8
    Add(0, i, ToString((i + 100) * 1000).c_str(),
417
8
        ToString((i + 100) * 1000 + 999).c_str(), 1000000, 0, i * 100,
418
8
        i * 100 + 99);
419
8
    UpdateVersionStorageInfo();
420
8
    ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()),
421
8
              vstorage_->CompactionScore(0) >= 1);
422
8
  }
423
1
}
424
425
// Tests if the correct compaction reason is used given which files are marked
426
// as being compacted. Specifically, the test ensures that if the earliest file
427
// available in a sequence of sorted runs is currently being compacted, it is
428
// not included in the compaction.
429
1
TEST_F(CompactionPickerTest, CompactionUniversalPickForFilesBeingCompacted) {
430
1
  NewVersionStorage(1, kCompactionStyleUniversal);
431
1
  ioptions_.compaction_style = kCompactionStyleUniversal;
432
1
  ioptions_.num_levels = 1;
433
1
  mutable_cf_options_.write_buffer_size = 100_KB;
434
1
  mutable_cf_options_.target_file_size_base = 32_KB;
435
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 3;
436
1
  UniversalCompactionPicker universal_compaction_picker(ioptions_, icmp_.get());
437
  // must return false when there's no files.
438
1
  ASSERT_FALSE(universal_compaction_picker.NeedsCompaction(vstorage_.get()));
439
1
  UpdateVersionStorageInfo();
440
441
1
  NewVersionStorage(1, kCompactionStyleUniversal);
442
443
  // Create three files, the earliest of which is significantly smaller than the other
444
  // two. This should cause the compaction picker to include all three files,
445
  // choosing "size amplification" as the compaction reason.
446
  // Add third file
447
1
  Add(/* level = */ 0, /* file number = */ 3, /* smallest = */ "300000",
448
1
      /* largest = */ "300999", /* file_size = */ 1000000, /* path_id = */ 0,
449
1
      /* smallest seq num = */ 300, /* largest seq num = */ 399);
450
  // Add second file
451
1
  Add(/* level = */ 0, /* file number = */ 2, /* smallest = */ "200000",
452
1
      /* largest = */ "200999", /* file size = */ 1000000, /* path_id = */ 0,
453
1
      /* smallest seq num = */ 200, /* largest seq num = */ 299);
454
  // Add first file
455
1
  Add(/* level = */ 0, /* file number = */ 1, /* smallest = */ "100000",
456
1
      /* largest = */ "100999", /* file size (smaller) = */ 10,
457
1
      /* path_id = */ 0, /* smallest seq num = */ 100, /* largest seq num = */ 199);
458
459
1
  UpdateVersionStorageInfo();
460
1
  auto compaction = universal_compaction_picker.PickCompaction(
461
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_);
462
1
  ASSERT_NE(compaction, nullptr);
463
1
  ASSERT_EQ(compaction->compaction_reason(), CompactionReason::kUniversalSizeAmplification);
464
  // Verify that all three files are now being compacted.
465
4
  for (int i = 1; i <= 3; i++) {
466
3
    ASSERT_TRUE(file_map_.at(i).first->being_compacted);
467
3
  }
468
469
  // Reset "being_compacted" on files 2 and 3 (simulates if earliest file is being compacted).
470
  // This scenario is particularly likely if file expiration based on TTL is enabled.
471
1
  file_map_.at(2).first->being_compacted = false;
472
1
  file_map_.at(3).first->being_compacted = false;
473
474
  // Files in sequence are [3 (available), 2 (available), 1 (being compacted)].
475
  // The compaction picker should still create a compaction, but it will only include files
476
  // 3 and 2, and will be due to file ratio/sorted run num.
477
1
  compaction = universal_compaction_picker.PickCompaction(
478
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_);
479
1
  ASSERT_NE(compaction, nullptr);
480
1
  ASSERT_EQ(compaction->compaction_reason(), CompactionReason::kUniversalSortedRunNum);
481
  // Verify there are exactly 2 files being compacted.
482
1
  ASSERT_EQ(compaction->inputs(0)->size(), 2);
483
1
}
484
485
// Tests if the files can be trivially moved in multi level
486
// universal compaction when allow_trivial_move option is set
487
// In this test as the input files overlaps, they cannot
488
// be trivially moved.
489
490
1
TEST_F(CompactionPickerTest, CannotTrivialMoveUniversal) {
491
1
  const uint64_t kFileSize = 100000;
492
493
1
  ioptions_.compaction_options_universal.allow_trivial_move = true;
494
1
  NewVersionStorage(1, kCompactionStyleUniversal);
495
1
  UniversalCompactionPicker universal_compaction_picker(ioptions_, icmp_.get());
496
  // must return false when there's no files.
497
1
  ASSERT_EQ(universal_compaction_picker.NeedsCompaction(vstorage_.get()),
498
1
            false);
499
500
1
  NewVersionStorage(3, kCompactionStyleUniversal);
501
502
1
  Add(0, 1U, "150", "200", kFileSize, 0, 500, 550);
503
1
  Add(0, 2U, "201", "250", kFileSize, 0, 401, 450);
504
1
  Add(0, 4U, "260", "300", kFileSize, 0, 260, 300);
505
1
  Add(1, 5U, "100", "151", kFileSize, 0, 200, 251);
506
1
  Add(1, 3U, "301", "350", kFileSize, 0, 101, 150);
507
1
  Add(2, 6U, "120", "200", kFileSize, 0, 20, 100);
508
509
1
  UpdateVersionStorageInfo();
510
511
1
  std::unique_ptr<Compaction> compaction(
512
1
      universal_compaction_picker.PickCompaction(
513
1
          cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
514
515
1
  ASSERT_TRUE(!compaction->is_trivial_move());
516
1
}
517
// Tests if the files can be trivially moved in multi level
518
// universal compaction when allow_trivial_move option is set
519
// In this test as the input files doesn't overlaps, they should
520
// be trivially moved.
521
1
TEST_F(CompactionPickerTest, AllowsTrivialMoveUniversal) {
522
1
  const uint64_t kFileSize = 100000;
523
524
1
  ioptions_.compaction_options_universal.allow_trivial_move = true;
525
1
  UniversalCompactionPicker universal_compaction_picker(ioptions_, icmp_.get());
526
527
1
  NewVersionStorage(3, kCompactionStyleUniversal);
528
529
1
  Add(0, 1U, "150", "200", kFileSize, 0, 500, 550);
530
1
  Add(0, 2U, "201", "250", kFileSize, 0, 401, 450);
531
1
  Add(0, 4U, "260", "300", kFileSize, 0, 260, 300);
532
1
  Add(1, 5U, "010", "080", kFileSize, 0, 200, 251);
533
1
  Add(2, 3U, "301", "350", kFileSize, 0, 101, 150);
534
535
1
  UpdateVersionStorageInfo();
536
537
1
  std::unique_ptr<Compaction> compaction(
538
1
      universal_compaction_picker.PickCompaction(
539
1
          cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
540
541
1
  ASSERT_TRUE(compaction->is_trivial_move());
542
1
}
543
544
1
TEST_F(CompactionPickerTest, NeedsCompactionFIFO) {
545
1
  NewVersionStorage(1, kCompactionStyleFIFO);
546
1
  const int kFileCount =
547
1
      mutable_cf_options_.level0_file_num_compaction_trigger * 3;
548
1
  const uint64_t kFileSize = 100000;
549
1
  const uint64_t kMaxSize = kFileSize * kFileCount / 2;
550
551
1
  fifo_options_.max_table_files_size = kMaxSize;
552
1
  ioptions_.compaction_options_fifo = fifo_options_;
553
1
  FIFOCompactionPicker fifo_compaction_picker(ioptions_, icmp_.get());
554
555
1
  UpdateVersionStorageInfo();
556
  // must return false when there's no files.
557
1
  ASSERT_EQ(fifo_compaction_picker.NeedsCompaction(vstorage_.get()), false);
558
559
  // verify whether compaction is needed based on the current
560
  // size of L0 files.
561
1
  uint64_t current_size = 0;
562
13
  for (int i = 1; i <= kFileCount; ++i) {
563
12
    NewVersionStorage(1, kCompactionStyleFIFO);
564
12
    Add(0, i, ToString((i + 100) * 1000).c_str(),
565
12
        ToString((i + 100) * 1000 + 999).c_str(),
566
12
        kFileSize, 0, i * 100, i * 100 + 99);
567
12
    current_size += kFileSize;
568
12
    UpdateVersionStorageInfo();
569
12
    ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()),
570
12
              vstorage_->CompactionScore(0) >= 1);
571
12
  }
572
1
}
573
#endif  // ROCKSDB_LITE
574
575
1
TEST_F(CompactionPickerTest, CompactionPriMinOverlapping1) {
576
1
  NewVersionStorage(6, kCompactionStyleLevel);
577
1
  mutable_cf_options_.target_file_size_base = 10000000;
578
1
  mutable_cf_options_.target_file_size_multiplier = 10;
579
1
  mutable_cf_options_.compaction_pri = kMinOverlappingRatio;
580
581
1
  Add(2, 6U, "150", "179", 50000000U);
582
1
  Add(2, 7U, "180", "220", 50000000U);
583
1
  Add(2, 8U, "321", "400", 50000000U);  // File not overlapping
584
1
  Add(2, 9U, "721", "800", 50000000U);
585
586
1
  Add(3, 26U, "150", "170", 260000000U);
587
1
  Add(3, 27U, "171", "179", 260000000U);
588
1
  Add(3, 28U, "191", "220", 260000000U);
589
1
  Add(3, 29U, "221", "300", 260000000U);
590
1
  Add(3, 30U, "750", "900", 260000000U);
591
1
  UpdateVersionStorageInfo();
592
593
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
594
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
595
1
  ASSERT_TRUE(compaction.get() != nullptr);
596
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
597
  // Pick file 8 because it overlaps with 0 files on level 3.
598
1
  ASSERT_EQ(8U, compaction->input(0, 0)->fd.GetNumber());
599
1
}
600
601
1
TEST_F(CompactionPickerTest, CompactionPriMinOverlapping2) {
602
1
  NewVersionStorage(6, kCompactionStyleLevel);
603
1
  mutable_cf_options_.target_file_size_base = 10000000;
604
1
  mutable_cf_options_.target_file_size_multiplier = 10;
605
1
  mutable_cf_options_.compaction_pri = kMinOverlappingRatio;
606
607
1
  Add(2, 6U, "150", "175",
608
1
      60000000U);  // Overlaps with file 26, 27, total size 521M
609
1
  Add(2, 7U, "176", "200", 60000000U);  // Overlaps with file 27, 28, total size
610
                                        // 520M, the smalelst overlapping
611
1
  Add(2, 8U, "201", "300",
612
1
      60000000U);  // Overlaps with file 28, 29, total size 521M
613
614
1
  Add(3, 26U, "100", "110", 261000000U);
615
1
  Add(3, 26U, "150", "170", 261000000U);
616
1
  Add(3, 27U, "171", "179", 260000000U);
617
1
  Add(3, 28U, "191", "220", 260000000U);
618
1
  Add(3, 29U, "221", "300", 261000000U);
619
1
  Add(3, 30U, "321", "400", 261000000U);
620
1
  UpdateVersionStorageInfo();
621
622
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
623
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
624
1
  ASSERT_TRUE(compaction.get() != nullptr);
625
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
626
  // Picking file 7 because overlapping ratio is the biggest.
627
1
  ASSERT_EQ(7U, compaction->input(0, 0)->fd.GetNumber());
628
1
}
629
630
1
TEST_F(CompactionPickerTest, CompactionPriMinOverlapping3) {
631
1
  NewVersionStorage(6, kCompactionStyleLevel);
632
1
  mutable_cf_options_.target_file_size_base = 10000000;
633
1
  mutable_cf_options_.target_file_size_multiplier = 10;
634
1
  mutable_cf_options_.compaction_pri = kMinOverlappingRatio;
635
636
  // file 7 and 8 over lap with the same file, but file 8 is smaller so
637
  // it will be picked.
638
1
  Add(2, 6U, "150", "175", 60000000U);  // Overlaps with file 26, 27
639
1
  Add(2, 7U, "176", "200", 60000000U);  // Overlaps with file 27
640
1
  Add(2, 8U, "201", "300", 61000000U);  // Overlaps with file 27
641
642
1
  Add(3, 26U, "160", "165", 260000000U);
643
1
  Add(3, 26U, "166", "170", 260000000U);
644
1
  Add(3, 27U, "180", "400", 260000000U);
645
1
  Add(3, 28U, "401", "500", 260000000U);
646
1
  UpdateVersionStorageInfo();
647
648
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
649
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
650
1
  ASSERT_TRUE(compaction.get() != nullptr);
651
1
  ASSERT_EQ(1U, compaction->num_input_files(0));
652
  // Picking file 8 because overlapping ratio is the biggest.
653
1
  ASSERT_EQ(8U, compaction->input(0, 0)->fd.GetNumber());
654
1
}
655
656
// This test exhibits the bug where we don't properly reset parent_index in
657
// PickCompaction()
658
1
TEST_F(CompactionPickerTest, ParentIndexResetBug) {
659
1
  int num_levels = ioptions_.num_levels;
660
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
661
1
  mutable_cf_options_.max_bytes_for_level_base = 200;
662
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
663
1
  Add(0, 1U, "150", "200");       // <- marked for compaction
664
1
  Add(1, 3U, "400", "500", 600);  // <- this one needs compacting
665
1
  Add(2, 4U, "150", "200");
666
1
  Add(2, 5U, "201", "210");
667
1
  Add(2, 6U, "300", "310");
668
1
  Add(2, 7U, "400", "500");  // <- being compacted
669
670
1
  vstorage_->LevelFiles(2)[3]->being_compacted = true;
671
1
  vstorage_->LevelFiles(0)[0]->marked_for_compaction = true;
672
673
1
  UpdateVersionStorageInfo();
674
675
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
676
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
677
1
}
678
679
// This test checks ExpandWhileOverlapping() by having overlapping user keys
680
// ranges (with different sequence numbers) in the input files.
681
1
TEST_F(CompactionPickerTest, OverlappingUserKeys) {
682
1
  NewVersionStorage(6, kCompactionStyleLevel);
683
1
  Add(1, 1U, "100", "150", 1U);
684
  // Overlapping user keys
685
1
  Add(1, 2U, "200", "400", 1U);
686
1
  Add(1, 3U, "400", "500", 1000000000U, 0, 0);
687
1
  Add(2, 4U, "600", "700", 1U);
688
1
  UpdateVersionStorageInfo();
689
690
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
691
1
              cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
692
1
  ASSERT_TRUE(compaction.get() != nullptr);
693
1
  ASSERT_EQ(1U, compaction->num_input_levels());
694
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
695
1
  ASSERT_EQ(2U, compaction->input(0, 0)->fd.GetNumber());
696
1
  ASSERT_EQ(3U, compaction->input(0, 1)->fd.GetNumber());
697
1
}
698
699
1
TEST_F(CompactionPickerTest, OverlappingUserKeys2) {
700
1
  NewVersionStorage(6, kCompactionStyleLevel);
701
  // Overlapping user keys on same level and output level
702
1
  Add(1, 1U, "200", "400", 1000000000U);
703
1
  Add(1, 2U, "400", "500", 1U, 0, 0);
704
1
  Add(2, 3U, "400", "600", 1U);
705
  // The following file is not in the compaction despite overlapping user keys
706
1
  Add(2, 4U, "600", "700", 1U, 0, 0);
707
1
  UpdateVersionStorageInfo();
708
709
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
710
1
              cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
711
1
  ASSERT_TRUE(compaction.get() != nullptr);
712
1
  ASSERT_EQ(2U, compaction->num_input_levels());
713
1
  ASSERT_EQ(2U, compaction->num_input_files(0));
714
1
  ASSERT_EQ(1U, compaction->num_input_files(1));
715
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
716
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
717
1
  ASSERT_EQ(3U, compaction->input(1, 0)->fd.GetNumber());
718
1
}
719
720
1
TEST_F(CompactionPickerTest, OverlappingUserKeys3) {
721
1
  NewVersionStorage(6, kCompactionStyleLevel);
722
  // Chain of overlapping user key ranges (forces ExpandWhileOverlapping() to
723
  // expand multiple times)
724
1
  Add(1, 1U, "100", "150", 1U);
725
1
  Add(1, 2U, "150", "200", 1U, 0, 0);
726
1
  Add(1, 3U, "200", "250", 1000000000U, 0, 0);
727
1
  Add(1, 4U, "250", "300", 1U, 0, 0);
728
1
  Add(1, 5U, "300", "350", 1U, 0, 0);
729
  // Output level overlaps with the beginning and the end of the chain
730
1
  Add(2, 6U, "050", "100", 1U);
731
1
  Add(2, 7U, "350", "400", 1U);
732
1
  UpdateVersionStorageInfo();
733
734
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
735
1
              cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
736
1
  ASSERT_TRUE(compaction.get() != nullptr);
737
1
  ASSERT_EQ(2U, compaction->num_input_levels());
738
1
  ASSERT_EQ(5U, compaction->num_input_files(0));
739
1
  ASSERT_EQ(2U, compaction->num_input_files(1));
740
1
  ASSERT_EQ(1U, compaction->input(0, 0)->fd.GetNumber());
741
1
  ASSERT_EQ(2U, compaction->input(0, 1)->fd.GetNumber());
742
1
  ASSERT_EQ(3U, compaction->input(0, 2)->fd.GetNumber());
743
1
  ASSERT_EQ(4U, compaction->input(0, 3)->fd.GetNumber());
744
1
  ASSERT_EQ(5U, compaction->input(0, 4)->fd.GetNumber());
745
1
  ASSERT_EQ(6U, compaction->input(1, 0)->fd.GetNumber());
746
1
  ASSERT_EQ(7U, compaction->input(1, 1)->fd.GetNumber());
747
1
}
748
749
1
TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri1) {
750
1
  NewVersionStorage(6, kCompactionStyleLevel);
751
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
752
1
  mutable_cf_options_.max_bytes_for_level_base = 900000000U;
753
754
  // 6 L0 files, score 3.
755
1
  Add(0, 1U, "000", "400", 1U);
756
1
  Add(0, 2U, "001", "400", 1U, 0, 0);
757
1
  Add(0, 3U, "001", "400", 1000000000U, 0, 0);
758
1
  Add(0, 31U, "001", "400", 1000000000U, 0, 0);
759
1
  Add(0, 32U, "001", "400", 1000000000U, 0, 0);
760
1
  Add(0, 33U, "001", "400", 1000000000U, 0, 0);
761
762
  // L1 total size 2GB, score 2.2. If one file being comapcted, score 1.1.
763
1
  Add(1, 4U, "050", "300", 1000000000U, 0, 0);
764
1
  file_map_[4u].first->being_compacted = true;
765
1
  Add(1, 5U, "301", "350", 1000000000U, 0, 0);
766
767
  // Output level overlaps with the beginning and the end of the chain
768
1
  Add(2, 6U, "050", "100", 1U);
769
1
  Add(2, 7U, "300", "400", 1U);
770
771
  // No compaction should be scheduled, if L0 has higher priority than L1
772
  // but L0->L1 compaction is blocked by a file in L1 being compacted.
773
1
  UpdateVersionStorageInfo();
774
1
  ASSERT_EQ(0, vstorage_->CompactionScoreLevel(0));
775
1
  ASSERT_EQ(1, vstorage_->CompactionScoreLevel(1));
776
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
777
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
778
1
  ASSERT_TRUE(compaction.get() == nullptr);
779
1
}
780
781
1
TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri2) {
782
1
  NewVersionStorage(6, kCompactionStyleLevel);
783
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
784
1
  mutable_cf_options_.max_bytes_for_level_base = 900000000U;
785
786
  // 6 L0 files, score 3.
787
1
  Add(0, 1U, "000", "400", 1U);
788
1
  Add(0, 2U, "001", "400", 1U, 0, 0);
789
1
  Add(0, 3U, "001", "400", 1000000000U, 0, 0);
790
1
  Add(0, 31U, "001", "400", 1000000000U, 0, 0);
791
1
  Add(0, 32U, "001", "400", 1000000000U, 0, 0);
792
1
  Add(0, 33U, "001", "400", 1000000000U, 0, 0);
793
794
  // L1 total size 2GB, score 2.2. If one file being comapcted, score 1.1.
795
1
  Add(1, 4U, "050", "300", 1000000000U, 0, 0);
796
1
  Add(1, 5U, "301", "350", 1000000000U, 0, 0);
797
798
  // Output level overlaps with the beginning and the end of the chain
799
1
  Add(2, 6U, "050", "100", 1U);
800
1
  Add(2, 7U, "300", "400", 1U);
801
802
  // If no file in L1 being compacted, L0->L1 compaction will be scheduled.
803
1
  UpdateVersionStorageInfo();  // being_compacted flag is cleared here.
804
1
  ASSERT_EQ(0, vstorage_->CompactionScoreLevel(0));
805
1
  ASSERT_EQ(1, vstorage_->CompactionScoreLevel(1));
806
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
807
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
808
1
  ASSERT_TRUE(compaction.get() != nullptr);
809
1
}
810
811
1
TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri3) {
812
1
  NewVersionStorage(6, kCompactionStyleLevel);
813
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 2;
814
1
  mutable_cf_options_.max_bytes_for_level_base = 900000000U;
815
816
  // 6 L0 files, score 3.
817
1
  Add(0, 1U, "000", "400", 1U);
818
1
  Add(0, 2U, "001", "400", 1U, 0, 0);
819
1
  Add(0, 3U, "001", "400", 1000000000U, 0, 0);
820
1
  Add(0, 31U, "001", "400", 1000000000U, 0, 0);
821
1
  Add(0, 32U, "001", "400", 1000000000U, 0, 0);
822
1
  Add(0, 33U, "001", "400", 1000000000U, 0, 0);
823
824
  // L1 score more than 6.
825
1
  Add(1, 4U, "050", "300", 1000000000U, 0, 0);
826
1
  file_map_[4u].first->being_compacted = true;
827
1
  Add(1, 5U, "301", "350", 1000000000U, 0, 0);
828
1
  Add(1, 51U, "351", "400", 6000000000U, 0, 0);
829
830
  // Output level overlaps with the beginning and the end of the chain
831
1
  Add(2, 6U, "050", "100", 1U);
832
1
  Add(2, 7U, "300", "400", 1U);
833
834
  // If score in L1 is larger than L0, L1 compaction goes through despite
835
  // there is pending L0 compaction.
836
1
  UpdateVersionStorageInfo();
837
1
  ASSERT_EQ(1, vstorage_->CompactionScoreLevel(0));
838
1
  ASSERT_EQ(0, vstorage_->CompactionScoreLevel(1));
839
1
  std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
840
1
      cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
841
1
  ASSERT_TRUE(compaction.get() != nullptr);
842
1
}
843
844
1
TEST_F(CompactionPickerTest, EstimateCompactionBytesNeeded1) {
845
1
  int num_levels = ioptions_.num_levels;
846
1
  ioptions_.level_compaction_dynamic_level_bytes = false;
847
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 3;
848
1
  mutable_cf_options_.max_bytes_for_level_base = 1000;
849
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
850
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
851
1
  Add(0, 1U, "150", "200", 200);
852
1
  Add(0, 2U, "150", "200", 200);
853
1
  Add(0, 3U, "150", "200", 200);
854
  // Level 1 is over target by 200
855
1
  Add(1, 4U, "400", "500", 600);
856
1
  Add(1, 5U, "600", "700", 600);
857
  // Level 2 is less than target 10000 even added size of level 1
858
1
  Add(2, 6U, "150", "200", 2500);
859
1
  Add(2, 7U, "201", "210", 2000);
860
1
  Add(2, 8U, "300", "310", 2500);
861
1
  Add(2, 9U, "400", "500", 2500);
862
  // Level 3 exceeds target 100,000 of 1000
863
1
  Add(3, 10U, "400", "500", 101000);
864
  // Level 4 exceeds target 1,000,000 of 500 after adding size from level 3
865
1
  Add(4, 11U, "400", "500", 999500);
866
1
  Add(5, 11U, "400", "500", 8000000);
867
868
1
  UpdateVersionStorageInfo();
869
870
1
  ASSERT_EQ(2200u + 11000u + 5500u,
871
1
            vstorage_->estimated_compaction_needed_bytes());
872
1
}
873
874
1
TEST_F(CompactionPickerTest, EstimateCompactionBytesNeeded2) {
875
1
  int num_levels = ioptions_.num_levels;
876
1
  ioptions_.level_compaction_dynamic_level_bytes = false;
877
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 3;
878
1
  mutable_cf_options_.max_bytes_for_level_base = 1000;
879
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
880
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
881
1
  Add(0, 1U, "150", "200", 200);
882
1
  Add(0, 2U, "150", "200", 200);
883
1
  Add(0, 4U, "150", "200", 200);
884
1
  Add(0, 5U, "150", "200", 200);
885
1
  Add(0, 6U, "150", "200", 200);
886
  // Level 1 is over target by
887
1
  Add(1, 7U, "400", "500", 200);
888
1
  Add(1, 8U, "600", "700", 200);
889
  // Level 2 is less than target 10000 even added size of level 1
890
1
  Add(2, 9U, "150", "200", 9500);
891
1
  Add(3, 10U, "400", "500", 101000);
892
893
1
  UpdateVersionStorageInfo();
894
895
1
  ASSERT_EQ(1400u + 4400u + 11000u,
896
1
            vstorage_->estimated_compaction_needed_bytes());
897
1
}
898
899
1
TEST_F(CompactionPickerTest, EstimateCompactionBytesNeededDynamicLevel) {
900
1
  int num_levels = ioptions_.num_levels;
901
1
  ioptions_.level_compaction_dynamic_level_bytes = true;
902
1
  mutable_cf_options_.level0_file_num_compaction_trigger = 3;
903
1
  mutable_cf_options_.max_bytes_for_level_base = 1000;
904
1
  mutable_cf_options_.max_bytes_for_level_multiplier = 10;
905
1
  NewVersionStorage(num_levels, kCompactionStyleLevel);
906
907
  // Set Last level size 50000
908
  // num_levels - 1 target 5000
909
  // num_levels - 2 is base level with taret 500
910
1
  Add(num_levels - 1, 10U, "400", "500", 50000);
911
912
1
  Add(0, 1U, "150", "200", 200);
913
1
  Add(0, 2U, "150", "200", 200);
914
1
  Add(0, 4U, "150", "200", 200);
915
1
  Add(0, 5U, "150", "200", 200);
916
1
  Add(0, 6U, "150", "200", 200);
917
  // num_levels - 3 is over target by 100 + 1000
918
1
  Add(num_levels - 3, 7U, "400", "500", 300);
919
1
  Add(num_levels - 3, 8U, "600", "700", 300);
920
  // Level 2 is over target by 1100 + 100
921
1
  Add(num_levels - 2, 9U, "150", "200", 5100);
922
923
1
  UpdateVersionStorageInfo();
924
925
1
  ASSERT_EQ(1600u + 12100u + 13200u,
926
1
            vstorage_->estimated_compaction_needed_bytes());
927
1
}
928
929
1
TEST_F(CompactionPickerTest, IsBottommostLevelTest) {
930
  // case 1: Higher levels are empty
931
1
  NewVersionStorage(6, kCompactionStyleLevel);
932
1
  Add(0, 1U, "a", "m");
933
1
  Add(0, 2U, "c", "z");
934
1
  Add(1, 3U, "d", "e");
935
1
  Add(1, 4U, "l", "p");
936
1
  Add(2, 5U, "g", "i");
937
1
  Add(2, 6U, "x", "z");
938
1
  UpdateVersionStorageInfo();
939
1
  SetCompactionInputFilesLevels(2, 1);
940
1
  AddToCompactionFiles(3U);
941
1
  AddToCompactionFiles(5U);
942
1
  bool result =
943
1
      Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
944
1
  ASSERT_TRUE(result);
945
946
  // case 2: Higher levels have no overlap
947
1
  NewVersionStorage(6, kCompactionStyleLevel);
948
1
  Add(0, 1U, "a", "m");
949
1
  Add(0, 2U, "c", "z");
950
1
  Add(1, 3U, "d", "e");
951
1
  Add(1, 4U, "l", "p");
952
1
  Add(2, 5U, "g", "i");
953
1
  Add(2, 6U, "x", "z");
954
1
  Add(3, 7U, "k", "p");
955
1
  Add(3, 8U, "t", "w");
956
1
  Add(4, 9U, "a", "b");
957
1
  Add(5, 10U, "c", "cc");
958
1
  UpdateVersionStorageInfo();
959
1
  SetCompactionInputFilesLevels(2, 1);
960
1
  AddToCompactionFiles(3U);
961
1
  AddToCompactionFiles(5U);
962
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
963
1
  ASSERT_TRUE(result);
964
965
  // case 3.1: Higher levels (level 3) have overlap
966
1
  NewVersionStorage(6, kCompactionStyleLevel);
967
1
  Add(0, 1U, "a", "m");
968
1
  Add(0, 2U, "c", "z");
969
1
  Add(1, 3U, "d", "e");
970
1
  Add(1, 4U, "l", "p");
971
1
  Add(2, 5U, "g", "i");
972
1
  Add(2, 6U, "x", "z");
973
1
  Add(3, 7U, "e", "g");
974
1
  Add(3, 8U, "h", "k");
975
1
  Add(4, 9U, "a", "b");
976
1
  Add(5, 10U, "c", "cc");
977
1
  UpdateVersionStorageInfo();
978
1
  SetCompactionInputFilesLevels(2, 1);
979
1
  AddToCompactionFiles(3U);
980
1
  AddToCompactionFiles(5U);
981
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
982
1
  ASSERT_FALSE(result);
983
984
  // case 3.2: Higher levels (level 5) have overlap
985
1
  DeleteVersionStorage();
986
1
  NewVersionStorage(6, kCompactionStyleLevel);
987
1
  Add(0, 1U, "a", "m");
988
1
  Add(0, 2U, "c", "z");
989
1
  Add(1, 3U, "d", "e");
990
1
  Add(1, 4U, "l", "p");
991
1
  Add(2, 5U, "g", "i");
992
1
  Add(2, 6U, "x", "z");
993
1
  Add(3, 7U, "j", "k");
994
1
  Add(3, 8U, "l", "m");
995
1
  Add(4, 9U, "a", "b");
996
1
  Add(5, 10U, "c", "cc");
997
1
  Add(5, 11U, "h", "k");
998
1
  Add(5, 12U, "y", "yy");
999
1
  Add(5, 13U, "z", "zz");
1000
1
  UpdateVersionStorageInfo();
1001
1
  SetCompactionInputFilesLevels(2, 1);
1002
1
  AddToCompactionFiles(3U);
1003
1
  AddToCompactionFiles(5U);
1004
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
1005
1
  ASSERT_FALSE(result);
1006
1007
  // case 3.3: Higher levels (level 5) have overlap, but it's only overlapping
1008
  // one key ("d")
1009
1
  NewVersionStorage(6, kCompactionStyleLevel);
1010
1
  Add(0, 1U, "a", "m");
1011
1
  Add(0, 2U, "c", "z");
1012
1
  Add(1, 3U, "d", "e");
1013
1
  Add(1, 4U, "l", "p");
1014
1
  Add(2, 5U, "g", "i");
1015
1
  Add(2, 6U, "x", "z");
1016
1
  Add(3, 7U, "j", "k");
1017
1
  Add(3, 8U, "l", "m");
1018
1
  Add(4, 9U, "a", "b");
1019
1
  Add(5, 10U, "c", "cc");
1020
1
  Add(5, 11U, "ccc", "d");
1021
1
  Add(5, 12U, "y", "yy");
1022
1
  Add(5, 13U, "z", "zz");
1023
1
  UpdateVersionStorageInfo();
1024
1
  SetCompactionInputFilesLevels(2, 1);
1025
1
  AddToCompactionFiles(3U);
1026
1
  AddToCompactionFiles(5U);
1027
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
1028
1
  ASSERT_FALSE(result);
1029
1030
  // Level 0 files overlap
1031
1
  NewVersionStorage(6, kCompactionStyleLevel);
1032
1
  Add(0, 1U, "s", "t");
1033
1
  Add(0, 2U, "a", "m");
1034
1
  Add(0, 3U, "b", "z");
1035
1
  Add(0, 4U, "e", "f");
1036
1
  Add(5, 10U, "y", "z");
1037
1
  UpdateVersionStorageInfo();
1038
1
  SetCompactionInputFilesLevels(1, 0);
1039
1
  AddToCompactionFiles(1U);
1040
1
  AddToCompactionFiles(2U);
1041
1
  AddToCompactionFiles(3U);
1042
1
  AddToCompactionFiles(4U);
1043
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
1044
1
  ASSERT_FALSE(result);
1045
1046
  // Level 0 files don't overlap
1047
1
  NewVersionStorage(6, kCompactionStyleLevel);
1048
1
  Add(0, 1U, "s", "t");
1049
1
  Add(0, 2U, "a", "m");
1050
1
  Add(0, 3U, "b", "k");
1051
1
  Add(0, 4U, "e", "f");
1052
1
  Add(5, 10U, "y", "z");
1053
1
  UpdateVersionStorageInfo();
1054
1
  SetCompactionInputFilesLevels(1, 0);
1055
1
  AddToCompactionFiles(1U);
1056
1
  AddToCompactionFiles(2U);
1057
1
  AddToCompactionFiles(3U);
1058
1
  AddToCompactionFiles(4U);
1059
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
1060
1
  ASSERT_TRUE(result);
1061
1062
  // Level 1 files overlap
1063
1
  NewVersionStorage(6, kCompactionStyleLevel);
1064
1
  Add(0, 1U, "s", "t");
1065
1
  Add(0, 2U, "a", "m");
1066
1
  Add(0, 3U, "b", "k");
1067
1
  Add(0, 4U, "e", "f");
1068
1
  Add(1, 5U, "a", "m");
1069
1
  Add(1, 6U, "n", "o");
1070
1
  Add(1, 7U, "w", "y");
1071
1
  Add(5, 10U, "y", "z");
1072
1
  UpdateVersionStorageInfo();
1073
1
  SetCompactionInputFilesLevels(2, 0);
1074
1
  AddToCompactionFiles(1U);
1075
1
  AddToCompactionFiles(2U);
1076
1
  AddToCompactionFiles(3U);
1077
1
  AddToCompactionFiles(4U);
1078
1
  AddToCompactionFiles(5U);
1079
1
  AddToCompactionFiles(6U);
1080
1
  AddToCompactionFiles(7U);
1081
1
  result = Compaction::TEST_IsBottommostLevel(2, vstorage_.get(), input_files_);
1082
1
  ASSERT_FALSE(result);
1083
1084
1
  DeleteVersionStorage();
1085
1
}
1086
1087
}  // namespace rocksdb
1088
1089
13.2k
int main(int argc, char** argv) {
1090
13.2k
  ::testing::InitGoogleTest(&argc, argv);
1091
13.2k
  return RUN_ALL_TESTS();
1092
13.2k
}