25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
4.8 KiB

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