2016-02-09 23:12:00 +00:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2013-10-16 21:59:46 +00:00
|
|
|
// 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.
|
|
|
|
//
|
2011-03-18 22:37:00 +00:00
|
|
|
// 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.
|
|
|
|
|
2013-10-05 05:32:05 +00:00
|
|
|
#pragma once
|
2014-05-30 21:31:55 +00:00
|
|
|
|
2015-12-16 20:08:30 +00:00
|
|
|
#include <set>
|
|
|
|
|
2015-10-12 22:06:38 +00:00
|
|
|
#include "table/internal_iterator.h"
|
2014-05-30 21:31:55 +00:00
|
|
|
|
2013-10-04 04:49:15 +00:00
|
|
|
namespace rocksdb {
|
2011-03-18 22:37:00 +00:00
|
|
|
|
|
|
|
// A internal wrapper class with an interface similar to Iterator that
|
|
|
|
// caches the valid() and key() results for an underlying iterator.
|
|
|
|
// This can help avoid virtual function calls and also gives better
|
|
|
|
// cache locality.
|
|
|
|
class IteratorWrapper {
|
|
|
|
public:
|
2015-12-16 20:08:30 +00:00
|
|
|
IteratorWrapper() : iter_(nullptr), iters_pinned_(false), valid_(false) {}
|
|
|
|
explicit IteratorWrapper(InternalIterator* _iter)
|
|
|
|
: iter_(nullptr), iters_pinned_(false) {
|
2015-10-12 22:06:38 +00:00
|
|
|
Set(_iter);
|
|
|
|
}
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
~IteratorWrapper() {}
|
2015-10-12 22:06:38 +00:00
|
|
|
InternalIterator* iter() const { return iter_; }
|
2011-03-18 22:37:00 +00:00
|
|
|
|
2015-12-16 20:08:30 +00:00
|
|
|
// Takes the ownership of "_iter" and will delete it when destroyed.
|
|
|
|
// Next call to Set() will destroy "_iter" except if PinData() was called.
|
2015-10-12 22:06:38 +00:00
|
|
|
void Set(InternalIterator* _iter) {
|
2015-12-16 20:08:30 +00:00
|
|
|
if (iters_pinned_ && iter_) {
|
|
|
|
// keep old iterator until ReleasePinnedData() is called
|
|
|
|
pinned_iters_.insert(iter_);
|
|
|
|
} else {
|
|
|
|
delete iter_;
|
|
|
|
}
|
|
|
|
|
2014-11-06 19:14:28 +00:00
|
|
|
iter_ = _iter;
|
2013-03-01 02:04:58 +00:00
|
|
|
if (iter_ == nullptr) {
|
2011-03-18 22:37:00 +00:00
|
|
|
valid_ = false;
|
|
|
|
} else {
|
|
|
|
Update();
|
2015-12-16 20:08:30 +00:00
|
|
|
if (iters_pinned_) {
|
|
|
|
// Pin new iterator
|
|
|
|
Status s = iter_->PinData();
|
|
|
|
assert(s.ok());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Status PinData() {
|
|
|
|
Status s;
|
|
|
|
if (iters_pinned_) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iter_) {
|
|
|
|
s = iter_->PinData();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s.ok()) {
|
|
|
|
iters_pinned_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status ReleasePinnedData() {
|
|
|
|
Status s;
|
|
|
|
if (!iters_pinned_) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iter_) {
|
|
|
|
s = iter_->ReleasePinnedData();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s.ok()) {
|
|
|
|
iters_pinned_ = false;
|
|
|
|
// No need to call ReleasePinnedData() for pinned_iters_
|
|
|
|
// since we will delete them
|
|
|
|
DeletePinnedIterators(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsKeyPinned() const {
|
|
|
|
assert(iter_);
|
|
|
|
return iters_pinned_ && iter_->IsKeyPinned();
|
|
|
|
}
|
|
|
|
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
void DeleteIter(bool is_arena_mode) {
|
2016-01-12 00:48:15 +00:00
|
|
|
if (iter_ && pinned_iters_.find(iter_) == pinned_iters_.end()) {
|
|
|
|
DestroyIterator(iter_, is_arena_mode);
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
}
|
2015-12-16 20:08:30 +00:00
|
|
|
DeletePinnedIterators(is_arena_mode);
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
}
|
|
|
|
|
2011-03-18 22:37:00 +00:00
|
|
|
// Iterator interface methods
|
2011-06-02 00:00:37 +00:00
|
|
|
bool Valid() const { return valid_; }
|
|
|
|
Slice key() const { assert(Valid()); return key_; }
|
|
|
|
Slice value() const { assert(Valid()); return iter_->value(); }
|
2013-03-01 02:04:58 +00:00
|
|
|
// Methods below require iter() != nullptr
|
2011-06-02 00:00:37 +00:00
|
|
|
Status status() const { assert(iter_); return iter_->status(); }
|
|
|
|
void Next() { assert(iter_); iter_->Next(); Update(); }
|
|
|
|
void Prev() { assert(iter_); iter_->Prev(); Update(); }
|
|
|
|
void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); }
|
|
|
|
void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); }
|
|
|
|
void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); }
|
2011-03-18 22:37:00 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
void Update() {
|
|
|
|
valid_ = iter_->Valid();
|
|
|
|
if (valid_) {
|
|
|
|
key_ = iter_->key();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-12 00:48:15 +00:00
|
|
|
void DeletePinnedIterators(bool is_arena_mode) {
|
|
|
|
for (auto it : pinned_iters_) {
|
|
|
|
DestroyIterator(it, is_arena_mode);
|
|
|
|
}
|
|
|
|
pinned_iters_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void DestroyIterator(InternalIterator* it, bool is_arena_mode) {
|
|
|
|
if (!is_arena_mode) {
|
|
|
|
delete it;
|
|
|
|
} else {
|
|
|
|
it->~InternalIterator();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-12 22:06:38 +00:00
|
|
|
InternalIterator* iter_;
|
2015-12-16 20:08:30 +00:00
|
|
|
// If set to true, current and future iterators wont be deleted.
|
|
|
|
bool iters_pinned_;
|
|
|
|
// List of past iterators that are pinned and wont be deleted as long as
|
|
|
|
// iters_pinned_ is true. When we are pinning iterators this set will contain
|
|
|
|
// iterators of previous data blocks to keep them from being deleted.
|
|
|
|
std::set<InternalIterator*> pinned_iters_;
|
2011-05-28 00:53:58 +00:00
|
|
|
bool valid_;
|
|
|
|
Slice key_;
|
|
|
|
};
|
2011-03-18 22:37:00 +00:00
|
|
|
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
class Arena;
|
|
|
|
// Return an empty iterator (yields nothing) allocated from arena.
|
2015-10-12 22:06:38 +00:00
|
|
|
extern InternalIterator* NewEmptyInternalIterator(Arena* arena);
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
|
|
|
|
// Return an empty iterator with the specified status, allocated arena.
|
2015-10-12 22:06:38 +00:00
|
|
|
extern InternalIterator* NewErrorInternalIterator(const Status& status,
|
|
|
|
Arena* arena);
|
In DB::NewIterator(), try to allocate the whole iterator tree in an arena
Summary:
In this patch, try to allocate the whole iterator tree starting from DBIter from an arena
1. ArenaWrappedDBIter is created when serves as the entry point of an iterator tree, with an arena in it.
2. Add an option to create iterator from arena for following iterators: DBIter, MergingIterator, MemtableIterator, all mem table's iterators, all table reader's iterators and two level iterator.
3. MergeIteratorBuilder is created to incrementally build the tree of internal iterators. It is passed to mem table list and version set and add iterators to it.
Limitations:
(1) Only DB::NewIterator() without tailing uses the arena. Other cases, including readonly DB and compactions are still from malloc
(2) Two level iterator itself is allocated in arena, but not iterators inside it.
Test Plan: make all check
Reviewers: ljin, haobo
Reviewed By: haobo
Subscribers: leveldb, dhruba, yhchiang, igor
Differential Revision: https://reviews.facebook.net/D18513
2014-06-02 23:38:00 +00:00
|
|
|
|
2013-10-04 04:49:15 +00:00
|
|
|
} // namespace rocksdb
|