作者: 谢瑞阳 10225101483 徐翔宇 10225101535
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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