db_iter.cc 21.1 KB
Newer Older
1 2 3 4 5
//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
J
jorlow@chromium.org 已提交
6 7 8 9 10
// 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"
11
#include <stdexcept>
12
#include <deque>
S
Stanislau Hlebik 已提交
13
#include <string>
S
Stanislau Hlebik 已提交
14
#include <limits>
J
jorlow@chromium.org 已提交
15 16 17

#include "db/filename.h"
#include "db/dbformat.h"
18 19 20 21
#include "rocksdb/env.h"
#include "rocksdb/options.h"
#include "rocksdb/iterator.h"
#include "rocksdb/merge_operator.h"
J
jorlow@chromium.org 已提交
22
#include "port/port.h"
23
#include "util/arena.h"
J
jorlow@chromium.org 已提交
24 25
#include "util/logging.h"
#include "util/mutexlock.h"
26
#include "util/perf_context_imp.h"
J
jorlow@chromium.org 已提交
27

28
namespace rocksdb {
J
jorlow@chromium.org 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

#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

// 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:
50
  // The following is grossly complicated. TODO: clean it up
J
jorlow@chromium.org 已提交
51 52 53 54 55 56 57 58 59 60
  // 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
  };

61
  DBIter(Env* env, const Options& options, const Comparator* cmp,
62 63
         Iterator* iter, SequenceNumber s, bool arena_mode,
         const Slice* iterate_upper_bound = nullptr)
64 65
      : arena_mode_(arena_mode),
        env_(env),
I
Igor Canadi 已提交
66
        logger_(options.info_log.get()),
J
jorlow@chromium.org 已提交
67
        user_comparator_(cmp),
68
        user_merge_operator_(options.merge_operator.get()),
J
jorlow@chromium.org 已提交
69 70
        iter_(iter),
        sequence_(s),
J
jorlow@chromium.org 已提交
71
        direction_(kForward),
72
        valid_(false),
73
        current_entry_is_merged_(false),
74 75
        statistics_(options.statistics.get()),
        iterate_upper_bound_(iterate_upper_bound) {
L
Lei Jin 已提交
76
    RecordTick(statistics_, NO_ITERATORS);
77
    prefix_extractor_ = options.prefix_extractor.get();
78
    max_skip_ = options.max_sequential_skip_in_iterations;
J
jorlow@chromium.org 已提交
79 80
  }
  virtual ~DBIter() {
81
    RecordTick(statistics_, NO_ITERATORS, -1);
82 83 84 85 86 87 88 89 90
    if (!arena_mode_) {
      delete iter_;
    } else {
      iter_->~Iterator();
    }
  }
  virtual void SetIter(Iterator* iter) {
    assert(iter_ == nullptr);
    iter_ = iter;
J
jorlow@chromium.org 已提交
91 92 93 94
  }
  virtual bool Valid() const { return valid_; }
  virtual Slice key() const {
    assert(valid_);
95
    return saved_key_.GetKey();
J
jorlow@chromium.org 已提交
96 97 98
  }
  virtual Slice value() const {
    assert(valid_);
99 100
    return (direction_ == kForward && !current_entry_is_merged_) ?
      iter_->value() : saved_value_;
J
jorlow@chromium.org 已提交
101 102 103 104 105 106 107 108 109
  }
  virtual Status status() const {
    if (status_.ok()) {
      return iter_->status();
    } else {
      return status_;
    }
  }

J
jorlow@chromium.org 已提交
110 111 112 113 114
  virtual void Next();
  virtual void Prev();
  virtual void Seek(const Slice& target);
  virtual void SeekToFirst();
  virtual void SeekToLast();
J
jorlow@chromium.org 已提交
115

J
jorlow@chromium.org 已提交
116
 private:
