#include "rocksdb/iterator.h"
#include "memory/arena.h"
#include "table/internal_iterator.h"
#include "table/iterator_wrapper.h"
namespace ROCKSDB_NAMESPACE {
Cleanable::Cleanable() {
cleanup_.function = nullptr;
cleanup_.next = nullptr;
}
Cleanable::~Cleanable() { DoCleanup(); }
Cleanable::Cleanable(Cleanable&& other) {
*this = std::move(other);
}
Cleanable& Cleanable::operator=(Cleanable&& other) {
if (this != &other) {
cleanup_ = other.cleanup_;
other.cleanup_.function = nullptr;
other.cleanup_.next = nullptr;
}
return *this;
}
void Cleanable::DelegateCleanupsTo(Cleanable* other) {
assert(other != nullptr);
if (cleanup_.function == nullptr) {
return;
}
Cleanup* c = &cleanup_;
other->RegisterCleanup(c->function, c->arg1, c->arg2);
c = c->next;
while (c != nullptr) {
Cleanup* next = c->next;
other->RegisterCleanup(c);
c = next;
}
cleanup_.function = nullptr;
cleanup_.next = nullptr;
}
void Cleanable::RegisterCleanup(Cleanable::Cleanup* c) {
assert(c != nullptr);
if (cleanup_.function == nullptr) {
cleanup_.function = c->function;
cleanup_.arg1 = c->arg1;
cleanup_.arg2 = c->arg2;
delete c;
} else {
c->next = cleanup_.next;
cleanup_.next = c;
}
}
void Cleanable::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) {
assert(func != nullptr);
Cleanup* c;
if (cleanup_.function == nullptr) {
c = &cleanup_;
} else {
c = new Cleanup;
c->next = cleanup_.next;
cleanup_.next = c;
}
c->function = func;
c->arg1 = arg1;
c->arg2 = arg2;
}
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();
}
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& ) override {}
void SeekForPrev(const Slice& ) 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& ) override {}
void SeekForPrev(const Slice& ) 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_;
};
}
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);
}