| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 | //  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.#include "table/two_level_iterator.h"#include "db/pinned_iterators_manager.h"#include "memory/arena.h"#include "rocksdb/options.h"#include "rocksdb/table.h"#include "table/block_based/block.h"#include "table/format.h"namespace ROCKSDB_NAMESPACE {namespace {class TwoLevelIndexIterator : public InternalIteratorBase<IndexValue> { public:  explicit TwoLevelIndexIterator(      TwoLevelIteratorState* state,      InternalIteratorBase<IndexValue>* first_level_iter);  ~TwoLevelIndexIterator() override {    first_level_iter_.DeleteIter(false /* is_arena_mode */);    second_level_iter_.DeleteIter(false /* is_arena_mode */);    delete state_;  }  void Seek(const Slice& target) override;  void SeekForPrev(const Slice& target) override;  void SeekToFirst() override;  void SeekToLast() override;  void Next() override;  void Prev() override;  bool Valid() const override { return second_level_iter_.Valid(); }  Slice key() const override {    assert(Valid());    return second_level_iter_.key();  }  IndexValue value() const override {    assert(Valid());    return second_level_iter_.value();  }  Status status() const override {    if (!first_level_iter_.status().ok()) {      assert(second_level_iter_.iter() == nullptr);      return first_level_iter_.status();    } else if (second_level_iter_.iter() != nullptr &&               !second_level_iter_.status().ok()) {      return second_level_iter_.status();    } else {      return status_;    }  }  void SetPinnedItersMgr(      PinnedIteratorsManager* /*pinned_iters_mgr*/) override {}  bool IsKeyPinned() const override { return false; }  bool IsValuePinned() const override { return false; } private:  void SaveError(const Status& s) {    if (status_.ok() && !s.ok()) status_ = s;  }  void SkipEmptyDataBlocksForward();  void SkipEmptyDataBlocksBackward();  void SetSecondLevelIterator(InternalIteratorBase<IndexValue>* iter);  void InitDataBlock();  TwoLevelIteratorState* state_;  IteratorWrapperBase<IndexValue> first_level_iter_;  IteratorWrapperBase<IndexValue> second_level_iter_;  // May be nullptr  Status status_;  // If second_level_iter is non-nullptr, then "data_block_handle_" holds the  // "index_value" passed to block_function_ to create the second_level_iter.  BlockHandle data_block_handle_;};TwoLevelIndexIterator::TwoLevelIndexIterator(    TwoLevelIteratorState* state,    InternalIteratorBase<IndexValue>* first_level_iter)    : state_(state), first_level_iter_(first_level_iter) {}void TwoLevelIndexIterator::Seek(const Slice& target) {  first_level_iter_.Seek(target);  InitDataBlock();  if (second_level_iter_.iter() != nullptr) {    second_level_iter_.Seek(target);  }  SkipEmptyDataBlocksForward();}void TwoLevelIndexIterator::SeekForPrev(const Slice& target) {  first_level_iter_.Seek(target);  InitDataBlock();  if (second_level_iter_.iter() != nullptr) {    second_level_iter_.SeekForPrev(target);  }  if (!Valid()) {    if (!first_level_iter_.Valid() && first_level_iter_.status().ok()) {      first_level_iter_.SeekToLast();      InitDataBlock();      if (second_level_iter_.iter() != nullptr) {        second_level_iter_.SeekForPrev(target);      }    }    SkipEmptyDataBlocksBackward();  }}void TwoLevelIndexIterator::SeekToFirst() {  first_level_iter_.SeekToFirst();  InitDataBlock();  if (second_level_iter_.iter() != nullptr) {    second_level_iter_.SeekToFirst();  }  SkipEmptyDataBlocksForward();}void TwoLevelIndexIterator::SeekToLast() {  first_level_iter_.SeekToLast();  InitDataBlock();  if (second_level_iter_.iter() != nullptr) {    second_level_iter_.SeekToLast();  }  SkipEmptyDataBlocksBackward();}void TwoLevelIndexIterator::Next() {  assert(Valid());  second_level_iter_.Next();  SkipEmptyDataBlocksForward();}void TwoLevelIndexIterator::Prev() {  assert(Valid());  second_level_iter_.Prev();  SkipEmptyDataBlocksBackward();}void TwoLevelIndexIterator::SkipEmptyDataBlocksForward() {  while (second_level_iter_.iter() == nullptr ||         (!second_level_iter_.Valid() && second_level_iter_.status().ok())) {    // Move to next block    if (!first_level_iter_.Valid()) {      SetSecondLevelIterator(nullptr);      return;    }    first_level_iter_.Next();    InitDataBlock();    if (second_level_iter_.iter() != nullptr) {      second_level_iter_.SeekToFirst();    }  }}void TwoLevelIndexIterator::SkipEmptyDataBlocksBackward() {  while (second_level_iter_.iter() == nullptr ||         (!second_level_iter_.Valid() && second_level_iter_.status().ok())) {    // Move to next block    if (!first_level_iter_.Valid()) {      SetSecondLevelIterator(nullptr);      return;    }    first_level_iter_.Prev();    InitDataBlock();    if (second_level_iter_.iter() != nullptr) {      second_level_iter_.SeekToLast();    }  }}void TwoLevelIndexIterator::SetSecondLevelIterator(    InternalIteratorBase<IndexValue>* iter) {  InternalIteratorBase<IndexValue>* old_iter = second_level_iter_.Set(iter);  delete old_iter;}void TwoLevelIndexIterator::InitDataBlock() {  if (!first_level_iter_.Valid()) {    SetSecondLevelIterator(nullptr);  } else {    BlockHandle handle = first_level_iter_.value().handle;    if (second_level_iter_.iter() != nullptr &&        !second_level_iter_.status().IsIncomplete() &&        handle.offset() == data_block_handle_.offset()) {      // second_level_iter is already constructed with this iterator, so      // no need to change anything    } else {      InternalIteratorBase<IndexValue>* iter =          state_->NewSecondaryIterator(handle);      data_block_handle_ = handle;      SetSecondLevelIterator(iter);    }  }}}  // namespaceInternalIteratorBase<IndexValue>* NewTwoLevelIterator(    TwoLevelIteratorState* state,    InternalIteratorBase<IndexValue>* first_level_iter) {  return new TwoLevelIndexIterator(state, first_level_iter);}}  // namespace ROCKSDB_NAMESPACE
 |