10225501448 李度 10225101546 陈胤遒 10215501422 高宇菲
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

197 lignes
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