提交 e67b35c0 编写于 作者: S Siying Dong 提交者: Facebook Github Bot

Add Iterator::Refresh()

Summary:
Add and implement Iterator::Refresh(). When this function is called, if the super version doesn't change, update the sequence number of the iterator to the latest one and invalidate the iterator. If the super version changed, recreated the whole iterator. This can help users reuse the iterator more easily.
Closes https://github.com/facebook/rocksdb/pull/2621

Differential Revision: D5464500

Pulled By: siying

fbshipit-source-id: f548bd35e85c1efca2ea69273802f6704eba6ba9
上级 a34b2e38
# Rocksdb Change Log # Rocksdb Change Log
## Unreleased
### New Features
* Add Iterator::Refresh(), which allows users to update the iterator state so that they can avoid some initialization costs of recreating iterators.
## 5.7.0 (07/13/2017) ## 5.7.0 (07/13/2017)
### Public API Change ### Public API Change
* DB property "rocksdb.sstables" now prints keys in hex form. * DB property "rocksdb.sstables" now prints keys in hex form.
......
...@@ -1402,8 +1402,7 @@ Iterator* DBImpl::NewIterator(const ReadOptions& read_options, ...@@ -1402,8 +1402,7 @@ Iterator* DBImpl::NewIterator(const ReadOptions& read_options,
return NewDBIterator( return NewDBIterator(
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), iter, env_, read_options, *cfd->ioptions(), cfd->user_comparator(), iter,
kMaxSequenceNumber, kMaxSequenceNumber,
sv->mutable_cf_options.max_sequential_skip_in_iterations, sv->mutable_cf_options.max_sequential_skip_in_iterations);
sv->version_number);
#endif #endif
} else { } else {
SequenceNumber latest_snapshot = versions_->LastSequence(); SequenceNumber latest_snapshot = versions_->LastSequence();
...@@ -1458,9 +1457,10 @@ Iterator* DBImpl::NewIterator(const ReadOptions& read_options, ...@@ -1458,9 +1457,10 @@ Iterator* DBImpl::NewIterator(const ReadOptions& read_options,
// likely that any iterator pointer is close to the iterator it points to so // likely that any iterator pointer is close to the iterator it points to so
// that they are likely to be in the same cache line and/or page. // that they are likely to be in the same cache line and/or page.
ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator( ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), snapshot, env_, read_options, *cfd->ioptions(), snapshot,
sv->mutable_cf_options.max_sequential_skip_in_iterations, sv->mutable_cf_options.max_sequential_skip_in_iterations,
sv->version_number); sv->version_number,
((read_options.snapshot != nullptr) ? nullptr : this), cfd);
InternalIterator* internal_iter = InternalIterator* internal_iter =
NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(), NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(),
...@@ -1511,8 +1511,7 @@ Status DBImpl::NewIterators( ...@@ -1511,8 +1511,7 @@ Status DBImpl::NewIterators(
iterators->push_back(NewDBIterator( iterators->push_back(NewDBIterator(
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), iter, env_, read_options, *cfd->ioptions(), cfd->user_comparator(), iter,
kMaxSequenceNumber, kMaxSequenceNumber,
sv->mutable_cf_options.max_sequential_skip_in_iterations, sv->mutable_cf_options.max_sequential_skip_in_iterations));
sv->version_number));
} }
#endif #endif
} else { } else {
...@@ -1530,9 +1529,10 @@ Status DBImpl::NewIterators( ...@@ -1530,9 +1529,10 @@ Status DBImpl::NewIterators(
: latest_snapshot; : latest_snapshot;
ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator( ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), env_, read_options, *cfd->ioptions(), snapshot,
snapshot, sv->mutable_cf_options.max_sequential_skip_in_iterations, sv->mutable_cf_options.max_sequential_skip_in_iterations,
sv->version_number); sv->version_number,
((read_options.snapshot != nullptr) ? nullptr : this), cfd);
InternalIterator* internal_iter = InternalIterator* internal_iter =
NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(), NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(),
db_iter->GetRangeDelAggregator()); db_iter->GetRangeDelAggregator());
......
...@@ -494,6 +494,12 @@ class DBImpl : public DB { ...@@ -494,6 +494,12 @@ class DBImpl : public DB {
const WriteController& write_controller() { return write_controller_; } const WriteController& write_controller() { return write_controller_; }
InternalIterator* NewInternalIterator(const ReadOptions&,
ColumnFamilyData* cfd,
SuperVersion* super_version,
Arena* arena,
RangeDelAggregator* range_del_agg);
// hollow transactions shell used for recovery. // hollow transactions shell used for recovery.
// these will then be passed to TransactionDB so that // these will then be passed to TransactionDB so that
// locks can be reacquired before writing can resume. // locks can be reacquired before writing can resume.
...@@ -552,6 +558,7 @@ class DBImpl : public DB { ...@@ -552,6 +558,7 @@ class DBImpl : public DB {
void AddToLogsToFreeQueue(log::Writer* log_writer) { void AddToLogsToFreeQueue(log::Writer* log_writer) {
logs_to_free_queue_.push_back(log_writer); logs_to_free_queue_.push_back(log_writer);
} }
InstrumentedMutex* mutex() { return &mutex_; }
Status NewDB(); Status NewDB();
...@@ -566,12 +573,6 @@ class DBImpl : public DB { ...@@ -566,12 +573,6 @@ class DBImpl : public DB {
std::unordered_map<std::string, RecoveredTransaction*> std::unordered_map<std::string, RecoveredTransaction*>
recovered_transactions_; recovered_transactions_;
InternalIterator* NewInternalIterator(const ReadOptions&,
ColumnFamilyData* cfd,
SuperVersion* super_version,
Arena* arena,
RangeDelAggregator* range_del_agg);
// Except in DB::Open(), WriteOptionsFile can only be called when: // Except in DB::Open(), WriteOptionsFile can only be called when:
// Persist options to options file. // Persist options to options file.
// If need_mutex_lock = false, the method will lock DB mutex. // If need_mutex_lock = false, the method will lock DB mutex.
......
...@@ -58,7 +58,7 @@ Iterator* DBImplReadOnly::NewIterator(const ReadOptions& read_options, ...@@ -58,7 +58,7 @@ Iterator* DBImplReadOnly::NewIterator(const ReadOptions& read_options,
SuperVersion* super_version = cfd->GetSuperVersion()->Ref(); SuperVersion* super_version = cfd->GetSuperVersion()->Ref();
SequenceNumber latest_snapshot = versions_->LastSequence(); SequenceNumber latest_snapshot = versions_->LastSequence();
auto db_iter = NewArenaWrappedDbIterator( auto db_iter = NewArenaWrappedDbIterator(
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), env_, read_options, *cfd->ioptions(),
(read_options.snapshot != nullptr (read_options.snapshot != nullptr
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot) ? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
->number_ ->number_
...@@ -87,7 +87,7 @@ Status DBImplReadOnly::NewIterators( ...@@ -87,7 +87,7 @@ Status DBImplReadOnly::NewIterators(
auto* cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(cfh)->cfd(); auto* cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(cfh)->cfd();
auto* sv = cfd->GetSuperVersion()->Ref(); auto* sv = cfd->GetSuperVersion()->Ref();
auto* db_iter = NewArenaWrappedDbIterator( auto* db_iter = NewArenaWrappedDbIterator(
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), env_, read_options, *cfd->ioptions(),
(read_options.snapshot != nullptr (read_options.snapshot != nullptr
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot) ? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
->number_ ->number_
......
...@@ -101,12 +101,12 @@ class DBIter: public Iterator { ...@@ -101,12 +101,12 @@ class DBIter: public Iterator {
uint64_t bytes_read_; uint64_t bytes_read_;
}; };
DBIter(Env* env, const ReadOptions& read_options, DBIter(Env* _env, const ReadOptions& read_options,
const ImmutableCFOptions& cf_options, const Comparator* cmp, const ImmutableCFOptions& cf_options, const Comparator* cmp,
InternalIterator* iter, SequenceNumber s, bool arena_mode, InternalIterator* iter, SequenceNumber s, bool arena_mode,
uint64_t max_sequential_skip_in_iterations, uint64_t version_number) uint64_t max_sequential_skip_in_iterations)
: arena_mode_(arena_mode), : arena_mode_(arena_mode),
env_(env), env_(_env),
logger_(cf_options.info_log), logger_(cf_options.info_log),
user_comparator_(cmp), user_comparator_(cmp),
merge_operator_(cf_options.merge_operator), merge_operator_(cf_options.merge_operator),
...@@ -116,7 +116,6 @@ class DBIter: public Iterator { ...@@ -116,7 +116,6 @@ class DBIter: public Iterator {
valid_(false), valid_(false),
current_entry_is_merged_(false), current_entry_is_merged_(false),
statistics_(cf_options.statistics), statistics_(cf_options.statistics),
version_number_(version_number),
iterate_upper_bound_(read_options.iterate_upper_bound), iterate_upper_bound_(read_options.iterate_upper_bound),
prefix_same_as_start_(read_options.prefix_same_as_start), prefix_same_as_start_(read_options.prefix_same_as_start),
pin_thru_lifetime_(read_options.pin_data), pin_thru_lifetime_(read_options.pin_data),
...@@ -188,10 +187,7 @@ class DBIter: public Iterator { ...@@ -188,10 +187,7 @@ class DBIter: public Iterator {
} }
if (prop_name == "rocksdb.iterator.super-version-number") { if (prop_name == "rocksdb.iterator.super-version-number") {
// First try to pass the value returned from inner iterator. // First try to pass the value returned from inner iterator.
if (!iter_->GetProperty(prop_name, prop).ok()) { return iter_->GetProperty(prop_name, prop);
*prop = ToString(version_number_);
}
return Status::OK();
} else if (prop_name == "rocksdb.iterator.is-key-pinned") { } else if (prop_name == "rocksdb.iterator.is-key-pinned") {
if (valid_) { if (valid_) {
*prop = (pin_thru_lifetime_ && saved_key_.IsKeyPinned()) ? "1" : "0"; *prop = (pin_thru_lifetime_ && saved_key_.IsKeyPinned()) ? "1" : "0";
...@@ -209,6 +205,9 @@ class DBIter: public Iterator { ...@@ -209,6 +205,9 @@ class DBIter: public Iterator {
virtual void SeekForPrev(const Slice& target) override; virtual void SeekForPrev(const Slice& target) override;
virtual void SeekToFirst() override; virtual void SeekToFirst() override;
virtual void SeekToLast() override; virtual void SeekToLast() override;
Env* env() { return env_; }
void set_sequence(uint64_t s) { sequence_ = s; }
void set_valid(bool v) { valid_ = v; }
private: private:
void ReverseToForward(); void ReverseToForward();
...@@ -260,7 +259,7 @@ class DBIter: public Iterator { ...@@ -260,7 +259,7 @@ class DBIter: public Iterator {
const Comparator* const user_comparator_; const Comparator* const user_comparator_;
const MergeOperator* const merge_operator_; const MergeOperator* const merge_operator_;
InternalIterator* iter_; InternalIterator* iter_;
SequenceNumber const sequence_; SequenceNumber sequence_;
Status status_; Status status_;
IterKey saved_key_; IterKey saved_key_;
...@@ -274,7 +273,6 @@ class DBIter: public Iterator { ...@@ -274,7 +273,6 @@ class DBIter: public Iterator {
uint64_t max_skip_; uint64_t max_skip_;
uint64_t max_skippable_internal_keys_; uint64_t max_skippable_internal_keys_;
uint64_t num_internal_keys_skipped_; uint64_t num_internal_keys_skipped_;
uint64_t version_number_;
const Slice* iterate_upper_bound_; const Slice* iterate_upper_bound_;
IterKey prefix_start_buf_; IterKey prefix_start_buf_;
Slice prefix_start_key_; Slice prefix_start_key_;
...@@ -1157,18 +1155,15 @@ Iterator* NewDBIterator(Env* env, const ReadOptions& read_options, ...@@ -1157,18 +1155,15 @@ Iterator* NewDBIterator(Env* env, const ReadOptions& read_options,
const Comparator* user_key_comparator, const Comparator* user_key_comparator,
InternalIterator* internal_iter, InternalIterator* internal_iter,
const SequenceNumber& sequence, const SequenceNumber& sequence,
uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations) {
uint64_t version_number) { DBIter* db_iter = new DBIter(env, read_options, cf_options,
DBIter* db_iter = new DBIter( user_key_comparator, internal_iter, sequence,
env, read_options, cf_options, user_key_comparator, internal_iter, false, max_sequential_skip_in_iterations);
sequence, false, max_sequential_skip_in_iterations, version_number);
return db_iter; return db_iter;
} }
ArenaWrappedDBIter::~ArenaWrappedDBIter() { db_iter_->~DBIter(); } ArenaWrappedDBIter::~ArenaWrappedDBIter() { db_iter_->~DBIter(); }
void ArenaWrappedDBIter::SetDBIter(DBIter* iter) { db_iter_ = iter; }
RangeDelAggregator* ArenaWrappedDBIter::GetRangeDelAggregator() { RangeDelAggregator* ArenaWrappedDBIter::GetRangeDelAggregator() {
return db_iter_->GetRangeDelAggregator(); return db_iter_->GetRangeDelAggregator();
} }
...@@ -1193,26 +1188,67 @@ inline Slice ArenaWrappedDBIter::value() const { return db_iter_->value(); } ...@@ -1193,26 +1188,67 @@ inline Slice ArenaWrappedDBIter::value() const { return db_iter_->value(); }
inline Status ArenaWrappedDBIter::status() const { return db_iter_->status(); } inline Status ArenaWrappedDBIter::status() const { return db_iter_->status(); }
inline Status ArenaWrappedDBIter::GetProperty(std::string prop_name, inline Status ArenaWrappedDBIter::GetProperty(std::string prop_name,
std::string* prop) { std::string* prop) {
if (prop_name == "rocksdb.iterator.super-version-number") {
// First try to pass the value returned from inner iterator.
if (!db_iter_->GetProperty(prop_name, prop).ok()) {
*prop = ToString(sv_number_);
}
return Status::OK();
}
return db_iter_->GetProperty(prop_name, prop); return db_iter_->GetProperty(prop_name, prop);
} }
void ArenaWrappedDBIter::RegisterCleanup(CleanupFunction function, void* arg1,
void* arg2) { void ArenaWrappedDBIter::Init(Env* env, const ReadOptions& read_options,
db_iter_->RegisterCleanup(function, arg1, arg2); const ImmutableCFOptions& cf_options,
const SequenceNumber& sequence,
uint64_t max_sequential_skip_in_iteration,
uint64_t version_number) {
auto mem = arena_.AllocateAligned(sizeof(DBIter));
db_iter_ = new (mem)
DBIter(env, read_options, cf_options, cf_options.user_comparator, nullptr,
sequence, true, max_sequential_skip_in_iteration);
sv_number_ = version_number;
}
Status ArenaWrappedDBIter::Refresh() {
if (cfd_ == nullptr || db_impl_ == nullptr) {
return Status::NotSupported("Creating renew iterator is not allowed.");
}
assert(db_iter_ != nullptr);
SequenceNumber latest_seq = db_impl_->GetLatestSequenceNumber();
uint64_t cur_sv_number = cfd_->GetSuperVersionNumber();
if (sv_number_ != cur_sv_number) {
Env* env = db_iter_->env();
db_iter_->~DBIter();
arena_.~Arena();
new (&arena_) Arena();
SuperVersion* sv = cfd_->GetReferencedSuperVersion(db_impl_->mutex());
Init(env, read_options_, *(cfd_->ioptions()), latest_seq,
sv->mutable_cf_options.max_sequential_skip_in_iterations,
cur_sv_number);
InternalIterator* internal_iter = db_impl_->NewInternalIterator(
read_options_, cfd_, sv, &arena_, db_iter_->GetRangeDelAggregator());
SetIterUnderDBIter(internal_iter);
} else {
db_iter_->set_sequence(latest_seq);
db_iter_->set_valid(false);
}
return Status::OK();
} }
ArenaWrappedDBIter* NewArenaWrappedDbIterator( ArenaWrappedDBIter* NewArenaWrappedDbIterator(
Env* env, const ReadOptions& read_options, Env* env, const ReadOptions& read_options,
const ImmutableCFOptions& cf_options, const Comparator* user_key_comparator, const ImmutableCFOptions& cf_options, const SequenceNumber& sequence,
const SequenceNumber& sequence, uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations, uint64_t version_number,
uint64_t version_number) { DBImpl* db_impl, ColumnFamilyData* cfd) {
ArenaWrappedDBIter* iter = new ArenaWrappedDBIter(); ArenaWrappedDBIter* iter = new ArenaWrappedDBIter();
Arena* arena = iter->GetArena(); iter->Init(env, read_options, cf_options, sequence,
auto mem = arena->AllocateAligned(sizeof(DBIter)); max_sequential_skip_in_iterations, version_number);
DBIter* db_iter = new (mem) if (db_impl != nullptr && cfd != nullptr) {
DBIter(env, read_options, cf_options, user_key_comparator, nullptr, iter->StoreRefreshInfo(read_options, db_impl, cfd);
sequence, true, max_sequential_skip_in_iterations, version_number); }
iter->SetDBIter(db_iter);
return iter; return iter;
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include "db/db_impl.h"
#include "db/dbformat.h" #include "db/dbformat.h"
#include "db/range_del_aggregator.h" #include "db/range_del_aggregator.h"
#include "options/cf_options.h" #include "options/cf_options.h"
...@@ -32,8 +33,7 @@ extern Iterator* NewDBIterator(Env* env, const ReadOptions& read_options, ...@@ -32,8 +33,7 @@ extern Iterator* NewDBIterator(Env* env, const ReadOptions& read_options,
const Comparator* user_key_comparator, const Comparator* user_key_comparator,
InternalIterator* internal_iter, InternalIterator* internal_iter,
const SequenceNumber& sequence, const SequenceNumber& sequence,
uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations);
uint64_t version_number);
// A wrapper iterator which wraps DB Iterator and the arena, with which the DB // A wrapper iterator which wraps DB Iterator and the arena, with which the DB
// iterator is supposed be allocated. This class is used as an entry point of // iterator is supposed be allocated. This class is used as an entry point of
...@@ -49,10 +49,6 @@ class ArenaWrappedDBIter : public Iterator { ...@@ -49,10 +49,6 @@ class ArenaWrappedDBIter : public Iterator {
virtual Arena* GetArena() { return &arena_; } virtual Arena* GetArena() { return &arena_; }
virtual RangeDelAggregator* GetRangeDelAggregator(); virtual RangeDelAggregator* GetRangeDelAggregator();
// Set the DB Iterator to be wrapped
virtual void SetDBIter(DBIter* iter);
// Set the internal iterator wrapped inside the DB Iterator. Usually it is // Set the internal iterator wrapped inside the DB Iterator. Usually it is
// a merging iterator. // a merging iterator.
virtual void SetIterUnderDBIter(InternalIterator* iter); virtual void SetIterUnderDBIter(InternalIterator* iter);
...@@ -66,20 +62,39 @@ class ArenaWrappedDBIter : public Iterator { ...@@ -66,20 +62,39 @@ class ArenaWrappedDBIter : public Iterator {
virtual Slice key() const override; virtual Slice key() const override;
virtual Slice value() const override; virtual Slice value() const override;
virtual Status status() const override; virtual Status status() const override;
virtual Status Refresh() override;
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
virtual Status GetProperty(std::string prop_name, std::string* prop) override; virtual Status GetProperty(std::string prop_name, std::string* prop) override;
void Init(Env* env, const ReadOptions& read_options,
const ImmutableCFOptions& cf_options,
const SequenceNumber& sequence,
uint64_t max_sequential_skip_in_iterations,
uint64_t version_number);
void StoreRefreshInfo(const ReadOptions& read_options, DBImpl* db_impl,
ColumnFamilyData* cfd) {
read_options_ = read_options;
db_impl_ = db_impl;
cfd_ = cfd;
}
private: private:
DBIter* db_iter_; DBIter* db_iter_;
Arena arena_; Arena arena_;
uint64_t sv_number_;
ColumnFamilyData* cfd_ = nullptr;
DBImpl* db_impl_ = nullptr;
ReadOptions read_options_;
}; };
// Generate the arena wrapped iterator class. // Generate the arena wrapped iterator class.
// `db_impl` and `cfd` are used for reneweal. If left null, renewal will not
// be supported.
extern ArenaWrappedDBIter* NewArenaWrappedDbIterator( extern ArenaWrappedDBIter* NewArenaWrappedDbIterator(
Env* env, const ReadOptions& read_options, Env* env, const ReadOptions& read_options,
const ImmutableCFOptions& cf_options, const Comparator* user_key_comparator, const ImmutableCFOptions& cf_options, const SequenceNumber& sequence,
const SequenceNumber& sequence, uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations, uint64_t version_number,
uint64_t version_number); DBImpl* db_impl = nullptr, ColumnFamilyData* cfd = nullptr);
} // namespace rocksdb } // namespace rocksdb
此差异已折叠。
...@@ -1909,6 +1909,65 @@ TEST_F(DBIteratorTest, DBIteratorSkipRecentDuplicatesTest) { ...@@ -1909,6 +1909,65 @@ TEST_F(DBIteratorTest, DBIteratorSkipRecentDuplicatesTest) {
NUMBER_OF_RESEEKS_IN_ITERATION)); NUMBER_OF_RESEEKS_IN_ITERATION));
} }
TEST_F(DBIteratorTest, Refresh) {
ASSERT_OK(Put("x", "y"));
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
iter->Seek(Slice("a"));
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
iter->Next();
ASSERT_FALSE(iter->Valid());
ASSERT_OK(Put("c", "d"));
iter->Seek(Slice("a"));
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
iter->Next();
ASSERT_FALSE(iter->Valid());
iter->Refresh();
iter->Seek(Slice("a"));
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("c")), 0);
iter->Next();
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
iter->Next();
ASSERT_FALSE(iter->Valid());
dbfull()->Flush(FlushOptions());
ASSERT_OK(Put("m", "n"));
iter->Seek(Slice("a"));
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("c")), 0);
iter->Next();
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
iter->Next();
ASSERT_FALSE(iter->Valid());
iter->Refresh();
iter->Seek(Slice("a"));
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("c")), 0);
iter->Next();
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("m")), 0);
iter->Next();
ASSERT_TRUE(iter->Valid());
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
iter->Next();
ASSERT_FALSE(iter->Valid());
iter.reset();
}
} // namespace rocksdb } // namespace rocksdb
int main(int argc, char** argv) { int main(int argc, char** argv) {
......
...@@ -80,6 +80,13 @@ class Iterator : public Cleanable { ...@@ -80,6 +80,13 @@ class Iterator : public Cleanable {
// satisfied without doing some IO, then this returns Status::Incomplete(). // satisfied without doing some IO, then this returns Status::Incomplete().
virtual Status status() const = 0; virtual Status status() const = 0;
// If supported, renew the iterator to represent the latest state. The
// iterator will be invalidated after the call. Not supported if
// ReadOptions.snapshot is given when creating the iterator.
virtual Status Refresh() {
return Status::NotSupported("Refresh() is not supported");
}
// Property "rocksdb.iterator.is-key-pinned": // Property "rocksdb.iterator.is-key-pinned":
// If returning "1", this means that the Slice returned by key() is valid // If returning "1", this means that the Slice returned by key() is valid
// as long as the iterator is not deleted. // as long as the iterator is not deleted.
......
...@@ -378,8 +378,8 @@ Iterator* DateTieredDBImpl::NewIterator(const ReadOptions& opts) { ...@@ -378,8 +378,8 @@ Iterator* DateTieredDBImpl::NewIterator(const ReadOptions& opts) {
DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_); DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_);
auto db_iter = NewArenaWrappedDbIterator( auto db_iter = NewArenaWrappedDbIterator(
db_impl->GetEnv(), opts, ioptions_, cf_options_.comparator, db_impl->GetEnv(), opts, ioptions_, kMaxSequenceNumber,
kMaxSequenceNumber, cf_options_.max_sequential_skip_in_iterations, 0); cf_options_.max_sequential_skip_in_iterations, 0);
auto arena = db_iter->GetArena(); auto arena = db_iter->GetArena();
MergeIteratorBuilder builder(cf_options_.comparator, arena); MergeIteratorBuilder builder(cf_options_.comparator, arena);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册