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