21e8daced5
Summary: fix assertion failure in db_stress. It happens because of prefix seek key is larger than merge iterator key when they have the same user key Test Plan: ./db_stress --max_background_compactions=1 --max_write_buffer_number=3 --sync=0 --reopen=20 --write_buffer_size=33554432 --delpercent=5 --log2_keys_per_lock=10 --block_size=16384 --allow_concurrent_memtable_write=0 --test_batches_snapshots=0 --max_bytes_for_level_base=67108864 --progress_reports=0 --mmap_read=0 --writepercent=35 --disable_data_sync=0 --readpercent=50 --subcompactions=4 --ops_per_thread=20000000 --memtablerep=skip_list --prefix_size=0 --target_file_size_multiplier=1 --column_families=1 --threads=32 --disable_wal=0 --open_files=500000 --destroy_db_initially=0 --target_file_size_base=16777216 --nooverwritepercent=1 --iterpercent=10 --max_key=100000000 --prefixpercent=0 --use_clock_cache=false --kill_random_test=888887 --cache_size=1048576 --verify_checksum=1 Reviewers: sdong, andrewkr, yiwu, yhchiang Reviewed By: yhchiang Subscribers: andrewkr, dhruba, leveldb Differential Revision: https://reviews.facebook.net/D65025
122 lines
4.4 KiB
C++
122 lines
4.4 KiB
C++
// Copyright (c) 2011-present, 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.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include "rocksdb/comparator.h"
|
|
#include "rocksdb/iterator.h"
|
|
#include "rocksdb/status.h"
|
|
|
|
namespace rocksdb {
|
|
|
|
class PinnedIteratorsManager;
|
|
|
|
class InternalIterator : public Cleanable {
|
|
public:
|
|
InternalIterator() {}
|
|
virtual ~InternalIterator() {}
|
|
|
|
// An iterator is either positioned at a key/value pair, or
|
|
// not valid. This method returns true iff the iterator is valid.
|
|
virtual bool Valid() const = 0;
|
|
|
|
// Position at the first key in the source. The iterator is Valid()
|
|
// after this call iff the source is not empty.
|
|
virtual void SeekToFirst() = 0;
|
|
|
|
// Position at the last key in the source. The iterator is
|
|
// Valid() after this call iff the source is not empty.
|
|
virtual void SeekToLast() = 0;
|
|
|
|
// Position at the first key in the source that at or past target
|
|
// The iterator is Valid() after this call iff the source contains
|
|
// an entry that comes at or past target.
|
|
virtual void Seek(const Slice& target) = 0;
|
|
|
|
// Position at the first key in the source that at or before target
|
|
// The iterator is Valid() after this call iff the source contains
|
|
// an entry that comes at or before target.
|
|
virtual void SeekForPrev(const Slice& target) = 0;
|
|
|
|
// Moves to the next entry in the source. After this call, Valid() is
|
|
// true iff the iterator was not positioned at the last entry in the source.
|
|
// REQUIRES: Valid()
|
|
virtual void Next() = 0;
|
|
|
|
// Moves to the previous entry in the source. After this call, Valid() is
|
|
// true iff the iterator was not positioned at the first entry in source.
|
|
// REQUIRES: Valid()
|
|
virtual void Prev() = 0;
|
|
|
|
// Return the key for the current entry. The underlying storage for
|
|
// the returned slice is valid only until the next modification of
|
|
// the iterator.
|
|
// REQUIRES: Valid()
|
|
virtual Slice key() const = 0;
|
|
|
|
// Return the value for the current entry. The underlying storage for
|
|
// the returned slice is valid only until the next modification of
|
|
// the iterator.
|
|
// REQUIRES: !AtEnd() && !AtStart()
|
|
virtual Slice value() const = 0;
|
|
|
|
// If an error has occurred, return it. Else return an ok status.
|
|
// If non-blocking IO is requested and this operation cannot be
|
|
// satisfied without doing some IO, then this returns Status::Incomplete().
|
|
virtual Status status() const = 0;
|
|
|
|
// Pass the PinnedIteratorsManager to the Iterator, most Iterators dont
|
|
// communicate with PinnedIteratorsManager so default implementation is no-op
|
|
// but for Iterators that need to communicate with PinnedIteratorsManager
|
|
// they will implement this function and use the passed pointer to communicate
|
|
// with PinnedIteratorsManager.
|
|
virtual void SetPinnedItersMgr(PinnedIteratorsManager* pinned_iters_mgr) {}
|
|
|
|
// If true, this means that the Slice returned by key() is valid as long as
|
|
// PinnedIteratorsManager::ReleasePinnedData is not called and the
|
|
// Iterator is not deleted.
|
|
//
|
|
// IsKeyPinned() is guaranteed to always return true if
|
|
// - Iterator is created with ReadOptions::pin_data = true
|
|
// - DB tables were created with BlockBasedTableOptions::use_delta_encoding
|
|
// set to false.
|
|
virtual bool IsKeyPinned() const { return false; }
|
|
|
|
// If true, this means that the Slice returned by value() is valid as long as
|
|
// PinnedIteratorsManager::ReleasePinnedData is not called and the
|
|
// Iterator is not deleted.
|
|
virtual bool IsValuePinned() const { return false; }
|
|
|
|
virtual Status GetProperty(std::string prop_name, std::string* prop) {
|
|
return Status::NotSupported("");
|
|
}
|
|
|
|
protected:
|
|
void SeekForPrevImpl(const Slice& target, const Comparator* cmp) {
|
|
Seek(target);
|
|
if (!Valid()) {
|
|
SeekToLast();
|
|
}
|
|
while (Valid() && cmp->Compare(target, key()) < 0) {
|
|
Prev();
|
|
}
|
|
}
|
|
|
|
private:
|
|
// No copying allowed
|
|
InternalIterator(const InternalIterator&) = delete;
|
|
InternalIterator& operator=(const InternalIterator&) = delete;
|
|
};
|
|
|
|
// Return an empty iterator (yields nothing).
|
|
extern InternalIterator* NewEmptyInternalIterator();
|
|
|
|
// Return an empty iterator with the specified status.
|
|
extern InternalIterator* NewErrorInternalIterator(const Status& status);
|
|
|
|
} // namespace rocksdb
|