/Users/deen/code/yugabyte-db/src/yb/rocksdb/table/iterator_wrapper.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
21 | | // Use of this source code is governed by a BSD-style license that can be |
22 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
23 | | |
24 | | #pragma once |
25 | | |
26 | | #include <set> |
27 | | |
28 | | #include "yb/rocksdb/table/internal_iterator.h" |
29 | | |
30 | | namespace rocksdb { |
31 | | |
32 | | // A internal wrapper class with an interface similar to Iterator that |
33 | | // caches the valid() and key() results for an underlying iterator. |
34 | | // This can help avoid virtual function calls and also gives better |
35 | | // cache locality. |
36 | | class IteratorWrapper { |
37 | | public: |
38 | 80.6M | IteratorWrapper() : iter_(nullptr), iters_pinned_(false), valid_(false) {} |
39 | | explicit IteratorWrapper(InternalIterator* _iter) |
40 | 9.89M | : iter_(nullptr), iters_pinned_(false) { |
41 | 9.89M | Set(_iter); |
42 | 9.89M | } |
43 | 45.3M | ~IteratorWrapper() {} |
44 | 389M | InternalIterator* iter() const { return iter_; } |
45 | | |
46 | | // Takes the ownership of "_iter" and will delete it when destroyed. |
47 | | // Next call to Set() will destroy "_iter" except if PinData() was called. |
48 | 33.3M | void Set(InternalIterator* _iter) { |
49 | 33.3M | if (iters_pinned_ && iter_) { |
50 | | // keep old iterator until ReleasePinnedData() is called |
51 | 508k | pinned_iters_.insert(iter_); |
52 | 32.8M | } else { |
53 | 32.8M | delete iter_; |
54 | 32.8M | } |
55 | | |
56 | 33.3M | iter_ = _iter; |
57 | 33.3M | if (iter_ == nullptr) { |
58 | 528k | valid_ = false; |
59 | 32.8M | } else { |
60 | 32.8M | Update(); |
61 | 32.8M | if (iters_pinned_) { |
62 | | // Pin new iterator |
63 | 627k | Status s = iter_->PinData(); |
64 | 627k | assert(s.ok()); |
65 | 627k | } |
66 | 32.8M | } |
67 | 33.3M | } |
68 | | |
69 | 118k | Status PinData() { |
70 | 118k | Status s; |
71 | 118k | if (iters_pinned_) { |
72 | 0 | return s; |
73 | 0 | } |
74 | | |
75 | 118k | if (iter_) { |
76 | 39 | s = iter_->PinData(); |
77 | 39 | } |
78 | | |
79 | 118k | if (s.ok()) { |
80 | 118k | iters_pinned_ = true; |
81 | 118k | } |
82 | | |
83 | 118k | return s; |
84 | 118k | } |
85 | | |
86 | 0 | Status ReleasePinnedData() { |
87 | 0 | Status s; |
88 | 0 | if (!iters_pinned_) { |
89 | 0 | return s; |
90 | 0 | } |
91 | 0 |
|
92 | 0 | if (iter_) { |
93 | 0 | s = iter_->ReleasePinnedData(); |
94 | 0 | } |
95 | 0 |
|
96 | 0 | if (s.ok()) { |
97 | 0 | iters_pinned_ = false; |
98 | 0 | // No need to call ReleasePinnedData() for pinned_iters_ |
99 | 0 | // since we will delete them |
100 | 0 | DeletePinnedIterators(false); |
101 | 0 | } |
102 | 0 |
|
103 | 0 | return s; |
104 | 0 | } |
105 | | |
106 | 250M | bool IsKeyPinned() const { |
107 | 250M | assert(iter_); |
108 | 250M | return iters_pinned_ && iter_->IsKeyPinned(); |
109 | 250M | } |
110 | | |
111 | 21.2M | void DeleteIter(bool is_arena_mode) { |
112 | 21.2M | if (iter_ && pinned_iters_.find(iter_) == pinned_iters_.end()) { |
113 | 20.9M | DestroyIterator(iter_, is_arena_mode); |
114 | 20.9M | } |
115 | 21.2M | DeletePinnedIterators(is_arena_mode); |
116 | 21.2M | } |
117 | | |
118 | | // Iterator interface methods |
119 | 5.74G | bool Valid() const { return valid_; } |
120 | 1.71G | Slice key() const { assert(Valid()); return key_; } |
121 | 1.59G | Slice value() const { assert(Valid()); return iter_->value(); } |
122 | | // Methods below require iter() != nullptr |
123 | 47.7M | Status status() const { assert(iter_); return iter_->status(); } |
124 | 593M | void Next() { assert(iter_); iter_->Next(); Update(); } |
125 | 4.90M | void Prev() { assert(iter_); iter_->Prev(); Update(); } |
126 | 82.2M | void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); } |
127 | 3.32M | void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); } |
128 | 1.10M | void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); } |
129 | | |
130 | | private: |
131 | 715M | void Update() { |
132 | 715M | valid_ = iter_->Valid(); |
133 | 715M | if (valid_) { |
134 | 676M | key_ = iter_->key(); |
135 | 676M | } |
136 | 715M | } |
137 | | |
138 | 21.2M | void DeletePinnedIterators(bool is_arena_mode) { |
139 | 508k | for (auto it : pinned_iters_) { |
140 | 508k | DestroyIterator(it, is_arena_mode); |
141 | 508k | } |
142 | 21.2M | pinned_iters_.clear(); |
143 | 21.2M | } |
144 | | |
145 | 21.4M | inline void DestroyIterator(InternalIterator* it, bool is_arena_mode) { |
146 | 21.4M | if (!is_arena_mode) { |
147 | 15.3M | delete it; |
148 | 6.11M | } else { |
149 | 6.11M | it->~InternalIterator(); |
150 | 6.11M | } |
151 | 21.4M | } |
152 | | |
153 | | InternalIterator* iter_; |
154 | | // If set to true, current and future iterators wont be deleted. |
155 | | bool iters_pinned_; |
156 | | // List of past iterators that are pinned and wont be deleted as long as |
157 | | // iters_pinned_ is true. When we are pinning iterators this set will contain |
158 | | // iterators of previous data blocks to keep them from being deleted. |
159 | | std::set<InternalIterator*> pinned_iters_; |
160 | | bool valid_; |
161 | | Slice key_; |
162 | | }; |
163 | | |
164 | | class Arena; |
165 | | // Return an empty iterator (yields nothing) allocated from arena. |
166 | | extern InternalIterator* NewEmptyInternalIterator(Arena* arena); |
167 | | |
168 | | // Return an empty iterator with the specified status, allocated arena. |
169 | | extern InternalIterator* NewErrorInternalIterator(const Status& status, |
170 | | Arena* arena); |
171 | | |
172 | | } // namespace rocksdb |