/bitcoin/src/leveldb/table/merger.cc
Line | Count | Source |
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 | 7 | : comparator_(comparator), |
18 | 7 | children_(new IteratorWrapper[n]), |
19 | 7 | n_(n), |
20 | 7 | current_(nullptr), |
21 | 7 | direction_(kForward) { |
22 | 21 | for (int i = 0; i < n; i++) { Branch (22:21): [True: 14, False: 7]
|
23 | 14 | children_[i].Set(children[i]); |
24 | 14 | } |
25 | 7 | } |
26 | | |
27 | 7 | ~MergingIterator() override { delete[] children_; } |
28 | | |
29 | 304 | bool Valid() const override { return (current_ != nullptr); } |
30 | | |
31 | 0 | void SeekToFirst() override { |
32 | 0 | for (int i = 0; i < n_; i++) { Branch (32:21): [True: 0, False: 0]
|
33 | 0 | children_[i].SeekToFirst(); |
34 | 0 | } |
35 | 0 | FindSmallest(); |
36 | 0 | direction_ = kForward; |
37 | 0 | } |
38 | | |
39 | 0 | void SeekToLast() override { |
40 | 0 | for (int i = 0; i < n_; i++) { Branch (40:21): [True: 0, False: 0]
|
41 | 0 | children_[i].SeekToLast(); |
42 | 0 | } |
43 | 0 | FindLargest(); |
44 | 0 | direction_ = kReverse; |
45 | 0 | } |
46 | | |
47 | 7 | void Seek(const Slice& target) override { |
48 | 21 | for (int i = 0; i < n_; i++) { Branch (48:21): [True: 14, False: 7]
|
49 | 14 | children_[i].Seek(target); |
50 | 14 | } |
51 | 7 | FindSmallest(); |
52 | 7 | direction_ = kForward; |
53 | 7 | } |
54 | | |
55 | 48 | void Next() override { |
56 | 48 | assert(Valid()); Branch (56:5): [True: 48, False: 0]
|
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 | 48 | if (direction_ != kForward) { Branch (63:9): [True: 0, False: 48]
|
64 | 0 | for (int i = 0; i < n_; i++) { Branch (64:23): [True: 0, False: 0]
|
65 | 0 | IteratorWrapper* child = &children_[i]; |
66 | 0 | if (child != current_) { Branch (66:13): [True: 0, False: 0]
|
67 | 0 | child->Seek(key()); |
68 | 0 | if (child->Valid() && Branch (68:15): [True: 0, False: 0]
Branch (68:15): [True: 0, False: 0]
|
69 | 0 | comparator_->Compare(key(), child->key()) == 0) { Branch (69:15): [True: 0, False: 0]
|
70 | 0 | child->Next(); |
71 | 0 | } |
72 | 0 | } |
73 | 0 | } |
74 | 0 | direction_ = kForward; |
75 | 0 | } |
76 | | |
77 | 48 | current_->Next(); |
78 | 48 | FindSmallest(); |
79 | 48 | } |
80 | | |
81 | 0 | void Prev() override { |
82 | 0 | assert(Valid()); Branch (82:5): [True: 0, False: 0]
|
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) { Branch (89:9): [True: 0, False: 0]
|
90 | 0 | for (int i = 0; i < n_; i++) { Branch (90:23): [True: 0, False: 0]
|
91 | 0 | IteratorWrapper* child = &children_[i]; |
92 | 0 | if (child != current_) { Branch (92:13): [True: 0, False: 0]
|
93 | 0 | child->Seek(key()); |
94 | 0 | if (child->Valid()) { Branch (94:15): [True: 0, False: 0]
|
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 | 100 | Slice key() const override { |
111 | 100 | assert(Valid()); Branch (111:5): [True: 100, False: 0]
|
112 | 100 | return current_->key(); |
113 | 100 | } |
114 | | |
115 | 74 | Slice value() const override { |
116 | 74 | assert(Valid()); Branch (116:5): [True: 74, False: 0]
|
117 | 74 | return current_->value(); |
118 | 74 | } |
119 | | |
120 | 0 | Status status() const override { |
121 | 0 | Status status; |
122 | 0 | for (int i = 0; i < n_; i++) { Branch (122:21): [True: 0, False: 0]
|
123 | 0 | status = children_[i].status(); |
124 | 0 | if (!status.ok()) { Branch (124:11): [True: 0, False: 0]
|
125 | 0 | break; |
126 | 0 | } |
127 | 0 | } |
128 | 0 | return status; |
129 | 0 | } |
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 | 55 | void MergingIterator::FindSmallest() { |
149 | 55 | IteratorWrapper* smallest = nullptr; |
150 | 165 | for (int i = 0; i < n_; i++) { Branch (150:19): [True: 110, False: 55]
|
151 | 110 | IteratorWrapper* child = &children_[i]; |
152 | 110 | if (child->Valid()) { Branch (152:9): [True: 64, False: 46]
|
153 | 64 | if (smallest == nullptr) { Branch (153:11): [True: 48, False: 16]
|
154 | 48 | smallest = child; |
155 | 48 | } else if (comparator_->Compare(child->key(), smallest->key()) < 0) { Branch (155:18): [True: 12, False: 4]
|
156 | 12 | smallest = child; |
157 | 12 | } |
158 | 64 | } |
159 | 110 | } |
160 | 55 | current_ = smallest; |
161 | 55 | } |
162 | | |
163 | 0 | void MergingIterator::FindLargest() { |
164 | 0 | IteratorWrapper* largest = nullptr; |
165 | 0 | for (int i = n_ - 1; i >= 0; i--) { Branch (165:24): [True: 0, False: 0]
|
166 | 0 | IteratorWrapper* child = &children_[i]; |
167 | 0 | if (child->Valid()) { Branch (167:9): [True: 0, False: 0]
|
168 | 0 | if (largest == nullptr) { Branch (168:11): [True: 0, False: 0]
|
169 | 0 | largest = child; |
170 | 0 | } else if (comparator_->Compare(child->key(), largest->key()) > 0) { Branch (170:18): [True: 0, False: 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 | 35.8k | int n) { |
181 | 35.8k | assert(n >= 0); Branch (181:3): [True: 35.8k, False: 0]
|
182 | 35.8k | if (n == 0) { Branch (182:7): [True: 0, False: 35.8k]
|
183 | 0 | return NewEmptyIterator(); |
184 | 35.8k | } else if (n == 1) { Branch (184:14): [True: 35.8k, False: 7]
|
185 | 35.8k | return children[0]; |
186 | 35.8k | } else { |
187 | 7 | return new MergingIterator(comparator, children, n); |
188 | 7 | } |
189 | 35.8k | } |
190 | | |
191 | | } // namespace leveldb |