prefix_test.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  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. #ifndef ROCKSDB_LITE
  6. #ifndef GFLAGS
  7. #include <cstdio>
  8. int main() {
  9. fprintf(stderr, "Please install gflags to run this test... Skipping...\n");
  10. return 0;
  11. }
  12. #else
  13. #include <algorithm>
  14. #include <iostream>
  15. #include <vector>
  16. #include "db/db_impl/db_impl.h"
  17. #include "monitoring/histogram.h"
  18. #include "rocksdb/comparator.h"
  19. #include "rocksdb/db.h"
  20. #include "rocksdb/filter_policy.h"
  21. #include "rocksdb/memtablerep.h"
  22. #include "rocksdb/perf_context.h"
  23. #include "rocksdb/slice_transform.h"
  24. #include "rocksdb/table.h"
  25. #include "test_util/testharness.h"
  26. #include "util/coding.h"
  27. #include "util/gflags_compat.h"
  28. #include "util/random.h"
  29. #include "util/stop_watch.h"
  30. #include "util/string_util.h"
  31. #include "utilities/merge_operators.h"
  32. using GFLAGS_NAMESPACE::ParseCommandLineFlags;
  33. DEFINE_bool(trigger_deadlock, false,
  34. "issue delete in range scan to trigger PrefixHashMap deadlock");
  35. DEFINE_int32(bucket_count, 100000, "number of buckets");
  36. DEFINE_uint64(num_locks, 10001, "number of locks");
  37. DEFINE_bool(random_prefix, false, "randomize prefix");
  38. DEFINE_uint64(total_prefixes, 100000, "total number of prefixes");
  39. DEFINE_uint64(items_per_prefix, 1, "total number of values per prefix");
  40. DEFINE_int64(write_buffer_size, 33554432, "");
  41. DEFINE_int32(max_write_buffer_number, 2, "");
  42. DEFINE_int32(min_write_buffer_number_to_merge, 1, "");
  43. DEFINE_int32(skiplist_height, 4, "");
  44. DEFINE_double(memtable_prefix_bloom_size_ratio, 0.1, "");
  45. DEFINE_int32(memtable_huge_page_size, 2 * 1024 * 1024, "");
  46. DEFINE_int32(value_size, 40, "");
  47. DEFINE_bool(enable_print, false, "Print options generated to console.");
  48. // Path to the database on file system
  49. const std::string kDbName =
  50. ROCKSDB_NAMESPACE::test::PerThreadDBPath("prefix_test");
  51. namespace ROCKSDB_NAMESPACE {
  52. struct TestKey {
  53. uint64_t prefix;
  54. uint64_t sorted;
  55. TestKey(uint64_t _prefix, uint64_t _sorted)
  56. : prefix(_prefix), sorted(_sorted) {}
  57. };
  58. // return a slice backed by test_key
  59. inline Slice TestKeyToSlice(std::string &s, const TestKey& test_key) {
  60. s.clear();
  61. PutFixed64(&s, test_key.prefix);
  62. PutFixed64(&s, test_key.sorted);
  63. return Slice(s.c_str(), s.size());
  64. }
  65. inline const TestKey SliceToTestKey(const Slice& slice) {
  66. return TestKey(DecodeFixed64(slice.data()),
  67. DecodeFixed64(slice.data() + 8));
  68. }
  69. class TestKeyComparator : public Comparator {
  70. public:
  71. // Compare needs to be aware of the possibility of a and/or b is
  72. // prefix only
  73. int Compare(const Slice& a, const Slice& b) const override {
  74. const TestKey kkey_a = SliceToTestKey(a);
  75. const TestKey kkey_b = SliceToTestKey(b);
  76. const TestKey *key_a = &kkey_a;
  77. const TestKey *key_b = &kkey_b;
  78. if (key_a->prefix != key_b->prefix) {
  79. if (key_a->prefix < key_b->prefix) return -1;
  80. if (key_a->prefix > key_b->prefix) return 1;
  81. } else {
  82. EXPECT_TRUE(key_a->prefix == key_b->prefix);
  83. // note, both a and b could be prefix only
  84. if (a.size() != b.size()) {
  85. // one of them is prefix
  86. EXPECT_TRUE(
  87. (a.size() == sizeof(uint64_t) && b.size() == sizeof(TestKey)) ||
  88. (b.size() == sizeof(uint64_t) && a.size() == sizeof(TestKey)));
  89. if (a.size() < b.size()) return -1;
  90. if (a.size() > b.size()) return 1;
  91. } else {
  92. // both a and b are prefix
  93. if (a.size() == sizeof(uint64_t)) {
  94. return 0;
  95. }
  96. // both a and b are whole key
  97. EXPECT_TRUE(a.size() == sizeof(TestKey) && b.size() == sizeof(TestKey));
  98. if (key_a->sorted < key_b->sorted) return -1;
  99. if (key_a->sorted > key_b->sorted) return 1;
  100. if (key_a->sorted == key_b->sorted) return 0;
  101. }
  102. }
  103. return 0;
  104. }
  105. bool operator()(const TestKey& a, const TestKey& b) const {
  106. std::string sa, sb;
  107. return Compare(TestKeyToSlice(sa, a), TestKeyToSlice(sb, b)) < 0;
  108. }
  109. const char* Name() const override { return "TestKeyComparator"; }
  110. void FindShortestSeparator(std::string* /*start*/,
  111. const Slice& /*limit*/) const override {}
  112. void FindShortSuccessor(std::string* /*key*/) const override {}
  113. };
  114. namespace {
  115. void PutKey(DB* db, WriteOptions write_options, uint64_t prefix,
  116. uint64_t suffix, const Slice& value) {
  117. TestKey test_key(prefix, suffix);
  118. std::string s;
  119. Slice key = TestKeyToSlice(s, test_key);
  120. ASSERT_OK(db->Put(write_options, key, value));
  121. }
  122. void PutKey(DB* db, WriteOptions write_options, const TestKey& test_key,
  123. const Slice& value) {
  124. std::string s;
  125. Slice key = TestKeyToSlice(s, test_key);
  126. ASSERT_OK(db->Put(write_options, key, value));
  127. }
  128. void MergeKey(DB* db, WriteOptions write_options, const TestKey& test_key,
  129. const Slice& value) {
  130. std::string s;
  131. Slice key = TestKeyToSlice(s, test_key);
  132. ASSERT_OK(db->Merge(write_options, key, value));
  133. }
  134. void DeleteKey(DB* db, WriteOptions write_options, const TestKey& test_key) {
  135. std::string s;
  136. Slice key = TestKeyToSlice(s, test_key);
  137. ASSERT_OK(db->Delete(write_options, key));
  138. }
  139. void SeekIterator(Iterator* iter, uint64_t prefix, uint64_t suffix) {
  140. TestKey test_key(prefix, suffix);
  141. std::string s;
  142. Slice key = TestKeyToSlice(s, test_key);
  143. iter->Seek(key);
  144. }
  145. const std::string kNotFoundResult = "NOT_FOUND";
  146. std::string Get(DB* db, const ReadOptions& read_options, uint64_t prefix,
  147. uint64_t suffix) {
  148. TestKey test_key(prefix, suffix);
  149. std::string s2;
  150. Slice key = TestKeyToSlice(s2, test_key);
  151. std::string result;
  152. Status s = db->Get(read_options, key, &result);
  153. if (s.IsNotFound()) {
  154. result = kNotFoundResult;
  155. } else if (!s.ok()) {
  156. result = s.ToString();
  157. }
  158. return result;
  159. }
  160. class SamePrefixTransform : public SliceTransform {
  161. private:
  162. const Slice prefix_;
  163. std::string name_;
  164. public:
  165. explicit SamePrefixTransform(const Slice& prefix)
  166. : prefix_(prefix), name_("rocksdb.SamePrefix." + prefix.ToString()) {}
  167. const char* Name() const override { return name_.c_str(); }
  168. Slice Transform(const Slice& src) const override {
  169. assert(InDomain(src));
  170. return prefix_;
  171. }
  172. bool InDomain(const Slice& src) const override {
  173. if (src.size() >= prefix_.size()) {
  174. return Slice(src.data(), prefix_.size()) == prefix_;
  175. }
  176. return false;
  177. }
  178. bool InRange(const Slice& dst) const override { return dst == prefix_; }
  179. bool FullLengthEnabled(size_t* /*len*/) const override { return false; }
  180. };
  181. } // namespace
  182. class PrefixTest : public testing::Test {
  183. public:
  184. std::shared_ptr<DB> OpenDb() {
  185. DB* db;
  186. options.create_if_missing = true;
  187. options.write_buffer_size = FLAGS_write_buffer_size;
  188. options.max_write_buffer_number = FLAGS_max_write_buffer_number;
  189. options.min_write_buffer_number_to_merge =
  190. FLAGS_min_write_buffer_number_to_merge;
  191. options.memtable_prefix_bloom_size_ratio =
  192. FLAGS_memtable_prefix_bloom_size_ratio;
  193. options.memtable_huge_page_size = FLAGS_memtable_huge_page_size;
  194. options.prefix_extractor.reset(NewFixedPrefixTransform(8));
  195. BlockBasedTableOptions bbto;
  196. bbto.filter_policy.reset(NewBloomFilterPolicy(10, false));
  197. bbto.whole_key_filtering = false;
  198. options.table_factory.reset(NewBlockBasedTableFactory(bbto));
  199. options.allow_concurrent_memtable_write = false;
  200. Status s = DB::Open(options, kDbName, &db);
  201. EXPECT_OK(s);
  202. return std::shared_ptr<DB>(db);
  203. }
  204. void FirstOption() {
  205. option_config_ = kBegin;
  206. }
  207. bool NextOptions(int bucket_count) {
  208. // skip some options
  209. option_config_++;
  210. if (option_config_ < kEnd) {
  211. options.prefix_extractor.reset(NewFixedPrefixTransform(8));
  212. switch(option_config_) {
  213. case kHashSkipList:
  214. options.memtable_factory.reset(
  215. NewHashSkipListRepFactory(bucket_count, FLAGS_skiplist_height));
  216. return true;
  217. case kHashLinkList:
  218. options.memtable_factory.reset(
  219. NewHashLinkListRepFactory(bucket_count));
  220. return true;
  221. case kHashLinkListHugePageTlb:
  222. options.memtable_factory.reset(
  223. NewHashLinkListRepFactory(bucket_count, 2 * 1024 * 1024));
  224. return true;
  225. case kHashLinkListTriggerSkipList:
  226. options.memtable_factory.reset(
  227. NewHashLinkListRepFactory(bucket_count, 0, 3));
  228. return true;
  229. default:
  230. return false;
  231. }
  232. }
  233. return false;
  234. }
  235. PrefixTest() : option_config_(kBegin) {
  236. options.comparator = new TestKeyComparator();
  237. }
  238. ~PrefixTest() override { delete options.comparator; }
  239. protected:
  240. enum OptionConfig {
  241. kBegin,
  242. kHashSkipList,
  243. kHashLinkList,
  244. kHashLinkListHugePageTlb,
  245. kHashLinkListTriggerSkipList,
  246. kEnd
  247. };
  248. int option_config_;
  249. Options options;
  250. };
  251. TEST(SamePrefixTest, InDomainTest) {
  252. DB* db;
  253. Options options;
  254. options.create_if_missing = true;
  255. options.prefix_extractor.reset(new SamePrefixTransform("HHKB"));
  256. BlockBasedTableOptions bbto;
  257. bbto.filter_policy.reset(NewBloomFilterPolicy(10, false));
  258. bbto.whole_key_filtering = false;
  259. options.table_factory.reset(NewBlockBasedTableFactory(bbto));
  260. WriteOptions write_options;
  261. ReadOptions read_options;
  262. {
  263. ASSERT_OK(DestroyDB(kDbName, Options()));
  264. ASSERT_OK(DB::Open(options, kDbName, &db));
  265. ASSERT_OK(db->Put(write_options, "HHKB pro2", "Mar 24, 2006"));
  266. ASSERT_OK(db->Put(write_options, "HHKB pro2 Type-S", "June 29, 2011"));
  267. ASSERT_OK(db->Put(write_options, "Realforce 87u", "idk"));
  268. db->Flush(FlushOptions());
  269. std::string result;
  270. auto db_iter = db->NewIterator(ReadOptions());
  271. db_iter->Seek("Realforce 87u");
  272. ASSERT_TRUE(db_iter->Valid());
  273. ASSERT_OK(db_iter->status());
  274. ASSERT_EQ(db_iter->key(), "Realforce 87u");
  275. ASSERT_EQ(db_iter->value(), "idk");
  276. delete db_iter;
  277. delete db;
  278. ASSERT_OK(DestroyDB(kDbName, Options()));
  279. }
  280. {
  281. ASSERT_OK(DB::Open(options, kDbName, &db));
  282. ASSERT_OK(db->Put(write_options, "pikachu", "1"));
  283. ASSERT_OK(db->Put(write_options, "Meowth", "1"));
  284. ASSERT_OK(db->Put(write_options, "Mewtwo", "idk"));
  285. db->Flush(FlushOptions());
  286. std::string result;
  287. auto db_iter = db->NewIterator(ReadOptions());
  288. db_iter->Seek("Mewtwo");
  289. ASSERT_TRUE(db_iter->Valid());
  290. ASSERT_OK(db_iter->status());
  291. delete db_iter;
  292. delete db;
  293. ASSERT_OK(DestroyDB(kDbName, Options()));
  294. }
  295. }
  296. TEST_F(PrefixTest, TestResult) {
  297. for (int num_buckets = 1; num_buckets <= 2; num_buckets++) {
  298. FirstOption();
  299. while (NextOptions(num_buckets)) {
  300. std::cout << "*** Mem table: " << options.memtable_factory->Name()
  301. << " number of buckets: " << num_buckets
  302. << std::endl;
  303. DestroyDB(kDbName, Options());
  304. auto db = OpenDb();
  305. WriteOptions write_options;
  306. ReadOptions read_options;
  307. // 1. Insert one row.
  308. Slice v16("v16");
  309. PutKey(db.get(), write_options, 1, 6, v16);
  310. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  311. SeekIterator(iter.get(), 1, 6);
  312. ASSERT_TRUE(iter->Valid());
  313. ASSERT_TRUE(v16 == iter->value());
  314. SeekIterator(iter.get(), 1, 5);
  315. ASSERT_TRUE(iter->Valid());
  316. ASSERT_TRUE(v16 == iter->value());
  317. SeekIterator(iter.get(), 1, 5);
  318. ASSERT_TRUE(iter->Valid());
  319. ASSERT_TRUE(v16 == iter->value());
  320. iter->Next();
  321. ASSERT_TRUE(!iter->Valid());
  322. SeekIterator(iter.get(), 2, 0);
  323. ASSERT_TRUE(!iter->Valid());
  324. ASSERT_EQ(v16.ToString(), Get(db.get(), read_options, 1, 6));
  325. ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 1, 5));
  326. ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 1, 7));
  327. ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 0, 6));
  328. ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 2, 6));
  329. // 2. Insert an entry for the same prefix as the last entry in the bucket.
  330. Slice v17("v17");
  331. PutKey(db.get(), write_options, 1, 7, v17);
  332. iter.reset(db->NewIterator(read_options));
  333. SeekIterator(iter.get(), 1, 7);
  334. ASSERT_TRUE(iter->Valid());
  335. ASSERT_TRUE(v17 == iter->value());
  336. SeekIterator(iter.get(), 1, 6);
  337. ASSERT_TRUE(iter->Valid());
  338. ASSERT_TRUE(v16 == iter->value());
  339. iter->Next();
  340. ASSERT_TRUE(iter->Valid());
  341. ASSERT_TRUE(v17 == iter->value());
  342. iter->Next();
  343. ASSERT_TRUE(!iter->Valid());
  344. SeekIterator(iter.get(), 2, 0);
  345. ASSERT_TRUE(!iter->Valid());
  346. // 3. Insert an entry for the same prefix as the head of the bucket.
  347. Slice v15("v15");
  348. PutKey(db.get(), write_options, 1, 5, v15);
  349. iter.reset(db->NewIterator(read_options));
  350. SeekIterator(iter.get(), 1, 7);
  351. ASSERT_TRUE(iter->Valid());
  352. ASSERT_TRUE(v17 == iter->value());
  353. SeekIterator(iter.get(), 1, 5);
  354. ASSERT_TRUE(iter->Valid());
  355. ASSERT_TRUE(v15 == iter->value());
  356. iter->Next();
  357. ASSERT_TRUE(iter->Valid());
  358. ASSERT_TRUE(v16 == iter->value());
  359. iter->Next();
  360. ASSERT_TRUE(iter->Valid());
  361. ASSERT_TRUE(v17 == iter->value());
  362. SeekIterator(iter.get(), 1, 5);
  363. ASSERT_TRUE(iter->Valid());
  364. ASSERT_TRUE(v15 == iter->value());
  365. ASSERT_EQ(v15.ToString(), Get(db.get(), read_options, 1, 5));
  366. ASSERT_EQ(v16.ToString(), Get(db.get(), read_options, 1, 6));
  367. ASSERT_EQ(v17.ToString(), Get(db.get(), read_options, 1, 7));
  368. // 4. Insert an entry with a larger prefix
  369. Slice v22("v22");
  370. PutKey(db.get(), write_options, 2, 2, v22);
  371. iter.reset(db->NewIterator(read_options));
  372. SeekIterator(iter.get(), 2, 2);
  373. ASSERT_TRUE(iter->Valid());
  374. ASSERT_TRUE(v22 == iter->value());
  375. SeekIterator(iter.get(), 2, 0);
  376. ASSERT_TRUE(iter->Valid());
  377. ASSERT_TRUE(v22 == iter->value());
  378. SeekIterator(iter.get(), 1, 5);
  379. ASSERT_TRUE(iter->Valid());
  380. ASSERT_TRUE(v15 == iter->value());
  381. SeekIterator(iter.get(), 1, 7);
  382. ASSERT_TRUE(iter->Valid());
  383. ASSERT_TRUE(v17 == iter->value());
  384. // 5. Insert an entry with a smaller prefix
  385. Slice v02("v02");
  386. PutKey(db.get(), write_options, 0, 2, v02);
  387. iter.reset(db->NewIterator(read_options));
  388. SeekIterator(iter.get(), 0, 2);
  389. ASSERT_TRUE(iter->Valid());
  390. ASSERT_TRUE(v02 == iter->value());
  391. SeekIterator(iter.get(), 0, 0);
  392. ASSERT_TRUE(iter->Valid());
  393. ASSERT_TRUE(v02 == iter->value());
  394. SeekIterator(iter.get(), 2, 0);
  395. ASSERT_TRUE(iter->Valid());
  396. ASSERT_TRUE(v22 == iter->value());
  397. SeekIterator(iter.get(), 1, 5);
  398. ASSERT_TRUE(iter->Valid());
  399. ASSERT_TRUE(v15 == iter->value());
  400. SeekIterator(iter.get(), 1, 7);
  401. ASSERT_TRUE(iter->Valid());
  402. ASSERT_TRUE(v17 == iter->value());
  403. // 6. Insert to the beginning and the end of the first prefix
  404. Slice v13("v13");
  405. Slice v18("v18");
  406. PutKey(db.get(), write_options, 1, 3, v13);
  407. PutKey(db.get(), write_options, 1, 8, v18);
  408. iter.reset(db->NewIterator(read_options));
  409. SeekIterator(iter.get(), 1, 7);
  410. ASSERT_TRUE(iter->Valid());
  411. ASSERT_TRUE(v17 == iter->value());
  412. SeekIterator(iter.get(), 1, 3);
  413. ASSERT_TRUE(iter->Valid());
  414. ASSERT_TRUE(v13 == iter->value());
  415. iter->Next();
  416. ASSERT_TRUE(iter->Valid());
  417. ASSERT_TRUE(v15 == iter->value());
  418. iter->Next();
  419. ASSERT_TRUE(iter->Valid());
  420. ASSERT_TRUE(v16 == iter->value());
  421. iter->Next();
  422. ASSERT_TRUE(iter->Valid());
  423. ASSERT_TRUE(v17 == iter->value());
  424. iter->Next();
  425. ASSERT_TRUE(iter->Valid());
  426. ASSERT_TRUE(v18 == iter->value());
  427. SeekIterator(iter.get(), 0, 0);
  428. ASSERT_TRUE(iter->Valid());
  429. ASSERT_TRUE(v02 == iter->value());
  430. SeekIterator(iter.get(), 2, 0);
  431. ASSERT_TRUE(iter->Valid());
  432. ASSERT_TRUE(v22 == iter->value());
  433. ASSERT_EQ(v22.ToString(), Get(db.get(), read_options, 2, 2));
  434. ASSERT_EQ(v02.ToString(), Get(db.get(), read_options, 0, 2));
  435. ASSERT_EQ(v13.ToString(), Get(db.get(), read_options, 1, 3));
  436. ASSERT_EQ(v15.ToString(), Get(db.get(), read_options, 1, 5));
  437. ASSERT_EQ(v16.ToString(), Get(db.get(), read_options, 1, 6));
  438. ASSERT_EQ(v17.ToString(), Get(db.get(), read_options, 1, 7));
  439. ASSERT_EQ(v18.ToString(), Get(db.get(), read_options, 1, 8));
  440. }
  441. }
  442. }
  443. // Show results in prefix
  444. TEST_F(PrefixTest, PrefixValid) {
  445. for (int num_buckets = 1; num_buckets <= 2; num_buckets++) {
  446. FirstOption();
  447. while (NextOptions(num_buckets)) {
  448. std::cout << "*** Mem table: " << options.memtable_factory->Name()
  449. << " number of buckets: " << num_buckets << std::endl;
  450. DestroyDB(kDbName, Options());
  451. auto db = OpenDb();
  452. WriteOptions write_options;
  453. ReadOptions read_options;
  454. // Insert keys with common prefix and one key with different
  455. Slice v16("v16");
  456. Slice v17("v17");
  457. Slice v18("v18");
  458. Slice v19("v19");
  459. PutKey(db.get(), write_options, 12345, 6, v16);
  460. PutKey(db.get(), write_options, 12345, 7, v17);
  461. PutKey(db.get(), write_options, 12345, 8, v18);
  462. PutKey(db.get(), write_options, 12345, 9, v19);
  463. PutKey(db.get(), write_options, 12346, 8, v16);
  464. db->Flush(FlushOptions());
  465. TestKey test_key(12346, 8);
  466. std::string s;
  467. db->Delete(write_options, TestKeyToSlice(s, test_key));
  468. db->Flush(FlushOptions());
  469. read_options.prefix_same_as_start = true;
  470. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  471. SeekIterator(iter.get(), 12345, 6);
  472. ASSERT_TRUE(iter->Valid());
  473. ASSERT_TRUE(v16 == iter->value());
  474. iter->Next();
  475. ASSERT_TRUE(iter->Valid());
  476. ASSERT_TRUE(v17 == iter->value());
  477. iter->Next();
  478. ASSERT_TRUE(iter->Valid());
  479. ASSERT_TRUE(v18 == iter->value());
  480. iter->Next();
  481. ASSERT_TRUE(iter->Valid());
  482. ASSERT_TRUE(v19 == iter->value());
  483. iter->Next();
  484. ASSERT_FALSE(iter->Valid());
  485. ASSERT_EQ(kNotFoundResult, Get(db.get(), read_options, 12346, 8));
  486. // Verify seeking past the prefix won't return a result.
  487. SeekIterator(iter.get(), 12345, 10);
  488. ASSERT_TRUE(!iter->Valid());
  489. }
  490. }
  491. }
  492. TEST_F(PrefixTest, DynamicPrefixIterator) {
  493. while (NextOptions(FLAGS_bucket_count)) {
  494. std::cout << "*** Mem table: " << options.memtable_factory->Name()
  495. << std::endl;
  496. DestroyDB(kDbName, Options());
  497. auto db = OpenDb();
  498. WriteOptions write_options;
  499. ReadOptions read_options;
  500. std::vector<uint64_t> prefixes;
  501. for (uint64_t i = 0; i < FLAGS_total_prefixes; ++i) {
  502. prefixes.push_back(i);
  503. }
  504. if (FLAGS_random_prefix) {
  505. std::random_shuffle(prefixes.begin(), prefixes.end());
  506. }
  507. HistogramImpl hist_put_time;
  508. HistogramImpl hist_put_comparison;
  509. // insert x random prefix, each with y continuous element.
  510. for (auto prefix : prefixes) {
  511. for (uint64_t sorted = 0; sorted < FLAGS_items_per_prefix; sorted++) {
  512. TestKey test_key(prefix, sorted);
  513. std::string s;
  514. Slice key = TestKeyToSlice(s, test_key);
  515. std::string value(FLAGS_value_size, 0);
  516. get_perf_context()->Reset();
  517. StopWatchNano timer(Env::Default(), true);
  518. ASSERT_OK(db->Put(write_options, key, value));
  519. hist_put_time.Add(timer.ElapsedNanos());
  520. hist_put_comparison.Add(get_perf_context()->user_key_comparison_count);
  521. }
  522. }
  523. std::cout << "Put key comparison: \n" << hist_put_comparison.ToString()
  524. << "Put time: \n" << hist_put_time.ToString();
  525. // test seek existing keys
  526. HistogramImpl hist_seek_time;
  527. HistogramImpl hist_seek_comparison;
  528. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  529. for (auto prefix : prefixes) {
  530. TestKey test_key(prefix, FLAGS_items_per_prefix / 2);
  531. std::string s;
  532. Slice key = TestKeyToSlice(s, test_key);
  533. std::string value = "v" + ToString(0);
  534. get_perf_context()->Reset();
  535. StopWatchNano timer(Env::Default(), true);
  536. auto key_prefix = options.prefix_extractor->Transform(key);
  537. uint64_t total_keys = 0;
  538. for (iter->Seek(key);
  539. iter->Valid() && iter->key().starts_with(key_prefix);
  540. iter->Next()) {
  541. if (FLAGS_trigger_deadlock) {
  542. std::cout << "Behold the deadlock!\n";
  543. db->Delete(write_options, iter->key());
  544. }
  545. total_keys++;
  546. }
  547. hist_seek_time.Add(timer.ElapsedNanos());
  548. hist_seek_comparison.Add(get_perf_context()->user_key_comparison_count);
  549. ASSERT_EQ(total_keys, FLAGS_items_per_prefix - FLAGS_items_per_prefix/2);
  550. }
  551. std::cout << "Seek key comparison: \n"
  552. << hist_seek_comparison.ToString()
  553. << "Seek time: \n"
  554. << hist_seek_time.ToString();
  555. // test non-existing keys
  556. HistogramImpl hist_no_seek_time;
  557. HistogramImpl hist_no_seek_comparison;
  558. for (auto prefix = FLAGS_total_prefixes;
  559. prefix < FLAGS_total_prefixes + 10000;
  560. prefix++) {
  561. TestKey test_key(prefix, 0);
  562. std::string s;
  563. Slice key = TestKeyToSlice(s, test_key);
  564. get_perf_context()->Reset();
  565. StopWatchNano timer(Env::Default(), true);
  566. iter->Seek(key);
  567. hist_no_seek_time.Add(timer.ElapsedNanos());
  568. hist_no_seek_comparison.Add(get_perf_context()->user_key_comparison_count);
  569. ASSERT_TRUE(!iter->Valid());
  570. }
  571. std::cout << "non-existing Seek key comparison: \n"
  572. << hist_no_seek_comparison.ToString()
  573. << "non-existing Seek time: \n"
  574. << hist_no_seek_time.ToString();
  575. }
  576. }
  577. TEST_F(PrefixTest, PrefixSeekModePrev) {
  578. // Only for SkipListFactory
  579. options.memtable_factory.reset(new SkipListFactory);
  580. options.merge_operator = MergeOperators::CreatePutOperator();
  581. options.write_buffer_size = 1024 * 1024;
  582. Random rnd(1);
  583. for (size_t m = 1; m < 100; m++) {
  584. std::cout << "[" + std::to_string(m) + "]" + "*** Mem table: "
  585. << options.memtable_factory->Name() << std::endl;
  586. DestroyDB(kDbName, Options());
  587. auto db = OpenDb();
  588. WriteOptions write_options;
  589. ReadOptions read_options;
  590. std::map<TestKey, std::string, TestKeyComparator> entry_maps[3], whole_map;
  591. for (uint64_t i = 0; i < 10; i++) {
  592. int div = i % 3 + 1;
  593. for (uint64_t j = 0; j < 10; j++) {
  594. whole_map[TestKey(i, j)] = entry_maps[rnd.Uniform(div)][TestKey(i, j)] =
  595. 'v' + std::to_string(i) + std::to_string(j);
  596. }
  597. }
  598. std::map<TestKey, std::string, TestKeyComparator> type_map;
  599. for (size_t i = 0; i < 3; i++) {
  600. for (auto& kv : entry_maps[i]) {
  601. if (rnd.OneIn(3)) {
  602. PutKey(db.get(), write_options, kv.first, kv.second);
  603. type_map[kv.first] = "value";
  604. } else {
  605. MergeKey(db.get(), write_options, kv.first, kv.second);
  606. type_map[kv.first] = "merge";
  607. }
  608. }
  609. if (i < 2) {
  610. db->Flush(FlushOptions());
  611. }
  612. }
  613. for (size_t i = 0; i < 2; i++) {
  614. for (auto& kv : entry_maps[i]) {
  615. if (rnd.OneIn(10)) {
  616. whole_map.erase(kv.first);
  617. DeleteKey(db.get(), write_options, kv.first);
  618. entry_maps[2][kv.first] = "delete";
  619. }
  620. }
  621. }
  622. if (FLAGS_enable_print) {
  623. for (size_t i = 0; i < 3; i++) {
  624. for (auto& kv : entry_maps[i]) {
  625. std::cout << "[" << i << "]" << kv.first.prefix << kv.first.sorted
  626. << " " << kv.second + " " + type_map[kv.first] << std::endl;
  627. }
  628. }
  629. }
  630. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  631. for (uint64_t prefix = 0; prefix < 10; prefix++) {
  632. uint64_t start_suffix = rnd.Uniform(9);
  633. SeekIterator(iter.get(), prefix, start_suffix);
  634. auto it = whole_map.find(TestKey(prefix, start_suffix));
  635. if (it == whole_map.end()) {
  636. continue;
  637. }
  638. ASSERT_NE(it, whole_map.end());
  639. ASSERT_TRUE(iter->Valid());
  640. if (FLAGS_enable_print) {
  641. std::cout << "round " << prefix
  642. << " iter: " << SliceToTestKey(iter->key()).prefix
  643. << SliceToTestKey(iter->key()).sorted
  644. << " | map: " << it->first.prefix << it->first.sorted << " | "
  645. << iter->value().ToString() << " " << it->second << std::endl;
  646. }
  647. ASSERT_EQ(iter->value(), it->second);
  648. uint64_t stored_prefix = prefix;
  649. for (size_t k = 0; k < 9; k++) {
  650. if (rnd.OneIn(2) || it == whole_map.begin()) {
  651. iter->Next();
  652. ++it;
  653. if (FLAGS_enable_print) {
  654. std::cout << "Next >> ";
  655. }
  656. } else {
  657. iter->Prev();
  658. it--;
  659. if (FLAGS_enable_print) {
  660. std::cout << "Prev >> ";
  661. }
  662. }
  663. if (!iter->Valid() ||
  664. SliceToTestKey(iter->key()).prefix != stored_prefix) {
  665. break;
  666. }
  667. stored_prefix = SliceToTestKey(iter->key()).prefix;
  668. ASSERT_TRUE(iter->Valid());
  669. ASSERT_NE(it, whole_map.end());
  670. ASSERT_EQ(iter->value(), it->second);
  671. if (FLAGS_enable_print) {
  672. std::cout << "iter: " << SliceToTestKey(iter->key()).prefix
  673. << SliceToTestKey(iter->key()).sorted
  674. << " | map: " << it->first.prefix << it->first.sorted
  675. << " | " << iter->value().ToString() << " " << it->second
  676. << std::endl;
  677. }
  678. }
  679. }
  680. }
  681. }
  682. TEST_F(PrefixTest, PrefixSeekModePrev2) {
  683. // Only for SkipListFactory
  684. // test the case
  685. // iter1 iter2
  686. // | prefix | suffix | | prefix | suffix |
  687. // | 1 | 1 | | 1 | 2 |
  688. // | 1 | 3 | | 1 | 4 |
  689. // | 2 | 1 | | 3 | 3 |
  690. // | 2 | 2 | | 3 | 4 |
  691. // after seek(15), iter1 will be at 21 and iter2 will be 33.
  692. // Then if call Prev() in prefix mode where SeekForPrev(21) gets called,
  693. // iter2 should turn to invalid state because of bloom filter.
  694. options.memtable_factory.reset(new SkipListFactory);
  695. options.write_buffer_size = 1024 * 1024;
  696. std::string v13("v13");
  697. DestroyDB(kDbName, Options());
  698. auto db = OpenDb();
  699. WriteOptions write_options;
  700. ReadOptions read_options;
  701. PutKey(db.get(), write_options, TestKey(1, 2), "v12");
  702. PutKey(db.get(), write_options, TestKey(1, 4), "v14");
  703. PutKey(db.get(), write_options, TestKey(3, 3), "v33");
  704. PutKey(db.get(), write_options, TestKey(3, 4), "v34");
  705. db->Flush(FlushOptions());
  706. reinterpret_cast<DBImpl*>(db.get())->TEST_WaitForFlushMemTable();
  707. PutKey(db.get(), write_options, TestKey(1, 1), "v11");
  708. PutKey(db.get(), write_options, TestKey(1, 3), "v13");
  709. PutKey(db.get(), write_options, TestKey(2, 1), "v21");
  710. PutKey(db.get(), write_options, TestKey(2, 2), "v22");
  711. db->Flush(FlushOptions());
  712. reinterpret_cast<DBImpl*>(db.get())->TEST_WaitForFlushMemTable();
  713. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  714. SeekIterator(iter.get(), 1, 5);
  715. iter->Prev();
  716. ASSERT_EQ(iter->value(), v13);
  717. }
  718. TEST_F(PrefixTest, PrefixSeekModePrev3) {
  719. // Only for SkipListFactory
  720. // test SeekToLast() with iterate_upper_bound_ in prefix_seek_mode
  721. options.memtable_factory.reset(new SkipListFactory);
  722. options.write_buffer_size = 1024 * 1024;
  723. std::string v14("v14");
  724. TestKey upper_bound_key = TestKey(1, 5);
  725. std::string s;
  726. Slice upper_bound = TestKeyToSlice(s, upper_bound_key);
  727. {
  728. DestroyDB(kDbName, Options());
  729. auto db = OpenDb();
  730. WriteOptions write_options;
  731. ReadOptions read_options;
  732. read_options.iterate_upper_bound = &upper_bound;
  733. PutKey(db.get(), write_options, TestKey(1, 2), "v12");
  734. PutKey(db.get(), write_options, TestKey(1, 4), "v14");
  735. db->Flush(FlushOptions());
  736. reinterpret_cast<DBImpl*>(db.get())->TEST_WaitForFlushMemTable();
  737. PutKey(db.get(), write_options, TestKey(1, 1), "v11");
  738. PutKey(db.get(), write_options, TestKey(1, 3), "v13");
  739. PutKey(db.get(), write_options, TestKey(2, 1), "v21");
  740. PutKey(db.get(), write_options, TestKey(2, 2), "v22");
  741. db->Flush(FlushOptions());
  742. reinterpret_cast<DBImpl*>(db.get())->TEST_WaitForFlushMemTable();
  743. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  744. iter->SeekToLast();
  745. ASSERT_EQ(iter->value(), v14);
  746. }
  747. {
  748. DestroyDB(kDbName, Options());
  749. auto db = OpenDb();
  750. WriteOptions write_options;
  751. ReadOptions read_options;
  752. read_options.iterate_upper_bound = &upper_bound;
  753. PutKey(db.get(), write_options, TestKey(1, 2), "v12");
  754. PutKey(db.get(), write_options, TestKey(1, 4), "v14");
  755. PutKey(db.get(), write_options, TestKey(3, 3), "v33");
  756. PutKey(db.get(), write_options, TestKey(3, 4), "v34");
  757. db->Flush(FlushOptions());
  758. reinterpret_cast<DBImpl*>(db.get())->TEST_WaitForFlushMemTable();
  759. PutKey(db.get(), write_options, TestKey(1, 1), "v11");
  760. PutKey(db.get(), write_options, TestKey(1, 3), "v13");
  761. db->Flush(FlushOptions());
  762. reinterpret_cast<DBImpl*>(db.get())->TEST_WaitForFlushMemTable();
  763. std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
  764. iter->SeekToLast();
  765. ASSERT_EQ(iter->value(), v14);
  766. }
  767. }
  768. } // namespace ROCKSDB_NAMESPACE
  769. int main(int argc, char** argv) {
  770. ::testing::InitGoogleTest(&argc, argv);
  771. ParseCommandLineFlags(&argc, &argv, true);
  772. return RUN_ALL_TESTS();
  773. }
  774. #endif // GFLAGS
  775. #else
  776. #include <stdio.h>
  777. int main(int /*argc*/, char** /*argv*/) {
  778. fprintf(stderr,
  779. "SKIPPED as HashSkipList and HashLinkList are not supported in "
  780. "ROCKSDB_LITE\n");
  781. return 0;
  782. }
  783. #endif // !ROCKSDB_LITE