xref: /aosp_15_r20/external/leveldb/table/merger.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/merger.h"
6*9507f98cSAndroid Build Coastguard Worker 
7*9507f98cSAndroid Build Coastguard Worker #include "leveldb/comparator.h"
8*9507f98cSAndroid Build Coastguard Worker #include "leveldb/iterator.h"
9*9507f98cSAndroid Build Coastguard Worker #include "table/iterator_wrapper.h"
10*9507f98cSAndroid Build Coastguard Worker 
11*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
12*9507f98cSAndroid Build Coastguard Worker 
13*9507f98cSAndroid Build Coastguard Worker namespace {
14*9507f98cSAndroid Build Coastguard Worker class MergingIterator : public Iterator {
15*9507f98cSAndroid Build Coastguard Worker  public:
MergingIterator(const Comparator * comparator,Iterator ** children,int n)16*9507f98cSAndroid Build Coastguard Worker   MergingIterator(const Comparator* comparator, Iterator** children, int n)
17*9507f98cSAndroid Build Coastguard Worker       : comparator_(comparator),
18*9507f98cSAndroid Build Coastguard Worker         children_(new IteratorWrapper[n]),
19*9507f98cSAndroid Build Coastguard Worker         n_(n),
20*9507f98cSAndroid Build Coastguard Worker         current_(nullptr),
21*9507f98cSAndroid Build Coastguard Worker         direction_(kForward) {
22*9507f98cSAndroid Build Coastguard Worker     for (int i = 0; i < n; i++) {
23*9507f98cSAndroid Build Coastguard Worker       children_[i].Set(children[i]);
24*9507f98cSAndroid Build Coastguard Worker     }
25*9507f98cSAndroid Build Coastguard Worker   }
26*9507f98cSAndroid Build Coastguard Worker 
~MergingIterator()27*9507f98cSAndroid Build Coastguard Worker   ~MergingIterator() override { delete[] children_; }
28*9507f98cSAndroid Build Coastguard Worker 
Valid() const29*9507f98cSAndroid Build Coastguard Worker   bool Valid() const override { return (current_ != nullptr); }
30*9507f98cSAndroid Build Coastguard Worker 
SeekToFirst()31*9507f98cSAndroid Build Coastguard Worker   void SeekToFirst() override {
32*9507f98cSAndroid Build Coastguard Worker     for (int i = 0; i < n_; i++) {
33*9507f98cSAndroid Build Coastguard Worker       children_[i].SeekToFirst();
34*9507f98cSAndroid Build Coastguard Worker     }
35*9507f98cSAndroid Build Coastguard Worker     FindSmallest();
36*9507f98cSAndroid Build Coastguard Worker     direction_ = kForward;
37*9507f98cSAndroid Build Coastguard Worker   }
38*9507f98cSAndroid Build Coastguard Worker 
SeekToLast()39*9507f98cSAndroid Build Coastguard Worker   void SeekToLast() override {
40*9507f98cSAndroid Build Coastguard Worker     for (int i = 0; i < n_; i++) {
41*9507f98cSAndroid Build Coastguard Worker       children_[i].SeekToLast();
42*9507f98cSAndroid Build Coastguard Worker     }
43*9507f98cSAndroid Build Coastguard Worker     FindLargest();
44*9507f98cSAndroid Build Coastguard Worker     direction_ = kReverse;
45*9507f98cSAndroid Build Coastguard Worker   }
46*9507f98cSAndroid Build Coastguard Worker 
Seek(const Slice & target)47*9507f98cSAndroid Build Coastguard Worker   void Seek(const Slice& target) override {
48*9507f98cSAndroid Build Coastguard Worker     for (int i = 0; i < n_; i++) {
49*9507f98cSAndroid Build Coastguard Worker       children_[i].Seek(target);
50*9507f98cSAndroid Build Coastguard Worker     }
51*9507f98cSAndroid Build Coastguard Worker     FindSmallest();
52*9507f98cSAndroid Build Coastguard Worker     direction_ = kForward;
53*9507f98cSAndroid Build Coastguard Worker   }
54*9507f98cSAndroid Build Coastguard Worker 
Next()55*9507f98cSAndroid Build Coastguard Worker   void Next() override {
56*9507f98cSAndroid Build Coastguard Worker     assert(Valid());
57*9507f98cSAndroid Build Coastguard Worker 
58*9507f98cSAndroid Build Coastguard Worker     // Ensure that all children are positioned after key().
59*9507f98cSAndroid Build Coastguard Worker     // If we are moving in the forward direction, it is already
60*9507f98cSAndroid Build Coastguard Worker     // true for all of the non-current_ children since current_ is
61*9507f98cSAndroid Build Coastguard Worker     // the smallest child and key() == current_->key().  Otherwise,
62*9507f98cSAndroid Build Coastguard Worker     // we explicitly position the non-current_ children.
63*9507f98cSAndroid Build Coastguard Worker     if (direction_ != kForward) {
64*9507f98cSAndroid Build Coastguard Worker       for (int i = 0; i < n_; i++) {
65*9507f98cSAndroid Build Coastguard Worker         IteratorWrapper* child = &children_[i];
66*9507f98cSAndroid Build Coastguard Worker         if (child != current_) {
67*9507f98cSAndroid Build Coastguard Worker           child->Seek(key());
68*9507f98cSAndroid Build Coastguard Worker           if (child->Valid() &&
69*9507f98cSAndroid Build Coastguard Worker               comparator_->Compare(key(), child->key()) == 0) {
70*9507f98cSAndroid Build Coastguard Worker             child->Next();
71*9507f98cSAndroid Build Coastguard Worker           }
72*9507f98cSAndroid Build Coastguard Worker         }
73*9507f98cSAndroid Build Coastguard Worker       }
74*9507f98cSAndroid Build Coastguard Worker       direction_ = kForward;
75*9507f98cSAndroid Build Coastguard Worker     }
76*9507f98cSAndroid Build Coastguard Worker 
77*9507f98cSAndroid Build Coastguard Worker     current_->Next();
78*9507f98cSAndroid Build Coastguard Worker     FindSmallest();
79*9507f98cSAndroid Build Coastguard Worker   }
80*9507f98cSAndroid Build Coastguard Worker 
Prev()81*9507f98cSAndroid Build Coastguard Worker   void Prev() override {
82*9507f98cSAndroid Build Coastguard Worker     assert(Valid());
83*9507f98cSAndroid Build Coastguard Worker 
84*9507f98cSAndroid Build Coastguard Worker     // Ensure that all children are positioned before key().
85*9507f98cSAndroid Build Coastguard Worker     // If we are moving in the reverse direction, it is already
86*9507f98cSAndroid Build Coastguard Worker     // true for all of the non-current_ children since current_ is
87*9507f98cSAndroid Build Coastguard Worker     // the largest child and key() == current_->key().  Otherwise,
88*9507f98cSAndroid Build Coastguard Worker     // we explicitly position the non-current_ children.
89*9507f98cSAndroid Build Coastguard Worker     if (direction_ != kReverse) {
90*9507f98cSAndroid Build Coastguard Worker       for (int i = 0; i < n_; i++) {
91*9507f98cSAndroid Build Coastguard Worker         IteratorWrapper* child = &children_[i];
92*9507f98cSAndroid Build Coastguard Worker         if (child != current_) {
93*9507f98cSAndroid Build Coastguard Worker           child->Seek(key());
94*9507f98cSAndroid Build Coastguard Worker           if (child->Valid()) {
95*9507f98cSAndroid Build Coastguard Worker             // Child is at first entry >= key().  Step back one to be < key()
96*9507f98cSAndroid Build Coastguard Worker             child->Prev();
97*9507f98cSAndroid Build Coastguard Worker           } else {
98*9507f98cSAndroid Build Coastguard Worker             // Child has no entries >= key().  Position at last entry.
99*9507f98cSAndroid Build Coastguard Worker             child->SeekToLast();
100*9507f98cSAndroid Build Coastguard Worker           }
101*9507f98cSAndroid Build Coastguard Worker         }
102*9507f98cSAndroid Build Coastguard Worker       }
103*9507f98cSAndroid Build Coastguard Worker       direction_ = kReverse;
104*9507f98cSAndroid Build Coastguard Worker     }
105*9507f98cSAndroid Build Coastguard Worker 
106*9507f98cSAndroid Build Coastguard Worker     current_->Prev();
107*9507f98cSAndroid Build Coastguard Worker     FindLargest();
108*9507f98cSAndroid Build Coastguard Worker   }
109*9507f98cSAndroid Build Coastguard Worker 
key() const110*9507f98cSAndroid Build Coastguard Worker   Slice key() const override {
111*9507f98cSAndroid Build Coastguard Worker     assert(Valid());
112*9507f98cSAndroid Build Coastguard Worker     return current_->key();
113*9507f98cSAndroid Build Coastguard Worker   }
114*9507f98cSAndroid Build Coastguard Worker 
value() const115*9507f98cSAndroid Build Coastguard Worker   Slice value() const override {
116*9507f98cSAndroid Build Coastguard Worker     assert(Valid());
117*9507f98cSAndroid Build Coastguard Worker     return current_->value();
118*9507f98cSAndroid Build Coastguard Worker   }
119*9507f98cSAndroid Build Coastguard Worker 
status() const120*9507f98cSAndroid Build Coastguard Worker   Status status() const override {
121*9507f98cSAndroid Build Coastguard Worker     Status status;
122*9507f98cSAndroid Build Coastguard Worker     for (int i = 0; i < n_; i++) {
123*9507f98cSAndroid Build Coastguard Worker       status = children_[i].status();
124*9507f98cSAndroid Build Coastguard Worker       if (!status.ok()) {
125*9507f98cSAndroid Build Coastguard Worker         break;
126*9507f98cSAndroid Build Coastguard Worker       }
127*9507f98cSAndroid Build Coastguard Worker     }
128*9507f98cSAndroid Build Coastguard Worker     return status;
129*9507f98cSAndroid Build Coastguard Worker   }
130*9507f98cSAndroid Build Coastguard Worker 
131*9507f98cSAndroid Build Coastguard Worker  private:
132*9507f98cSAndroid Build Coastguard Worker   // Which direction is the iterator moving?
133*9507f98cSAndroid Build Coastguard Worker   enum Direction { kForward, kReverse };
134*9507f98cSAndroid Build Coastguard Worker 
135*9507f98cSAndroid Build Coastguard Worker   void FindSmallest();
136*9507f98cSAndroid Build Coastguard Worker   void FindLargest();
137*9507f98cSAndroid Build Coastguard Worker 
138*9507f98cSAndroid Build Coastguard Worker   // We might want to use a heap in case there are lots of children.
139*9507f98cSAndroid Build Coastguard Worker   // For now we use a simple array since we expect a very small number
140*9507f98cSAndroid Build Coastguard Worker   // of children in leveldb.
141*9507f98cSAndroid Build Coastguard Worker   const Comparator* comparator_;
142*9507f98cSAndroid Build Coastguard Worker   IteratorWrapper* children_;
143*9507f98cSAndroid Build Coastguard Worker   int n_;
144*9507f98cSAndroid Build Coastguard Worker   IteratorWrapper* current_;
145*9507f98cSAndroid Build Coastguard Worker   Direction direction_;
146*9507f98cSAndroid Build Coastguard Worker };
147*9507f98cSAndroid Build Coastguard Worker 
FindSmallest()148*9507f98cSAndroid Build Coastguard Worker void MergingIterator::FindSmallest() {
149*9507f98cSAndroid Build Coastguard Worker   IteratorWrapper* smallest = nullptr;
150*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < n_; i++) {
151*9507f98cSAndroid Build Coastguard Worker     IteratorWrapper* child = &children_[i];
152*9507f98cSAndroid Build Coastguard Worker     if (child->Valid()) {
153*9507f98cSAndroid Build Coastguard Worker       if (smallest == nullptr) {
154*9507f98cSAndroid Build Coastguard Worker         smallest = child;
155*9507f98cSAndroid Build Coastguard Worker       } else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
156*9507f98cSAndroid Build Coastguard Worker         smallest = child;
157*9507f98cSAndroid Build Coastguard Worker       }
158*9507f98cSAndroid Build Coastguard Worker     }
159*9507f98cSAndroid Build Coastguard Worker   }
160*9507f98cSAndroid Build Coastguard Worker   current_ = smallest;
161*9507f98cSAndroid Build Coastguard Worker }
162*9507f98cSAndroid Build Coastguard Worker 
FindLargest()163*9507f98cSAndroid Build Coastguard Worker void MergingIterator::FindLargest() {
164*9507f98cSAndroid Build Coastguard Worker   IteratorWrapper* largest = nullptr;
165*9507f98cSAndroid Build Coastguard Worker   for (int i = n_ - 1; i >= 0; i--) {
166*9507f98cSAndroid Build Coastguard Worker     IteratorWrapper* child = &children_[i];
167*9507f98cSAndroid Build Coastguard Worker     if (child->Valid()) {
168*9507f98cSAndroid Build Coastguard Worker       if (largest == nullptr) {
169*9507f98cSAndroid Build Coastguard Worker         largest = child;
170*9507f98cSAndroid Build Coastguard Worker       } else if (comparator_->Compare(child->key(), largest->key()) > 0) {
171*9507f98cSAndroid Build Coastguard Worker         largest = child;
172*9507f98cSAndroid Build Coastguard Worker       }
173*9507f98cSAndroid Build Coastguard Worker     }
174*9507f98cSAndroid Build Coastguard Worker   }
175*9507f98cSAndroid Build Coastguard Worker   current_ = largest;
176*9507f98cSAndroid Build Coastguard Worker }
177*9507f98cSAndroid Build Coastguard Worker }  // namespace
178*9507f98cSAndroid Build Coastguard Worker 
NewMergingIterator(const Comparator * comparator,Iterator ** children,int n)179*9507f98cSAndroid Build Coastguard Worker Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children,
180*9507f98cSAndroid Build Coastguard Worker                              int n) {
181*9507f98cSAndroid Build Coastguard Worker   assert(n >= 0);
182*9507f98cSAndroid Build Coastguard Worker   if (n == 0) {
183*9507f98cSAndroid Build Coastguard Worker     return NewEmptyIterator();
184*9507f98cSAndroid Build Coastguard Worker   } else if (n == 1) {
185*9507f98cSAndroid Build Coastguard Worker     return children[0];
186*9507f98cSAndroid Build Coastguard Worker   } else {
187*9507f98cSAndroid Build Coastguard Worker     return new MergingIterator(comparator, children, n);
188*9507f98cSAndroid Build Coastguard Worker   }
189*9507f98cSAndroid Build Coastguard Worker }
190*9507f98cSAndroid Build Coastguard Worker 
191*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
192