diff --git a/db/db_test.cc b/db/db_test.cc index 4bc2942a8..da9f62e65 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -6917,6 +6917,28 @@ TEST(DBTest, TailingIteratorPrefixSeek) { ASSERT_TRUE(!iter->Valid()); } +TEST(DBTest, TailingIteratorIncomplete) { + CreateAndReopenWithCF({"pikachu"}); + ReadOptions read_options; + read_options.tailing = true; + read_options.read_tier = kBlockCacheTier; + + std::string key("key"); + std::string value("value"); + + ASSERT_OK(db_->Put(WriteOptions(), key, value)); + + std::unique_ptr iter(db_->NewIterator(read_options)); + iter->SeekToFirst(); + // we either see the entry or it's not in cache + ASSERT_TRUE(iter->Valid() || iter->status().IsIncomplete()); + + ASSERT_OK(db_->CompactRange(nullptr, nullptr)); + iter->SeekToFirst(); + // should still be true after compaction + ASSERT_TRUE(iter->Valid() || iter->status().IsIncomplete()); +} + TEST(DBTest, BlockBasedTablePrefixIndexTest) { // create a DB with block prefix index BlockBasedTableOptions table_options; diff --git a/db/forward_iterator.cc b/db/forward_iterator.cc index 1a0d02688..e1de2f932 100644 --- a/db/forward_iterator.cc +++ b/db/forward_iterator.cc @@ -87,7 +87,12 @@ class LevelIterator : public Iterator { return file_iter_->value(); } Status status() const override { - return status_; + if (!status_.ok()) { + return status_; + } else if (file_iter_ && !file_iter_->status().ok()) { + return file_iter_->status(); + } + return Status::OK(); } private: @@ -334,6 +339,23 @@ Status ForwardIterator::status() const { } else if (!mutable_iter_->status().ok()) { return mutable_iter_->status(); } + + for (auto *it : imm_iters_) { + if (it && !it->status().ok()) { + return it->status(); + } + } + for (auto *it : l0_iters_) { + if (it && !it->status().ok()) { + return it->status(); + } + } + for (auto *it : level_iters_) { + if (it && !it->status().ok()) { + return it->status(); + } + } + return Status::OK(); }