S
Stanislau Hlebik 已提交
117 118 119 120 121 122
  void PrevInternal();
  void FindParseableKey(ParsedInternalKey* ikey, Direction direction);
  bool FindValueForCurrentKey();
  bool FindValueForCurrentKeyUsingSeek();
  void FindPrevUserKey();
  void FindNextUserKey();
123 124
  inline void FindNextUserEntry(bool skipping);
  void FindNextUserEntryInternal(bool skipping);
J
jorlow@chromium.org 已提交
125
  bool ParseKey(ParsedInternalKey* key);
126
  void MergeValuesNewToOld();
J
jorlow@chromium.org 已提交
127 128 129 130 131 132 133 134 135 136

  inline void ClearSavedValue() {
    if (saved_value_.capacity() > 1048576) {
      std::string empty;
      swap(empty, saved_value_);
    } else {
      saved_value_.clear();
    }
  }

137
  const SliceTransform* prefix_extractor_;
138
  bool arena_mode_;
J
jorlow@chromium.org 已提交
139
  Env* const env_;
I
Igor Canadi 已提交
140
  Logger* logger_;
J
jorlow@chromium.org 已提交
141
  const Comparator* const user_comparator_;
142
  const MergeOperator* const user_merge_operator_;
143
  Iterator* iter_;
J
jorlow@chromium.org 已提交
144
  SequenceNumber const sequence_;
J
jorlow@chromium.org 已提交
145

J
jorlow@chromium.org 已提交
146
  Status status_;
S
Stanislau Hlebik 已提交
147 148
  IterKey saved_key_;
  std::string saved_value_;
J
jorlow@chromium.org 已提交
149
  Direction direction_;
J
jorlow@chromium.org 已提交
150
  bool valid_;
151
  bool current_entry_is_merged_;
152
  Statistics* statistics_;
153
  uint64_t max_skip_;
154
  const Slice* iterate_upper_bound_;
J
jorlow@chromium.org 已提交
155 156 157 158 159 160 161 162 163

  // 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");
164 165
    Log(logger_, "corrupted internal key in DBIter: %s",
        iter_->key().ToString(true).c_str());
J
jorlow@chromium.org 已提交
166 167 168 169 170 171
    return false;
  } else {
    return true;
  }
}

J
jorlow@chromium.org 已提交
172 173 174
void DBIter::Next() {
  assert(valid_);

S
Stanislau Hlebik 已提交
175 176
  if (direction_ == kReverse) {
    FindNextUserKey();
J
jorlow@chromium.org 已提交
177 178 179
    direction_ = kForward;
    if (!iter_->Valid()) {
      iter_->SeekToFirst();
J
jorlow@chromium.org 已提交
180 181
    }
  }
J
jorlow@chromium.org 已提交
182

183 184 185 186 187 188
  // If the current value is merged, we might already hit end of iter_
  if (!iter_->Valid()) {
    valid_ = false;
    return;
  }
  FindNextUserEntry(true /* skipping the current user key */);
J
jorlow@chromium.org 已提交
189 190
}

191 192 193 194 195 196 197 198
// PRE: saved_key_ has the current user key if skipping
// POST: saved_key_ should have the next user key if valid_,
//       if the current entry is a result of merge
//           current_entry_is_merged_ => true
//           saved_value_             => the merged value
//
// NOTE: In between, saved_key_ can point to a user key that has
//       a delete marker
199
inline void DBIter::FindNextUserEntry(bool skipping) {
200
  PERF_TIMER_GUARD(find_next_user_entry_time);
201 202 203 204 205
  FindNextUserEntryInternal(skipping);
}

