LevelDB project 1 10225501460 林子骥 10211900416 郭夏辉
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.

171 lines
4.8 KiB

2 months ago
  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/two_level_iterator.h"
  5. #include "leveldb/table.h"
  6. #include "table/block.h"
  7. #include "table/format.h"
  8. #include "table/iterator_wrapper.h"
  9. namespace leveldb {
  10. namespace {
  11. typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&);
  12. class TwoLevelIterator : public Iterator {
  13. public:
  14. TwoLevelIterator(Iterator* index_iter, BlockFunction block_function,
  15. void* arg, const ReadOptions& options);
  16. ~TwoLevelIterator() override;
  17. void Seek(const Slice& target) override;
  18. void SeekToFirst() override;
  19. void SeekToLast() override;
  20. void Next() override;
  21. void Prev() override;
  22. bool Valid() const override { return data_iter_.Valid(); }
  23. Slice key() const override {
  24. assert(Valid());
  25. return data_iter_.key();
  26. }
  27. Slice value() const override {
  28. assert(Valid());
  29. return data_iter_.value();
  30. }
  31. Status status() const override {
  32. // It'd be nice if status() returned a const Status& instead of a Status
  33. if (!index_iter_.status().ok()) {
  34. return index_iter_.status();
  35. } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) {
  36. return data_iter_.status();
  37. } else {
  38. return status_;
  39. }
  40. }
  41. private:
  42. void SaveError(const Status& s) {
  43. if (status_.ok() && !s.ok()) status_ = s;
  44. }
  45. void SkipEmptyDataBlocksForward();
  46. void SkipEmptyDataBlocksBackward();
  47. void SetDataIterator(Iterator* data_iter);
  48. void InitDataBlock();
  49. BlockFunction block_function_;
  50. void* arg_;
  51. const ReadOptions options_;
  52. Status status_;
  53. IteratorWrapper index_iter_;
  54. IteratorWrapper data_iter_; // May be nullptr
  55. // If data_iter_ is non-null, then "data_block_handle_" holds the
  56. // "index_value" passed to block_function_ to create the data_iter_.
  57. std::string data_block_handle_;
  58. };
  59. TwoLevelIterator::TwoLevelIterator(Iterator* index_iter,
  60. BlockFunction block_function, void* arg,
  61. const ReadOptions& options)
  62. : block_function_(block_function),
  63. arg_(arg),
  64. options_(options),
  65. index_iter_(index_iter),
  66. data_iter_(nullptr) {}
  67. TwoLevelIterator::~TwoLevelIterator() = default;
  68. void TwoLevelIterator::Seek(const Slice& target) {
  69. index_iter_.Seek(target);
  70. InitDataBlock();
  71. if (data_iter_.iter() != nullptr) data_iter_.Seek(target);
  72. SkipEmptyDataBlocksForward();
  73. }
  74. void TwoLevelIterator::SeekToFirst() {
  75. index_iter_.SeekToFirst();
  76. InitDataBlock();
  77. if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();
  78. SkipEmptyDataBlocksForward();
  79. }
  80. void TwoLevelIterator::SeekToLast() {
  81. index_iter_.SeekToLast();
  82. InitDataBlock();
  83. if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();
  84. SkipEmptyDataBlocksBackward();
  85. }
  86. void TwoLevelIterator::Next() {
  87. assert(Valid());
  88. data_iter_.Next();
  89. SkipEmptyDataBlocksForward();
  90. }
  91. void TwoLevelIterator::Prev() {
  92. assert(Valid());
  93. data_iter_.Prev();
  94. SkipEmptyDataBlocksBackward();
  95. }
  96. void TwoLevelIterator::SkipEmptyDataBlocksForward() {
  97. while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
  98. // Move to next block
  99. if (!index_iter_.Valid()) {
  100. SetDataIterator(nullptr);
  101. return;
  102. }
  103. index_iter_.Next();
  104. InitDataBlock();
  105. if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();
  106. }
  107. }
  108. void TwoLevelIterator::SkipEmptyDataBlocksBackward() {
  109. while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
  110. // Move to next block
  111. if (!index_iter_.Valid()) {
  112. SetDataIterator(nullptr);
  113. return;
  114. }
  115. index_iter_.Prev();
  116. InitDataBlock();
  117. if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();
  118. }
  119. }
  120. void TwoLevelIterator::SetDataIterator(Iterator* data_iter) {
  121. if (data_iter_.iter() != nullptr) SaveError(data_iter_.status());
  122. data_iter_.Set(data_iter);
  123. }
  124. void TwoLevelIterator::InitDataBlock() {
  125. if (!index_iter_.Valid()) {
  126. SetDataIterator(nullptr);
  127. } else {
  128. Slice handle = index_iter_.value();
  129. if (data_iter_.iter() != nullptr &&
  130. handle.compare(data_block_handle_) == 0) {
  131. // data_iter_ is already constructed with this iterator, so
  132. // no need to change anything
  133. } else {
  134. Iterator* iter = (*block_function_)(arg_, options_, handle);
  135. data_block_handle_.assign(handle.data(), handle.size());
  136. SetDataIterator(iter);
  137. }
  138. }
  139. }
  140. } // namespace
  141. Iterator* NewTwoLevelIterator(Iterator* index_iter,
  142. BlockFunction block_function, void* arg,
  143. const ReadOptions& options) {
  144. return new TwoLevelIterator(index_iter, block_function, arg, options);
  145. }
  146. } // namespace leveldb