db_test_util.cc 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564
  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 "db/forward_iterator.h"
  11. #include "rocksdb/env_encryption.h"
  12. #include "rocksdb/utilities/object_registry.h"
  13. namespace ROCKSDB_NAMESPACE {
  14. // Special Env used to delay background operations
  15. SpecialEnv::SpecialEnv(Env* base)
  16. : EnvWrapper(base),
  17. rnd_(301),
  18. sleep_counter_(this),
  19. addon_time_(0),
  20. time_elapse_only_sleep_(false),
  21. no_slowdown_(false) {
  22. delay_sstable_sync_.store(false, std::memory_order_release);
  23. drop_writes_.store(false, std::memory_order_release);
  24. no_space_.store(false, std::memory_order_release);
  25. non_writable_.store(false, std::memory_order_release);
  26. count_random_reads_ = false;
  27. count_sequential_reads_ = false;
  28. manifest_sync_error_.store(false, std::memory_order_release);
  29. manifest_write_error_.store(false, std::memory_order_release);
  30. log_write_error_.store(false, std::memory_order_release);
  31. random_file_open_counter_.store(0, std::memory_order_relaxed);
  32. delete_count_.store(0, std::memory_order_relaxed);
  33. num_open_wal_file_.store(0);
  34. log_write_slowdown_ = 0;
  35. bytes_written_ = 0;
  36. sync_counter_ = 0;
  37. non_writeable_rate_ = 0;
  38. new_writable_count_ = 0;
  39. non_writable_count_ = 0;
  40. table_write_callback_ = nullptr;
  41. }
  42. #ifndef ROCKSDB_LITE
  43. ROT13BlockCipher rot13Cipher_(16);
  44. #endif // ROCKSDB_LITE
  45. DBTestBase::DBTestBase(const std::string path)
  46. : mem_env_(nullptr), encrypted_env_(nullptr), option_config_(kDefault) {
  47. Env* base_env = Env::Default();
  48. #ifndef ROCKSDB_LITE
  49. const char* test_env_uri = getenv("TEST_ENV_URI");
  50. if (test_env_uri) {
  51. Env* test_env = nullptr;
  52. Status s = Env::LoadEnv(test_env_uri, &test_env, &env_guard_);
  53. base_env = test_env;
  54. EXPECT_OK(s);
  55. EXPECT_NE(Env::Default(), base_env);
  56. }
  57. #endif // !ROCKSDB_LITE
  58. EXPECT_NE(nullptr, base_env);
  59. if (getenv("MEM_ENV")) {
  60. mem_env_ = new MockEnv(base_env);
  61. }
  62. #ifndef ROCKSDB_LITE
  63. if (getenv("ENCRYPTED_ENV")) {
  64. encrypted_env_ = NewEncryptedEnv(mem_env_ ? mem_env_ : base_env,
  65. new CTREncryptionProvider(rot13Cipher_));
  66. }
  67. #endif // !ROCKSDB_LITE
  68. env_ = new SpecialEnv(encrypted_env_ ? encrypted_env_
  69. : (mem_env_ ? mem_env_ : base_env));
  70. env_->SetBackgroundThreads(1, Env::LOW);
  71. env_->SetBackgroundThreads(1, Env::HIGH);
  72. dbname_ = test::PerThreadDBPath(env_, path);
  73. alternative_wal_dir_ = dbname_ + "/wal";
  74. alternative_db_log_dir_ = dbname_ + "/db_log_dir";
  75. auto options = CurrentOptions();
  76. options.env = env_;
  77. auto delete_options = options;
  78. delete_options.wal_dir = alternative_wal_dir_;
  79. EXPECT_OK(DestroyDB(dbname_, delete_options));
  80. // Destroy it for not alternative WAL dir is used.
  81. EXPECT_OK(DestroyDB(dbname_, options));
  82. db_ = nullptr;
  83. Reopen(options);
  84. Random::GetTLSInstance()->Reset(0xdeadbeef);
  85. }
  86. DBTestBase::~DBTestBase() {
  87. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  88. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({});
  89. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  90. Close();
  91. Options options;
  92. options.db_paths.emplace_back(dbname_, 0);
  93. options.db_paths.emplace_back(dbname_ + "_2", 0);
  94. options.db_paths.emplace_back(dbname_ + "_3", 0);
  95. options.db_paths.emplace_back(dbname_ + "_4", 0);
  96. options.env = env_;
  97. if (getenv("KEEP_DB")) {
  98. printf("DB is still at %s\n", dbname_.c_str());
  99. } else {
  100. EXPECT_OK(DestroyDB(dbname_, options));
  101. }
  102. delete env_;
  103. }
  104. bool DBTestBase::ShouldSkipOptions(int option_config, int skip_mask) {
  105. #ifdef ROCKSDB_LITE
  106. // These options are not supported in ROCKSDB_LITE
  107. if (option_config == kHashSkipList ||
  108. option_config == kPlainTableFirstBytePrefix ||
  109. option_config == kPlainTableCappedPrefix ||
  110. option_config == kPlainTableCappedPrefixNonMmap ||
  111. option_config == kPlainTableAllBytesPrefix ||
  112. option_config == kVectorRep || option_config == kHashLinkList ||
  113. option_config == kUniversalCompaction ||
  114. option_config == kUniversalCompactionMultiLevel ||
  115. option_config == kUniversalSubcompactions ||
  116. option_config == kFIFOCompaction ||
  117. option_config == kConcurrentSkipList) {
  118. return true;
  119. }
  120. #endif
  121. if ((skip_mask & kSkipUniversalCompaction) &&
  122. (option_config == kUniversalCompaction ||
  123. option_config == kUniversalCompactionMultiLevel ||
  124. option_config == kUniversalSubcompactions)) {
  125. return true;
  126. }
  127. if ((skip_mask & kSkipMergePut) && option_config == kMergePut) {
  128. return true;
  129. }
  130. if ((skip_mask & kSkipNoSeekToLast) &&
  131. (option_config == kHashLinkList || option_config == kHashSkipList)) {
  132. return true;
  133. }
  134. if ((skip_mask & kSkipPlainTable) &&
  135. (option_config == kPlainTableAllBytesPrefix ||
  136. option_config == kPlainTableFirstBytePrefix ||
  137. option_config == kPlainTableCappedPrefix ||
  138. option_config == kPlainTableCappedPrefixNonMmap)) {
  139. return true;
  140. }
  141. if ((skip_mask & kSkipHashIndex) &&
  142. (option_config == kBlockBasedTableWithPrefixHashIndex ||
  143. option_config == kBlockBasedTableWithWholeKeyHashIndex)) {
  144. return true;
  145. }
  146. if ((skip_mask & kSkipFIFOCompaction) && option_config == kFIFOCompaction) {
  147. return true;
  148. }
  149. if ((skip_mask & kSkipMmapReads) && option_config == kWalDirAndMmapReads) {
  150. return true;
  151. }
  152. return false;
  153. }
  154. // Switch to a fresh database with the next option configuration to
  155. // test. Return false if there are no more configurations to test.
  156. bool DBTestBase::ChangeOptions(int skip_mask) {
  157. for (option_config_++; option_config_ < kEnd; option_config_++) {
  158. if (ShouldSkipOptions(option_config_, skip_mask)) {
  159. continue;
  160. }
  161. break;
  162. }
  163. if (option_config_ >= kEnd) {
  164. Destroy(last_options_);
  165. return false;
  166. } else {
  167. auto options = CurrentOptions();
  168. options.create_if_missing = true;
  169. DestroyAndReopen(options);
  170. return true;
  171. }
  172. }
  173. // Switch between different compaction styles.
  174. bool DBTestBase::ChangeCompactOptions() {
  175. if (option_config_ == kDefault) {
  176. option_config_ = kUniversalCompaction;
  177. Destroy(last_options_);
  178. auto options = CurrentOptions();
  179. options.create_if_missing = true;
  180. TryReopen(options);
  181. return true;
  182. } else if (option_config_ == kUniversalCompaction) {
  183. option_config_ = kUniversalCompactionMultiLevel;
  184. Destroy(last_options_);
  185. auto options = CurrentOptions();
  186. options.create_if_missing = true;
  187. TryReopen(options);
  188. return true;
  189. } else if (option_config_ == kUniversalCompactionMultiLevel) {
  190. option_config_ = kLevelSubcompactions;
  191. Destroy(last_options_);
  192. auto options = CurrentOptions();
  193. assert(options.max_subcompactions > 1);
  194. TryReopen(options);
  195. return true;
  196. } else if (option_config_ == kLevelSubcompactions) {
  197. option_config_ = kUniversalSubcompactions;
  198. Destroy(last_options_);
  199. auto options = CurrentOptions();
  200. assert(options.max_subcompactions > 1);
  201. TryReopen(options);
  202. return true;
  203. } else {
  204. return false;
  205. }
  206. }
  207. // Switch between different WAL settings
  208. bool DBTestBase::ChangeWalOptions() {
  209. if (option_config_ == kDefault) {
  210. option_config_ = kDBLogDir;
  211. Destroy(last_options_);
  212. auto options = CurrentOptions();
  213. Destroy(options);
  214. options.create_if_missing = true;
  215. TryReopen(options);
  216. return true;
  217. } else if (option_config_ == kDBLogDir) {
  218. option_config_ = kWalDirAndMmapReads;
  219. Destroy(last_options_);
  220. auto options = CurrentOptions();
  221. Destroy(options);
  222. options.create_if_missing = true;
  223. TryReopen(options);
  224. return true;
  225. } else if (option_config_ == kWalDirAndMmapReads) {
  226. option_config_ = kRecycleLogFiles;
  227. Destroy(last_options_);
  228. auto options = CurrentOptions();
  229. Destroy(options);
  230. TryReopen(options);
  231. return true;
  232. } else {
  233. return false;
  234. }
  235. }
  236. // Switch between different filter policy
  237. // Jump from kDefault to kFilter to kFullFilter
  238. bool DBTestBase::ChangeFilterOptions() {
  239. if (option_config_ == kDefault) {
  240. option_config_ = kFilter;
  241. } else if (option_config_ == kFilter) {
  242. option_config_ = kFullFilterWithNewTableReaderForCompactions;
  243. } else if (option_config_ == kFullFilterWithNewTableReaderForCompactions) {
  244. option_config_ = kPartitionedFilterWithNewTableReaderForCompactions;
  245. } else {
  246. return false;
  247. }
  248. Destroy(last_options_);
  249. auto options = CurrentOptions();
  250. options.create_if_missing = true;
  251. TryReopen(options);
  252. return true;
  253. }
  254. // Switch between different DB options for file ingestion tests.
  255. bool DBTestBase::ChangeOptionsForFileIngestionTest() {
  256. if (option_config_ == kDefault) {
  257. option_config_ = kUniversalCompaction;
  258. Destroy(last_options_);
  259. auto options = CurrentOptions();
  260. options.create_if_missing = true;
  261. TryReopen(options);
  262. return true;
  263. } else if (option_config_ == kUniversalCompaction) {
  264. option_config_ = kUniversalCompactionMultiLevel;
  265. Destroy(last_options_);
  266. auto options = CurrentOptions();
  267. options.create_if_missing = true;
  268. TryReopen(options);
  269. return true;
  270. } else if (option_config_ == kUniversalCompactionMultiLevel) {
  271. option_config_ = kLevelSubcompactions;
  272. Destroy(last_options_);
  273. auto options = CurrentOptions();
  274. assert(options.max_subcompactions > 1);
  275. TryReopen(options);
  276. return true;
  277. } else if (option_config_ == kLevelSubcompactions) {
  278. option_config_ = kUniversalSubcompactions;
  279. Destroy(last_options_);
  280. auto options = CurrentOptions();
  281. assert(options.max_subcompactions > 1);
  282. TryReopen(options);
  283. return true;
  284. } else if (option_config_ == kUniversalSubcompactions) {
  285. option_config_ = kDirectIO;
  286. Destroy(last_options_);
  287. auto options = CurrentOptions();
  288. TryReopen(options);
  289. return true;
  290. } else {
  291. return false;
  292. }
  293. }
  294. // Return the current option configuration.
  295. Options DBTestBase::CurrentOptions(
  296. const anon::OptionsOverride& options_override) const {
  297. return GetOptions(option_config_, GetDefaultOptions(), options_override);
  298. }
  299. Options DBTestBase::CurrentOptions(
  300. const Options& default_options,
  301. const anon::OptionsOverride& options_override) const {
  302. return GetOptions(option_config_, default_options, options_override);
  303. }
  304. Options DBTestBase::GetDefaultOptions() {
  305. Options options;
  306. options.write_buffer_size = 4090 * 4096;
  307. options.target_file_size_base = 2 * 1024 * 1024;
  308. options.max_bytes_for_level_base = 10 * 1024 * 1024;
  309. options.max_open_files = 5000;
  310. options.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords;
  311. options.compaction_pri = CompactionPri::kByCompensatedSize;
  312. return options;
  313. }
  314. Options DBTestBase::GetOptions(
  315. int option_config, const Options& default_options,
  316. const anon::OptionsOverride& options_override) const {
  317. // this redundant copy is to minimize code change w/o having lint error.
  318. Options options = default_options;
  319. BlockBasedTableOptions table_options;
  320. bool set_block_based_table_factory = true;
  321. #if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
  322. !defined(OS_AIX)
  323. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  324. "NewRandomAccessFile:O_DIRECT");
  325. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  326. "NewWritableFile:O_DIRECT");
  327. #endif
  328. bool can_allow_mmap = IsMemoryMappedAccessSupported();
  329. switch (option_config) {
  330. #ifndef ROCKSDB_LITE
  331. case kHashSkipList:
  332. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  333. options.memtable_factory.reset(NewHashSkipListRepFactory(16));
  334. options.allow_concurrent_memtable_write = false;
  335. options.unordered_write = false;
  336. break;
  337. case kPlainTableFirstBytePrefix:
  338. options.table_factory.reset(new PlainTableFactory());
  339. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  340. options.allow_mmap_reads = can_allow_mmap;
  341. options.max_sequential_skip_in_iterations = 999999;
  342. set_block_based_table_factory = false;
  343. break;
  344. case kPlainTableCappedPrefix:
  345. options.table_factory.reset(new PlainTableFactory());
  346. options.prefix_extractor.reset(NewCappedPrefixTransform(8));
  347. options.allow_mmap_reads = can_allow_mmap;
  348. options.max_sequential_skip_in_iterations = 999999;
  349. set_block_based_table_factory = false;
  350. break;
  351. case kPlainTableCappedPrefixNonMmap:
  352. options.table_factory.reset(new PlainTableFactory());
  353. options.prefix_extractor.reset(NewCappedPrefixTransform(8));
  354. options.allow_mmap_reads = false;
  355. options.max_sequential_skip_in_iterations = 999999;
  356. set_block_based_table_factory = false;
  357. break;
  358. case kPlainTableAllBytesPrefix:
  359. options.table_factory.reset(new PlainTableFactory());
  360. options.prefix_extractor.reset(NewNoopTransform());
  361. options.allow_mmap_reads = can_allow_mmap;
  362. options.max_sequential_skip_in_iterations = 999999;
  363. set_block_based_table_factory = false;
  364. break;
  365. case kVectorRep:
  366. options.memtable_factory.reset(new VectorRepFactory(100));
  367. options.allow_concurrent_memtable_write = false;
  368. options.unordered_write = false;
  369. break;
  370. case kHashLinkList:
  371. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  372. options.memtable_factory.reset(
  373. NewHashLinkListRepFactory(4, 0, 3, true, 4));
  374. options.allow_concurrent_memtable_write = false;
  375. options.unordered_write = false;
  376. break;
  377. case kDirectIO: {
  378. options.use_direct_reads = true;
  379. options.use_direct_io_for_flush_and_compaction = true;
  380. options.compaction_readahead_size = 2 * 1024 * 1024;
  381. #if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
  382. !defined(OS_AIX) && !defined(OS_OPENBSD)
  383. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  384. "NewWritableFile:O_DIRECT", [&](void* arg) {
  385. int* val = static_cast<int*>(arg);
  386. *val &= ~O_DIRECT;
  387. });
  388. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  389. "NewRandomAccessFile:O_DIRECT", [&](void* arg) {
  390. int* val = static_cast<int*>(arg);
  391. *val &= ~O_DIRECT;
  392. });
  393. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  394. #endif
  395. break;
  396. }
  397. #endif // ROCKSDB_LITE
  398. case kMergePut:
  399. options.merge_operator = MergeOperators::CreatePutOperator();
  400. break;
  401. case kFilter:
  402. table_options.filter_policy.reset(NewBloomFilterPolicy(10, true));
  403. break;
  404. case kFullFilterWithNewTableReaderForCompactions:
  405. table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
  406. options.new_table_reader_for_compaction_inputs = true;
  407. options.compaction_readahead_size = 10 * 1024 * 1024;
  408. break;
  409. case kPartitionedFilterWithNewTableReaderForCompactions:
  410. table_options.filter_policy.reset(NewBloomFilterPolicy(10, false));
  411. table_options.partition_filters = true;
  412. table_options.index_type =
  413. BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch;
  414. options.new_table_reader_for_compaction_inputs = true;
  415. options.compaction_readahead_size = 10 * 1024 * 1024;
  416. break;
  417. case kUncompressed:
  418. options.compression = kNoCompression;
  419. break;
  420. case kNumLevel_3:
  421. options.num_levels = 3;
  422. break;
  423. case kDBLogDir:
  424. options.db_log_dir = alternative_db_log_dir_;
  425. break;
  426. case kWalDirAndMmapReads:
  427. options.wal_dir = alternative_wal_dir_;
  428. // mmap reads should be orthogonal to WalDir setting, so we piggyback to
  429. // this option config to test mmap reads as well
  430. options.allow_mmap_reads = can_allow_mmap;
  431. break;
  432. case kManifestFileSize:
  433. options.max_manifest_file_size = 50; // 50 bytes
  434. break;
  435. case kPerfOptions:
  436. options.soft_rate_limit = 2.0;
  437. options.delayed_write_rate = 8 * 1024 * 1024;
  438. options.report_bg_io_stats = true;
  439. // TODO(3.13) -- test more options
  440. break;
  441. case kUniversalCompaction:
  442. options.compaction_style = kCompactionStyleUniversal;
  443. options.num_levels = 1;
  444. break;
  445. case kUniversalCompactionMultiLevel:
  446. options.compaction_style = kCompactionStyleUniversal;
  447. options.num_levels = 8;
  448. break;
  449. case kCompressedBlockCache:
  450. options.allow_mmap_writes = can_allow_mmap;
  451. table_options.block_cache_compressed = NewLRUCache(8 * 1024 * 1024);
  452. break;
  453. case kInfiniteMaxOpenFiles:
  454. options.max_open_files = -1;
  455. break;
  456. case kxxHashChecksum: {
  457. table_options.checksum = kxxHash;
  458. break;
  459. }
  460. case kxxHash64Checksum: {
  461. table_options.checksum = kxxHash64;
  462. break;
  463. }
  464. case kFIFOCompaction: {
  465. options.compaction_style = kCompactionStyleFIFO;
  466. break;
  467. }
  468. case kBlockBasedTableWithPrefixHashIndex: {
  469. table_options.index_type = BlockBasedTableOptions::kHashSearch;
  470. options.prefix_extractor.reset(NewFixedPrefixTransform(1));
  471. break;
  472. }
  473. case kBlockBasedTableWithWholeKeyHashIndex: {
  474. table_options.index_type = BlockBasedTableOptions::kHashSearch;
  475. options.prefix_extractor.reset(NewNoopTransform());
  476. break;
  477. }
  478. case kBlockBasedTableWithPartitionedIndex: {
  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 kOptimizeFiltersForHits: {
  500. options.optimize_filters_for_hits = true;
  501. set_block_based_table_factory = true;
  502. break;
  503. }
  504. case kRowCache: {
  505. options.row_cache = NewLRUCache(1024 * 1024);
  506. break;
  507. }
  508. case kRecycleLogFiles: {
  509. options.recycle_log_file_num = 2;
  510. break;
  511. }
  512. case kLevelSubcompactions: {
  513. options.max_subcompactions = 4;
  514. break;
  515. }
  516. case kUniversalSubcompactions: {
  517. options.compaction_style = kCompactionStyleUniversal;
  518. options.num_levels = 8;
  519. options.max_subcompactions = 4;
  520. break;
  521. }
  522. case kConcurrentSkipList: {
  523. options.allow_concurrent_memtable_write = true;
  524. options.enable_write_thread_adaptive_yield = true;
  525. break;
  526. }
  527. case kPipelinedWrite: {
  528. options.enable_pipelined_write = true;
  529. break;
  530. }
  531. case kConcurrentWALWrites: {
  532. // This options optimize 2PC commit path
  533. options.two_write_queues = true;
  534. options.manual_wal_flush = true;
  535. break;
  536. }
  537. case kUnorderedWrite: {
  538. options.allow_concurrent_memtable_write = false;
  539. options.unordered_write = false;
  540. break;
  541. }
  542. default:
  543. break;
  544. }
  545. if (options_override.filter_policy) {
  546. table_options.filter_policy = options_override.filter_policy;
  547. table_options.partition_filters = options_override.partition_filters;
  548. table_options.metadata_block_size = options_override.metadata_block_size;
  549. }
  550. if (set_block_based_table_factory) {
  551. options.table_factory.reset(NewBlockBasedTableFactory(table_options));
  552. }
  553. options.env = env_;
  554. options.create_if_missing = true;
  555. options.fail_if_options_file_error = true;
  556. return options;
  557. }
  558. void DBTestBase::CreateColumnFamilies(const std::vector<std::string>& cfs,
  559. const Options& options) {
  560. ColumnFamilyOptions cf_opts(options);
  561. size_t cfi = handles_.size();
  562. handles_.resize(cfi + cfs.size());
  563. for (auto cf : cfs) {
  564. Status s = db_->CreateColumnFamily(cf_opts, cf, &handles_[cfi++]);
  565. ASSERT_OK(s);
  566. }
  567. }
  568. void DBTestBase::CreateAndReopenWithCF(const std::vector<std::string>& cfs,
  569. const Options& options) {
  570. CreateColumnFamilies(cfs, options);
  571. std::vector<std::string> cfs_plus_default = cfs;
  572. cfs_plus_default.insert(cfs_plus_default.begin(), kDefaultColumnFamilyName);
  573. ReopenWithColumnFamilies(cfs_plus_default, options);
  574. }
  575. void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
  576. const std::vector<Options>& options) {
  577. ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
  578. }
  579. void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
  580. const Options& options) {
  581. ASSERT_OK(TryReopenWithColumnFamilies(cfs, options));
  582. }
  583. Status DBTestBase::TryReopenWithColumnFamilies(
  584. const std::vector<std::string>& cfs, const std::vector<Options>& options) {
  585. Close();
  586. EXPECT_EQ(cfs.size(), options.size());
  587. std::vector<ColumnFamilyDescriptor> column_families;
  588. for (size_t i = 0; i < cfs.size(); ++i) {
  589. column_families.push_back(ColumnFamilyDescriptor(cfs[i], options[i]));
  590. }
  591. DBOptions db_opts = DBOptions(options[0]);
  592. last_options_ = options[0];
  593. return DB::Open(db_opts, dbname_, column_families, &handles_, &db_);
  594. }
  595. Status DBTestBase::TryReopenWithColumnFamilies(
  596. const std::vector<std::string>& cfs, const Options& options) {
  597. Close();
  598. std::vector<Options> v_opts(cfs.size(), options);
  599. return TryReopenWithColumnFamilies(cfs, v_opts);
  600. }
  601. void DBTestBase::Reopen(const Options& options) {
  602. ASSERT_OK(TryReopen(options));
  603. }
  604. void DBTestBase::Close() {
  605. for (auto h : handles_) {
  606. db_->DestroyColumnFamilyHandle(h);
  607. }
  608. handles_.clear();
  609. delete db_;
  610. db_ = nullptr;
  611. }
  612. void DBTestBase::DestroyAndReopen(const Options& options) {
  613. // Destroy using last options
  614. Destroy(last_options_);
  615. ASSERT_OK(TryReopen(options));
  616. }
  617. void DBTestBase::Destroy(const Options& options, bool delete_cf_paths) {
  618. std::vector<ColumnFamilyDescriptor> column_families;
  619. if (delete_cf_paths) {
  620. for (size_t i = 0; i < handles_.size(); ++i) {
  621. ColumnFamilyDescriptor cfdescriptor;
  622. handles_[i]->GetDescriptor(&cfdescriptor);
  623. column_families.push_back(cfdescriptor);
  624. }
  625. }
  626. Close();
  627. ASSERT_OK(DestroyDB(dbname_, options, column_families));
  628. }
  629. Status DBTestBase::ReadOnlyReopen(const Options& options) {
  630. return DB::OpenForReadOnly(options, dbname_, &db_);
  631. }
  632. Status DBTestBase::TryReopen(const Options& options) {
  633. Close();
  634. last_options_.table_factory.reset();
  635. // Note: operator= is an unsafe approach here since it destructs
  636. // std::shared_ptr in the same order of their creation, in contrast to
  637. // destructors which destructs them in the opposite order of creation. One
  638. // particular problme is that the cache destructor might invoke callback
  639. // functions that use Option members such as statistics. To work around this
  640. // problem, we manually call destructor of table_facotry which eventually
  641. // clears the block cache.
  642. last_options_ = options;
  643. return DB::Open(options, dbname_, &db_);
  644. }
  645. bool DBTestBase::IsDirectIOSupported() {
  646. return test::IsDirectIOSupported(env_, dbname_);
  647. }
  648. bool DBTestBase::IsMemoryMappedAccessSupported() const {
  649. return (!encrypted_env_);
  650. }
  651. Status DBTestBase::Flush(int cf) {
  652. if (cf == 0) {
  653. return db_->Flush(FlushOptions());
  654. } else {
  655. return db_->Flush(FlushOptions(), handles_[cf]);
  656. }
  657. }
  658. Status DBTestBase::Flush(const std::vector<int>& cf_ids) {
  659. std::vector<ColumnFamilyHandle*> cfhs;
  660. std::for_each(cf_ids.begin(), cf_ids.end(),
  661. [&cfhs, this](int id) { cfhs.emplace_back(handles_[id]); });
  662. return db_->Flush(FlushOptions(), cfhs);
  663. }
  664. Status DBTestBase::Put(const Slice& k, const Slice& v, WriteOptions wo) {
  665. if (kMergePut == option_config_) {
  666. return db_->Merge(wo, k, v);
  667. } else {
  668. return db_->Put(wo, k, v);
  669. }
  670. }
  671. Status DBTestBase::Put(int cf, const Slice& k, const Slice& v,
  672. WriteOptions wo) {
  673. if (kMergePut == option_config_) {
  674. return db_->Merge(wo, handles_[cf], k, v);
  675. } else {
  676. return db_->Put(wo, handles_[cf], k, v);
  677. }
  678. }
  679. Status DBTestBase::Merge(const Slice& k, const Slice& v, WriteOptions wo) {
  680. return db_->Merge(wo, k, v);
  681. }
  682. Status DBTestBase::Merge(int cf, const Slice& k, const Slice& v,
  683. WriteOptions wo) {
  684. return db_->Merge(wo, handles_[cf], k, v);
  685. }
  686. Status DBTestBase::Delete(const std::string& k) {
  687. return db_->Delete(WriteOptions(), k);
  688. }
  689. Status DBTestBase::Delete(int cf, const std::string& k) {
  690. return db_->Delete(WriteOptions(), handles_[cf], k);
  691. }
  692. Status DBTestBase::SingleDelete(const std::string& k) {
  693. return db_->SingleDelete(WriteOptions(), k);
  694. }
  695. Status DBTestBase::SingleDelete(int cf, const std::string& k) {
  696. return db_->SingleDelete(WriteOptions(), handles_[cf], k);
  697. }
  698. bool DBTestBase::SetPreserveDeletesSequenceNumber(SequenceNumber sn) {
  699. return db_->SetPreserveDeletesSequenceNumber(sn);
  700. }
  701. std::string DBTestBase::Get(const std::string& k, const Snapshot* snapshot) {
  702. ReadOptions options;
  703. options.verify_checksums = true;
  704. options.snapshot = snapshot;
  705. std::string result;
  706. Status s = db_->Get(options, k, &result);
  707. if (s.IsNotFound()) {
  708. result = "NOT_FOUND";
  709. } else if (!s.ok()) {
  710. result = s.ToString();
  711. }
  712. return result;
  713. }
  714. std::string DBTestBase::Get(int cf, const std::string& k,
  715. const Snapshot* snapshot) {
  716. ReadOptions options;
  717. options.verify_checksums = true;
  718. options.snapshot = snapshot;
  719. std::string result;
  720. Status s = db_->Get(options, handles_[cf], k, &result);
  721. if (s.IsNotFound()) {
  722. result = "NOT_FOUND";
  723. } else if (!s.ok()) {
  724. result = s.ToString();
  725. }
  726. return result;
  727. }
  728. std::vector<std::string> DBTestBase::MultiGet(std::vector<int> cfs,
  729. const std::vector<std::string>& k,
  730. const Snapshot* snapshot,
  731. const bool batched) {
  732. ReadOptions options;
  733. options.verify_checksums = true;
  734. options.snapshot = snapshot;
  735. std::vector<ColumnFamilyHandle*> handles;
  736. std::vector<Slice> keys;
  737. std::vector<std::string> result;
  738. for (unsigned int i = 0; i < cfs.size(); ++i) {
  739. handles.push_back(handles_[cfs[i]]);
  740. keys.push_back(k[i]);
  741. }
  742. std::vector<Status> s;
  743. if (!batched) {
  744. s = db_->MultiGet(options, handles, keys, &result);
  745. for (unsigned int i = 0; i < s.size(); ++i) {
  746. if (s[i].IsNotFound()) {
  747. result[i] = "NOT_FOUND";
  748. } else if (!s[i].ok()) {
  749. result[i] = s[i].ToString();
  750. }
  751. }
  752. } else {
  753. std::vector<PinnableSlice> pin_values(cfs.size());
  754. result.resize(cfs.size());
  755. s.resize(cfs.size());
  756. db_->MultiGet(options, cfs.size(), handles.data(), keys.data(),
  757. pin_values.data(), s.data());
  758. for (unsigned int i = 0; i < s.size(); ++i) {
  759. if (s[i].IsNotFound()) {
  760. result[i] = "NOT_FOUND";
  761. } else if (!s[i].ok()) {
  762. result[i] = s[i].ToString();
  763. } else {
  764. result[i].assign(pin_values[i].data(), pin_values[i].size());
  765. }
  766. }
  767. }
  768. return result;
  769. }
  770. std::vector<std::string> DBTestBase::MultiGet(const std::vector<std::string>& k,
  771. const Snapshot* snapshot) {
  772. ReadOptions options;
  773. options.verify_checksums = true;
  774. options.snapshot = snapshot;
  775. std::vector<Slice> keys;
  776. std::vector<std::string> result;
  777. std::vector<Status> statuses(k.size());
  778. std::vector<PinnableSlice> pin_values(k.size());
  779. for (unsigned int i = 0; i < k.size(); ++i) {
  780. keys.push_back(k[i]);
  781. }
  782. db_->MultiGet(options, dbfull()->DefaultColumnFamily(), keys.size(),
  783. keys.data(), pin_values.data(), statuses.data());
  784. result.resize(k.size());
  785. for (auto iter = result.begin(); iter != result.end(); ++iter) {
  786. iter->assign(pin_values[iter - result.begin()].data(),
  787. pin_values[iter - result.begin()].size());
  788. }
  789. for (unsigned int i = 0; i < statuses.size(); ++i) {
  790. if (statuses[i].IsNotFound()) {
  791. result[i] = "NOT_FOUND";
  792. }
  793. }
  794. return result;
  795. }
  796. Status DBTestBase::Get(const std::string& k, PinnableSlice* v) {
  797. ReadOptions options;
  798. options.verify_checksums = true;
  799. Status s = dbfull()->Get(options, dbfull()->DefaultColumnFamily(), k, v);
  800. return s;
  801. }
  802. uint64_t DBTestBase::GetNumSnapshots() {
  803. uint64_t int_num;
  804. EXPECT_TRUE(dbfull()->GetIntProperty("rocksdb.num-snapshots", &int_num));
  805. return int_num;
  806. }
  807. uint64_t DBTestBase::GetTimeOldestSnapshots() {
  808. uint64_t int_num;
  809. EXPECT_TRUE(
  810. dbfull()->GetIntProperty("rocksdb.oldest-snapshot-time", &int_num));
  811. return int_num;
  812. }
  813. uint64_t DBTestBase::GetSequenceOldestSnapshots() {
  814. uint64_t int_num;
  815. EXPECT_TRUE(
  816. dbfull()->GetIntProperty("rocksdb.oldest-snapshot-sequence", &int_num));
  817. return int_num;
  818. }
  819. // Return a string that contains all key,value pairs in order,
  820. // formatted like "(k1->v1)(k2->v2)".
  821. std::string DBTestBase::Contents(int cf) {
  822. std::vector<std::string> forward;
  823. std::string result;
  824. Iterator* iter = (cf == 0) ? db_->NewIterator(ReadOptions())
  825. : db_->NewIterator(ReadOptions(), handles_[cf]);
  826. for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
  827. std::string s = IterStatus(iter);
  828. result.push_back('(');
  829. result.append(s);
  830. result.push_back(')');
  831. forward.push_back(s);
  832. }
  833. // Check reverse iteration results are the reverse of forward results
  834. unsigned int matched = 0;
  835. for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
  836. EXPECT_LT(matched, forward.size());
  837. EXPECT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
  838. matched++;
  839. }
  840. EXPECT_EQ(matched, forward.size());
  841. delete iter;
  842. return result;
  843. }
  844. std::string DBTestBase::AllEntriesFor(const Slice& user_key, int cf) {
  845. Arena arena;
  846. auto options = CurrentOptions();
  847. InternalKeyComparator icmp(options.comparator);
  848. ReadRangeDelAggregator range_del_agg(&icmp,
  849. kMaxSequenceNumber /* upper_bound */);
  850. ScopedArenaIterator iter;
  851. if (cf == 0) {
  852. iter.set(dbfull()->NewInternalIterator(&arena, &range_del_agg,
  853. kMaxSequenceNumber));
  854. } else {
  855. iter.set(dbfull()->NewInternalIterator(&arena, &range_del_agg,
  856. kMaxSequenceNumber, handles_[cf]));
  857. }
  858. InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
  859. iter->Seek(target.Encode());
  860. std::string result;
  861. if (!iter->status().ok()) {
  862. result = iter->status().ToString();
  863. } else {
  864. result = "[ ";
  865. bool first = true;
  866. while (iter->Valid()) {
  867. ParsedInternalKey ikey(Slice(), 0, kTypeValue);
  868. if (!ParseInternalKey(iter->key(), &ikey)) {
  869. result += "CORRUPTED";
  870. } else {
  871. if (!last_options_.comparator->Equal(ikey.user_key, user_key)) {
  872. break;
  873. }
  874. if (!first) {
  875. result += ", ";
  876. }
  877. first = false;
  878. switch (ikey.type) {
  879. case kTypeValue:
  880. result += iter->value().ToString();
  881. break;
  882. case kTypeMerge:
  883. // keep it the same as kTypeValue for testing kMergePut
  884. result += iter->value().ToString();
  885. break;
  886. case kTypeDeletion:
  887. result += "DEL";
  888. break;
  889. case kTypeSingleDeletion:
  890. result += "SDEL";
  891. break;
  892. default:
  893. assert(false);
  894. break;
  895. }
  896. }
  897. iter->Next();
  898. }
  899. if (!first) {
  900. result += " ";
  901. }
  902. result += "]";
  903. }
  904. return result;
  905. }
  906. #ifndef ROCKSDB_LITE
  907. int DBTestBase::NumSortedRuns(int cf) {
  908. ColumnFamilyMetaData cf_meta;
  909. if (cf == 0) {
  910. db_->GetColumnFamilyMetaData(&cf_meta);
  911. } else {
  912. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  913. }
  914. int num_sr = static_cast<int>(cf_meta.levels[0].files.size());
  915. for (size_t i = 1U; i < cf_meta.levels.size(); i++) {
  916. if (cf_meta.levels[i].files.size() > 0) {
  917. num_sr++;
  918. }
  919. }
  920. return num_sr;
  921. }
  922. uint64_t DBTestBase::TotalSize(int cf) {
  923. ColumnFamilyMetaData cf_meta;
  924. if (cf == 0) {
  925. db_->GetColumnFamilyMetaData(&cf_meta);
  926. } else {
  927. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  928. }
  929. return cf_meta.size;
  930. }
  931. uint64_t DBTestBase::SizeAtLevel(int level) {
  932. std::vector<LiveFileMetaData> metadata;
  933. db_->GetLiveFilesMetaData(&metadata);
  934. uint64_t sum = 0;
  935. for (const auto& m : metadata) {
  936. if (m.level == level) {
  937. sum += m.size;
  938. }
  939. }
  940. return sum;
  941. }
  942. size_t DBTestBase::TotalLiveFiles(int cf) {
  943. ColumnFamilyMetaData cf_meta;
  944. if (cf == 0) {
  945. db_->GetColumnFamilyMetaData(&cf_meta);
  946. } else {
  947. db_->GetColumnFamilyMetaData(handles_[cf], &cf_meta);
  948. }
  949. size_t num_files = 0;
  950. for (auto& level : cf_meta.levels) {
  951. num_files += level.files.size();
  952. }
  953. return num_files;
  954. }
  955. size_t DBTestBase::CountLiveFiles() {
  956. std::vector<LiveFileMetaData> metadata;
  957. db_->GetLiveFilesMetaData(&metadata);
  958. return metadata.size();
  959. }
  960. int DBTestBase::NumTableFilesAtLevel(int level, int cf) {
  961. std::string property;
  962. if (cf == 0) {
  963. // default cfd
  964. EXPECT_TRUE(db_->GetProperty(
  965. "rocksdb.num-files-at-level" + NumberToString(level), &property));
  966. } else {
  967. EXPECT_TRUE(db_->GetProperty(
  968. handles_[cf], "rocksdb.num-files-at-level" + NumberToString(level),
  969. &property));
  970. }
  971. return atoi(property.c_str());
  972. }
  973. double DBTestBase::CompressionRatioAtLevel(int level, int cf) {
  974. std::string property;
  975. if (cf == 0) {
  976. // default cfd
  977. EXPECT_TRUE(db_->GetProperty(
  978. "rocksdb.compression-ratio-at-level" + NumberToString(level),
  979. &property));
  980. } else {
  981. EXPECT_TRUE(db_->GetProperty(
  982. handles_[cf],
  983. "rocksdb.compression-ratio-at-level" + NumberToString(level),
  984. &property));
  985. }
  986. return std::stod(property);
  987. }
  988. int DBTestBase::TotalTableFiles(int cf, int levels) {
  989. if (levels == -1) {
  990. levels = (cf == 0) ? db_->NumberLevels() : db_->NumberLevels(handles_[1]);
  991. }
  992. int result = 0;
  993. for (int level = 0; level < levels; level++) {
  994. result += NumTableFilesAtLevel(level, cf);
  995. }
  996. return result;
  997. }
  998. // Return spread of files per level
  999. std::string DBTestBase::FilesPerLevel(int cf) {
  1000. int num_levels =
  1001. (cf == 0) ? db_->NumberLevels() : db_->NumberLevels(handles_[1]);
  1002. std::string result;
  1003. size_t last_non_zero_offset = 0;
  1004. for (int level = 0; level < num_levels; level++) {
  1005. int f = NumTableFilesAtLevel(level, cf);
  1006. char buf[100];
  1007. snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f);
  1008. result += buf;
  1009. if (f > 0) {
  1010. last_non_zero_offset = result.size();
  1011. }
  1012. }
  1013. result.resize(last_non_zero_offset);
  1014. return result;
  1015. }
  1016. #endif // !ROCKSDB_LITE
  1017. size_t DBTestBase::CountFiles() {
  1018. std::vector<std::string> files;
  1019. env_->GetChildren(dbname_, &files);
  1020. std::vector<std::string> logfiles;
  1021. if (dbname_ != last_options_.wal_dir) {
  1022. env_->GetChildren(last_options_.wal_dir, &logfiles);
  1023. }
  1024. return files.size() + logfiles.size();
  1025. }
  1026. uint64_t DBTestBase::Size(const Slice& start, const Slice& limit, int cf) {
  1027. Range r(start, limit);
  1028. uint64_t size;
  1029. if (cf == 0) {
  1030. db_->GetApproximateSizes(&r, 1, &size);
  1031. } else {
  1032. db_->GetApproximateSizes(handles_[1], &r, 1, &size);
  1033. }
  1034. return size;
  1035. }
  1036. void DBTestBase::Compact(int cf, const Slice& start, const Slice& limit,
  1037. uint32_t target_path_id) {
  1038. CompactRangeOptions compact_options;
  1039. compact_options.target_path_id = target_path_id;
  1040. ASSERT_OK(db_->CompactRange(compact_options, handles_[cf], &start, &limit));
  1041. }
  1042. void DBTestBase::Compact(int cf, const Slice& start, const Slice& limit) {
  1043. ASSERT_OK(
  1044. db_->CompactRange(CompactRangeOptions(), handles_[cf], &start, &limit));
  1045. }
  1046. void DBTestBase::Compact(const Slice& start, const Slice& limit) {
  1047. ASSERT_OK(db_->CompactRange(CompactRangeOptions(), &start, &limit));
  1048. }
  1049. // Do n memtable compactions, each of which produces an sstable
  1050. // covering the range [small,large].
  1051. void DBTestBase::MakeTables(int n, const std::string& small,
  1052. const std::string& large, int cf) {
  1053. for (int i = 0; i < n; i++) {
  1054. ASSERT_OK(Put(cf, small, "begin"));
  1055. ASSERT_OK(Put(cf, large, "end"));
  1056. ASSERT_OK(Flush(cf));
  1057. MoveFilesToLevel(n - i - 1, cf);
  1058. }
  1059. }
  1060. // Prevent pushing of new sstables into deeper levels by adding
  1061. // tables that cover a specified range to all levels.
  1062. void DBTestBase::FillLevels(const std::string& smallest,
  1063. const std::string& largest, int cf) {
  1064. MakeTables(db_->NumberLevels(handles_[cf]), smallest, largest, cf);
  1065. }
  1066. void DBTestBase::MoveFilesToLevel(int level, int cf) {
  1067. for (int l = 0; l < level; ++l) {
  1068. if (cf > 0) {
  1069. dbfull()->TEST_CompactRange(l, nullptr, nullptr, handles_[cf]);
  1070. } else {
  1071. dbfull()->TEST_CompactRange(l, nullptr, nullptr);
  1072. }
  1073. }
  1074. }
  1075. #ifndef ROCKSDB_LITE
  1076. void DBTestBase::DumpFileCounts(const char* label) {
  1077. fprintf(stderr, "---\n%s:\n", label);
  1078. fprintf(stderr, "maxoverlap: %" PRIu64 "\n",
  1079. dbfull()->TEST_MaxNextLevelOverlappingBytes());
  1080. for (int level = 0; level < db_->NumberLevels(); level++) {
  1081. int num = NumTableFilesAtLevel(level);
  1082. if (num > 0) {
  1083. fprintf(stderr, " level %3d : %d files\n", level, num);
  1084. }
  1085. }
  1086. }
  1087. #endif // !ROCKSDB_LITE
  1088. std::string DBTestBase::DumpSSTableList() {
  1089. std::string property;
  1090. db_->GetProperty("rocksdb.sstables", &property);
  1091. return property;
  1092. }
  1093. void DBTestBase::GetSstFiles(Env* env, std::string path,
  1094. std::vector<std::string>* files) {
  1095. env->GetChildren(path, files);
  1096. files->erase(
  1097. std::remove_if(files->begin(), files->end(), [](std::string name) {
  1098. uint64_t number;
  1099. FileType type;
  1100. return !(ParseFileName(name, &number, &type) && type == kTableFile);
  1101. }), files->end());
  1102. }
  1103. int DBTestBase::GetSstFileCount(std::string path) {
  1104. std::vector<std::string> files;
  1105. DBTestBase::GetSstFiles(env_, path, &files);
  1106. return static_cast<int>(files.size());
  1107. }
  1108. // this will generate non-overlapping files since it keeps increasing key_idx
  1109. void DBTestBase::GenerateNewFile(int cf, Random* rnd, int* key_idx,
  1110. bool nowait) {
  1111. for (int i = 0; i < KNumKeysByGenerateNewFile; i++) {
  1112. ASSERT_OK(Put(cf, Key(*key_idx), RandomString(rnd, (i == 99) ? 1 : 990)));
  1113. (*key_idx)++;
  1114. }
  1115. if (!nowait) {
  1116. dbfull()->TEST_WaitForFlushMemTable();
  1117. dbfull()->TEST_WaitForCompact();
  1118. }
  1119. }
  1120. // this will generate non-overlapping files since it keeps increasing key_idx
  1121. void DBTestBase::GenerateNewFile(Random* rnd, int* key_idx, bool nowait) {
  1122. for (int i = 0; i < KNumKeysByGenerateNewFile; i++) {
  1123. ASSERT_OK(Put(Key(*key_idx), RandomString(rnd, (i == 99) ? 1 : 990)));
  1124. (*key_idx)++;
  1125. }
  1126. if (!nowait) {
  1127. dbfull()->TEST_WaitForFlushMemTable();
  1128. dbfull()->TEST_WaitForCompact();
  1129. }
  1130. }
  1131. const int DBTestBase::kNumKeysByGenerateNewRandomFile = 51;
  1132. void DBTestBase::GenerateNewRandomFile(Random* rnd, bool nowait) {
  1133. for (int i = 0; i < kNumKeysByGenerateNewRandomFile; i++) {
  1134. ASSERT_OK(Put("key" + RandomString(rnd, 7), RandomString(rnd, 2000)));
  1135. }
  1136. ASSERT_OK(Put("key" + RandomString(rnd, 7), RandomString(rnd, 200)));
  1137. if (!nowait) {
  1138. dbfull()->TEST_WaitForFlushMemTable();
  1139. dbfull()->TEST_WaitForCompact();
  1140. }
  1141. }
  1142. std::string DBTestBase::IterStatus(Iterator* iter) {
  1143. std::string result;
  1144. if (iter->Valid()) {
  1145. result = iter->key().ToString() + "->" + iter->value().ToString();
  1146. } else {
  1147. result = "(invalid)";
  1148. }
  1149. return result;
  1150. }
  1151. Options DBTestBase::OptionsForLogIterTest() {
  1152. Options options = CurrentOptions();
  1153. options.create_if_missing = true;
  1154. options.WAL_ttl_seconds = 1000;
  1155. return options;
  1156. }
  1157. std::string DBTestBase::DummyString(size_t len, char c) {
  1158. return std::string(len, c);
  1159. }
  1160. void DBTestBase::VerifyIterLast(std::string expected_key, int cf) {
  1161. Iterator* iter;
  1162. ReadOptions ro;
  1163. if (cf == 0) {
  1164. iter = db_->NewIterator(ro);
  1165. } else {
  1166. iter = db_->NewIterator(ro, handles_[cf]);
  1167. }
  1168. iter->SeekToLast();
  1169. ASSERT_EQ(IterStatus(iter), expected_key);
  1170. delete iter;
  1171. }
  1172. // Used to test InplaceUpdate
  1173. // If previous value is nullptr or delta is > than previous value,
  1174. // sets newValue with delta
  1175. // If previous value is not empty,
  1176. // updates previous value with 'b' string of previous value size - 1.
  1177. UpdateStatus DBTestBase::updateInPlaceSmallerSize(char* prevValue,
  1178. uint32_t* prevSize,
  1179. Slice delta,
  1180. std::string* newValue) {
  1181. if (prevValue == nullptr) {
  1182. *newValue = std::string(delta.size(), 'c');
  1183. return UpdateStatus::UPDATED;
  1184. } else {
  1185. *prevSize = *prevSize - 1;
  1186. std::string str_b = std::string(*prevSize, 'b');
  1187. memcpy(prevValue, str_b.c_str(), str_b.size());
  1188. return UpdateStatus::UPDATED_INPLACE;
  1189. }
  1190. }
  1191. UpdateStatus DBTestBase::updateInPlaceSmallerVarintSize(char* prevValue,
  1192. uint32_t* prevSize,
  1193. Slice delta,
  1194. std::string* newValue) {
  1195. if (prevValue == nullptr) {
  1196. *newValue = std::string(delta.size(), 'c');
  1197. return UpdateStatus::UPDATED;
  1198. } else {
  1199. *prevSize = 1;
  1200. std::string str_b = std::string(*prevSize, 'b');
  1201. memcpy(prevValue, str_b.c_str(), str_b.size());
  1202. return UpdateStatus::UPDATED_INPLACE;
  1203. }
  1204. }
  1205. UpdateStatus DBTestBase::updateInPlaceLargerSize(char* /*prevValue*/,
  1206. uint32_t* /*prevSize*/,
  1207. Slice delta,
  1208. std::string* newValue) {
  1209. *newValue = std::string(delta.size(), 'c');
  1210. return UpdateStatus::UPDATED;
  1211. }
  1212. UpdateStatus DBTestBase::updateInPlaceNoAction(char* /*prevValue*/,
  1213. uint32_t* /*prevSize*/,
  1214. Slice /*delta*/,
  1215. std::string* /*newValue*/) {
  1216. return UpdateStatus::UPDATE_FAILED;
  1217. }
  1218. // Utility method to test InplaceUpdate
  1219. void DBTestBase::validateNumberOfEntries(int numValues, int cf) {
  1220. Arena arena;
  1221. auto options = CurrentOptions();
  1222. InternalKeyComparator icmp(options.comparator);
  1223. ReadRangeDelAggregator range_del_agg(&icmp,
  1224. kMaxSequenceNumber /* upper_bound */);
  1225. // This should be defined after range_del_agg so that it destructs the
  1226. // assigned iterator before it range_del_agg is already destructed.
  1227. ScopedArenaIterator iter;
  1228. if (cf != 0) {
  1229. iter.set(dbfull()->NewInternalIterator(&arena, &range_del_agg,
  1230. kMaxSequenceNumber, handles_[cf]));
  1231. } else {
  1232. iter.set(dbfull()->NewInternalIterator(&arena, &range_del_agg,
  1233. kMaxSequenceNumber));
  1234. }
  1235. iter->SeekToFirst();
  1236. ASSERT_EQ(iter->status().ok(), true);
  1237. int seq = numValues;
  1238. while (iter->Valid()) {
  1239. ParsedInternalKey ikey;
  1240. ikey.clear();
  1241. ASSERT_EQ(ParseInternalKey(iter->key(), &ikey), true);
  1242. // checks sequence number for updates
  1243. ASSERT_EQ(ikey.sequence, (unsigned)seq--);
  1244. iter->Next();
  1245. }
  1246. ASSERT_EQ(0, seq);
  1247. }
  1248. void DBTestBase::CopyFile(const std::string& source,
  1249. const std::string& destination, uint64_t size) {
  1250. const EnvOptions soptions;
  1251. std::unique_ptr<SequentialFile> srcfile;
  1252. ASSERT_OK(env_->NewSequentialFile(source, &srcfile, soptions));
  1253. std::unique_ptr<WritableFile> destfile;
  1254. ASSERT_OK(env_->NewWritableFile(destination, &destfile, soptions));
  1255. if (size == 0) {
  1256. // default argument means copy everything
  1257. ASSERT_OK(env_->GetFileSize(source, &size));
  1258. }
  1259. char buffer[4096];
  1260. Slice slice;
  1261. while (size > 0) {
  1262. uint64_t one = std::min(uint64_t(sizeof(buffer)), size);
  1263. ASSERT_OK(srcfile->Read(one, &slice, buffer));
  1264. ASSERT_OK(destfile->Append(slice));
  1265. size -= slice.size();
  1266. }
  1267. ASSERT_OK(destfile->Close());
  1268. }
  1269. std::unordered_map<std::string, uint64_t> DBTestBase::GetAllSSTFiles(
  1270. uint64_t* total_size) {
  1271. std::unordered_map<std::string, uint64_t> res;
  1272. if (total_size) {
  1273. *total_size = 0;
  1274. }
  1275. std::vector<std::string> files;
  1276. env_->GetChildren(dbname_, &files);
  1277. for (auto& file_name : files) {
  1278. uint64_t number;
  1279. FileType type;
  1280. std::string file_path = dbname_ + "/" + file_name;
  1281. if (ParseFileName(file_name, &number, &type) && type == kTableFile) {
  1282. uint64_t file_size = 0;
  1283. env_->GetFileSize(file_path, &file_size);
  1284. res[file_path] = file_size;
  1285. if (total_size) {
  1286. *total_size += file_size;
  1287. }
  1288. }
  1289. }
  1290. return res;
  1291. }
  1292. std::vector<std::uint64_t> DBTestBase::ListTableFiles(Env* env,
  1293. const std::string& path) {
  1294. std::vector<std::string> files;
  1295. std::vector<uint64_t> file_numbers;
  1296. env->GetChildren(path, &files);
  1297. uint64_t number;
  1298. FileType type;
  1299. for (size_t i = 0; i < files.size(); ++i) {
  1300. if (ParseFileName(files[i], &number, &type)) {
  1301. if (type == kTableFile) {
  1302. file_numbers.push_back(number);
  1303. }
  1304. }
  1305. }
  1306. return file_numbers;
  1307. }
  1308. void DBTestBase::VerifyDBFromMap(std::map<std::string, std::string> true_data,
  1309. size_t* total_reads_res, bool tailing_iter,
  1310. std::map<std::string, Status> status) {
  1311. size_t total_reads = 0;
  1312. for (auto& kv : true_data) {
  1313. Status s = status[kv.first];
  1314. if (s.ok()) {
  1315. ASSERT_EQ(Get(kv.first), kv.second);
  1316. } else {
  1317. std::string value;
  1318. ASSERT_EQ(s, db_->Get(ReadOptions(), kv.first, &value));
  1319. }
  1320. total_reads++;
  1321. }
  1322. // Normal Iterator
  1323. {
  1324. int iter_cnt = 0;
  1325. ReadOptions ro;
  1326. ro.total_order_seek = true;
  1327. Iterator* iter = db_->NewIterator(ro);
  1328. // Verify Iterator::Next()
  1329. iter_cnt = 0;
  1330. auto data_iter = true_data.begin();
  1331. Status s;
  1332. for (iter->SeekToFirst(); iter->Valid(); iter->Next(), data_iter++) {
  1333. ASSERT_EQ(iter->key().ToString(), data_iter->first);
  1334. Status current_status = status[data_iter->first];
  1335. if (!current_status.ok()) {
  1336. s = current_status;
  1337. }
  1338. ASSERT_EQ(iter->status(), s);
  1339. if (current_status.ok()) {
  1340. ASSERT_EQ(iter->value().ToString(), data_iter->second);
  1341. }
  1342. iter_cnt++;
  1343. total_reads++;
  1344. }
  1345. ASSERT_EQ(data_iter, true_data.end()) << iter_cnt << " / "
  1346. << true_data.size();
  1347. delete iter;
  1348. // Verify Iterator::Prev()
  1349. // Use a new iterator to make sure its status is clean.
  1350. iter = db_->NewIterator(ro);
  1351. iter_cnt = 0;
  1352. s = Status::OK();
  1353. auto data_rev = true_data.rbegin();
  1354. for (iter->SeekToLast(); iter->Valid(); iter->Prev(), data_rev++) {
  1355. ASSERT_EQ(iter->key().ToString(), data_rev->first);
  1356. Status current_status = status[data_rev->first];
  1357. if (!current_status.ok()) {
  1358. s = current_status;
  1359. }
  1360. ASSERT_EQ(iter->status(), s);
  1361. if (current_status.ok()) {
  1362. ASSERT_EQ(iter->value().ToString(), data_rev->second);
  1363. }
  1364. iter_cnt++;
  1365. total_reads++;
  1366. }
  1367. ASSERT_EQ(data_rev, true_data.rend()) << iter_cnt << " / "
  1368. << true_data.size();
  1369. // Verify Iterator::Seek()
  1370. for (auto kv : true_data) {
  1371. iter->Seek(kv.first);
  1372. ASSERT_EQ(kv.first, iter->key().ToString());
  1373. ASSERT_EQ(kv.second, iter->value().ToString());
  1374. total_reads++;
  1375. }
  1376. delete iter;
  1377. }
  1378. if (tailing_iter) {
  1379. #ifndef ROCKSDB_LITE
  1380. // Tailing iterator
  1381. int iter_cnt = 0;
  1382. ReadOptions ro;
  1383. ro.tailing = true;
  1384. ro.total_order_seek = true;
  1385. Iterator* iter = db_->NewIterator(ro);
  1386. // Verify ForwardIterator::Next()
  1387. iter_cnt = 0;
  1388. auto data_iter = true_data.begin();
  1389. for (iter->SeekToFirst(); iter->Valid(); iter->Next(), data_iter++) {
  1390. ASSERT_EQ(iter->key().ToString(), data_iter->first);
  1391. ASSERT_EQ(iter->value().ToString(), data_iter->second);
  1392. iter_cnt++;
  1393. total_reads++;
  1394. }
  1395. ASSERT_EQ(data_iter, true_data.end()) << iter_cnt << " / "
  1396. << true_data.size();
  1397. // Verify ForwardIterator::Seek()
  1398. for (auto kv : true_data) {
  1399. iter->Seek(kv.first);
  1400. ASSERT_EQ(kv.first, iter->key().ToString());
  1401. ASSERT_EQ(kv.second, iter->value().ToString());
  1402. total_reads++;
  1403. }
  1404. delete iter;
  1405. #endif // ROCKSDB_LITE
  1406. }
  1407. if (total_reads_res) {
  1408. *total_reads_res = total_reads;
  1409. }
  1410. }
  1411. void DBTestBase::VerifyDBInternal(
  1412. std::vector<std::pair<std::string, std::string>> true_data) {
  1413. Arena arena;
  1414. InternalKeyComparator icmp(last_options_.comparator);
  1415. ReadRangeDelAggregator range_del_agg(&icmp,
  1416. kMaxSequenceNumber /* upper_bound */);
  1417. auto iter =
  1418. dbfull()->NewInternalIterator(&arena, &range_del_agg, kMaxSequenceNumber);
  1419. iter->SeekToFirst();
  1420. for (auto p : true_data) {
  1421. ASSERT_TRUE(iter->Valid());
  1422. ParsedInternalKey ikey;
  1423. ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey));
  1424. ASSERT_EQ(p.first, ikey.user_key);
  1425. ASSERT_EQ(p.second, iter->value());
  1426. iter->Next();
  1427. };
  1428. ASSERT_FALSE(iter->Valid());
  1429. iter->~InternalIterator();
  1430. }
  1431. #ifndef ROCKSDB_LITE
  1432. uint64_t DBTestBase::GetNumberOfSstFilesForColumnFamily(
  1433. DB* db, std::string column_family_name) {
  1434. std::vector<LiveFileMetaData> metadata;
  1435. db->GetLiveFilesMetaData(&metadata);
  1436. uint64_t result = 0;
  1437. for (auto& fileMetadata : metadata) {
  1438. result += (fileMetadata.column_family_name == column_family_name);
  1439. }
  1440. return result;
  1441. }
  1442. #endif // ROCKSDB_LITE
  1443. } // namespace ROCKSDB_NAMESPACE