// Actual implementation of DBIter::FindNextUserEntry()
void DBIter::FindNextUserEntryInternal(bool skipping) {
J
jorlow@chromium.org 已提交
206 207 208
  // Loop until we hit an acceptable entry to yield
  assert(iter_->Valid());
  assert(direction_ == kForward);
209
  current_entry_is_merged_ = false;
210
  uint64_t num_skipped = 0;
J
jorlow@chromium.org 已提交
211
  do {
J
jorlow@chromium.org 已提交
212
    ParsedInternalKey ikey;
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

    if (ParseKey(&ikey)) {
      if (iterate_upper_bound_ != nullptr &&
          ikey.user_key.compare(*iterate_upper_bound_) >= 0) {
        break;
      }

      if (ikey.sequence <= sequence_) {
        if (skipping &&
           user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) {
          num_skipped++;  // skip this entry
          PERF_COUNTER_ADD(internal_key_skipped_count, 1);
        } else {
          skipping = false;
          switch (ikey.type) {
            case kTypeDeletion:
              // Arrange to skip all upcoming entries for this key since
              // they are hidden by this deletion.
              saved_key_.SetKey(ikey.user_key);
              skipping = true;
              num_skipped = 0;
              PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
              break;
            case kTypeValue:
              valid_ = true;
              saved_key_.SetKey(ikey.user_key);
              return;
            case kTypeMerge:
              // By now, we are sure the current ikey is going to yield a value
              saved_key_.SetKey(ikey.user_key);
              current_entry_is_merged_ = true;
              valid_ = true;
              MergeValuesNewToOld();  // Go to a different state machine
              return;
            default:
              assert(false);
              break;
          }
251
        }
J
jorlow@chromium.org 已提交
252
      }
J
jorlow@chromium.org 已提交
253
    }
254 255 256 257 258 259 260
    // If we have sequentially iterated via numerous keys and still not
    // found the next user-key, then it is better to seek so that we can
    // avoid too many key comparisons. We seek to the last occurence of
    // our current key by looking for sequence number 0.
    if (skipping && num_skipped > max_skip_) {
      num_skipped = 0;
      std::string last_key;
261 262
      AppendInternalKey(&last_key, ParsedInternalKey(saved_key_.GetKey(), 0,
                                                     kValueTypeForSeek));
263 264 265 266 267
      iter_->Seek(last_key);
      RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
    } else {
      iter_->Next();
    }
J
jorlow@chromium.org 已提交
268 269
  } while (iter_->Valid());
  valid_ = false;
J
jorlow@chromium.org 已提交
270 271
}

272 273 274 275 276 277 278
// Merge values of the same user key starting from the current iter_ position
// Scan from the newer entries to older entries.
// PRE: iter_->key() points to the first merge type entry
//      saved_key_ stores the user key
// POST: saved_value_ has the merged value for the user key
//       iter_ points to the next entry (or invalid)
void DBIter::MergeValuesNewToOld() {
D
Deon Nicholas 已提交
279 280 281 282 283
  if (!user_merge_operator_) {
    Log(logger_, "Options::merge_operator is null.");
    throw std::logic_error("DBIter::MergeValuesNewToOld() with"
                           " Options::merge_operator null");
  }
284

285 286 287
  // Start the merge process by pushing the first operand
  std::deque<std::string> operands;
  operands.push_front(iter_->value().ToString());
288

289
  std::string merge_result;   // Temporary string to hold merge result later
290 291 292 293 294 295 296
  ParsedInternalKey ikey;
  for (iter_->Next(); iter_->Valid(); iter_->Next()) {
    if (!ParseKey(&ikey)) {
      // skip corrupted key
      continue;
    }

297
    if (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) != 0) {
298 299 300 301 302 303 304 305 306 307 308 309
      // hit the next user key, stop right here
      break;
    }

    if (kTypeDeletion == ikey.type) {
      // hit a delete with the same user key, stop right here
      // iter_ is positioned after delete
      iter_->Next();
      break;
    }

    if (kTypeValue == ikey.type) {
310 311 312
      // hit a put, merge the put value with operands and store the
      // final result in saved_value_. We are done!
      // ignore corruption if there is any.
313
      const Slice value = iter_->value();
D
Deon Nicholas 已提交
314
      user_merge_operator_->FullMerge(ikey.user_key, &value, operands,
I
Igor Canadi 已提交
315
                                      &saved_value_, logger_);
316 317 318 319 320 321
      // iter_ is positioned after put
      iter_->Next();
      return;
    }

    if (kTypeMerge == ikey.type) {
322 323 324 325
      // hit a merge, add the value as an operand and run associative merge.
      // when complete, add result to operands and continue.
      const Slice& value = iter_->value();
      operands.push_front(value.ToString());
326 327 328 329 330
    }
  }

  // we either exhausted all internal keys under this user key, or hit
  // a deletion marker.
