db_tailing_iter_test.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  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. // Introduction of SyncPoint effectively disabled building and running this test
  10. // in Release build.
  11. // which is a pity, it is a good test
  12. #include "db/db_test_util.h"
  13. #include "db/forward_iterator.h"
  14. #include "port/stack_trace.h"
  15. namespace {
  16. static bool enable_io_uring = true;
  17. extern "C" bool RocksDbIOUringEnable() { return enable_io_uring; }
  18. } // namespace
  19. namespace ROCKSDB_NAMESPACE {
  20. class DBTestTailingIterator : public DBTestBase,
  21. public ::testing::WithParamInterface<bool> {
  22. public:
  23. DBTestTailingIterator()
  24. : DBTestBase("db_tailing_iterator_test", /*env_do_fsync=*/true) {}
  25. };
  26. INSTANTIATE_TEST_CASE_P(DBTestTailingIterator, DBTestTailingIterator,
  27. ::testing::Bool());
  28. TEST_P(DBTestTailingIterator, TailingIteratorSingle) {
  29. ReadOptions read_options;
  30. read_options.tailing = true;
  31. if (GetParam()) {
  32. read_options.async_io = true;
  33. }
  34. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options));
  35. iter->SeekToFirst();
  36. ASSERT_TRUE(!iter->Valid());
  37. ASSERT_OK(iter->status());
  38. // add a record and check that iter can see it
  39. ASSERT_OK(db_->Put(WriteOptions(), "mirko", "fodor"));
  40. iter->SeekToFirst();
  41. ASSERT_TRUE(iter->Valid());
  42. ASSERT_EQ(iter->key().ToString(), "mirko");
  43. iter->Next();
  44. ASSERT_TRUE(!iter->Valid());
  45. ASSERT_OK(iter->status());
  46. }
  47. TEST_P(DBTestTailingIterator, TailingIteratorKeepAdding) {
  48. if (mem_env_ || encrypted_env_) {
  49. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  50. return;
  51. }
  52. std::unique_ptr<Env> env(
  53. new CompositeEnvWrapper(env_, FileSystem::Default()));
  54. Options options = CurrentOptions();
  55. options.env = env.get();
  56. CreateAndReopenWithCF({"pikachu"}, options);
  57. ReadOptions read_options;
  58. read_options.tailing = true;
  59. if (GetParam()) {
  60. read_options.async_io = true;
  61. }
  62. {
  63. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options, handles_[1]));
  64. ASSERT_OK(iter->status());
  65. std::string value(1024, 'a');
  66. const int num_records = 10000;
  67. for (int i = 0; i < num_records; ++i) {
  68. char buf[32];
  69. snprintf(buf, sizeof(buf), "%016d", i);
  70. Slice key(buf, 16);
  71. ASSERT_OK(Put(1, key, value));
  72. iter->Seek(key);
  73. ASSERT_TRUE(iter->Valid());
  74. ASSERT_EQ(iter->key().compare(key), 0);
  75. }
  76. }
  77. Close();
  78. }
  79. TEST_P(DBTestTailingIterator, TailingIteratorSeekToNext) {
  80. if (mem_env_ || encrypted_env_) {
  81. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  82. return;
  83. }
  84. std::unique_ptr<Env> env(
  85. new CompositeEnvWrapper(env_, FileSystem::Default()));
  86. Options options = CurrentOptions();
  87. options.env = env.get();
  88. CreateAndReopenWithCF({"pikachu"}, options);
  89. ReadOptions read_options;
  90. read_options.tailing = true;
  91. if (GetParam()) {
  92. read_options.async_io = true;
  93. }
  94. {
  95. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options, handles_[1]));
  96. ASSERT_OK(iter->status());
  97. std::unique_ptr<Iterator> itern(
  98. db_->NewIterator(read_options, handles_[1]));
  99. ASSERT_OK(itern->status());
  100. std::string value(1024, 'a');
  101. const int num_records = 1000;
  102. for (int i = 1; i < num_records; ++i) {
  103. char buf1[32];
  104. char buf2[32];
  105. snprintf(buf1, sizeof(buf1), "00a0%016d", i * 5);
  106. Slice key(buf1, 20);
  107. ASSERT_OK(Put(1, key, value));
  108. if (i % 100 == 99) {
  109. ASSERT_OK(Flush(1));
  110. }
  111. snprintf(buf2, sizeof(buf2), "00a0%016d", i * 5 - 2);
  112. Slice target(buf2, 20);
  113. iter->Seek(target);
  114. ASSERT_TRUE(iter->Valid());
  115. ASSERT_EQ(iter->key().compare(key), 0);
  116. if (i == 1) {
  117. itern->SeekToFirst();
  118. } else {
  119. itern->Next();
  120. }
  121. ASSERT_TRUE(itern->Valid());
  122. ASSERT_EQ(itern->key().compare(key), 0);
  123. }
  124. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  125. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  126. for (int i = 2 * num_records; i > 0; --i) {
  127. char buf1[32];
  128. char buf2[32];
  129. snprintf(buf1, sizeof(buf1), "00a0%016d", i * 5);
  130. Slice key(buf1, 20);
  131. ASSERT_OK(Put(1, key, value));
  132. if (i % 100 == 99) {
  133. ASSERT_OK(Flush(1));
  134. }
  135. snprintf(buf2, sizeof(buf2), "00a0%016d", i * 5 - 2);
  136. Slice target(buf2, 20);
  137. iter->Seek(target);
  138. ASSERT_TRUE(iter->Valid());
  139. ASSERT_EQ(iter->key().compare(key), 0);
  140. }
  141. }
  142. Close();
  143. }
  144. TEST_P(DBTestTailingIterator, TailingIteratorTrimSeekToNext) {
  145. if (mem_env_ || encrypted_env_) {
  146. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  147. return;
  148. }
  149. const uint64_t k150KB = 150 * 1024;
  150. std::unique_ptr<Env> env(
  151. new CompositeEnvWrapper(env_, FileSystem::Default()));
  152. Options options;
  153. options.env = env.get();
  154. options.write_buffer_size = k150KB;
  155. options.max_write_buffer_number = 3;
  156. options.min_write_buffer_number_to_merge = 2;
  157. options.env = env_;
  158. CreateAndReopenWithCF({"pikachu"}, options);
  159. ReadOptions read_options;
  160. read_options.tailing = true;
  161. if (GetParam()) {
  162. read_options.async_io = true;
  163. }
  164. int num_iters, deleted_iters;
  165. char bufe[32];
  166. snprintf(bufe, sizeof(bufe), "00b0%016d", 0);
  167. Slice keyu(bufe, 20);
  168. read_options.iterate_upper_bound = &keyu;
  169. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options, handles_[1]));
  170. ASSERT_OK(iter->status());
  171. std::unique_ptr<Iterator> itern(db_->NewIterator(read_options, handles_[1]));
  172. ASSERT_OK(itern->status());
  173. std::unique_ptr<Iterator> iterh(db_->NewIterator(read_options, handles_[1]));
  174. ASSERT_OK(iterh->status());
  175. std::string value(1024, 'a');
  176. bool file_iters_deleted = false;
  177. bool file_iters_renewed_null = false;
  178. bool file_iters_renewed_copy = false;
  179. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  180. "ForwardIterator::SeekInternal:Return", [&](void* arg) {
  181. ForwardIterator* fiter = static_cast<ForwardIterator*>(arg);
  182. ASSERT_TRUE(!file_iters_deleted ||
  183. fiter->TEST_CheckDeletedIters(&deleted_iters, &num_iters));
  184. });
  185. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  186. "ForwardIterator::Next:Return", [&](void* arg) {
  187. ForwardIterator* fiter = static_cast<ForwardIterator*>(arg);
  188. ASSERT_TRUE(!file_iters_deleted ||
  189. fiter->TEST_CheckDeletedIters(&deleted_iters, &num_iters));
  190. });
  191. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  192. "ForwardIterator::RenewIterators:Null",
  193. [&](void* /*arg*/) { file_iters_renewed_null = true; });
  194. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  195. "ForwardIterator::RenewIterators:Copy",
  196. [&](void* /*arg*/) { file_iters_renewed_copy = true; });
  197. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  198. const int num_records = 1000;
  199. for (int i = 1; i < num_records; ++i) {
  200. char buf1[32];
  201. char buf2[32];
  202. char buf3[32];
  203. char buf4[32];
  204. snprintf(buf1, sizeof(buf1), "00a0%016d", i * 5);
  205. snprintf(buf3, sizeof(buf3), "00b0%016d", i * 5);
  206. Slice key(buf1, 20);
  207. ASSERT_OK(Put(1, key, value));
  208. Slice keyn(buf3, 20);
  209. ASSERT_OK(Put(1, keyn, value));
  210. if (i % 100 == 99) {
  211. ASSERT_OK(Flush(1));
  212. ASSERT_OK(dbfull()->TEST_WaitForCompact());
  213. if (i == 299) {
  214. file_iters_deleted = true;
  215. }
  216. snprintf(buf4, sizeof(buf4), "00a0%016d", i * 5 / 2);
  217. Slice target(buf4, 20);
  218. iterh->Seek(target);
  219. ASSERT_TRUE(iter->Valid());
  220. for (int j = (i + 1) * 5 / 2; j < i * 5; j += 5) {
  221. iterh->Next();
  222. ASSERT_TRUE(iterh->Valid());
  223. }
  224. if (i == 299) {
  225. file_iters_deleted = false;
  226. }
  227. }
  228. file_iters_deleted = true;
  229. snprintf(buf2, sizeof(buf2), "00a0%016d", i * 5 - 2);
  230. Slice target(buf2, 20);
  231. iter->Seek(target);
  232. ASSERT_TRUE(iter->Valid());
  233. ASSERT_EQ(iter->key().compare(key), 0);
  234. ASSERT_LE(num_iters, 1);
  235. if (i == 1) {
  236. itern->SeekToFirst();
  237. } else {
  238. itern->Next();
  239. }
  240. ASSERT_TRUE(itern->Valid());
  241. ASSERT_EQ(itern->key().compare(key), 0);
  242. ASSERT_LE(num_iters, 1);
  243. file_iters_deleted = false;
  244. }
  245. ASSERT_TRUE(file_iters_renewed_null);
  246. ASSERT_TRUE(file_iters_renewed_copy);
  247. iter = nullptr;
  248. itern = nullptr;
  249. iterh = nullptr;
  250. BlockBasedTableOptions table_options;
  251. table_options.no_block_cache = true;
  252. options.table_factory.reset(NewBlockBasedTableFactory(table_options));
  253. ReopenWithColumnFamilies({"default", "pikachu"}, options);
  254. read_options.read_tier = kBlockCacheTier;
  255. std::unique_ptr<Iterator> iteri(db_->NewIterator(read_options, handles_[1]));
  256. ASSERT_OK(iteri->status());
  257. char buf5[32];
  258. snprintf(buf5, sizeof(buf5), "00a0%016d", (num_records / 2) * 5 - 2);
  259. Slice target1(buf5, 20);
  260. iteri->Seek(target1);
  261. ASSERT_TRUE(iteri->status().IsIncomplete());
  262. iteri = nullptr;
  263. read_options.read_tier = kReadAllTier;
  264. options.table_factory.reset(NewBlockBasedTableFactory());
  265. ReopenWithColumnFamilies({"default", "pikachu"}, options);
  266. iter.reset(db_->NewIterator(read_options, handles_[1]));
  267. ASSERT_OK(iter->status());
  268. for (int i = 2 * num_records; i > 0; --i) {
  269. char buf1[32];
  270. char buf2[32];
  271. snprintf(buf1, sizeof(buf1), "00a0%016d", i * 5);
  272. Slice key(buf1, 20);
  273. ASSERT_OK(Put(1, key, value));
  274. if (i % 100 == 99) {
  275. ASSERT_OK(Flush(1));
  276. }
  277. snprintf(buf2, sizeof(buf2), "00a0%016d", i * 5 - 2);
  278. Slice target(buf2, 20);
  279. iter->Seek(target);
  280. ASSERT_TRUE(iter->Valid());
  281. ASSERT_EQ(iter->key().compare(key), 0);
  282. }
  283. }
  284. TEST_P(DBTestTailingIterator, TailingIteratorDeletes) {
  285. if (mem_env_ || encrypted_env_) {
  286. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  287. return;
  288. }
  289. std::unique_ptr<Env> env(
  290. new CompositeEnvWrapper(env_, FileSystem::Default()));
  291. Options options = CurrentOptions();
  292. options.env = env.get();
  293. CreateAndReopenWithCF({"pikachu"}, options);
  294. ReadOptions read_options;
  295. read_options.tailing = true;
  296. if (GetParam()) {
  297. read_options.async_io = true;
  298. }
  299. {
  300. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options, handles_[1]));
  301. ASSERT_OK(iter->status());
  302. // write a single record, read it using the iterator, then delete it
  303. ASSERT_OK(Put(1, "0test", "test"));
  304. iter->SeekToFirst();
  305. ASSERT_TRUE(iter->Valid());
  306. ASSERT_EQ(iter->key().ToString(), "0test");
  307. ASSERT_OK(Delete(1, "0test"));
  308. // write many more records
  309. const int num_records = 10000;
  310. std::string value(1024, 'A');
  311. for (int i = 0; i < num_records; ++i) {
  312. char buf[32];
  313. snprintf(buf, sizeof(buf), "1%015d", i);
  314. Slice key(buf, 16);
  315. ASSERT_OK(Put(1, key, value));
  316. }
  317. // force a flush to make sure that no records are read from memtable
  318. ASSERT_OK(Flush(1));
  319. // skip "0test"
  320. iter->Next();
  321. // make sure we can read all new records using the existing iterator
  322. int count = 0;
  323. for (; iter->Valid(); iter->Next(), ++count) {
  324. ;
  325. }
  326. ASSERT_OK(iter->status());
  327. ASSERT_EQ(count, num_records);
  328. }
  329. Close();
  330. }
  331. TEST_P(DBTestTailingIterator, TailingIteratorPrefixSeek) {
  332. if (mem_env_ || encrypted_env_) {
  333. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  334. return;
  335. }
  336. ReadOptions read_options;
  337. read_options.tailing = true;
  338. if (GetParam()) {
  339. read_options.async_io = true;
  340. }
  341. std::unique_ptr<Env> env(
  342. new CompositeEnvWrapper(env_, FileSystem::Default()));
  343. Options options = CurrentOptions();
  344. options.env = env.get();
  345. options.create_if_missing = true;
  346. options.disable_auto_compactions = true;
  347. options.prefix_extractor.reset(NewFixedPrefixTransform(2));
  348. options.memtable_factory.reset(NewHashSkipListRepFactory(16));
  349. options.allow_concurrent_memtable_write = false;
  350. DestroyAndReopen(options);
  351. CreateAndReopenWithCF({"pikachu"}, options);
  352. {
  353. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options, handles_[1]));
  354. ASSERT_OK(iter->status());
  355. ASSERT_OK(Put(1, "0101", "test"));
  356. ASSERT_OK(Flush(1));
  357. ASSERT_OK(Put(1, "0202", "test"));
  358. // Seek(0102) shouldn't find any records since 0202 has a different prefix
  359. iter->Seek("0102");
  360. ASSERT_TRUE(!iter->Valid());
  361. iter->Seek("0202");
  362. ASSERT_TRUE(iter->Valid());
  363. ASSERT_EQ(iter->key().ToString(), "0202");
  364. iter->Next();
  365. ASSERT_TRUE(!iter->Valid());
  366. ASSERT_OK(iter->status());
  367. }
  368. Close();
  369. }
  370. TEST_P(DBTestTailingIterator, TailingIteratorIncomplete) {
  371. if (mem_env_ || encrypted_env_) {
  372. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  373. return;
  374. }
  375. std::unique_ptr<Env> env(
  376. new CompositeEnvWrapper(env_, FileSystem::Default()));
  377. Options options = CurrentOptions();
  378. options.env = env.get();
  379. CreateAndReopenWithCF({"pikachu"}, options);
  380. ReadOptions read_options;
  381. read_options.tailing = true;
  382. if (GetParam()) {
  383. read_options.async_io = true;
  384. }
  385. read_options.read_tier = kBlockCacheTier;
  386. std::string key("key");
  387. std::string value("value");
  388. ASSERT_OK(db_->Put(WriteOptions(), key, value));
  389. {
  390. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options));
  391. ASSERT_OK(iter->status());
  392. iter->SeekToFirst();
  393. // we either see the entry or it's not in cache
  394. ASSERT_TRUE(iter->Valid() || iter->status().IsIncomplete());
  395. ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
  396. iter->SeekToFirst();
  397. // should still be true after compaction
  398. ASSERT_TRUE(iter->Valid() || iter->status().IsIncomplete());
  399. }
  400. Close();
  401. }
  402. TEST_P(DBTestTailingIterator, TailingIteratorSeekToSame) {
  403. if (mem_env_ || encrypted_env_) {
  404. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  405. return;
  406. }
  407. std::unique_ptr<Env> env(
  408. new CompositeEnvWrapper(env_, FileSystem::Default()));
  409. Options options = CurrentOptions();
  410. options.env = env.get();
  411. options.compaction_style = kCompactionStyleUniversal;
  412. options.write_buffer_size = 1000;
  413. CreateAndReopenWithCF({"pikachu"}, options);
  414. ReadOptions read_options;
  415. read_options.tailing = true;
  416. if (GetParam()) {
  417. read_options.async_io = true;
  418. }
  419. const int NROWS = 10000;
  420. // Write rows with keys 00000, 00002, 00004 etc.
  421. for (int i = 0; i < NROWS; ++i) {
  422. char buf[100];
  423. snprintf(buf, sizeof(buf), "%05d", 2 * i);
  424. std::string key(buf);
  425. std::string value("value");
  426. ASSERT_OK(db_->Put(WriteOptions(), key, value));
  427. }
  428. {
  429. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options));
  430. ASSERT_OK(iter->status());
  431. // Seek to 00001. We expect to find 00002.
  432. std::string start_key = "00001";
  433. iter->Seek(start_key);
  434. ASSERT_TRUE(iter->Valid());
  435. std::string found = iter->key().ToString();
  436. ASSERT_EQ("00002", found);
  437. // Now seek to the same key. The iterator should remain in the same
  438. // position.
  439. iter->Seek(found);
  440. ASSERT_TRUE(iter->Valid());
  441. ASSERT_EQ(found, iter->key().ToString());
  442. }
  443. Close();
  444. }
  445. // Sets iterate_upper_bound and verifies that ForwardIterator doesn't call
  446. // Seek() on immutable iterators when target key is >= prev_key and all
  447. // iterators, including the memtable iterator, are over the upper bound.
  448. TEST_P(DBTestTailingIterator, TailingIteratorUpperBound) {
  449. if (mem_env_ || encrypted_env_) {
  450. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  451. return;
  452. }
  453. std::unique_ptr<Env> env(
  454. new CompositeEnvWrapper(env_, FileSystem::Default()));
  455. Options options = CurrentOptions();
  456. options.env = env.get();
  457. CreateAndReopenWithCF({"pikachu"}, options);
  458. const Slice upper_bound("20", 3);
  459. ReadOptions read_options;
  460. read_options.tailing = true;
  461. read_options.iterate_upper_bound = &upper_bound;
  462. if (GetParam()) {
  463. read_options.async_io = true;
  464. }
  465. ASSERT_OK(Put(1, "11", "11"));
  466. ASSERT_OK(Put(1, "12", "12"));
  467. ASSERT_OK(Put(1, "22", "22"));
  468. ASSERT_OK(Flush(1)); // flush all those keys to an immutable SST file
  469. // Add another key to the memtable.
  470. ASSERT_OK(Put(1, "21", "21"));
  471. {
  472. bool read_async_called = false;
  473. SyncPoint::GetInstance()->SetCallBack(
  474. "UpdateResults::io_uring_result",
  475. [&](void* /*arg*/) { read_async_called = true; });
  476. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  477. auto it =
  478. std::unique_ptr<Iterator>(db_->NewIterator(read_options, handles_[1]));
  479. ASSERT_OK(it->status());
  480. it->Seek("12");
  481. ASSERT_TRUE(it->Valid());
  482. ASSERT_EQ("12", it->key().ToString());
  483. it->Next();
  484. // Not valid since "21" is over the upper bound.
  485. ASSERT_FALSE(it->Valid());
  486. ASSERT_OK(it->status());
  487. // This keeps track of the number of times NeedToSeekImmutable() was true.
  488. int immutable_seeks = 0;
  489. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  490. "ForwardIterator::SeekInternal:Immutable",
  491. [&](void* /*arg*/) { ++immutable_seeks; });
  492. // Seek to 13. This should not require any immutable seeks.
  493. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  494. it->Seek("13");
  495. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  496. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  497. SyncPoint::GetInstance()->SetCallBack(
  498. "UpdateResults::io_uring_result",
  499. [&](void* /*arg*/) { read_async_called = true; });
  500. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  501. ASSERT_FALSE(it->Valid());
  502. ASSERT_OK(it->status());
  503. if (GetParam() && read_async_called) {
  504. ASSERT_EQ(1, immutable_seeks);
  505. } else {
  506. ASSERT_EQ(0, immutable_seeks);
  507. }
  508. }
  509. Close();
  510. }
  511. TEST_P(DBTestTailingIterator, TailingIteratorGap) {
  512. // level 1: [20, 25] [35, 40]
  513. // level 2: [10 - 15] [45 - 50]
  514. // level 3: [20, 30, 40]
  515. // Previously there is a bug in tailing_iterator that if there is a gap in
  516. // lower level, the key will be skipped if it is within the range between
  517. // the largest key of index n file and the smallest key of index n+1 file
  518. // if both file fit in that gap. In this example, 25 < key < 35
  519. // https://github.com/facebook/rocksdb/issues/1372
  520. if (mem_env_ || encrypted_env_) {
  521. ROCKSDB_GTEST_BYPASS("Test requires non-mem or non-encrypted environment");
  522. return;
  523. }
  524. std::unique_ptr<Env> env(
  525. new CompositeEnvWrapper(env_, FileSystem::Default()));
  526. Options options = CurrentOptions();
  527. options.env = env.get();
  528. CreateAndReopenWithCF({"pikachu"}, options);
  529. ReadOptions read_options;
  530. read_options.tailing = true;
  531. if (GetParam()) {
  532. read_options.async_io = true;
  533. }
  534. ASSERT_OK(Put(1, "20", "20"));
  535. ASSERT_OK(Put(1, "30", "30"));
  536. ASSERT_OK(Put(1, "40", "40"));
  537. ASSERT_OK(Flush(1));
  538. MoveFilesToLevel(3, 1);
  539. ASSERT_OK(Put(1, "10", "10"));
  540. ASSERT_OK(Put(1, "15", "15"));
  541. ASSERT_OK(Flush(1));
  542. ASSERT_OK(Put(1, "45", "45"));
  543. ASSERT_OK(Put(1, "50", "50"));
  544. ASSERT_OK(Flush(1));
  545. MoveFilesToLevel(2, 1);
  546. ASSERT_OK(Put(1, "20", "20"));
  547. ASSERT_OK(Put(1, "25", "25"));
  548. ASSERT_OK(Flush(1));
  549. ASSERT_OK(Put(1, "35", "35"));
  550. ASSERT_OK(Put(1, "40", "40"));
  551. ASSERT_OK(Flush(1));
  552. MoveFilesToLevel(1, 1);
  553. ColumnFamilyMetaData meta;
  554. db_->GetColumnFamilyMetaData(handles_[1], &meta);
  555. {
  556. std::unique_ptr<Iterator> it(db_->NewIterator(read_options, handles_[1]));
  557. it->Seek("30");
  558. ASSERT_TRUE(it->Valid());
  559. ASSERT_EQ("30", it->key().ToString());
  560. it->Next();
  561. ASSERT_TRUE(it->Valid());
  562. ASSERT_EQ("35", it->key().ToString());
  563. it->Next();
  564. ASSERT_TRUE(it->Valid());
  565. ASSERT_EQ("40", it->key().ToString());
  566. ASSERT_OK(it->status());
  567. }
  568. Close();
  569. }
  570. TEST_P(DBTestTailingIterator, SeekWithUpperBoundBug) {
  571. ReadOptions read_options;
  572. read_options.tailing = true;
  573. if (GetParam()) {
  574. read_options.async_io = true;
  575. }
  576. const Slice upper_bound("cc", 3);
  577. read_options.iterate_upper_bound = &upper_bound;
  578. // 1st L0 file
  579. ASSERT_OK(db_->Put(WriteOptions(), "aa", "SEEN"));
  580. ASSERT_OK(Flush());
  581. // 2nd L0 file
  582. ASSERT_OK(db_->Put(WriteOptions(), "zz", "NOT-SEEN"));
  583. ASSERT_OK(Flush());
  584. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options));
  585. ASSERT_OK(iter->status());
  586. iter->Seek("aa");
  587. ASSERT_TRUE(iter->Valid());
  588. ASSERT_EQ(iter->key().ToString(), "aa");
  589. }
  590. TEST_P(DBTestTailingIterator, SeekToFirstWithUpperBoundBug) {
  591. ReadOptions read_options;
  592. read_options.tailing = true;
  593. if (GetParam()) {
  594. read_options.async_io = true;
  595. }
  596. const Slice upper_bound("cc", 3);
  597. read_options.iterate_upper_bound = &upper_bound;
  598. // 1st L0 file
  599. ASSERT_OK(db_->Put(WriteOptions(), "aa", "SEEN"));
  600. ASSERT_OK(Flush());
  601. // 2nd L0 file
  602. ASSERT_OK(db_->Put(WriteOptions(), "zz", "NOT-SEEN"));
  603. ASSERT_OK(Flush());
  604. std::unique_ptr<Iterator> iter(db_->NewIterator(read_options));
  605. ASSERT_OK(iter->status());
  606. iter->SeekToFirst();
  607. ASSERT_TRUE(iter->Valid());
  608. ASSERT_EQ(iter->key().ToString(), "aa");
  609. iter->Next();
  610. ASSERT_FALSE(iter->Valid());
  611. iter->SeekToFirst();
  612. ASSERT_TRUE(iter->Valid());
  613. ASSERT_EQ(iter->key().ToString(), "aa");
  614. }
  615. } // namespace ROCKSDB_NAMESPACE
  616. int main(int argc, char** argv) {
  617. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  618. ::testing::InitGoogleTest(&argc, argv);
  619. return RUN_ALL_TESTS();
  620. }