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 
10 #pragma once
11 
12 #include <set>
13 
14 #include "table/internal_iterator.h"
15 #include "test_util/sync_point.h"
16 
17 namespace ROCKSDB_NAMESPACE {
18 
19 // A internal wrapper class with an interface similar to Iterator that caches
20 // the valid() and key() results for an underlying iterator.
21 // This can help avoid virtual function calls and also gives better
22 // cache locality.
23 template <class TValue = Slice>
24 class IteratorWrapperBase {
25  public:
IteratorWrapperBase()26   IteratorWrapperBase() : iter_(nullptr), valid_(false) {}
IteratorWrapperBase(InternalIteratorBase<TValue> * _iter)27   explicit IteratorWrapperBase(InternalIteratorBase<TValue>* _iter)
28       : iter_(nullptr) {
29     Set(_iter);
30   }
~IteratorWrapperBase()31   ~IteratorWrapperBase() {}
iter()32   InternalIteratorBase<TValue>* iter() const { return iter_; }
33 
34   // Set the underlying Iterator to _iter and return
35   // previous underlying Iterator.
Set(InternalIteratorBase<TValue> * _iter)36   InternalIteratorBase<TValue>* Set(InternalIteratorBase<TValue>* _iter) {
37     InternalIteratorBase<TValue>* old_iter = iter_;
38 
39     iter_ = _iter;
40     if (iter_ == nullptr) {
41       valid_ = false;
42     } else {
43       Update();
44     }
45     return old_iter;
46   }
47 
DeleteIter(bool is_arena_mode)48   void DeleteIter(bool is_arena_mode) {
49     if (iter_) {
50       if (!is_arena_mode) {
51         delete iter_;
52       } else {
53         iter_->~InternalIteratorBase<TValue>();
54       }
55     }
56   }
57 
58   // Iterator interface methods
Valid()59   bool Valid() const { return valid_; }
key()60   Slice key() const {
61     assert(Valid());
62     return result_.key;
63   }
value()64   TValue value() const {
65     assert(Valid());
66     return iter_->value();
67   }
68   // Methods below require iter() != nullptr
status()69   Status status() const {
70     assert(iter_);
71     return iter_->status();
72   }
Next()73   void Next() {
74     assert(iter_);
75     valid_ = iter_->NextAndGetResult(&result_);
76     assert(!valid_ || iter_->status().ok());
77   }
Prev()78   void Prev() {
79     assert(iter_);
80     iter_->Prev();
81     Update();
82   }
Seek(const Slice & k)83   void Seek(const Slice& k) {
84     assert(iter_);
85     iter_->Seek(k);
86     Update();
87   }
SeekForPrev(const Slice & k)88   void SeekForPrev(const Slice& k) {
89     assert(iter_);
90     iter_->SeekForPrev(k);
91     Update();
92   }
SeekToFirst()93   void SeekToFirst() {
94     assert(iter_);
95     iter_->SeekToFirst();
96     Update();
97   }
SeekToLast()98   void SeekToLast() {
99     assert(iter_);
100     iter_->SeekToLast();
101     Update();
102   }
103 
MayBeOutOfLowerBound()104   bool MayBeOutOfLowerBound() {
105     assert(Valid());
106     return iter_->MayBeOutOfLowerBound();
107   }
108 
MayBeOutOfUpperBound()109   bool MayBeOutOfUpperBound() {
110     assert(Valid());
111     return result_.may_be_out_of_upper_bound;
112   }
113 
SetPinnedItersMgr(PinnedIteratorsManager * pinned_iters_mgr)114   void SetPinnedItersMgr(PinnedIteratorsManager* pinned_iters_mgr) {
115     assert(iter_);
116     iter_->SetPinnedItersMgr(pinned_iters_mgr);
117   }
IsKeyPinned()118   bool IsKeyPinned() const {
119     assert(Valid());
120     return iter_->IsKeyPinned();
121   }
IsValuePinned()122   bool IsValuePinned() const {
123     assert(Valid());
124     return iter_->IsValuePinned();
125   }
126 
127  private:
Update()128   void Update() {
129     valid_ = iter_->Valid();
130     if (valid_) {
131       assert(iter_->status().ok());
132       result_.key = iter_->key();
133       result_.may_be_out_of_upper_bound = true;
134     }
135   }
136 
137   InternalIteratorBase<TValue>* iter_;
138   IterateResult result_;
139   bool valid_;
140 };
141 
142 using IteratorWrapper = IteratorWrapperBase<Slice>;
143 
144 class Arena;
145 // Return an empty iterator (yields nothing) allocated from arena.
146 template <class TValue = Slice>
147 extern InternalIteratorBase<TValue>* NewEmptyInternalIterator(Arena* arena);
148 
149 }  // namespace ROCKSDB_NAMESPACE
150