2013-10-16 23:59:46 +02:00
|
|
|
// 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.
|
|
|
|
//
|
2013-08-23 17:38:13 +02:00
|
|
|
#include "rocksdb/memtablerep.h"
|
2013-07-23 23:42:27 +02:00
|
|
|
#include "db/memtable.h"
|
|
|
|
#include "db/skiplist.h"
|
|
|
|
|
2013-10-04 06:49:15 +02:00
|
|
|
namespace rocksdb {
|
2013-08-23 08:10:02 +02:00
|
|
|
namespace {
|
2013-07-23 23:42:27 +02:00
|
|
|
class SkipListRep : public MemTableRep {
|
2014-03-10 20:56:46 +01:00
|
|
|
SkipList<const char*, const MemTableRep::KeyComparator&> skip_list_;
|
2013-07-23 23:42:27 +02:00
|
|
|
public:
|
2014-03-10 20:56:46 +01:00
|
|
|
explicit SkipListRep(const MemTableRep::KeyComparator& compare, Arena* arena)
|
Make arena block size configurable
Summary:
Add an option for arena block size, default value 4096 bytes. Arena will allocate blocks with such size.
I am not sure about passing parameter to skiplist in the new virtualized framework, though I talked to Jim a bit. So add Jim as reviewer.
Test Plan:
new unit test, I am running db_test.
For passing paramter from configured option to Arena, I tried tests like:
TEST(DBTest, Arena_Option) {
std::string dbname = test::TmpDir() + "/db_arena_option_test";
DestroyDB(dbname, Options());
DB* db = nullptr;
Options opts;
opts.create_if_missing = true;
opts.arena_block_size = 1000000; // tested 99, 999999
Status s = DB::Open(opts, dbname, &db);
db->Put(WriteOptions(), "a", "123");
}
and printed some debug info. The results look good. Any suggestion for such a unit-test?
Reviewers: haobo, dhruba, emayanke, jpaton
Reviewed By: dhruba
CC: leveldb, zshao
Differential Revision: https://reviews.facebook.net/D11799
2013-07-31 21:42:23 +02:00
|
|
|
: skip_list_(compare, arena) {
|
2014-03-10 20:56:46 +01:00
|
|
|
}
|
2013-07-23 23:42:27 +02:00
|
|
|
|
|
|
|
// Insert key into the list.
|
|
|
|
// REQUIRES: nothing that compares equal to key is currently in the list.
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual void Insert(const char* key) override {
|
2013-07-23 23:42:27 +02:00
|
|
|
skip_list_.Insert(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true iff an entry that compares equal to key is in the list.
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual bool Contains(const char* key) const override {
|
2013-07-23 23:42:27 +02:00
|
|
|
return skip_list_.Contains(key);
|
|
|
|
}
|
|
|
|
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual size_t ApproximateMemoryUsage() override {
|
|
|
|
// All memory is allocated through arena; nothing to report here
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-11 18:46:30 +01:00
|
|
|
virtual void Get(const LookupKey& k, void* callback_args,
|
|
|
|
bool (*callback_func)(void* arg,
|
|
|
|
const char* entry)) override {
|
|
|
|
SkipListRep::Iterator iter(&skip_list_);
|
|
|
|
Slice dummy_slice;
|
|
|
|
for (iter.Seek(dummy_slice, k.memtable_key().data());
|
|
|
|
iter.Valid() && callback_func(callback_args, iter.key());
|
|
|
|
iter.Next()) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual ~SkipListRep() override { }
|
2013-07-23 23:42:27 +02:00
|
|
|
|
|
|
|
// Iteration over the contents of a skip list
|
|
|
|
class Iterator : public MemTableRep::Iterator {
|
2014-03-10 20:56:46 +01:00
|
|
|
SkipList<const char*, const MemTableRep::KeyComparator&>::Iterator iter_;
|
2013-07-23 23:42:27 +02:00
|
|
|
public:
|
|
|
|
// Initialize an iterator over the specified list.
|
|
|
|
// The returned iterator is not valid.
|
|
|
|
explicit Iterator(
|
2014-03-10 20:56:46 +01:00
|
|
|
const SkipList<const char*, const MemTableRep::KeyComparator&>* list
|
2013-07-23 23:42:27 +02:00
|
|
|
) : iter_(list) { }
|
|
|
|
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual ~Iterator() override { }
|
2013-07-23 23:42:27 +02:00
|
|
|
|
|
|
|
// Returns true iff the iterator is positioned at a valid node.
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual bool Valid() const override {
|
2013-07-23 23:42:27 +02:00
|
|
|
return iter_.Valid();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the key at the current position.
|
|
|
|
// REQUIRES: Valid()
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual const char* key() const override {
|
2013-07-23 23:42:27 +02:00
|
|
|
return iter_.key();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advances to the next position.
|
|
|
|
// REQUIRES: Valid()
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual void Next() override {
|
2013-07-23 23:42:27 +02:00
|
|
|
iter_.Next();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advances to the previous position.
|
|
|
|
// REQUIRES: Valid()
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual void Prev() override {
|
2013-07-23 23:42:27 +02:00
|
|
|
iter_.Prev();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advance to the first entry with a key >= target
|
2013-11-21 04:49:27 +01:00
|
|
|
virtual void Seek(const Slice& user_key, const char* memtable_key)
|
|
|
|
override {
|
|
|
|
if (memtable_key != nullptr) {
|
|
|
|
iter_.Seek(memtable_key);
|
|
|
|
} else {
|
|
|
|
iter_.Seek(EncodeKey(&tmp_, user_key));
|
|
|
|
}
|
2013-07-23 23:42:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Position at the first entry in list.
|
|
|
|
// Final state of iterator is Valid() iff list is not empty.
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual void SeekToFirst() override {
|
2013-07-23 23:42:27 +02:00
|
|
|
iter_.SeekToFirst();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Position at the last entry in list.
|
|
|
|
// Final state of iterator is Valid() iff list is not empty.
|
2013-08-23 08:10:02 +02:00
|
|
|
virtual void SeekToLast() override {
|
2013-07-23 23:42:27 +02:00
|
|
|
iter_.SeekToLast();
|
|
|
|
}
|
2013-11-21 04:49:27 +01:00
|
|
|
protected:
|
|
|
|
std::string tmp_; // For passing to EncodeKey
|
2013-07-23 23:42:27 +02:00
|
|
|
};
|
|
|
|
|
2013-08-23 08:10:02 +02:00
|
|
|
// Unhide default implementations of GetIterator
|
|
|
|
using MemTableRep::GetIterator;
|
2013-07-23 23:42:27 +02:00
|
|
|
|
2014-01-16 03:17:58 +01:00
|
|
|
virtual MemTableRep::Iterator* GetIterator() override {
|
|
|
|
return new SkipListRep::Iterator(&skip_list_);
|
2013-07-23 23:42:27 +02:00
|
|
|
}
|
|
|
|
};
|
2013-08-23 08:10:02 +02:00
|
|
|
}
|
2013-07-23 23:42:27 +02:00
|
|
|
|
2014-01-16 03:17:58 +01:00
|
|
|
MemTableRep* SkipListFactory::CreateMemTableRep(
|
2014-03-10 20:56:46 +01:00
|
|
|
const MemTableRep::KeyComparator& compare, Arena* arena,
|
|
|
|
const SliceTransform*) {
|
2014-01-16 03:17:58 +01:00
|
|
|
return new SkipListRep(compare, arena);
|
2013-07-23 23:42:27 +02:00
|
|
|
}
|
|
|
|
|
2013-10-04 06:49:15 +02:00
|
|
|
} // namespace rocksdb
|