1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
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.
10 #include "db/version_set.h"
11 #include "db/log_writer.h"
12 #include "table/mock_table.h"
13 #include "util/logging.h"
14 #include "util/string_util.h"
15 #include "util/testharness.h"
16 #include "util/testutil.h"
20 class GenerateLevelFilesBriefTest
: public testing::Test
{
22 std::vector
<FileMetaData
*> files_
;
23 LevelFilesBrief file_level_
;
26 GenerateLevelFilesBriefTest() { }
28 ~GenerateLevelFilesBriefTest() {
29 for (size_t i
= 0; i
< files_
.size(); i
++) {
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
);
46 for (size_t i
= 0; i
< files_
.size(); i
++) {
47 if (file_level_
.files
[i
].fd
.GetNumber() != files_
[i
]->fd
.GetNumber()) {
55 TEST_F(GenerateLevelFilesBriefTest
, Empty
) {
56 DoGenerateLevelFilesBrief(&file_level_
, files_
, &arena_
);
57 ASSERT_EQ(0u, file_level_
.num_files
);
58 ASSERT_EQ(0, Compare());
61 TEST_F(GenerateLevelFilesBriefTest
, Single
) {
63 DoGenerateLevelFilesBrief(&file_level_
, files_
, &arena_
);
64 ASSERT_EQ(1u, file_level_
.num_files
);
65 ASSERT_EQ(0, Compare());
68 TEST_F(GenerateLevelFilesBriefTest
, Multiple
) {
73 DoGenerateLevelFilesBrief(&file_level_
, files_
, &arena_
);
74 ASSERT_EQ(4u, file_level_
.num_files
);
75 ASSERT_EQ(0, Compare());
78 class CountingLogger
: public Logger
{
80 CountingLogger() : log_count(0) {}
82 virtual void Logv(const char* /*format*/, va_list /*ap*/) override
{
88 Options
GetOptionsWithNumLevels(int num_levels
,
89 std::shared_ptr
<CountingLogger
> logger
) {
91 opt
.num_levels
= num_levels
;
92 opt
.info_log
= logger
;
96 class VersionStorageInfoTest
: public testing::Test
{
98 const Comparator
* ucmp_
;
99 InternalKeyComparator icmp_
;
100 std::shared_ptr
<CountingLogger
> logger_
;
102 ImmutableCFOptions ioptions_
;
103 MutableCFOptions mutable_cf_options_
;
104 VersionStorageInfo vstorage_
;
106 InternalKey
GetInternalKey(const char* ukey
,
107 SequenceNumber smallest_seq
= 100) {
108 return InternalKey(ukey
, smallest_seq
, kTypeValue
);
111 VersionStorageInfoTest()
112 : ucmp_(BytewiseComparator()),
114 logger_(new CountingLogger()),
115 options_(GetOptionsWithNumLevels(6, logger_
)),
117 mutable_cf_options_(options_
),
118 vstorage_(&icmp_
, ucmp_
, 6, kCompactionStyleLevel
, nullptr, false) {}
120 ~VersionStorageInfoTest() {
121 for (int i
= 0; i
< vstorage_
.num_levels(); i
++) {
122 for (auto* f
: vstorage_
.LevelFiles(i
)) {
123 if (--f
->refs
== 0) {
130 void Add(int level
, uint32_t file_number
, const char* smallest
,
131 const char* largest
, uint64_t file_size
= 0) {
132 assert(level
< vstorage_
.num_levels());
133 FileMetaData
* f
= new FileMetaData
;
134 f
->fd
= FileDescriptor(file_number
, 0, file_size
);
135 f
->smallest
= GetInternalKey(smallest
, 0);
136 f
->largest
= GetInternalKey(largest
, 0);
137 f
->compensated_file_size
= file_size
;
140 f
->num_deletions
= 0;
141 vstorage_
.AddFile(level
, f
);
144 void Add(int level
, uint32_t file_number
, const InternalKey
& smallest
,
145 const InternalKey
& largest
, uint64_t file_size
= 0) {
146 assert(level
< vstorage_
.num_levels());
147 FileMetaData
* f
= new FileMetaData
;
148 f
->fd
= FileDescriptor(file_number
, 0, file_size
);
149 f
->smallest
= smallest
;
150 f
->largest
= largest
;
151 f
->compensated_file_size
= file_size
;
154 f
->num_deletions
= 0;
155 vstorage_
.AddFile(level
, f
);
158 std::string
GetOverlappingFiles(int level
, const InternalKey
& begin
,
159 const InternalKey
& end
) {
160 std::vector
<FileMetaData
*> inputs
;
161 vstorage_
.GetOverlappingInputs(level
, &begin
, &end
, &inputs
);
164 for (size_t i
= 0; i
< inputs
.size(); ++i
) {
168 AppendNumberTo(&result
, inputs
[i
]->fd
.GetNumber());
174 TEST_F(VersionStorageInfoTest
, MaxBytesForLevelStatic
) {
175 ioptions_
.level_compaction_dynamic_level_bytes
= false;
176 mutable_cf_options_
.max_bytes_for_level_base
= 10;
177 mutable_cf_options_
.max_bytes_for_level_multiplier
= 5;
178 Add(4, 100U, "1", "2");
179 Add(5, 101U, "1", "2");
181 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
182 ASSERT_EQ(vstorage_
.MaxBytesForLevel(1), 10U);
183 ASSERT_EQ(vstorage_
.MaxBytesForLevel(2), 50U);
184 ASSERT_EQ(vstorage_
.MaxBytesForLevel(3), 250U);
185 ASSERT_EQ(vstorage_
.MaxBytesForLevel(4), 1250U);
187 ASSERT_EQ(0, logger_
->log_count
);
190 TEST_F(VersionStorageInfoTest
, MaxBytesForLevelDynamic
) {
191 ioptions_
.level_compaction_dynamic_level_bytes
= true;
192 mutable_cf_options_
.max_bytes_for_level_base
= 1000;
193 mutable_cf_options_
.max_bytes_for_level_multiplier
= 5;
194 Add(5, 1U, "1", "2", 500U);
196 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
197 ASSERT_EQ(0, logger_
->log_count
);
198 ASSERT_EQ(vstorage_
.base_level(), 5);
200 Add(5, 2U, "3", "4", 550U);
201 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
202 ASSERT_EQ(0, logger_
->log_count
);
203 ASSERT_EQ(vstorage_
.MaxBytesForLevel(4), 1000U);
204 ASSERT_EQ(vstorage_
.base_level(), 4);
206 Add(4, 3U, "3", "4", 550U);
207 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
208 ASSERT_EQ(0, logger_
->log_count
);
209 ASSERT_EQ(vstorage_
.MaxBytesForLevel(4), 1000U);
210 ASSERT_EQ(vstorage_
.base_level(), 4);
212 Add(3, 4U, "3", "4", 250U);
213 Add(3, 5U, "5", "7", 300U);
214 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
215 ASSERT_EQ(1, logger_
->log_count
);
216 ASSERT_EQ(vstorage_
.MaxBytesForLevel(4), 1005U);
217 ASSERT_EQ(vstorage_
.MaxBytesForLevel(3), 1000U);
218 ASSERT_EQ(vstorage_
.base_level(), 3);
220 Add(1, 6U, "3", "4", 5U);
221 Add(1, 7U, "8", "9", 5U);
222 logger_
->log_count
= 0;
223 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
224 ASSERT_EQ(1, logger_
->log_count
);
225 ASSERT_GT(vstorage_
.MaxBytesForLevel(4), 1005U);
226 ASSERT_GT(vstorage_
.MaxBytesForLevel(3), 1005U);
227 ASSERT_EQ(vstorage_
.MaxBytesForLevel(2), 1005U);
228 ASSERT_EQ(vstorage_
.MaxBytesForLevel(1), 1000U);
229 ASSERT_EQ(vstorage_
.base_level(), 1);
232 TEST_F(VersionStorageInfoTest
, MaxBytesForLevelDynamicLotsOfData
) {
233 ioptions_
.level_compaction_dynamic_level_bytes
= true;
234 mutable_cf_options_
.max_bytes_for_level_base
= 100;
235 mutable_cf_options_
.max_bytes_for_level_multiplier
= 2;
236 Add(0, 1U, "1", "2", 50U);
237 Add(1, 2U, "1", "2", 50U);
238 Add(2, 3U, "1", "2", 500U);
239 Add(3, 4U, "1", "2", 500U);
240 Add(4, 5U, "1", "2", 1700U);
241 Add(5, 6U, "1", "2", 500U);
243 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
244 ASSERT_EQ(vstorage_
.MaxBytesForLevel(4), 800U);
245 ASSERT_EQ(vstorage_
.MaxBytesForLevel(3), 400U);
246 ASSERT_EQ(vstorage_
.MaxBytesForLevel(2), 200U);
247 ASSERT_EQ(vstorage_
.MaxBytesForLevel(1), 100U);
248 ASSERT_EQ(vstorage_
.base_level(), 1);
249 ASSERT_EQ(0, logger_
->log_count
);
252 TEST_F(VersionStorageInfoTest
, MaxBytesForLevelDynamicLargeLevel
) {
253 uint64_t kOneGB
= 1000U * 1000U * 1000U;
254 ioptions_
.level_compaction_dynamic_level_bytes
= true;
255 mutable_cf_options_
.max_bytes_for_level_base
= 10U * kOneGB
;
256 mutable_cf_options_
.max_bytes_for_level_multiplier
= 10;
257 Add(0, 1U, "1", "2", 50U);
258 Add(3, 4U, "1", "2", 32U * kOneGB
);
259 Add(4, 5U, "1", "2", 500U * kOneGB
);
260 Add(5, 6U, "1", "2", 3000U * kOneGB
);
262 vstorage_
.CalculateBaseBytes(ioptions_
, mutable_cf_options_
);
263 ASSERT_EQ(vstorage_
.MaxBytesForLevel(5), 3000U * kOneGB
);
264 ASSERT_EQ(vstorage_
.MaxBytesForLevel(4), 300U * kOneGB
);
265 ASSERT_EQ(vstorage_
.MaxBytesForLevel(3), 30U * kOneGB
);
266 ASSERT_EQ(vstorage_
.MaxBytesForLevel(2), 10U * kOneGB
);
267 ASSERT_EQ(vstorage_
.base_level(), 2);
268 ASSERT_EQ(0, logger_
->log_count
);
271 TEST_F(VersionStorageInfoTest
, EstimateLiveDataSize
) {
272 // Test whether the overlaps are detected as expected
273 Add(1, 1U, "4", "7", 1U); // Perfect overlap with last level
274 Add(2, 2U, "3", "5", 1U); // Partial overlap with last level
275 Add(2, 3U, "6", "8", 1U); // Partial overlap with last level
276 Add(3, 4U, "1", "9", 1U); // Contains range of last level
277 Add(4, 5U, "4", "5", 1U); // Inside range of last level
278 Add(4, 5U, "6", "7", 1U); // Inside range of last level
279 Add(5, 6U, "4", "7", 10U);
280 ASSERT_EQ(10U, vstorage_
.EstimateLiveDataSize());
283 TEST_F(VersionStorageInfoTest
, EstimateLiveDataSize2
) {
284 Add(0, 1U, "9", "9", 1U); // Level 0 is not ordered
285 Add(0, 1U, "5", "6", 1U); // Ignored because of [5,6] in l1
286 Add(1, 1U, "1", "2", 1U); // Ignored because of [2,3] in l2
287 Add(1, 2U, "3", "4", 1U); // Ignored because of [2,3] in l2
288 Add(1, 3U, "5", "6", 1U);
289 Add(2, 4U, "2", "3", 1U);
290 Add(3, 5U, "7", "8", 1U);
291 ASSERT_EQ(4U, vstorage_
.EstimateLiveDataSize());
294 TEST_F(VersionStorageInfoTest
, GetOverlappingInputs
) {
295 // Two files that overlap at the range deletion tombstone sentinel.
296 Add(1, 1U, {"a", 0, kTypeValue
}, {"b", kMaxSequenceNumber
, kTypeRangeDeletion
}, 1);
297 Add(1, 2U, {"b", 0, kTypeValue
}, {"c", 0, kTypeValue
}, 1);
298 // Two files that overlap at the same user key.
299 Add(1, 3U, {"d", 0, kTypeValue
}, {"e", kMaxSequenceNumber
, kTypeValue
}, 1);
300 Add(1, 4U, {"e", 0, kTypeValue
}, {"f", 0, kTypeValue
}, 1);
301 // Two files that do not overlap.
302 Add(1, 5U, {"g", 0, kTypeValue
}, {"h", 0, kTypeValue
}, 1);
303 Add(1, 6U, {"i", 0, kTypeValue
}, {"j", 0, kTypeValue
}, 1);
304 vstorage_
.UpdateNumNonEmptyLevels();
305 vstorage_
.GenerateLevelFilesBrief();
307 ASSERT_EQ("1,2", GetOverlappingFiles(
308 1, {"a", 0, kTypeValue
}, {"b", 0, kTypeValue
}));
309 ASSERT_EQ("1", GetOverlappingFiles(
310 1, {"a", 0, kTypeValue
}, {"b", kMaxSequenceNumber
, kTypeRangeDeletion
}));
311 ASSERT_EQ("2", GetOverlappingFiles(
312 1, {"b", kMaxSequenceNumber
, kTypeValue
}, {"c", 0, kTypeValue
}));
313 ASSERT_EQ("3,4", GetOverlappingFiles(
314 1, {"d", 0, kTypeValue
}, {"e", 0, kTypeValue
}));
315 ASSERT_EQ("3", GetOverlappingFiles(
316 1, {"d", 0, kTypeValue
}, {"e", kMaxSequenceNumber
, kTypeRangeDeletion
}));
317 ASSERT_EQ("3,4", GetOverlappingFiles(
318 1, {"e", kMaxSequenceNumber
, kTypeValue
}, {"f", 0, kTypeValue
}));
319 ASSERT_EQ("3,4", GetOverlappingFiles(
320 1, {"e", 0, kTypeValue
}, {"f", 0, kTypeValue
}));
321 ASSERT_EQ("5", GetOverlappingFiles(
322 1, {"g", 0, kTypeValue
}, {"h", 0, kTypeValue
}));
323 ASSERT_EQ("6", GetOverlappingFiles(
324 1, {"i", 0, kTypeValue
}, {"j", 0, kTypeValue
}));
328 class FindLevelFileTest
: public testing::Test
{
330 LevelFilesBrief file_level_
;
331 bool disjoint_sorted_files_
;
334 FindLevelFileTest() : disjoint_sorted_files_(true) { }
336 ~FindLevelFileTest() {
339 void LevelFileInit(size_t num
= 0) {
340 char* mem
= arena_
.AllocateAligned(num
* sizeof(FdWithKeyRange
));
341 file_level_
.files
= new (mem
)FdWithKeyRange
[num
];
342 file_level_
.num_files
= 0;
345 void Add(const char* smallest
, const char* largest
,
346 SequenceNumber smallest_seq
= 100,
347 SequenceNumber largest_seq
= 100) {
348 InternalKey smallest_key
= InternalKey(smallest
, smallest_seq
, kTypeValue
);
349 InternalKey largest_key
= InternalKey(largest
, largest_seq
, kTypeValue
);
351 Slice smallest_slice
= smallest_key
.Encode();
352 Slice largest_slice
= largest_key
.Encode();
354 char* mem
= arena_
.AllocateAligned(
355 smallest_slice
.size() + largest_slice
.size());
356 memcpy(mem
, smallest_slice
.data(), smallest_slice
.size());
357 memcpy(mem
+ smallest_slice
.size(), largest_slice
.data(),
358 largest_slice
.size());
360 // add to file_level_
361 size_t num
= file_level_
.num_files
;
362 auto& file
= file_level_
.files
[num
];
363 file
.fd
= FileDescriptor(num
+ 1, 0, 0);
364 file
.smallest_key
= Slice(mem
, smallest_slice
.size());
365 file
.largest_key
= Slice(mem
+ smallest_slice
.size(),
366 largest_slice
.size());
367 file_level_
.num_files
++;
370 int Find(const char* key
) {
371 InternalKey
target(key
, 100, kTypeValue
);
372 InternalKeyComparator
cmp(BytewiseComparator());
373 return FindFile(cmp
, file_level_
, target
.Encode());
376 bool Overlaps(const char* smallest
, const char* largest
) {
377 InternalKeyComparator
cmp(BytewiseComparator());
378 Slice
s(smallest
!= nullptr ? smallest
: "");
379 Slice
l(largest
!= nullptr ? largest
: "");
380 return SomeFileOverlapsRange(cmp
, disjoint_sorted_files_
, file_level_
,
381 (smallest
!= nullptr ? &s
: nullptr),
382 (largest
!= nullptr ? &l
: nullptr));
386 TEST_F(FindLevelFileTest
, LevelEmpty
) {
389 ASSERT_EQ(0, Find("foo"));
390 ASSERT_TRUE(! Overlaps("a", "z"));
391 ASSERT_TRUE(! Overlaps(nullptr, "z"));
392 ASSERT_TRUE(! Overlaps("a", nullptr));
393 ASSERT_TRUE(! Overlaps(nullptr, nullptr));
396 TEST_F(FindLevelFileTest
, LevelSingle
) {
400 ASSERT_EQ(0, Find("a"));
401 ASSERT_EQ(0, Find("p"));
402 ASSERT_EQ(0, Find("p1"));
403 ASSERT_EQ(0, Find("q"));
404 ASSERT_EQ(1, Find("q1"));
405 ASSERT_EQ(1, Find("z"));
407 ASSERT_TRUE(! Overlaps("a", "b"));
408 ASSERT_TRUE(! Overlaps("z1", "z2"));
409 ASSERT_TRUE(Overlaps("a", "p"));
410 ASSERT_TRUE(Overlaps("a", "q"));
411 ASSERT_TRUE(Overlaps("a", "z"));
412 ASSERT_TRUE(Overlaps("p", "p1"));
413 ASSERT_TRUE(Overlaps("p", "q"));
414 ASSERT_TRUE(Overlaps("p", "z"));
415 ASSERT_TRUE(Overlaps("p1", "p2"));
416 ASSERT_TRUE(Overlaps("p1", "z"));
417 ASSERT_TRUE(Overlaps("q", "q"));
418 ASSERT_TRUE(Overlaps("q", "q1"));
420 ASSERT_TRUE(! Overlaps(nullptr, "j"));
421 ASSERT_TRUE(! Overlaps("r", nullptr));
422 ASSERT_TRUE(Overlaps(nullptr, "p"));
423 ASSERT_TRUE(Overlaps(nullptr, "p1"));
424 ASSERT_TRUE(Overlaps("q", nullptr));
425 ASSERT_TRUE(Overlaps(nullptr, nullptr));
428 TEST_F(FindLevelFileTest
, LevelMultiple
) {
435 ASSERT_EQ(0, Find("100"));
436 ASSERT_EQ(0, Find("150"));
437 ASSERT_EQ(0, Find("151"));
438 ASSERT_EQ(0, Find("199"));
439 ASSERT_EQ(0, Find("200"));
440 ASSERT_EQ(1, Find("201"));
441 ASSERT_EQ(1, Find("249"));
442 ASSERT_EQ(1, Find("250"));
443 ASSERT_EQ(2, Find("251"));
444 ASSERT_EQ(2, Find("299"));
445 ASSERT_EQ(2, Find("300"));
446 ASSERT_EQ(2, Find("349"));
447 ASSERT_EQ(2, Find("350"));
448 ASSERT_EQ(3, Find("351"));
449 ASSERT_EQ(3, Find("400"));
450 ASSERT_EQ(3, Find("450"));
451 ASSERT_EQ(4, Find("451"));
453 ASSERT_TRUE(! Overlaps("100", "149"));
454 ASSERT_TRUE(! Overlaps("251", "299"));
455 ASSERT_TRUE(! Overlaps("451", "500"));
456 ASSERT_TRUE(! Overlaps("351", "399"));
458 ASSERT_TRUE(Overlaps("100", "150"));
459 ASSERT_TRUE(Overlaps("100", "200"));
460 ASSERT_TRUE(Overlaps("100", "300"));
461 ASSERT_TRUE(Overlaps("100", "400"));
462 ASSERT_TRUE(Overlaps("100", "500"));
463 ASSERT_TRUE(Overlaps("375", "400"));
464 ASSERT_TRUE(Overlaps("450", "450"));
465 ASSERT_TRUE(Overlaps("450", "500"));
468 TEST_F(FindLevelFileTest
, LevelMultipleNullBoundaries
) {
475 ASSERT_TRUE(! Overlaps(nullptr, "149"));
476 ASSERT_TRUE(! Overlaps("451", nullptr));
477 ASSERT_TRUE(Overlaps(nullptr, nullptr));
478 ASSERT_TRUE(Overlaps(nullptr, "150"));
479 ASSERT_TRUE(Overlaps(nullptr, "199"));
480 ASSERT_TRUE(Overlaps(nullptr, "200"));
481 ASSERT_TRUE(Overlaps(nullptr, "201"));
482 ASSERT_TRUE(Overlaps(nullptr, "400"));
483 ASSERT_TRUE(Overlaps(nullptr, "800"));
484 ASSERT_TRUE(Overlaps("100", nullptr));
485 ASSERT_TRUE(Overlaps("200", nullptr));
486 ASSERT_TRUE(Overlaps("449", nullptr));
487 ASSERT_TRUE(Overlaps("450", nullptr));
490 TEST_F(FindLevelFileTest
, LevelOverlapSequenceChecks
) {
493 Add("200", "200", 5000, 3000);
494 ASSERT_TRUE(! Overlaps("199", "199"));
495 ASSERT_TRUE(! Overlaps("201", "300"));
496 ASSERT_TRUE(Overlaps("200", "200"));
497 ASSERT_TRUE(Overlaps("190", "200"));
498 ASSERT_TRUE(Overlaps("200", "210"));
501 TEST_F(FindLevelFileTest
, LevelOverlappingFiles
) {
506 disjoint_sorted_files_
= false;
507 ASSERT_TRUE(! Overlaps("100", "149"));
508 ASSERT_TRUE(! Overlaps("601", "700"));
509 ASSERT_TRUE(Overlaps("100", "150"));
510 ASSERT_TRUE(Overlaps("100", "200"));
511 ASSERT_TRUE(Overlaps("100", "300"));
512 ASSERT_TRUE(Overlaps("100", "400"));
513 ASSERT_TRUE(Overlaps("100", "500"));
514 ASSERT_TRUE(Overlaps("375", "400"));
515 ASSERT_TRUE(Overlaps("450", "450"));
516 ASSERT_TRUE(Overlaps("450", "500"));
517 ASSERT_TRUE(Overlaps("450", "700"));
518 ASSERT_TRUE(Overlaps("600", "700"));
521 class ManifestWriterTest
: public testing::Test
{
524 : env_(Env::Default()),
525 dbname_(test::PerThreadDBPath("version_set_test")),
527 mutable_cf_options_(cf_options_
),
528 table_cache_(NewLRUCache(50000, 16)),
529 write_buffer_manager_(db_options_
.db_write_buffer_size
),
530 versions_(new VersionSet(dbname_
, &db_options_
, env_options_
,
531 table_cache_
.get(), &write_buffer_manager_
,
532 &write_controller_
)),
533 shutting_down_(false),
534 mock_table_factory_(std::make_shared
<mock::MockTableFactory
>()) {
535 EXPECT_OK(env_
->CreateDirIfMissing(dbname_
));
536 db_options_
.db_paths
.emplace_back(dbname_
,
537 std::numeric_limits
<uint64_t>::max());
540 // Create DB with 3 column families.
543 new_db
.SetLogNumber(0);
544 new_db
.SetNextFile(2);
545 new_db
.SetLastSequence(0);
547 const std::vector
<std::string
> cf_names
= {kDefaultColumnFamilyName
,
549 const int kInitialNumOfCfs
= static_cast<int>(cf_names
.size());
550 autovector
<VersionEdit
> new_cfs
;
551 uint64_t last_seq
= 1;
553 for (int i
= 1; i
!= kInitialNumOfCfs
; ++i
) {
555 new_cf
.AddColumnFamily(cf_names
[i
]);
556 new_cf
.SetColumnFamily(cf_id
++);
557 new_cf
.SetLogNumber(0);
558 new_cf
.SetNextFile(2);
559 new_cf
.SetLastSequence(last_seq
++);
560 new_cfs
.emplace_back(new_cf
);
563 const std::string manifest
= DescriptorFileName(dbname_
, 1);
564 unique_ptr
<WritableFile
> file
;
565 Status s
= env_
->NewWritableFile(
566 manifest
, &file
, env_
->OptimizeForManifestWrite(env_options_
));
568 unique_ptr
<WritableFileWriter
> file_writer(
569 new WritableFileWriter(std::move(file
), manifest
, env_options_
));
571 log::Writer
log(std::move(file_writer
), 0, false);
573 new_db
.EncodeTo(&record
);
574 s
= log
.AddRecord(record
);
575 for (const auto& e
: new_cfs
) {
577 s
= log
.AddRecord(record
);
582 // Make "CURRENT" file point to the new manifest file.
583 s
= SetCurrentFile(env_
, dbname_
, 1, nullptr);
585 std::vector
<ColumnFamilyDescriptor
> column_families
;
586 cf_options_
.table_factory
= mock_table_factory_
;
587 for (const auto& cf_name
: cf_names
) {
588 column_families
.emplace_back(cf_name
, cf_options_
);
591 EXPECT_OK(versions_
->Recover(column_families
, false));
592 EXPECT_EQ(kInitialNumOfCfs
,
593 versions_
->GetColumnFamilySet()->NumberOfColumnFamilies());
594 for (auto cfd
: *versions_
->GetColumnFamilySet()) {
595 cfds_
.emplace_back(cfd
);
600 const std::string dbname_
;
601 EnvOptions env_options_
;
602 ImmutableDBOptions db_options_
;
603 ColumnFamilyOptions cf_options_
;
604 MutableCFOptions mutable_cf_options_
;
605 std::shared_ptr
<Cache
> table_cache_
;
606 WriteController write_controller_
;
607 WriteBufferManager write_buffer_manager_
;
608 std::unique_ptr
<VersionSet
> versions_
;
609 InstrumentedMutex mutex_
;
610 std::atomic
<bool> shutting_down_
;
611 std::shared_ptr
<mock::MockTableFactory
> mock_table_factory_
;
612 std::vector
<ColumnFamilyData
*> cfds_
;
615 TEST_F(ManifestWriterTest
, SameColumnFamilyGroupCommit
) {
617 const int kGroupSize
= 5;
618 std::vector
<VersionEdit
> edits(kGroupSize
);
619 std::vector
<ColumnFamilyData
*> cfds(kGroupSize
, cfds_
[0]);
620 std::vector
<MutableCFOptions
> all_mutable_cf_options(kGroupSize
,
621 mutable_cf_options_
);
622 std::vector
<autovector
<VersionEdit
*>> edit_lists(kGroupSize
);
623 for (int i
= 0; i
!= kGroupSize
; ++i
) {
624 edit_lists
[i
].emplace_back(&edits
[i
]);
628 SyncPoint::GetInstance()->SetCallBack(
629 "VersionSet::ProcessManifestWrites:SameColumnFamily", [&](void* arg
) {
630 uint32_t* cf_id
= reinterpret_cast<uint32_t*>(arg
);
631 EXPECT_EQ(0, *cf_id
);
634 SyncPoint::GetInstance()->EnableProcessing();
637 versions_
->LogAndApply(cfds
, all_mutable_cf_options
, edit_lists
, &mutex_
);
640 EXPECT_EQ(kGroupSize
- 1, count
);
642 } // namespace rocksdb
644 int main(int argc
, char** argv
) {
645 ::testing::InitGoogleTest(&argc
, argv
);
646 return RUN_ALL_TESTS();