作者: 谢瑞阳 10225101483 徐翔宇 10225101535
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.1 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 "include/comparator.h"
  6. #include "include/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. for (int i = 0; i < n; i++) {
  18. children_[i].Set(children[i]);
  19. }
  20. }
  21. virtual ~MergingIterator() {
  22. delete[] children_;
  23. }
  24. virtual bool Valid() const {
  25. return (current_ != NULL);
  26. }
  27. virtual void SeekToFirst() {
  28. for (int i = 0; i < n_; i++) {
  29. children_[i].SeekToFirst();
  30. }
  31. FindSmallest();
  32. }
  33. virtual void SeekToLast() {
  34. for (int i = 0; i < n_; i++) {
  35. children_[i].SeekToLast();
  36. }
  37. FindLargest();
  38. }
  39. virtual void Seek(const Slice& target) {
  40. for (int i = 0; i < n_; i++) {
  41. children_[i].Seek(target);
  42. }
  43. FindSmallest();
  44. }
  45. virtual void Next() {
  46. assert(Valid());
  47. current_->Next();
  48. FindSmallest();
  49. }
  50. virtual void Prev() {
  51. assert(Valid());
  52. current_->Prev();
  53. FindLargest();
  54. }
  55. virtual Slice key() const {
  56. assert(Valid());
  57. return current_->key();
  58. }
  59. virtual Slice value() const {
  60. assert(Valid());
  61. return current_->value();
  62. }
  63. virtual Status status() const {
  64. Status status;
  65. for (int i = 0; i < n_; i++) {
  66. status = children_[i].status();
  67. if (!status.ok()) {
  68. break;
  69. }
  70. }
  71. return status;
  72. }
  73. private:
  74. void FindSmallest();
  75. void FindLargest();
  76. // We might want to use a heap in case there are lots of children.
  77. // For now we use a simple array since we expect a very small number
  78. // of children in leveldb.
  79. const Comparator* comparator_;
  80. IteratorWrapper* children_;
  81. int n_;
  82. IteratorWrapper* current_;
  83. };
  84. void MergingIterator::FindSmallest() {
  85. IteratorWrapper* smallest = NULL;
  86. for (int i = 0; i < n_; i++) {
  87. IteratorWrapper* child = &children_[i];
  88. if (child->Valid()) {
  89. if (smallest == NULL) {
  90. smallest = child;
  91. } else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
  92. smallest = child;
  93. }
  94. }
  95. }
  96. current_ = smallest;
  97. }
  98. void MergingIterator::FindLargest() {
  99. IteratorWrapper* largest = NULL;
  100. for (int i = n_-1; i >= 0; i--) {
  101. IteratorWrapper* child = &children_[i];
  102. if (child->Valid()) {
  103. if (largest == NULL) {
  104. largest = child;
  105. } else if (comparator_->Compare(child->key(), largest->key()) > 0) {
  106. largest = child;
  107. }
  108. }
  109. }
  110. current_ = largest;
  111. }
  112. }
  113. Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) {
  114. assert(n >= 0);
  115. if (n == 0) {
  116. return NewEmptyIterator();
  117. } else if (n == 1) {
  118. return list[0];
  119. } else {
  120. return new MergingIterator(cmp, list, n);
  121. }
  122. }
  123. }