two_level_iterator.cc
1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. See the AUTHORS file for names of contributors. 4 5 #include "table/two_level_iterator.h" 6 7 #include "leveldb/table.h" 8 #include "table/block.h" 9 #include "table/format.h" 10 #include "table/iterator_wrapper.h" 11 12 namespace leveldb { 13 14 namespace { 15 16 typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); 17 18 class TwoLevelIterator : public Iterator { 19 public: 20 TwoLevelIterator(Iterator* index_iter, BlockFunction block_function, 21 void* arg, const ReadOptions& options); 22 23 ~TwoLevelIterator() override; 24 25 void Seek(const Slice& target) override; 26 void SeekToFirst() override; 27 void SeekToLast() override; 28 void Next() override; 29 void Prev() override; 30 31 bool Valid() const override { return data_iter_.Valid(); } 32 Slice key() const override { 33 assert(Valid()); 34 return data_iter_.key(); 35 } 36 Slice value() const override { 37 assert(Valid()); 38 return data_iter_.value(); 39 } 40 Status status() const override { 41 // It'd be nice if status() returned a const Status& instead of a Status 42 if (!index_iter_.status().ok()) { 43 return index_iter_.status(); 44 } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) { 45 return data_iter_.status(); 46 } else { 47 return status_; 48 } 49 } 50 51 private: 52 void SaveError(const Status& s) { 53 if (status_.ok() && !s.ok()) status_ = s; 54 } 55 void SkipEmptyDataBlocksForward(); 56 void SkipEmptyDataBlocksBackward(); 57 void SetDataIterator(Iterator* data_iter); 58 void InitDataBlock(); 59 60 BlockFunction block_function_; 61 void* arg_; 62 const ReadOptions options_; 63 Status status_; 64 IteratorWrapper index_iter_; 65 IteratorWrapper data_iter_; // May be nullptr 66 // If data_iter_ is non-null, then "data_block_handle_" holds the 67 // "index_value" passed to block_function_ to create the data_iter_. 68 std::string data_block_handle_; 69 }; 70 71 TwoLevelIterator::TwoLevelIterator(Iterator* index_iter, 72 BlockFunction block_function, void* arg, 73 const ReadOptions& options) 74 : block_function_(block_function), 75 arg_(arg), 76 options_(options), 77 index_iter_(index_iter), 78 data_iter_(nullptr) {} 79 80 TwoLevelIterator::~TwoLevelIterator() = default; 81 82 void TwoLevelIterator::Seek(const Slice& target) { 83 index_iter_.Seek(target); 84 InitDataBlock(); 85 if (data_iter_.iter() != nullptr) data_iter_.Seek(target); 86 SkipEmptyDataBlocksForward(); 87 } 88 89 void TwoLevelIterator::SeekToFirst() { 90 index_iter_.SeekToFirst(); 91 InitDataBlock(); 92 if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); 93 SkipEmptyDataBlocksForward(); 94 } 95 96 void TwoLevelIterator::SeekToLast() { 97 index_iter_.SeekToLast(); 98 InitDataBlock(); 99 if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); 100 SkipEmptyDataBlocksBackward(); 101 } 102 103 void TwoLevelIterator::Next() { 104 assert(Valid()); 105 data_iter_.Next(); 106 SkipEmptyDataBlocksForward(); 107 } 108 109 void TwoLevelIterator::Prev() { 110 assert(Valid()); 111 data_iter_.Prev(); 112 SkipEmptyDataBlocksBackward(); 113 } 114 115 void TwoLevelIterator::SkipEmptyDataBlocksForward() { 116 while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { 117 // Move to next block 118 if (!index_iter_.Valid()) { 119 SetDataIterator(nullptr); 120 return; 121 } 122 index_iter_.Next(); 123 InitDataBlock(); 124 if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); 125 } 126 } 127 128 void TwoLevelIterator::SkipEmptyDataBlocksBackward() { 129 while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { 130 // Move to next block 131 if (!index_iter_.Valid()) { 132 SetDataIterator(nullptr); 133 return; 134 } 135 index_iter_.Prev(); 136 InitDataBlock(); 137 if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); 138 } 139 } 140 141 void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { 142 if (data_iter_.iter() != nullptr) SaveError(data_iter_.status()); 143 data_iter_.Set(data_iter); 144 } 145 146 void TwoLevelIterator::InitDataBlock() { 147 if (!index_iter_.Valid()) { 148 SetDataIterator(nullptr); 149 } else { 150 Slice handle = index_iter_.value(); 151 if (data_iter_.iter() != nullptr && 152 handle.compare(data_block_handle_) == 0) { 153 // data_iter_ is already constructed with this iterator, so 154 // no need to change anything 155 } else { 156 Iterator* iter = (*block_function_)(arg_, options_, handle); 157 data_block_handle_.assign(handle.data(), handle.size()); 158 SetDataIterator(iter); 159 } 160 } 161 } 162 163 } // namespace 164 165 Iterator* NewTwoLevelIterator(Iterator* index_iter, 166 BlockFunction block_function, void* arg, 167 const ReadOptions& options) { 168 return new TwoLevelIterator(index_iter, block_function, arg, options); 169 } 170 171 } // namespace leveldb