331
  // feed null as the existing value to the merge operator, such that
332
  // client can differentiate this scenario and do things accordingly.
333
  user_merge_operator_->FullMerge(saved_key_.GetKey(), nullptr, operands,
I
Igor Canadi 已提交
334
                                  &saved_value_, logger_);
335 336
}

J
jorlow@chromium.org 已提交
337 338
void DBIter::Prev() {
  assert(valid_);
S
Stanislau Hlebik 已提交
339 340 341 342 343 344
  if (direction_ == kForward) {
    FindPrevUserKey();
    direction_ = kReverse;
  }
  PrevInternal();
}
J
jorlow@chromium.org 已提交
345

S
Stanislau Hlebik 已提交
346 347 348 349
void DBIter::PrevInternal() {
  if (!iter_->Valid()) {
    valid_ = false;
    return;
350 351
  }

S
Stanislau Hlebik 已提交
352 353 354
  ParsedInternalKey ikey;

  while (iter_->Valid()) {
L
Lei Jin 已提交
355
    saved_key_.SetKey(ExtractUserKey(iter_->key()));
S
Stanislau Hlebik 已提交
356 357
    if (FindValueForCurrentKey()) {
      valid_ = true;
J
jorlow@chromium.org 已提交
358 359 360
      if (!iter_->Valid()) {
        return;
      }
S
Stanislau Hlebik 已提交
361 362 363
      FindParseableKey(&ikey, kReverse);
      if (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) == 0) {
        FindPrevUserKey();
J
jorlow@chromium.org 已提交
364
      }
S
Stanislau Hlebik 已提交
365
      return;
J
jorlow@chromium.org 已提交
366
    }
S
Stanislau Hlebik 已提交
367 368 369 370 371
    if (!iter_->Valid()) {
      break;
    }
    FindParseableKey(&ikey, kReverse);
    if (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) == 0) {
J
jorlow@chromium.org 已提交
372

S
Stanislau Hlebik 已提交
373 374 375 376 377 378
      FindPrevUserKey();
    }
  }
  // We haven't found any key - iterator is not valid
  assert(!iter_->Valid());
  valid_ = false;
J
jorlow@chromium.org 已提交
379 380
}

