-
Notifications
You must be signed in to change notification settings - Fork 6.3k
/
internal_iterator.h
242 lines (202 loc) · 9.71 KB
/
internal_iterator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
#pragma once
#include <string>
#include "db/dbformat.h"
#include "file/readahead_file_info.h"
#include "rocksdb/comparator.h"
#include "rocksdb/iterator.h"
#include "rocksdb/status.h"
#include "table/format.h"
namespace ROCKSDB_NAMESPACE {
class PinnedIteratorsManager;
enum class IterBoundCheck : char {
kUnknown = 0,
kOutOfBound,
kInbound,
};
struct IterateResult {
Slice key;
IterBoundCheck bound_check_result = IterBoundCheck::kUnknown;
// If false, PrepareValue() needs to be called before value().
bool value_prepared = true;
};
template <class TValue>
class InternalIteratorBase : public Cleanable {
public:
InternalIteratorBase() {}
// No copying allowed
InternalIteratorBase(const InternalIteratorBase&) = delete;
InternalIteratorBase& operator=(const InternalIteratorBase&) = delete;
virtual ~InternalIteratorBase() {}
// This iterator will only process range tombstones with sequence
// number <= `read_seqno`.
// Noop for most child classes.
// For range tombstone iterators (TruncatedRangeDelIterator,
// FragmentedRangeTombstoneIterator), will only return range tombstones with
// sequence number <= `read_seqno`. For LevelIterator, it may open new table
// files and create new range tombstone iterators during scanning. It will use
// `read_seqno` as the sequence number for creating new range tombstone
// iterators.
virtual void SetRangeDelReadSeqno(SequenceNumber /* read_seqno */) {}
// An iterator is either positioned at a key/value pair, or
// not valid. This method returns true iff the iterator is valid.
// Always returns false if !status().ok().
virtual bool Valid() const = 0;
// Position at the first key in the source. The iterator is Valid()
// after this call iff the source is not empty.
virtual void SeekToFirst() = 0;
// Position at the last key in the source. The iterator is
// Valid() after this call iff the source is not empty.
virtual void SeekToLast() = 0;
// Position at the first key in the source that at or past target
// The iterator is Valid() after this call iff the source contains
// an entry that comes at or past target.
// All Seek*() methods clear any error status() that the iterator had prior to
// the call; after the seek, status() indicates only the error (if any) that
// happened during the seek, not any past errors.
// 'target' contains user timestamp if timestamp is enabled.
virtual void Seek(const Slice& target) = 0;
// Position at the first key in the source that at or before target
// The iterator is Valid() after this call iff the source contains
// an entry that comes at or before target.
virtual void SeekForPrev(const Slice& target) = 0;
// Moves to the next entry in the source. After this call, Valid() is
// true iff the iterator was not positioned at the last entry in the source.
// REQUIRES: Valid()
virtual void Next() = 0;
// Moves to the next entry in the source, and return result. Iterator
// implementation should override this method to help methods inline better,
// or when UpperBoundCheckResult() is non-trivial.
// REQUIRES: Valid()
virtual bool NextAndGetResult(IterateResult* result) {
Next();
bool is_valid = Valid();
if (is_valid) {
result->key = key();
// Default may_be_out_of_upper_bound to true to avoid unnecessary virtual
// call. If an implementation has non-trivial UpperBoundCheckResult(),
// it should also override NextAndGetResult().
result->bound_check_result = IterBoundCheck::kUnknown;
result->value_prepared = false;
assert(UpperBoundCheckResult() != IterBoundCheck::kOutOfBound);
}
return is_valid;
}
// Moves to the previous entry in the source. After this call, Valid() is
// true iff the iterator was not positioned at the first entry in source.
// REQUIRES: Valid()
virtual void Prev() = 0;
// Return the key for the current entry. The underlying storage for
// the returned slice is valid only until the next modification of
// the iterator.
// REQUIRES: Valid()
virtual Slice key() const = 0;
// Returns the approximate write time of this entry, which is deduced from
// sequence number if sequence number to time mapping is available.
// The default implementation returns maximum uint64_t and that indicates the
// write time is unknown.
virtual uint64_t write_unix_time() const {
return std::numeric_limits<uint64_t>::max();
}
// Return user key for the current entry.
// REQUIRES: Valid()
virtual Slice user_key() const { return ExtractUserKey(key()); }
// Return the value for the current entry. The underlying storage for
// the returned slice is valid only until the next modification of
// the iterator.
// REQUIRES: Valid()
// REQUIRES: PrepareValue() has been called if needed (see PrepareValue()).
virtual TValue value() const = 0;
// If an error has occurred, return it. Else return an ok status.
// If non-blocking IO is requested and this operation cannot be
// satisfied without doing some IO, then this returns Status::Incomplete().
virtual Status status() const = 0;
// For some types of iterators, sometimes Seek()/Next()/SeekForPrev()/etc may
// load key but not value (to avoid the IO cost of reading the value from disk
// if it won't be not needed). This method loads the value in such situation.
//
// Needs to be called before value() at least once after each iterator
// movement (except if IterateResult::value_prepared = true), for iterators
// created with allow_unprepared_value = true.
//
// Returns false if an error occurred; in this case Valid() is also changed
// to false, and status() is changed to non-ok.
// REQUIRES: Valid()
virtual bool PrepareValue() { return true; }
// Keys return from this iterator can be smaller than iterate_lower_bound.
virtual bool MayBeOutOfLowerBound() { return true; }
// If the iterator has checked the key against iterate_upper_bound, returns
// the result here. The function can be used by user of the iterator to skip
// their own checks. If Valid() = true, IterBoundCheck::kUnknown is always
// a valid value. If Valid() = false, IterBoundCheck::kOutOfBound indicates
// that the iterator is filtered out by upper bound checks.
virtual IterBoundCheck UpperBoundCheckResult() {
return IterBoundCheck::kUnknown;
}
// Pass the PinnedIteratorsManager to the Iterator, most Iterators don't
// communicate with PinnedIteratorsManager so default implementation is no-op
// but for Iterators that need to communicate with PinnedIteratorsManager
// they will implement this function and use the passed pointer to communicate
// with PinnedIteratorsManager.
virtual void SetPinnedItersMgr(PinnedIteratorsManager* /*pinned_iters_mgr*/) {
}
// If true, this means that the Slice returned by key() is valid as long as
// PinnedIteratorsManager::ReleasePinnedData is not called and the
// Iterator is not deleted.
//
// IsKeyPinned() is guaranteed to always return true if
// - Iterator is created with ReadOptions::pin_data = true
// - DB tables were created with BlockBasedTableOptions::use_delta_encoding
// set to false.
virtual bool IsKeyPinned() const { return false; }
// If true, this means that the Slice returned by value() is valid as long as
// PinnedIteratorsManager::ReleasePinnedData is not called and the
// Iterator is not deleted.
// REQUIRES: Same as for value().
virtual bool IsValuePinned() const { return false; }
virtual Status GetProperty(std::string /*prop_name*/, std::string* /*prop*/) {
return Status::NotSupported("");
}
// When iterator moves from one file to another file at same level, new file's
// readahead state (details of last block read) is updated with previous
// file's readahead state. This way internal readahead_size of Prefetch Buffer
// doesn't start from scratch and can fall back to 8KB with no prefetch if
// reads are not sequential.
//
// Default implementation is no-op and its implemented by iterators.
virtual void GetReadaheadState(ReadaheadFileInfo* /*readahead_file_info*/) {}
// Default implementation is no-op and its implemented by iterators.
virtual void SetReadaheadState(ReadaheadFileInfo* /*readahead_file_info*/) {}
// When used under merging iterator, LevelIterator treats file boundaries
// as sentinel keys to prevent it from moving to next SST file before range
// tombstones in the current SST file are no longer needed. This method makes
// it cheap to check if the current key is a sentinel key. This should only be
// used by MergingIterator and LevelIterator for now.
virtual bool IsDeleteRangeSentinelKey() const { return false; }
protected:
void SeekForPrevImpl(const Slice& target, const CompareInterface* cmp) {
Seek(target);
if (!Valid()) {
SeekToLast();
}
while (Valid() && cmp->Compare(target, key()) < 0) {
Prev();
}
}
};
using InternalIterator = InternalIteratorBase<Slice>;
// Return an empty iterator (yields nothing).
template <class TValue = Slice>
InternalIteratorBase<TValue>* NewEmptyInternalIterator();
// Return an empty iterator with the specified status.
template <class TValue = Slice>
InternalIteratorBase<TValue>* NewErrorInternalIterator(const Status& status);
// Return an empty iterator with the specified status, allocated arena.
template <class TValue = Slice>
InternalIteratorBase<TValue>* NewErrorInternalIterator(const Status& status,
Arena* arena);
} // namespace ROCKSDB_NAMESPACE