db_test_util.cc 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #include "db/db_test_util.h"
  10. #include "cache/cache_reservation_manager.h"
  11. #include "db/forward_iterator.h"
  12. #include "env/fs_readonly.h"
  13. #include "env/mock_env.h"
  14. #include "port/lang.h"
  15. #include "rocksdb/cache.h"
  16. #include "rocksdb/convenience.h"
  17. #include "rocksdb/env_encryption.h"
  18. #include "rocksdb/unique_id.h"
  19. #include "rocksdb/utilities/object_registry.h"
  20. #include "table/format.h"
  21. #include "util/random.h"
  22. namespace ROCKSDB_NAMESPACE {
  23. namespace {
  24. int64_t MaybeCurrentTime(Env* env) {
  25. int64_t time = 1337346000; // arbitrary fallback default
  26. env->GetCurrentTime(&time).PermitUncheckedError();
  27. return time;
  28. }
  29. } // anonymous namespace
  30. // Special Env used to delay background operations
  31. SpecialEnv::SpecialEnv(Env* base, bool time_elapse_only_sleep)
  32. : EnvWrapper(base),
  33. maybe_starting_time_(MaybeCurrentTime(base)),
  34. rnd_(301),
  35. sleep_counter_(this),
  36. time_elapse_only_sleep_(time_elapse_only_sleep),
  37. no_slowdown_(time_elapse_only_sleep) {
  38. delay_sstable_sync_.store(false, std::memory_order_release);
  39. drop_writes_.store(false, std::memory_order_release);
  40. no_space_.store(false, std::memory_order_release);
  41. non_writable_.store(false, std::memory_order_release);
  42. count_random_reads_ = false;
  43. count_sequential_reads_ = false;
  44. manifest_sync_error_.store(false, std::memory_order_release);
  45. manifest_write_error_.store(false, std::memory_order_release);
  46. log_write_error_.store(false, std::memory_order_release);
  47. no_file_overwrite_.store(false, std::memory_order_release);
  48. random_file_open_counter_.store(0, std::memory_order_relaxed);
  49. delete_count_.store(0, std::memory_order_relaxed);
  50. num_open_wal_file_.store(0);
  51. log_write_slowdown_ = 0;
  52. bytes_written_ = 0;
  53. sync_counter_ = 0;
  54. non_writeable_rate_ = 0;
  55. new_writable_count_ = 0;
  56. non_writable_count_ = 0;
  57. table_write_callback_ = nullptr;
  58. }
  59. DBTestBase::DBTestBase(const std::string path, bool env_do_fsync)
  60. : mem_env_(nullptr), encrypted_env_(nullptr), option_config_(kDefault) {
  61. Env* base_env = Env::Default();
  62. ConfigOptions config_options;
  63. EXPECT_OK(test::CreateEnvFromSystem(config_options, &base_env, &env_guard_));
  64. EXPECT_NE(nullptr, base_env);
  65. if (getenv("MEM_ENV")) {
  66. mem_env_ = MockEnv::Create(base_env, base_env->GetSystemClock());
  67. }
  68. if (auto ee = getenv("ENCRYPTED_ENV")) {
  69. std::shared_ptr<EncryptionProvider> provider;
  70. std::string provider_id = ee;
  71. if (provider_id.find('=') == std::string::npos &&
  72. !EndsWith(provider_id, "://test")) {
  73. provider_id = provider_id + "://test";
  74. }
  75. EXPECT_OK(EncryptionProvider::CreateFromString(ConfigOptions(), provider_id,
  76. &provider));
  77. encrypted_env_ = NewEncryptedEnv(mem_env_ ? mem_env_ : base_env, provider);
  78. }
  79. env_ = new SpecialEnv(encrypted_env_ ? encrypted_env_
  80. : (mem_env_ ? mem_env_ : base_env));
  81. env_->SetBackgroundThreads(1, Env::LOW);
  82. env_->SetBackgroundThreads(1, Env::HIGH);
  83. env_->skip_fsync_ = !env_do_fsync;
  84. dbname_ = test::PerThreadDBPath(env_, path);
  85. alternative_wal_dir_ = dbname_ + "/wal";
  86. alternative_db_log_dir_ = dbname_ + "/db_log_dir";
  87. auto options = CurrentOptions();
  88. options.env = env_;
  89. auto delete_options = options;
  90. delete_options.wal_dir = alternative_wal_dir_;
  91. EXPECT_OK(DestroyDB(dbname_, delete_options));
  92. // Destroy it for not alternative WAL dir is used.
  93. EXPECT_OK(DestroyDB(dbname_, options));
  94. db_ = nullptr;
  95. Reopen(options);
  96. Random::GetTLSInstance()->Reset(0xdeadbeef);
  97. }
  98. DBTestBase::~DBTestBase() {
  99. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  100. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({});
  101. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  102. Close();
  103. Options options;
  104. options.db_paths.emplace_back(dbname_, 0);
  105. options.db_paths.emplace_back(dbname_ + "_2", 0);
  106. options.db_paths.emplace_back(dbname_ + "_3", 0);
  107. options.db_paths.emplace_back(dbname_ + "_4", 0);
  108. options.env = env_;
  109. if (getenv("KEEP_DB")) {
  110. printf("DB is still at %s\n", dbname_.c_str());
  111. } else {
  112. EXPECT_OK(DestroyDB(dbname_, options));
  113. }
  114. delete env_;
  115. }
  116. bool DBTestBase::ShouldSkipOptions(int option_config, int skip_mask) {
  117. if ((skip_mask & kSkipUniversalCompaction) &&
  118. (option_config == kUniversalCompaction ||
  119. option_config == kUniversalCompactionMultiLevel ||
  120. option_config == kUniversalSubcompactions)) {
  121. return true;
  122. }
  123. if ((skip_mask & kSkipMergePut) && option_config == kMergePut) {
  124. return true;
  125. }
  126. if ((skip_mask & kSkipNoSeekToLast) &&
  127. (option_config == kHashLinkList || option_config == kHashSkipList)) {
  128. return true;
  129. }
  130. if ((skip_mask & kSkipPlainTable) &&
  131. (option_config == kPlainTableAllBytesPrefix ||
  132. option_config == kPlainTableFirstBytePrefix ||
  133. option_config == kPlainTableCappedPrefix ||
  134. option_config == kPlainTableCappedPrefixNonMmap)) {
  135. return true;
  136. }
  137. if ((skip_mask & kSkipHashIndex) &&
  138. (option_config == kBlockBasedTableWithPrefixHashIndex ||
  139. option_config == kBlockBasedTableWithWholeKeyHashIndex)) {
  140. return true;
  141. }
  142. if ((skip_mask & kSkipFIFOCompaction) && option_config == kFIFOCompaction) {
  143. return true;
  144. }
  145. if ((skip_mask & kSkipMmapReads) && option_config == kWalDirAndMmapReads) {
  146. return true;
  147. }
  148. if ((skip_mask & kSkipRowCache) && option_config == kRowCache) {
  149. return true;
  150. }
  151. return false;
  152. }
  153. // Switch to a fresh database with the next option configuration to
  154. // test. Return false if there are no more configurations to test.
  155. bool DBTestBase::ChangeOptions(int skip_mask) {
  156. for (option_config_++; option_config_ < kEnd; option_config_++) {
  157. if (ShouldSkipOptions(option_config_, skip_mask)) {
  158. continue;
  159. }
  160. break;
  161. }
  162. if (option_config_ >= kEnd) {
  163. Destroy(last_options_);
  164. return false;
  165. } else {
  166. auto options = CurrentOptions();
  167. options.create_if_missing = true;
  168. DestroyAndReopen(options);
  169. return true;
  170. }
  171. }
  172. // Switch between different compaction styles.
  173. bool DBTestBase::ChangeCompactOptions() {
  174. if (option_config_ == kDefault) {
  175. option_config_ = kUniversalCompaction;
  176. Destroy(last_options_);
  177. auto options = CurrentOptions();
  178. options.create_if_missing = true;
  179. Reopen(options);
  180. return true;
  181. } else if (option_config_ == kUniversalCompaction) {
  182. option_config_ = kUniversalCompactionMultiLevel;
  183. Destroy(last_options_);
  184. auto options = CurrentOptions();
  185. options.create_if_missing = true;
  186. Reopen(options);
  187. return true;
  188. } else if (option_config_ == kUniversalCompactionMultiLevel) {
  189. option_config_ = kLevelSubcompactions;
  190. Destroy(last_options_);
  191. auto options = CurrentOptions();
  192. assert(options.max_subcompactions > 1);
  193. Reopen(options);
  194. return true;
  195. } else if (option_config_ == kLevelSubcompactions) {
  196. option_config_ = kUniversalSubcompactions;
  197. Destroy(last_options_);
  198. auto options = CurrentOptions();
  199. assert(options.max_subcompactions > 1);
  200. Reopen(options);
  201. return true;
  202. } else {
  203. return false;
  204. }
  205. }
  206. // Switch between different WAL settings
  207. bool DBTestBase::ChangeWalOptions() {
  208. if (option_config_ == kDefault) {
  209. option_config_ = kDBLogDir;
  210. Destroy(last_options_);
  211. auto options = CurrentOptions();
  212. Destroy(options);
  213. options.create_if_missing = true;
  214. Reopen(options);
  215. return true;
  216. } else if (option_config_ == kDBLogDir) {
  217. option_config_ = kWalDirAndMmapReads;
  218. Destroy(last_options_);
  219. auto options = CurrentOptions();
  220. Destroy(options);
  221. options.create_if_missing = true;
  222. Reopen(options);
  223. return true;
  224. } else if (option_config_ == kWalDirAndMmapReads) {
  225. option_config_ = kRecycleLogFiles;
  226. Destroy(last_options_);
  227. auto options = CurrentOptions();
  228. Destroy(options);
  229. Reopen(options);
  230. return true;
  231. } else {
  232. return false;
  233. }
  234. }
  235. // Switch between different filter policy
  236. // Jump from kDefault to kFilter to kFullFilter
  237. bool DBTestBase::ChangeFilterOptions() {
  238. if (option_config_ == kDefault) {
  239. option_config_ = kFilter;
  240. } else if (option_config_ == kFilter) {
  241. option_config_ = kFullFilterWithNewTableReaderForCompactions;
  242. } else if (option_config_ == kFullFilterWithNewTableReaderForCompactions) {
  243. option_config_ = kPartitionedFilterWithNewTableReaderForCompactions;
  244. } else {
  245. return false;
  246. }
  247. Destroy(last_options_);
  248. auto options = CurrentOptions();
  249. options.create_if_missing = true;
  250. EXPECT_OK(TryReopen(options));
  251. return true;
  252. }
  253. // Switch between different DB options for file ingestion tests.
  254. bool DBTestBase::ChangeOptionsForFileIngestionTest() {
  255. if (option_config_ == kDefault) {
  256. option_config_ = kUniversalCompaction;
  257. Destroy(last_options_);
  258. auto options = CurrentOptions();
  259. options.create_if_missing = true;
  260. EXPECT_OK(TryReopen(options));
  261. return true;
  262. } else if (option_config_ == kUniversalCompaction) {
  263. option_config_ = kUniversalCompactionMultiLevel;
  264. Destroy(last_options_);
  265. auto options = CurrentOptions();
  266. options.create_if_missing = true;
  267. EXPECT_OK(TryReopen(options));
  268. return true;
  269. } else if (option_config_ == kUniversalCompactionMultiLevel) {
  270. option_config_ = kLevelSubcompactions;
  271. Destroy(last_options_);
  272. auto options = CurrentOptions();
  273. assert(options.max_subcompactions > 1);
  274. EXPECT_OK(TryReopen(options));
  275. return true;
  276. } else if (option_config_ == kLevelSubcompactions) {
  277. option_config_ = kUniversalSubcompactions;
  278. Destroy(last_options_);
  279. auto options = CurrentOptions();
  280. assert(options.max_subcompactions > 1);
  281. EXPECT_OK(TryReopen(options));
  282. return true;
  283. } else if (option_config_ == kUniversalSubcompactions) {
  284. option_config_ = kDirectIO;
  285. Destroy(last_options_);
  286. auto options = CurrentOptions();
  287. EXPECT_OK(TryReopen(options));
  288. return true;
  289. } else {
  290. return false;
  291. }
  292. }
  293. // Return the current option configuration.
  294. Options DBTestBase::CurrentOptions(
  295. const anon::OptionsOverride& options_override) const {
  296. return GetOptions(option_config_, GetDefaultOptions(), options_override);
  297. }
  298. Options DBTestBase::CurrentOptions(
  299. const Options& default_options,
  300. const anon::OptionsOverride& options_override) const {
  301. return GetOptions(option_config_, default_options, options_override);
  302. }
  303. Options DBTestBase::GetDefaultOptions() const {
  304. Options options;
  305. options.write_buffer_size = 4090 * 4096;
  306. options.target_file_size_base = 2 * 1024 * 1024;
  307. options.max_bytes_for_level_base = 10 * 1024 * 1024;
  308. options.max_open_files = 5000;
  309. options.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords;
  310. options.compaction_pri = CompactionPri::kByCompensatedSize;
  311. // The original default value for this option is false,
  312. // and many unit tests assume this value. It also makes
  313. // it easier to create desired LSM shape in unit tests.
  314. // Unit tests for this option sets level_compaction_dynamic_level_bytes=true
  315. // explicitly.
  316. options.level_compaction_dynamic_level_bytes = false;
  317. options.env = env_;
  318. if (!env_->skip_fsync_) {
  319. options.track_and_verify_wals_in_manifest = true;
  320. }
  321. return options;
  322. }
  323. Options DBTestBase::GetOptions(
  324. int option_config, const Options& default_options,
  325. const anon::OptionsOverride& options_override) const {
  326. // this redundant copy is to minimize code change w/o having lint error.
  327. Options options = default_options;
  328. BlockBasedTableOptions table_options;
  329. bool set_block_based_table_factory = true;
  330. #if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
  331. !defined(OS_AIX)
  332. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  333. "NewRandomAccessFile:O_DIRECT");
  334. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  335. "NewWritableFile:O_DIRECT");
  336. #endif
  337. // kMustFreeHeapAllocations -> indicates ASAN build
  338. if (kMustFreeHeapAllocations && !options_override.full_block_cache) {
  339. // Detecting block cache use-after-free is normally difficult in unit
  340. // tests, because as a cache, it tends to keep unreferenced entries in
  341. // memory, and we normally want unit tests to take advantage of block
  342. // cache for speed. However, we also want a strong chance of detecting
  343. // block cache use-after-free in unit tests in ASAN builds, so for ASAN
  344. // builds we use a trivially small block cache to which entries can be
  345. // added but are immediately freed on no more references.
  346. table_options.block_cache = NewLRUCache(/* too small */ 1);
  347. }
  348. bool can_allow_mmap = IsMemoryMappedAccessSupported();
  349. switch (option_config) {
  350. case kHashSkipList:
  351. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  352. options.memtable_factory.reset(NewHashSkipListRepFactory(16));
  353. options.allow_concurrent_memtable_write = false;
  354. options.unordered_write = false;
  355. break;
  356. case kPlainTableFirstBytePrefix:
  357. options.table_factory.reset(NewPlainTableFactory());
  358. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  359. options.allow_mmap_reads = can_allow_mmap;
  360. options.max_sequential_skip_in_iterations = 999999;
  361. set_block_based_table_factory = false;
  362. break;
  363. case kPlainTableCappedPrefix:
  364. options.table_factory.reset(NewPlainTableFactory());
  365. options.prefix_extractor.reset(NewCappedPrefixTransform(8));
  366. options.allow_mmap_reads = can_allow_mmap;
  367. options.max_sequential_skip_in_iterations = 999999;
  368. set_block_based_table_factory = false;
  369. break;
  370. case kPlainTableCappedPrefixNonMmap:
  371. options.table_factory.reset(NewPlainTableFactory());
  372. options.prefix_extractor.reset(NewCappedPrefixTransform(8));
  373. options.allow_mmap_reads = false;
  374. options.max_sequential_skip_in_iterations = 999999;
  375. set_block_based_table_factory = false;
  376. break;
  377. case kPlainTableAllBytesPrefix:
  378. options.table_factory.reset(NewPlainTableFactory());
  379. options.prefix_extractor.reset(NewNoopTransform());
  380. options.allow_mmap_reads = can_allow_mmap;
  381. options.max_sequential_skip_in_iterations = 999999;
  382. set_block_based_table_factory = false;
  383. break;
  384. case kVectorRep:
  385. options.memtable_factory.reset(new VectorRepFactory(100));
  386. options.allow_concurrent_memtable_write = false;
  387. options.unordered_write = false;
  388. break;
  389. case kHashLinkList:
  390. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  391. options.memtable_factory.reset(
  392. NewHashLinkListRepFactory(4, 0, 3, true, 4));
  393. options.allow_concurrent_memtable_write = false;
  394. options.unordered_write = false;
  395. break;
  396. case kDirectIO: {
  397. options.use_direct_reads = true;
  398. options.use_direct_io_for_flush_and_compaction = true;
  399. options.compaction_readahead_size = 2 * 1024 * 1024;
  400. SetupSyncPointsToMockDirectIO();
  401. break;
  402. }
  403. case kMergePut:
  404. options.merge_operator = MergeOperators::CreatePutOperator();
  405. break;
  406. case kFilter:
  407. table_options.filter_policy.reset(NewBloomFilterPolicy(10, true));
  408. break;
  409. case kFullFilterWithNewTableReaderForCompactions:
  410. table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
  411. options.compaction_readahead_size = 10 * 1024 * 1024;
  412. break;
  413. case kPartitionedFilterWithNewTableReaderForCompactions:
  414. table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
  415. table_options.partition_filters = true;
  416. table_options.index_type =
  417. BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch;
  418. options.compaction_readahead_size = 10 * 1024 * 1024;
  419. break;
  420. case kUncompressed:
  421. options.compression = kNoCompression;
  422. break;
  423. case kNumLevel_3:
  424. options.num_levels = 3;
  425. break;
  426. case kDBLogDir:
  427. options.db_log_dir = alternative_db_log_dir_;
  428. break;
  429. case kWalDirAndMmapReads:
  430. options.wal_dir = alternative_wal_dir_;
  431. // mmap reads should be orthogonal to WalDir setting, so we piggyback to
  432. // this option config to test mmap reads as well
  433. options.allow_mmap_reads = can_allow_mmap;
  434. break;
  435. case kManifestFileSize:
  436. options.max_manifest_file_size = 50; // 50 bytes
  437. break;
  438. case kPerfOptions:
  439. options.delayed_write_rate = 8 * 1024 * 1024;
  440. options.report_bg_io_stats = true;
  441. // TODO(3.13) -- test more options
  442. break;
  443. case kUniversalCompaction:
  444. options.compaction_style = kCompactionStyleUniversal;
  445. options.num_levels = 1;
  446. break;
  447. case kUniversalCompactionMultiLevel:
  448. options.compaction_style = kCompactionStyleUniversal;
  449. options.num_levels = 8;
  450. break;
  451. case kInfiniteMaxOpenFiles:
  452. options.max_open_files = -1;
  453. break;
  454. case kCRC32cChecksum: {
  455. // Old default was CRC32c, but XXH3 (new default) is faster on common
  456. // hardware
  457. table_options.checksum = kCRC32c;
  458. // Thrown in here for basic coverage:
  459. options.DisableExtraChecks();
  460. break;
  461. }
  462. case kFIFOCompaction: {
  463. options.compaction_style = kCompactionStyleFIFO;
  464. options.max_open_files = -1;
  465. break;
  466. }
  467. case kBlockBasedTableWithPrefixHashIndex: {
  468. table_options.index_type = BlockBasedTableOptions::kHashSearch;
  469. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  470. break;
  471. }
  472. case kBlockBasedTableWithWholeKeyHashIndex: {
  473. table_options.index_type = BlockBasedTableOptions::kHashSearch;
  474. options.prefix_extractor.reset(NewNoopTransform());
  475. break;
  476. }
  477. case kBlockBasedTableWithPartitionedIndex: {
  478. table_options.format_version = 3;
  479. table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
  480. options.prefix_extractor.reset(NewNoopTransform());
  481. break;
  482. }
  483. case kBlockBasedTableWithPartitionedIndexFormat4: {
  484. table_options.format_version = 4;
  485. // Format 4 changes the binary index format. Since partitioned index is a
  486. // super-set of simple indexes, we are also using kTwoLevelIndexSearch to
  487. // test this format.
  488. table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
  489. // The top-level index in partition filters are also affected by format 4.
  490. table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
  491. table_options.partition_filters = true;
  492. table_options.index_block_restart_interval = 8;
  493. break;
  494. }
  495. case kBlockBasedTableWithIndexRestartInterval: {
  496. table_options.index_block_restart_interval = 8;
  497. break;
  498. }
  499. case kBlockBasedTableWithLatestFormat: {
  500. // In case different from default
  501. table_options.format_version = kLatestFormatVersion;
  502. break;
  503. }
  504. case kOptimizeFiltersForHits: {
  505. options.optimize_filters_for_hits = true;
  506. set_block_based_table_factory = true;
  507. break;
  508. }
  509. case kRowCache: {
  510. options.row_cache = NewLRUCache(1024 * 1024);
  511. break;
  512. }
  513. case kRecycleLogFiles: {
  514. options.recycle_log_file_num = 2;
  515. break;
  516. }
  517. case kLevelSubcompactions: {
  518. options.max_subcompactions = 4;
  519. break;
  520. }
  521. case kUniversalSubcompactions: {
  522. options.compaction_style = kCompactionStyleUniversal;
  523. options.num_levels = 8;
  524. options.max_subcompactions = 4;
  525. break;
  526. }
  527. case kConcurrentSkipList: {
  528. options.allow_concurrent_memtable_write = true;
  529. options.enable_write_thread_adaptive_yield = true;
  530. break;
  531. }
  532. case kPipelinedWrite: {
  533. options.enable_pipelined_write = true;
  534. break;
  535. }
  536. case kConcurrentWALWrites: {
  537. // This options optimize 2PC commit path
  538. options.two_write_queues = true;
  539. options.manual_wal_flush = true;
  540. break;
  541. }
  542. case kUnorderedWrite: {
  543. options.allow_concurrent_memtable_write = false;
  544. options.unordered_write = false;
  545. break;
  546. }
  547. case kBlockBasedTableWithBinarySearchWithFirstKeyIndex: {
  548. table_options.index_type =
  549. BlockBasedTableOptions::kBinarySearchWithFirstKey;
  550. break;
  551. }
  552. default:
  553. break;
  554. }
  555. if (options_override.filter_policy) {
  556. table_options.filter_policy = options_override.filter_policy;
  557. table_options.partition_filters = options_override.partition_filters;
  558. table_options.metadata_block_size = options_override.metadata_block_size;
  559. }
  560. if (set_block_based_table_factory) {
  561. options.table_factory.reset(NewBlockBasedTableFactory(table_options));
  562. }
  563. options.level_compaction_dynamic_level_bytes =
  564. options_override.level_compaction_dynamic_level_bytes;
  565. options.env = env_;
  566. options.create_if_missing = true;
  567. return options;
  568. }
  569. void DBTestBase::CreateColumnFamilies(const std::vector<std::string>& cfs,
  570. const Options& options) {
  571. ColumnFamilyOptions cf_opts(options);
  572. size_t cfi = handles_.size();
  573. handles_.resize(cfi + cfs.size());
  574. for (const auto& cf : cfs) {
  575. Status s = db_->CreateColumnFamily(cf_opts, cf, &handles_[cfi++]);
  576. ASSERT_OK(s);
  577. }
  578. }
  579. void DBTestBase::CreateAndReopenWithCF(const std::vector<std::string>& cfs,
  580. const Options& options) {
  581. CreateColumnFamilies(cfs, options);
  582. std::vector<std::string> cfs_plus_default = cfs;
  583. cfs_plus_default.insert(cfs_plus_default.begin(), kDefaultColumnFamilyName);
  584. ReopenWithColumnFamilies(cfs_plus_default, options);
  585. }
  586. void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
  587. const std::vector<Options>& options) {
  588. ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
  589. }
  590. void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
  591. const Options& options) {
  592. ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
  593. }
  594. void DBTestBase::SetTimeElapseOnlySleepOnReopen(DBOptions* options) {
  595. time_elapse_only_sleep_on_reopen_ = true;
  596. // Need to disable stats dumping and persisting which also use
  597. // RepeatableThread, which uses InstrumentedCondVar::TimedWaitInternal.
  598. // With time_elapse_only_sleep_, this can hang on some platforms (MacOS)
  599. // because (a) on some platforms, pthread_cond_timedwait does not appear
  600. // to release the lock for other threads to operate if the deadline time
  601. // is already passed, and (b) TimedWait calls are currently a bad abstraction
  602. // because the deadline parameter is usually computed from Env time,
  603. // but is interpreted in real clock time.
  604. options->stats_dump_period_sec = 0;
  605. options->stats_persist_period_sec = 0;
  606. }
  607. void DBTestBase::MaybeInstallTimeElapseOnlySleep(const DBOptions& options) {
  608. if (time_elapse_only_sleep_on_reopen_) {
  609. assert(options.env == env_ ||
  610. static_cast_with_check<CompositeEnvWrapper>(options.env)
  611. ->env_target() == env_);
  612. assert(options.stats_dump_period_sec == 0);
  613. assert(options.stats_persist_period_sec == 0);
  614. // We cannot set these before destroying the last DB because they might
  615. // cause a deadlock or similar without the appropriate options set in
  616. // the DB.
  617. env_->time_elapse_only_sleep_ = true;
  618. env_->no_slowdown_ = true;
  619. } else {
  620. // Going back in same test run is not yet supported, so no
  621. // reset in this case.
  622. }
  623. }
  624. Status DBTestBase::TryReopenWithColumnFamilies(
  625. const std::vector<std::string>& cfs, const std::vector<Options>& options) {
  626. Close();
  627. EXPECT_EQ(cfs.size(), options.size());
  628. std::vector<ColumnFamilyDescriptor> column_families;
  629. for (size_t i = 0; i < cfs.size(); ++i) {
  630. column_families.emplace_back(cfs[i], options[i]);
  631. }
  632. DBOptions db_opts = DBOptions(options[0]);
  633. last_options_ = options[0];
  634. MaybeInstallTimeElapseOnlySleep(db_opts);
  635. return DB::Open(db_opts, dbname_, column_families, &handles_, &db_);
  636. }
  637. Status DBTestBase::TryReopenWithColumnFamilies(
  638. const std::vector<std::string>& cfs, const Options& options) {
  639. Close();
  640. std::vector<Options> v_opts(cfs.size(), options);
  641. return TryReopenWithColumnFamilies(cfs, v_opts);
  642. }
  643. void DBTestBase::Reopen(const Options& options) {
  644. ASSERT_OK(TryReopen(options));
  645. }
  646. void DBTestBase::Close() {
  647. for (auto h : handles_) {
  648. EXPECT_OK(db_->DestroyColumnFamilyHandle(h));
  649. }
  650. handles_.clear();
  651. delete db_;
  652. db_ = nullptr;
  653. }
  654. void DBTestBase::DestroyAndReopen(const Options& options) {
  655. // Destroy using last options
  656. Destroy(last_options_);
  657. Reopen(options);
  658. }
  659. void DBTestBase::Destroy(const Options& options, bool delete_cf_paths) {
  660. std::vector<ColumnFamilyDescriptor> column_families;
  661. if (delete_cf_paths) {
  662. for (size_t i = 0; i < handles_.size(); ++i) {
  663. ColumnFamilyDescriptor cfdescriptor;
  664. handles_[i]->GetDescriptor(&cfdescriptor).PermitUncheckedError();
  665. column_families.push_back(cfdescriptor);
  666. }
  667. }
  668. Close();
  669. ASSERT_OK(DestroyDB(dbname_, options, column_families));
  670. }
  671. Status DBTestBase::ReadOnlyReopen(const Options& options) {
  672. Close();
  673. MaybeInstallTimeElapseOnlySleep(options);
  674. return DB::OpenForReadOnly(options, dbname_, &db_);
  675. }
  676. Status DBTestBase::EnforcedReadOnlyReopen(const Options& options) {
  677. Close();
  678. Options options_copy = options;
  679. MaybeInstallTimeElapseOnlySleep(options_copy);
  680. auto fs_read_only =
  681. std::make_shared<ReadOnlyFileSystem>(env_->GetFileSystem());
  682. env_read_only_ = std::make_shared<CompositeEnvWrapper>(env_, fs_read_only);
  683. options_copy.env = env_read_only_.get();
  684. return DB::OpenForReadOnly(options_copy, dbname_, &db_);
  685. }
  686. Status DBTestBase::TryReopen(const Options& options) {
  687. Close();
  688. last_options_.table_factory.reset();
  689. // Note: operator= is an unsafe approach here since it destructs
  690. // std::shared_ptr in the same order of their creation, in contrast to
  691. // destructors which destructs them in the opposite order of creation. One
  692. // particular problem is that the cache destructor might invoke callback
  693. // functions that use Option members such as statistics. To work around this
  694. // problem, we manually call destructor of table_factory which eventually
  695. // clears the block cache.
  696. last_options_ = options;
  697. MaybeInstallTimeElapseOnlySleep(options);
  698. return DB::Open(options, dbname_, &db_);
  699. }
  700. bool DBTestBase::IsDirectIOSupported() {
  701. return test::IsDirectIOSupported(env_, dbname_);
  702. }
  703. bool DBTestBase::IsMemoryMappedAccessSupported() const {
  704. return (!encrypted_env_);
  705. }
  706. Status DBTestBase::Flush(int cf) {
  707. if (cf == 0) {
  708. return db_->Flush(FlushOptions());
  709. } else {
  710. return db_->Flush(FlushOptions(), handles_[cf]);
  711. }
  712. }
  713. Status DBTestBase::Flush(const std::vector<int>& cf_ids) {
  714. std::vector<ColumnFamilyHandle*> cfhs;
  715. std::for_each(cf_ids.begin(), cf_ids.end(),
  716. [&cfhs, this](int id) { cfhs.emplace_back(handles_[id]); });
  717. return db_->Flush(FlushOptions(), cfhs);
  718. }
  719. Status DBTestBase::Put(const Slice& k, const Slice& v, WriteOptions wo) {
  720. if (kMergePut == option_config_) {
  721. return db_->Merge(wo, k, v);
  722. } else {
  723. return db_->Put(wo, k, v);
  724. }
  725. }
  726. Status DBTestBase::Put(int cf, const Slice& k, const Slice& v,
  727. WriteOptions wo) {
  728. if (kMergePut == option_config_) {
  729. return db_->Merge(wo, handles_[cf], k, v);
  730. } else {
  731. return db_->Put(wo, handles_[cf], k, v);
  732. }
  733. }
  734. Status DBTestBase::TimedPut(const Slice& k, const Slice& v,
  735. uint64_t write_unix_time, WriteOptions wo) {
  736. return TimedPut(0, k, v, write_unix_time, wo);
  737. }
  738. Status DBTestBase::TimedPut(int cf, const Slice& k, const Slice& v,
  739. uint64_t write_unix_time, WriteOptions wo) {
  740. WriteBatch wb(/*reserved_bytes=*/0, /*max_bytes=*/0,
  741. wo.protection_bytes_per_key,
  742. /*default_cf_ts_sz=*/0);
  743. ColumnFamilyHandle* cfh;
  744. if (cf != 0) {
  745. cfh = handles_[cf];
  746. } else {
  747. cfh = db_->DefaultColumnFamily();
  748. }
  749. EXPECT_OK(wb.TimedPut(cfh, k, v, write_unix_time));
  750. return db_->Write(wo, &wb);
  751. }
  752. Status DBTestBase::Merge(const Slice& k, const Slice& v, WriteOptions wo) {
  753. return db_->Merge(wo, k, v);
  754. }
  755. Status DBTestBase::Merge(int cf, const Slice& k, const Slice& v,
  756. WriteOptions wo) {
  757. return db_->Merge(wo, handles_[cf], k, v);
  758. }
  759. Status DBTestBase::Delete(const std::string& k) {
  760. return db_->Delete(WriteOptions(), k);
  761. }
  762. Status DBTestBase::Delete(int cf, const std::string& k) {
  763. return db_->Delete(WriteOptions(), handles_[cf], k);
  764. }
  765. Status DBTestBase::SingleDelete(const std::string& k) {
  766. return db_->SingleDelete(WriteOptions(), k);
  767. }
  768. Status DBTestBase::SingleDelete(int cf, const std::string& k) {
  769. return db_->SingleDelete(WriteOptions(), handles_[cf], k);
  770. }
  771. std::string DBTestBase::Get(const std::string& k, const Snapshot* snapshot) {
  772. ReadOptions options;
  773. options.verify_checksums = true;
  774. options.snapshot = snapshot;
  775. std::string result;
  776. Status s = db_->Get(options, k, &result);
  777. if (s.IsNotFound()) {
  778. result = "NOT_FOUND";
  779. } else if (!s.ok()) {
  780. result = s.ToString();
  781. }
  782. return result;
  783. }
  784. std::string DBTestBase::Get(int cf, const std::string& k,
  785. const Snapshot* snapshot) {
  786. ReadOptions options;
  787. options.verify_checksums = true;
  788. options.snapshot = snapshot;
  789. std::string result;
  790. Status s = db_->Get(options, handles_[cf], k, &result);
  791. if (s.IsNotFound()) {
  792. result = "NOT_FOUND";
  793. } else if (!s.ok()) {
  794. result = s.ToString();
  795. }
  796. return result;
  797. }
  798. std::vector<std::string> DBTestBase::MultiGet(std::vector<int> cfs,
  799. const std::vector<std::string>& k,
  800. const Snapshot* snapshot,
  801. const bool batched,
  802. const bool async) {
  803. ReadOptions options;
  804. options.verify_checksums = true;
  805. options.snapshot = snapshot;
  806. options.async_io = async;
  807. std::vector<ColumnFamilyHandle*> handles;
  808. std::vector<Slice> keys;
  809. std::vector<std::string> result;
  810. for (unsigned int i = 0; i < cfs.size(); ++i) {
  811. handles.push_back(handles_[cfs[i]]);
  812. keys.emplace_back(k[i]);
  813. }
  814. std::vector<Status> s;
  815. if (!batched) {
  816. s = db_->MultiGet(options, handles, keys, &result);
  817. for (size_t i = 0; i < s.size(); ++i) {
  818. if (s[i].IsNotFound()) {
  819. result[i] = "NOT_FOUND";
  820. } else if (!s[i].ok()) {
  821. result[i] = s[i].ToString();
  822. }
  823. }
  824. } else {
  825. std::vector<PinnableSlice> pin_values(cfs.size());
  826. result.resize(cfs.size());
  827. s.resize(cfs.size());
  828. db_->MultiGet(options, cfs.size(), handles.data(), keys.data(),
  829. pin_values.data(), s.data());
  830. for (size_t i = 0; i < s.size(); ++i) {
  831. if (s[i].IsNotFound()) {
  832. result[i] = "NOT_FOUND";
  833. } else if (!s[i].ok()) {
  834. result[i] = s[i].ToString();
  835. } else {
  836. result[i].assign(pin_values[i].data(), pin_values[i].size());
  837. // Increase likelihood of detecting potential use-after-free bugs with
  838. // PinnableSlices tracking the same resource
  839. pin_values[i].Reset();
  840. }
  841. }
  842. }
  843. return result;
  844. }
  845. std::vector<std::string> DBTestBase::MultiGet(const std::vector<std::string>& k,
  846. const Snapshot* snapshot,
  847. const bool async) {
  848. ReadOptions options;
  849. options.verify_checksums = true;
  850. options.snapshot = snapshot;
  851. options.async_io = async;
  852. std::vector<Slice> keys;
  853. std::vector<std::string> result(k.size());
  854. std::vector<Status> statuses(k.size());
  855. std::vector<PinnableSlice> pin_values(k.size());
  856. for (size_t i = 0; i < k.size(); ++i) {
  857. keys.emplace_back(k[i]);
  858. }
  859. db_->MultiGet(options, dbfull()->DefaultColumnFamily(), keys.size(),
  860. keys.data(), pin_values.data(), statuses.data());
  861. for (size_t i = 0; i < statuses.size(); ++i) {
  862. if (statuses[i].IsNotFound()) {
  863. result[i] = "NOT_FOUND";
  864. } else if (!statuses[i].ok()) {
  865. result[i] = statuses[i].ToString();
  866. } else {
  867. result[i].assign(pin_values[i].data(), pin_values[i].size());
  868. // Increase likelihood of detecting potential use-after-free bugs with
  869. // PinnableSlices tracking the same resource
  870. pin_values[i].Reset();
  871. }
  872. }
  873. return result;
  874. }
  875. Status DBTestBase::Get(const std::string& k, PinnableSlice* v) {
  876. ReadOptions options;
  877. options.verify_checksums = true;
  878. Status s = dbfull()->Get(options, dbfull()->DefaultColumnFamily(), k, v);
  879. return s;
  880. }
  881. Status DBTestBase::CompactRange(const CompactRangeOptions& options,
  882. std::optional<Slice> begin,
  883. std::optional<Slice> end) {
  884. return db_->CompactRange(options, begin ? &begin.value() : nullptr,
  885. end ? &end.value() : nullptr);
  886. }
  887. uint64_t DBTestBase::GetNumSnapshots() {
  888. uint64_t int_num;
  889. EXPECT_TRUE(dbfull()->GetIntProperty("rocksdb.num-snapshots", &int_num));
  890. return int_num;
  891. }
  892. uint64_t DBTestBase::GetTimeOldestSnapshots() {
  893. uint64_t int_num;
  894. EXPECT_TRUE(
  895. dbfull()->GetIntProperty("rocksdb.oldest-snapshot-time", &int_num));
  896. return int_num;
  897. }
  898. uint64_t DBTestBase::GetSequenceOldestSnapshots() {
  899. uint64_t int_num;
  900. EXPECT_TRUE(
  901. dbfull()->GetIntProperty("rocksdb.oldest-snapshot-sequence", &int_num));
  902. return int_num;
  903. }
  904. // Return a string that contains all key,value pairs in order,
  905. // formatted like "(k1->v1)(k2->v2)".
  906. std::string DBTestBase::Contents(int cf) {
  907. std::vector<std::string> forward;
  908. std::string result;
  909. Iterator* iter = (cf == 0) ? db_->NewIterator(ReadOptions())
  910. : db_->NewIterator(ReadOptions(), handles_[cf]);
  911. for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
  912. std::string s = IterStatus(iter);
  913. result.push_back('(');
  914. result.append(s);
  915. result.push_back(')');
  916. forward.push_back(s);
  917. }
  918. // Check reverse iteration results are the reverse of forward results
  919. unsigned int matched = 0;
  920. for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
  921. EXPECT_LT(matched, forward.size());
  922. EXPECT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
  923. matched++;
  924. }
  925. EXPECT_OK(iter->status());
  926. EXPECT_EQ(matched, forward.size());
  927. delete iter;
  928. return result;
  929. }
  930. void DBTestBase::CheckAllEntriesWithFifoReopen(
  931. const std::string& expected_value, const Slice& user_key, int cf,
  932. const std::vector<std::string>& cfs, const Options& options) {
  933. ASSERT_EQ(AllEntriesFor(user_key, cf), expected_value);
  934. std::vector<std::string> cfs_plus_default = cfs;
  935. cfs_plus_default.insert(cfs_plus_default.begin(), kDefaultColumnFamilyName);
  936. Options fifo_options(options);
  937. fifo_options.compaction_style = kCompactionStyleFIFO;
  938. fifo_options.max_open_files = -1;
  939. fifo_options.disable_auto_compactions = true;
  940. ASSERT_OK(TryReopenWithColumnFamilies(cfs_plus_default, fifo_options));
  941. ASSERT_EQ(AllEntriesFor(user_key, cf), expected_value);
  942. ASSERT_OK(TryReopenWithColumnFamilies(cfs_plus_default, options));
  943. ASSERT_EQ(AllEntriesFor(user_key, cf), expected_value);
  944. }
  945. std::string DBTestBase::AllEntriesFor(const Slice& user_key, int cf) {
  946. Arena arena;
  947. auto options = CurrentOptions();
  948. InternalKeyComparator icmp(options.comparator);
  949. ReadOptions read_options;
  950. ScopedArenaPtr<InternalIterator> iter;
  951. if (cf == 0) {
  952. iter.reset(dbfull()->NewInternalIterator(read_options, &arena,
  953. kMaxSequenceNumber));
  954. } else {
  955. iter.reset(dbfull()->NewInternalIterator(read_options, &arena,
  956. kMaxSequenceNumber, handles_[cf]));
  957. }
  958. InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
  959. iter->Seek(target.Encode());
  960. std::string result;
  961. if (!iter->status().ok()) {
  962. result = iter->status().ToString();
  963. } else {
  964. result = "[ ";
  965. bool first = true;
  966. while (iter->Valid()) {
  967. ParsedInternalKey ikey(Slice(), 0, kTypeValue);
  968. if (ParseInternalKey(iter->key(), &ikey, true /* log_err_key */) !=
  969. Status::OK()) {
  970. result += "CORRUPTED";
  971. } else {
  972. if (!last_options_.comparator->Equal(ikey.user_key, user_key)) {
  973. break;
  974. }
  975. if (!first) {
  976. result += ", ";
  977. }
  978. first = false;
  979. switch (ikey.type) {
  980. case kTypeValue:
  981. result += iter->value().ToString();
  982. break;
  983. case kTypeMerge:
  984. // keep it the same as kTypeValue for testing kMergePut
  985. result += iter->value().ToString();
  986. break;
  987. case kTypeDeletion:
  988. result += "DEL";
  989. break;
  990. case kTypeSingleDeletion:
  991. result += "SDEL";
  992. break;
  993. default:
  994. assert(false);
  995. break;
  996. }
  997. }
  998. iter->Next();
  999. }
  1000. if (!first) {
  1001. result += " ";
  1002. }
  1003. result += "]";
  1004. }
  1005. return result;
  1006. }
  1007. int DBTestBase::NumSortedRuns(int cf) {
  1008. ColumnFamilyMetaData cf_meta;
  1009. if (cf == 0) {
  1010. db_->GetColumnFamilyMetaData(&cf_meta);
  1011. } else {
  1012. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  1013. }
  1014. int num_sr = static_cast<int>(cf_meta.levels[0].files.size());
  1015. for (size_t i = 1U; i < cf_meta.levels.size(); i++) {
  1016. if (cf_meta.levels[i].files.size() > 0) {
  1017. num_sr++;
  1018. }
  1019. }
  1020. return num_sr;
  1021. }
  1022. uint64_t DBTestBase::TotalSize(int cf) {
  1023. ColumnFamilyMetaData cf_meta;
  1024. if (cf == 0) {
  1025. db_->GetColumnFamilyMetaData(&cf_meta);
  1026. } else {
  1027. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  1028. }
  1029. return cf_meta.size;
  1030. }
  1031. uint64_t DBTestBase::SizeAtLevel(int level) {
  1032. std::vector<LiveFileMetaData> metadata;
  1033. db_->GetLiveFilesMetaData(&metadata);
  1034. uint64_t sum = 0;
  1035. for (const auto& m : metadata) {
  1036. if (m.level == level) {
  1037. sum += m.size;
  1038. }
  1039. }
  1040. return sum;
  1041. }
  1042. size_t DBTestBase::TotalLiveFiles(int cf) {
  1043. ColumnFamilyMetaData cf_meta;
  1044. if (cf == 0) {
  1045. db_->GetColumnFamilyMetaData(&cf_meta);
  1046. } else {
  1047. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  1048. }
  1049. size_t num_files = 0;
  1050. for (auto& level : cf_meta.levels) {
  1051. num_files += level.files.size();
  1052. }
  1053. return num_files;
  1054. }
  1055. size_t DBTestBase::TotalLiveFilesAtPath(int cf, const std::string& path) {
  1056. ColumnFamilyMetaData cf_meta;
  1057. if (cf == 0) {
  1058. db_->GetColumnFamilyMetaData(&cf_meta);
  1059. } else {
  1060. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  1061. }
  1062. size_t num_files = 0;
  1063. for (auto& level : cf_meta.levels) {
  1064. for (auto& f : level.files) {
  1065. if (f.directory == path) {
  1066. num_files++;
  1067. }
  1068. }
  1069. }
  1070. return num_files;
  1071. }
  1072. size_t DBTestBase::CountLiveFiles() {
  1073. std::vector<LiveFileMetaData> metadata;
  1074. db_->GetLiveFilesMetaData(&metadata);
  1075. return metadata.size();
  1076. }
  1077. int DBTestBase::NumTableFilesAtLevel(int level, int cf) {
  1078. return NumTableFilesAtLevel(level,
  1079. cf ? handles_[cf] : db_->DefaultColumnFamily());
  1080. }
  1081. int DBTestBase::NumTableFilesAtLevel(int level, ColumnFamilyHandle* cfh,
  1082. DB* db) {
  1083. if (!db) {
  1084. db = db_;
  1085. }
  1086. std::string property;
  1087. EXPECT_TRUE(db->GetProperty(
  1088. cfh, "rocksdb.num-files-at-level" + std::to_string(level), &property));
  1089. return atoi(property.c_str());
  1090. }
  1091. double DBTestBase::CompressionRatioAtLevel(int level, int cf) {
  1092. std::string property;
  1093. if (cf == 0) {
  1094. // default cfd
  1095. EXPECT_TRUE(db_->GetProperty(
  1096. "rocksdb.compression-ratio-at-level" + std::to_string(level),
  1097. &property));
  1098. } else {
  1099. EXPECT_TRUE(db_->GetProperty(
  1100. handles_[cf],
  1101. "rocksdb.compression-ratio-at-level" + std::to_string(level),
  1102. &property));
  1103. }
  1104. return std::stod(property);
  1105. }
  1106. int DBTestBase::TotalTableFiles(int cf, int levels) {
  1107. if (levels == -1) {
  1108. levels = (cf == 0) ? db_->NumberLevels() : db_->NumberLevels(handles_[1]);
  1109. }
  1110. int result = 0;
  1111. for (int level = 0; level < levels; level++) {
  1112. result += NumTableFilesAtLevel(level, cf);
  1113. }
  1114. return result;
  1115. }
  1116. // Return spread of files per level
  1117. std::string DBTestBase::FilesPerLevel(int cf) {
  1118. if (cf == 0) {
  1119. return FilesPerLevel(db_->DefaultColumnFamily());
  1120. } else {
  1121. return FilesPerLevel(handles_[cf]);
  1122. }
  1123. }
  1124. std::string DBTestBase::FilesPerLevel(ColumnFamilyHandle* cfh, DB* db) {
  1125. if (!db) {
  1126. db = db_;
  1127. }
  1128. int num_levels = db->NumberLevels(cfh);
  1129. std::string result;
  1130. size_t last_non_zero_offset = 0;
  1131. for (int level = 0; level < num_levels; level++) {
  1132. int f = NumTableFilesAtLevel(level, cfh, db);
  1133. char buf[100];
  1134. snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f);
  1135. result += buf;
  1136. if (f > 0) {
  1137. last_non_zero_offset = result.size();
  1138. }
  1139. }
  1140. result.resize(last_non_zero_offset);
  1141. return result;
  1142. }
  1143. std::vector<uint64_t> DBTestBase::GetBlobFileNumbers() {
  1144. VersionSet* const versions = dbfull()->GetVersionSet();
  1145. assert(versions);
  1146. ColumnFamilyData* const cfd = versions->GetColumnFamilySet()->GetDefault();
  1147. assert(cfd);
  1148. Version* const current = cfd->current();
  1149. assert(current);
  1150. const VersionStorageInfo* const storage_info = current->storage_info();
  1151. assert(storage_info);
  1152. const auto& blob_files = storage_info->GetBlobFiles();
  1153. std::vector<uint64_t> result;
  1154. result.reserve(blob_files.size());
  1155. for (const auto& blob_file : blob_files) {
  1156. assert(blob_file);
  1157. result.emplace_back(blob_file->GetBlobFileNumber());
  1158. }
  1159. return result;
  1160. }
  1161. size_t DBTestBase::CountFiles() {
  1162. size_t count = 0;
  1163. std::vector<std::string> files;
  1164. if (env_->GetChildren(dbname_, &files).ok()) {
  1165. count += files.size();
  1166. }
  1167. if (dbname_ != last_options_.wal_dir) {
  1168. if (env_->GetChildren(last_options_.wal_dir, &files).ok()) {
  1169. count += files.size();
  1170. }
  1171. }
  1172. return count;
  1173. };
  1174. Status DBTestBase::CountFiles(size_t* count) {
  1175. std::vector<std::string> files;
  1176. Status s = env_->GetChildren(dbname_, &files);
  1177. if (!s.ok()) {
  1178. return s;
  1179. }
  1180. size_t files_count = files.size();
  1181. if (dbname_ != last_options_.wal_dir) {
  1182. s = env_->GetChildren(last_options_.wal_dir, &files);
  1183. if (!s.ok()) {
  1184. return s;
  1185. }
  1186. *count = files_count + files.size();
  1187. }
  1188. return Status::OK();
  1189. }
  1190. std::vector<FileMetaData*> DBTestBase::GetLevelFileMetadatas(int level,
  1191. int cf) {
  1192. VersionSet* const versions = dbfull()->GetVersionSet();
  1193. assert(versions);
  1194. ColumnFamilyData* const cfd =
  1195. versions->GetColumnFamilySet()->GetColumnFamily(cf);
  1196. assert(cfd);
  1197. Version* const current = cfd->current();
  1198. assert(current);
  1199. VersionStorageInfo* const storage_info = current->storage_info();
  1200. assert(storage_info);
  1201. return storage_info->LevelFiles(level);
  1202. }
  1203. Status DBTestBase::Size(const Slice& start, const Slice& limit, int cf,
  1204. uint64_t* size) {
  1205. Range r(start, limit);
  1206. if (cf == 0) {
  1207. return db_->GetApproximateSizes(&r, 1, size);
  1208. } else {
  1209. return db_->GetApproximateSizes(handles_[1], &r, 1, size);
  1210. }
  1211. }
  1212. void DBTestBase::Compact(int cf, const Slice& start, const Slice& limit,
  1213. uint32_t target_path_id) {
  1214. CompactRangeOptions compact_options;
  1215. compact_options.target_path_id = target_path_id;
  1216. ASSERT_OK(db_->CompactRange(compact_options, handles_[cf], &start, &limit));
  1217. }
  1218. void DBTestBase::Compact(int cf, const Slice& start, const Slice& limit) {
  1219. ASSERT_OK(
  1220. db_->CompactRange(CompactRangeOptions(), handles_[cf], &start, &limit));
  1221. }
  1222. void DBTestBase::Compact(const Slice& start, const Slice& limit) {
  1223. ASSERT_OK(db_->CompactRange(CompactRangeOptions(), &start, &limit));
  1224. }
  1225. // Do n memtable compactions, each of which produces an sstable
  1226. // covering the range [small,large].
  1227. void DBTestBase::MakeTables(int n, const std::string& small,
  1228. const std::string& large, int cf) {
  1229. for (int i = 0; i < n; i++) {
  1230. ASSERT_OK(Put(cf, small, "begin"));
  1231. ASSERT_OK(Put(cf, large, "end"));
  1232. ASSERT_OK(Flush(cf));
  1233. MoveFilesToLevel(n - i - 1, cf);
  1234. }
  1235. }
  1236. // Prevent pushing of new sstables into deeper levels by adding
  1237. // tables that cover a specified range to all levels.
  1238. void DBTestBase::FillLevels(const std::string& smallest,
  1239. const std::string& largest, int cf) {
  1240. MakeTables(db_->NumberLevels(handles_[cf]), smallest, largest, cf);
  1241. }
  1242. void DBTestBase::MoveFilesToLevel(int level, int cf) {
  1243. MoveFilesToLevel(level, cf ? handles_[cf] : db_->DefaultColumnFamily());
  1244. }
  1245. void DBTestBase::MoveFilesToLevel(int level, ColumnFamilyHandle* column_family,
  1246. DB* db) {
  1247. DBImpl* db_impl = db ? static_cast<DBImpl*>(db) : dbfull();
  1248. for (int l = 0; l < level; ++l) {
  1249. EXPECT_OK(db_impl->TEST_CompactRange(l, nullptr, nullptr, column_family));
  1250. }
  1251. }
  1252. void DBTestBase::DumpFileCounts(const char* label) {
  1253. fprintf(stderr, "---\n%s:\n", label);
  1254. fprintf(stderr, "maxoverlap: %" PRIu64 "\n",
  1255. dbfull()->TEST_MaxNextLevelOverlappingBytes());
  1256. for (int level = 0; level < db_->NumberLevels(); level++) {
  1257. int num = NumTableFilesAtLevel(level);
  1258. if (num > 0) {
  1259. fprintf(stderr, " level %3d : %d files\n", level, num);
  1260. }
  1261. }
  1262. }
  1263. std::string DBTestBase::DumpSSTableList() {
  1264. std::string property;
  1265. db_->GetProperty("rocksdb.sstables", &property);
  1266. return property;
  1267. }
  1268. void DBTestBase::GetSstFiles(Env* env, std::string path,
  1269. std::vector<std::string>* files) {
  1270. EXPECT_OK(env->GetChildren(path, files));
  1271. files->erase(std::remove_if(files->begin(), files->end(),
  1272. [](std::string name) {
  1273. uint64_t number;
  1274. FileType type;
  1275. return !(ParseFileName(name, &number, &type) &&
  1276. type == kTableFile);
  1277. }),
  1278. files->end());
  1279. }
  1280. int DBTestBase::GetSstFileCount(std::string path) {
  1281. std::vector<std::string> files;
  1282. DBTestBase::GetSstFiles(env_, path, &files);
  1283. return static_cast<int>(files.size());
  1284. }
  1285. // this will generate non-overlapping files since it keeps increasing key_idx
  1286. void DBTestBase::GenerateNewFile(int cf, Random* rnd, int* key_idx,
  1287. bool nowait) {
  1288. for (int i = 0; i < KNumKeysByGenerateNewFile; i++) {
  1289. ASSERT_OK(Put(cf, Key(*key_idx), rnd->RandomString((i == 99) ? 1 : 990)));
  1290. (*key_idx)++;
  1291. }
  1292. if (!nowait) {
  1293. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  1294. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  1295. }
  1296. }
  1297. // this will generate non-overlapping files since it keeps increasing key_idx
  1298. void DBTestBase::GenerateNewFile(Random* rnd, int* key_idx, bool nowait) {
  1299. for (int i = 0; i < KNumKeysByGenerateNewFile; i++) {
  1300. ASSERT_OK(Put(Key(*key_idx), rnd->RandomString((i == 99) ? 1 : 990)));
  1301. (*key_idx)++;
  1302. }
  1303. if (!nowait) {
  1304. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  1305. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  1306. }
  1307. }
  1308. const int DBTestBase::kNumKeysByGenerateNewRandomFile = 51;
  1309. void DBTestBase::GenerateNewRandomFile(Random* rnd, bool nowait) {
  1310. for (int i = 0; i < kNumKeysByGenerateNewRandomFile; i++) {
  1311. ASSERT_OK(Put("key" + rnd->RandomString(7), rnd->RandomString(2000)));
  1312. }
  1313. ASSERT_OK(Put("key" + rnd->RandomString(7), rnd->RandomString(200)));
  1314. if (!nowait) {
  1315. ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
  1316. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  1317. }
  1318. }
  1319. std::string DBTestBase::IterStatus(Iterator* iter) {
  1320. std::string result;
  1321. if (iter->Valid()) {
  1322. result = iter->key().ToString() + "->" + iter->value().ToString();
  1323. } else {
  1324. EXPECT_OK(iter->status());
  1325. result = "(invalid)";
  1326. }
  1327. return result;
  1328. }
  1329. Options DBTestBase::OptionsForLogIterTest() {
  1330. Options options = CurrentOptions();
  1331. options.create_if_missing = true;
  1332. options.WAL_ttl_seconds = 1000;
  1333. return options;
  1334. }
  1335. std::string DBTestBase::DummyString(size_t len, char c) {
  1336. return std::string(len, c);
  1337. }
  1338. void DBTestBase::VerifyIterLast(std::string expected_key, int cf) {
  1339. Iterator* iter;
  1340. ReadOptions ro;
  1341. if (cf == 0) {
  1342. iter = db_->NewIterator(ro);
  1343. } else {
  1344. iter = db_->NewIterator(ro, handles_[cf]);
  1345. }
  1346. iter->SeekToLast();
  1347. ASSERT_EQ(IterStatus(iter), expected_key);
  1348. delete iter;
  1349. }
  1350. // Used to test InplaceUpdate
  1351. // If previous value is nullptr or delta is > than previous value,
  1352. // sets newValue with delta
  1353. // If previous value is not empty,
  1354. // updates previous value with 'b' string of previous value size - 1.
  1355. UpdateStatus DBTestBase::updateInPlaceSmallerSize(char* prevValue,
  1356. uint32_t* prevSize,
  1357. Slice delta,
  1358. std::string* newValue) {
  1359. if (prevValue == nullptr) {
  1360. *newValue = std::string(delta.size(), 'c');
  1361. return UpdateStatus::UPDATED;
  1362. } else {
  1363. *prevSize = *prevSize - 1;
  1364. std::string str_b = std::string(*prevSize, 'b');
  1365. memcpy(prevValue, str_b.c_str(), str_b.size());
  1366. return UpdateStatus::UPDATED_INPLACE;
  1367. }
  1368. }
  1369. UpdateStatus DBTestBase::updateInPlaceSmallerVarintSize(char* prevValue,
  1370. uint32_t* prevSize,
  1371. Slice delta,
  1372. std::string* newValue) {
  1373. if (prevValue == nullptr) {
  1374. *newValue = std::string(delta.size(), 'c');
  1375. return UpdateStatus::UPDATED;
  1376. } else {
  1377. *prevSize = 1;
  1378. std::string str_b = std::string(*prevSize, 'b');
  1379. memcpy(prevValue, str_b.c_str(), str_b.size());
  1380. return UpdateStatus::UPDATED_INPLACE;
  1381. }
  1382. }
  1383. UpdateStatus DBTestBase::updateInPlaceLargerSize(char* /*prevValue*/,
  1384. uint32_t* /*prevSize*/,
  1385. Slice delta,
  1386. std::string* newValue) {
  1387. *newValue = std::string(delta.size(), 'c');
  1388. return UpdateStatus::UPDATED;
  1389. }
  1390. UpdateStatus DBTestBase::updateInPlaceNoAction(char* /*prevValue*/,
  1391. uint32_t* /*prevSize*/,
  1392. Slice /*delta*/,
  1393. std::string* /*newValue*/) {
  1394. return UpdateStatus::UPDATE_FAILED;
  1395. }
  1396. // Utility method to test InplaceUpdate
  1397. void DBTestBase::validateNumberOfEntries(int numValues, int cf) {
  1398. Arena arena;
  1399. auto options = CurrentOptions();
  1400. InternalKeyComparator icmp(options.comparator);
  1401. ReadOptions read_options;
  1402. ScopedArenaPtr<InternalIterator> iter;
  1403. if (cf != 0) {
  1404. iter.reset(dbfull()->NewInternalIterator(read_options, &arena,
  1405. kMaxSequenceNumber, handles_[cf]));
  1406. } else {
  1407. iter.reset(dbfull()->NewInternalIterator(read_options, &arena,
  1408. kMaxSequenceNumber));
  1409. }
  1410. iter->SeekToFirst();
  1411. ASSERT_OK(iter->status());
  1412. int seq = numValues;
  1413. while (iter->Valid()) {
  1414. ParsedInternalKey ikey;
  1415. ikey.clear();
  1416. ASSERT_OK(ParseInternalKey(iter->key(), &ikey, true /* log_err_key */));
  1417. // checks sequence number for updates
  1418. ASSERT_EQ(ikey.sequence, (unsigned)seq--);
  1419. iter->Next();
  1420. }
  1421. ASSERT_EQ(0, seq);
  1422. }
  1423. void DBTestBase::CopyFile(const std::string& source,
  1424. const std::string& destination, uint64_t size) {
  1425. const EnvOptions soptions;
  1426. std::unique_ptr<SequentialFile> srcfile;
  1427. ASSERT_OK(env_->NewSequentialFile(source, &srcfile, soptions));
  1428. std::unique_ptr<WritableFile> destfile;
  1429. ASSERT_OK(env_->NewWritableFile(destination, &destfile, soptions));
  1430. if (size == 0) {
  1431. // default argument means copy everything
  1432. ASSERT_OK(env_->GetFileSize(source, &size));
  1433. }
  1434. char buffer[4096];
  1435. Slice slice;
  1436. while (size > 0) {
  1437. uint64_t one = std::min(uint64_t(sizeof(buffer)), size);
  1438. ASSERT_OK(srcfile->Read(one, &slice, buffer));
  1439. ASSERT_OK(destfile->Append(slice));
  1440. size -= slice.size();
  1441. }
  1442. ASSERT_OK(destfile->Close());
  1443. }
  1444. Status DBTestBase::GetAllDataFiles(
  1445. const FileType file_type, std::unordered_map<std::string, uint64_t>* files,
  1446. uint64_t* total_size /* = nullptr */) {
  1447. if (total_size) {
  1448. *total_size = 0;
  1449. }
  1450. std::vector<std::string> children;
  1451. Status s = env_->GetChildren(dbname_, &children);
  1452. if (s.ok()) {
  1453. for (auto& file_name : children) {
  1454. uint64_t number;
  1455. FileType type;
  1456. if (ParseFileName(file_name, &number, &type) && type == file_type) {
  1457. std::string file_path = dbname_ + "/" + file_name;
  1458. uint64_t file_size = 0;
  1459. s = env_->GetFileSize(file_path, &file_size);
  1460. if (!s.ok()) {
  1461. break;
  1462. }
  1463. (*files)[file_path] = file_size;
  1464. if (total_size) {
  1465. *total_size += file_size;
  1466. }
  1467. }
  1468. }
  1469. }
  1470. return s;
  1471. }
  1472. std::vector<std::uint64_t> DBTestBase::ListTableFiles(Env* env,
  1473. const std::string& path) {
  1474. std::vector<std::string> files;
  1475. std::vector<uint64_t> file_numbers;
  1476. EXPECT_OK(env->GetChildren(path, &files));
  1477. uint64_t number;
  1478. FileType type;
  1479. for (size_t i = 0; i < files.size(); ++i) {
  1480. if (ParseFileName(files[i], &number, &type)) {
  1481. if (type == kTableFile) {
  1482. file_numbers.push_back(number);
  1483. }
  1484. }
  1485. }
  1486. return file_numbers;
  1487. }
  1488. void DBTestBase::VerifyDBFromMap(
  1489. std::map<std::string, std::string> true_data, size_t* total_reads_res,
  1490. bool tailing_iter, ReadOptions* ro, ColumnFamilyHandle* cf,
  1491. std::unordered_set<std::string>* not_found) const {
  1492. ReadOptions temp_ro;
  1493. if (!ro) {
  1494. ro = &temp_ro;
  1495. ro->verify_checksums = true;
  1496. }
  1497. if (!cf) {
  1498. cf = db_->DefaultColumnFamily();
  1499. }
  1500. // Get
  1501. size_t total_reads = 0;
  1502. std::string result;
  1503. for (auto& [k, v] : true_data) {
  1504. ASSERT_OK(db_->Get(*ro, cf, k, &result)) << "key is " << k;
  1505. ASSERT_EQ(v, result);
  1506. total_reads++;
  1507. }
  1508. if (not_found) {
  1509. for (const auto& k : *not_found) {
  1510. ASSERT_TRUE(db_->Get(*ro, cf, k, &result).IsNotFound())
  1511. << "key is " << k << " val is " << result;
  1512. }
  1513. }
  1514. // MultiGet
  1515. std::vector<Slice> key_slice;
  1516. for (const auto& [k, _] : true_data) {
  1517. key_slice.emplace_back(k);
  1518. }
  1519. std::vector<std::string> values;
  1520. std::vector<ColumnFamilyHandle*> cfs(key_slice.size(), cf);
  1521. std::vector<Status> status = db_->MultiGet(*ro, cfs, key_slice, &values);
  1522. total_reads += key_slice.size();
  1523. auto data_iter = true_data.begin();
  1524. for (size_t i = 0; i < key_slice.size(); ++i, ++data_iter) {
  1525. ASSERT_OK(status[i]);
  1526. ASSERT_EQ(values[i], data_iter->second);
  1527. }
  1528. // MultiGet - not found
  1529. if (not_found) {
  1530. key_slice.clear();
  1531. for (const auto& k : *not_found) {
  1532. key_slice.emplace_back(k);
  1533. }
  1534. cfs = std::vector<ColumnFamilyHandle*>(key_slice.size(), cf);
  1535. values.clear();
  1536. status = db_->MultiGet(*ro, cfs, key_slice, &values);
  1537. for (const auto& s : status) {
  1538. ASSERT_TRUE(s.IsNotFound());
  1539. }
  1540. }
  1541. // Normal Iterator
  1542. {
  1543. int iter_cnt = 0;
  1544. ReadOptions ro_ = *ro;
  1545. ro_.total_order_seek = true;
  1546. Iterator* iter = db_->NewIterator(ro_, cf);
  1547. // Verify Iterator::Next()
  1548. iter_cnt = 0;
  1549. data_iter = true_data.begin();
  1550. for (iter->SeekToFirst(); iter->Valid(); iter->Next(), ++data_iter) {
  1551. ASSERT_EQ(iter->key().ToString(), data_iter->first);
  1552. ASSERT_EQ(iter->value().ToString(), data_iter->second);
  1553. iter_cnt++;
  1554. total_reads++;
  1555. }
  1556. ASSERT_OK(iter->status());
  1557. ASSERT_EQ(data_iter, true_data.end())
  1558. << iter_cnt << " / " << true_data.size();
  1559. delete iter;
  1560. // Verify Iterator::Prev()
  1561. // Use a new iterator to make sure its status is clean.
  1562. iter = db_->NewIterator(ro_, cf);
  1563. iter_cnt = 0;
  1564. auto data_rev = true_data.rbegin();
  1565. for (iter->SeekToLast(); iter->Valid(); iter->Prev(), data_rev++) {
  1566. ASSERT_EQ(iter->key().ToString(), data_rev->first);
  1567. ASSERT_EQ(iter->value().ToString(), data_rev->second);
  1568. iter_cnt++;
  1569. total_reads++;
  1570. }
  1571. ASSERT_OK(iter->status());
  1572. ASSERT_EQ(data_rev, true_data.rend())
  1573. << iter_cnt << " / " << true_data.size();
  1574. // Verify Iterator::Seek() and SeekForPrev()
  1575. for (const auto& [k, v] : true_data) {
  1576. for (bool prev : {false, true}) {
  1577. if (prev) {
  1578. iter->SeekForPrev(k);
  1579. } else {
  1580. iter->Seek(k);
  1581. }
  1582. ASSERT_TRUE(iter->Valid());
  1583. ASSERT_OK(iter->status());
  1584. ASSERT_EQ(iter->key(), k);
  1585. ASSERT_EQ(iter->value(), v);
  1586. ++total_reads;
  1587. }
  1588. }
  1589. delete iter;
  1590. }
  1591. if (tailing_iter) {
  1592. // Tailing iterator
  1593. int iter_cnt = 0;
  1594. ReadOptions ro_ = *ro;
  1595. ro_.tailing = true;
  1596. ro_.total_order_seek = true;
  1597. Iterator* iter = db_->NewIterator(ro_, cf);
  1598. // Verify ForwardIterator::Next()
  1599. iter_cnt = 0;
  1600. data_iter = true_data.begin();
  1601. for (iter->SeekToFirst(); iter->Valid(); iter->Next(), data_iter++) {
  1602. ASSERT_EQ(iter->key().ToString(), data_iter->first);
  1603. ASSERT_EQ(iter->value().ToString(), data_iter->second);
  1604. iter_cnt++;
  1605. total_reads++;
  1606. }
  1607. ASSERT_EQ(data_iter, true_data.end())
  1608. << iter_cnt << " / " << true_data.size();
  1609. // Verify ForwardIterator::Seek()
  1610. for (const auto& kv : true_data) {
  1611. iter->Seek(kv.first);
  1612. ASSERT_EQ(kv.first, iter->key().ToString());
  1613. ASSERT_EQ(kv.second, iter->value().ToString());
  1614. total_reads++;
  1615. }
  1616. delete iter;
  1617. }
  1618. if (total_reads_res) {
  1619. *total_reads_res = total_reads;
  1620. }
  1621. }
  1622. void DBTestBase::VerifyDBInternal(
  1623. std::vector<std::pair<std::string, std::string>> true_data) {
  1624. Arena arena;
  1625. InternalKeyComparator icmp(last_options_.comparator);
  1626. ReadOptions read_options;
  1627. auto iter =
  1628. dbfull()->NewInternalIterator(read_options, &arena, kMaxSequenceNumber);
  1629. iter->SeekToFirst();
  1630. for (const auto& p : true_data) {
  1631. ASSERT_TRUE(iter->Valid());
  1632. ParsedInternalKey ikey;
  1633. ASSERT_OK(ParseInternalKey(iter->key(), &ikey, true /* log_err_key */));
  1634. ASSERT_EQ(p.first, ikey.user_key);
  1635. ASSERT_EQ(p.second, iter->value());
  1636. iter->Next();
  1637. };
  1638. ASSERT_FALSE(iter->Valid());
  1639. iter->~InternalIterator();
  1640. }
  1641. uint64_t DBTestBase::GetNumberOfSstFilesForColumnFamily(
  1642. DB* db, std::string column_family_name) {
  1643. std::vector<LiveFileMetaData> metadata;
  1644. db->GetLiveFilesMetaData(&metadata);
  1645. uint64_t result = 0;
  1646. for (auto& fileMetadata : metadata) {
  1647. result += (fileMetadata.column_family_name == column_family_name);
  1648. }
  1649. return result;
  1650. }
  1651. uint64_t DBTestBase::GetSstSizeHelper(Temperature temperature) {
  1652. std::string prop;
  1653. EXPECT_TRUE(dbfull()->GetProperty(
  1654. DB::Properties::kLiveSstFilesSizeAtTemperature +
  1655. std::to_string(static_cast<uint8_t>(temperature)),
  1656. &prop));
  1657. return static_cast<uint64_t>(std::atoi(prop.c_str()));
  1658. }
  1659. void VerifySstUniqueIds(const TablePropertiesCollection& props) {
  1660. ASSERT_FALSE(props.empty()); // suspicious test if empty
  1661. std::unordered_set<std::string> seen;
  1662. for (auto& pair : props) {
  1663. std::string id;
  1664. ASSERT_OK(GetUniqueIdFromTableProperties(*pair.second, &id));
  1665. ASSERT_TRUE(seen.insert(id).second);
  1666. }
  1667. }
  1668. template <CacheEntryRole R>
  1669. TargetCacheChargeTrackingCache<R>::TargetCacheChargeTrackingCache(
  1670. std::shared_ptr<Cache> target)
  1671. : CacheWrapper(std::move(target)),
  1672. cur_cache_charge_(0),
  1673. cache_charge_peak_(0),
  1674. cache_charge_increment_(0),
  1675. last_peak_tracked_(false),
  1676. cache_charge_increments_sum_(0) {}
  1677. template <CacheEntryRole R>
  1678. Status TargetCacheChargeTrackingCache<R>::Insert(
  1679. const Slice& key, ObjectPtr value, const CacheItemHelper* helper,
  1680. size_t charge, Handle** handle, Priority priority, const Slice& compressed,
  1681. CompressionType type) {
  1682. Status s = target_->Insert(key, value, helper, charge, handle, priority,
  1683. compressed, type);
  1684. if (helper == kCrmHelper) {
  1685. if (last_peak_tracked_) {
  1686. cache_charge_peak_ = 0;
  1687. cache_charge_increment_ = 0;
  1688. last_peak_tracked_ = false;
  1689. }
  1690. if (s.ok()) {
  1691. cur_cache_charge_ += charge;
  1692. }
  1693. cache_charge_peak_ = std::max(cache_charge_peak_, cur_cache_charge_);
  1694. cache_charge_increment_ += charge;
  1695. }
  1696. return s;
  1697. }
  1698. template <CacheEntryRole R>
  1699. bool TargetCacheChargeTrackingCache<R>::Release(Handle* handle,
  1700. bool erase_if_last_ref) {
  1701. auto helper = GetCacheItemHelper(handle);
  1702. if (helper == kCrmHelper) {
  1703. if (!last_peak_tracked_) {
  1704. cache_charge_peaks_.push_back(cache_charge_peak_);
  1705. cache_charge_increments_sum_ += cache_charge_increment_;
  1706. last_peak_tracked_ = true;
  1707. }
  1708. cur_cache_charge_ -= GetCharge(handle);
  1709. }
  1710. bool is_successful = target_->Release(handle, erase_if_last_ref);
  1711. return is_successful;
  1712. }
  1713. template <CacheEntryRole R>
  1714. const Cache::CacheItemHelper* TargetCacheChargeTrackingCache<R>::kCrmHelper =
  1715. CacheReservationManagerImpl<R>::TEST_GetCacheItemHelperForRole();
  1716. template class TargetCacheChargeTrackingCache<
  1717. CacheEntryRole::kFilterConstruction>;
  1718. template class TargetCacheChargeTrackingCache<
  1719. CacheEntryRole::kBlockBasedTableReader>;
  1720. template class TargetCacheChargeTrackingCache<CacheEntryRole::kFileMetadata>;
  1721. const std::vector<Temperature> kKnownTemperatures = {
  1722. Temperature::kHot, Temperature::kWarm, Temperature::kCool,
  1723. Temperature::kCold, Temperature::kIce};
  1724. Temperature RandomKnownTemperature() {
  1725. return kKnownTemperatures[Random::GetTLSInstance()->Uniform(
  1726. static_cast<int>(kKnownTemperatures.size()))];
  1727. }
  1728. } // namespace ROCKSDB_NAMESPACE