]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/db/version_set_test.cc
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rocksdb / db / version_set_test.cc
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
5//
6// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7// Use of this source code is governed by a BSD-style license that can be
8// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10#include "db/version_set.h"
11fdf7f2
TL
11#include "db/log_writer.h"
12#include "table/mock_table.h"
7c673cae 13#include "util/logging.h"
11fdf7f2 14#include "util/string_util.h"
7c673cae
FG
15#include "util/testharness.h"
16#include "util/testutil.h"
17
18namespace rocksdb {
19
20class GenerateLevelFilesBriefTest : public testing::Test {
21 public:
22 std::vector<FileMetaData*> files_;
23 LevelFilesBrief file_level_;
24 Arena arena_;
25
26 GenerateLevelFilesBriefTest() { }
27
494da23a 28 ~GenerateLevelFilesBriefTest() override {
7c673cae
FG
29 for (size_t i = 0; i < files_.size(); i++) {
30 delete files_[i];
31 }
32 }
33
34 void Add(const char* smallest, const char* largest,
35 SequenceNumber smallest_seq = 100,
36 SequenceNumber largest_seq = 100) {
37 FileMetaData* f = new FileMetaData;
38 f->fd = FileDescriptor(files_.size() + 1, 0, 0);
39 f->smallest = InternalKey(smallest, smallest_seq, kTypeValue);
40 f->largest = InternalKey(largest, largest_seq, kTypeValue);
41 files_.push_back(f);
42 }
43
44 int Compare() {
45 int diff = 0;
46 for (size_t i = 0; i < files_.size(); i++) {
47 if (file_level_.files[i].fd.GetNumber() != files_[i]->fd.GetNumber()) {
48 diff++;
49 }
50 }
51 return diff;
52 }
53};
54
55TEST_F(GenerateLevelFilesBriefTest, Empty) {
56 DoGenerateLevelFilesBrief(&file_level_, files_, &arena_);
57 ASSERT_EQ(0u, file_level_.num_files);
58 ASSERT_EQ(0, Compare());
59}
60
61TEST_F(GenerateLevelFilesBriefTest, Single) {
62 Add("p", "q");
63 DoGenerateLevelFilesBrief(&file_level_, files_, &arena_);
64 ASSERT_EQ(1u, file_level_.num_files);
65 ASSERT_EQ(0, Compare());
66}
67
68TEST_F(GenerateLevelFilesBriefTest, Multiple) {
69 Add("150", "200");
70 Add("200", "250");
71 Add("300", "350");
72 Add("400", "450");
73 DoGenerateLevelFilesBrief(&file_level_, files_, &arena_);
74 ASSERT_EQ(4u, file_level_.num_files);
75 ASSERT_EQ(0, Compare());
76}
77
78class CountingLogger : public Logger {
79 public:
80 CountingLogger() : log_count(0) {}
81 using Logger::Logv;
494da23a 82 void Logv(const char* /*format*/, va_list /*ap*/) override { log_count++; }
7c673cae
FG
83 int log_count;
84};
85
86Options GetOptionsWithNumLevels(int num_levels,
87 std::shared_ptr<CountingLogger> logger) {
88 Options opt;
89 opt.num_levels = num_levels;
90 opt.info_log = logger;
91 return opt;
92}
93
94class VersionStorageInfoTest : public testing::Test {
95 public:
96 const Comparator* ucmp_;
97 InternalKeyComparator icmp_;
98 std::shared_ptr<CountingLogger> logger_;
99 Options options_;
100 ImmutableCFOptions ioptions_;
101 MutableCFOptions mutable_cf_options_;
102 VersionStorageInfo vstorage_;
103
104 InternalKey GetInternalKey(const char* ukey,
105 SequenceNumber smallest_seq = 100) {
106 return InternalKey(ukey, smallest_seq, kTypeValue);
107 }
108
109 VersionStorageInfoTest()
110 : ucmp_(BytewiseComparator()),
111 icmp_(ucmp_),
112 logger_(new CountingLogger()),
113 options_(GetOptionsWithNumLevels(6, logger_)),
114 ioptions_(options_),
115 mutable_cf_options_(options_),
116 vstorage_(&icmp_, ucmp_, 6, kCompactionStyleLevel, nullptr, false) {}
117
494da23a 118 ~VersionStorageInfoTest() override {
7c673cae
FG
119 for (int i = 0; i < vstorage_.num_levels(); i++) {
120 for (auto* f : vstorage_.LevelFiles(i)) {
121 if (--f->refs == 0) {
122 delete f;
123 }
124 }
125 }
126 }
127
128 void Add(int level, uint32_t file_number, const char* smallest,
129 const char* largest, uint64_t file_size = 0) {
130 assert(level < vstorage_.num_levels());
131 FileMetaData* f = new FileMetaData;
132 f->fd = FileDescriptor(file_number, 0, file_size);
133 f->smallest = GetInternalKey(smallest, 0);
134 f->largest = GetInternalKey(largest, 0);
135 f->compensated_file_size = file_size;
136 f->refs = 0;
137 f->num_entries = 0;
138 f->num_deletions = 0;
139 vstorage_.AddFile(level, f);
140 }
11fdf7f2
TL
141
142 void Add(int level, uint32_t file_number, const InternalKey& smallest,
143 const InternalKey& largest, uint64_t file_size = 0) {
144 assert(level < vstorage_.num_levels());
145 FileMetaData* f = new FileMetaData;
146 f->fd = FileDescriptor(file_number, 0, file_size);
147 f->smallest = smallest;
148 f->largest = largest;
149 f->compensated_file_size = file_size;
150 f->refs = 0;
151 f->num_entries = 0;
152 f->num_deletions = 0;
153 vstorage_.AddFile(level, f);
154 }
155
156 std::string GetOverlappingFiles(int level, const InternalKey& begin,
157 const InternalKey& end) {
158 std::vector<FileMetaData*> inputs;
159 vstorage_.GetOverlappingInputs(level, &begin, &end, &inputs);
160
161 std::string result;
162 for (size_t i = 0; i < inputs.size(); ++i) {
163 if (i > 0) {
164 result += ",";
165 }
166 AppendNumberTo(&result, inputs[i]->fd.GetNumber());
167 }
168 return result;
169 }
7c673cae
FG
170};
171
172TEST_F(VersionStorageInfoTest, MaxBytesForLevelStatic) {
173 ioptions_.level_compaction_dynamic_level_bytes = false;
174 mutable_cf_options_.max_bytes_for_level_base = 10;
175 mutable_cf_options_.max_bytes_for_level_multiplier = 5;
176 Add(4, 100U, "1", "2");
177 Add(5, 101U, "1", "2");
178
179 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
180 ASSERT_EQ(vstorage_.MaxBytesForLevel(1), 10U);
181 ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 50U);
182 ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 250U);
183 ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 1250U);
184
185 ASSERT_EQ(0, logger_->log_count);
186}
187
188TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamic) {
189 ioptions_.level_compaction_dynamic_level_bytes = true;
190 mutable_cf_options_.max_bytes_for_level_base = 1000;
191 mutable_cf_options_.max_bytes_for_level_multiplier = 5;
192 Add(5, 1U, "1", "2", 500U);
193
194 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
195 ASSERT_EQ(0, logger_->log_count);
196 ASSERT_EQ(vstorage_.base_level(), 5);
197
198 Add(5, 2U, "3", "4", 550U);
199 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
200 ASSERT_EQ(0, logger_->log_count);
11fdf7f2 201 ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 1000U);
7c673cae
FG
202 ASSERT_EQ(vstorage_.base_level(), 4);
203
204 Add(4, 3U, "3", "4", 550U);
205 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
206 ASSERT_EQ(0, logger_->log_count);
11fdf7f2 207 ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 1000U);
7c673cae
FG
208 ASSERT_EQ(vstorage_.base_level(), 4);
209
210 Add(3, 4U, "3", "4", 250U);
211 Add(3, 5U, "5", "7", 300U);
212 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
213 ASSERT_EQ(1, logger_->log_count);
214 ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 1005U);
11fdf7f2 215 ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 1000U);
7c673cae
FG
216 ASSERT_EQ(vstorage_.base_level(), 3);
217
218 Add(1, 6U, "3", "4", 5U);
219 Add(1, 7U, "8", "9", 5U);
220 logger_->log_count = 0;
221 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
222 ASSERT_EQ(1, logger_->log_count);
223 ASSERT_GT(vstorage_.MaxBytesForLevel(4), 1005U);
224 ASSERT_GT(vstorage_.MaxBytesForLevel(3), 1005U);
225 ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 1005U);
11fdf7f2 226 ASSERT_EQ(vstorage_.MaxBytesForLevel(1), 1000U);
7c673cae
FG
227 ASSERT_EQ(vstorage_.base_level(), 1);
228}
229
230TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicLotsOfData) {
231 ioptions_.level_compaction_dynamic_level_bytes = true;
232 mutable_cf_options_.max_bytes_for_level_base = 100;
233 mutable_cf_options_.max_bytes_for_level_multiplier = 2;
234 Add(0, 1U, "1", "2", 50U);
235 Add(1, 2U, "1", "2", 50U);
236 Add(2, 3U, "1", "2", 500U);
237 Add(3, 4U, "1", "2", 500U);
238 Add(4, 5U, "1", "2", 1700U);
239 Add(5, 6U, "1", "2", 500U);
240
241 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
242 ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 800U);
243 ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 400U);
244 ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 200U);
245 ASSERT_EQ(vstorage_.MaxBytesForLevel(1), 100U);
246 ASSERT_EQ(vstorage_.base_level(), 1);
247 ASSERT_EQ(0, logger_->log_count);
248}
249
250TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicLargeLevel) {
251 uint64_t kOneGB = 1000U * 1000U * 1000U;
252 ioptions_.level_compaction_dynamic_level_bytes = true;
253 mutable_cf_options_.max_bytes_for_level_base = 10U * kOneGB;
254 mutable_cf_options_.max_bytes_for_level_multiplier = 10;
255 Add(0, 1U, "1", "2", 50U);
256 Add(3, 4U, "1", "2", 32U * kOneGB);
257 Add(4, 5U, "1", "2", 500U * kOneGB);
258 Add(5, 6U, "1", "2", 3000U * kOneGB);
259
260 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
261 ASSERT_EQ(vstorage_.MaxBytesForLevel(5), 3000U * kOneGB);
262 ASSERT_EQ(vstorage_.MaxBytesForLevel(4), 300U * kOneGB);
263 ASSERT_EQ(vstorage_.MaxBytesForLevel(3), 30U * kOneGB);
11fdf7f2 264 ASSERT_EQ(vstorage_.MaxBytesForLevel(2), 10U * kOneGB);
7c673cae
FG
265 ASSERT_EQ(vstorage_.base_level(), 2);
266 ASSERT_EQ(0, logger_->log_count);
267}
268
494da23a
TL
269TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicWithLargeL0_1) {
270 ioptions_.level_compaction_dynamic_level_bytes = true;
271 mutable_cf_options_.max_bytes_for_level_base = 40000;
272 mutable_cf_options_.max_bytes_for_level_multiplier = 5;
273 mutable_cf_options_.level0_file_num_compaction_trigger = 2;
274
275 Add(0, 1U, "1", "2", 10000U);
276 Add(0, 2U, "1", "2", 10000U);
277 Add(0, 3U, "1", "2", 10000U);
278
279 Add(5, 4U, "1", "2", 1286250U);
280 Add(4, 5U, "1", "2", 200000U);
281 Add(3, 6U, "1", "2", 40000U);
282 Add(2, 7U, "1", "2", 8000U);
283
284 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
285 ASSERT_EQ(0, logger_->log_count);
286 ASSERT_EQ(2, vstorage_.base_level());
287 // level multiplier should be 3.5
288 ASSERT_EQ(vstorage_.level_multiplier(), 5.0);
289 // Level size should be around 30,000, 105,000, 367,500
290 ASSERT_EQ(40000U, vstorage_.MaxBytesForLevel(2));
291 ASSERT_EQ(51450U, vstorage_.MaxBytesForLevel(3));
292 ASSERT_EQ(257250U, vstorage_.MaxBytesForLevel(4));
293}
294
295TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicWithLargeL0_2) {
296 ioptions_.level_compaction_dynamic_level_bytes = true;
297 mutable_cf_options_.max_bytes_for_level_base = 10000;
298 mutable_cf_options_.max_bytes_for_level_multiplier = 5;
299 mutable_cf_options_.level0_file_num_compaction_trigger = 2;
300
301 Add(0, 11U, "1", "2", 10000U);
302 Add(0, 12U, "1", "2", 10000U);
303 Add(0, 13U, "1", "2", 10000U);
304
305 Add(5, 4U, "1", "2", 1286250U);
306 Add(4, 5U, "1", "2", 200000U);
307 Add(3, 6U, "1", "2", 40000U);
308 Add(2, 7U, "1", "2", 8000U);
309
310 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
311 ASSERT_EQ(0, logger_->log_count);
312 ASSERT_EQ(2, vstorage_.base_level());
313 // level multiplier should be 3.5
314 ASSERT_LT(vstorage_.level_multiplier(), 3.6);
315 ASSERT_GT(vstorage_.level_multiplier(), 3.4);
316 // Level size should be around 30,000, 105,000, 367,500
317 ASSERT_EQ(30000U, vstorage_.MaxBytesForLevel(2));
318 ASSERT_LT(vstorage_.MaxBytesForLevel(3), 110000U);
319 ASSERT_GT(vstorage_.MaxBytesForLevel(3), 100000U);
320 ASSERT_LT(vstorage_.MaxBytesForLevel(4), 370000U);
321 ASSERT_GT(vstorage_.MaxBytesForLevel(4), 360000U);
322}
323
324TEST_F(VersionStorageInfoTest, MaxBytesForLevelDynamicWithLargeL0_3) {
325 ioptions_.level_compaction_dynamic_level_bytes = true;
326 mutable_cf_options_.max_bytes_for_level_base = 10000;
327 mutable_cf_options_.max_bytes_for_level_multiplier = 5;
328 mutable_cf_options_.level0_file_num_compaction_trigger = 2;
329
330 Add(0, 11U, "1", "2", 5000U);
331 Add(0, 12U, "1", "2", 5000U);
332 Add(0, 13U, "1", "2", 5000U);
333 Add(0, 14U, "1", "2", 5000U);
334 Add(0, 15U, "1", "2", 5000U);
335 Add(0, 16U, "1", "2", 5000U);
336
337 Add(5, 4U, "1", "2", 1286250U);
338 Add(4, 5U, "1", "2", 200000U);
339 Add(3, 6U, "1", "2", 40000U);
340 Add(2, 7U, "1", "2", 8000U);
341
342 vstorage_.CalculateBaseBytes(ioptions_, mutable_cf_options_);
343 ASSERT_EQ(0, logger_->log_count);
344 ASSERT_EQ(2, vstorage_.base_level());
345 // level multiplier should be 3.5
346 ASSERT_LT(vstorage_.level_multiplier(), 3.6);
347 ASSERT_GT(vstorage_.level_multiplier(), 3.4);
348 // Level size should be around 30,000, 105,000, 367,500
349 ASSERT_EQ(30000U, vstorage_.MaxBytesForLevel(2));
350 ASSERT_LT(vstorage_.MaxBytesForLevel(3), 110000U);
351 ASSERT_GT(vstorage_.MaxBytesForLevel(3), 100000U);
352 ASSERT_LT(vstorage_.MaxBytesForLevel(4), 370000U);
353 ASSERT_GT(vstorage_.MaxBytesForLevel(4), 360000U);
354}
355
7c673cae
FG
356TEST_F(VersionStorageInfoTest, EstimateLiveDataSize) {
357 // Test whether the overlaps are detected as expected
358 Add(1, 1U, "4", "7", 1U); // Perfect overlap with last level
359 Add(2, 2U, "3", "5", 1U); // Partial overlap with last level
360 Add(2, 3U, "6", "8", 1U); // Partial overlap with last level
361 Add(3, 4U, "1", "9", 1U); // Contains range of last level
362 Add(4, 5U, "4", "5", 1U); // Inside range of last level
363 Add(4, 5U, "6", "7", 1U); // Inside range of last level
364 Add(5, 6U, "4", "7", 10U);
365 ASSERT_EQ(10U, vstorage_.EstimateLiveDataSize());
366}
367
368TEST_F(VersionStorageInfoTest, EstimateLiveDataSize2) {
369 Add(0, 1U, "9", "9", 1U); // Level 0 is not ordered
370 Add(0, 1U, "5", "6", 1U); // Ignored because of [5,6] in l1
371 Add(1, 1U, "1", "2", 1U); // Ignored because of [2,3] in l2
372 Add(1, 2U, "3", "4", 1U); // Ignored because of [2,3] in l2
373 Add(1, 3U, "5", "6", 1U);
374 Add(2, 4U, "2", "3", 1U);
375 Add(3, 5U, "7", "8", 1U);
376 ASSERT_EQ(4U, vstorage_.EstimateLiveDataSize());
377}
378
11fdf7f2
TL
379TEST_F(VersionStorageInfoTest, GetOverlappingInputs) {
380 // Two files that overlap at the range deletion tombstone sentinel.
381 Add(1, 1U, {"a", 0, kTypeValue}, {"b", kMaxSequenceNumber, kTypeRangeDeletion}, 1);
382 Add(1, 2U, {"b", 0, kTypeValue}, {"c", 0, kTypeValue}, 1);
383 // Two files that overlap at the same user key.
384 Add(1, 3U, {"d", 0, kTypeValue}, {"e", kMaxSequenceNumber, kTypeValue}, 1);
385 Add(1, 4U, {"e", 0, kTypeValue}, {"f", 0, kTypeValue}, 1);
386 // Two files that do not overlap.
387 Add(1, 5U, {"g", 0, kTypeValue}, {"h", 0, kTypeValue}, 1);
388 Add(1, 6U, {"i", 0, kTypeValue}, {"j", 0, kTypeValue}, 1);
389 vstorage_.UpdateNumNonEmptyLevels();
390 vstorage_.GenerateLevelFilesBrief();
391
392 ASSERT_EQ("1,2", GetOverlappingFiles(
393 1, {"a", 0, kTypeValue}, {"b", 0, kTypeValue}));
394 ASSERT_EQ("1", GetOverlappingFiles(
395 1, {"a", 0, kTypeValue}, {"b", kMaxSequenceNumber, kTypeRangeDeletion}));
396 ASSERT_EQ("2", GetOverlappingFiles(
397 1, {"b", kMaxSequenceNumber, kTypeValue}, {"c", 0, kTypeValue}));
398 ASSERT_EQ("3,4", GetOverlappingFiles(
399 1, {"d", 0, kTypeValue}, {"e", 0, kTypeValue}));
400 ASSERT_EQ("3", GetOverlappingFiles(
401 1, {"d", 0, kTypeValue}, {"e", kMaxSequenceNumber, kTypeRangeDeletion}));
402 ASSERT_EQ("3,4", GetOverlappingFiles(
403 1, {"e", kMaxSequenceNumber, kTypeValue}, {"f", 0, kTypeValue}));
404 ASSERT_EQ("3,4", GetOverlappingFiles(
405 1, {"e", 0, kTypeValue}, {"f", 0, kTypeValue}));
406 ASSERT_EQ("5", GetOverlappingFiles(
407 1, {"g", 0, kTypeValue}, {"h", 0, kTypeValue}));
408 ASSERT_EQ("6", GetOverlappingFiles(
409 1, {"i", 0, kTypeValue}, {"j", 0, kTypeValue}));
410}
411
412
7c673cae
FG
413class FindLevelFileTest : public testing::Test {
414 public:
415 LevelFilesBrief file_level_;
416 bool disjoint_sorted_files_;
417 Arena arena_;
418
419 FindLevelFileTest() : disjoint_sorted_files_(true) { }
420
494da23a 421 ~FindLevelFileTest() override {}
7c673cae
FG
422
423 void LevelFileInit(size_t num = 0) {
424 char* mem = arena_.AllocateAligned(num * sizeof(FdWithKeyRange));
425 file_level_.files = new (mem)FdWithKeyRange[num];
426 file_level_.num_files = 0;
427 }
428
429 void Add(const char* smallest, const char* largest,
430 SequenceNumber smallest_seq = 100,
431 SequenceNumber largest_seq = 100) {
432 InternalKey smallest_key = InternalKey(smallest, smallest_seq, kTypeValue);
433 InternalKey largest_key = InternalKey(largest, largest_seq, kTypeValue);
434
435 Slice smallest_slice = smallest_key.Encode();
436 Slice largest_slice = largest_key.Encode();
437
438 char* mem = arena_.AllocateAligned(
439 smallest_slice.size() + largest_slice.size());
440 memcpy(mem, smallest_slice.data(), smallest_slice.size());
441 memcpy(mem + smallest_slice.size(), largest_slice.data(),
442 largest_slice.size());
443
444 // add to file_level_
445 size_t num = file_level_.num_files;
446 auto& file = file_level_.files[num];
447 file.fd = FileDescriptor(num + 1, 0, 0);
448 file.smallest_key = Slice(mem, smallest_slice.size());
449 file.largest_key = Slice(mem + smallest_slice.size(),
450 largest_slice.size());
451 file_level_.num_files++;
452 }
453
454 int Find(const char* key) {
455 InternalKey target(key, 100, kTypeValue);
456 InternalKeyComparator cmp(BytewiseComparator());
457 return FindFile(cmp, file_level_, target.Encode());
458 }
459
460 bool Overlaps(const char* smallest, const char* largest) {
461 InternalKeyComparator cmp(BytewiseComparator());
462 Slice s(smallest != nullptr ? smallest : "");
463 Slice l(largest != nullptr ? largest : "");
464 return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, file_level_,
465 (smallest != nullptr ? &s : nullptr),
466 (largest != nullptr ? &l : nullptr));
467 }
468};
469
470TEST_F(FindLevelFileTest, LevelEmpty) {
471 LevelFileInit(0);
472
473 ASSERT_EQ(0, Find("foo"));
474 ASSERT_TRUE(! Overlaps("a", "z"));
475 ASSERT_TRUE(! Overlaps(nullptr, "z"));
476 ASSERT_TRUE(! Overlaps("a", nullptr));
477 ASSERT_TRUE(! Overlaps(nullptr, nullptr));
478}
479
480TEST_F(FindLevelFileTest, LevelSingle) {
481 LevelFileInit(1);
482
483 Add("p", "q");
484 ASSERT_EQ(0, Find("a"));
485 ASSERT_EQ(0, Find("p"));
486 ASSERT_EQ(0, Find("p1"));
487 ASSERT_EQ(0, Find("q"));
488 ASSERT_EQ(1, Find("q1"));
489 ASSERT_EQ(1, Find("z"));
490
491 ASSERT_TRUE(! Overlaps("a", "b"));
492 ASSERT_TRUE(! Overlaps("z1", "z2"));
493 ASSERT_TRUE(Overlaps("a", "p"));
494 ASSERT_TRUE(Overlaps("a", "q"));
495 ASSERT_TRUE(Overlaps("a", "z"));
496 ASSERT_TRUE(Overlaps("p", "p1"));
497 ASSERT_TRUE(Overlaps("p", "q"));
498 ASSERT_TRUE(Overlaps("p", "z"));
499 ASSERT_TRUE(Overlaps("p1", "p2"));
500 ASSERT_TRUE(Overlaps("p1", "z"));
501 ASSERT_TRUE(Overlaps("q", "q"));
502 ASSERT_TRUE(Overlaps("q", "q1"));
503
504 ASSERT_TRUE(! Overlaps(nullptr, "j"));
505 ASSERT_TRUE(! Overlaps("r", nullptr));
506 ASSERT_TRUE(Overlaps(nullptr, "p"));
507 ASSERT_TRUE(Overlaps(nullptr, "p1"));
508 ASSERT_TRUE(Overlaps("q", nullptr));
509 ASSERT_TRUE(Overlaps(nullptr, nullptr));
510}
511
512TEST_F(FindLevelFileTest, LevelMultiple) {
513 LevelFileInit(4);
514
515 Add("150", "200");
516 Add("200", "250");
517 Add("300", "350");
518 Add("400", "450");
519 ASSERT_EQ(0, Find("100"));
520 ASSERT_EQ(0, Find("150"));
521 ASSERT_EQ(0, Find("151"));
522 ASSERT_EQ(0, Find("199"));
523 ASSERT_EQ(0, Find("200"));
524 ASSERT_EQ(1, Find("201"));
525 ASSERT_EQ(1, Find("249"));
526 ASSERT_EQ(1, Find("250"));
527 ASSERT_EQ(2, Find("251"));
528 ASSERT_EQ(2, Find("299"));
529 ASSERT_EQ(2, Find("300"));
530 ASSERT_EQ(2, Find("349"));
531 ASSERT_EQ(2, Find("350"));
532 ASSERT_EQ(3, Find("351"));
533 ASSERT_EQ(3, Find("400"));
534 ASSERT_EQ(3, Find("450"));
535 ASSERT_EQ(4, Find("451"));
536
537 ASSERT_TRUE(! Overlaps("100", "149"));
538 ASSERT_TRUE(! Overlaps("251", "299"));
539 ASSERT_TRUE(! Overlaps("451", "500"));
540 ASSERT_TRUE(! Overlaps("351", "399"));
541
542 ASSERT_TRUE(Overlaps("100", "150"));
543 ASSERT_TRUE(Overlaps("100", "200"));
544 ASSERT_TRUE(Overlaps("100", "300"));
545 ASSERT_TRUE(Overlaps("100", "400"));
546 ASSERT_TRUE(Overlaps("100", "500"));
547 ASSERT_TRUE(Overlaps("375", "400"));
548 ASSERT_TRUE(Overlaps("450", "450"));
549 ASSERT_TRUE(Overlaps("450", "500"));
550}
551
552TEST_F(FindLevelFileTest, LevelMultipleNullBoundaries) {
553 LevelFileInit(4);
554
555 Add("150", "200");
556 Add("200", "250");
557 Add("300", "350");
558 Add("400", "450");
559 ASSERT_TRUE(! Overlaps(nullptr, "149"));
560 ASSERT_TRUE(! Overlaps("451", nullptr));
561 ASSERT_TRUE(Overlaps(nullptr, nullptr));
562 ASSERT_TRUE(Overlaps(nullptr, "150"));
563 ASSERT_TRUE(Overlaps(nullptr, "199"));
564 ASSERT_TRUE(Overlaps(nullptr, "200"));
565 ASSERT_TRUE(Overlaps(nullptr, "201"));
566 ASSERT_TRUE(Overlaps(nullptr, "400"));
567 ASSERT_TRUE(Overlaps(nullptr, "800"));
568 ASSERT_TRUE(Overlaps("100", nullptr));
569 ASSERT_TRUE(Overlaps("200", nullptr));
570 ASSERT_TRUE(Overlaps("449", nullptr));
571 ASSERT_TRUE(Overlaps("450", nullptr));
572}
573
574TEST_F(FindLevelFileTest, LevelOverlapSequenceChecks) {
575 LevelFileInit(1);
576
577 Add("200", "200", 5000, 3000);
578 ASSERT_TRUE(! Overlaps("199", "199"));
579 ASSERT_TRUE(! Overlaps("201", "300"));
580 ASSERT_TRUE(Overlaps("200", "200"));
581 ASSERT_TRUE(Overlaps("190", "200"));
582 ASSERT_TRUE(Overlaps("200", "210"));
583}
584
585TEST_F(FindLevelFileTest, LevelOverlappingFiles) {
586 LevelFileInit(2);
587
588 Add("150", "600");
589 Add("400", "500");
590 disjoint_sorted_files_ = false;
591 ASSERT_TRUE(! Overlaps("100", "149"));
592 ASSERT_TRUE(! Overlaps("601", "700"));
593 ASSERT_TRUE(Overlaps("100", "150"));
594 ASSERT_TRUE(Overlaps("100", "200"));
595 ASSERT_TRUE(Overlaps("100", "300"));
596 ASSERT_TRUE(Overlaps("100", "400"));
597 ASSERT_TRUE(Overlaps("100", "500"));
598 ASSERT_TRUE(Overlaps("375", "400"));
599 ASSERT_TRUE(Overlaps("450", "450"));
600 ASSERT_TRUE(Overlaps("450", "500"));
601 ASSERT_TRUE(Overlaps("450", "700"));
602 ASSERT_TRUE(Overlaps("600", "700"));
603}
604
494da23a 605class VersionSetTestBase {
11fdf7f2 606 public:
494da23a
TL
607 const static std::string kColumnFamilyName1;
608 const static std::string kColumnFamilyName2;
609 const static std::string kColumnFamilyName3;
610
611 VersionSetTestBase()
11fdf7f2
TL
612 : env_(Env::Default()),
613 dbname_(test::PerThreadDBPath("version_set_test")),
614 db_options_(),
615 mutable_cf_options_(cf_options_),
616 table_cache_(NewLRUCache(50000, 16)),
617 write_buffer_manager_(db_options_.db_write_buffer_size),
618 versions_(new VersionSet(dbname_, &db_options_, env_options_,
619 table_cache_.get(), &write_buffer_manager_,
620 &write_controller_)),
621 shutting_down_(false),
622 mock_table_factory_(std::make_shared<mock::MockTableFactory>()) {
623 EXPECT_OK(env_->CreateDirIfMissing(dbname_));
624 db_options_.db_paths.emplace_back(dbname_,
625 std::numeric_limits<uint64_t>::max());
626 }
627
494da23a
TL
628 void PrepareManifest(std::vector<ColumnFamilyDescriptor>* column_families,
629 SequenceNumber* last_seqno,
630 std::unique_ptr<log::Writer>* log_writer) {
631 assert(column_families != nullptr);
632 assert(last_seqno != nullptr);
633 assert(log_writer != nullptr);
11fdf7f2
TL
634 VersionEdit new_db;
635 new_db.SetLogNumber(0);
636 new_db.SetNextFile(2);
637 new_db.SetLastSequence(0);
638
494da23a
TL
639 const std::vector<std::string> cf_names = {
640 kDefaultColumnFamilyName, kColumnFamilyName1, kColumnFamilyName2,
641 kColumnFamilyName3};
11fdf7f2
TL
642 const int kInitialNumOfCfs = static_cast<int>(cf_names.size());
643 autovector<VersionEdit> new_cfs;
644 uint64_t last_seq = 1;
645 uint32_t cf_id = 1;
646 for (int i = 1; i != kInitialNumOfCfs; ++i) {
647 VersionEdit new_cf;
648 new_cf.AddColumnFamily(cf_names[i]);
649 new_cf.SetColumnFamily(cf_id++);
650 new_cf.SetLogNumber(0);
651 new_cf.SetNextFile(2);
652 new_cf.SetLastSequence(last_seq++);
653 new_cfs.emplace_back(new_cf);
654 }
494da23a 655 *last_seqno = last_seq;
11fdf7f2
TL
656
657 const std::string manifest = DescriptorFileName(dbname_, 1);
494da23a 658 std::unique_ptr<WritableFile> file;
11fdf7f2
TL
659 Status s = env_->NewWritableFile(
660 manifest, &file, env_->OptimizeForManifestWrite(env_options_));
661 ASSERT_OK(s);
494da23a 662 std::unique_ptr<WritableFileWriter> file_writer(
11fdf7f2
TL
663 new WritableFileWriter(std::move(file), manifest, env_options_));
664 {
494da23a 665 log_writer->reset(new log::Writer(std::move(file_writer), 0, false));
11fdf7f2
TL
666 std::string record;
667 new_db.EncodeTo(&record);
494da23a 668 s = (*log_writer)->AddRecord(record);
11fdf7f2 669 for (const auto& e : new_cfs) {
494da23a 670 record.clear();
11fdf7f2 671 e.EncodeTo(&record);
494da23a 672 s = (*log_writer)->AddRecord(record);
11fdf7f2
TL
673 ASSERT_OK(s);
674 }
675 }
676 ASSERT_OK(s);
11fdf7f2 677
11fdf7f2
TL
678 cf_options_.table_factory = mock_table_factory_;
679 for (const auto& cf_name : cf_names) {
494da23a 680 column_families->emplace_back(cf_name, cf_options_);
11fdf7f2 681 }
494da23a
TL
682 }
683
684 // Create DB with 3 column families.
685 void NewDB() {
686 std::vector<ColumnFamilyDescriptor> column_families;
687 SequenceNumber last_seqno;
688 std::unique_ptr<log::Writer> log_writer;
689
690 PrepareManifest(&column_families, &last_seqno, &log_writer);
691 log_writer.reset();
692 // Make "CURRENT" file point to the new manifest file.
693 Status s = SetCurrentFile(env_, dbname_, 1, nullptr);
694 ASSERT_OK(s);
11fdf7f2
TL
695
696 EXPECT_OK(versions_->Recover(column_families, false));
494da23a 697 EXPECT_EQ(column_families.size(),
11fdf7f2 698 versions_->GetColumnFamilySet()->NumberOfColumnFamilies());
11fdf7f2
TL
699 }
700
701 Env* env_;
702 const std::string dbname_;
703 EnvOptions env_options_;
704 ImmutableDBOptions db_options_;
705 ColumnFamilyOptions cf_options_;
706 MutableCFOptions mutable_cf_options_;
707 std::shared_ptr<Cache> table_cache_;
708 WriteController write_controller_;
709 WriteBufferManager write_buffer_manager_;
494da23a 710 std::shared_ptr<VersionSet> versions_;
11fdf7f2
TL
711 InstrumentedMutex mutex_;
712 std::atomic<bool> shutting_down_;
713 std::shared_ptr<mock::MockTableFactory> mock_table_factory_;
11fdf7f2
TL
714};
715
494da23a
TL
716const std::string VersionSetTestBase::kColumnFamilyName1 = "alice";
717const std::string VersionSetTestBase::kColumnFamilyName2 = "bob";
718const std::string VersionSetTestBase::kColumnFamilyName3 = "charles";
719
720class VersionSetTest : public VersionSetTestBase, public testing::Test {
721 public:
722 VersionSetTest() : VersionSetTestBase() {}
723};
724
725TEST_F(VersionSetTest, SameColumnFamilyGroupCommit) {
11fdf7f2
TL
726 NewDB();
727 const int kGroupSize = 5;
494da23a
TL
728 autovector<VersionEdit> edits;
729 for (int i = 0; i != kGroupSize; ++i) {
730 edits.emplace_back(VersionEdit());
731 }
732 autovector<ColumnFamilyData*> cfds;
733 autovector<const MutableCFOptions*> all_mutable_cf_options;
734 autovector<autovector<VersionEdit*>> edit_lists;
11fdf7f2 735 for (int i = 0; i != kGroupSize; ++i) {
494da23a
TL
736 cfds.emplace_back(versions_->GetColumnFamilySet()->GetDefault());
737 all_mutable_cf_options.emplace_back(&mutable_cf_options_);
738 autovector<VersionEdit*> edit_list;
739 edit_list.emplace_back(&edits[i]);
740 edit_lists.emplace_back(edit_list);
11fdf7f2
TL
741 }
742
494da23a
TL
743 SyncPoint::GetInstance()->DisableProcessing();
744 SyncPoint::GetInstance()->ClearAllCallBacks();
11fdf7f2
TL
745 int count = 0;
746 SyncPoint::GetInstance()->SetCallBack(
747 "VersionSet::ProcessManifestWrites:SameColumnFamily", [&](void* arg) {
748 uint32_t* cf_id = reinterpret_cast<uint32_t*>(arg);
749 EXPECT_EQ(0, *cf_id);
750 ++count;
751 });
752 SyncPoint::GetInstance()->EnableProcessing();
753 mutex_.Lock();
754 Status s =
755 versions_->LogAndApply(cfds, all_mutable_cf_options, edit_lists, &mutex_);
756 mutex_.Unlock();
757 EXPECT_OK(s);
758 EXPECT_EQ(kGroupSize - 1, count);
759}
494da23a
TL
760
761TEST_F(VersionSetTest, HandleValidAtomicGroup) {
762 std::vector<ColumnFamilyDescriptor> column_families;
763 SequenceNumber last_seqno;
764 std::unique_ptr<log::Writer> log_writer;
765 PrepareManifest(&column_families, &last_seqno, &log_writer);
766
767 // Append multiple version edits that form an atomic group
768 const int kAtomicGroupSize = 3;
769 std::vector<VersionEdit> edits(kAtomicGroupSize);
770 int remaining = kAtomicGroupSize;
771 for (size_t i = 0; i != edits.size(); ++i) {
772 edits[i].SetLogNumber(0);
773 edits[i].SetNextFile(2);
774 edits[i].MarkAtomicGroup(--remaining);
775 edits[i].SetLastSequence(last_seqno++);
776 }
777 Status s;
778 for (const auto& edit : edits) {
779 std::string record;
780 edit.EncodeTo(&record);
781 s = log_writer->AddRecord(record);
782 ASSERT_OK(s);
783 }
784 log_writer.reset();
785
786 s = SetCurrentFile(env_, dbname_, 1, nullptr);
787 ASSERT_OK(s);
788
789 SyncPoint::GetInstance()->DisableProcessing();
790 SyncPoint::GetInstance()->ClearAllCallBacks();
791
792 bool first_in_atomic_group = false;
793 bool last_in_atomic_group = false;
794
795 SyncPoint::GetInstance()->SetCallBack(
796 "VersionSet::Recover:FirstInAtomicGroup", [&](void* arg) {
797 VersionEdit* e = reinterpret_cast<VersionEdit*>(arg);
798 EXPECT_EQ(edits.front().DebugString(),
799 e->DebugString()); // compare based on value
800 first_in_atomic_group = true;
801 });
802 SyncPoint::GetInstance()->SetCallBack(
803 "VersionSet::Recover:LastInAtomicGroup", [&](void* arg) {
804 VersionEdit* e = reinterpret_cast<VersionEdit*>(arg);
805 EXPECT_EQ(edits.back().DebugString(),
806 e->DebugString()); // compare based on value
807 EXPECT_TRUE(first_in_atomic_group);
808 last_in_atomic_group = true;
809 });
810 SyncPoint::GetInstance()->EnableProcessing();
811
812 EXPECT_OK(versions_->Recover(column_families, false));
813 EXPECT_EQ(column_families.size(),
814 versions_->GetColumnFamilySet()->NumberOfColumnFamilies());
815 EXPECT_TRUE(first_in_atomic_group);
816 EXPECT_TRUE(last_in_atomic_group);
817}
818
819TEST_F(VersionSetTest, HandleIncompleteTrailingAtomicGroup) {
820 std::vector<ColumnFamilyDescriptor> column_families;
821 SequenceNumber last_seqno;
822 std::unique_ptr<log::Writer> log_writer;
823 PrepareManifest(&column_families, &last_seqno, &log_writer);
824
825 // Append multiple version edits that form an atomic group
826 const int kAtomicGroupSize = 4;
827 const int kNumberOfPersistedVersionEdits = kAtomicGroupSize - 1;
828 std::vector<VersionEdit> edits(kNumberOfPersistedVersionEdits);
829 int remaining = kAtomicGroupSize;
830 for (size_t i = 0; i != edits.size(); ++i) {
831 edits[i].SetLogNumber(0);
832 edits[i].SetNextFile(2);
833 edits[i].MarkAtomicGroup(--remaining);
834 edits[i].SetLastSequence(last_seqno++);
835 }
836 Status s;
837 for (const auto& edit : edits) {
838 std::string record;
839 edit.EncodeTo(&record);
840 s = log_writer->AddRecord(record);
841 ASSERT_OK(s);
842 }
843 log_writer.reset();
844
845 s = SetCurrentFile(env_, dbname_, 1, nullptr);
846 ASSERT_OK(s);
847
848 SyncPoint::GetInstance()->DisableProcessing();
849 SyncPoint::GetInstance()->ClearAllCallBacks();
850
851 bool first_in_atomic_group = false;
852 bool last_in_atomic_group = false;
853 size_t num = 0;
854
855 SyncPoint::GetInstance()->SetCallBack(
856 "VersionSet::Recover:FirstInAtomicGroup", [&](void* arg) {
857 VersionEdit* e = reinterpret_cast<VersionEdit*>(arg);
858 EXPECT_EQ(edits.front().DebugString(),
859 e->DebugString()); // compare based on value
860 first_in_atomic_group = true;
861 });
862 SyncPoint::GetInstance()->SetCallBack(
863 "VersionSet::Recover:LastInAtomicGroup",
864 [&](void* /* arg */) { last_in_atomic_group = true; });
865 SyncPoint::GetInstance()->SetCallBack("VersionSet::Recover:AtomicGroup",
866 [&](void* /* arg */) { ++num; });
867 SyncPoint::GetInstance()->EnableProcessing();
868
869 EXPECT_OK(versions_->Recover(column_families, false));
870 EXPECT_EQ(column_families.size(),
871 versions_->GetColumnFamilySet()->NumberOfColumnFamilies());
872 EXPECT_TRUE(first_in_atomic_group);
873 EXPECT_FALSE(last_in_atomic_group);
874 EXPECT_EQ(kNumberOfPersistedVersionEdits, num);
875}
876
877TEST_F(VersionSetTest, HandleCorruptedAtomicGroup) {
878 std::vector<ColumnFamilyDescriptor> column_families;
879 SequenceNumber last_seqno;
880 std::unique_ptr<log::Writer> log_writer;
881 PrepareManifest(&column_families, &last_seqno, &log_writer);
882
883 // Append multiple version edits that form an atomic group
884 const int kAtomicGroupSize = 4;
885 std::vector<VersionEdit> edits(kAtomicGroupSize);
886 int remaining = kAtomicGroupSize;
887 for (size_t i = 0; i != edits.size(); ++i) {
888 edits[i].SetLogNumber(0);
889 edits[i].SetNextFile(2);
890 if (i != (kAtomicGroupSize / 2)) {
891 edits[i].MarkAtomicGroup(--remaining);
892 }
893 edits[i].SetLastSequence(last_seqno++);
894 }
895 Status s;
896 for (const auto& edit : edits) {
897 std::string record;
898 edit.EncodeTo(&record);
899 s = log_writer->AddRecord(record);
900 ASSERT_OK(s);
901 }
902 log_writer.reset();
903
904 s = SetCurrentFile(env_, dbname_, 1, nullptr);
905 ASSERT_OK(s);
906
907 SyncPoint::GetInstance()->DisableProcessing();
908 SyncPoint::GetInstance()->ClearAllCallBacks();
909
910 bool mixed = false;
911 SyncPoint::GetInstance()->SetCallBack(
912 "VersionSet::Recover:AtomicGroupMixedWithNormalEdits", [&](void* arg) {
913 VersionEdit* e = reinterpret_cast<VersionEdit*>(arg);
914 EXPECT_EQ(edits[kAtomicGroupSize / 2].DebugString(), e->DebugString());
915 mixed = true;
916 });
917 SyncPoint::GetInstance()->EnableProcessing();
918 EXPECT_NOK(versions_->Recover(column_families, false));
919 EXPECT_EQ(column_families.size(),
920 versions_->GetColumnFamilySet()->NumberOfColumnFamilies());
921 EXPECT_TRUE(mixed);
922}
923
924TEST_F(VersionSetTest, HandleIncorrectAtomicGroupSize) {
925 std::vector<ColumnFamilyDescriptor> column_families;
926 SequenceNumber last_seqno;
927 std::unique_ptr<log::Writer> log_writer;
928 PrepareManifest(&column_families, &last_seqno, &log_writer);
929
930 // Append multiple version edits that form an atomic group
931 const int kAtomicGroupSize = 4;
932 std::vector<VersionEdit> edits(kAtomicGroupSize);
933 int remaining = kAtomicGroupSize;
934 for (size_t i = 0; i != edits.size(); ++i) {
935 edits[i].SetLogNumber(0);
936 edits[i].SetNextFile(2);
937 if (i != 1) {
938 edits[i].MarkAtomicGroup(--remaining);
939 } else {
940 edits[i].MarkAtomicGroup(remaining--);
941 }
942 edits[i].SetLastSequence(last_seqno++);
943 }
944 Status s;
945 for (const auto& edit : edits) {
946 std::string record;
947 edit.EncodeTo(&record);
948 s = log_writer->AddRecord(record);
949 ASSERT_OK(s);
950 }
951 log_writer.reset();
952
953 s = SetCurrentFile(env_, dbname_, 1, nullptr);
954 ASSERT_OK(s);
955
956 SyncPoint::GetInstance()->DisableProcessing();
957 SyncPoint::GetInstance()->ClearAllCallBacks();
958
959 bool incorrect_group_size = false;
960 SyncPoint::GetInstance()->SetCallBack(
961 "VersionSet::Recover:IncorrectAtomicGroupSize", [&](void* arg) {
962 VersionEdit* e = reinterpret_cast<VersionEdit*>(arg);
963 EXPECT_EQ(edits[1].DebugString(), e->DebugString());
964 incorrect_group_size = true;
965 });
966 SyncPoint::GetInstance()->EnableProcessing();
967 EXPECT_NOK(versions_->Recover(column_families, false));
968 EXPECT_EQ(column_families.size(),
969 versions_->GetColumnFamilySet()->NumberOfColumnFamilies());
970 EXPECT_TRUE(incorrect_group_size);
971}
972
973class VersionSetTestDropOneCF : public VersionSetTestBase,
974 public testing::TestWithParam<std::string> {
975 public:
976 VersionSetTestDropOneCF() : VersionSetTestBase() {}
977};
978
979// This test simulates the following execution sequence
980// Time thread1 bg_flush_thr
981// | Prepare version edits (e1,e2,e3) for atomic
982// | flush cf1, cf2, cf3
983// | Enqueue e to drop cfi
984// | to manifest_writers_
985// | Enqueue (e1,e2,e3) to manifest_writers_
986// |
987// | Apply e,
988// | cfi.IsDropped() is true
989// | Apply (e1,e2,e3),
990// | since cfi.IsDropped() == true, we need to
991// | drop ei and write the rest to MANIFEST.
992// V
993//
994// Repeat the test for i = 1, 2, 3 to simulate dropping the first, middle and
995// last column family in an atomic group.
996TEST_P(VersionSetTestDropOneCF, HandleDroppedColumnFamilyInAtomicGroup) {
997 std::vector<ColumnFamilyDescriptor> column_families;
998 SequenceNumber last_seqno;
999 std::unique_ptr<log::Writer> log_writer;
1000 PrepareManifest(&column_families, &last_seqno, &log_writer);
1001 Status s = SetCurrentFile(env_, dbname_, 1, nullptr);
1002 ASSERT_OK(s);
1003
1004 EXPECT_OK(versions_->Recover(column_families, false /* read_only */));
1005 EXPECT_EQ(column_families.size(),
1006 versions_->GetColumnFamilySet()->NumberOfColumnFamilies());
1007
1008 const int kAtomicGroupSize = 3;
1009 const std::vector<std::string> non_default_cf_names = {
1010 kColumnFamilyName1, kColumnFamilyName2, kColumnFamilyName3};
1011
1012 // Drop one column family
1013 VersionEdit drop_cf_edit;
1014 drop_cf_edit.DropColumnFamily();
1015 const std::string cf_to_drop_name(GetParam());
1016 auto cfd_to_drop =
1017 versions_->GetColumnFamilySet()->GetColumnFamily(cf_to_drop_name);
1018 ASSERT_NE(nullptr, cfd_to_drop);
1019 // Increase its refcount because cfd_to_drop is used later, and we need to
1020 // prevent it from being deleted.
1021 cfd_to_drop->Ref();
1022 drop_cf_edit.SetColumnFamily(cfd_to_drop->GetID());
1023 mutex_.Lock();
1024 s = versions_->LogAndApply(cfd_to_drop,
1025 *cfd_to_drop->GetLatestMutableCFOptions(),
1026 &drop_cf_edit, &mutex_);
1027 mutex_.Unlock();
1028 ASSERT_OK(s);
1029
1030 std::vector<VersionEdit> edits(kAtomicGroupSize);
1031 uint32_t remaining = kAtomicGroupSize;
1032 size_t i = 0;
1033 autovector<ColumnFamilyData*> cfds;
1034 autovector<const MutableCFOptions*> mutable_cf_options_list;
1035 autovector<autovector<VersionEdit*>> edit_lists;
1036 for (const auto& cf_name : non_default_cf_names) {
1037 auto cfd = (cf_name != cf_to_drop_name)
1038 ? versions_->GetColumnFamilySet()->GetColumnFamily(cf_name)
1039 : cfd_to_drop;
1040 ASSERT_NE(nullptr, cfd);
1041 cfds.push_back(cfd);
1042 mutable_cf_options_list.emplace_back(cfd->GetLatestMutableCFOptions());
1043 edits[i].SetColumnFamily(cfd->GetID());
1044 edits[i].SetLogNumber(0);
1045 edits[i].SetNextFile(2);
1046 edits[i].MarkAtomicGroup(--remaining);
1047 edits[i].SetLastSequence(last_seqno++);
1048 autovector<VersionEdit*> tmp_edits;
1049 tmp_edits.push_back(&edits[i]);
1050 edit_lists.emplace_back(tmp_edits);
1051 ++i;
1052 }
1053 int called = 0;
1054 SyncPoint::GetInstance()->DisableProcessing();
1055 SyncPoint::GetInstance()->ClearAllCallBacks();
1056 SyncPoint::GetInstance()->SetCallBack(
1057 "VersionSet::ProcessManifestWrites:CheckOneAtomicGroup", [&](void* arg) {
1058 std::vector<VersionEdit*>* tmp_edits =
1059 reinterpret_cast<std::vector<VersionEdit*>*>(arg);
1060 EXPECT_EQ(kAtomicGroupSize - 1, tmp_edits->size());
1061 for (const auto e : *tmp_edits) {
1062 bool found = false;
1063 for (const auto& e2 : edits) {
1064 if (&e2 == e) {
1065 found = true;
1066 break;
1067 }
1068 }
1069 ASSERT_TRUE(found);
1070 }
1071 ++called;
1072 });
1073 SyncPoint::GetInstance()->EnableProcessing();
1074 mutex_.Lock();
1075 s = versions_->LogAndApply(cfds, mutable_cf_options_list, edit_lists,
1076 &mutex_);
1077 mutex_.Unlock();
1078 ASSERT_OK(s);
1079 ASSERT_EQ(1, called);
1080 if (cfd_to_drop->Unref()) {
1081 delete cfd_to_drop;
1082 cfd_to_drop = nullptr;
1083 }
1084}
1085
1086INSTANTIATE_TEST_CASE_P(
1087 AtomicGroup, VersionSetTestDropOneCF,
1088 testing::Values(VersionSetTestBase::kColumnFamilyName1,
1089 VersionSetTestBase::kColumnFamilyName2,
1090 VersionSetTestBase::kColumnFamilyName3));
1091
7c673cae
FG
1092} // namespace rocksdb
1093
1094int main(int argc, char** argv) {
1095 ::testing::InitGoogleTest(&argc, argv);
1096 return RUN_ALL_TESTS();
1097}