S
Stanislau Hlebik 已提交
381 382 383 384 385 386 387 388 389
// This function checks, if the entry with biggest sequence_number <= sequence_
// is non kTypeDeletion. If it's not, we save value in saved_value_
bool DBIter::FindValueForCurrentKey() {
  assert(iter_->Valid());
  // Contains operands for merge operator.
  std::deque<std::string> operands;
  // last entry before merge (could be kTypeDeletion or kTypeValue)
  ValueType last_not_merge_type = kTypeDeletion;
  ValueType last_key_entry_type = kTypeDeletion;
J
jorlow@chromium.org 已提交
390

S
Stanislau Hlebik 已提交
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
  ParsedInternalKey ikey;
  FindParseableKey(&ikey, kReverse);

  size_t num_skipped = 0;
  while (iter_->Valid() && ikey.sequence <= sequence_ &&
         (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) == 0)) {
    // We iterate too much: let's use Seek() to avoid too much key comparisons
    if (num_skipped >= max_skip_) {
      return FindValueForCurrentKeyUsingSeek();
    }

    last_key_entry_type = ikey.type;
    switch (last_key_entry_type) {
      case kTypeValue:
        operands.clear();
        saved_value_ = iter_->value().ToString();
        last_not_merge_type = kTypeValue;
        break;
      case kTypeDeletion:
        operands.clear();
        last_not_merge_type = kTypeDeletion;
412
        PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
S
Stanislau Hlebik 已提交
413 414 415 416 417 418 419 420 421
        break;
      case kTypeMerge:
        assert(user_merge_operator_ != nullptr);
        operands.push_back(iter_->value().ToString());
        break;
      default:
        assert(false);
    }

422
    PERF_COUNTER_ADD(internal_key_skipped_count, 1);
S
Stanislau Hlebik 已提交
423 424 425 426 427 428 429 430 431 432 433 434 435 436
    assert(user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) == 0);
    iter_->Prev();
    ++num_skipped;
    FindParseableKey(&ikey, kReverse);
  }

  switch (last_key_entry_type) {
    case kTypeDeletion:
      valid_ = false;
      return false;
    case kTypeMerge:
      if (last_not_merge_type == kTypeDeletion) {
        user_merge_operator_->FullMerge(saved_key_.GetKey(), nullptr, operands,
                                        &saved_value_, logger_);
437
      } else {
S
Stanislau Hlebik 已提交
438 439 440 441 442
        assert(last_not_merge_type == kTypeValue);
        std::string last_put_value = saved_value_;
        Slice temp_slice(last_put_value);
        user_merge_operator_->FullMerge(saved_key_.GetKey(), &temp_slice,
                                        operands, &saved_value_, logger_);
443
      }
S
Stanislau Hlebik 已提交
444 445 446 447 448 449 450
      break;
    case kTypeValue:
      // do nothing - we've already has value in saved_value_
      break;
    default:
      assert(false);
      break;
J
jorlow@chromium.org 已提交
451
  }
S
Stanislau Hlebik 已提交
452 453 454
  valid_ = true;
  return true;
}
J
jorlow@chromium.org 已提交
455

S
Stanislau Hlebik 已提交
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
// This function is used in FindValueForCurrentKey.
// We use Seek() function instead of Prev() to find necessary value
bool DBIter::FindValueForCurrentKeyUsingSeek() {
  std::string last_key;
  AppendInternalKey(&last_key, ParsedInternalKey(saved_key_.GetKey(), sequence_,
                                                 kValueTypeForSeek));
  iter_->Seek(last_key);
  RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);

  // assume there is at least one parseable key for this user key
  ParsedInternalKey ikey;
  FindParseableKey(&ikey, kForward);

  if (ikey.type == kTypeValue || ikey.type == kTypeDeletion) {
    if (ikey.type == kTypeValue) {
      saved_value_ = iter_->value().ToString();
      valid_ = true;
      return true;
    }
J
jorlow@chromium.org 已提交
475
    valid_ = false;
S
Stanislau Hlebik 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
    return false;
  }

  // kTypeMerge. We need to collect all kTypeMerge values and save them
  // in operands
  std::deque<std::string> operands;
  while (iter_->Valid() &&
         (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) == 0) &&
         ikey.type == kTypeMerge) {
    operands.push_front(iter_->value().ToString());
    iter_->Next();
    FindParseableKey(&ikey, kForward);
  }

  if (!iter_->Valid() ||
      (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) != 0) ||
      ikey.type == kTypeDeletion) {
    user_merge_operator_->FullMerge(saved_key_.GetKey(), nullptr, operands,
                                    &saved_value_, logger_);

    // Make iter_ valid and point to saved_key_
    if (!iter_->Valid() ||
        (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) != 0)) {
      iter_->Seek(last_key);
      RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
    }
J
jorlow@chromium.org 已提交
502
    valid_ = true;
S
Stanislau Hlebik 已提交
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
    return true;
  }

  const Slice& value = iter_->value();
  user_merge_operator_->FullMerge(saved_key_.GetKey(), &value, operands,
                                  &saved_value_, logger_);
  valid_ = true;
  return true;
}

