// 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). // // Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. #pragma once #include #include "table/internal_iterator.h" #include "test_util/sync_point.h" namespace ROCKSDB_NAMESPACE { // A internal wrapper class with an interface similar to Iterator that caches // the valid() and key() results for an underlying iterator. // This can help avoid virtual function calls and also gives better // cache locality. template class IteratorWrapperBase { public: IteratorWrapperBase() : iter_(nullptr), valid_(false) {} explicit IteratorWrapperBase(InternalIteratorBase* _iter) : iter_(nullptr) { Set(_iter); } ~IteratorWrapperBase() {} InternalIteratorBase* iter() const { return iter_; } // Set the underlying Iterator to _iter and return // previous underlying Iterator. InternalIteratorBase* Set(InternalIteratorBase* _iter) { InternalIteratorBase* old_iter = iter_; iter_ = _iter; if (iter_ == nullptr) { valid_ = false; } else { Update(); } return old_iter; } void DeleteIter(bool is_arena_mode) { if (iter_) { if (!is_arena_mode) { delete iter_; } else { iter_->~InternalIteratorBase(); } } } // Iterator interface methods bool Valid() const { return valid_; } Slice key() const { assert(Valid()); return result_.key; } TValue value() const { assert(Valid()); return iter_->value(); } // Methods below require iter() != nullptr Status status() const { assert(iter_); return iter_->status(); } void Next() { assert(iter_); valid_ = iter_->NextAndGetResult(&result_); assert(!valid_ || iter_->status().ok()); } void Prev() { assert(iter_); iter_->Prev(); Update(); } void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); } void SeekForPrev(const Slice& k) { assert(iter_); iter_->SeekForPrev(k); Update(); } void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); } void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); } bool MayBeOutOfLowerBound() { assert(Valid()); return iter_->MayBeOutOfLowerBound(); } bool MayBeOutOfUpperBound() { assert(Valid()); return result_.may_be_out_of_upper_bound; } void SetPinnedItersMgr(PinnedIteratorsManager* pinned_iters_mgr) { assert(iter_); iter_->SetPinnedItersMgr(pinned_iters_mgr); } bool IsKeyPinned() const { assert(Valid()); return iter_->IsKeyPinned(); } bool IsValuePinned() const { assert(Valid()); return iter_->IsValuePinned(); } private: void Update() { valid_ = iter_->Valid(); if (valid_) { assert(iter_->status().ok()); result_.key = iter_->key(); result_.may_be_out_of_upper_bound = true; } } InternalIteratorBase* iter_; IterateResult result_; bool valid_; }; using IteratorWrapper = IteratorWrapperBase; class Arena; // Return an empty iterator (yields nothing) allocated from arena. template extern InternalIteratorBase* NewEmptyInternalIterator(Arena* arena); } // namespace ROCKSDB_NAMESPACE