summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/table/internal_iterator.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/rocksdb/table/internal_iterator.h')
-rw-r--r--src/rocksdb/table/internal_iterator.h226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/rocksdb/table/internal_iterator.h b/src/rocksdb/table/internal_iterator.h
new file mode 100644
index 000000000..945dec806
--- /dev/null
+++ b/src/rocksdb/table/internal_iterator.h
@@ -0,0 +1,226 @@
+// 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() {}
+
+ // 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;
+
+ // 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();
+ }
+ }
+
+ bool is_mutable_;
+};
+
+using InternalIterator = InternalIteratorBase<Slice>;
+
+// Return an empty iterator (yields nothing).
+template <class TValue = Slice>
+extern InternalIteratorBase<TValue>* NewEmptyInternalIterator();
+
+// Return an empty iterator with the specified status.
+template <class TValue = Slice>
+extern InternalIteratorBase<TValue>* NewErrorInternalIterator(
+ const Status& status);
+
+// Return an empty iterator with the specified status, allocated arena.
+template <class TValue = Slice>
+extern InternalIteratorBase<TValue>* NewErrorInternalIterator(
+ const Status& status, Arena* arena);
+
+} // namespace ROCKSDB_NAMESPACE