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