/src/rocksdb/table/two_level_iterator.cc
Line | Count | Source |
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 | | #include "table/two_level_iterator.h" |
11 | | |
12 | | #include "db/pinned_iterators_manager.h" |
13 | | #include "memory/arena.h" |
14 | | #include "rocksdb/options.h" |
15 | | #include "rocksdb/table.h" |
16 | | #include "table/block_based/block.h" |
17 | | #include "table/format.h" |
18 | | |
19 | | namespace ROCKSDB_NAMESPACE { |
20 | | |
21 | | namespace { |
22 | | |
23 | | class TwoLevelIndexIterator : public InternalIteratorBase<IndexValue> { |
24 | | public: |
25 | | explicit TwoLevelIndexIterator( |
26 | | TwoLevelIteratorState* state, |
27 | | InternalIteratorBase<IndexValue>* first_level_iter); |
28 | | |
29 | 0 | ~TwoLevelIndexIterator() override { |
30 | 0 | first_level_iter_.DeleteIter(false /* is_arena_mode */); |
31 | 0 | second_level_iter_.DeleteIter(false /* is_arena_mode */); |
32 | 0 | delete state_; |
33 | 0 | } |
34 | | |
35 | | void Seek(const Slice& target) override; |
36 | | void SeekForPrev(const Slice& target) override; |
37 | | void SeekToFirst() override; |
38 | | void SeekToLast() override; |
39 | | void Next() override; |
40 | | void Prev() override; |
41 | | |
42 | 0 | bool Valid() const override { return second_level_iter_.Valid(); } |
43 | 0 | Slice key() const override { |
44 | 0 | assert(Valid()); |
45 | 0 | return second_level_iter_.key(); |
46 | 0 | } |
47 | 0 | Slice user_key() const override { |
48 | 0 | assert(Valid()); |
49 | 0 | return second_level_iter_.user_key(); |
50 | 0 | } |
51 | 0 | IndexValue value() const override { |
52 | 0 | assert(Valid()); |
53 | 0 | return second_level_iter_.value(); |
54 | 0 | } |
55 | 0 | Status status() const override { |
56 | 0 | if (!first_level_iter_.status().ok()) { |
57 | 0 | assert(second_level_iter_.iter() == nullptr); |
58 | 0 | return first_level_iter_.status(); |
59 | 0 | } else if (second_level_iter_.iter() != nullptr && |
60 | 0 | !second_level_iter_.status().ok()) { |
61 | 0 | return second_level_iter_.status(); |
62 | 0 | } else { |
63 | 0 | return status_; |
64 | 0 | } |
65 | 0 | } |
66 | | void SetPinnedItersMgr( |
67 | 0 | PinnedIteratorsManager* /*pinned_iters_mgr*/) override {} |
68 | 0 | bool IsKeyPinned() const override { return false; } |
69 | 0 | bool IsValuePinned() const override { return false; } |
70 | | |
71 | | private: |
72 | 0 | void SaveError(const Status& s) { |
73 | 0 | if (status_.ok() && !s.ok()) { |
74 | 0 | status_ = s; |
75 | 0 | } |
76 | 0 | } |
77 | | void SkipEmptyDataBlocksForward(); |
78 | | void SkipEmptyDataBlocksBackward(); |
79 | | void SetSecondLevelIterator(InternalIteratorBase<IndexValue>* iter); |
80 | | void InitDataBlock(); |
81 | | |
82 | | TwoLevelIteratorState* state_; |
83 | | IteratorWrapperBase<IndexValue> first_level_iter_; |
84 | | IteratorWrapperBase<IndexValue> second_level_iter_; // May be nullptr |
85 | | Status status_; |
86 | | // If second_level_iter is non-nullptr, then "data_block_handle_" holds the |
87 | | // "index_value" passed to block_function_ to create the second_level_iter. |
88 | | BlockHandle data_block_handle_; |
89 | | }; |
90 | | |
91 | | TwoLevelIndexIterator::TwoLevelIndexIterator( |
92 | | TwoLevelIteratorState* state, |
93 | | InternalIteratorBase<IndexValue>* first_level_iter) |
94 | 0 | : state_(state), first_level_iter_(first_level_iter) {} |
95 | | |
96 | 0 | void TwoLevelIndexIterator::Seek(const Slice& target) { |
97 | 0 | first_level_iter_.Seek(target); |
98 | |
|
99 | 0 | InitDataBlock(); |
100 | 0 | if (second_level_iter_.iter() != nullptr) { |
101 | 0 | second_level_iter_.Seek(target); |
102 | 0 | } |
103 | 0 | SkipEmptyDataBlocksForward(); |
104 | 0 | } |
105 | | |
106 | 0 | void TwoLevelIndexIterator::SeekForPrev(const Slice& target) { |
107 | 0 | first_level_iter_.Seek(target); |
108 | 0 | InitDataBlock(); |
109 | 0 | if (second_level_iter_.iter() != nullptr) { |
110 | 0 | second_level_iter_.SeekForPrev(target); |
111 | 0 | } |
112 | 0 | if (!Valid()) { |
113 | 0 | if (!first_level_iter_.Valid() && first_level_iter_.status().ok()) { |
114 | 0 | first_level_iter_.SeekToLast(); |
115 | 0 | InitDataBlock(); |
116 | 0 | if (second_level_iter_.iter() != nullptr) { |
117 | 0 | second_level_iter_.SeekForPrev(target); |
118 | 0 | } |
119 | 0 | } |
120 | 0 | SkipEmptyDataBlocksBackward(); |
121 | 0 | } |
122 | 0 | } |
123 | | |
124 | 0 | void TwoLevelIndexIterator::SeekToFirst() { |
125 | 0 | first_level_iter_.SeekToFirst(); |
126 | 0 | InitDataBlock(); |
127 | 0 | if (second_level_iter_.iter() != nullptr) { |
128 | 0 | second_level_iter_.SeekToFirst(); |
129 | 0 | } |
130 | 0 | SkipEmptyDataBlocksForward(); |
131 | 0 | } |
132 | | |
133 | 0 | void TwoLevelIndexIterator::SeekToLast() { |
134 | 0 | first_level_iter_.SeekToLast(); |
135 | 0 | InitDataBlock(); |
136 | 0 | if (second_level_iter_.iter() != nullptr) { |
137 | 0 | second_level_iter_.SeekToLast(); |
138 | 0 | } |
139 | 0 | SkipEmptyDataBlocksBackward(); |
140 | 0 | } |
141 | | |
142 | 0 | void TwoLevelIndexIterator::Next() { |
143 | 0 | assert(Valid()); |
144 | 0 | second_level_iter_.Next(); |
145 | 0 | SkipEmptyDataBlocksForward(); |
146 | 0 | } |
147 | | |
148 | 0 | void TwoLevelIndexIterator::Prev() { |
149 | 0 | assert(Valid()); |
150 | 0 | second_level_iter_.Prev(); |
151 | 0 | SkipEmptyDataBlocksBackward(); |
152 | 0 | } |
153 | | |
154 | 0 | void TwoLevelIndexIterator::SkipEmptyDataBlocksForward() { |
155 | 0 | while (second_level_iter_.iter() == nullptr || |
156 | 0 | (!second_level_iter_.Valid() && second_level_iter_.status().ok())) { |
157 | | // Move to next block |
158 | 0 | if (!first_level_iter_.Valid()) { |
159 | 0 | SetSecondLevelIterator(nullptr); |
160 | 0 | return; |
161 | 0 | } |
162 | 0 | first_level_iter_.Next(); |
163 | 0 | InitDataBlock(); |
164 | 0 | if (second_level_iter_.iter() != nullptr) { |
165 | 0 | second_level_iter_.SeekToFirst(); |
166 | 0 | } |
167 | 0 | } |
168 | 0 | } |
169 | | |
170 | 0 | void TwoLevelIndexIterator::SkipEmptyDataBlocksBackward() { |
171 | 0 | while (second_level_iter_.iter() == nullptr || |
172 | 0 | (!second_level_iter_.Valid() && second_level_iter_.status().ok())) { |
173 | | // Move to next block |
174 | 0 | if (!first_level_iter_.Valid()) { |
175 | 0 | SetSecondLevelIterator(nullptr); |
176 | 0 | return; |
177 | 0 | } |
178 | 0 | first_level_iter_.Prev(); |
179 | 0 | InitDataBlock(); |
180 | 0 | if (second_level_iter_.iter() != nullptr) { |
181 | 0 | second_level_iter_.SeekToLast(); |
182 | 0 | } |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | void TwoLevelIndexIterator::SetSecondLevelIterator( |
187 | 0 | InternalIteratorBase<IndexValue>* iter) { |
188 | 0 | InternalIteratorBase<IndexValue>* old_iter = second_level_iter_.Set(iter); |
189 | 0 | delete old_iter; |
190 | 0 | } |
191 | | |
192 | 0 | void TwoLevelIndexIterator::InitDataBlock() { |
193 | 0 | if (!first_level_iter_.Valid()) { |
194 | 0 | SetSecondLevelIterator(nullptr); |
195 | 0 | } else { |
196 | 0 | BlockHandle handle = first_level_iter_.value().handle; |
197 | 0 | if (second_level_iter_.iter() != nullptr && |
198 | 0 | !second_level_iter_.status().IsIncomplete() && |
199 | 0 | handle.offset() == data_block_handle_.offset()) { |
200 | | // second_level_iter is already constructed with this iterator, so |
201 | | // no need to change anything |
202 | 0 | } else { |
203 | 0 | InternalIteratorBase<IndexValue>* iter = |
204 | 0 | state_->NewSecondaryIterator(handle); |
205 | 0 | data_block_handle_ = handle; |
206 | 0 | SetSecondLevelIterator(iter); |
207 | 0 | if (iter == nullptr) { |
208 | 0 | status_ = Status::Corruption("Missing block for partition " + |
209 | 0 | handle.ToString()); |
210 | 0 | } |
211 | 0 | } |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | | } // namespace |
216 | | |
217 | | InternalIteratorBase<IndexValue>* NewTwoLevelIterator( |
218 | | TwoLevelIteratorState* state, |
219 | 0 | InternalIteratorBase<IndexValue>* first_level_iter) { |
220 | 0 | return new TwoLevelIndexIterator(state, first_level_iter); |
221 | 0 | } |
222 | | } // namespace ROCKSDB_NAMESPACE |