db_iter.cc 7.8 KB
Newer Older
J
jorlow@chromium.org 已提交
1 2 3 4 5 6 7 8
// 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/filename.h"
#include "db/dbformat.h"
9 10
#include "leveldb/env.h"
#include "leveldb/iterator.h"
J
jorlow@chromium.org 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#include "port/port.h"
#include "util/logging.h"
#include "util/mutexlock.h"

namespace leveldb {

#if 0
static void DumpInternalIter(Iterator* iter) {
  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
    ParsedInternalKey k;
    if (!ParseInternalKey(iter->key(), &k)) {
      fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str());
    } else {
      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:
J
jorlow@chromium.org 已提交
39 40 41 42 43 44 45 46 47 48
  // 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
  };

J
jorlow@chromium.org 已提交
49 50 51 52 53 54 55
  DBIter(const std::string* dbname, Env* env,
         const Comparator* cmp, Iterator* iter, SequenceNumber s)
      : dbname_(dbname),
        env_(env),
        user_comparator_(cmp),
        iter_(iter),
        sequence_(s),
J
jorlow@chromium.org 已提交
56
        direction_(kForward),
J
jorlow@chromium.org 已提交
57 58 59 60 61 62 63 64
        valid_(false) {
  }
  virtual ~DBIter() {
    delete iter_;
  }
  virtual bool Valid() const { return valid_; }
  virtual Slice key() const {
    assert(valid_);
J
jorlow@chromium.org 已提交
65
    return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_;
J
jorlow@chromium.org 已提交
66 67 68
  }
  virtual Slice value() const {
    assert(valid_);
D
dgrogan@chromium.org 已提交
69
    return (direction_ == kForward) ? iter_->value() : saved_value_;
J
jorlow@chromium.org 已提交
70 71 72 73 74 75 76 77 78
  }
  virtual Status status() const {
    if (status_.ok()) {
      return iter_->status();
    } else {
      return status_;
    }
  }

J
jorlow@chromium.org 已提交
79 80 81 82 83
  virtual void Next();
  virtual void Prev();
  virtual void Seek(const Slice& target);
  virtual void SeekToFirst();
  virtual void SeekToLast();
J
jorlow@chromium.org 已提交
84

J
jorlow@chromium.org 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
 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();
    }
  }

J
jorlow@chromium.org 已提交
103 104 105 106 107
  const std::string* const dbname_;
  Env* const env_;
  const Comparator* const user_comparator_;
  Iterator* const iter_;
  SequenceNumber const sequence_;
J
jorlow@chromium.org 已提交
108

J
jorlow@chromium.org 已提交
109
  Status status_;
J
jorlow@chromium.org 已提交
110 111 112
  std::string saved_key_;     // == current key when direction_==kReverse
  std::string saved_value_;   // == current raw value when direction_==kReverse
  Direction direction_;
J
jorlow@chromium.org 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  bool valid_;

  // No copying allowed
  DBIter(const DBIter&);
  void operator=(const DBIter&);
};

inline bool DBIter::ParseKey(ParsedInternalKey* ikey) {
  if (!ParseInternalKey(iter_->key(), ikey)) {
    status_ = Status::Corruption("corrupted internal key in DBIter");
    return false;
  } else {
    return true;
  }
}

J
jorlow@chromium.org 已提交
129 130 131 132 133 134 135 136 137 138 139
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 {
J
jorlow@chromium.org 已提交
140 141
      iter_->Next();
    }
J
jorlow@chromium.org 已提交
142 143 144 145
    if (!iter_->Valid()) {
      valid_ = false;
      saved_key_.clear();
      return;
J
jorlow@chromium.org 已提交
146 147
    }
  }
J
jorlow@chromium.org 已提交
148 149 150 151 152

  // Temporarily use saved_key_ as storage for key to skip.
  std::string* skip = &saved_key_;
  SaveKey(ExtractUserKey(iter_->key()), skip);
  FindNextUserEntry(true, skip);
J
jorlow@chromium.org 已提交
153 154
}

