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   }
PrepareValue()73   bool PrepareValue() {
74     assert(Valid());
75     if (result_.value_prepared) {
76       return true;
77     }
78     if (iter_->PrepareValue()) {
79       result_.value_prepared = true;
80       return true;
81     }
82 
83     assert(!iter_->Valid());
84     valid_ = false;
85     return false;
86   }
Next()87   void Next() {
88     assert(iter_);
89     valid_ = iter_->NextAndGetResult(&result_);
90     assert(!valid_ || iter_->status().ok());
91   }
NextAndGetResult(IterateResult * result)92   bool NextAndGetResult(IterateResult* result) {
93     assert(iter_);
94     valid_ = iter_->NextAndGetResult(&result_);
95     *result = result_;
96     assert(!valid_ || iter_->status().ok());
97     return valid_;
98   }
Prev()99   void Prev() {
100     assert(iter_);
101     iter_->Prev();
102     Update();
103   }
Seek(const Slice & k)104   void Seek(const Slice& k) {
105     assert(iter_);
106     iter_->Seek(k);
107     Update();
108   }
SeekForPrev(const Slice & k)109   void SeekForPrev(const Slice& k) {
110     assert(iter_);
111     iter_->SeekForPrev(k);
112     Update();
113   }
SeekToFirst()114   void SeekToFirst() {
115     assert(iter_);
116     iter_->SeekToFirst();
117     Update();
118   }
SeekToLast()119   void SeekToLast() {
120     assert(iter_);
121     iter_->SeekToLast();
122     Update();
123   }
124 
MayBeOutOfLowerBound()125   bool MayBeOutOfLowerBound() {
126     assert(Valid());
127     return iter_->MayBeOutOfLowerBound();
128   }
129 
UpperBoundCheckResult()130   IterBoundCheck UpperBoundCheckResult() {
131     assert(Valid());
132     return result_.bound_check_result;
133   }
134 
SetPinnedItersMgr(PinnedIteratorsManager * pinned_iters_mgr)135   void SetPinnedItersMgr(PinnedIteratorsManager* pinned_iters_mgr) {
136     assert(iter_);
137     iter_->SetPinnedItersMgr(pinned_iters_mgr);
138   }
IsKeyPinned()139   bool IsKeyPinned() const {
140     assert(Valid());
141     return iter_->IsKeyPinned();
142   }
IsValuePinned()143   bool IsValuePinned() const {
144     assert(Valid());
145     return iter_->IsValuePinned();
146   }
147 
IsValuePrepared()148   bool IsValuePrepared() const {
149     return result_.value_prepared;
150   }
151 
user_key()152   Slice user_key() const {
153     assert(Valid());
154     return iter_->user_key();
155   }
156 
157  private:
Update()158   void Update() {
159     valid_ = iter_->Valid();
160     if (valid_) {
161       assert(iter_->status().ok());
162       result_.key = iter_->key();
163       result_.bound_check_result = IterBoundCheck::kUnknown;
164       result_.value_prepared = false;
165     }
166   }
167 
168   InternalIteratorBase<TValue>* iter_;
169   IterateResult result_;
170   bool valid_;
171 };
172 
173 using IteratorWrapper = IteratorWrapperBase<Slice>;
174 
175 class Arena;
176 // Return an empty iterator (yields nothing) allocated from arena.
177 template <class TValue = Slice>
178 extern InternalIteratorBase<TValue>* NewEmptyInternalIterator(Arena* arena);
179 
180 }  // namespace ROCKSDB_NAMESPACE
181