// Used in Next to change directions
// Go to next user key
// Don't use Seek(),
// because next user key will be very close
void DBIter::FindNextUserKey() {
  if (!iter_->Valid()) {
    return;
  }
  ParsedInternalKey ikey;
  FindParseableKey(&ikey, kForward);
  while (iter_->Valid() &&
         user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) != 0) {
    iter_->Next();
    FindParseableKey(&ikey, kForward);
  }
}

// Go to previous user_key
void DBIter::FindPrevUserKey() {
  if (!iter_->Valid()) {
    return;
  }
  size_t num_skipped = 0;
  ParsedInternalKey ikey;
  FindParseableKey(&ikey, kReverse);
  while (iter_->Valid() &&
         user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) == 0) {
    if (num_skipped >= max_skip_) {
      num_skipped = 0;
      IterKey last_key;
      last_key.SetInternalKey(ParsedInternalKey(
          saved_key_.GetKey(), kMaxSequenceNumber, kValueTypeForSeek));
      iter_->Seek(last_key.GetKey());
      RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
    }

    iter_->Prev();
    ++num_skipped;
    FindParseableKey(&ikey, kReverse);
  }
}

// Skip all unparseable keys
void DBIter::FindParseableKey(ParsedInternalKey* ikey, Direction direction) {
  while (iter_->Valid() && !ParseKey(ikey)) {
    if (direction == kReverse) {
      iter_->Prev();
    } else {
      iter_->Next();
    }
J
jorlow@chromium.org 已提交
563 564
  }
}
J
jorlow@chromium.org 已提交
565

J
jorlow@chromium.org 已提交
566
void DBIter::Seek(const Slice& target) {
L
Lei Jin 已提交
567 568
  StopWatch sw(env_, statistics_, DB_SEEK);

569 570 571 572 573 574 575 576 577 578 579 580 581 582
  // total ordering is not guaranteed if prefix_extractor is set
  // hence prefix based seeks will not give correct results
  if (iterate_upper_bound_ != nullptr && prefix_extractor_ != nullptr) {
    if (!prefix_extractor_->InDomain(*iterate_upper_bound_) ||
        !prefix_extractor_->InDomain(target) ||
        prefix_extractor_->Transform(*iterate_upper_bound_).compare(
          prefix_extractor_->Transform(target)) != 0) {
      status_ = Status::InvalidArgument("read_options.iterate_*_bound "
                  " and seek target need to have the same prefix.");
      valid_ = false;
      return;
    }
  }

583 584 585
  saved_key_.Clear();
  // now savved_key is used to store internal key.
  saved_key_.SetInternalKey(target, sequence_);
586 587 588 589 590 591

  {
    PERF_TIMER_GUARD(seek_internal_seek_time);
    iter_->Seek(saved_key_.GetKey());
  }

J
jorlow@chromium.org 已提交
592
  if (iter_->Valid()) {
593 594
    direction_ = kForward;
    ClearSavedValue();
595
    FindNextUserEntry(false /*not skipping */);
J
jorlow@chromium.org 已提交
596 597 598 599
  } else {
    valid_ = false;
  }
}
J
jorlow@chromium.org 已提交
600

J
jorlow@chromium.org 已提交
601
void DBIter::SeekToFirst() {
S
Stanislau Hlebik 已提交
602 603
  // Don't use iter_::Seek() if we set a prefix extractor
  // because prefix seek wiil be used.
604
  if (prefix_extractor_ != nullptr) {
S
Stanislau Hlebik 已提交
605 606
    max_skip_ = std::numeric_limits<uint64_t>::max();
  }
J
jorlow@chromium.org 已提交
607 608
  direction_ = kForward;
  ClearSavedValue();
609 610 611 612 613 614

  {
    PERF_TIMER_GUARD(seek_internal_seek_time);
    iter_->SeekToFirst();
  }

J
jorlow@chromium.org 已提交
615
  if (iter_->Valid()) {
616
    FindNextUserEntry(false /* not skipping */);
J
jorlow@chromium.org 已提交
617 618
  } else {
    valid_ = false;
J
jorlow@chromium.org 已提交
619 620 621
  }
}

