mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-25 14:31:35 +00:00
4eaf628120
Summary: `ReadOptions::pin_data` already has the effect of pinning the `Slice` returned by `Iterator::value()` when the value is stored inline (e.g., `kTypeValue`). This PR adds a bit of visibility into that via a new `Iterator` property, "rocksdb.iterator.is-value-pinned", as well as some documentation and tests. See also: https://github.com/facebook/rocksdb/issues/12658 Pull Request resolved: https://github.com/facebook/rocksdb/pull/12659 Reviewed By: cbi42 Differential Revision: D57391200 Pulled By: ajkr fbshipit-source-id: 0caa8db27ca1aba86ee2addc3dfd6f0e003d32e2
135 lines
4.3 KiB
C++
135 lines
4.3 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
//
|
|
// 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 "rocksdb/iterator.h"
|
|
|
|
#include "memory/arena.h"
|
|
#include "table/internal_iterator.h"
|
|
#include "table/iterator_wrapper.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
Status Iterator::GetProperty(std::string prop_name, std::string* prop) {
|
|
if (prop == nullptr) {
|
|
return Status::InvalidArgument("prop is nullptr");
|
|
}
|
|
if (prop_name == "rocksdb.iterator.is-key-pinned") {
|
|
*prop = "0";
|
|
return Status::OK();
|
|
}
|
|
if (prop_name == "rocksdb.iterator.is-value-pinned") {
|
|
*prop = "0";
|
|
return Status::OK();
|
|
}
|
|
return Status::InvalidArgument("Unidentified property.");
|
|
}
|
|
|
|
namespace {
|
|
class EmptyIterator : public Iterator {
|
|
public:
|
|
explicit EmptyIterator(const Status& s) : status_(s) {}
|
|
bool Valid() const override { return false; }
|
|
void Seek(const Slice& /*target*/) override {}
|
|
void SeekForPrev(const Slice& /*target*/) override {}
|
|
void SeekToFirst() override {}
|
|
void SeekToLast() override {}
|
|
void Next() override { assert(false); }
|
|
void Prev() override { assert(false); }
|
|
Slice key() const override {
|
|
assert(false);
|
|
return Slice();
|
|
}
|
|
Slice value() const override {
|
|
assert(false);
|
|
return Slice();
|
|
}
|
|
Status status() const override { return status_; }
|
|
|
|
private:
|
|
Status status_;
|
|
};
|
|
|
|
template <class TValue = Slice>
|
|
class EmptyInternalIterator : public InternalIteratorBase<TValue> {
|
|
public:
|
|
explicit EmptyInternalIterator(const Status& s) : status_(s) {}
|
|
bool Valid() const override { return false; }
|
|
void Seek(const Slice& /*target*/) override {}
|
|
void SeekForPrev(const Slice& /*target*/) override {}
|
|
void SeekToFirst() override {}
|
|
void SeekToLast() override {}
|
|
void Next() override { assert(false); }
|
|
void Prev() override { assert(false); }
|
|
Slice key() const override {
|
|
assert(false);
|
|
return Slice();
|
|
}
|
|
TValue value() const override {
|
|
assert(false);
|
|
return TValue();
|
|
}
|
|
Status status() const override { return status_; }
|
|
|
|
private:
|
|
Status status_;
|
|
};
|
|
} // namespace
|
|
|
|
Iterator* NewEmptyIterator() { return new EmptyIterator(Status::OK()); }
|
|
|
|
Iterator* NewErrorIterator(const Status& status) {
|
|
return new EmptyIterator(status);
|
|
}
|
|
|
|
template <class TValue>
|
|
InternalIteratorBase<TValue>* NewErrorInternalIterator(const Status& status) {
|
|
return new EmptyInternalIterator<TValue>(status);
|
|
}
|
|
template InternalIteratorBase<IndexValue>* NewErrorInternalIterator(
|
|
const Status& status);
|
|
template InternalIteratorBase<Slice>* NewErrorInternalIterator(
|
|
const Status& status);
|
|
|
|
template <class TValue>
|
|
InternalIteratorBase<TValue>* NewErrorInternalIterator(const Status& status,
|
|
Arena* arena) {
|
|
if (arena == nullptr) {
|
|
return NewErrorInternalIterator<TValue>(status);
|
|
} else {
|
|
auto mem = arena->AllocateAligned(sizeof(EmptyInternalIterator<TValue>));
|
|
return new (mem) EmptyInternalIterator<TValue>(status);
|
|
}
|
|
}
|
|
template InternalIteratorBase<IndexValue>* NewErrorInternalIterator(
|
|
const Status& status, Arena* arena);
|
|
template InternalIteratorBase<Slice>* NewErrorInternalIterator(
|
|
const Status& status, Arena* arena);
|
|
|
|
template <class TValue>
|
|
InternalIteratorBase<TValue>* NewEmptyInternalIterator() {
|
|
return new EmptyInternalIterator<TValue>(Status::OK());
|
|
}
|
|
template InternalIteratorBase<IndexValue>* NewEmptyInternalIterator();
|
|
template InternalIteratorBase<Slice>* NewEmptyInternalIterator();
|
|
|
|
template <class TValue>
|
|
InternalIteratorBase<TValue>* NewEmptyInternalIterator(Arena* arena) {
|
|
if (arena == nullptr) {
|
|
return NewEmptyInternalIterator<TValue>();
|
|
} else {
|
|
auto mem = arena->AllocateAligned(sizeof(EmptyInternalIterator<TValue>));
|
|
return new (mem) EmptyInternalIterator<TValue>(Status::OK());
|
|
}
|
|
}
|
|
template InternalIteratorBase<IndexValue>* NewEmptyInternalIterator(
|
|
Arena* arena);
|
|
template InternalIteratorBase<Slice>* NewEmptyInternalIterator(Arena* arena);
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|