J
jorlow@chromium.org 已提交
155 156 157 158 159
void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
  // Loop until we hit an acceptable entry to yield
  assert(iter_->Valid());
  assert(direction_ == kForward);
  do {
J
jorlow@chromium.org 已提交
160
    ParsedInternalKey ikey;
J
jorlow@chromium.org 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    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;
      }
J
jorlow@chromium.org 已提交
180 181
    }
    iter_->Next();
J
jorlow@chromium.org 已提交
182 183 184
  } while (iter_->Valid());
  saved_key_.clear();
  valid_ = false;
J
jorlow@chromium.org 已提交
185 186
}

J
jorlow@chromium.org 已提交
187 188
void DBIter::Prev() {
  assert(valid_);
J
jorlow@chromium.org 已提交
189

J
jorlow@chromium.org 已提交
190 191 192 193 194 195 196
  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();
J
jorlow@chromium.org 已提交
197
      if (!iter_->Valid()) {
J
jorlow@chromium.org 已提交
198 199 200
        valid_ = false;
        saved_key_.clear();
        ClearSavedValue();
J
jorlow@chromium.org 已提交
201 202
        return;
      }
J
jorlow@chromium.org 已提交
203 204 205 206
      if (user_comparator_->Compare(ExtractUserKey(iter_->key()),
                                    saved_key_) < 0) {
        break;
      }
J
jorlow@chromium.org 已提交
207
    }
J
jorlow@chromium.org 已提交
208
    direction_ = kReverse;
J
jorlow@chromium.org 已提交
209
  }
J
jorlow@chromium.org 已提交
210 211

  FindPrevUserEntry();
J
jorlow@chromium.org 已提交
212 213
}

J
jorlow@chromium.org 已提交
214 215
void DBIter::FindPrevUserEntry() {
  assert(direction_ == kReverse);
J
jorlow@chromium.org 已提交
216

J
jorlow@chromium.org 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
  ValueType value_type = kTypeDeletion;
  if (iter_->Valid()) {
    SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
    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) {
          ClearSavedValue();
        } else {
          Slice raw_value = iter_->value();
          if (saved_value_.capacity() > raw_value.size() + 1048576) {
            std::string empty;
            swap(empty, saved_value_);
          }
          saved_value_.assign(raw_value.data(), raw_value.size());
        }
      }
J
jorlow@chromium.org 已提交
240
      iter_->Prev();
J
jorlow@chromium.org 已提交
241 242
    } while (iter_->Valid());
  }
J
jorlow@chromium.org 已提交
243

J
jorlow@chromium.org 已提交
244 245 246 247 248 249 250 251 252 253
  if (value_type == kTypeDeletion) {
    // End
    valid_ = false;
    saved_key_.clear();
    ClearSavedValue();
    direction_ = kForward;
  } else {
    valid_ = true;
  }
}
J
jorlow@chromium.org 已提交
254

J
jorlow@chromium.org 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267
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;
  }
}
J
jorlow@chromium.org 已提交
268

J
jorlow@chromium.org 已提交
269 270 271 272 273 274 275 276
void DBIter::SeekToFirst() {
  direction_ = kForward;
  ClearSavedValue();
  iter_->SeekToFirst();
  if (iter_->Valid()) {
    FindNextUserEntry(false, &saved_key_ /* temporary storage */);
  } else {
    valid_ = false;
J
jorlow@chromium.org 已提交
277 278 279
  }
}

J
jorlow@chromium.org 已提交
280 281 282 283 284 285 286
void DBIter::SeekToLast() {
  direction_ = kReverse;
  ClearSavedValue();
  iter_->SeekToLast();
  FindPrevUserEntry();
}

J
jorlow@chromium.org 已提交
287 288 289 290 291 292 293 294 295 296 297 298
}  // anonymous namespace

Iterator* NewDBIterator(
    const std::string* dbname,
    Env* env,
    const Comparator* user_key_comparator,
    Iterator* internal_iter,
    const SequenceNumber& sequence) {
  return new DBIter(dbname, env, user_key_comparator, internal_iter, sequence);
}

}