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.
11 #include <unordered_map>
13 #include "db/column_family.h"
14 #include "db/db_impl.h"
15 #include "db/db_test_util.h"
16 #include "options/options_helper.h"
17 #include "port/stack_trace.h"
18 #include "rocksdb/cache.h"
19 #include "rocksdb/convenience.h"
20 #include "rocksdb/rate_limiter.h"
21 #include "util/random.h"
22 #include "util/sync_point.h"
23 #include "util/testutil.h"
27 class DBOptionsTest
: public DBTestBase
{
29 DBOptionsTest() : DBTestBase("/db_options_test") {}
32 std::unordered_map
<std::string
, std::string
> GetMutableDBOptionsMap(
33 const DBOptions
& options
) {
34 std::string options_str
;
35 GetStringFromDBOptions(&options_str
, options
);
36 std::unordered_map
<std::string
, std::string
> options_map
;
37 StringToMap(options_str
, &options_map
);
38 std::unordered_map
<std::string
, std::string
> mutable_map
;
39 for (const auto opt
: db_options_type_info
) {
40 if (opt
.second
.is_mutable
&&
41 opt
.second
.verification
!= OptionVerificationType::kDeprecated
) {
42 mutable_map
[opt
.first
] = options_map
[opt
.first
];
48 std::unordered_map
<std::string
, std::string
> GetMutableCFOptionsMap(
49 const ColumnFamilyOptions
& options
) {
50 std::string options_str
;
51 GetStringFromColumnFamilyOptions(&options_str
, options
);
52 std::unordered_map
<std::string
, std::string
> options_map
;
53 StringToMap(options_str
, &options_map
);
54 std::unordered_map
<std::string
, std::string
> mutable_map
;
55 for (const auto opt
: cf_options_type_info
) {
56 if (opt
.second
.is_mutable
&&
57 opt
.second
.verification
!= OptionVerificationType::kDeprecated
) {
58 mutable_map
[opt
.first
] = options_map
[opt
.first
];
64 std::unordered_map
<std::string
, std::string
> GetRandomizedMutableCFOptionsMap(
68 ImmutableDBOptions
db_options(options
);
69 test::RandomInitCFOptions(&options
, rnd
);
70 auto sanitized_options
= SanitizeOptions(db_options
, options
);
71 auto opt_map
= GetMutableCFOptionsMap(sanitized_options
);
72 delete options
.compaction_filter
;
76 std::unordered_map
<std::string
, std::string
> GetRandomizedMutableDBOptionsMap(
79 test::RandomInitDBOptions(&db_options
, rnd
);
80 auto sanitized_options
= SanitizeOptions(dbname_
, db_options
);
81 return GetMutableDBOptionsMap(sanitized_options
);
83 #endif // ROCKSDB_LITE
86 // RocksDB lite don't support dynamic options.
89 TEST_F(DBOptionsTest
, GetLatestDBOptions
) {
90 // GetOptions should be able to get latest option changed by SetOptions.
92 options
.create_if_missing
= true;
96 auto new_options
= GetRandomizedMutableDBOptionsMap(&rnd
);
97 ASSERT_OK(dbfull()->SetDBOptions(new_options
));
98 ASSERT_EQ(new_options
, GetMutableDBOptionsMap(dbfull()->GetDBOptions()));
101 TEST_F(DBOptionsTest
, GetLatestCFOptions
) {
102 // GetOptions should be able to get latest option changed by SetOptions.
104 options
.create_if_missing
= true;
108 CreateColumnFamilies({"foo"}, options
);
109 ReopenWithColumnFamilies({"default", "foo"}, options
);
110 auto options_default
= GetRandomizedMutableCFOptionsMap(&rnd
);
111 auto options_foo
= GetRandomizedMutableCFOptionsMap(&rnd
);
112 ASSERT_OK(dbfull()->SetOptions(handles_
[0], options_default
));
113 ASSERT_OK(dbfull()->SetOptions(handles_
[1], options_foo
));
114 ASSERT_EQ(options_default
,
115 GetMutableCFOptionsMap(dbfull()->GetOptions(handles_
[0])));
116 ASSERT_EQ(options_foo
,
117 GetMutableCFOptionsMap(dbfull()->GetOptions(handles_
[1])));
120 TEST_F(DBOptionsTest
, SetBytesPerSync
) {
121 const size_t kValueSize
= 1024 * 1024; // 1MB
123 options
.create_if_missing
= true;
124 options
.bytes_per_sync
= 1024 * 1024;
125 options
.use_direct_reads
= false;
126 options
.write_buffer_size
= 400 * kValueSize
;
127 options
.disable_auto_compactions
= true;
128 options
.compression
= kNoCompression
;
132 int low_bytes_per_sync
= 0;
134 const std::string
kValue(kValueSize
, 'v');
135 ASSERT_EQ(options
.bytes_per_sync
, dbfull()->GetDBOptions().bytes_per_sync
);
136 rocksdb::SyncPoint::GetInstance()->SetCallBack(
137 "WritableFileWriter::RangeSync:0", [&](void* /*arg*/) {
141 WriteOptions write_opts
;
142 // should sync approximately 40MB/1MB ~= 40 times.
143 for (i
= 0; i
< 40; i
++) {
144 Put(Key(i
), kValue
, write_opts
);
146 rocksdb::SyncPoint::GetInstance()->EnableProcessing();
147 ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
148 rocksdb::SyncPoint::GetInstance()->DisableProcessing();
149 low_bytes_per_sync
= counter
;
150 ASSERT_GT(low_bytes_per_sync
, 35);
151 ASSERT_LT(low_bytes_per_sync
, 45);
154 // 8388608 = 8 * 1024 * 1024
155 ASSERT_OK(dbfull()->SetDBOptions({{"bytes_per_sync", "8388608"}}));
156 ASSERT_EQ(8388608, dbfull()->GetDBOptions().bytes_per_sync
);
157 // should sync approximately 40MB*2/8MB ~= 10 times.
158 // data will be 40*2MB because of previous Puts too.
159 for (i
= 0; i
< 40; i
++) {
160 Put(Key(i
), kValue
, write_opts
);
162 rocksdb::SyncPoint::GetInstance()->EnableProcessing();
163 ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
164 ASSERT_GT(counter
, 5);
165 ASSERT_LT(counter
, 15);
167 // Redundant assert. But leaving it here just to get the point across that
168 // low_bytes_per_sync > counter.
169 ASSERT_GT(low_bytes_per_sync
, counter
);
172 TEST_F(DBOptionsTest
, SetWalBytesPerSync
) {
173 const size_t kValueSize
= 1024 * 1024 * 3;
175 options
.create_if_missing
= true;
176 options
.wal_bytes_per_sync
= 512;
177 options
.write_buffer_size
= 100 * kValueSize
;
178 options
.disable_auto_compactions
= true;
179 options
.compression
= kNoCompression
;
182 ASSERT_EQ(512, dbfull()->GetDBOptions().wal_bytes_per_sync
);
184 int low_bytes_per_sync
= 0;
185 rocksdb::SyncPoint::GetInstance()->SetCallBack(
186 "WritableFileWriter::RangeSync:0", [&](void* /*arg*/) {
189 rocksdb::SyncPoint::GetInstance()->EnableProcessing();
190 const std::string
kValue(kValueSize
, 'v');
192 for (; i
< 10; i
++) {
195 // Do not flush. If we flush here, SwitchWAL will reuse old WAL file since its
196 // empty and will not get the new wal_bytes_per_sync value.
197 low_bytes_per_sync
= counter
;
198 //5242880 = 1024 * 1024 * 5
199 ASSERT_OK(dbfull()->SetDBOptions({{"wal_bytes_per_sync", "5242880"}}));
200 ASSERT_EQ(5242880, dbfull()->GetDBOptions().wal_bytes_per_sync
);
203 for (; i
< 10; i
++) {
206 ASSERT_GT(counter
, 0);
207 ASSERT_GT(low_bytes_per_sync
, 0);
208 ASSERT_GT(low_bytes_per_sync
, counter
);
211 TEST_F(DBOptionsTest
, WritableFileMaxBufferSize
) {
213 options
.create_if_missing
= true;
214 options
.writable_file_max_buffer_size
= 1024 * 1024;
215 options
.level0_file_num_compaction_trigger
= 3;
216 options
.max_manifest_file_size
= 1;
218 int buffer_size
= 1024 * 1024;
220 ASSERT_EQ(buffer_size
,
221 dbfull()->GetDBOptions().writable_file_max_buffer_size
);
223 std::atomic
<int> match_cnt(0);
224 std::atomic
<int> unmatch_cnt(0);
225 rocksdb::SyncPoint::GetInstance()->SetCallBack(
226 "WritableFileWriter::WritableFileWriter:0", [&](void* arg
) {
227 int value
= static_cast<int>(reinterpret_cast<uintptr_t>(arg
));
228 if (value
== buffer_size
) {
234 rocksdb::SyncPoint::GetInstance()->EnableProcessing();
237 ASSERT_OK(Put("foo", ToString(i
)));
238 ASSERT_OK(Put("bar", ToString(i
)));
241 dbfull()->TEST_WaitForCompact();
242 ASSERT_EQ(unmatch_cnt
, 0);
243 ASSERT_GE(match_cnt
, 11);
246 dbfull()->SetDBOptions({{"writable_file_max_buffer_size", "524288"}}));
247 buffer_size
= 512 * 1024;
249 unmatch_cnt
= 0; // SetDBOptions() will create a WriteableFileWriter
251 ASSERT_EQ(buffer_size
,
252 dbfull()->GetDBOptions().writable_file_max_buffer_size
);
255 ASSERT_OK(Put("foo", ToString(i
)));
256 ASSERT_OK(Put("bar", ToString(i
)));
259 dbfull()->TEST_WaitForCompact();
260 ASSERT_EQ(unmatch_cnt
, 0);
261 ASSERT_GE(match_cnt
, 11);
264 TEST_F(DBOptionsTest
, SetOptionsAndReopen
) {
266 auto rand_opts
= GetRandomizedMutableCFOptionsMap(&rnd
);
267 ASSERT_OK(dbfull()->SetOptions(rand_opts
));
268 // Verify if DB can be reopen after setting options.
271 ASSERT_OK(TryReopen(options
));
274 TEST_F(DBOptionsTest
, EnableAutoCompactionAndTriggerStall
) {
275 const std::string
kValue(1024, 'v');
276 for (int method_type
= 0; method_type
< 2; method_type
++) {
277 for (int option_type
= 0; option_type
< 4; option_type
++) {
279 options
.create_if_missing
= true;
280 options
.disable_auto_compactions
= true;
281 options
.write_buffer_size
= 1024 * 1024 * 10;
282 options
.compression
= CompressionType::kNoCompression
;
283 options
.level0_file_num_compaction_trigger
= 1;
284 options
.level0_stop_writes_trigger
= std::numeric_limits
<int>::max();
285 options
.level0_slowdown_writes_trigger
= std::numeric_limits
<int>::max();
286 options
.hard_pending_compaction_bytes_limit
=
287 std::numeric_limits
<uint64_t>::max();
288 options
.soft_pending_compaction_bytes_limit
=
289 std::numeric_limits
<uint64_t>::max();
292 DestroyAndReopen(options
);
294 for (; i
< 1024; i
++) {
298 for (; i
< 1024 * 2; i
++) {
302 dbfull()->TEST_WaitForFlushMemTable();
303 ASSERT_EQ(2, NumTableFilesAtLevel(0));
304 uint64_t l0_size
= SizeAtLevel(0);
306 switch (option_type
) {
308 // test with level0_stop_writes_trigger
309 options
.level0_stop_writes_trigger
= 2;
310 options
.level0_slowdown_writes_trigger
= 2;
313 options
.level0_slowdown_writes_trigger
= 2;
316 options
.hard_pending_compaction_bytes_limit
= l0_size
;
317 options
.soft_pending_compaction_bytes_limit
= l0_size
;
320 options
.soft_pending_compaction_bytes_limit
= l0_size
;
324 dbfull()->TEST_WaitForCompact();
325 ASSERT_FALSE(dbfull()->TEST_write_controler().IsStopped());
326 ASSERT_FALSE(dbfull()->TEST_write_controler().NeedsDelay());
328 SyncPoint::GetInstance()->LoadDependency(
329 {{"DBOptionsTest::EnableAutoCompactionAndTriggerStall:1",
330 "BackgroundCallCompaction:0"},
331 {"DBImpl::BackgroundCompaction():BeforePickCompaction",
332 "DBOptionsTest::EnableAutoCompactionAndTriggerStall:2"},
333 {"DBOptionsTest::EnableAutoCompactionAndTriggerStall:3",
334 "DBImpl::BackgroundCompaction():AfterPickCompaction"}});
335 // Block background compaction.
336 SyncPoint::GetInstance()->EnableProcessing();
338 switch (method_type
) {
341 dbfull()->SetOptions({{"disable_auto_compactions", "false"}}));
344 ASSERT_OK(dbfull()->EnableAutoCompaction(
345 {dbfull()->DefaultColumnFamily()}));
348 TEST_SYNC_POINT("DBOptionsTest::EnableAutoCompactionAndTriggerStall:1");
349 // Wait for stall condition recalculate.
350 TEST_SYNC_POINT("DBOptionsTest::EnableAutoCompactionAndTriggerStall:2");
352 switch (option_type
) {
354 ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped());
357 ASSERT_FALSE(dbfull()->TEST_write_controler().IsStopped());
358 ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
361 ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped());
364 ASSERT_FALSE(dbfull()->TEST_write_controler().IsStopped());
365 ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
368 TEST_SYNC_POINT("DBOptionsTest::EnableAutoCompactionAndTriggerStall:3");
370 // Background compaction executed.
371 dbfull()->TEST_WaitForCompact();
372 ASSERT_FALSE(dbfull()->TEST_write_controler().IsStopped());
373 ASSERT_FALSE(dbfull()->TEST_write_controler().NeedsDelay());
378 TEST_F(DBOptionsTest
, SetOptionsMayTriggerCompaction
) {
380 options
.create_if_missing
= true;
381 options
.level0_file_num_compaction_trigger
= 1000;
384 for (int i
= 0; i
< 3; i
++) {
385 // Need to insert two keys to avoid trivial move.
386 ASSERT_OK(Put("foo", ToString(i
)));
387 ASSERT_OK(Put("bar", ToString(i
)));
390 ASSERT_EQ("3", FilesPerLevel());
392 dbfull()->SetOptions({{"level0_file_num_compaction_trigger", "3"}}));
393 dbfull()->TEST_WaitForCompact();
394 ASSERT_EQ("0,1", FilesPerLevel());
397 TEST_F(DBOptionsTest
, SetBackgroundCompactionThreads
) {
399 options
.create_if_missing
= true;
400 options
.max_background_compactions
= 1; // default value
403 ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
404 ASSERT_OK(dbfull()->SetDBOptions({{"max_background_compactions", "3"}}));
405 ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
406 auto stop_token
= dbfull()->TEST_write_controler().GetStopToken();
407 ASSERT_EQ(3, dbfull()->TEST_BGCompactionsAllowed());
410 TEST_F(DBOptionsTest
, SetBackgroundJobs
) {
412 options
.create_if_missing
= true;
413 options
.max_background_jobs
= 8;
417 for (int i
= 0; i
< 2; ++i
) {
419 options
.max_background_jobs
= 12;
420 ASSERT_OK(dbfull()->SetDBOptions(
421 {{"max_background_jobs",
422 std::to_string(options
.max_background_jobs
)}}));
425 ASSERT_EQ(options
.max_background_jobs
/ 4,
426 dbfull()->TEST_BGFlushesAllowed());
427 ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
429 auto stop_token
= dbfull()->TEST_write_controler().GetStopToken();
431 ASSERT_EQ(options
.max_background_jobs
/ 4,
432 dbfull()->TEST_BGFlushesAllowed());
433 ASSERT_EQ(3 * options
.max_background_jobs
/ 4,
434 dbfull()->TEST_BGCompactionsAllowed());
438 TEST_F(DBOptionsTest
, AvoidFlushDuringShutdown
) {
440 options
.create_if_missing
= true;
441 options
.disable_auto_compactions
= true;
443 WriteOptions write_without_wal
;
444 write_without_wal
.disableWAL
= true;
446 ASSERT_FALSE(options
.avoid_flush_during_shutdown
);
447 DestroyAndReopen(options
);
448 ASSERT_OK(Put("foo", "v1", write_without_wal
));
450 ASSERT_EQ("v1", Get("foo"));
451 ASSERT_EQ("1", FilesPerLevel());
453 DestroyAndReopen(options
);
454 ASSERT_OK(Put("foo", "v2", write_without_wal
));
455 ASSERT_OK(dbfull()->SetDBOptions({{"avoid_flush_during_shutdown", "true"}}));
457 ASSERT_EQ("NOT_FOUND", Get("foo"));
458 ASSERT_EQ("", FilesPerLevel());
461 TEST_F(DBOptionsTest
, SetDelayedWriteRateOption
) {
463 options
.create_if_missing
= true;
464 options
.delayed_write_rate
= 2 * 1024U * 1024U;
467 ASSERT_EQ(2 * 1024U * 1024U, dbfull()->TEST_write_controler().max_delayed_write_rate());
469 ASSERT_OK(dbfull()->SetDBOptions({{"delayed_write_rate", "20000"}}));
470 ASSERT_EQ(20000, dbfull()->TEST_write_controler().max_delayed_write_rate());
473 TEST_F(DBOptionsTest
, MaxTotalWalSizeChange
) {
475 const auto value_size
= size_t(1024);
477 test::RandomString(&rnd
, value_size
, &value
);
480 options
.create_if_missing
= true;
482 CreateColumnFamilies({"1", "2", "3"}, options
);
483 ReopenWithColumnFamilies({"default", "1", "2", "3"}, options
);
485 WriteOptions write_options
;
487 const int key_count
= 100;
488 for (int i
= 0; i
< key_count
; ++i
) {
489 for (size_t cf
= 0; cf
< handles_
.size(); ++cf
) {
490 ASSERT_OK(Put(static_cast<int>(cf
), Key(i
), value
));
493 ASSERT_OK(dbfull()->SetDBOptions({{"max_total_wal_size", "10"}}));
495 for (size_t cf
= 0; cf
< handles_
.size(); ++cf
) {
496 dbfull()->TEST_WaitForFlushMemTable(handles_
[cf
]);
497 ASSERT_EQ("1", FilesPerLevel(static_cast<int>(cf
)));
501 TEST_F(DBOptionsTest
, SetStatsDumpPeriodSec
) {
503 options
.create_if_missing
= true;
504 options
.stats_dump_period_sec
= 5;
507 ASSERT_EQ(5, dbfull()->GetDBOptions().stats_dump_period_sec
);
509 for (int i
= 0; i
< 20; i
++) {
510 int num
= rand() % 5000 + 1;
511 ASSERT_OK(dbfull()->SetDBOptions(
512 {{"stats_dump_period_sec", std::to_string(num
)}}));
513 ASSERT_EQ(num
, dbfull()->GetDBOptions().stats_dump_period_sec
);
517 static void assert_candidate_files_empty(DBImpl
* dbfull
, const bool empty
) {
518 dbfull
->TEST_LockMutex();
519 JobContext
job_context(0);
520 dbfull
->FindObsoleteFiles(&job_context
, false);
521 ASSERT_EQ(empty
, job_context
.full_scan_candidate_files
.empty());
522 dbfull
->TEST_UnlockMutex();
523 if (job_context
.HaveSomethingToDelete()) {
524 // fulfill the contract of FindObsoleteFiles by calling PurgeObsoleteFiles
525 // afterwards; otherwise the test may hang on shutdown
526 dbfull
->PurgeObsoleteFiles(job_context
);
531 TEST_F(DBOptionsTest
, DeleteObsoleteFilesPeriodChange
) {
532 SpecialEnv
env(env_
);
533 env
.time_elapse_only_sleep_
= true;
536 options
.create_if_missing
= true;
537 ASSERT_OK(TryReopen(options
));
539 // Verify that candidate files set is empty when no full scan requested.
540 assert_candidate_files_empty(dbfull(), true);
543 dbfull()->SetDBOptions({{"delete_obsolete_files_period_micros", "0"}}));
545 // After delete_obsolete_files_period_micros updated to 0, the next call
546 // to FindObsoleteFiles should make a full scan
547 assert_candidate_files_empty(dbfull(), false);
550 dbfull()->SetDBOptions({{"delete_obsolete_files_period_micros", "20"}}));
552 assert_candidate_files_empty(dbfull(), true);
554 env
.addon_time_
.store(20);
555 assert_candidate_files_empty(dbfull(), true);
557 env
.addon_time_
.store(21);
558 assert_candidate_files_empty(dbfull(), false);
563 TEST_F(DBOptionsTest
, MaxOpenFilesChange
) {
564 SpecialEnv
env(env_
);
566 options
.env
= CurrentOptions().env
;
567 options
.max_open_files
= -1;
571 Cache
* tc
= dbfull()->TEST_table_cache();
573 ASSERT_EQ(-1, dbfull()->GetDBOptions().max_open_files
);
574 ASSERT_LT(2000, tc
->GetCapacity());
575 ASSERT_OK(dbfull()->SetDBOptions({{"max_open_files", "1024"}}));
576 ASSERT_EQ(1024, dbfull()->GetDBOptions().max_open_files
);
577 // examine the table cache (actual size should be 1014)
578 ASSERT_GT(1500, tc
->GetCapacity());
582 TEST_F(DBOptionsTest
, SanitizeDelayedWriteRate
) {
584 options
.delayed_write_rate
= 0;
586 ASSERT_EQ(16 * 1024 * 1024, dbfull()->GetDBOptions().delayed_write_rate
);
588 options
.rate_limiter
.reset(NewGenericRateLimiter(31 * 1024 * 1024));
590 ASSERT_EQ(31 * 1024 * 1024, dbfull()->GetDBOptions().delayed_write_rate
);
593 TEST_F(DBOptionsTest
, SetFIFOCompactionOptions
) {
595 options
.compaction_style
= kCompactionStyleFIFO
;
596 options
.write_buffer_size
= 10 << 10; // 10KB
597 options
.arena_block_size
= 4096;
598 options
.compression
= kNoCompression
;
599 options
.create_if_missing
= true;
600 options
.compaction_options_fifo
.allow_compaction
= false;
601 env_
->time_elapse_only_sleep_
= false;
604 // Test dynamically changing compaction_options_fifo.ttl
605 env_
->addon_time_
.store(0);
606 options
.compaction_options_fifo
.ttl
= 1 * 60 * 60; // 1 hour
607 ASSERT_OK(TryReopen(options
));
610 for (int i
= 0; i
< 10; i
++) {
611 // Generate and flush a file about 10KB.
612 for (int j
= 0; j
< 10; j
++) {
613 ASSERT_OK(Put(ToString(i
* 20 + j
), RandomString(&rnd
, 980)));
617 ASSERT_OK(dbfull()->TEST_WaitForCompact());
618 ASSERT_EQ(NumTableFilesAtLevel(0), 10);
620 // Add 61 seconds to the time.
621 env_
->addon_time_
.fetch_add(61);
623 // No files should be compacted as ttl is set to 1 hour.
624 ASSERT_EQ(dbfull()->GetOptions().compaction_options_fifo
.ttl
, 3600);
625 dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
626 ASSERT_EQ(NumTableFilesAtLevel(0), 10);
628 // Set ttl to 1 minute. So all files should get deleted.
629 ASSERT_OK(dbfull()->SetOptions({{"compaction_options_fifo", "{ttl=60;}"}}));
630 ASSERT_EQ(dbfull()->GetOptions().compaction_options_fifo
.ttl
, 60);
631 dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
632 ASSERT_OK(dbfull()->TEST_WaitForCompact());
633 ASSERT_EQ(NumTableFilesAtLevel(0), 0);
635 // Test dynamically changing compaction_options_fifo.max_table_files_size
636 env_
->addon_time_
.store(0);
637 options
.compaction_options_fifo
.max_table_files_size
= 500 << 10; // 00KB
638 options
.compaction_options_fifo
.ttl
= 0;
639 DestroyAndReopen(options
);
641 for (int i
= 0; i
< 10; i
++) {
642 // Generate and flush a file about 10KB.
643 for (int j
= 0; j
< 10; j
++) {
644 ASSERT_OK(Put(ToString(i
* 20 + j
), RandomString(&rnd
, 980)));
648 ASSERT_OK(dbfull()->TEST_WaitForCompact());
649 ASSERT_EQ(NumTableFilesAtLevel(0), 10);
651 // No files should be compacted as max_table_files_size is set to 500 KB.
652 ASSERT_EQ(dbfull()->GetOptions().compaction_options_fifo
.max_table_files_size
,
654 dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
655 ASSERT_EQ(NumTableFilesAtLevel(0), 10);
657 // Set max_table_files_size to 12 KB. So only 1 file should remain now.
658 ASSERT_OK(dbfull()->SetOptions(
659 {{"compaction_options_fifo", "{max_table_files_size=12288;}"}}));
660 ASSERT_EQ(dbfull()->GetOptions().compaction_options_fifo
.max_table_files_size
,
662 dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
663 ASSERT_OK(dbfull()->TEST_WaitForCompact());
664 ASSERT_EQ(NumTableFilesAtLevel(0), 1);
666 // Test dynamically changing compaction_options_fifo.allow_compaction
667 options
.compaction_options_fifo
.max_table_files_size
= 500 << 10; // 500KB
668 options
.compaction_options_fifo
.ttl
= 0;
669 options
.compaction_options_fifo
.allow_compaction
= false;
670 options
.level0_file_num_compaction_trigger
= 6;
671 DestroyAndReopen(options
);
673 for (int i
= 0; i
< 10; i
++) {
674 // Generate and flush a file about 10KB.
675 for (int j
= 0; j
< 10; j
++) {
676 ASSERT_OK(Put(ToString(i
* 20 + j
), RandomString(&rnd
, 980)));
680 ASSERT_OK(dbfull()->TEST_WaitForCompact());
681 ASSERT_EQ(NumTableFilesAtLevel(0), 10);
683 // No files should be compacted as max_table_files_size is set to 500 KB and
684 // allow_compaction is false
685 ASSERT_EQ(dbfull()->GetOptions().compaction_options_fifo
.allow_compaction
,
687 dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
688 ASSERT_EQ(NumTableFilesAtLevel(0), 10);
690 // Set allow_compaction to true. So number of files should be between 1 and 5.
691 ASSERT_OK(dbfull()->SetOptions(
692 {{"compaction_options_fifo", "{allow_compaction=true;}"}}));
693 ASSERT_EQ(dbfull()->GetOptions().compaction_options_fifo
.allow_compaction
,
695 dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
696 ASSERT_OK(dbfull()->TEST_WaitForCompact());
697 ASSERT_GE(NumTableFilesAtLevel(0), 1);
698 ASSERT_LE(NumTableFilesAtLevel(0), 5);
701 TEST_F(DBOptionsTest
, CompactionReadaheadSizeChange
) {
702 SpecialEnv
env(env_
);
706 options
.compaction_readahead_size
= 0;
707 options
.new_table_reader_for_compaction_inputs
= true;
708 options
.level0_file_num_compaction_trigger
= 2;
709 const std::string
kValue(1024, 'v');
712 ASSERT_EQ(0, dbfull()->GetDBOptions().compaction_readahead_size
);
713 ASSERT_OK(dbfull()->SetDBOptions({{"compaction_readahead_size", "256"}}));
714 ASSERT_EQ(256, dbfull()->GetDBOptions().compaction_readahead_size
);
715 for (int i
= 0; i
< 1024; i
++) {
719 for (int i
= 0; i
< 1024 * 2; i
++) {
723 dbfull()->TEST_WaitForCompact();
724 ASSERT_EQ(256, env_
->compaction_readahead_size_
);
727 #endif // ROCKSDB_LITE
729 } // namespace rocksdb
731 int main(int argc
, char** argv
) {
732 rocksdb::port::InstallStackTraceHandler();
733 ::testing::InitGoogleTest(&argc
, argv
);
734 return RUN_ALL_TESTS();