J
jorlow@chromium.org 已提交
622
void DBIter::SeekToLast() {
S
Stanislau Hlebik 已提交
623 624
  // Don't use iter_::Seek() if we set a prefix extractor
  // because prefix seek wiil be used.
625
  if (prefix_extractor_ != nullptr) {
S
Stanislau Hlebik 已提交
626 627
    max_skip_ = std::numeric_limits<uint64_t>::max();
  }
J
jorlow@chromium.org 已提交
628 629
  direction_ = kReverse;
  ClearSavedValue();
630 631 632 633 634

  {
    PERF_TIMER_GUARD(seek_internal_seek_time);
    iter_->SeekToLast();
  }
S
Stanislau Hlebik 已提交
635 636

  PrevInternal();
J
jorlow@chromium.org 已提交
637 638
}

639 640 641
Iterator* NewDBIterator(Env* env, const Options& options,
                        const Comparator* user_key_comparator,
                        Iterator* internal_iter,
642 643
                        const SequenceNumber& sequence,
                        const Slice* iterate_upper_bound) {
644
  return new DBIter(env, options, user_key_comparator, internal_iter, sequence,
645
                    false, iterate_upper_bound);
646 647
}

I
Igor Canadi 已提交
648
ArenaWrappedDBIter::~ArenaWrappedDBIter() { db_iter_->~DBIter(); }
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670

void ArenaWrappedDBIter::SetDBIter(DBIter* iter) { db_iter_ = iter; }

void ArenaWrappedDBIter::SetIterUnderDBIter(Iterator* iter) {
  static_cast<DBIter*>(db_iter_)->SetIter(iter);
}

inline bool ArenaWrappedDBIter::Valid() const { return db_iter_->Valid(); }
inline void ArenaWrappedDBIter::SeekToFirst() { db_iter_->SeekToFirst(); }
inline void ArenaWrappedDBIter::SeekToLast() { db_iter_->SeekToLast(); }
inline void ArenaWrappedDBIter::Seek(const Slice& target) {
  db_iter_->Seek(target);
}
inline void ArenaWrappedDBIter::Next() { db_iter_->Next(); }
inline void ArenaWrappedDBIter::Prev() { db_iter_->Prev(); }
inline Slice ArenaWrappedDBIter::key() const { return db_iter_->key(); }
inline Slice ArenaWrappedDBIter::value() const { return db_iter_->value(); }
inline Status ArenaWrappedDBIter::status() const { return db_iter_->status(); }
void ArenaWrappedDBIter::RegisterCleanup(CleanupFunction function, void* arg1,
                                         void* arg2) {
  db_iter_->RegisterCleanup(function, arg1, arg2);
}
J
jorlow@chromium.org 已提交
671

672 673
ArenaWrappedDBIter* NewArenaWrappedDbIterator(
    Env* env, const Options& options, const Comparator* user_key_comparator,
674 675
    const SequenceNumber& sequence,
    const Slice* iterate_upper_bound) {
676 677 678
  ArenaWrappedDBIter* iter = new ArenaWrappedDBIter();
  Arena* arena = iter->GetArena();
  auto mem = arena->AllocateAligned(sizeof(DBIter));
679 680 681
  DBIter* db_iter = new (mem) DBIter(env, options, user_key_comparator,
      nullptr, sequence, true, iterate_upper_bound);

682
  iter->SetDBIter(db_iter);
683

684
  return iter;
J
jorlow@chromium.org 已提交
685 686
}

687
}  // namespace rocksdb