skiplistrep.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. #include "db/memtable.h"
  7. #include "memory/arena.h"
  8. #include "memtable/inlineskiplist.h"
  9. #include "rocksdb/memtablerep.h"
  10. namespace ROCKSDB_NAMESPACE {
  11. namespace {
  12. class SkipListRep : public MemTableRep {
  13. InlineSkipList<const MemTableRep::KeyComparator&> skip_list_;
  14. const MemTableRep::KeyComparator& cmp_;
  15. const SliceTransform* transform_;
  16. const size_t lookahead_;
  17. friend class LookaheadIterator;
  18. public:
  19. explicit SkipListRep(const MemTableRep::KeyComparator& compare,
  20. Allocator* allocator, const SliceTransform* transform,
  21. const size_t lookahead)
  22. : MemTableRep(allocator),
  23. skip_list_(compare, allocator),
  24. cmp_(compare),
  25. transform_(transform),
  26. lookahead_(lookahead) {}
  27. KeyHandle Allocate(const size_t len, char** buf) override {
  28. *buf = skip_list_.AllocateKey(len);
  29. return static_cast<KeyHandle>(*buf);
  30. }
  31. // Insert key into the list.
  32. // REQUIRES: nothing that compares equal to key is currently in the list.
  33. void Insert(KeyHandle handle) override {
  34. skip_list_.Insert(static_cast<char*>(handle));
  35. }
  36. bool InsertKey(KeyHandle handle) override {
  37. return skip_list_.Insert(static_cast<char*>(handle));
  38. }
  39. void InsertWithHint(KeyHandle handle, void** hint) override {
  40. skip_list_.InsertWithHint(static_cast<char*>(handle), hint);
  41. }
  42. bool InsertKeyWithHint(KeyHandle handle, void** hint) override {
  43. return skip_list_.InsertWithHint(static_cast<char*>(handle), hint);
  44. }
  45. void InsertWithHintConcurrently(KeyHandle handle, void** hint) override {
  46. skip_list_.InsertWithHintConcurrently(static_cast<char*>(handle), hint);
  47. }
  48. bool InsertKeyWithHintConcurrently(KeyHandle handle, void** hint) override {
  49. return skip_list_.InsertWithHintConcurrently(static_cast<char*>(handle),
  50. hint);
  51. }
  52. void InsertConcurrently(KeyHandle handle) override {
  53. skip_list_.InsertConcurrently(static_cast<char*>(handle));
  54. }
  55. bool InsertKeyConcurrently(KeyHandle handle) override {
  56. return skip_list_.InsertConcurrently(static_cast<char*>(handle));
  57. }
  58. // Returns true iff an entry that compares equal to key is in the list.
  59. bool Contains(const char* key) const override {
  60. return skip_list_.Contains(key);
  61. }
  62. size_t ApproximateMemoryUsage() override {
  63. // All memory is allocated through allocator; nothing to report here
  64. return 0;
  65. }
  66. void Get(const LookupKey& k, void* callback_args,
  67. bool (*callback_func)(void* arg, const char* entry)) override {
  68. SkipListRep::Iterator iter(&skip_list_);
  69. Slice dummy_slice;
  70. for (iter.Seek(dummy_slice, k.memtable_key().data());
  71. iter.Valid() && callback_func(callback_args, iter.key()); iter.Next()) {
  72. }
  73. }
  74. uint64_t ApproximateNumEntries(const Slice& start_ikey,
  75. const Slice& end_ikey) override {
  76. std::string tmp;
  77. uint64_t start_count =
  78. skip_list_.EstimateCount(EncodeKey(&tmp, start_ikey));
  79. uint64_t end_count = skip_list_.EstimateCount(EncodeKey(&tmp, end_ikey));
  80. return (end_count >= start_count) ? (end_count - start_count) : 0;
  81. }
  82. ~SkipListRep() override {}
  83. // Iteration over the contents of a skip list
  84. class Iterator : public MemTableRep::Iterator {
  85. InlineSkipList<const MemTableRep::KeyComparator&>::Iterator iter_;
  86. public:
  87. // Initialize an iterator over the specified list.
  88. // The returned iterator is not valid.
  89. explicit Iterator(
  90. const InlineSkipList<const MemTableRep::KeyComparator&>* list)
  91. : iter_(list) {}
  92. ~Iterator() override {}
  93. // Returns true iff the iterator is positioned at a valid node.
  94. bool Valid() const override { return iter_.Valid(); }
  95. // Returns the key at the current position.
  96. // REQUIRES: Valid()
  97. const char* key() const override { return iter_.key(); }
  98. // Advances to the next position.
  99. // REQUIRES: Valid()
  100. void Next() override { iter_.Next(); }
  101. // Advances to the previous position.
  102. // REQUIRES: Valid()
  103. void Prev() override { iter_.Prev(); }
  104. // Advance to the first entry with a key >= target
  105. void Seek(const Slice& user_key, const char* memtable_key) override {
  106. if (memtable_key != nullptr) {
  107. iter_.Seek(memtable_key);
  108. } else {
  109. iter_.Seek(EncodeKey(&tmp_, user_key));
  110. }
  111. }
  112. // Retreat to the last entry with a key <= target
  113. void SeekForPrev(const Slice& user_key, const char* memtable_key) override {
  114. if (memtable_key != nullptr) {
  115. iter_.SeekForPrev(memtable_key);
  116. } else {
  117. iter_.SeekForPrev(EncodeKey(&tmp_, user_key));
  118. }
  119. }
  120. // Position at the first entry in list.
  121. // Final state of iterator is Valid() iff list is not empty.
  122. void SeekToFirst() override { iter_.SeekToFirst(); }
  123. // Position at the last entry in list.
  124. // Final state of iterator is Valid() iff list is not empty.
  125. void SeekToLast() override { iter_.SeekToLast(); }
  126. protected:
  127. std::string tmp_; // For passing to EncodeKey
  128. };
  129. // Iterator over the contents of a skip list which also keeps track of the
  130. // previously visited node. In Seek(), it examines a few nodes after it
  131. // first, falling back to O(log n) search from the head of the list only if
  132. // the target key hasn't been found.
  133. class LookaheadIterator : public MemTableRep::Iterator {
  134. public:
  135. explicit LookaheadIterator(const SkipListRep& rep) :
  136. rep_(rep), iter_(&rep_.skip_list_), prev_(iter_) {}
  137. ~LookaheadIterator() override {}
  138. bool Valid() const override { return iter_.Valid(); }
  139. const char* key() const override {
  140. assert(Valid());
  141. return iter_.key();
  142. }
  143. void Next() override {
  144. assert(Valid());
  145. bool advance_prev = true;
  146. if (prev_.Valid()) {
  147. auto k1 = rep_.UserKey(prev_.key());
  148. auto k2 = rep_.UserKey(iter_.key());
  149. if (k1.compare(k2) == 0) {
  150. // same user key, don't move prev_
  151. advance_prev = false;
  152. } else if (rep_.transform_) {
  153. // only advance prev_ if it has the same prefix as iter_
  154. auto t1 = rep_.transform_->Transform(k1);
  155. auto t2 = rep_.transform_->Transform(k2);
  156. advance_prev = t1.compare(t2) == 0;
  157. }
  158. }
  159. if (advance_prev) {
  160. prev_ = iter_;
  161. }
  162. iter_.Next();
  163. }
  164. void Prev() override {
  165. assert(Valid());
  166. iter_.Prev();
  167. prev_ = iter_;
  168. }
  169. void Seek(const Slice& internal_key, const char* memtable_key) override {
  170. const char *encoded_key =
  171. (memtable_key != nullptr) ?
  172. memtable_key : EncodeKey(&tmp_, internal_key);
  173. if (prev_.Valid() && rep_.cmp_(encoded_key, prev_.key()) >= 0) {
  174. // prev_.key() is smaller or equal to our target key; do a quick
  175. // linear search (at most lookahead_ steps) starting from prev_
  176. iter_ = prev_;
  177. size_t cur = 0;
  178. while (cur++ <= rep_.lookahead_ && iter_.Valid()) {
  179. if (rep_.cmp_(encoded_key, iter_.key()) <= 0) {
  180. return;
  181. }
  182. Next();
  183. }
  184. }
  185. iter_.Seek(encoded_key);
  186. prev_ = iter_;
  187. }
  188. void SeekForPrev(const Slice& internal_key,
  189. const char* memtable_key) override {
  190. const char* encoded_key = (memtable_key != nullptr)
  191. ? memtable_key
  192. : EncodeKey(&tmp_, internal_key);
  193. iter_.SeekForPrev(encoded_key);
  194. prev_ = iter_;
  195. }
  196. void SeekToFirst() override {
  197. iter_.SeekToFirst();
  198. prev_ = iter_;
  199. }
  200. void SeekToLast() override {
  201. iter_.SeekToLast();
  202. prev_ = iter_;
  203. }
  204. protected:
  205. std::string tmp_; // For passing to EncodeKey
  206. private:
  207. const SkipListRep& rep_;
  208. InlineSkipList<const MemTableRep::KeyComparator&>::Iterator iter_;
  209. InlineSkipList<const MemTableRep::KeyComparator&>::Iterator prev_;
  210. };
  211. MemTableRep::Iterator* GetIterator(Arena* arena = nullptr) override {
  212. if (lookahead_ > 0) {
  213. void *mem =
  214. arena ? arena->AllocateAligned(sizeof(SkipListRep::LookaheadIterator))
  215. : operator new(sizeof(SkipListRep::LookaheadIterator));
  216. return new (mem) SkipListRep::LookaheadIterator(*this);
  217. } else {
  218. void *mem =
  219. arena ? arena->AllocateAligned(sizeof(SkipListRep::Iterator))
  220. : operator new(sizeof(SkipListRep::Iterator));
  221. return new (mem) SkipListRep::Iterator(&skip_list_);
  222. }
  223. }
  224. };
  225. }
  226. MemTableRep* SkipListFactory::CreateMemTableRep(
  227. const MemTableRep::KeyComparator& compare, Allocator* allocator,
  228. const SliceTransform* transform, Logger* /*logger*/) {
  229. return new SkipListRep(compare, allocator, transform, lookahead_);
  230. }
  231. } // namespace ROCKSDB_NAMESPACE