Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
merger.cc
Go to the documentation of this file.
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/merger.h"
6 
7 #include "leveldb/comparator.h"
8 #include "leveldb/iterator.h"
10 
11 namespace leveldb {
12 
13 namespace {
14 class MergingIterator : public Iterator {
15  public:
16  MergingIterator(const Comparator* comparator, Iterator** children, int n)
17  : comparator_(comparator),
18  children_(new IteratorWrapper[n]),
19  n_(n),
20  current_(NULL),
21  direction_(kForward) {
22  for (int i = 0; i < n; i++) {
23  children_[i].Set(children[i]);
24  }
25  }
26 
27  virtual ~MergingIterator() {
28  delete[] children_;
29  }
30 
31  virtual bool Valid() const {
32  return (current_ != NULL);
33  }
34 
35  virtual void SeekToFirst() {
36  for (int i = 0; i < n_; i++) {
37  children_[i].SeekToFirst();
38  }
39  FindSmallest();
40  direction_ = kForward;
41  }
42 
43  virtual void SeekToLast() {
44  for (int i = 0; i < n_; i++) {
45  children_[i].SeekToLast();
46  }
47  FindLargest();
48  direction_ = kReverse;
49  }
50 
51  virtual void Seek(const Slice& target) {
52  for (int i = 0; i < n_; i++) {
53  children_[i].Seek(target);
54  }
55  FindSmallest();
56  direction_ = kForward;
57  }
58 
59  virtual void Next() {
60  assert(Valid());
61 
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_) {
71  child->Seek(key());
72  if (child->Valid() &&
73  comparator_->Compare(key(), child->key()) == 0) {
74  child->Next();
75  }
76  }
77  }
78  direction_ = kForward;
79  }
80 
81  current_->Next();
82  FindSmallest();
83  }
84 
85  virtual void Prev() {
86  assert(Valid());
87 
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_) {
97  child->Seek(key());
98  if (child->Valid()) {
99  // Child is at first entry >= key(). Step back one to be < key()
100  child->Prev();
101  } else {
102  // Child has no entries >= key(). Position at last entry.
103  child->SeekToLast();
104  }
105  }
106  }
107  direction_ = kReverse;
108  }
109 
110  current_->Prev();
111  FindLargest();
112  }
113 
114  virtual Slice key() const {
115  assert(Valid());
116  return current_->key();
117  }
118 
119  virtual Slice value() const {
120  assert(Valid());
121  return current_->value();
122  }
123 
124  virtual Status status() const {
125  Status status;
126  for (int i = 0; i < n_; i++) {
127  status = children_[i].status();
128  if (!status.ok()) {
129  break;
130  }
131  }
132  return status;
133  }
134 
135  private:
136  void FindSmallest();
137  void FindLargest();
138 
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_;
144  int n_;
145  IteratorWrapper* current_;
146 
147  // Which direction is the iterator moving?
148  enum Direction {
149  kForward,
150  kReverse
151  };
152  Direction direction_;
153 };
154 
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) {
161  smallest = child;
162  } else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
163  smallest = child;
164  }
165  }
166  }
167  current_ = smallest;
168 }
169 
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) {
176  largest = child;
177  } else if (comparator_->Compare(child->key(), largest->key()) > 0) {
178  largest = child;
179  }
180  }
181  }
182  current_ = largest;
183 }
184 } // namespace
185 
187  assert(n >= 0);
188  if (n == 0) {
189  return NewEmptyIterator();
190  } else if (n == 1) {
191  return list[0];
192  } else {
193  return new MergingIterator(cmp, list, n);
194  }
195 }
196 
197 } // namespace leveldb
std::string * value
Definition: version_set.cc:270
Direction direction_
Definition: merger.cc:152
int n_
Definition: merger.cc:144
IteratorWrapper * current_
Definition: merger.cc:145
const Comparator * comparator_
Definition: merger.cc:142
Iterator * NewEmptyIterator()
Definition: iterator.cc:59
Iterator * NewMergingIterator(const Comparator *cmp, Iterator **list, int n)
Definition: merger.cc:186
IteratorWrapper * children_
Definition: merger.cc:143
virtual int Compare(const Slice &a, const Slice &b) const =0
const Comparator * cmp
Definition: table_test.cc:80