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