Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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