option_change_migration_test.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  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).
  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. #include "rocksdb/utilities/option_change_migration.h"
  10. #include <cstdint>
  11. #include <limits>
  12. #include <set>
  13. #include "db/db_test_util.h"
  14. #include "port/stack_trace.h"
  15. #include "util/random.h"
  16. namespace ROCKSDB_NAMESPACE {
  17. class DBOptionChangeMigrationTests
  18. : public DBTestBase,
  19. public testing::WithParamInterface<
  20. std::tuple<int, int, bool, int, int, bool, uint64_t>> {
  21. public:
  22. DBOptionChangeMigrationTests()
  23. : DBTestBase("db_option_change_migration_test", /*env_do_fsync=*/true) {
  24. level1_ = std::get<0>(GetParam());
  25. compaction_style1_ = std::get<1>(GetParam());
  26. is_dynamic1_ = std::get<2>(GetParam());
  27. level2_ = std::get<3>(GetParam());
  28. compaction_style2_ = std::get<4>(GetParam());
  29. is_dynamic2_ = std::get<5>(GetParam());
  30. // This is set to be extremely large if not zero to avoid dropping any data
  31. // right after migration, which makes test verification difficult
  32. fifo_max_table_files_size_ = std::get<6>(GetParam());
  33. }
  34. // Required if inheriting from testing::WithParamInterface<>
  35. static void SetUpTestCase() {}
  36. static void TearDownTestCase() {}
  37. int level1_;
  38. int compaction_style1_;
  39. bool is_dynamic1_;
  40. int level2_;
  41. int compaction_style2_;
  42. bool is_dynamic2_;
  43. uint64_t fifo_max_table_files_size_;
  44. };
  45. TEST_P(DBOptionChangeMigrationTests, Migrate1) {
  46. Options old_options = CurrentOptions();
  47. old_options.compaction_style =
  48. static_cast<CompactionStyle>(compaction_style1_);
  49. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  50. old_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  51. }
  52. if (old_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  53. old_options.max_open_files = -1;
  54. }
  55. old_options.level0_file_num_compaction_trigger = 3;
  56. old_options.write_buffer_size = 64 * 1024;
  57. old_options.target_file_size_base = 128 * 1024;
  58. // Make level target of L1, L2 to be 200KB and 600KB
  59. old_options.num_levels = level1_;
  60. old_options.max_bytes_for_level_multiplier = 3;
  61. old_options.max_bytes_for_level_base = 200 * 1024;
  62. Reopen(old_options);
  63. Random rnd(301);
  64. int key_idx = 0;
  65. // Generate at least 2MB of data
  66. for (int num = 0; num < 20; num++) {
  67. GenerateNewFile(&rnd, &key_idx);
  68. }
  69. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  70. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  71. // Will make sure exactly those keys are in the DB after migration.
  72. std::set<std::string> keys;
  73. {
  74. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  75. it->SeekToFirst();
  76. for (; it->Valid(); it->Next()) {
  77. keys.insert(it->key().ToString());
  78. }
  79. ASSERT_OK(it->status());
  80. }
  81. Close();
  82. Options new_options = old_options;
  83. new_options.compaction_style =
  84. static_cast<CompactionStyle>(compaction_style2_);
  85. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  86. new_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  87. }
  88. if (new_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  89. new_options.max_open_files = -1;
  90. }
  91. if (fifo_max_table_files_size_ != 0) {
  92. new_options.compaction_options_fifo.max_table_files_size =
  93. fifo_max_table_files_size_;
  94. }
  95. new_options.target_file_size_base = 256 * 1024;
  96. new_options.num_levels = level2_;
  97. new_options.max_bytes_for_level_base = 150 * 1024;
  98. new_options.max_bytes_for_level_multiplier = 4;
  99. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  100. Reopen(new_options);
  101. // Wait for compaction to finish and make sure it can reopen
  102. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  103. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  104. Reopen(new_options);
  105. {
  106. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  107. it->SeekToFirst();
  108. for (const std::string& key : keys) {
  109. ASSERT_TRUE(it->Valid());
  110. ASSERT_EQ(key, it->key().ToString());
  111. it->Next();
  112. }
  113. ASSERT_TRUE(!it->Valid());
  114. ASSERT_OK(it->status());
  115. }
  116. }
  117. TEST_P(DBOptionChangeMigrationTests, Migrate2) {
  118. Options old_options = CurrentOptions();
  119. old_options.compaction_style =
  120. static_cast<CompactionStyle>(compaction_style2_);
  121. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  122. old_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  123. }
  124. if (old_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  125. old_options.max_open_files = -1;
  126. }
  127. old_options.level0_file_num_compaction_trigger = 3;
  128. old_options.write_buffer_size = 64 * 1024;
  129. old_options.target_file_size_base = 128 * 1024;
  130. // Make level target of L1, L2 to be 200KB and 600KB
  131. old_options.num_levels = level2_;
  132. old_options.max_bytes_for_level_multiplier = 3;
  133. old_options.max_bytes_for_level_base = 200 * 1024;
  134. Reopen(old_options);
  135. Random rnd(301);
  136. int key_idx = 0;
  137. // Generate at least 2MB of data
  138. for (int num = 0; num < 20; num++) {
  139. GenerateNewFile(&rnd, &key_idx);
  140. }
  141. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  142. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  143. // Will make sure exactly those keys are in the DB after migration.
  144. std::set<std::string> keys;
  145. {
  146. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  147. it->SeekToFirst();
  148. for (; it->Valid(); it->Next()) {
  149. keys.insert(it->key().ToString());
  150. }
  151. ASSERT_OK(it->status());
  152. }
  153. Close();
  154. Options new_options = old_options;
  155. new_options.compaction_style =
  156. static_cast<CompactionStyle>(compaction_style1_);
  157. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  158. new_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  159. }
  160. if (new_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  161. new_options.max_open_files = -1;
  162. }
  163. if (fifo_max_table_files_size_ != 0) {
  164. new_options.compaction_options_fifo.max_table_files_size =
  165. fifo_max_table_files_size_;
  166. }
  167. new_options.target_file_size_base = 256 * 1024;
  168. new_options.num_levels = level1_;
  169. new_options.max_bytes_for_level_base = 150 * 1024;
  170. new_options.max_bytes_for_level_multiplier = 4;
  171. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  172. Reopen(new_options);
  173. // Wait for compaction to finish and make sure it can reopen
  174. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  175. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  176. Reopen(new_options);
  177. {
  178. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  179. it->SeekToFirst();
  180. for (const std::string& key : keys) {
  181. ASSERT_TRUE(it->Valid());
  182. ASSERT_EQ(key, it->key().ToString());
  183. it->Next();
  184. }
  185. ASSERT_TRUE(!it->Valid());
  186. ASSERT_OK(it->status());
  187. }
  188. }
  189. TEST_P(DBOptionChangeMigrationTests, Migrate3) {
  190. Options old_options = CurrentOptions();
  191. old_options.compaction_style =
  192. static_cast<CompactionStyle>(compaction_style1_);
  193. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  194. old_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  195. }
  196. if (old_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  197. old_options.max_open_files = -1;
  198. }
  199. old_options.level0_file_num_compaction_trigger = 3;
  200. old_options.write_buffer_size = 64 * 1024;
  201. old_options.target_file_size_base = 128 * 1024;
  202. // Make level target of L1, L2 to be 200KB and 600KB
  203. old_options.num_levels = level1_;
  204. old_options.max_bytes_for_level_multiplier = 3;
  205. old_options.max_bytes_for_level_base = 200 * 1024;
  206. Reopen(old_options);
  207. Random rnd(301);
  208. for (int num = 0; num < 20; num++) {
  209. for (int i = 0; i < 50; i++) {
  210. ASSERT_OK(Put(Key(num * 100 + i), rnd.RandomString(900)));
  211. }
  212. ASSERT_OK(Flush());
  213. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  214. if (num == 9) {
  215. // Issue a full compaction to generate some zero-out files
  216. CompactRangeOptions cro;
  217. cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
  218. ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
  219. }
  220. }
  221. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  222. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  223. // Will make sure exactly those keys are in the DB after migration.
  224. std::set<std::string> keys;
  225. {
  226. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  227. it->SeekToFirst();
  228. for (; it->Valid(); it->Next()) {
  229. keys.insert(it->key().ToString());
  230. }
  231. ASSERT_OK(it->status());
  232. }
  233. Close();
  234. Options new_options = old_options;
  235. new_options.compaction_style =
  236. static_cast<CompactionStyle>(compaction_style2_);
  237. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  238. new_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  239. }
  240. if (new_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  241. new_options.max_open_files = -1;
  242. }
  243. if (fifo_max_table_files_size_ != 0) {
  244. new_options.compaction_options_fifo.max_table_files_size =
  245. fifo_max_table_files_size_;
  246. }
  247. new_options.target_file_size_base = 256 * 1024;
  248. new_options.num_levels = level2_;
  249. new_options.max_bytes_for_level_base = 150 * 1024;
  250. new_options.max_bytes_for_level_multiplier = 4;
  251. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  252. Reopen(new_options);
  253. // Wait for compaction to finish and make sure it can reopen
  254. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  255. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  256. Reopen(new_options);
  257. {
  258. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  259. it->SeekToFirst();
  260. for (const std::string& key : keys) {
  261. ASSERT_TRUE(it->Valid());
  262. ASSERT_EQ(key, it->key().ToString());
  263. it->Next();
  264. }
  265. ASSERT_TRUE(!it->Valid());
  266. ASSERT_OK(it->status());
  267. }
  268. }
  269. TEST_P(DBOptionChangeMigrationTests, Migrate4) {
  270. Options old_options = CurrentOptions();
  271. old_options.compaction_style =
  272. static_cast<CompactionStyle>(compaction_style2_);
  273. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  274. old_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  275. }
  276. if (old_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  277. old_options.max_open_files = -1;
  278. }
  279. old_options.level0_file_num_compaction_trigger = 3;
  280. old_options.write_buffer_size = 64 * 1024;
  281. old_options.target_file_size_base = 128 * 1024;
  282. // Make level target of L1, L2 to be 200KB and 600KB
  283. old_options.num_levels = level2_;
  284. old_options.max_bytes_for_level_multiplier = 3;
  285. old_options.max_bytes_for_level_base = 200 * 1024;
  286. Reopen(old_options);
  287. Random rnd(301);
  288. for (int num = 0; num < 20; num++) {
  289. for (int i = 0; i < 50; i++) {
  290. ASSERT_OK(Put(Key(num * 100 + i), rnd.RandomString(900)));
  291. }
  292. ASSERT_OK(Flush());
  293. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  294. if (num == 9) {
  295. // Issue a full compaction to generate some zero-out files
  296. CompactRangeOptions cro;
  297. cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
  298. ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
  299. }
  300. }
  301. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  302. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  303. // Will make sure exactly those keys are in the DB after migration.
  304. std::set<std::string> keys;
  305. {
  306. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  307. it->SeekToFirst();
  308. for (; it->Valid(); it->Next()) {
  309. keys.insert(it->key().ToString());
  310. }
  311. ASSERT_OK(it->status());
  312. }
  313. Close();
  314. Options new_options = old_options;
  315. new_options.compaction_style =
  316. static_cast<CompactionStyle>(compaction_style1_);
  317. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  318. new_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  319. }
  320. if (new_options.compaction_style == CompactionStyle::kCompactionStyleFIFO) {
  321. new_options.max_open_files = -1;
  322. }
  323. if (fifo_max_table_files_size_ != 0) {
  324. new_options.compaction_options_fifo.max_table_files_size =
  325. fifo_max_table_files_size_;
  326. }
  327. new_options.target_file_size_base = 256 * 1024;
  328. new_options.num_levels = level1_;
  329. new_options.max_bytes_for_level_base = 150 * 1024;
  330. new_options.max_bytes_for_level_multiplier = 4;
  331. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  332. Reopen(new_options);
  333. // Wait for compaction to finish and make sure it can reopen
  334. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  335. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  336. Reopen(new_options);
  337. {
  338. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  339. it->SeekToFirst();
  340. for (const std::string& key : keys) {
  341. ASSERT_TRUE(it->Valid());
  342. ASSERT_EQ(key, it->key().ToString());
  343. it->Next();
  344. }
  345. ASSERT_TRUE(!it->Valid());
  346. ASSERT_OK(it->status());
  347. }
  348. }
  349. INSTANTIATE_TEST_CASE_P(
  350. DBOptionChangeMigrationTests, DBOptionChangeMigrationTests,
  351. ::testing::Values(
  352. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  353. false /* is dynamic leveling in old option */,
  354. 4 /* old num_levels */, 0 /* new compaction style */,
  355. false /* is dynamic leveling in new option */,
  356. 0 /*fifo max_table_files_size*/),
  357. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  358. true /* is dynamic leveling in old option */,
  359. 4 /* old num_levels */, 0 /* new compaction style */,
  360. true /* is dynamic leveling in new option */,
  361. 0 /*fifo max_table_files_size*/),
  362. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  363. true /* is dynamic leveling in old option */,
  364. 4 /* old num_levels */, 0 /* new compaction style */,
  365. false, 0 /*fifo max_table_files_size*/),
  366. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  367. false /* is dynamic leveling in old option */,
  368. 4 /* old num_levels */, 0 /* new compaction style */,
  369. true /* is dynamic leveling in new option */,
  370. 0 /*fifo max_table_files_size*/),
  371. std::make_tuple(3 /* old num_levels */, 1 /* old compaction style */,
  372. false /* is dynamic leveling in old option */,
  373. 4 /* old num_levels */, 1 /* new compaction style */,
  374. false /* is dynamic leveling in new option */,
  375. 0 /*fifo max_table_files_size*/),
  376. std::make_tuple(1 /* old num_levels */, 1 /* old compaction style */,
  377. false /* is dynamic leveling in old option */,
  378. 4 /* old num_levels */, 1 /* new compaction style */,
  379. false /* is dynamic leveling in new option */,
  380. 0 /*fifo max_table_files_size*/),
  381. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  382. false /* is dynamic leveling in old option */,
  383. 4 /* old num_levels */, 1 /* new compaction style */,
  384. false /* is dynamic leveling in new option */,
  385. 0 /*fifo max_table_files_size*/),
  386. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  387. false /* is dynamic leveling in old option */,
  388. 1 /* old num_levels */, 1 /* new compaction style */,
  389. false /* is dynamic leveling in new option */,
  390. 0 /*fifo max_table_files_size*/),
  391. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  392. true /* is dynamic leveling in old option */,
  393. 4 /* old num_levels */, 1 /* new compaction style */,
  394. false /* is dynamic leveling in new option */,
  395. 0 /*fifo max_table_files_size*/),
  396. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  397. true /* is dynamic leveling in old option */,
  398. 1 /* old num_levels */, 1 /* new compaction style */,
  399. false /* is dynamic leveling in new option */,
  400. 0 /*fifo max_table_files_size*/),
  401. std::make_tuple(1 /* old num_levels */, 1 /* old compaction style */,
  402. false /* is dynamic leveling in old option */,
  403. 4 /* old num_levels */, 0 /* new compaction style */,
  404. false /* is dynamic leveling in new option */,
  405. 0 /*fifo max_table_files_size*/),
  406. std::make_tuple(4 /* old num_levels */, 0 /* old compaction style */,
  407. false /* is dynamic leveling in old option */,
  408. 1 /* old num_levels */, 2 /* new compaction style */,
  409. false /* is dynamic leveling in new option */,
  410. 0 /*fifo max_table_files_size*/),
  411. std::make_tuple(3 /* old num_levels */, 0 /* old compaction style */,
  412. true /* is dynamic leveling in old option */,
  413. 2 /* old num_levels */, 2 /* new compaction style */,
  414. false /* is dynamic leveling in new option */,
  415. 0 /*fifo max_table_files_size*/),
  416. std::make_tuple(3 /* old num_levels */, 1 /* old compaction style */,
  417. false /* is dynamic leveling in old option */,
  418. 3 /* old num_levels */, 2 /* new compaction style */,
  419. false /* is dynamic leveling in new option */,
  420. 0 /*fifo max_table_files_size*/),
  421. std::make_tuple(1 /* old num_levels */, 1 /* old compaction style */,
  422. false /* is dynamic leveling in old option */,
  423. 4 /* old num_levels */, 2 /* new compaction style */,
  424. false /* is dynamic leveling in new option */, 0),
  425. std::make_tuple(
  426. 4 /* old num_levels */, 0 /* old compaction style */,
  427. false /* is dynamic leveling in old option */,
  428. 1 /* old num_levels */, 2 /* new compaction style */,
  429. false /* is dynamic leveling in new option */,
  430. std::numeric_limits<uint64_t>::max() /*fifo max_table_files_size*/),
  431. std::make_tuple(
  432. 3 /* old num_levels */, 0 /* old compaction style */,
  433. true /* is dynamic leveling in old option */,
  434. 2 /* old num_levels */, 2 /* new compaction style */,
  435. false /* is dynamic leveling in new option */,
  436. std::numeric_limits<uint64_t>::max() /*fifo max_table_files_size*/),
  437. std::make_tuple(
  438. 3 /* old num_levels */, 1 /* old compaction style */,
  439. false /* is dynamic leveling in old option */,
  440. 3 /* old num_levels */, 2 /* new compaction style */,
  441. false /* is dynamic leveling in new option */,
  442. std::numeric_limits<uint64_t>::max() /*fifo max_table_files_size*/),
  443. std::make_tuple(1 /* old num_levels */, 1 /* old compaction style */,
  444. false /* is dynamic leveling in old option */,
  445. 4 /* old num_levels */, 2 /* new compaction style */,
  446. false /* is dynamic leveling in new option */,
  447. std::numeric_limits<
  448. uint64_t>::max() /*fifo max_table_files_size*/)));
  449. class DBOptionChangeMigrationTest : public DBTestBase {
  450. public:
  451. DBOptionChangeMigrationTest()
  452. : DBTestBase("db_option_change_migration_test2", /*env_do_fsync=*/true) {}
  453. };
  454. TEST_F(DBOptionChangeMigrationTest, CompactedSrcToUniversal) {
  455. Options old_options = CurrentOptions();
  456. old_options.compaction_style = CompactionStyle::kCompactionStyleLevel;
  457. old_options.max_compaction_bytes = 200 * 1024;
  458. old_options.level_compaction_dynamic_level_bytes = false;
  459. old_options.level0_file_num_compaction_trigger = 3;
  460. old_options.write_buffer_size = 64 * 1024;
  461. old_options.target_file_size_base = 128 * 1024;
  462. // Make level target of L1, L2 to be 200KB and 600KB
  463. old_options.num_levels = 4;
  464. old_options.max_bytes_for_level_multiplier = 3;
  465. old_options.max_bytes_for_level_base = 200 * 1024;
  466. Reopen(old_options);
  467. Random rnd(301);
  468. for (int num = 0; num < 20; num++) {
  469. for (int i = 0; i < 50; i++) {
  470. ASSERT_OK(Put(Key(num * 100 + i), rnd.RandomString(900)));
  471. }
  472. }
  473. ASSERT_OK(Flush());
  474. CompactRangeOptions cro;
  475. cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
  476. ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
  477. // Will make sure exactly those keys are in the DB after migration.
  478. std::set<std::string> keys;
  479. {
  480. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  481. it->SeekToFirst();
  482. for (; it->Valid(); it->Next()) {
  483. keys.insert(it->key().ToString());
  484. }
  485. ASSERT_OK(it->status());
  486. }
  487. Close();
  488. Options new_options = old_options;
  489. new_options.compaction_style = CompactionStyle::kCompactionStyleUniversal;
  490. new_options.target_file_size_base = 256 * 1024;
  491. new_options.num_levels = 1;
  492. new_options.max_bytes_for_level_base = 150 * 1024;
  493. new_options.max_bytes_for_level_multiplier = 4;
  494. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  495. Reopen(new_options);
  496. // Wait for compaction to finish and make sure it can reopen
  497. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  498. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  499. Reopen(new_options);
  500. {
  501. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  502. it->SeekToFirst();
  503. for (const std::string& key : keys) {
  504. ASSERT_TRUE(it->Valid());
  505. ASSERT_EQ(key, it->key().ToString());
  506. it->Next();
  507. }
  508. ASSERT_TRUE(!it->Valid());
  509. ASSERT_OK(it->status());
  510. }
  511. }
  512. } // namespace ROCKSDB_NAMESPACE
  513. int main(int argc, char** argv) {
  514. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  515. ::testing::InitGoogleTest(&argc, argv);
  516. return RUN_ALL_TESTS();
  517. }