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.
5 #include "table/merger.h"
7 #include "leveldb/comparator.h"
8 #include "leveldb/iterator.h"
9 #include "table/iterator_wrapper.h"
14 class MergingIterator : public Iterator {
16 MergingIterator(const Comparator* comparator, Iterator** children, int n)
17 : comparator_(comparator),
18 children_(new IteratorWrapper[n]),
21 direction_(kForward) {
22 for (int i = 0; i < n; i++) {
23 children_[i].Set(children[i]);
27 virtual ~MergingIterator() {
31 virtual bool Valid() const {
32 return (current_ != NULL);
35 virtual void SeekToFirst() {
36 for (int i = 0; i < n_; i++) {
37 children_[i].SeekToFirst();
40 direction_ = kForward;
43 virtual void SeekToLast() {
44 for (int i = 0; i < n_; i++) {
45 children_[i].SeekToLast();
48 direction_ = kReverse;
51 virtual void Seek(const Slice& target) {
52 for (int i = 0; i < n_; i++) {
53 children_[i].Seek(target);
56 direction_ = kForward;
62 // Ensure that all children are positioned after key().
63 // If we are moving in the forward direction, it is already
64 // true for all of the non-current_ children since current_ is
65 // the smallest child and key() == current_->key(). Otherwise,
66 // we explicitly position the non-current_ children.
67 if (direction_ != kForward) {
68 for (int i = 0; i < n_; i++) {
69 IteratorWrapper* child = &children_[i];
70 if (child != current_) {
73 comparator_->Compare(key(), child->key()) == 0) {
78 direction_ = kForward;
88 // Ensure that all children are positioned before key().
89 // If we are moving in the reverse direction, it is already
90 // true for all of the non-current_ children since current_ is
91 // the largest child and key() == current_->key(). Otherwise,
92 // we explicitly position the non-current_ children.
93 if (direction_ != kReverse) {
94 for (int i = 0; i < n_; i++) {
95 IteratorWrapper* child = &children_[i];
96 if (child != current_) {
99 // Child is at first entry >= key(). Step back one to be < key()
102 // Child has no entries >= key(). Position at last entry.
107 direction_ = kReverse;
114 virtual Slice key() const {
116 return current_->key();
119 virtual Slice value() const {
121 return current_->value();
124 virtual Status status() const {
126 for (int i = 0; i < n_; i++) {
127 status = children_[i].status();
139 // We might want to use a heap in case there are lots of children.
140 // For now we use a simple array since we expect a very small number
141 // of children in leveldb.
142 const Comparator* comparator_;
143 IteratorWrapper* children_;
145 IteratorWrapper* current_;
147 // Which direction is the iterator moving?
152 Direction direction_;
155 void MergingIterator::FindSmallest() {
156 IteratorWrapper* smallest = NULL;
157 for (int i = 0; i < n_; i++) {
158 IteratorWrapper* child = &children_[i];
159 if (child->Valid()) {
160 if (smallest == NULL) {
162 } else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
170 void MergingIterator::FindLargest() {
171 IteratorWrapper* largest = NULL;
172 for (int i = n_-1; i >= 0; i--) {
173 IteratorWrapper* child = &children_[i];
174 if (child->Valid()) {
175 if (largest == NULL) {
177 } else if (comparator_->Compare(child->key(), largest->key()) > 0) {
186 Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) {
189 return NewEmptyIterator();
193 return new MergingIterator(cmp, list, n);
197 } // namespace leveldb