option_change_migration_test.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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 <set>
  11. #include "db/db_test_util.h"
  12. #include "port/stack_trace.h"
  13. namespace ROCKSDB_NAMESPACE {
  14. class DBOptionChangeMigrationTests
  15. : public DBTestBase,
  16. public testing::WithParamInterface<
  17. std::tuple<int, int, bool, int, int, bool>> {
  18. public:
  19. DBOptionChangeMigrationTests()
  20. : DBTestBase("/db_option_change_migration_test") {
  21. level1_ = std::get<0>(GetParam());
  22. compaction_style1_ = std::get<1>(GetParam());
  23. is_dynamic1_ = std::get<2>(GetParam());
  24. level2_ = std::get<3>(GetParam());
  25. compaction_style2_ = std::get<4>(GetParam());
  26. is_dynamic2_ = std::get<5>(GetParam());
  27. }
  28. // Required if inheriting from testing::WithParamInterface<>
  29. static void SetUpTestCase() {}
  30. static void TearDownTestCase() {}
  31. int level1_;
  32. int compaction_style1_;
  33. bool is_dynamic1_;
  34. int level2_;
  35. int compaction_style2_;
  36. bool is_dynamic2_;
  37. };
  38. #ifndef ROCKSDB_LITE
  39. TEST_P(DBOptionChangeMigrationTests, Migrate1) {
  40. Options old_options = CurrentOptions();
  41. old_options.compaction_style =
  42. static_cast<CompactionStyle>(compaction_style1_);
  43. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  44. old_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  45. }
  46. old_options.level0_file_num_compaction_trigger = 3;
  47. old_options.write_buffer_size = 64 * 1024;
  48. old_options.target_file_size_base = 128 * 1024;
  49. // Make level target of L1, L2 to be 200KB and 600KB
  50. old_options.num_levels = level1_;
  51. old_options.max_bytes_for_level_multiplier = 3;
  52. old_options.max_bytes_for_level_base = 200 * 1024;
  53. Reopen(old_options);
  54. Random rnd(301);
  55. int key_idx = 0;
  56. // Generate at least 2MB of data
  57. for (int num = 0; num < 20; num++) {
  58. GenerateNewFile(&rnd, &key_idx);
  59. }
  60. dbfull()->TEST_WaitForFlushMemTable();
  61. dbfull()->TEST_WaitForCompact();
  62. // Will make sure exactly those keys are in the DB after migration.
  63. std::set<std::string> keys;
  64. {
  65. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  66. it->SeekToFirst();
  67. for (; it->Valid(); it->Next()) {
  68. keys.insert(it->key().ToString());
  69. }
  70. }
  71. Close();
  72. Options new_options = old_options;
  73. new_options.compaction_style =
  74. static_cast<CompactionStyle>(compaction_style2_);
  75. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  76. new_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  77. }
  78. new_options.target_file_size_base = 256 * 1024;
  79. new_options.num_levels = level2_;
  80. new_options.max_bytes_for_level_base = 150 * 1024;
  81. new_options.max_bytes_for_level_multiplier = 4;
  82. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  83. Reopen(new_options);
  84. // Wait for compaction to finish and make sure it can reopen
  85. dbfull()->TEST_WaitForFlushMemTable();
  86. dbfull()->TEST_WaitForCompact();
  87. Reopen(new_options);
  88. {
  89. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  90. it->SeekToFirst();
  91. for (std::string key : keys) {
  92. ASSERT_TRUE(it->Valid());
  93. ASSERT_EQ(key, it->key().ToString());
  94. it->Next();
  95. }
  96. ASSERT_TRUE(!it->Valid());
  97. }
  98. }
  99. TEST_P(DBOptionChangeMigrationTests, Migrate2) {
  100. Options old_options = CurrentOptions();
  101. old_options.compaction_style =
  102. static_cast<CompactionStyle>(compaction_style2_);
  103. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  104. old_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  105. }
  106. old_options.level0_file_num_compaction_trigger = 3;
  107. old_options.write_buffer_size = 64 * 1024;
  108. old_options.target_file_size_base = 128 * 1024;
  109. // Make level target of L1, L2 to be 200KB and 600KB
  110. old_options.num_levels = level2_;
  111. old_options.max_bytes_for_level_multiplier = 3;
  112. old_options.max_bytes_for_level_base = 200 * 1024;
  113. Reopen(old_options);
  114. Random rnd(301);
  115. int key_idx = 0;
  116. // Generate at least 2MB of data
  117. for (int num = 0; num < 20; num++) {
  118. GenerateNewFile(&rnd, &key_idx);
  119. }
  120. dbfull()->TEST_WaitForFlushMemTable();
  121. dbfull()->TEST_WaitForCompact();
  122. // Will make sure exactly those keys are in the DB after migration.
  123. std::set<std::string> keys;
  124. {
  125. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  126. it->SeekToFirst();
  127. for (; it->Valid(); it->Next()) {
  128. keys.insert(it->key().ToString());
  129. }
  130. }
  131. Close();
  132. Options new_options = old_options;
  133. new_options.compaction_style =
  134. static_cast<CompactionStyle>(compaction_style1_);
  135. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  136. new_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  137. }
  138. new_options.target_file_size_base = 256 * 1024;
  139. new_options.num_levels = level1_;
  140. new_options.max_bytes_for_level_base = 150 * 1024;
  141. new_options.max_bytes_for_level_multiplier = 4;
  142. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  143. Reopen(new_options);
  144. // Wait for compaction to finish and make sure it can reopen
  145. dbfull()->TEST_WaitForFlushMemTable();
  146. dbfull()->TEST_WaitForCompact();
  147. Reopen(new_options);
  148. {
  149. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  150. it->SeekToFirst();
  151. for (std::string key : keys) {
  152. ASSERT_TRUE(it->Valid());
  153. ASSERT_EQ(key, it->key().ToString());
  154. it->Next();
  155. }
  156. ASSERT_TRUE(!it->Valid());
  157. }
  158. }
  159. TEST_P(DBOptionChangeMigrationTests, Migrate3) {
  160. Options old_options = CurrentOptions();
  161. old_options.compaction_style =
  162. static_cast<CompactionStyle>(compaction_style1_);
  163. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  164. old_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  165. }
  166. old_options.level0_file_num_compaction_trigger = 3;
  167. old_options.write_buffer_size = 64 * 1024;
  168. old_options.target_file_size_base = 128 * 1024;
  169. // Make level target of L1, L2 to be 200KB and 600KB
  170. old_options.num_levels = level1_;
  171. old_options.max_bytes_for_level_multiplier = 3;
  172. old_options.max_bytes_for_level_base = 200 * 1024;
  173. Reopen(old_options);
  174. Random rnd(301);
  175. for (int num = 0; num < 20; num++) {
  176. for (int i = 0; i < 50; i++) {
  177. ASSERT_OK(Put(Key(num * 100 + i), RandomString(&rnd, 900)));
  178. }
  179. Flush();
  180. dbfull()->TEST_WaitForCompact();
  181. if (num == 9) {
  182. // Issue a full compaction to generate some zero-out files
  183. CompactRangeOptions cro;
  184. cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
  185. dbfull()->CompactRange(cro, nullptr, nullptr);
  186. }
  187. }
  188. dbfull()->TEST_WaitForFlushMemTable();
  189. dbfull()->TEST_WaitForCompact();
  190. // Will make sure exactly those keys are in the DB after migration.
  191. std::set<std::string> keys;
  192. {
  193. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  194. it->SeekToFirst();
  195. for (; it->Valid(); it->Next()) {
  196. keys.insert(it->key().ToString());
  197. }
  198. }
  199. Close();
  200. Options new_options = old_options;
  201. new_options.compaction_style =
  202. static_cast<CompactionStyle>(compaction_style2_);
  203. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  204. new_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  205. }
  206. new_options.target_file_size_base = 256 * 1024;
  207. new_options.num_levels = level2_;
  208. new_options.max_bytes_for_level_base = 150 * 1024;
  209. new_options.max_bytes_for_level_multiplier = 4;
  210. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  211. Reopen(new_options);
  212. // Wait for compaction to finish and make sure it can reopen
  213. dbfull()->TEST_WaitForFlushMemTable();
  214. dbfull()->TEST_WaitForCompact();
  215. Reopen(new_options);
  216. {
  217. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  218. it->SeekToFirst();
  219. for (std::string key : keys) {
  220. ASSERT_TRUE(it->Valid());
  221. ASSERT_EQ(key, it->key().ToString());
  222. it->Next();
  223. }
  224. ASSERT_TRUE(!it->Valid());
  225. }
  226. }
  227. TEST_P(DBOptionChangeMigrationTests, Migrate4) {
  228. Options old_options = CurrentOptions();
  229. old_options.compaction_style =
  230. static_cast<CompactionStyle>(compaction_style2_);
  231. if (old_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  232. old_options.level_compaction_dynamic_level_bytes = is_dynamic2_;
  233. }
  234. old_options.level0_file_num_compaction_trigger = 3;
  235. old_options.write_buffer_size = 64 * 1024;
  236. old_options.target_file_size_base = 128 * 1024;
  237. // Make level target of L1, L2 to be 200KB and 600KB
  238. old_options.num_levels = level2_;
  239. old_options.max_bytes_for_level_multiplier = 3;
  240. old_options.max_bytes_for_level_base = 200 * 1024;
  241. Reopen(old_options);
  242. Random rnd(301);
  243. for (int num = 0; num < 20; num++) {
  244. for (int i = 0; i < 50; i++) {
  245. ASSERT_OK(Put(Key(num * 100 + i), RandomString(&rnd, 900)));
  246. }
  247. Flush();
  248. dbfull()->TEST_WaitForCompact();
  249. if (num == 9) {
  250. // Issue a full compaction to generate some zero-out files
  251. CompactRangeOptions cro;
  252. cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
  253. dbfull()->CompactRange(cro, nullptr, nullptr);
  254. }
  255. }
  256. dbfull()->TEST_WaitForFlushMemTable();
  257. dbfull()->TEST_WaitForCompact();
  258. // Will make sure exactly those keys are in the DB after migration.
  259. std::set<std::string> keys;
  260. {
  261. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  262. it->SeekToFirst();
  263. for (; it->Valid(); it->Next()) {
  264. keys.insert(it->key().ToString());
  265. }
  266. }
  267. Close();
  268. Options new_options = old_options;
  269. new_options.compaction_style =
  270. static_cast<CompactionStyle>(compaction_style1_);
  271. if (new_options.compaction_style == CompactionStyle::kCompactionStyleLevel) {
  272. new_options.level_compaction_dynamic_level_bytes = is_dynamic1_;
  273. }
  274. new_options.target_file_size_base = 256 * 1024;
  275. new_options.num_levels = level1_;
  276. new_options.max_bytes_for_level_base = 150 * 1024;
  277. new_options.max_bytes_for_level_multiplier = 4;
  278. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  279. Reopen(new_options);
  280. // Wait for compaction to finish and make sure it can reopen
  281. dbfull()->TEST_WaitForFlushMemTable();
  282. dbfull()->TEST_WaitForCompact();
  283. Reopen(new_options);
  284. {
  285. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  286. it->SeekToFirst();
  287. for (std::string key : keys) {
  288. ASSERT_TRUE(it->Valid());
  289. ASSERT_EQ(key, it->key().ToString());
  290. it->Next();
  291. }
  292. ASSERT_TRUE(!it->Valid());
  293. }
  294. }
  295. INSTANTIATE_TEST_CASE_P(
  296. DBOptionChangeMigrationTests, DBOptionChangeMigrationTests,
  297. ::testing::Values(std::make_tuple(3, 0, false, 4, 0, false),
  298. std::make_tuple(3, 0, true, 4, 0, true),
  299. std::make_tuple(3, 0, true, 4, 0, false),
  300. std::make_tuple(3, 0, false, 4, 0, true),
  301. std::make_tuple(3, 1, false, 4, 1, false),
  302. std::make_tuple(1, 1, false, 4, 1, false),
  303. std::make_tuple(3, 0, false, 4, 1, false),
  304. std::make_tuple(3, 0, false, 1, 1, false),
  305. std::make_tuple(3, 0, true, 4, 1, false),
  306. std::make_tuple(3, 0, true, 1, 1, false),
  307. std::make_tuple(1, 1, false, 4, 0, false),
  308. std::make_tuple(4, 0, false, 1, 2, false),
  309. std::make_tuple(3, 0, true, 2, 2, false),
  310. std::make_tuple(3, 1, false, 3, 2, false),
  311. std::make_tuple(1, 1, false, 4, 2, false)));
  312. class DBOptionChangeMigrationTest : public DBTestBase {
  313. public:
  314. DBOptionChangeMigrationTest()
  315. : DBTestBase("/db_option_change_migration_test2") {}
  316. };
  317. TEST_F(DBOptionChangeMigrationTest, CompactedSrcToUniversal) {
  318. Options old_options = CurrentOptions();
  319. old_options.compaction_style = CompactionStyle::kCompactionStyleLevel;
  320. old_options.max_compaction_bytes = 200 * 1024;
  321. old_options.level_compaction_dynamic_level_bytes = false;
  322. old_options.level0_file_num_compaction_trigger = 3;
  323. old_options.write_buffer_size = 64 * 1024;
  324. old_options.target_file_size_base = 128 * 1024;
  325. // Make level target of L1, L2 to be 200KB and 600KB
  326. old_options.num_levels = 4;
  327. old_options.max_bytes_for_level_multiplier = 3;
  328. old_options.max_bytes_for_level_base = 200 * 1024;
  329. Reopen(old_options);
  330. Random rnd(301);
  331. for (int num = 0; num < 20; num++) {
  332. for (int i = 0; i < 50; i++) {
  333. ASSERT_OK(Put(Key(num * 100 + i), RandomString(&rnd, 900)));
  334. }
  335. }
  336. Flush();
  337. CompactRangeOptions cro;
  338. cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
  339. dbfull()->CompactRange(cro, nullptr, nullptr);
  340. // Will make sure exactly those keys are in the DB after migration.
  341. std::set<std::string> keys;
  342. {
  343. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  344. it->SeekToFirst();
  345. for (; it->Valid(); it->Next()) {
  346. keys.insert(it->key().ToString());
  347. }
  348. }
  349. Close();
  350. Options new_options = old_options;
  351. new_options.compaction_style = CompactionStyle::kCompactionStyleUniversal;
  352. new_options.target_file_size_base = 256 * 1024;
  353. new_options.num_levels = 1;
  354. new_options.max_bytes_for_level_base = 150 * 1024;
  355. new_options.max_bytes_for_level_multiplier = 4;
  356. ASSERT_OK(OptionChangeMigration(dbname_, old_options, new_options));
  357. Reopen(new_options);
  358. // Wait for compaction to finish and make sure it can reopen
  359. dbfull()->TEST_WaitForFlushMemTable();
  360. dbfull()->TEST_WaitForCompact();
  361. Reopen(new_options);
  362. {
  363. std::unique_ptr<Iterator> it(db_->NewIterator(ReadOptions()));
  364. it->SeekToFirst();
  365. for (std::string key : keys) {
  366. ASSERT_TRUE(it->Valid());
  367. ASSERT_EQ(key, it->key().ToString());
  368. it->Next();
  369. }
  370. ASSERT_TRUE(!it->Valid());
  371. }
  372. }
  373. #endif // ROCKSDB_LITE
  374. } // namespace ROCKSDB_NAMESPACE
  375. int main(int argc, char** argv) {
  376. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  377. ::testing::InitGoogleTest(&argc, argv);
  378. return RUN_ALL_TESTS();
  379. }