123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file. See the AUTHORS file for names of contributors.
- #include "db/db_iter.h"
- #include "db/db_impl.h"
- #include "db/dbformat.h"
- #include "db/filename.h"
- #include "leveldb/env.h"
- #include "leveldb/iterator.h"
- #include "port/port.h"
- #include "util/logging.h"
- #include "util/mutexlock.h"
- #include "util/random.h"
- namespace leveldb {
- #if 0
- static void DumpInternalIter(Iterator* iter) {
- for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
- ParsedInternalKey k;
- if (!ParseInternalKey(iter->key(), &k)) {
- std::fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());
- } else {
- std::fprintf(stderr, "@ '%s'\n", k.DebugString().c_str());
- }
- }
- }
- #endif
- namespace {
- // Memtables and sstables that make the DB representation contain
- // (userkey,seq,type) => uservalue entries. DBIter
- // combines multiple entries for the same userkey found in the DB
- // representation into a single entry while accounting for sequence
- // numbers, deletion markers, overwrites, etc.
- class DBIter : public Iterator {
- public:
- // Which direction is the iterator currently moving?
- // (1) When moving forward, the internal iterator is positioned at
- // the exact entry that yields this->key(), this->value()
- // (2) When moving backwards, the internal iterator is positioned
- // just before all entries whose user key == this->key().
- enum Direction { kForward, kReverse };
- DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
- uint32_t seed)
- : db_(db),
- user_comparator_(cmp),
- iter_(iter),
- sequence_(s),
- direction_(kForward),
- valid_(false),
- rnd_(seed),
- bytes_until_read_sampling_(RandomCompactionPeriod()) {}
- DBIter(const DBIter&) = delete;
- DBIter& operator=(const DBIter&) = delete;
- ~DBIter() override { delete iter_; }
- bool Valid() const override { return valid_; }
- Slice key() const override {
- assert(valid_);
- return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
- }
- Slice value() const override {
- assert(valid_);
- return (direction_ == kForward) ? iter_->value() : saved_value_;
- }
- Status status() const override {
- if (status_.ok()) {
- return iter_->status();
- } else {
- return status_;
- }
- }
- void Next() override;
- void Prev() override;
- void Seek(const Slice& target) override;
- void SeekToFirst() override;
- void SeekToLast() override;
- private:
- void FindNextUserEntry(bool skipping, std::string* skip);
- void FindPrevUserEntry();
- bool ParseKey(ParsedInternalKey* key);
- inline void SaveKey(const Slice& k, std::string* dst) {
- dst->assign(k.data(), k.size());
- }
- inline void ClearSavedValue() {
- if (saved_value_.capacity() > 1048576) {
- std::string empty;
- swap(empty, saved_value_);
- } else {
- saved_value_.clear();
- }
- }
- // Picks the number of bytes that can be read until a compaction is scheduled.
- size_t RandomCompactionPeriod() {
- return rnd_.Uniform(2 * config::kReadBytesPeriod);
- }
- DBImpl* db_;
- const Comparator* const user_comparator_;
- Iterator* const iter_;
- SequenceNumber const sequence_;
- Status status_;
- std::string saved_key_; // == current key when direction_==kReverse
- std::string saved_value_; // == current raw value when direction_==kReverse
- Direction direction_;
- bool valid_;
- Random rnd_;
- size_t bytes_until_read_sampling_;
- };
- inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
- Slice k = iter_->key();
- size_t bytes_read = k.size() + iter_->value().size();
- while (bytes_until_read_sampling_ < bytes_read) {
- bytes_until_read_sampling_ += RandomCompactionPeriod();
- db_->RecordReadSample(k);
- }
- assert(bytes_until_read_sampling_ >= bytes_read);
- bytes_until_read_sampling_ -= bytes_read;
- if (!ParseInternalKey(k, ikey)) {
- status_ = Status::Corruption("corrupted internal key in DBIter");
- return false;
- } else {
- return true;
- }
- }
- void DBIter::Next() {
- assert(valid_);
- if (direction_ == kReverse) { // Switch directions?
- direction_ = kForward;
- // iter_ is pointing just before the entries for this->key(),
- // so advance into the range of entries for this->key() and then
- // use the normal skipping code below.
- if (!iter_->Valid()) {
- iter_->SeekToFirst();
- } else {
- iter_->Next();
- }
- if (!iter_->Valid()) {
- valid_ = false;
- saved_key_.clear();
- return;
- }
- // saved_key_ already contains the key to skip past.
- } else {
- // Store in saved_key_ the current key so we skip it below.
- SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
- // iter_ is pointing to current key. We can now safely move to the next to
- // avoid checking current key.
- iter_->Next();
- if (!iter_->Valid()) {
- valid_ = false;
- saved_key_.clear();
- return;
- }
- }
- FindNextUserEntry(true, &saved_key_);
- }
- void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
- // Loop until we hit an acceptable entry to yield
- assert(iter_->Valid());
- assert(direction_ == kForward);
- do {
- ParsedInternalKey ikey;
- if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
- switch (ikey.type) {
- case kTypeDeletion:
- // Arrange to skip all upcoming entries for this key since
- // they are hidden by this deletion.
- SaveKey(ikey.user_key, skip);
- skipping = true;
- break;
- case kTypeValue:
- if (skipping &&
- user_comparator_->Compare(ikey.user_key, *skip) <= 0) {
- // Entry hidden
- } else {
- valid_ = true;
- saved_key_.clear();
- return;
- }
- break;
- }
- }
- iter_->Next();
- } while (iter_->Valid());
- saved_key_.clear();
- valid_ = false;
- }
- void DBIter::Prev() {
- assert(valid_);
- if (direction_ == kForward) { // Switch directions?
- // iter_ is pointing at the current entry. Scan backwards until
- // the key changes so we can use the normal reverse scanning code.
- assert(iter_->Valid()); // Otherwise valid_ would have been false
- SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
- while (true) {
- iter_->Prev();
- if (!iter_->Valid()) {
- valid_ = false;
- saved_key_.clear();
- ClearSavedValue();
- return;
- }
- if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) <
- 0) {
- break;
- }
- }
- direction_ = kReverse;
- }
- FindPrevUserEntry();
- }
- void DBIter::FindPrevUserEntry() {
- assert(direction_ == kReverse);
- ValueType value_type = kTypeDeletion;
- if (iter_->Valid()) {
- do {
- ParsedInternalKey ikey;
- if (ParseKey(&ikey) && ikey.sequence <= sequence_) {
- if ((value_type != kTypeDeletion) &&
- user_comparator_->Compare(ikey.user_key, saved_key_) < 0) {
- // We encountered a non-deleted value in entries for previous keys,
- break;
- }
- value_type = ikey.type;
- if (value_type == kTypeDeletion) {
- saved_key_.clear();
- ClearSavedValue();
- } else {
- Slice raw_value = iter_->value();
- if (saved_value_.capacity() > raw_value.size() + 1048576) {
- std::string empty;
- swap(empty, saved_value_);
- }
- SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
- saved_value_.assign(raw_value.data(), raw_value.size());
- }
- }
- iter_->Prev();
- } while (iter_->Valid());
- }
- if (value_type == kTypeDeletion) {
- // End
- valid_ = false;
- saved_key_.clear();
- ClearSavedValue();
- direction_ = kForward;
- } else {
- valid_ = true;
- }
- }
- void DBIter::Seek(const Slice& target) {
- direction_ = kForward;
- ClearSavedValue();
- saved_key_.clear();
- AppendInternalKey(&saved_key_,
- ParsedInternalKey(target, sequence_, kValueTypeForSeek));
- iter_->Seek(saved_key_);
- if (iter_->Valid()) {
- FindNextUserEntry(false, &saved_key_ /* temporary storage */);
- } else {
- valid_ = false;
- }
- }
- void DBIter::SeekToFirst() {
- direction_ = kForward;
- ClearSavedValue();
- iter_->SeekToFirst();
- if (iter_->Valid()) {
- FindNextUserEntry(false, &saved_key_ /* temporary storage */);
- } else {
- valid_ = false;
- }
- }
- void DBIter::SeekToLast() {
- direction_ = kReverse;
- ClearSavedValue();
- iter_->SeekToLast();
- FindPrevUserEntry();
- }
- } // anonymous namespace
- Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator,
- Iterator* internal_iter, SequenceNumber sequence,
- uint32_t seed) {
- return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
- }
- } // namespace leveldb
|