import_column_family_test.cc 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. // Copyright (c) Meta Platforms, Inc. and affiliates.
  2. //
  3. // This source code is licensed under both the GPLv2 (found in the
  4. // COPYING file in the root directory) and Apache 2.0 License
  5. // (found in the LICENSE.Apache file in the root directory).
  6. #include <functional>
  7. #include "db/db_test_util.h"
  8. #include "port/port.h"
  9. #include "port/stack_trace.h"
  10. #include "rocksdb/sst_file_writer.h"
  11. #include "test_util/testutil.h"
  12. #include "util/random.h"
  13. namespace ROCKSDB_NAMESPACE {
  14. class ImportColumnFamilyTest : public DBTestBase {
  15. public:
  16. ImportColumnFamilyTest()
  17. : DBTestBase("import_column_family_test", /*env_do_fsync=*/true) {
  18. sst_files_dir_ = dbname_ + "/sst_files/";
  19. export_files_dir_ = test::PerThreadDBPath(env_, "export");
  20. export_files_dir2_ = test::PerThreadDBPath(env_, "export2");
  21. DestroyAndRecreateExternalSSTFilesDir();
  22. import_cfh_ = nullptr;
  23. import_cfh2_ = nullptr;
  24. metadata_ptr_ = nullptr;
  25. metadata_ptr2_ = nullptr;
  26. }
  27. ~ImportColumnFamilyTest() {
  28. if (import_cfh_) {
  29. EXPECT_OK(db_->DropColumnFamily(import_cfh_));
  30. EXPECT_OK(db_->DestroyColumnFamilyHandle(import_cfh_));
  31. import_cfh_ = nullptr;
  32. }
  33. if (import_cfh2_) {
  34. EXPECT_OK(db_->DropColumnFamily(import_cfh2_));
  35. EXPECT_OK(db_->DestroyColumnFamilyHandle(import_cfh2_));
  36. import_cfh2_ = nullptr;
  37. }
  38. if (metadata_ptr_) {
  39. delete metadata_ptr_;
  40. metadata_ptr_ = nullptr;
  41. }
  42. if (metadata_ptr2_) {
  43. delete metadata_ptr2_;
  44. metadata_ptr2_ = nullptr;
  45. }
  46. EXPECT_OK(DestroyDir(env_, sst_files_dir_));
  47. EXPECT_OK(DestroyDir(env_, export_files_dir_));
  48. EXPECT_OK(DestroyDir(env_, export_files_dir2_));
  49. }
  50. void DestroyAndRecreateExternalSSTFilesDir() {
  51. EXPECT_OK(DestroyDir(env_, sst_files_dir_));
  52. EXPECT_OK(env_->CreateDir(sst_files_dir_));
  53. EXPECT_OK(DestroyDir(env_, export_files_dir_));
  54. EXPECT_OK(DestroyDir(env_, export_files_dir2_));
  55. }
  56. LiveFileMetaData LiveFileMetaDataInit(std::string name, std::string path,
  57. int level,
  58. SequenceNumber smallest_seqno,
  59. SequenceNumber largest_seqno) {
  60. LiveFileMetaData metadata;
  61. metadata.name = name;
  62. metadata.db_path = path;
  63. metadata.smallest_seqno = smallest_seqno;
  64. metadata.largest_seqno = largest_seqno;
  65. metadata.level = level;
  66. return metadata;
  67. }
  68. protected:
  69. std::string sst_files_dir_;
  70. std::string export_files_dir_;
  71. std::string export_files_dir2_;
  72. ColumnFamilyHandle* import_cfh_;
  73. ColumnFamilyHandle* import_cfh2_;
  74. ExportImportFilesMetaData* metadata_ptr_;
  75. ExportImportFilesMetaData* metadata_ptr2_;
  76. };
  77. TEST_F(ImportColumnFamilyTest, ImportSSTFileWriterFiles) {
  78. Options options = CurrentOptions();
  79. CreateAndReopenWithCF({"koko"}, options);
  80. SstFileWriter sfw_cf1(EnvOptions(), options, handles_[1]);
  81. SstFileWriter sfw_unknown(EnvOptions(), options);
  82. // cf1.sst
  83. const std::string cf1_sst_name = "cf1.sst";
  84. const std::string cf1_sst = sst_files_dir_ + cf1_sst_name;
  85. ASSERT_OK(sfw_cf1.Open(cf1_sst));
  86. ASSERT_OK(sfw_cf1.Put("K1", "V1"));
  87. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  88. ASSERT_OK(sfw_cf1.Finish());
  89. // cf_unknown.sst
  90. const std::string unknown_sst_name = "cf_unknown.sst";
  91. const std::string unknown_sst = sst_files_dir_ + unknown_sst_name;
  92. ASSERT_OK(sfw_unknown.Open(unknown_sst));
  93. ASSERT_OK(sfw_unknown.Put("K3", "V1"));
  94. ASSERT_OK(sfw_unknown.Put("K4", "V2"));
  95. ASSERT_OK(sfw_unknown.Finish());
  96. {
  97. // Import sst file corresponding to cf1 onto a new cf and verify
  98. ExportImportFilesMetaData metadata;
  99. metadata.files.push_back(
  100. LiveFileMetaDataInit(cf1_sst_name, sst_files_dir_, 0, 10, 19));
  101. metadata.db_comparator_name = options.comparator->Name();
  102. ASSERT_OK(db_->CreateColumnFamilyWithImport(
  103. options, "toto", ImportColumnFamilyOptions(), metadata, &import_cfh_));
  104. ASSERT_NE(import_cfh_, nullptr);
  105. std::string value;
  106. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, "K1", &value));
  107. ASSERT_EQ(value, "V1");
  108. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, "K2", &value));
  109. ASSERT_EQ(value, "V2");
  110. ASSERT_OK(db_->DropColumnFamily(import_cfh_));
  111. ASSERT_OK(db_->DestroyColumnFamilyHandle(import_cfh_));
  112. import_cfh_ = nullptr;
  113. }
  114. {
  115. // Import sst file corresponding to unknown cf onto a new cf and verify
  116. ExportImportFilesMetaData metadata;
  117. metadata.files.push_back(
  118. LiveFileMetaDataInit(unknown_sst_name, sst_files_dir_, 0, 20, 29));
  119. metadata.db_comparator_name = options.comparator->Name();
  120. ASSERT_OK(db_->CreateColumnFamilyWithImport(
  121. options, "yoyo", ImportColumnFamilyOptions(), metadata, &import_cfh_));
  122. ASSERT_NE(import_cfh_, nullptr);
  123. std::string value;
  124. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, "K3", &value));
  125. ASSERT_EQ(value, "V1");
  126. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, "K4", &value));
  127. ASSERT_EQ(value, "V2");
  128. }
  129. EXPECT_OK(db_->DestroyColumnFamilyHandle(import_cfh_));
  130. import_cfh_ = nullptr;
  131. // verify sst unique id during reopen
  132. options.verify_sst_unique_id_in_manifest = true;
  133. ReopenWithColumnFamilies({"default", "koko", "yoyo"}, options);
  134. }
  135. TEST_F(ImportColumnFamilyTest, ImportSSTFileWriterFilesWithOverlap) {
  136. Options options = CurrentOptions();
  137. CreateAndReopenWithCF({"koko"}, options);
  138. SstFileWriter sfw_cf1(EnvOptions(), options, handles_[1]);
  139. // file3.sst
  140. const std::string file3_sst_name = "file3.sst";
  141. const std::string file3_sst = sst_files_dir_ + file3_sst_name;
  142. ASSERT_OK(sfw_cf1.Open(file3_sst));
  143. for (int i = 0; i < 100; ++i) {
  144. ASSERT_OK(sfw_cf1.Put(Key(i), Key(i) + "_val"));
  145. }
  146. ASSERT_OK(sfw_cf1.Finish());
  147. // file2.sst
  148. const std::string file2_sst_name = "file2.sst";
  149. const std::string file2_sst = sst_files_dir_ + file2_sst_name;
  150. ASSERT_OK(sfw_cf1.Open(file2_sst));
  151. for (int i = 0; i < 100; i += 2) {
  152. ASSERT_OK(sfw_cf1.Put(Key(i), Key(i) + "_overwrite1"));
  153. }
  154. ASSERT_OK(sfw_cf1.Finish());
  155. // file1a.sst
  156. const std::string file1a_sst_name = "file1a.sst";
  157. const std::string file1a_sst = sst_files_dir_ + file1a_sst_name;
  158. ASSERT_OK(sfw_cf1.Open(file1a_sst));
  159. for (int i = 0; i < 52; i += 4) {
  160. ASSERT_OK(sfw_cf1.Put(Key(i), Key(i) + "_overwrite2"));
  161. }
  162. ASSERT_OK(sfw_cf1.Finish());
  163. // file1b.sst
  164. const std::string file1b_sst_name = "file1b.sst";
  165. const std::string file1b_sst = sst_files_dir_ + file1b_sst_name;
  166. ASSERT_OK(sfw_cf1.Open(file1b_sst));
  167. for (int i = 52; i < 100; i += 4) {
  168. ASSERT_OK(sfw_cf1.Put(Key(i), Key(i) + "_overwrite2"));
  169. }
  170. ASSERT_OK(sfw_cf1.Finish());
  171. // file0a.sst
  172. const std::string file0a_sst_name = "file0a.sst";
  173. const std::string file0a_sst = sst_files_dir_ + file0a_sst_name;
  174. ASSERT_OK(sfw_cf1.Open(file0a_sst));
  175. for (int i = 0; i < 100; i += 16) {
  176. ASSERT_OK(sfw_cf1.Put(Key(i), Key(i) + "_overwrite3"));
  177. }
  178. ASSERT_OK(sfw_cf1.Finish());
  179. // file0b.sst
  180. const std::string file0b_sst_name = "file0b.sst";
  181. const std::string file0b_sst = sst_files_dir_ + file0b_sst_name;
  182. ASSERT_OK(sfw_cf1.Open(file0b_sst));
  183. for (int i = 0; i < 100; i += 16) {
  184. ASSERT_OK(sfw_cf1.Put(Key(i), Key(i) + "_overwrite4"));
  185. }
  186. ASSERT_OK(sfw_cf1.Finish());
  187. // Import sst files and verify
  188. ExportImportFilesMetaData metadata;
  189. metadata.files.push_back(
  190. LiveFileMetaDataInit(file3_sst_name, sst_files_dir_, 3, 10, 19));
  191. metadata.files.push_back(
  192. LiveFileMetaDataInit(file2_sst_name, sst_files_dir_, 2, 20, 29));
  193. metadata.files.push_back(
  194. LiveFileMetaDataInit(file1a_sst_name, sst_files_dir_, 1, 30, 34));
  195. metadata.files.push_back(
  196. LiveFileMetaDataInit(file1b_sst_name, sst_files_dir_, 1, 35, 39));
  197. metadata.files.push_back(
  198. LiveFileMetaDataInit(file0a_sst_name, sst_files_dir_, 0, 40, 49));
  199. metadata.files.push_back(
  200. LiveFileMetaDataInit(file0b_sst_name, sst_files_dir_, 0, 50, 59));
  201. metadata.db_comparator_name = options.comparator->Name();
  202. ASSERT_OK(db_->CreateColumnFamilyWithImport(
  203. options, "toto", ImportColumnFamilyOptions(), metadata, &import_cfh_));
  204. ASSERT_NE(import_cfh_, nullptr);
  205. for (int i = 0; i < 100; i++) {
  206. std::string value;
  207. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value));
  208. if (i % 16 == 0) {
  209. ASSERT_EQ(value, Key(i) + "_overwrite4");
  210. } else if (i % 4 == 0) {
  211. ASSERT_EQ(value, Key(i) + "_overwrite2");
  212. } else if (i % 2 == 0) {
  213. ASSERT_EQ(value, Key(i) + "_overwrite1");
  214. } else {
  215. ASSERT_EQ(value, Key(i) + "_val");
  216. }
  217. }
  218. for (int i = 0; i < 100; i += 5) {
  219. ASSERT_OK(
  220. db_->Put(WriteOptions(), import_cfh_, Key(i), Key(i) + "_overwrite5"));
  221. }
  222. // Flush and check again
  223. ASSERT_OK(db_->Flush(FlushOptions(), import_cfh_));
  224. for (int i = 0; i < 100; i++) {
  225. std::string value;
  226. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value));
  227. if (i % 5 == 0) {
  228. ASSERT_EQ(value, Key(i) + "_overwrite5");
  229. } else if (i % 16 == 0) {
  230. ASSERT_EQ(value, Key(i) + "_overwrite4");
  231. } else if (i % 4 == 0) {
  232. ASSERT_EQ(value, Key(i) + "_overwrite2");
  233. } else if (i % 2 == 0) {
  234. ASSERT_EQ(value, Key(i) + "_overwrite1");
  235. } else {
  236. ASSERT_EQ(value, Key(i) + "_val");
  237. }
  238. }
  239. // Compact and check again.
  240. ASSERT_OK(
  241. db_->CompactRange(CompactRangeOptions(), import_cfh_, nullptr, nullptr));
  242. for (int i = 0; i < 100; i++) {
  243. std::string value;
  244. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value));
  245. if (i % 5 == 0) {
  246. ASSERT_EQ(value, Key(i) + "_overwrite5");
  247. } else if (i % 16 == 0) {
  248. ASSERT_EQ(value, Key(i) + "_overwrite4");
  249. } else if (i % 4 == 0) {
  250. ASSERT_EQ(value, Key(i) + "_overwrite2");
  251. } else if (i % 2 == 0) {
  252. ASSERT_EQ(value, Key(i) + "_overwrite1");
  253. } else {
  254. ASSERT_EQ(value, Key(i) + "_val");
  255. }
  256. }
  257. }
  258. TEST_F(ImportColumnFamilyTest, ImportSSTFileWriterFilesWithRangeTombstone) {
  259. // Test for a bug where import file's smallest and largest key did not
  260. // consider range tombstone.
  261. Options options = CurrentOptions();
  262. CreateAndReopenWithCF({"koko"}, options);
  263. SstFileWriter sfw_cf1(EnvOptions(), options, handles_[1]);
  264. // cf1.sst
  265. const std::string cf1_sst_name = "cf1.sst";
  266. const std::string cf1_sst = sst_files_dir_ + cf1_sst_name;
  267. ASSERT_OK(sfw_cf1.Open(cf1_sst));
  268. ASSERT_OK(sfw_cf1.Put("K1", "V1"));
  269. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  270. ASSERT_OK(sfw_cf1.DeleteRange("K3", "K4"));
  271. ASSERT_OK(sfw_cf1.DeleteRange("K7", "K9"));
  272. ASSERT_OK(sfw_cf1.Finish());
  273. // Import sst file corresponding to cf1 onto a new cf and verify
  274. ExportImportFilesMetaData metadata;
  275. metadata.files.push_back(
  276. LiveFileMetaDataInit(cf1_sst_name, sst_files_dir_, 0, 0, 19));
  277. metadata.db_comparator_name = options.comparator->Name();
  278. ASSERT_OK(db_->CreateColumnFamilyWithImport(
  279. options, "toto", ImportColumnFamilyOptions(), metadata, &import_cfh_));
  280. ASSERT_NE(import_cfh_, nullptr);
  281. ColumnFamilyMetaData import_cf_meta;
  282. db_->GetColumnFamilyMetaData(import_cfh_, &import_cf_meta);
  283. ASSERT_EQ(import_cf_meta.file_count, 1);
  284. const SstFileMetaData* file_meta = nullptr;
  285. for (const auto& level_meta : import_cf_meta.levels) {
  286. if (!level_meta.files.empty()) {
  287. file_meta = level_meta.files.data();
  288. break;
  289. }
  290. }
  291. ASSERT_TRUE(file_meta != nullptr);
  292. InternalKey largest;
  293. largest.DecodeFrom(file_meta->largest);
  294. ASSERT_EQ(largest.user_key(), "K9");
  295. std::string value;
  296. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, "K1", &value));
  297. ASSERT_EQ(value, "V1");
  298. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, "K2", &value));
  299. ASSERT_EQ(value, "V2");
  300. ASSERT_OK(db_->DropColumnFamily(import_cfh_));
  301. ASSERT_OK(db_->DestroyColumnFamilyHandle(import_cfh_));
  302. import_cfh_ = nullptr;
  303. }
  304. TEST_F(ImportColumnFamilyTest, ImportExportedSSTFromAnotherCF) {
  305. Options options = CurrentOptions();
  306. CreateAndReopenWithCF({"koko"}, options);
  307. for (int i = 0; i < 100; ++i) {
  308. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  309. }
  310. ASSERT_OK(Flush(1));
  311. ASSERT_OK(
  312. db_->CompactRange(CompactRangeOptions(), handles_[1], nullptr, nullptr));
  313. // Overwrite the value in the same set of keys.
  314. for (int i = 0; i < 100; ++i) {
  315. ASSERT_OK(Put(1, Key(i), Key(i) + "_overwrite"));
  316. }
  317. // Flush to create L0 file.
  318. ASSERT_OK(Flush(1));
  319. for (int i = 0; i < 100; ++i) {
  320. ASSERT_OK(Put(1, Key(i), Key(i) + "_overwrite2"));
  321. }
  322. // Flush again to create another L0 file. It should have higher sequencer.
  323. ASSERT_OK(Flush(1));
  324. Checkpoint* checkpoint;
  325. ASSERT_OK(Checkpoint::Create(db_, &checkpoint));
  326. ASSERT_OK(checkpoint->ExportColumnFamily(handles_[1], export_files_dir_,
  327. &metadata_ptr_));
  328. ASSERT_NE(metadata_ptr_, nullptr);
  329. delete checkpoint;
  330. ImportColumnFamilyOptions import_options;
  331. import_options.move_files = false;
  332. ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "toto", import_options,
  333. *metadata_ptr_, &import_cfh_));
  334. ASSERT_NE(import_cfh_, nullptr);
  335. import_options.move_files = true;
  336. ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "yoyo", import_options,
  337. *metadata_ptr_, &import_cfh2_));
  338. ASSERT_NE(import_cfh2_, nullptr);
  339. delete metadata_ptr_;
  340. metadata_ptr_ = nullptr;
  341. std::string value1, value2;
  342. for (int i = 0; i < 100; ++i) {
  343. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  344. ASSERT_EQ(Get(1, Key(i)), value1);
  345. }
  346. for (int i = 0; i < 100; ++i) {
  347. ASSERT_OK(db_->Get(ReadOptions(), import_cfh2_, Key(i), &value2));
  348. ASSERT_EQ(Get(1, Key(i)), value2);
  349. }
  350. // Modify keys in cf1 and verify.
  351. for (int i = 0; i < 25; i++) {
  352. ASSERT_OK(db_->Delete(WriteOptions(), import_cfh_, Key(i)));
  353. }
  354. for (int i = 25; i < 50; i++) {
  355. ASSERT_OK(
  356. db_->Put(WriteOptions(), import_cfh_, Key(i), Key(i) + "_overwrite3"));
  357. }
  358. for (int i = 0; i < 25; ++i) {
  359. ASSERT_TRUE(
  360. db_->Get(ReadOptions(), import_cfh_, Key(i), &value1).IsNotFound());
  361. }
  362. for (int i = 25; i < 50; ++i) {
  363. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  364. ASSERT_EQ(Key(i) + "_overwrite3", value1);
  365. }
  366. for (int i = 50; i < 100; ++i) {
  367. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  368. ASSERT_EQ(Key(i) + "_overwrite2", value1);
  369. }
  370. for (int i = 0; i < 100; ++i) {
  371. ASSERT_OK(db_->Get(ReadOptions(), import_cfh2_, Key(i), &value2));
  372. ASSERT_EQ(Get(1, Key(i)), value2);
  373. }
  374. // Compact and check again.
  375. ASSERT_OK(db_->Flush(FlushOptions(), import_cfh_));
  376. ASSERT_OK(
  377. db_->CompactRange(CompactRangeOptions(), import_cfh_, nullptr, nullptr));
  378. for (int i = 0; i < 25; ++i) {
  379. ASSERT_TRUE(
  380. db_->Get(ReadOptions(), import_cfh_, Key(i), &value1).IsNotFound());
  381. }
  382. for (int i = 25; i < 50; ++i) {
  383. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  384. ASSERT_EQ(Key(i) + "_overwrite3", value1);
  385. }
  386. for (int i = 50; i < 100; ++i) {
  387. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  388. ASSERT_EQ(Key(i) + "_overwrite2", value1);
  389. }
  390. for (int i = 0; i < 100; ++i) {
  391. ASSERT_OK(db_->Get(ReadOptions(), import_cfh2_, Key(i), &value2));
  392. ASSERT_EQ(Get(1, Key(i)), value2);
  393. }
  394. }
  395. TEST_F(ImportColumnFamilyTest, ImportExportedSSTFromAnotherDB) {
  396. Options options = CurrentOptions();
  397. CreateAndReopenWithCF({"koko"}, options);
  398. for (int i = 0; i < 100; ++i) {
  399. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  400. }
  401. ASSERT_OK(Flush(1));
  402. // Compact to create a L1 file.
  403. ASSERT_OK(
  404. db_->CompactRange(CompactRangeOptions(), handles_[1], nullptr, nullptr));
  405. // Overwrite the value in the same set of keys.
  406. for (int i = 0; i < 50; ++i) {
  407. ASSERT_OK(Put(1, Key(i), Key(i) + "_overwrite"));
  408. }
  409. // Flush to create L0 file.
  410. ASSERT_OK(Flush(1));
  411. for (int i = 0; i < 25; ++i) {
  412. ASSERT_OK(Put(1, Key(i), Key(i) + "_overwrite2"));
  413. }
  414. // Flush again to create another L0 file. It should have higher sequencer.
  415. ASSERT_OK(Flush(1));
  416. Checkpoint* checkpoint;
  417. ASSERT_OK(Checkpoint::Create(db_, &checkpoint));
  418. ASSERT_OK(checkpoint->ExportColumnFamily(handles_[1], export_files_dir_,
  419. &metadata_ptr_));
  420. ASSERT_NE(metadata_ptr_, nullptr);
  421. delete checkpoint;
  422. // Create a new db and import the files.
  423. DB* db_copy;
  424. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  425. ASSERT_OK(DB::Open(options, dbname_ + "/db_copy", &db_copy));
  426. ColumnFamilyHandle* cfh = nullptr;
  427. ASSERT_OK(db_copy->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  428. ImportColumnFamilyOptions(),
  429. *metadata_ptr_, &cfh));
  430. ASSERT_NE(cfh, nullptr);
  431. for (int i = 0; i < 100; ++i) {
  432. std::string value;
  433. ASSERT_OK(db_copy->Get(ReadOptions(), cfh, Key(i), &value));
  434. ASSERT_EQ(Get(1, Key(i)), value);
  435. }
  436. ASSERT_OK(db_copy->DropColumnFamily(cfh));
  437. ASSERT_OK(db_copy->DestroyColumnFamilyHandle(cfh));
  438. delete db_copy;
  439. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  440. }
  441. TEST_F(ImportColumnFamilyTest,
  442. ImportExportedSSTFromAnotherCFWithRangeTombstone) {
  443. // Test for a bug where import file's smallest and largest key did not
  444. // consider range tombstone.
  445. Options options = CurrentOptions();
  446. options.disable_auto_compactions = true;
  447. CreateAndReopenWithCF({"koko"}, options);
  448. for (int i = 10; i < 20; ++i) {
  449. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  450. }
  451. ASSERT_OK(Flush(1 /* cf */));
  452. MoveFilesToLevel(1 /* level */, 1 /* cf */);
  453. const Snapshot* snapshot = db_->GetSnapshot();
  454. ASSERT_OK(db_->DeleteRange(WriteOptions(), handles_[1], Key(0), Key(25)));
  455. ASSERT_OK(Put(1, Key(1), "t"));
  456. ASSERT_OK(Flush(1));
  457. // Tests importing a range tombstone only file
  458. ASSERT_OK(db_->DeleteRange(WriteOptions(), handles_[1], Key(0), Key(2)));
  459. Checkpoint* checkpoint;
  460. ASSERT_OK(Checkpoint::Create(db_, &checkpoint));
  461. ASSERT_OK(checkpoint->ExportColumnFamily(handles_[1], export_files_dir_,
  462. &metadata_ptr_));
  463. ASSERT_NE(metadata_ptr_, nullptr);
  464. delete checkpoint;
  465. ImportColumnFamilyOptions import_options;
  466. import_options.move_files = false;
  467. ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "toto", import_options,
  468. *metadata_ptr_, &import_cfh_));
  469. ASSERT_NE(import_cfh_, nullptr);
  470. import_options.move_files = true;
  471. ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "yoyo", import_options,
  472. *metadata_ptr_, &import_cfh2_));
  473. ASSERT_NE(import_cfh2_, nullptr);
  474. delete metadata_ptr_;
  475. metadata_ptr_ = nullptr;
  476. std::string value1, value2;
  477. ReadOptions ro_latest;
  478. ReadOptions ro_snapshot;
  479. ro_snapshot.snapshot = snapshot;
  480. for (int i = 10; i < 20; ++i) {
  481. ASSERT_TRUE(db_->Get(ro_latest, import_cfh_, Key(i), &value1).IsNotFound());
  482. ASSERT_OK(db_->Get(ro_snapshot, import_cfh_, Key(i), &value1));
  483. ASSERT_EQ(Get(1, Key(i), snapshot), value1);
  484. }
  485. ASSERT_TRUE(db_->Get(ro_latest, import_cfh_, Key(1), &value1).IsNotFound());
  486. for (int i = 10; i < 20; ++i) {
  487. ASSERT_TRUE(
  488. db_->Get(ro_latest, import_cfh2_, Key(i), &value1).IsNotFound());
  489. ASSERT_OK(db_->Get(ro_snapshot, import_cfh2_, Key(i), &value2));
  490. ASSERT_EQ(Get(1, Key(i), snapshot), value2);
  491. }
  492. ASSERT_TRUE(db_->Get(ro_latest, import_cfh2_, Key(1), &value1).IsNotFound());
  493. db_->ReleaseSnapshot(snapshot);
  494. }
  495. TEST_F(ImportColumnFamilyTest, LevelFilesOverlappingAtEndpoints) {
  496. // Imports a column family containing a level where two files overlap at their
  497. // endpoints. "Overlap" means the largest user key in one file is the same as
  498. // the smallest user key in the second file.
  499. const int kFileBytes = 128 << 10; // 128KB
  500. const int kValueBytes = 1 << 10; // 1KB
  501. const int kNumFiles = 4;
  502. Options options = CurrentOptions();
  503. options.disable_auto_compactions = true;
  504. options.num_levels = 2;
  505. CreateAndReopenWithCF({"koko"}, options);
  506. Random rnd(301);
  507. // Every key is snapshot protected to ensure older versions will not be
  508. // dropped during compaction.
  509. std::vector<const Snapshot*> snapshots;
  510. snapshots.reserve(kFileBytes / kValueBytes * kNumFiles);
  511. for (int i = 0; i < kNumFiles; ++i) {
  512. for (int j = 0; j < kFileBytes / kValueBytes; ++j) {
  513. auto value = rnd.RandomString(kValueBytes);
  514. ASSERT_OK(Put(1, "key", value));
  515. snapshots.push_back(db_->GetSnapshot());
  516. }
  517. ASSERT_OK(Flush(1));
  518. }
  519. // Compact to create overlapping L1 files.
  520. ASSERT_OK(
  521. db_->CompactRange(CompactRangeOptions(), handles_[1], nullptr, nullptr));
  522. ASSERT_GT(NumTableFilesAtLevel(1, 1), 1);
  523. Checkpoint* checkpoint;
  524. ASSERT_OK(Checkpoint::Create(db_, &checkpoint));
  525. ASSERT_OK(checkpoint->ExportColumnFamily(handles_[1], export_files_dir_,
  526. &metadata_ptr_));
  527. ASSERT_NE(metadata_ptr_, nullptr);
  528. delete checkpoint;
  529. // Create a new db and import the files.
  530. DB* db_copy;
  531. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  532. ASSERT_OK(DB::Open(options, dbname_ + "/db_copy", &db_copy));
  533. ColumnFamilyHandle* cfh = nullptr;
  534. ASSERT_OK(db_copy->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  535. ImportColumnFamilyOptions(),
  536. *metadata_ptr_, &cfh));
  537. ASSERT_NE(cfh, nullptr);
  538. {
  539. std::string value;
  540. ASSERT_OK(db_copy->Get(ReadOptions(), cfh, "key", &value));
  541. }
  542. ASSERT_OK(db_copy->DropColumnFamily(cfh));
  543. ASSERT_OK(db_copy->DestroyColumnFamilyHandle(cfh));
  544. delete db_copy;
  545. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  546. for (const Snapshot* snapshot : snapshots) {
  547. db_->ReleaseSnapshot(snapshot);
  548. }
  549. }
  550. TEST_F(ImportColumnFamilyTest, ImportColumnFamilyNegativeTest) {
  551. Options options = CurrentOptions();
  552. CreateAndReopenWithCF({"koko"}, options);
  553. {
  554. // Create column family with existing cf name.
  555. ExportImportFilesMetaData metadata;
  556. metadata.db_comparator_name = options.comparator->Name();
  557. Status s = db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "koko",
  558. ImportColumnFamilyOptions(),
  559. metadata, &import_cfh_);
  560. ASSERT_TRUE(std::strstr(s.getState(), "Column family already exists"));
  561. ASSERT_EQ(import_cfh_, nullptr);
  562. }
  563. {
  564. // Import with no files specified.
  565. ExportImportFilesMetaData metadata;
  566. metadata.db_comparator_name = options.comparator->Name();
  567. Status s = db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  568. ImportColumnFamilyOptions(),
  569. metadata, &import_cfh_);
  570. ASSERT_TRUE(std::strstr(s.getState(), "The list of files is empty"));
  571. ASSERT_EQ(import_cfh_, nullptr);
  572. }
  573. {
  574. // Import with overlapping keys in sst files.
  575. ExportImportFilesMetaData metadata;
  576. SstFileWriter sfw_cf1(EnvOptions(), options, handles_[1]);
  577. const std::string file1_sst_name = "file1.sst";
  578. const std::string file1_sst = sst_files_dir_ + file1_sst_name;
  579. ASSERT_OK(sfw_cf1.Open(file1_sst));
  580. ASSERT_OK(sfw_cf1.Put("K1", "V1"));
  581. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  582. ASSERT_OK(sfw_cf1.Finish());
  583. const std::string file2_sst_name = "file2.sst";
  584. const std::string file2_sst = sst_files_dir_ + file2_sst_name;
  585. ASSERT_OK(sfw_cf1.Open(file2_sst));
  586. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  587. ASSERT_OK(sfw_cf1.Put("K3", "V3"));
  588. ASSERT_OK(sfw_cf1.Finish());
  589. metadata.files.push_back(
  590. LiveFileMetaDataInit(file1_sst_name, sst_files_dir_, 1, 10, 19));
  591. metadata.files.push_back(
  592. LiveFileMetaDataInit(file2_sst_name, sst_files_dir_, 1, 10, 19));
  593. metadata.db_comparator_name = options.comparator->Name();
  594. ASSERT_NOK(db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  595. ImportColumnFamilyOptions(),
  596. metadata, &import_cfh_));
  597. ASSERT_EQ(import_cfh_, nullptr);
  598. }
  599. {
  600. // Import with a mismatching comparator, should fail with appropriate error.
  601. ExportImportFilesMetaData metadata;
  602. Options mismatch_options = CurrentOptions();
  603. mismatch_options.comparator = ReverseBytewiseComparator();
  604. SstFileWriter sfw_cf1(EnvOptions(), mismatch_options, handles_[1]);
  605. const std::string file1_sst_name = "file1.sst";
  606. const std::string file1_sst = sst_files_dir_ + file1_sst_name;
  607. ASSERT_OK(sfw_cf1.Open(file1_sst));
  608. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  609. ASSERT_OK(sfw_cf1.Put("K1", "V1"));
  610. ASSERT_OK(sfw_cf1.Finish());
  611. metadata.files.push_back(
  612. LiveFileMetaDataInit(file1_sst_name, sst_files_dir_, 1, 10, 19));
  613. metadata.db_comparator_name = mismatch_options.comparator->Name();
  614. Status s = db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "coco",
  615. ImportColumnFamilyOptions(),
  616. metadata, &import_cfh_);
  617. ASSERT_TRUE(std::strstr(s.getState(), "Comparator name mismatch"));
  618. ASSERT_EQ(import_cfh_, nullptr);
  619. }
  620. {
  621. // Import with non existent sst file should fail with appropriate error
  622. ExportImportFilesMetaData metadata;
  623. SstFileWriter sfw_cf1(EnvOptions(), options, handles_[1]);
  624. const std::string file1_sst_name = "file1.sst";
  625. const std::string file1_sst = sst_files_dir_ + file1_sst_name;
  626. ASSERT_OK(sfw_cf1.Open(file1_sst));
  627. ASSERT_OK(sfw_cf1.Put("K1", "V1"));
  628. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  629. ASSERT_OK(sfw_cf1.Finish());
  630. const std::string file3_sst_name = "file3.sst";
  631. metadata.files.push_back(
  632. LiveFileMetaDataInit(file1_sst_name, sst_files_dir_, 1, 10, 19));
  633. metadata.files.push_back(
  634. LiveFileMetaDataInit(file3_sst_name, sst_files_dir_, 1, 10, 19));
  635. metadata.db_comparator_name = options.comparator->Name();
  636. Status s = db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  637. ImportColumnFamilyOptions(),
  638. metadata, &import_cfh_);
  639. ASSERT_TRUE(std::strstr(s.getState(), "No such file or directory"));
  640. ASSERT_EQ(import_cfh_, nullptr);
  641. // Test successful import after a failure with the same CF name. Ensures
  642. // there is no side effect with CF when there is a failed import
  643. metadata.files.pop_back();
  644. metadata.db_comparator_name = options.comparator->Name();
  645. ASSERT_OK(db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  646. ImportColumnFamilyOptions(),
  647. metadata, &import_cfh_));
  648. ASSERT_NE(import_cfh_, nullptr);
  649. }
  650. }
  651. TEST_F(ImportColumnFamilyTest, ImportMultiColumnFamilyTest) {
  652. Options options = CurrentOptions();
  653. CreateAndReopenWithCF({"koko"}, options);
  654. for (int i = 0; i < 100; ++i) {
  655. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  656. }
  657. ASSERT_OK(Flush(1));
  658. ASSERT_OK(
  659. db_->CompactRange(CompactRangeOptions(), handles_[1], nullptr, nullptr));
  660. // Overwrite the value in the same set of keys.
  661. for (int i = 0; i < 100; ++i) {
  662. ASSERT_OK(Put(1, Key(i), Key(i) + "_overwrite"));
  663. }
  664. // Flush again to create another L0 file. It should have higher sequencer.
  665. ASSERT_OK(Flush(1));
  666. Checkpoint* checkpoint1;
  667. Checkpoint* checkpoint2;
  668. ASSERT_OK(Checkpoint::Create(db_, &checkpoint1));
  669. ASSERT_OK(checkpoint1->ExportColumnFamily(handles_[1], export_files_dir_,
  670. &metadata_ptr_));
  671. // Create a new db and import the files.
  672. DB* db_copy;
  673. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  674. ASSERT_OK(DB::Open(options, dbname_ + "/db_copy", &db_copy));
  675. ColumnFamilyHandle* copy_cfh = nullptr;
  676. ASSERT_OK(db_copy->CreateColumnFamily(options, "koko", &copy_cfh));
  677. WriteOptions wo;
  678. for (int i = 100; i < 200; ++i) {
  679. ASSERT_OK(db_copy->Put(wo, copy_cfh, Key(i), Key(i) + "_val"));
  680. }
  681. ASSERT_OK(db_copy->Flush(FlushOptions()));
  682. for (int i = 100; i < 200; ++i) {
  683. ASSERT_OK(db_copy->Put(wo, copy_cfh, Key(i), Key(i) + "_overwrite"));
  684. }
  685. ASSERT_OK(db_copy->Flush(FlushOptions()));
  686. for (int i = 100; i < 200; ++i) {
  687. ASSERT_OK(db_copy->Put(wo, copy_cfh, Key(i), Key(i) + "_overwrite2"));
  688. }
  689. ASSERT_OK(db_copy->Flush(FlushOptions()));
  690. // Flush again to create another L0 file. It should have higher sequencer.
  691. ASSERT_OK(Checkpoint::Create(db_copy, &checkpoint2));
  692. ASSERT_OK(checkpoint2->ExportColumnFamily(copy_cfh, export_files_dir2_,
  693. &metadata_ptr2_));
  694. ASSERT_NE(metadata_ptr_, nullptr);
  695. ASSERT_NE(metadata_ptr2_, nullptr);
  696. delete checkpoint1;
  697. delete checkpoint2;
  698. ImportColumnFamilyOptions import_options;
  699. import_options.move_files = false;
  700. std::vector<const ExportImportFilesMetaData*> metadatas = {metadata_ptr_,
  701. metadata_ptr2_};
  702. ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "toto", import_options,
  703. metadatas, &import_cfh_));
  704. std::string value1, value2;
  705. for (int i = 0; i < 100; ++i) {
  706. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  707. ASSERT_EQ(Get(1, Key(i)), value1);
  708. }
  709. for (int i = 100; i < 200; ++i) {
  710. ASSERT_OK(db_->Get(ReadOptions(), import_cfh_, Key(i), &value1));
  711. ASSERT_OK(db_copy->Get(ReadOptions(), copy_cfh, Key(i), &value2));
  712. ASSERT_EQ(value1, value2);
  713. }
  714. ASSERT_OK(db_copy->DropColumnFamily(copy_cfh));
  715. ASSERT_OK(db_copy->DestroyColumnFamilyHandle(copy_cfh));
  716. delete db_copy;
  717. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  718. }
  719. TEST_F(ImportColumnFamilyTest, ImportMultiColumnFamilyWithOverlap) {
  720. Options options = CurrentOptions();
  721. CreateAndReopenWithCF({"koko"}, options);
  722. for (int i = 0; i < 100; ++i) {
  723. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  724. }
  725. Checkpoint* checkpoint1;
  726. Checkpoint* checkpoint2;
  727. ASSERT_OK(Checkpoint::Create(db_, &checkpoint1));
  728. ASSERT_OK(checkpoint1->ExportColumnFamily(handles_[1], export_files_dir_,
  729. &metadata_ptr_));
  730. // Create a new db and import the files.
  731. DB* db_copy;
  732. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  733. ASSERT_OK(DB::Open(options, dbname_ + "/db_copy", &db_copy));
  734. ColumnFamilyHandle* copy_cfh = nullptr;
  735. ASSERT_OK(db_copy->CreateColumnFamily(options, "koko", &copy_cfh));
  736. WriteOptions wo;
  737. for (int i = 50; i < 150; ++i) {
  738. ASSERT_OK(db_copy->Put(wo, copy_cfh, Key(i), Key(i) + "_val"));
  739. }
  740. ASSERT_OK(db_copy->Flush(FlushOptions()));
  741. // Flush again to create another L0 file. It should have higher sequencer.
  742. ASSERT_OK(Checkpoint::Create(db_copy, &checkpoint2));
  743. ASSERT_OK(checkpoint2->ExportColumnFamily(copy_cfh, export_files_dir2_,
  744. &metadata_ptr2_));
  745. ASSERT_NE(metadata_ptr_, nullptr);
  746. ASSERT_NE(metadata_ptr2_, nullptr);
  747. delete checkpoint1;
  748. delete checkpoint2;
  749. ImportColumnFamilyOptions import_options;
  750. import_options.move_files = false;
  751. std::vector<const ExportImportFilesMetaData*> metadatas = {metadata_ptr_,
  752. metadata_ptr2_};
  753. ASSERT_EQ(db_->CreateColumnFamilyWithImport(options, "toto", import_options,
  754. metadatas, &import_cfh_),
  755. Status::InvalidArgument("CFs have overlapping ranges"));
  756. ASSERT_OK(db_copy->DropColumnFamily(copy_cfh));
  757. ASSERT_OK(db_copy->DestroyColumnFamilyHandle(copy_cfh));
  758. delete db_copy;
  759. ASSERT_OK(DestroyDir(env_, dbname_ + "/db_copy"));
  760. }
  761. TEST_F(ImportColumnFamilyTest, ImportMultiColumnFamilySeveralFilesWithOverlap) {
  762. Options options = CurrentOptions();
  763. CreateAndReopenWithCF({"koko"}, options);
  764. SstFileWriter sfw_cf1(EnvOptions(), options, handles_[1]);
  765. const std::string file1_sst_name = "file1.sst";
  766. const std::string file1_sst = sst_files_dir_ + file1_sst_name;
  767. ASSERT_OK(sfw_cf1.Open(file1_sst));
  768. ASSERT_OK(sfw_cf1.Put("K1", "V1"));
  769. ASSERT_OK(sfw_cf1.Put("K2", "V2"));
  770. ASSERT_OK(sfw_cf1.Finish());
  771. SstFileWriter sfw_cf2(EnvOptions(), options, handles_[1]);
  772. const std::string file2_sst_name = "file2.sst";
  773. const std::string file2_sst = sst_files_dir_ + file2_sst_name;
  774. ASSERT_OK(sfw_cf2.Open(file2_sst));
  775. ASSERT_OK(sfw_cf2.Put("K2", "V2"));
  776. ASSERT_OK(sfw_cf2.Put("K3", "V3"));
  777. ASSERT_OK(sfw_cf2.Finish());
  778. ColumnFamilyHandle* second_cfh = nullptr;
  779. ASSERT_OK(db_->CreateColumnFamily(options, "toto", &second_cfh));
  780. SstFileWriter sfw_cf3(EnvOptions(), options, second_cfh);
  781. const std::string file3_sst_name = "file3.sst";
  782. const std::string file3_sst = sst_files_dir_ + file3_sst_name;
  783. ASSERT_OK(sfw_cf3.Open(file3_sst));
  784. ASSERT_OK(sfw_cf3.Put("K3", "V3"));
  785. ASSERT_OK(sfw_cf3.Put("K4", "V4"));
  786. ASSERT_OK(sfw_cf3.Finish());
  787. SstFileWriter sfw_cf4(EnvOptions(), options, second_cfh);
  788. const std::string file4_sst_name = "file4.sst";
  789. const std::string file4_sst = sst_files_dir_ + file4_sst_name;
  790. ASSERT_OK(sfw_cf4.Open(file4_sst));
  791. ASSERT_OK(sfw_cf4.Put("K4", "V4"));
  792. ASSERT_OK(sfw_cf4.Put("K5", "V5"));
  793. ASSERT_OK(sfw_cf4.Finish());
  794. ExportImportFilesMetaData metadata1, metadata2;
  795. metadata1.files.push_back(
  796. LiveFileMetaDataInit(file1_sst_name, sst_files_dir_, 1, 1, 2));
  797. metadata1.files.push_back(
  798. LiveFileMetaDataInit(file2_sst_name, sst_files_dir_, 1, 3, 4));
  799. metadata1.db_comparator_name = options.comparator->Name();
  800. metadata2.files.push_back(
  801. LiveFileMetaDataInit(file3_sst_name, sst_files_dir_, 1, 1, 2));
  802. metadata2.files.push_back(
  803. LiveFileMetaDataInit(file4_sst_name, sst_files_dir_, 1, 3, 4));
  804. metadata2.db_comparator_name = options.comparator->Name();
  805. std::vector<const ExportImportFilesMetaData*> metadatas{&metadata1,
  806. &metadata2};
  807. ASSERT_EQ(db_->CreateColumnFamilyWithImport(ColumnFamilyOptions(), "yoyo",
  808. ImportColumnFamilyOptions(),
  809. metadatas, &import_cfh_),
  810. Status::InvalidArgument("CFs have overlapping ranges"));
  811. ASSERT_EQ(import_cfh_, nullptr);
  812. ASSERT_OK(db_->DropColumnFamily(second_cfh));
  813. ASSERT_OK(db_->DestroyColumnFamilyHandle(second_cfh));
  814. }
  815. TEST_F(ImportColumnFamilyTest, AssignEpochNumberToMultipleCF) {
  816. // Test ingesting CFs where L0 files could have the same epoch number.
  817. Options options = CurrentOptions();
  818. options.level_compaction_dynamic_level_bytes = true;
  819. options.max_background_jobs = 8;
  820. // Always allow parallel compaction
  821. options.soft_pending_compaction_bytes_limit = 10;
  822. env_->SetBackgroundThreads(2, Env::LOW);
  823. env_->SetBackgroundThreads(0, Env::BOTTOM);
  824. CreateAndReopenWithCF({"CF1", "CF2"}, options);
  825. // CF1:
  826. // L6: [0, 99], [100, 199]
  827. // CF2:
  828. // L6: [1000, 1099], [1100, 1199]
  829. for (int i = 100; i < 200; ++i) {
  830. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  831. ASSERT_OK(Put(2, Key(1000 + i), Key(1000 + i) + "_val"));
  832. }
  833. ASSERT_OK(Flush(1));
  834. ASSERT_OK(Flush(2));
  835. for (int i = 0; i < 100; ++i) {
  836. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  837. ASSERT_OK(Put(2, Key(1000 + i), Key(1000 + i) + "_val"));
  838. }
  839. ASSERT_OK(Flush(1));
  840. ASSERT_OK(Flush(2));
  841. MoveFilesToLevel(6, 1);
  842. MoveFilesToLevel(6, 2);
  843. // CF1:
  844. // level 0 epoch: 5 file num 30 smallest key000010 - key000019
  845. // level 0 epoch: 4 file num 27 smallest key000000 - key000009
  846. // level 0 epoch: 3 file num 23 smallest key000100 - key000199
  847. // level 6 epoch: 2 file num 20 smallest key000000 - key000099
  848. // level 6 epoch: 1 file num 17 smallest key000100 - key000199
  849. // CF2:
  850. // level 0 epoch: 5 file num 31 smallest key001010 - key001019
  851. // level 0 epoch: 4 file num 28 smallest key001000 - key001009
  852. // level 0 epoch: 3 file num 25 smallest key001020 - key001029
  853. // level 6 epoch: 2 file num 21 smallest key001000 - key001099
  854. // level 6 epoch: 1 file num 18 smallest key001100 - key001199
  855. for (int i = 100; i < 200; ++i) {
  856. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  857. }
  858. ASSERT_OK(Flush(1));
  859. for (int i = 20; i < 30; ++i) {
  860. ASSERT_OK(Put(2, Key(i + 1000), Key(i + 1000) + "_val"));
  861. }
  862. ASSERT_OK(Flush(2));
  863. for (int i = 0; i < 20; ++i) {
  864. ASSERT_OK(Put(1, Key(i), Key(i) + "_val"));
  865. ASSERT_OK(Put(2, Key(i + 1000), Key(i + 1000) + "_val"));
  866. if (i % 10 == 9) {
  867. ASSERT_OK(Flush(1));
  868. ASSERT_OK(Flush(2));
  869. }
  870. }
  871. ASSERT_OK(Flush(1));
  872. ASSERT_OK(Flush(2));
  873. // Create a CF by importing these two CF1 and CF2.
  874. // Then two compactions will be triggerred, one to compact from L0
  875. // to L6 (files #23 and #17), and another to do intra-L0 compaction
  876. // for the rest of the L0 files. Before a bug fix, we used to
  877. // directly use the epoch numbers from the ingested files in the new CF.
  878. // This means different files from different CFs can have the same epoch
  879. // number. If the intra-L0 compaction finishes first, it can cause a
  880. // corruption where two L0 files can have the same epoch number but
  881. // with overlapping key range.
  882. Checkpoint* checkpoint1;
  883. ASSERT_OK(Checkpoint::Create(db_, &checkpoint1));
  884. ASSERT_OK(checkpoint1->ExportColumnFamily(handles_[1], export_files_dir_,
  885. &metadata_ptr_));
  886. ASSERT_OK(checkpoint1->ExportColumnFamily(handles_[2], export_files_dir2_,
  887. &metadata_ptr2_));
  888. ASSERT_NE(metadata_ptr_, nullptr);
  889. ASSERT_NE(metadata_ptr2_, nullptr);
  890. std::atomic_int compaction_counter = 0;
  891. SyncPoint::GetInstance()->SetCallBack(
  892. "DBImpl::BackgroundCompaction:NonTrivial:BeforeRun",
  893. [&compaction_counter](void*) {
  894. compaction_counter++;
  895. if (compaction_counter == 1) {
  896. // Wait for the next compaction to finish
  897. TEST_SYNC_POINT("WaitForSecondCompaction");
  898. }
  899. });
  900. SyncPoint::GetInstance()->LoadDependency(
  901. {{"DBImpl::BackgroundCompaction:AfterCompaction",
  902. "WaitForSecondCompaction"}});
  903. SyncPoint::GetInstance()->EnableProcessing();
  904. ImportColumnFamilyOptions import_options;
  905. import_options.move_files = false;
  906. std::vector<const ExportImportFilesMetaData*> metadatas = {metadata_ptr_,
  907. metadata_ptr2_};
  908. ASSERT_OK(db_->CreateColumnFamilyWithImport(options, "CF3", import_options,
  909. metadatas, &import_cfh_));
  910. WaitForCompactOptions o;
  911. ASSERT_OK(db_->WaitForCompact(o));
  912. delete checkpoint1;
  913. }
  914. } // namespace ROCKSDB_NAMESPACE
  915. int main(int argc, char** argv) {
  916. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  917. ::testing::InitGoogleTest(&argc, argv);
  918. return RUN_ALL_TESTS();
  919. }