version_builder_test.cc 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905
  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. #include <cstring>
  6. #include <iomanip>
  7. #include <memory>
  8. #include <sstream>
  9. #include <string>
  10. #include "db/version_edit.h"
  11. #include "db/version_set.h"
  12. #include "rocksdb/advanced_options.h"
  13. #include "table/unique_id_impl.h"
  14. #include "test_util/testharness.h"
  15. #include "test_util/testutil.h"
  16. #include "util/string_util.h"
  17. namespace ROCKSDB_NAMESPACE {
  18. class VersionBuilderTest : public testing::Test {
  19. public:
  20. const Comparator* ucmp_;
  21. InternalKeyComparator icmp_;
  22. Options options_;
  23. ImmutableOptions ioptions_;
  24. MutableCFOptions mutable_cf_options_;
  25. VersionStorageInfo vstorage_;
  26. uint32_t file_num_;
  27. CompactionOptionsFIFO fifo_options_;
  28. std::vector<uint64_t> size_being_compacted_;
  29. VersionBuilderTest()
  30. : ucmp_(BytewiseComparator()),
  31. icmp_(ucmp_),
  32. ioptions_(options_),
  33. mutable_cf_options_(options_),
  34. vstorage_(&icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel,
  35. nullptr, false, EpochNumberRequirement::kMustPresent,
  36. ioptions_.clock, options_.bottommost_file_compaction_delay,
  37. OffpeakTimeOption(options_.daily_offpeak_time_utc)),
  38. file_num_(1) {
  39. mutable_cf_options_.RefreshDerivedOptions(ioptions_);
  40. size_being_compacted_.resize(options_.num_levels);
  41. }
  42. ~VersionBuilderTest() override {
  43. for (int i = 0; i < vstorage_.num_levels(); i++) {
  44. for (auto* f : vstorage_.LevelFiles(i)) {
  45. if (--f->refs == 0) {
  46. delete f;
  47. }
  48. }
  49. }
  50. }
  51. InternalKey GetInternalKey(const char* ukey,
  52. SequenceNumber smallest_seq = 100) {
  53. return InternalKey(ukey, smallest_seq, kTypeValue);
  54. }
  55. void Add(int level, uint64_t file_number, const char* smallest,
  56. const char* largest, uint64_t file_size = 0, uint32_t path_id = 0,
  57. SequenceNumber smallest_seq = 100, SequenceNumber largest_seq = 100,
  58. uint64_t num_entries = 0, uint64_t num_deletions = 0,
  59. bool sampled = false, SequenceNumber smallest_seqno = 0,
  60. SequenceNumber largest_seqno = 0,
  61. uint64_t oldest_blob_file_number = kInvalidBlobFileNumber,
  62. uint64_t epoch_number = kUnknownEpochNumber) {
  63. assert(level < vstorage_.num_levels());
  64. FileMetaData* f = new FileMetaData(
  65. file_number, path_id, file_size, GetInternalKey(smallest, smallest_seq),
  66. GetInternalKey(largest, largest_seq), smallest_seqno, largest_seqno,
  67. /* marked_for_compact */ false, Temperature::kUnknown,
  68. oldest_blob_file_number, kUnknownOldestAncesterTime,
  69. kUnknownFileCreationTime, epoch_number, kUnknownFileChecksum,
  70. kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0, 0,
  71. /* user_defined_timestamps_persisted */ true);
  72. f->compensated_file_size = file_size;
  73. f->num_entries = num_entries;
  74. f->num_deletions = num_deletions;
  75. vstorage_.AddFile(level, f);
  76. if (sampled) {
  77. f->init_stats_from_file = true;
  78. vstorage_.UpdateAccumulatedStats(f);
  79. }
  80. }
  81. void AddBlob(uint64_t blob_file_number, uint64_t total_blob_count,
  82. uint64_t total_blob_bytes, std::string checksum_method,
  83. std::string checksum_value,
  84. BlobFileMetaData::LinkedSsts linked_ssts,
  85. uint64_t garbage_blob_count, uint64_t garbage_blob_bytes) {
  86. auto shared_meta = SharedBlobFileMetaData::Create(
  87. blob_file_number, total_blob_count, total_blob_bytes,
  88. std::move(checksum_method), std::move(checksum_value));
  89. auto meta =
  90. BlobFileMetaData::Create(std::move(shared_meta), std::move(linked_ssts),
  91. garbage_blob_count, garbage_blob_bytes);
  92. vstorage_.AddBlobFile(std::move(meta));
  93. }
  94. void AddDummyFile(uint64_t table_file_number, uint64_t blob_file_number,
  95. uint64_t epoch_number) {
  96. constexpr int level = 0;
  97. constexpr char smallest[] = "bar";
  98. constexpr char largest[] = "foo";
  99. constexpr uint64_t file_size = 100;
  100. constexpr uint32_t path_id = 0;
  101. constexpr SequenceNumber smallest_seq = 0;
  102. constexpr SequenceNumber largest_seq = 0;
  103. constexpr uint64_t num_entries = 0;
  104. constexpr uint64_t num_deletions = 0;
  105. constexpr bool sampled = false;
  106. Add(level, table_file_number, smallest, largest, file_size, path_id,
  107. smallest_seq, largest_seq, num_entries, num_deletions, sampled,
  108. smallest_seq, largest_seq, blob_file_number, epoch_number);
  109. }
  110. void AddDummyFileToEdit(VersionEdit* edit, uint64_t table_file_number,
  111. uint64_t blob_file_number, uint64_t epoch_number) {
  112. assert(edit);
  113. constexpr int level = 0;
  114. constexpr uint32_t path_id = 0;
  115. constexpr uint64_t file_size = 100;
  116. constexpr char smallest[] = "bar";
  117. constexpr char largest[] = "foo";
  118. constexpr SequenceNumber smallest_seqno = 100;
  119. constexpr SequenceNumber largest_seqno = 300;
  120. constexpr bool marked_for_compaction = false;
  121. edit->AddFile(
  122. level, table_file_number, path_id, file_size, GetInternalKey(smallest),
  123. GetInternalKey(largest), smallest_seqno, largest_seqno,
  124. marked_for_compaction, Temperature::kUnknown, blob_file_number,
  125. kUnknownOldestAncesterTime, kUnknownFileCreationTime, epoch_number,
  126. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2,
  127. 0, 0, /* user_defined_timestamps_persisted */ true);
  128. }
  129. void UpdateVersionStorageInfo(VersionStorageInfo* vstorage) {
  130. assert(vstorage);
  131. vstorage->PrepareForVersionAppend(ioptions_, mutable_cf_options_);
  132. vstorage->SetFinalized();
  133. }
  134. void UpdateVersionStorageInfo() { UpdateVersionStorageInfo(&vstorage_); }
  135. };
  136. void UnrefFilesInVersion(VersionStorageInfo* new_vstorage) {
  137. for (int i = 0; i < new_vstorage->num_levels(); i++) {
  138. for (auto* f : new_vstorage->LevelFiles(i)) {
  139. if (--f->refs == 0) {
  140. delete f;
  141. }
  142. }
  143. }
  144. }
  145. TEST_F(VersionBuilderTest, ApplyAndSaveTo) {
  146. Add(0, 1U, "150", "200", 100U, /*path_id*/ 0,
  147. /*smallest_seq*/ 100, /*largest_seq*/ 100,
  148. /*num_entries*/ 0, /*num_deletions*/ 0,
  149. /*sampled*/ false, /*smallest_seqno*/ 0,
  150. /*largest_seqno*/ 0,
  151. /*oldest_blob_file_number*/ kInvalidBlobFileNumber,
  152. /*epoch_number*/ 1);
  153. Add(1, 66U, "150", "200", 100U);
  154. Add(1, 88U, "201", "300", 100U);
  155. Add(2, 6U, "150", "179", 100U);
  156. Add(2, 7U, "180", "220", 100U);
  157. Add(2, 8U, "221", "300", 100U);
  158. Add(3, 26U, "150", "170", 100U);
  159. Add(3, 27U, "171", "179", 100U);
  160. Add(3, 28U, "191", "220", 100U);
  161. Add(3, 29U, "221", "300", 100U);
  162. UpdateVersionStorageInfo();
  163. VersionEdit version_edit;
  164. version_edit.AddFile(
  165. 2, 666, 0, 100U, GetInternalKey("301"), GetInternalKey("350"), 200, 200,
  166. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  167. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  168. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  169. 0, /* user_defined_timestamps_persisted */ true);
  170. version_edit.DeleteFile(3, 27U);
  171. EnvOptions env_options;
  172. constexpr TableCache* table_cache = nullptr;
  173. constexpr VersionSet* version_set = nullptr;
  174. VersionBuilder version_builder(env_options, &ioptions_, table_cache,
  175. &vstorage_, version_set);
  176. VersionStorageInfo new_vstorage(
  177. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr, false,
  178. EpochNumberRequirement::kMightMissing, nullptr, 0,
  179. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  180. ASSERT_OK(version_builder.Apply(&version_edit));
  181. ASSERT_OK(version_builder.SaveTo(&new_vstorage));
  182. UpdateVersionStorageInfo(&new_vstorage);
  183. ASSERT_EQ(400U, new_vstorage.NumLevelBytes(2));
  184. ASSERT_EQ(300U, new_vstorage.NumLevelBytes(3));
  185. UnrefFilesInVersion(&new_vstorage);
  186. }
  187. TEST_F(VersionBuilderTest, ApplyAndSaveToDynamic) {
  188. ioptions_.level_compaction_dynamic_level_bytes = true;
  189. Add(0, 1U, "150", "200", 100U, 0, 200U, 200U, 0, 0, false, 200U, 200U,
  190. /*oldest_blob_file_number*/ kInvalidBlobFileNumber,
  191. /*epoch_number*/ 2);
  192. Add(0, 88U, "201", "300", 100U, 0, 100U, 100U, 0, 0, false, 100U, 100U,
  193. /*oldest_blob_file_number*/ kInvalidBlobFileNumber,
  194. /*epoch_number*/ 1);
  195. Add(4, 6U, "150", "179", 100U);
  196. Add(4, 7U, "180", "220", 100U);
  197. Add(4, 8U, "221", "300", 100U);
  198. Add(5, 26U, "150", "170", 100U);
  199. Add(5, 27U, "171", "179", 100U);
  200. UpdateVersionStorageInfo();
  201. VersionEdit version_edit;
  202. version_edit.AddFile(
  203. 3, 666, 0, 100U, GetInternalKey("301"), GetInternalKey("350"), 200, 200,
  204. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  205. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  206. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  207. 0, /* user_defined_timestamps_persisted */ true);
  208. version_edit.DeleteFile(0, 1U);
  209. version_edit.DeleteFile(0, 88U);
  210. EnvOptions env_options;
  211. constexpr TableCache* table_cache = nullptr;
  212. constexpr VersionSet* version_set = nullptr;
  213. VersionBuilder version_builder(env_options, &ioptions_, table_cache,
  214. &vstorage_, version_set);
  215. VersionStorageInfo new_vstorage(
  216. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr, false,
  217. EpochNumberRequirement::kMightMissing, nullptr, 0,
  218. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  219. ASSERT_OK(version_builder.Apply(&version_edit));
  220. ASSERT_OK(version_builder.SaveTo(&new_vstorage));
  221. UpdateVersionStorageInfo(&new_vstorage);
  222. ASSERT_EQ(0U, new_vstorage.NumLevelBytes(0));
  223. ASSERT_EQ(100U, new_vstorage.NumLevelBytes(3));
  224. ASSERT_EQ(300U, new_vstorage.NumLevelBytes(4));
  225. ASSERT_EQ(200U, new_vstorage.NumLevelBytes(5));
  226. UnrefFilesInVersion(&new_vstorage);
  227. }
  228. TEST_F(VersionBuilderTest, ApplyAndSaveToDynamic2) {
  229. ioptions_.level_compaction_dynamic_level_bytes = true;
  230. Add(0, 1U, "150", "200", 100U, 0, 200U, 200U, 0, 0, false, 200U, 200U,
  231. /*oldest_blob_file_number*/ kInvalidBlobFileNumber,
  232. /*epoch_number*/ 2);
  233. Add(0, 88U, "201", "300", 100U, 0, 100U, 100U, 0, 0, false, 100U, 100U,
  234. /*oldest_blob_file_number*/ kInvalidBlobFileNumber,
  235. /*epoch_number*/ 1);
  236. Add(4, 6U, "150", "179", 100U);
  237. Add(4, 7U, "180", "220", 100U);
  238. Add(4, 8U, "221", "300", 100U);
  239. Add(5, 26U, "150", "170", 100U);
  240. Add(5, 27U, "171", "179", 100U);
  241. UpdateVersionStorageInfo();
  242. VersionEdit version_edit;
  243. version_edit.AddFile(
  244. 4, 666, 0, 100U, GetInternalKey("301"), GetInternalKey("350"), 200, 200,
  245. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  246. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  247. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  248. 0, /* user_defined_timestamps_persisted */ true);
  249. version_edit.DeleteFile(0, 1U);
  250. version_edit.DeleteFile(0, 88U);
  251. version_edit.DeleteFile(4, 6U);
  252. version_edit.DeleteFile(4, 7U);
  253. version_edit.DeleteFile(4, 8U);
  254. EnvOptions env_options;
  255. constexpr TableCache* table_cache = nullptr;
  256. constexpr VersionSet* version_set = nullptr;
  257. VersionBuilder version_builder(env_options, &ioptions_, table_cache,
  258. &vstorage_, version_set);
  259. VersionStorageInfo new_vstorage(
  260. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr, false,
  261. EpochNumberRequirement::kMightMissing, nullptr, 0,
  262. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  263. ASSERT_OK(version_builder.Apply(&version_edit));
  264. ASSERT_OK(version_builder.SaveTo(&new_vstorage));
  265. UpdateVersionStorageInfo(&new_vstorage);
  266. ASSERT_EQ(0U, new_vstorage.NumLevelBytes(0));
  267. ASSERT_EQ(100U, new_vstorage.NumLevelBytes(4));
  268. ASSERT_EQ(200U, new_vstorage.NumLevelBytes(5));
  269. UnrefFilesInVersion(&new_vstorage);
  270. }
  271. TEST_F(VersionBuilderTest, ApplyMultipleAndSaveTo) {
  272. UpdateVersionStorageInfo();
  273. VersionEdit version_edit;
  274. version_edit.AddFile(
  275. 2, 666, 0, 100U, GetInternalKey("301"), GetInternalKey("350"), 200, 200,
  276. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  277. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  278. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  279. 0, /* user_defined_timestamps_persisted */ true);
  280. version_edit.AddFile(
  281. 2, 676, 0, 100U, GetInternalKey("401"), GetInternalKey("450"), 200, 200,
  282. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  283. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  284. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  285. 0, /* user_defined_timestamps_persisted */ true);
  286. version_edit.AddFile(
  287. 2, 636, 0, 100U, GetInternalKey("601"), GetInternalKey("650"), 200, 200,
  288. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  289. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  290. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  291. 0, /* user_defined_timestamps_persisted */ true);
  292. version_edit.AddFile(
  293. 2, 616, 0, 100U, GetInternalKey("501"), GetInternalKey("550"), 200, 200,
  294. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  295. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  296. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  297. 0, /* user_defined_timestamps_persisted */ true);
  298. version_edit.AddFile(
  299. 2, 606, 0, 100U, GetInternalKey("701"), GetInternalKey("750"), 200, 200,
  300. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  301. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  302. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  303. 0, /* user_defined_timestamps_persisted */ true);
  304. EnvOptions env_options;
  305. constexpr TableCache* table_cache = nullptr;
  306. constexpr VersionSet* version_set = nullptr;
  307. VersionBuilder version_builder(env_options, &ioptions_, table_cache,
  308. &vstorage_, version_set);
  309. VersionStorageInfo new_vstorage(
  310. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr, false,
  311. EpochNumberRequirement::kMightMissing, nullptr, 0,
  312. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  313. ASSERT_OK(version_builder.Apply(&version_edit));
  314. ASSERT_OK(version_builder.SaveTo(&new_vstorage));
  315. UpdateVersionStorageInfo(&new_vstorage);
  316. ASSERT_EQ(500U, new_vstorage.NumLevelBytes(2));
  317. UnrefFilesInVersion(&new_vstorage);
  318. }
  319. TEST_F(VersionBuilderTest, ApplyDeleteAndSaveTo) {
  320. UpdateVersionStorageInfo();
  321. EnvOptions env_options;
  322. constexpr TableCache* table_cache = nullptr;
  323. constexpr VersionSet* version_set = nullptr;
  324. VersionBuilder version_builder(env_options, &ioptions_, table_cache,
  325. &vstorage_, version_set);
  326. VersionStorageInfo new_vstorage(
  327. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr, false,
  328. EpochNumberRequirement::kMightMissing, nullptr, 0,
  329. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  330. VersionEdit version_edit;
  331. version_edit.AddFile(
  332. 2, 666, 0, 100U, GetInternalKey("301"), GetInternalKey("350"), 200, 200,
  333. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  334. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  335. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  336. 0, /* user_defined_timestamps_persisted */ true);
  337. version_edit.AddFile(
  338. 2, 676, 0, 100U, GetInternalKey("401"), GetInternalKey("450"), 200, 200,
  339. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  340. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  341. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  342. 0, /* user_defined_timestamps_persisted */ true);
  343. version_edit.AddFile(
  344. 2, 636, 0, 100U, GetInternalKey("601"), GetInternalKey("650"), 200, 200,
  345. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  346. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  347. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  348. 0, /* user_defined_timestamps_persisted */ true);
  349. version_edit.AddFile(
  350. 2, 616, 0, 100U, GetInternalKey("501"), GetInternalKey("550"), 200, 200,
  351. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  352. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  353. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  354. 0, /* user_defined_timestamps_persisted */ true);
  355. version_edit.AddFile(
  356. 2, 606, 0, 100U, GetInternalKey("701"), GetInternalKey("750"), 200, 200,
  357. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  358. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  359. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  360. 0, /* user_defined_timestamps_persisted */ true);
  361. ASSERT_OK(version_builder.Apply(&version_edit));
  362. VersionEdit version_edit2;
  363. version_edit.AddFile(
  364. 2, 808, 0, 100U, GetInternalKey("901"), GetInternalKey("950"), 200, 200,
  365. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  366. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  367. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  368. 0, /* user_defined_timestamps_persisted */ true);
  369. version_edit2.DeleteFile(2, 616);
  370. version_edit2.DeleteFile(2, 636);
  371. version_edit.AddFile(
  372. 2, 806, 0, 100U, GetInternalKey("801"), GetInternalKey("850"), 200, 200,
  373. false, Temperature::kUnknown, kInvalidBlobFileNumber,
  374. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  375. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  376. 0, /* user_defined_timestamps_persisted */ true);
  377. ASSERT_OK(version_builder.Apply(&version_edit2));
  378. ASSERT_OK(version_builder.SaveTo(&new_vstorage));
  379. UpdateVersionStorageInfo(&new_vstorage);
  380. ASSERT_EQ(300U, new_vstorage.NumLevelBytes(2));
  381. UnrefFilesInVersion(&new_vstorage);
  382. }
  383. TEST_F(VersionBuilderTest, ApplyFileDeletionIncorrectLevel) {
  384. constexpr int level = 1;
  385. constexpr uint64_t file_number = 2345;
  386. constexpr char smallest[] = "bar";
  387. constexpr char largest[] = "foo";
  388. constexpr uint64_t file_size = 100;
  389. Add(level, file_number, smallest, largest, file_size);
  390. UpdateVersionStorageInfo();
  391. EnvOptions env_options;
  392. constexpr TableCache* table_cache = nullptr;
  393. constexpr VersionSet* version_set = nullptr;
  394. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  395. version_set);
  396. VersionEdit edit;
  397. constexpr int incorrect_level = 3;
  398. edit.DeleteFile(incorrect_level, file_number);
  399. const Status s = builder.Apply(&edit);
  400. ASSERT_TRUE(s.IsCorruption());
  401. ASSERT_TRUE(std::strstr(s.getState(),
  402. "Cannot delete table file #2345 from level 3 since "
  403. "it is on level 1"));
  404. }
  405. TEST_F(VersionBuilderTest, ApplyFileDeletionNotInLSMTree) {
  406. UpdateVersionStorageInfo();
  407. EnvOptions env_options;
  408. constexpr TableCache* table_cache = nullptr;
  409. constexpr VersionSet* version_set = nullptr;
  410. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  411. version_set);
  412. VersionEdit edit;
  413. constexpr int level = 3;
  414. constexpr uint64_t file_number = 1234;
  415. edit.DeleteFile(level, file_number);
  416. const Status s = builder.Apply(&edit);
  417. ASSERT_TRUE(s.IsCorruption());
  418. ASSERT_TRUE(std::strstr(s.getState(),
  419. "Cannot delete table file #1234 from level 3 since "
  420. "it is not in the LSM tree"));
  421. }
  422. TEST_F(VersionBuilderTest, ApplyFileDeletionAndAddition) {
  423. constexpr int level = 1;
  424. constexpr uint64_t file_number = 2345;
  425. constexpr char smallest[] = "bar";
  426. constexpr char largest[] = "foo";
  427. constexpr uint64_t file_size = 10000;
  428. constexpr uint32_t path_id = 0;
  429. constexpr SequenceNumber smallest_seq = 100;
  430. constexpr SequenceNumber largest_seq = 500;
  431. constexpr uint64_t num_entries = 0;
  432. constexpr uint64_t num_deletions = 0;
  433. constexpr bool sampled = false;
  434. constexpr SequenceNumber smallest_seqno = 1;
  435. constexpr SequenceNumber largest_seqno = 1000;
  436. Add(level, file_number, smallest, largest, file_size, path_id, smallest_seq,
  437. largest_seq, num_entries, num_deletions, sampled, smallest_seqno,
  438. largest_seqno);
  439. UpdateVersionStorageInfo();
  440. EnvOptions env_options;
  441. constexpr TableCache* table_cache = nullptr;
  442. constexpr VersionSet* version_set = nullptr;
  443. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  444. version_set);
  445. VersionEdit deletion;
  446. deletion.DeleteFile(level, file_number);
  447. ASSERT_OK(builder.Apply(&deletion));
  448. VersionEdit addition;
  449. constexpr bool marked_for_compaction = false;
  450. addition.AddFile(
  451. level, file_number, path_id, file_size,
  452. GetInternalKey(smallest, smallest_seq),
  453. GetInternalKey(largest, largest_seq), smallest_seqno, largest_seqno,
  454. marked_for_compaction, Temperature::kUnknown, kInvalidBlobFileNumber,
  455. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  456. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  457. 0, /* user_defined_timestamps_persisted */ true);
  458. ASSERT_OK(builder.Apply(&addition));
  459. constexpr bool force_consistency_checks = false;
  460. VersionStorageInfo new_vstorage(
  461. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  462. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  463. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  464. ASSERT_OK(builder.SaveTo(&new_vstorage));
  465. UpdateVersionStorageInfo(&new_vstorage);
  466. ASSERT_EQ(new_vstorage.GetFileLocation(file_number).GetLevel(), level);
  467. UnrefFilesInVersion(&new_vstorage);
  468. }
  469. TEST_F(VersionBuilderTest, ApplyFileAdditionAlreadyInBase) {
  470. constexpr int level = 1;
  471. constexpr uint64_t file_number = 2345;
  472. constexpr char smallest[] = "bar";
  473. constexpr char largest[] = "foo";
  474. constexpr uint64_t file_size = 10000;
  475. Add(level, file_number, smallest, largest, file_size);
  476. UpdateVersionStorageInfo();
  477. EnvOptions env_options;
  478. constexpr TableCache* table_cache = nullptr;
  479. constexpr VersionSet* version_set = nullptr;
  480. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  481. version_set);
  482. VersionEdit edit;
  483. constexpr int new_level = 2;
  484. constexpr uint32_t path_id = 0;
  485. constexpr SequenceNumber smallest_seqno = 100;
  486. constexpr SequenceNumber largest_seqno = 1000;
  487. constexpr bool marked_for_compaction = false;
  488. edit.AddFile(
  489. new_level, file_number, path_id, file_size, GetInternalKey(smallest),
  490. GetInternalKey(largest), smallest_seqno, largest_seqno,
  491. marked_for_compaction, Temperature::kUnknown, kInvalidBlobFileNumber,
  492. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  493. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  494. 0, /* user_defined_timestamps_persisted */ true);
  495. const Status s = builder.Apply(&edit);
  496. ASSERT_TRUE(s.IsCorruption());
  497. ASSERT_TRUE(std::strstr(s.getState(),
  498. "Cannot add table file #2345 to level 2 since it is "
  499. "already in the LSM tree on level 1"));
  500. }
  501. TEST_F(VersionBuilderTest, ApplyFileAdditionAlreadyApplied) {
  502. UpdateVersionStorageInfo();
  503. EnvOptions env_options;
  504. constexpr TableCache* table_cache = nullptr;
  505. constexpr VersionSet* version_set = nullptr;
  506. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  507. version_set);
  508. VersionEdit edit;
  509. constexpr int level = 3;
  510. constexpr uint64_t file_number = 2345;
  511. constexpr uint32_t path_id = 0;
  512. constexpr uint64_t file_size = 10000;
  513. constexpr char smallest[] = "bar";
  514. constexpr char largest[] = "foo";
  515. constexpr SequenceNumber smallest_seqno = 100;
  516. constexpr SequenceNumber largest_seqno = 1000;
  517. constexpr bool marked_for_compaction = false;
  518. edit.AddFile(
  519. level, file_number, path_id, file_size, GetInternalKey(smallest),
  520. GetInternalKey(largest), smallest_seqno, largest_seqno,
  521. marked_for_compaction, Temperature::kUnknown, kInvalidBlobFileNumber,
  522. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  523. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  524. 0, /* user_defined_timestamps_persisted */ true);
  525. ASSERT_OK(builder.Apply(&edit));
  526. VersionEdit other_edit;
  527. constexpr int new_level = 2;
  528. other_edit.AddFile(
  529. new_level, file_number, path_id, file_size, GetInternalKey(smallest),
  530. GetInternalKey(largest), smallest_seqno, largest_seqno,
  531. marked_for_compaction, Temperature::kUnknown, kInvalidBlobFileNumber,
  532. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  533. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  534. 0, /* user_defined_timestamps_persisted */ true);
  535. const Status s = builder.Apply(&other_edit);
  536. ASSERT_TRUE(s.IsCorruption());
  537. ASSERT_TRUE(std::strstr(s.getState(),
  538. "Cannot add table file #2345 to level 2 since it is "
  539. "already in the LSM tree on level 3"));
  540. }
  541. TEST_F(VersionBuilderTest, ApplyFileAdditionAndDeletion) {
  542. UpdateVersionStorageInfo();
  543. constexpr int level = 1;
  544. constexpr uint64_t file_number = 2345;
  545. constexpr uint32_t path_id = 0;
  546. constexpr uint64_t file_size = 10000;
  547. constexpr char smallest[] = "bar";
  548. constexpr char largest[] = "foo";
  549. constexpr SequenceNumber smallest_seqno = 100;
  550. constexpr SequenceNumber largest_seqno = 1000;
  551. constexpr bool marked_for_compaction = false;
  552. EnvOptions env_options;
  553. constexpr TableCache* table_cache = nullptr;
  554. constexpr VersionSet* version_set = nullptr;
  555. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  556. version_set);
  557. VersionEdit addition;
  558. addition.AddFile(
  559. level, file_number, path_id, file_size, GetInternalKey(smallest),
  560. GetInternalKey(largest), smallest_seqno, largest_seqno,
  561. marked_for_compaction, Temperature::kUnknown, kInvalidBlobFileNumber,
  562. kUnknownOldestAncesterTime, kUnknownFileCreationTime, kUnknownEpochNumber,
  563. kUnknownFileChecksum, kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0,
  564. 0, /* user_defined_timestamps_persisted */ true);
  565. ASSERT_OK(builder.Apply(&addition));
  566. VersionEdit deletion;
  567. deletion.DeleteFile(level, file_number);
  568. ASSERT_OK(builder.Apply(&deletion));
  569. constexpr bool force_consistency_checks = false;
  570. VersionStorageInfo new_vstorage(
  571. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  572. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  573. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  574. ASSERT_OK(builder.SaveTo(&new_vstorage));
  575. UpdateVersionStorageInfo(&new_vstorage);
  576. ASSERT_FALSE(new_vstorage.GetFileLocation(file_number).IsValid());
  577. UnrefFilesInVersion(&new_vstorage);
  578. }
  579. TEST_F(VersionBuilderTest, ApplyBlobFileAddition) {
  580. UpdateVersionStorageInfo();
  581. EnvOptions env_options;
  582. constexpr TableCache* table_cache = nullptr;
  583. constexpr VersionSet* version_set = nullptr;
  584. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  585. version_set);
  586. VersionEdit edit;
  587. constexpr uint64_t blob_file_number = 1234;
  588. constexpr uint64_t total_blob_count = 5678;
  589. constexpr uint64_t total_blob_bytes = 999999;
  590. constexpr char checksum_method[] = "SHA1";
  591. constexpr char checksum_value[] =
  592. "\xbd\xb7\xf3\x4a\x59\xdf\xa1\x59\x2c\xe7\xf5\x2e\x99\xf9\x8c\x57\x0c\x52"
  593. "\x5c\xbd";
  594. edit.AddBlobFile(blob_file_number, total_blob_count, total_blob_bytes,
  595. checksum_method, checksum_value);
  596. // Add dummy table file to ensure the blob file is referenced.
  597. constexpr uint64_t table_file_number = 1;
  598. AddDummyFileToEdit(&edit, table_file_number, blob_file_number,
  599. 1 /*epoch_number*/);
  600. ASSERT_OK(builder.Apply(&edit));
  601. constexpr bool force_consistency_checks = false;
  602. VersionStorageInfo new_vstorage(
  603. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  604. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  605. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  606. ASSERT_OK(builder.SaveTo(&new_vstorage));
  607. UpdateVersionStorageInfo(&new_vstorage);
  608. const auto& new_blob_files = new_vstorage.GetBlobFiles();
  609. ASSERT_EQ(new_blob_files.size(), 1);
  610. const auto new_meta = new_vstorage.GetBlobFileMetaData(blob_file_number);
  611. ASSERT_NE(new_meta, nullptr);
  612. ASSERT_EQ(new_meta->GetBlobFileNumber(), blob_file_number);
  613. ASSERT_EQ(new_meta->GetTotalBlobCount(), total_blob_count);
  614. ASSERT_EQ(new_meta->GetTotalBlobBytes(), total_blob_bytes);
  615. ASSERT_EQ(new_meta->GetChecksumMethod(), checksum_method);
  616. ASSERT_EQ(new_meta->GetChecksumValue(), checksum_value);
  617. ASSERT_EQ(new_meta->GetLinkedSsts(),
  618. BlobFileMetaData::LinkedSsts{table_file_number});
  619. ASSERT_EQ(new_meta->GetGarbageBlobCount(), 0);
  620. ASSERT_EQ(new_meta->GetGarbageBlobBytes(), 0);
  621. UnrefFilesInVersion(&new_vstorage);
  622. }
  623. TEST_F(VersionBuilderTest, ApplyBlobFileAdditionAlreadyInBase) {
  624. // Attempt to add a blob file that is already present in the base version.
  625. constexpr uint64_t blob_file_number = 1234;
  626. constexpr uint64_t total_blob_count = 5678;
  627. constexpr uint64_t total_blob_bytes = 999999;
  628. constexpr char checksum_method[] = "SHA1";
  629. constexpr char checksum_value[] =
  630. "\xbd\xb7\xf3\x4a\x59\xdf\xa1\x59\x2c\xe7\xf5\x2e\x99\xf9\x8c\x57\x0c\x52"
  631. "\x5c\xbd";
  632. constexpr uint64_t garbage_blob_count = 123;
  633. constexpr uint64_t garbage_blob_bytes = 456789;
  634. AddBlob(blob_file_number, total_blob_count, total_blob_bytes, checksum_method,
  635. checksum_value, BlobFileMetaData::LinkedSsts(), garbage_blob_count,
  636. garbage_blob_bytes);
  637. UpdateVersionStorageInfo();
  638. EnvOptions env_options;
  639. constexpr TableCache* table_cache = nullptr;
  640. constexpr VersionSet* version_set = nullptr;
  641. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  642. version_set);
  643. VersionEdit edit;
  644. edit.AddBlobFile(blob_file_number, total_blob_count, total_blob_bytes,
  645. checksum_method, checksum_value);
  646. const Status s = builder.Apply(&edit);
  647. ASSERT_TRUE(s.IsCorruption());
  648. ASSERT_TRUE(std::strstr(s.getState(), "Blob file #1234 already added"));
  649. }
  650. TEST_F(VersionBuilderTest, ApplyBlobFileAdditionAlreadyApplied) {
  651. // Attempt to add the same blob file twice using version edits.
  652. UpdateVersionStorageInfo();
  653. EnvOptions env_options;
  654. constexpr TableCache* table_cache = nullptr;
  655. constexpr VersionSet* version_set = nullptr;
  656. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  657. version_set);
  658. VersionEdit edit;
  659. constexpr uint64_t blob_file_number = 1234;
  660. constexpr uint64_t total_blob_count = 5678;
  661. constexpr uint64_t total_blob_bytes = 999999;
  662. constexpr char checksum_method[] = "SHA1";
  663. constexpr char checksum_value[] =
  664. "\xbd\xb7\xf3\x4a\x59\xdf\xa1\x59\x2c\xe7\xf5\x2e\x99\xf9\x8c\x57\x0c\x52"
  665. "\x5c\xbd";
  666. edit.AddBlobFile(blob_file_number, total_blob_count, total_blob_bytes,
  667. checksum_method, checksum_value);
  668. ASSERT_OK(builder.Apply(&edit));
  669. const Status s = builder.Apply(&edit);
  670. ASSERT_TRUE(s.IsCorruption());
  671. ASSERT_TRUE(std::strstr(s.getState(), "Blob file #1234 already added"));
  672. }
  673. TEST_F(VersionBuilderTest, ApplyBlobFileGarbageFileInBase) {
  674. // Increase the amount of garbage for a blob file present in the base version.
  675. constexpr uint64_t table_file_number = 1;
  676. constexpr uint64_t blob_file_number = 1234;
  677. constexpr uint64_t total_blob_count = 5678;
  678. constexpr uint64_t total_blob_bytes = 999999;
  679. constexpr char checksum_method[] = "SHA1";
  680. constexpr char checksum_value[] =
  681. "\xbd\xb7\xf3\x4a\x59\xdf\xa1\x59\x2c\xe7\xf5\x2e\x99\xf9\x8c\x57\x0c\x52"
  682. "\x5c\xbd";
  683. constexpr uint64_t garbage_blob_count = 123;
  684. constexpr uint64_t garbage_blob_bytes = 456789;
  685. AddBlob(blob_file_number, total_blob_count, total_blob_bytes, checksum_method,
  686. checksum_value, BlobFileMetaData::LinkedSsts{table_file_number},
  687. garbage_blob_count, garbage_blob_bytes);
  688. const auto meta = vstorage_.GetBlobFileMetaData(blob_file_number);
  689. ASSERT_NE(meta, nullptr);
  690. // Add dummy table file to ensure the blob file is referenced.
  691. AddDummyFile(table_file_number, blob_file_number, 1 /*epoch_number*/);
  692. UpdateVersionStorageInfo();
  693. EnvOptions env_options;
  694. constexpr TableCache* table_cache = nullptr;
  695. constexpr VersionSet* version_set = nullptr;
  696. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  697. version_set);
  698. VersionEdit edit;
  699. constexpr uint64_t new_garbage_blob_count = 456;
  700. constexpr uint64_t new_garbage_blob_bytes = 111111;
  701. edit.AddBlobFileGarbage(blob_file_number, new_garbage_blob_count,
  702. new_garbage_blob_bytes);
  703. ASSERT_OK(builder.Apply(&edit));
  704. constexpr bool force_consistency_checks = false;
  705. VersionStorageInfo new_vstorage(
  706. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  707. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  708. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  709. ASSERT_OK(builder.SaveTo(&new_vstorage));
  710. UpdateVersionStorageInfo(&new_vstorage);
  711. const auto& new_blob_files = new_vstorage.GetBlobFiles();
  712. ASSERT_EQ(new_blob_files.size(), 1);
  713. const auto new_meta = new_vstorage.GetBlobFileMetaData(blob_file_number);
  714. ASSERT_NE(new_meta, nullptr);
  715. ASSERT_EQ(new_meta->GetSharedMeta(), meta->GetSharedMeta());
  716. ASSERT_EQ(new_meta->GetBlobFileNumber(), blob_file_number);
  717. ASSERT_EQ(new_meta->GetTotalBlobCount(), total_blob_count);
  718. ASSERT_EQ(new_meta->GetTotalBlobBytes(), total_blob_bytes);
  719. ASSERT_EQ(new_meta->GetChecksumMethod(), checksum_method);
  720. ASSERT_EQ(new_meta->GetChecksumValue(), checksum_value);
  721. ASSERT_EQ(new_meta->GetLinkedSsts(),
  722. BlobFileMetaData::LinkedSsts{table_file_number});
  723. ASSERT_EQ(new_meta->GetGarbageBlobCount(),
  724. garbage_blob_count + new_garbage_blob_count);
  725. ASSERT_EQ(new_meta->GetGarbageBlobBytes(),
  726. garbage_blob_bytes + new_garbage_blob_bytes);
  727. UnrefFilesInVersion(&new_vstorage);
  728. }
  729. TEST_F(VersionBuilderTest, ApplyBlobFileGarbageFileAdditionApplied) {
  730. // Increase the amount of garbage for a blob file added using a version edit.
  731. UpdateVersionStorageInfo();
  732. EnvOptions env_options;
  733. constexpr TableCache* table_cache = nullptr;
  734. constexpr VersionSet* version_set = nullptr;
  735. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  736. version_set);
  737. VersionEdit addition;
  738. constexpr uint64_t blob_file_number = 1234;
  739. constexpr uint64_t total_blob_count = 5678;
  740. constexpr uint64_t total_blob_bytes = 999999;
  741. constexpr char checksum_method[] = "SHA1";
  742. constexpr char checksum_value[] =
  743. "\xbd\xb7\xf3\x4a\x59\xdf\xa1\x59\x2c\xe7\xf5\x2e\x99\xf9\x8c\x57\x0c\x52"
  744. "\x5c\xbd";
  745. addition.AddBlobFile(blob_file_number, total_blob_count, total_blob_bytes,
  746. checksum_method, checksum_value);
  747. // Add dummy table file to ensure the blob file is referenced.
  748. constexpr uint64_t table_file_number = 1;
  749. AddDummyFileToEdit(&addition, table_file_number, blob_file_number,
  750. 1 /*epoch_number*/);
  751. ASSERT_OK(builder.Apply(&addition));
  752. constexpr uint64_t garbage_blob_count = 123;
  753. constexpr uint64_t garbage_blob_bytes = 456789;
  754. VersionEdit garbage;
  755. garbage.AddBlobFileGarbage(blob_file_number, garbage_blob_count,
  756. garbage_blob_bytes);
  757. ASSERT_OK(builder.Apply(&garbage));
  758. constexpr bool force_consistency_checks = false;
  759. VersionStorageInfo new_vstorage(
  760. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  761. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  762. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  763. ASSERT_OK(builder.SaveTo(&new_vstorage));
  764. UpdateVersionStorageInfo(&new_vstorage);
  765. const auto& new_blob_files = new_vstorage.GetBlobFiles();
  766. ASSERT_EQ(new_blob_files.size(), 1);
  767. const auto new_meta = new_vstorage.GetBlobFileMetaData(blob_file_number);
  768. ASSERT_NE(new_meta, nullptr);
  769. ASSERT_EQ(new_meta->GetBlobFileNumber(), blob_file_number);
  770. ASSERT_EQ(new_meta->GetTotalBlobCount(), total_blob_count);
  771. ASSERT_EQ(new_meta->GetTotalBlobBytes(), total_blob_bytes);
  772. ASSERT_EQ(new_meta->GetChecksumMethod(), checksum_method);
  773. ASSERT_EQ(new_meta->GetChecksumValue(), checksum_value);
  774. ASSERT_EQ(new_meta->GetLinkedSsts(),
  775. BlobFileMetaData::LinkedSsts{table_file_number});
  776. ASSERT_EQ(new_meta->GetGarbageBlobCount(), garbage_blob_count);
  777. ASSERT_EQ(new_meta->GetGarbageBlobBytes(), garbage_blob_bytes);
  778. UnrefFilesInVersion(&new_vstorage);
  779. }
  780. TEST_F(VersionBuilderTest, ApplyBlobFileGarbageFileNotFound) {
  781. // Attempt to increase the amount of garbage for a blob file that is
  782. // neither in the base version, nor was it added using a version edit.
  783. UpdateVersionStorageInfo();
  784. EnvOptions env_options;
  785. constexpr TableCache* table_cache = nullptr;
  786. constexpr VersionSet* version_set = nullptr;
  787. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  788. version_set);
  789. VersionEdit edit;
  790. constexpr uint64_t blob_file_number = 1234;
  791. constexpr uint64_t garbage_blob_count = 5678;
  792. constexpr uint64_t garbage_blob_bytes = 999999;
  793. edit.AddBlobFileGarbage(blob_file_number, garbage_blob_count,
  794. garbage_blob_bytes);
  795. const Status s = builder.Apply(&edit);
  796. ASSERT_TRUE(s.IsCorruption());
  797. ASSERT_TRUE(std::strstr(s.getState(), "Blob file #1234 not found"));
  798. }
  799. TEST_F(VersionBuilderTest, BlobFileGarbageOverflow) {
  800. // Test that VersionEdits that would result in the count/total size of garbage
  801. // exceeding the count/total size of all blobs are rejected.
  802. UpdateVersionStorageInfo();
  803. EnvOptions env_options;
  804. constexpr TableCache* table_cache = nullptr;
  805. constexpr VersionSet* version_set = nullptr;
  806. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  807. version_set);
  808. VersionEdit addition;
  809. constexpr uint64_t blob_file_number = 1234;
  810. constexpr uint64_t total_blob_count = 5678;
  811. constexpr uint64_t total_blob_bytes = 999999;
  812. constexpr char checksum_method[] = "SHA1";
  813. constexpr char checksum_value[] =
  814. "\xbd\xb7\xf3\x4a\x59\xdf\xa1\x59\x2c\xe7\xf5\x2e\x99\xf9\x8c\x57\x0c\x52"
  815. "\x5c\xbd";
  816. addition.AddBlobFile(blob_file_number, total_blob_count, total_blob_bytes,
  817. checksum_method, checksum_value);
  818. // Add dummy table file to ensure the blob file is referenced.
  819. constexpr uint64_t table_file_number = 1;
  820. AddDummyFileToEdit(&addition, table_file_number, blob_file_number,
  821. 1 /*epoch_number*/);
  822. ASSERT_OK(builder.Apply(&addition));
  823. {
  824. // Garbage blob count overflow
  825. constexpr uint64_t garbage_blob_count = 5679;
  826. constexpr uint64_t garbage_blob_bytes = 999999;
  827. VersionEdit garbage;
  828. garbage.AddBlobFileGarbage(blob_file_number, garbage_blob_count,
  829. garbage_blob_bytes);
  830. const Status s = builder.Apply(&garbage);
  831. ASSERT_TRUE(s.IsCorruption());
  832. ASSERT_TRUE(
  833. std::strstr(s.getState(), "Garbage overflow for blob file #1234"));
  834. }
  835. {
  836. // Garbage blob bytes overflow
  837. constexpr uint64_t garbage_blob_count = 5678;
  838. constexpr uint64_t garbage_blob_bytes = 1000000;
  839. VersionEdit garbage;
  840. garbage.AddBlobFileGarbage(blob_file_number, garbage_blob_count,
  841. garbage_blob_bytes);
  842. const Status s = builder.Apply(&garbage);
  843. ASSERT_TRUE(s.IsCorruption());
  844. ASSERT_TRUE(
  845. std::strstr(s.getState(), "Garbage overflow for blob file #1234"));
  846. }
  847. }
  848. TEST_F(VersionBuilderTest, SaveBlobFilesTo) {
  849. // Add three blob files to base version.
  850. for (uint64_t i = 1; i <= 3; ++i) {
  851. const uint64_t table_file_number = 2 * i;
  852. const uint64_t blob_file_number = 2 * i + 1;
  853. const uint64_t total_blob_count = i * 1000;
  854. const uint64_t total_blob_bytes = i * 1000000;
  855. const uint64_t garbage_blob_count = i * 100;
  856. const uint64_t garbage_blob_bytes = i * 20000;
  857. AddBlob(blob_file_number, total_blob_count, total_blob_bytes,
  858. /* checksum_method */ std::string(),
  859. /* checksum_value */ std::string(),
  860. BlobFileMetaData::LinkedSsts{table_file_number}, garbage_blob_count,
  861. garbage_blob_bytes);
  862. }
  863. // Add dummy table files to ensure the blob files are referenced.
  864. // Note: files are added to L0, so they have to be added in reverse order
  865. // (newest first).
  866. for (uint64_t i = 3; i >= 1; --i) {
  867. const uint64_t table_file_number = 2 * i;
  868. const uint64_t blob_file_number = 2 * i + 1;
  869. AddDummyFile(table_file_number, blob_file_number, i /*epoch_number*/);
  870. }
  871. UpdateVersionStorageInfo();
  872. EnvOptions env_options;
  873. constexpr TableCache* table_cache = nullptr;
  874. constexpr VersionSet* version_set = nullptr;
  875. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  876. version_set);
  877. VersionEdit edit;
  878. // Add some garbage to the second and third blob files. The second blob file
  879. // remains valid since it does not consist entirely of garbage yet. The third
  880. // blob file is all garbage after the edit and will not be part of the new
  881. // version. The corresponding dummy table file is also removed for
  882. // consistency.
  883. edit.AddBlobFileGarbage(/* blob_file_number */ 5,
  884. /* garbage_blob_count */ 200,
  885. /* garbage_blob_bytes */ 100000);
  886. edit.AddBlobFileGarbage(/* blob_file_number */ 7,
  887. /* garbage_blob_count */ 2700,
  888. /* garbage_blob_bytes */ 2940000);
  889. edit.DeleteFile(/* level */ 0, /* file_number */ 6);
  890. // Add a fourth blob file.
  891. edit.AddBlobFile(/* blob_file_number */ 9, /* total_blob_count */ 4000,
  892. /* total_blob_bytes */ 4000000,
  893. /* checksum_method */ std::string(),
  894. /* checksum_value */ std::string());
  895. ASSERT_OK(builder.Apply(&edit));
  896. constexpr bool force_consistency_checks = false;
  897. VersionStorageInfo new_vstorage(
  898. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  899. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  900. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  901. ASSERT_OK(builder.SaveTo(&new_vstorage));
  902. UpdateVersionStorageInfo(&new_vstorage);
  903. const auto& new_blob_files = new_vstorage.GetBlobFiles();
  904. ASSERT_EQ(new_blob_files.size(), 3);
  905. const auto meta3 = new_vstorage.GetBlobFileMetaData(/* blob_file_number */ 3);
  906. ASSERT_NE(meta3, nullptr);
  907. ASSERT_EQ(meta3->GetBlobFileNumber(), 3);
  908. ASSERT_EQ(meta3->GetTotalBlobCount(), 1000);
  909. ASSERT_EQ(meta3->GetTotalBlobBytes(), 1000000);
  910. ASSERT_EQ(meta3->GetGarbageBlobCount(), 100);
  911. ASSERT_EQ(meta3->GetGarbageBlobBytes(), 20000);
  912. const auto meta5 = new_vstorage.GetBlobFileMetaData(/* blob_file_number */ 5);
  913. ASSERT_NE(meta5, nullptr);
  914. ASSERT_EQ(meta5->GetBlobFileNumber(), 5);
  915. ASSERT_EQ(meta5->GetTotalBlobCount(), 2000);
  916. ASSERT_EQ(meta5->GetTotalBlobBytes(), 2000000);
  917. ASSERT_EQ(meta5->GetGarbageBlobCount(), 400);
  918. ASSERT_EQ(meta5->GetGarbageBlobBytes(), 140000);
  919. const auto meta9 = new_vstorage.GetBlobFileMetaData(/* blob_file_number */ 9);
  920. ASSERT_NE(meta9, nullptr);
  921. ASSERT_EQ(meta9->GetBlobFileNumber(), 9);
  922. ASSERT_EQ(meta9->GetTotalBlobCount(), 4000);
  923. ASSERT_EQ(meta9->GetTotalBlobBytes(), 4000000);
  924. ASSERT_EQ(meta9->GetGarbageBlobCount(), 0);
  925. ASSERT_EQ(meta9->GetGarbageBlobBytes(), 0);
  926. // Delete the first table file, which makes the first blob file obsolete
  927. // since it's at the head and unreferenced.
  928. VersionBuilder second_builder(env_options, &ioptions_, table_cache,
  929. &new_vstorage, version_set);
  930. VersionEdit second_edit;
  931. second_edit.DeleteFile(/* level */ 0, /* file_number */ 2);
  932. ASSERT_OK(second_builder.Apply(&second_edit));
  933. VersionStorageInfo new_vstorage_2(
  934. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &new_vstorage,
  935. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  936. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  937. ASSERT_OK(second_builder.SaveTo(&new_vstorage_2));
  938. UpdateVersionStorageInfo(&new_vstorage_2);
  939. const auto& newer_blob_files = new_vstorage_2.GetBlobFiles();
  940. ASSERT_EQ(newer_blob_files.size(), 2);
  941. const auto newer_meta3 =
  942. new_vstorage_2.GetBlobFileMetaData(/* blob_file_number */ 3);
  943. ASSERT_EQ(newer_meta3, nullptr);
  944. // Blob file #5 is referenced by table file #4, and blob file #9 is
  945. // unreferenced. After deleting table file #4, all blob files will become
  946. // unreferenced and will therefore be obsolete.
  947. VersionBuilder third_builder(env_options, &ioptions_, table_cache,
  948. &new_vstorage_2, version_set);
  949. VersionEdit third_edit;
  950. third_edit.DeleteFile(/* level */ 0, /* file_number */ 4);
  951. ASSERT_OK(third_builder.Apply(&third_edit));
  952. VersionStorageInfo new_vstorage_3(
  953. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel,
  954. &new_vstorage_2, force_consistency_checks,
  955. EpochNumberRequirement::kMightMissing, nullptr, 0,
  956. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  957. ASSERT_OK(third_builder.SaveTo(&new_vstorage_3));
  958. UpdateVersionStorageInfo(&new_vstorage_3);
  959. ASSERT_TRUE(new_vstorage_3.GetBlobFiles().empty());
  960. UnrefFilesInVersion(&new_vstorage_3);
  961. UnrefFilesInVersion(&new_vstorage_2);
  962. UnrefFilesInVersion(&new_vstorage);
  963. }
  964. TEST_F(VersionBuilderTest, SaveBlobFilesToConcurrentJobs) {
  965. // When multiple background jobs (flushes/compactions) are executing in
  966. // parallel, it is possible for the VersionEdit adding blob file K to be
  967. // applied *after* the VersionEdit adding blob file N (for N > K). This test
  968. // case makes sure this is handled correctly.
  969. // Add blob file #4 (referenced by table file #3) to base version.
  970. constexpr uint64_t base_table_file_number = 3;
  971. constexpr uint64_t base_blob_file_number = 4;
  972. constexpr uint64_t base_total_blob_count = 100;
  973. constexpr uint64_t base_total_blob_bytes = 1 << 20;
  974. constexpr char checksum_method[] = "SHA1";
  975. constexpr char checksum_value[] = "\xfa\xce\xb0\x0c";
  976. constexpr uint64_t garbage_blob_count = 0;
  977. constexpr uint64_t garbage_blob_bytes = 0;
  978. AddDummyFile(base_table_file_number, base_blob_file_number,
  979. 1 /*epoch_number*/);
  980. AddBlob(base_blob_file_number, base_total_blob_count, base_total_blob_bytes,
  981. checksum_method, checksum_value,
  982. BlobFileMetaData::LinkedSsts{base_table_file_number},
  983. garbage_blob_count, garbage_blob_bytes);
  984. UpdateVersionStorageInfo();
  985. EnvOptions env_options;
  986. constexpr TableCache* table_cache = nullptr;
  987. constexpr VersionSet* version_set = nullptr;
  988. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  989. version_set);
  990. VersionEdit edit;
  991. // Add blob file #2 (referenced by table file #1).
  992. constexpr int level = 0;
  993. constexpr uint64_t table_file_number = 1;
  994. constexpr uint32_t path_id = 0;
  995. constexpr uint64_t file_size = 1 << 12;
  996. constexpr char smallest[] = "key1";
  997. constexpr char largest[] = "key987";
  998. constexpr SequenceNumber smallest_seqno = 0;
  999. constexpr SequenceNumber largest_seqno = 0;
  1000. constexpr bool marked_for_compaction = false;
  1001. constexpr uint64_t blob_file_number = 2;
  1002. static_assert(blob_file_number < base_blob_file_number,
  1003. "Added blob file should have a smaller file number");
  1004. constexpr uint64_t total_blob_count = 234;
  1005. constexpr uint64_t total_blob_bytes = 1 << 22;
  1006. edit.AddFile(
  1007. level, table_file_number, path_id, file_size, GetInternalKey(smallest),
  1008. GetInternalKey(largest), smallest_seqno, largest_seqno,
  1009. marked_for_compaction, Temperature::kUnknown, blob_file_number,
  1010. kUnknownOldestAncesterTime, kUnknownFileCreationTime, 2 /*epoch_number*/,
  1011. checksum_value, checksum_method, kNullUniqueId64x2, 0, 0,
  1012. /* user_defined_timestamps_persisted */ true);
  1013. edit.AddBlobFile(blob_file_number, total_blob_count, total_blob_bytes,
  1014. checksum_method, checksum_value);
  1015. ASSERT_OK(builder.Apply(&edit));
  1016. constexpr bool force_consistency_checks = true;
  1017. VersionStorageInfo new_vstorage(
  1018. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  1019. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  1020. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1021. ASSERT_OK(builder.SaveTo(&new_vstorage));
  1022. UpdateVersionStorageInfo(&new_vstorage);
  1023. const auto& new_blob_files = new_vstorage.GetBlobFiles();
  1024. ASSERT_EQ(new_blob_files.size(), 2);
  1025. const auto base_meta =
  1026. new_vstorage.GetBlobFileMetaData(base_blob_file_number);
  1027. ASSERT_NE(base_meta, nullptr);
  1028. ASSERT_EQ(base_meta->GetBlobFileNumber(), base_blob_file_number);
  1029. ASSERT_EQ(base_meta->GetTotalBlobCount(), base_total_blob_count);
  1030. ASSERT_EQ(base_meta->GetTotalBlobBytes(), base_total_blob_bytes);
  1031. ASSERT_EQ(base_meta->GetGarbageBlobCount(), garbage_blob_count);
  1032. ASSERT_EQ(base_meta->GetGarbageBlobBytes(), garbage_blob_bytes);
  1033. ASSERT_EQ(base_meta->GetChecksumMethod(), checksum_method);
  1034. ASSERT_EQ(base_meta->GetChecksumValue(), checksum_value);
  1035. const auto added_meta = new_vstorage.GetBlobFileMetaData(blob_file_number);
  1036. ASSERT_NE(added_meta, nullptr);
  1037. ASSERT_EQ(added_meta->GetBlobFileNumber(), blob_file_number);
  1038. ASSERT_EQ(added_meta->GetTotalBlobCount(), total_blob_count);
  1039. ASSERT_EQ(added_meta->GetTotalBlobBytes(), total_blob_bytes);
  1040. ASSERT_EQ(added_meta->GetGarbageBlobCount(), garbage_blob_count);
  1041. ASSERT_EQ(added_meta->GetGarbageBlobBytes(), garbage_blob_bytes);
  1042. ASSERT_EQ(added_meta->GetChecksumMethod(), checksum_method);
  1043. ASSERT_EQ(added_meta->GetChecksumValue(), checksum_value);
  1044. UnrefFilesInVersion(&new_vstorage);
  1045. }
  1046. TEST_F(VersionBuilderTest, CheckConsistencyForBlobFiles) {
  1047. // Initialize base version. The first table file points to a valid blob file
  1048. // in this version; the second one does not refer to any blob files.
  1049. Add(/* level */ 1, /* file_number */ 1, /* smallest */ "150",
  1050. /* largest */ "200", /* file_size */ 100,
  1051. /* path_id */ 0, /* smallest_seq */ 100, /* largest_seq */ 100,
  1052. /* num_entries */ 0, /* num_deletions */ 0,
  1053. /* sampled */ false, /* smallest_seqno */ 100, /* largest_seqno */ 100,
  1054. /* oldest_blob_file_number */ 16);
  1055. Add(/* level */ 1, /* file_number */ 23, /* smallest */ "201",
  1056. /* largest */ "300", /* file_size */ 100,
  1057. /* path_id */ 0, /* smallest_seq */ 200, /* largest_seq */ 200,
  1058. /* num_entries */ 0, /* num_deletions */ 0,
  1059. /* sampled */ false, /* smallest_seqno */ 200, /* largest_seqno */ 200,
  1060. kInvalidBlobFileNumber);
  1061. AddBlob(/* blob_file_number */ 16, /* total_blob_count */ 1000,
  1062. /* total_blob_bytes */ 1000000,
  1063. /* checksum_method */ std::string(),
  1064. /* checksum_value */ std::string(), BlobFileMetaData::LinkedSsts{1},
  1065. /* garbage_blob_count */ 500, /* garbage_blob_bytes */ 300000);
  1066. UpdateVersionStorageInfo();
  1067. // Add a new table file that points to the existing blob file, and add a
  1068. // new table file--blob file pair.
  1069. EnvOptions env_options;
  1070. constexpr TableCache* table_cache = nullptr;
  1071. constexpr VersionSet* version_set = nullptr;
  1072. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  1073. version_set);
  1074. VersionEdit edit;
  1075. edit.AddFile(/* level */ 1, /* file_number */ 606, /* path_id */ 0,
  1076. /* file_size */ 100, /* smallest */ GetInternalKey("701"),
  1077. /* largest */ GetInternalKey("750"), /* smallest_seqno */ 200,
  1078. /* largest_seqno */ 200, /* marked_for_compaction */ false,
  1079. Temperature::kUnknown,
  1080. /* oldest_blob_file_number */ 16, kUnknownOldestAncesterTime,
  1081. kUnknownFileCreationTime, kUnknownEpochNumber,
  1082. kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1083. kNullUniqueId64x2, 0, 0,
  1084. /* user_defined_timestamps_persisted */ true);
  1085. edit.AddFile(/* level */ 1, /* file_number */ 700, /* path_id */ 0,
  1086. /* file_size */ 100, /* smallest */ GetInternalKey("801"),
  1087. /* largest */ GetInternalKey("850"), /* smallest_seqno */ 200,
  1088. /* largest_seqno */ 200, /* marked_for_compaction */ false,
  1089. Temperature::kUnknown,
  1090. /* oldest_blob_file_number */ 1000, kUnknownOldestAncesterTime,
  1091. kUnknownFileCreationTime, kUnknownEpochNumber,
  1092. kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1093. kNullUniqueId64x2, 0, 0,
  1094. /* user_defined_timestamps_persisted */ true);
  1095. edit.AddBlobFile(/* blob_file_number */ 1000, /* total_blob_count */ 2000,
  1096. /* total_blob_bytes */ 200000,
  1097. /* checksum_method */ std::string(),
  1098. /* checksum_value */ std::string());
  1099. ASSERT_OK(builder.Apply(&edit));
  1100. // Save to a new version in order to trigger consistency checks.
  1101. constexpr bool force_consistency_checks = true;
  1102. VersionStorageInfo new_vstorage(
  1103. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  1104. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  1105. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1106. ASSERT_OK(builder.SaveTo(&new_vstorage));
  1107. UpdateVersionStorageInfo(&new_vstorage);
  1108. UnrefFilesInVersion(&new_vstorage);
  1109. }
  1110. TEST_F(VersionBuilderTest, CheckConsistencyForBlobFilesInconsistentLinks) {
  1111. // Initialize base version. Links between the table file and the blob file
  1112. // are inconsistent.
  1113. Add(/* level */ 1, /* file_number */ 1, /* smallest */ "150",
  1114. /* largest */ "200", /* file_size */ 100,
  1115. /* path_id */ 0, /* smallest_seq */ 100, /* largest_seq */ 100,
  1116. /* num_entries */ 0, /* num_deletions */ 0,
  1117. /* sampled */ false, /* smallest_seqno */ 100, /* largest_seqno */ 100,
  1118. /* oldest_blob_file_number */ 256);
  1119. AddBlob(/* blob_file_number */ 16, /* total_blob_count */ 1000,
  1120. /* total_blob_bytes */ 1000000,
  1121. /* checksum_method */ std::string(),
  1122. /* checksum_value */ std::string(), BlobFileMetaData::LinkedSsts{1},
  1123. /* garbage_blob_count */ 500, /* garbage_blob_bytes */ 300000);
  1124. UpdateVersionStorageInfo();
  1125. EnvOptions env_options;
  1126. constexpr TableCache* table_cache = nullptr;
  1127. constexpr VersionSet* version_set = nullptr;
  1128. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  1129. version_set);
  1130. // Save to a new version in order to trigger consistency checks.
  1131. constexpr bool force_consistency_checks = true;
  1132. VersionStorageInfo new_vstorage(
  1133. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  1134. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  1135. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1136. const Status s = builder.SaveTo(&new_vstorage);
  1137. ASSERT_TRUE(s.IsCorruption());
  1138. ASSERT_TRUE(std::strstr(
  1139. s.getState(),
  1140. "Links are inconsistent between table files and blob file #16"));
  1141. UnrefFilesInVersion(&new_vstorage);
  1142. }
  1143. TEST_F(VersionBuilderTest, CheckConsistencyForBlobFilesAllGarbage) {
  1144. // Initialize base version. The table file points to a blob file that is
  1145. // all garbage.
  1146. Add(/* level */ 1, /* file_number */ 1, /* smallest */ "150",
  1147. /* largest */ "200", /* file_size */ 100,
  1148. /* path_id */ 0, /* smallest_seq */ 100, /* largest_seq */ 100,
  1149. /* num_entries */ 0, /* num_deletions */ 0,
  1150. /* sampled */ false, /* smallest_seqno */ 100, /* largest_seqno */ 100,
  1151. /* oldest_blob_file_number */ 16);
  1152. AddBlob(/* blob_file_number */ 16, /* total_blob_count */ 1000,
  1153. /* total_blob_bytes */ 1000000,
  1154. /* checksum_method */ std::string(),
  1155. /* checksum_value */ std::string(), BlobFileMetaData::LinkedSsts{1},
  1156. /* garbage_blob_count */ 1000, /* garbage_blob_bytes */ 1000000);
  1157. UpdateVersionStorageInfo();
  1158. EnvOptions env_options;
  1159. constexpr TableCache* table_cache = nullptr;
  1160. constexpr VersionSet* version_set = nullptr;
  1161. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  1162. version_set);
  1163. // Save to a new version in order to trigger consistency checks.
  1164. constexpr bool force_consistency_checks = true;
  1165. VersionStorageInfo new_vstorage(
  1166. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  1167. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  1168. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1169. const Status s = builder.SaveTo(&new_vstorage);
  1170. ASSERT_TRUE(s.IsCorruption());
  1171. ASSERT_TRUE(
  1172. std::strstr(s.getState(), "Blob file #16 consists entirely of garbage"));
  1173. UnrefFilesInVersion(&new_vstorage);
  1174. }
  1175. TEST_F(VersionBuilderTest, CheckConsistencyForBlobFilesAllGarbageLinkedSsts) {
  1176. // Initialize base version, with a table file pointing to a blob file
  1177. // that has no garbage at this point.
  1178. Add(/* level */ 1, /* file_number */ 1, /* smallest */ "150",
  1179. /* largest */ "200", /* file_size */ 100,
  1180. /* path_id */ 0, /* smallest_seq */ 100, /* largest_seq */ 100,
  1181. /* num_entries */ 0, /* num_deletions */ 0,
  1182. /* sampled */ false, /* smallest_seqno */ 100, /* largest_seqno */ 100,
  1183. /* oldest_blob_file_number */ 16);
  1184. AddBlob(/* blob_file_number */ 16, /* total_blob_count */ 1000,
  1185. /* total_blob_bytes */ 1000000,
  1186. /* checksum_method */ std::string(),
  1187. /* checksum_value */ std::string(), BlobFileMetaData::LinkedSsts{1},
  1188. /* garbage_blob_count */ 0, /* garbage_blob_bytes */ 0);
  1189. UpdateVersionStorageInfo();
  1190. // Mark the entire blob file garbage but do not remove the linked SST.
  1191. EnvOptions env_options;
  1192. constexpr TableCache* table_cache = nullptr;
  1193. constexpr VersionSet* version_set = nullptr;
  1194. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  1195. version_set);
  1196. VersionEdit edit;
  1197. edit.AddBlobFileGarbage(/* blob_file_number */ 16,
  1198. /* garbage_blob_count */ 1000,
  1199. /* garbage_blob_bytes */ 1000000);
  1200. ASSERT_OK(builder.Apply(&edit));
  1201. // Save to a new version in order to trigger consistency checks.
  1202. constexpr bool force_consistency_checks = true;
  1203. VersionStorageInfo new_vstorage(
  1204. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  1205. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  1206. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1207. const Status s = builder.SaveTo(&new_vstorage);
  1208. ASSERT_TRUE(s.IsCorruption());
  1209. ASSERT_TRUE(
  1210. std::strstr(s.getState(), "Blob file #16 consists entirely of garbage"));
  1211. UnrefFilesInVersion(&new_vstorage);
  1212. }
  1213. TEST_F(VersionBuilderTest, MaintainLinkedSstsForBlobFiles) {
  1214. // Initialize base version. Table files 1..10 are linked to blob files 1..5,
  1215. // while table files 11..20 are not linked to any blob files.
  1216. for (uint64_t i = 1; i <= 10; ++i) {
  1217. std::ostringstream oss;
  1218. oss << std::setw(2) << std::setfill('0') << i;
  1219. const std::string key = oss.str();
  1220. Add(/* level */ 1, /* file_number */ i, /* smallest */ key.c_str(),
  1221. /* largest */ key.c_str(), /* file_size */ 100,
  1222. /* path_id */ 0, /* smallest_seq */ i * 100, /* largest_seq */ i * 100,
  1223. /* num_entries */ 0, /* num_deletions */ 0,
  1224. /* sampled */ false, /* smallest_seqno */ i * 100,
  1225. /* largest_seqno */ i * 100,
  1226. /* oldest_blob_file_number */ ((i - 1) % 5) + 1);
  1227. }
  1228. for (uint64_t i = 1; i <= 5; ++i) {
  1229. AddBlob(/* blob_file_number */ i, /* total_blob_count */ 2000,
  1230. /* total_blob_bytes */ 2000000,
  1231. /* checksum_method */ std::string(),
  1232. /* checksum_value */ std::string(),
  1233. BlobFileMetaData::LinkedSsts{i, i + 5},
  1234. /* garbage_blob_count */ 1000, /* garbage_blob_bytes */ 1000000);
  1235. }
  1236. for (uint64_t i = 11; i <= 20; ++i) {
  1237. std::ostringstream oss;
  1238. oss << std::setw(2) << std::setfill('0') << i;
  1239. const std::string key = oss.str();
  1240. Add(/* level */ 1, /* file_number */ i, /* smallest */ key.c_str(),
  1241. /* largest */ key.c_str(), /* file_size */ 100,
  1242. /* path_id */ 0, /* smallest_seq */ i * 100, /* largest_seq */ i * 100,
  1243. /* num_entries */ 0, /* num_deletions */ 0,
  1244. /* sampled */ false, /* smallest_seqno */ i * 100,
  1245. /* largest_seqno */ i * 100, kInvalidBlobFileNumber);
  1246. }
  1247. UpdateVersionStorageInfo();
  1248. {
  1249. const auto& blob_files = vstorage_.GetBlobFiles();
  1250. ASSERT_EQ(blob_files.size(), 5);
  1251. const std::vector<BlobFileMetaData::LinkedSsts> expected_linked_ssts{
  1252. {1, 6}, {2, 7}, {3, 8}, {4, 9}, {5, 10}};
  1253. for (size_t i = 0; i < 5; ++i) {
  1254. const auto meta =
  1255. vstorage_.GetBlobFileMetaData(/* blob_file_number */ i + 1);
  1256. ASSERT_NE(meta, nullptr);
  1257. ASSERT_EQ(meta->GetLinkedSsts(), expected_linked_ssts[i]);
  1258. }
  1259. }
  1260. VersionEdit edit;
  1261. // Add an SST that references a blob file.
  1262. edit.AddFile(
  1263. /* level */ 1, /* file_number */ 21, /* path_id */ 0,
  1264. /* file_size */ 100, /* smallest */ GetInternalKey("21", 2100),
  1265. /* largest */ GetInternalKey("21", 2100), /* smallest_seqno */ 2100,
  1266. /* largest_seqno */ 2100, /* marked_for_compaction */ false,
  1267. Temperature::kUnknown,
  1268. /* oldest_blob_file_number */ 1, kUnknownOldestAncesterTime,
  1269. kUnknownFileCreationTime, kUnknownEpochNumber, kUnknownFileChecksum,
  1270. kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0, 0,
  1271. /* user_defined_timestamps_persisted */ true);
  1272. // Add an SST that does not reference any blob files.
  1273. edit.AddFile(
  1274. /* level */ 1, /* file_number */ 22, /* path_id */ 0,
  1275. /* file_size */ 100, /* smallest */ GetInternalKey("22", 2200),
  1276. /* largest */ GetInternalKey("22", 2200), /* smallest_seqno */ 2200,
  1277. /* largest_seqno */ 2200, /* marked_for_compaction */ false,
  1278. Temperature::kUnknown, kInvalidBlobFileNumber, kUnknownOldestAncesterTime,
  1279. kUnknownFileCreationTime, kUnknownEpochNumber, kUnknownFileChecksum,
  1280. kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0, 0,
  1281. /* user_defined_timestamps_persisted */ true);
  1282. // Delete a file that references a blob file.
  1283. edit.DeleteFile(/* level */ 1, /* file_number */ 6);
  1284. // Delete a file that does not reference any blob files.
  1285. edit.DeleteFile(/* level */ 1, /* file_number */ 16);
  1286. // Trivially move a file that references a blob file. Note that we save
  1287. // the original BlobFileMetaData object so we can check that no new object
  1288. // gets created.
  1289. auto meta3 = vstorage_.GetBlobFileMetaData(/* blob_file_number */ 3);
  1290. edit.DeleteFile(/* level */ 1, /* file_number */ 3);
  1291. edit.AddFile(/* level */ 2, /* file_number */ 3, /* path_id */ 0,
  1292. /* file_size */ 100, /* smallest */ GetInternalKey("03", 300),
  1293. /* largest */ GetInternalKey("03", 300),
  1294. /* smallest_seqno */ 300,
  1295. /* largest_seqno */ 300, /* marked_for_compaction */ false,
  1296. Temperature::kUnknown,
  1297. /* oldest_blob_file_number */ 3, kUnknownOldestAncesterTime,
  1298. kUnknownFileCreationTime, kUnknownEpochNumber,
  1299. kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1300. kNullUniqueId64x2, 0, 0,
  1301. /* user_defined_timestamps_persisted */ true);
  1302. // Trivially move a file that does not reference any blob files.
  1303. edit.DeleteFile(/* level */ 1, /* file_number */ 13);
  1304. edit.AddFile(/* level */ 2, /* file_number */ 13, /* path_id */ 0,
  1305. /* file_size */ 100, /* smallest */ GetInternalKey("13", 1300),
  1306. /* largest */ GetInternalKey("13", 1300),
  1307. /* smallest_seqno */ 1300,
  1308. /* largest_seqno */ 1300, /* marked_for_compaction */ false,
  1309. Temperature::kUnknown, kInvalidBlobFileNumber,
  1310. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  1311. kUnknownEpochNumber, kUnknownFileChecksum,
  1312. kUnknownFileChecksumFuncName, kNullUniqueId64x2, 0, 0,
  1313. /* user_defined_timestamps_persisted */ true);
  1314. // Add one more SST file that references a blob file, then promptly
  1315. // delete it in a second version edit before the new version gets saved.
  1316. // This file should not show up as linked to the blob file in the new version.
  1317. edit.AddFile(/* level */ 1, /* file_number */ 23, /* path_id */ 0,
  1318. /* file_size */ 100, /* smallest */ GetInternalKey("23", 2300),
  1319. /* largest */ GetInternalKey("23", 2300),
  1320. /* smallest_seqno */ 2300,
  1321. /* largest_seqno */ 2300, /* marked_for_compaction */ false,
  1322. Temperature::kUnknown,
  1323. /* oldest_blob_file_number */ 5, kUnknownOldestAncesterTime,
  1324. kUnknownFileCreationTime, kUnknownEpochNumber,
  1325. kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1326. kNullUniqueId64x2, 0, 0,
  1327. /* user_defined_timestamps_persisted */ true);
  1328. VersionEdit edit2;
  1329. edit2.DeleteFile(/* level */ 1, /* file_number */ 23);
  1330. EnvOptions env_options;
  1331. constexpr TableCache* table_cache = nullptr;
  1332. constexpr VersionSet* version_set = nullptr;
  1333. VersionBuilder builder(env_options, &ioptions_, table_cache, &vstorage_,
  1334. version_set);
  1335. ASSERT_OK(builder.Apply(&edit));
  1336. ASSERT_OK(builder.Apply(&edit2));
  1337. constexpr bool force_consistency_checks = true;
  1338. VersionStorageInfo new_vstorage(
  1339. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, &vstorage_,
  1340. force_consistency_checks, EpochNumberRequirement::kMightMissing, nullptr,
  1341. 0, OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1342. ASSERT_OK(builder.SaveTo(&new_vstorage));
  1343. UpdateVersionStorageInfo(&new_vstorage);
  1344. {
  1345. const auto& blob_files = new_vstorage.GetBlobFiles();
  1346. ASSERT_EQ(blob_files.size(), 5);
  1347. const std::vector<BlobFileMetaData::LinkedSsts> expected_linked_ssts{
  1348. {1, 21}, {2, 7}, {3, 8}, {4, 9}, {5, 10}};
  1349. for (size_t i = 0; i < 5; ++i) {
  1350. const auto meta =
  1351. new_vstorage.GetBlobFileMetaData(/* blob_file_number */ i + 1);
  1352. ASSERT_NE(meta, nullptr);
  1353. ASSERT_EQ(meta->GetLinkedSsts(), expected_linked_ssts[i]);
  1354. }
  1355. // Make sure that no new BlobFileMetaData got created for the blob file
  1356. // affected by the trivial move.
  1357. ASSERT_EQ(new_vstorage.GetBlobFileMetaData(/* blob_file_number */ 3),
  1358. meta3);
  1359. }
  1360. UnrefFilesInVersion(&new_vstorage);
  1361. }
  1362. TEST_F(VersionBuilderTest, CheckConsistencyForFileDeletedTwice) {
  1363. Add(0, 1U, "150", "200", 100, /*path_id*/ 0,
  1364. /*smallest_seq*/ 100, /*largest_seq*/ 100,
  1365. /*num_entries*/ 0, /*num_deletions*/ 0,
  1366. /*sampled*/ false, /*smallest_seqno*/ 0,
  1367. /*largest_seqno*/ 0,
  1368. /*oldest_blob_file_number*/ kInvalidBlobFileNumber,
  1369. /*epoch_number*/ 1);
  1370. UpdateVersionStorageInfo();
  1371. VersionEdit version_edit;
  1372. version_edit.DeleteFile(0, 1U);
  1373. EnvOptions env_options;
  1374. constexpr TableCache* table_cache = nullptr;
  1375. constexpr VersionSet* version_set = nullptr;
  1376. VersionBuilder version_builder(env_options, &ioptions_, table_cache,
  1377. &vstorage_, version_set);
  1378. VersionStorageInfo new_vstorage(
  1379. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr,
  1380. true /* force_consistency_checks */,
  1381. EpochNumberRequirement::kMightMissing, nullptr, 0,
  1382. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1383. ASSERT_OK(version_builder.Apply(&version_edit));
  1384. ASSERT_OK(version_builder.SaveTo(&new_vstorage));
  1385. UpdateVersionStorageInfo(&new_vstorage);
  1386. VersionBuilder version_builder2(env_options, &ioptions_, table_cache,
  1387. &new_vstorage, version_set);
  1388. VersionStorageInfo new_vstorage2(
  1389. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel, nullptr,
  1390. true /* force_consistency_checks */,
  1391. EpochNumberRequirement::kMightMissing, nullptr, 0,
  1392. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1393. ASSERT_NOK(version_builder2.Apply(&version_edit));
  1394. UnrefFilesInVersion(&new_vstorage);
  1395. UnrefFilesInVersion(&new_vstorage2);
  1396. }
  1397. TEST_F(VersionBuilderTest, CheckConsistencyForL0FilesSortedByEpochNumber) {
  1398. Status s;
  1399. // To verify files of same epoch number of overlapping ranges are caught as
  1400. // corrupted
  1401. VersionEdit version_edit_1;
  1402. version_edit_1.AddFile(
  1403. /* level */ 0, /* file_number */ 1U, /* path_id */ 0,
  1404. /* file_size */ 100, /* smallest */ GetInternalKey("a", 1),
  1405. /* largest */ GetInternalKey("c", 3), /* smallest_seqno */ 1,
  1406. /* largest_seqno */ 3, /* marked_for_compaction */ false,
  1407. Temperature::kUnknown,
  1408. /* oldest_blob_file_number */ kInvalidBlobFileNumber,
  1409. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  1410. 1 /* epoch_number */, kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1411. kNullUniqueId64x2, 0, 0, /* user_defined_timestamps_persisted */ true);
  1412. version_edit_1.AddFile(
  1413. /* level */ 0, /* file_number */ 2U, /* path_id */ 0,
  1414. /* file_size */ 100, /* smallest */ GetInternalKey("b", 2),
  1415. /* largest */ GetInternalKey("d", 4), /* smallest_seqno */ 2,
  1416. /* largest_seqno */ 4, /* marked_for_compaction */ false,
  1417. Temperature::kUnknown,
  1418. /* oldest_blob_file_number */ kInvalidBlobFileNumber,
  1419. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  1420. 1 /* epoch_number */, kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1421. kNullUniqueId64x2, 0, 0, /* user_defined_timestamps_persisted */ true);
  1422. VersionBuilder version_builder_1(EnvOptions(), &ioptions_,
  1423. nullptr /* table_cache */, &vstorage_,
  1424. nullptr /* file_metadata_cache_res_mgr */);
  1425. VersionStorageInfo new_vstorage_1(
  1426. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel,
  1427. nullptr /* src_vstorage */, true /* force_consistency_checks */,
  1428. EpochNumberRequirement::kMightMissing, nullptr, 0,
  1429. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1430. ASSERT_OK(version_builder_1.Apply(&version_edit_1));
  1431. s = version_builder_1.SaveTo(&new_vstorage_1);
  1432. EXPECT_TRUE(s.IsCorruption());
  1433. EXPECT_TRUE(std::strstr(
  1434. s.getState(), "L0 files of same epoch number but overlapping range"));
  1435. UnrefFilesInVersion(&new_vstorage_1);
  1436. // To verify L0 files not sorted by epoch_number are caught as corrupted
  1437. VersionEdit version_edit_2;
  1438. version_edit_2.AddFile(
  1439. /* level */ 0, /* file_number */ 1U, /* path_id */ 0,
  1440. /* file_size */ 100, /* smallest */ GetInternalKey("a", 1),
  1441. /* largest */ GetInternalKey("a", 1), /* smallest_seqno */ 1,
  1442. /* largest_seqno */ 1, /* marked_for_compaction */ false,
  1443. Temperature::kUnknown,
  1444. /* oldest_blob_file_number */ kInvalidBlobFileNumber,
  1445. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  1446. 1 /* epoch_number */, kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1447. kNullUniqueId64x2, 0, 0, /* user_defined_timestamps_persisted */ true);
  1448. version_edit_2.AddFile(
  1449. /* level */ 0, /* file_number */ 2U, /* path_id */ 0,
  1450. /* file_size */ 100, /* smallest */ GetInternalKey("b", 2),
  1451. /* largest */ GetInternalKey("b", 2), /* smallest_seqno */ 2,
  1452. /* largest_seqno */ 2, /* marked_for_compaction */ false,
  1453. Temperature::kUnknown,
  1454. /* oldest_blob_file_number */ kInvalidBlobFileNumber,
  1455. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  1456. 2 /* epoch_number */, kUnknownFileChecksum, kUnknownFileChecksumFuncName,
  1457. kNullUniqueId64x2, 0, 0, /* user_defined_timestamps_persisted */ true);
  1458. VersionBuilder version_builder_2(EnvOptions(), &ioptions_,
  1459. nullptr /* table_cache */, &vstorage_,
  1460. nullptr /* file_metadata_cache_res_mgr */);
  1461. VersionStorageInfo new_vstorage_2(
  1462. &icmp_, ucmp_, options_.num_levels, kCompactionStyleLevel,
  1463. nullptr /* src_vstorage */, true /* force_consistency_checks */,
  1464. EpochNumberRequirement::kMightMissing, nullptr, 0,
  1465. OffpeakTimeOption(options_.daily_offpeak_time_utc));
  1466. ASSERT_OK(version_builder_2.Apply(&version_edit_2));
  1467. s = version_builder_2.SaveTo(&new_vstorage_2);
  1468. ASSERT_TRUE(s.ok());
  1469. const std::vector<FileMetaData*>& l0_files = new_vstorage_2.LevelFiles(0);
  1470. ASSERT_EQ(l0_files.size(), 2);
  1471. // Manually corrupt L0 files's epoch_number
  1472. l0_files[0]->epoch_number = 1;
  1473. l0_files[1]->epoch_number = 2;
  1474. // To surface corruption error by applying dummy version edit
  1475. VersionEdit dummy_version_edit;
  1476. VersionBuilder dummy_version_builder(
  1477. EnvOptions(), &ioptions_, nullptr /* table_cache */, &vstorage_,
  1478. nullptr /* file_metadata_cache_res_mgr */);
  1479. ASSERT_OK(dummy_version_builder.Apply(&dummy_version_edit));
  1480. s = dummy_version_builder.SaveTo(&new_vstorage_2);
  1481. EXPECT_TRUE(s.IsCorruption());
  1482. EXPECT_TRUE(std::strstr(s.getState(), "L0 files are not sorted properly"));
  1483. UnrefFilesInVersion(&new_vstorage_2);
  1484. }
  1485. TEST_F(VersionBuilderTest, EstimatedActiveKeys) {
  1486. const uint32_t kTotalSamples = 20;
  1487. const uint32_t kNumLevels = 5;
  1488. const uint32_t kFilesPerLevel = 8;
  1489. const uint32_t kNumFiles = kNumLevels * kFilesPerLevel;
  1490. const uint32_t kEntriesPerFile = 1000;
  1491. const uint32_t kDeletionsPerFile = 100;
  1492. for (uint32_t i = 0; i < kNumFiles; ++i) {
  1493. Add(static_cast<int>(i / kFilesPerLevel), i + 1,
  1494. std::to_string((i + 100) * 1000).c_str(),
  1495. std::to_string((i + 100) * 1000 + 999).c_str(), 100U, 0, 100, 100,
  1496. kEntriesPerFile, kDeletionsPerFile, (i < kTotalSamples));
  1497. }
  1498. // minus 2X for the number of deletion entries because:
  1499. // 1x for deletion entry does not count as a data entry.
  1500. // 1x for each deletion entry will actually remove one data entry.
  1501. ASSERT_EQ(vstorage_.GetEstimatedActiveKeys(),
  1502. (kEntriesPerFile - 2 * kDeletionsPerFile) * kNumFiles);
  1503. }
  1504. } // namespace ROCKSDB_NAMESPACE
  1505. int main(int argc, char** argv) {
  1506. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  1507. ::testing::InitGoogleTest(&argc, argv);
  1508. return RUN_ALL_TESTS();
  1509. }