Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kv/KeyValueDB: add column family #18049

Merged
merged 11 commits into from
Oct 6, 2017
4 changes: 4 additions & 0 deletions src/common/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3447,6 +3447,10 @@ std::vector<Option> get_global_options() {
.set_default("compression=kNoCompression,max_write_buffer_number=4,min_write_buffer_number_to_merge=1,recycle_log_file_num=4,write_buffer_size=268435456,writable_file_max_buffer_size=0,compaction_readahead_size=2097152")
.set_description("Rocksdb options"),

Option("bluestore_rocksdb_cf", Option::TYPE_BOOL, Option::LEVEL_ADVANCED)
.set_default(false)
.set_description("Enable use of rocksdb column families for bluestore metadata"),

Option("bluestore_fsck_on_mount", Option::TYPE_BOOL, Option::LEVEL_DEV)
.set_default(false)
.set_description("Run fsck at mount"),
Expand Down
121 changes: 87 additions & 34 deletions src/kv/KeyValueDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,31 @@
#include "common/perf_counters.h"

using std::string;
using std::vector;
/**
* Defines virtual interface to be implemented by key value store
*
* Kyoto Cabinet or LevelDB should implement this
*/
class KeyValueDB {
public:
/*
* See RocksDB's definition of a column family(CF) and how to use it.
* The interfaces of KeyValueDB is extended, when a column family is created.
* Prefix will be the name of column family to use.
*/
struct ColumnFamily {
string name; //< name of this individual column family
string option; //< configure option string for this CF
ColumnFamily(const string &name, const string &option)
: name(name), option(option) {}
};

class TransactionImpl {
public:
/// Set Keys
void set(
const std::string &prefix, ///< [in] Prefix for keys
const std::string &prefix, ///< [in] Prefix for keys, or CF name

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tab left

const std::map<std::string, bufferlist> &to_set ///< [in] keys/values to set
) {
std::map<std::string, bufferlist>::const_iterator it;
Expand All @@ -36,8 +49,8 @@ class KeyValueDB {

/// Set Keys (via encoded bufferlist)
void set(
const std::string &prefix, ///< [in] prefix
bufferlist& to_set_bl ///< [in] encoded key/values to set
const std::string &prefix, ///< [in] prefix, or CF name
bufferlist& to_set_bl ///< [in] encoded key/values to set
) {
bufferlist::iterator p = to_set_bl.begin();
uint32_t num;
Expand All @@ -53,9 +66,9 @@ class KeyValueDB {

/// Set Key
virtual void set(
const std::string &prefix, ///< [in] Prefix for the key
const std::string &prefix, ///< [in] Prefix or CF for the key
const std::string &k, ///< [in] Key to set
const bufferlist &bl ///< [in] Value to set
const bufferlist &bl ///< [in] Value to set
) = 0;
virtual void set(
const std::string &prefix,
Expand All @@ -67,8 +80,8 @@ class KeyValueDB {

/// Removes Keys (via encoded bufferlist)
void rmkeys(
const std::string &prefix, ///< [in] Prefix to search for
bufferlist &keys_bl ///< [in] Keys to remove
const std::string &prefix, ///< [in] Prefix or CF to search for
bufferlist &keys_bl ///< [in] Keys to remove
) {
bufferlist::iterator p = keys_bl.begin();
uint32_t num;
Expand All @@ -82,7 +95,7 @@ class KeyValueDB {

/// Removes Keys
void rmkeys(
const std::string &prefix, ///< [in] Prefix to search for
const std::string &prefix, ///< [in] Prefix/CF to search for
const std::set<std::string> &keys ///< [in] Keys to remove
) {
std::set<std::string>::const_iterator it;
Expand All @@ -92,8 +105,8 @@ class KeyValueDB {

/// Remove Key
virtual void rmkey(
const std::string &prefix, ///< [in] Prefix to search for
const std::string &k ///< [in] Key to remove
const std::string &prefix, ///< [in] Prefix/CF to search for
const std::string &k ///< [in] Key to remove
) = 0;
virtual void rmkey(
const std::string &prefix, ///< [in] Prefix to search for
Expand All @@ -109,13 +122,13 @@ class KeyValueDB {
/// If a key is overwritten (by calling set multiple times), then the result
/// of calling rm_single_key on this key is undefined.
virtual void rm_single_key(
const std::string &prefix, ///< [in] Prefix to search for
const std::string &prefix, ///< [in] Prefix/CF to search for
const std::string &k ///< [in] Key to remove
) { return rmkey(prefix, k);}

/// Removes keys beginning with prefix
virtual void rmkeys_by_prefix(
const std::string &prefix ///< [in] Prefix by which to remove keys
const std::string &prefix ///< [in] Prefix/CF by which to remove keys
) = 0;

virtual void rm_range_keys(
Expand All @@ -126,7 +139,7 @@ class KeyValueDB {

/// Merge value into key
virtual void merge(
const std::string &prefix, ///< [in] Prefix ==> MUST match some established merge operator
const std::string &prefix, ///< [in] Prefix/CF ==> MUST match some established merge operator
const std::string &key, ///< [in] Key to be merged
const bufferlist &value ///< [in] value to be merged into key
) { assert(0 == "Not implemented"); }
Expand All @@ -144,8 +157,16 @@ class KeyValueDB {
static int test_init(const std::string& type, const std::string& dir);
virtual int init(string option_str="") = 0;
virtual int open(std::ostream &out) = 0;
virtual int open(std::ostream &out, const vector<ColumnFamily>& cfs) {
assert(0 == "Not implemented");
}
virtual int create_and_open(std::ostream &out) = 0;
virtual void close() { }
// vector cfs contains column families to be created when db is created.
virtual int create_and_open(std::ostream &out,
const vector<ColumnFamily>& cfs) {
assert(0 == "Not implemented");
}

virtual Transaction get_transaction() = 0;
virtual int submit_transaction(Transaction) = 0;
Expand All @@ -155,13 +176,13 @@ class KeyValueDB {

/// Retrieve Keys
virtual int get(
const std::string &prefix, ///< [in] Prefix for key
const std::set<std::string> &key, ///< [in] Key to retrieve
std::map<std::string, bufferlist> *out ///< [out] Key value retrieved
const std::string &prefix, ///< [in] Prefix/CF for key
const std::set<std::string> &key, ///< [in] Key to retrieve
std::map<std::string, bufferlist> *out ///< [out] Key value retrieved
) = 0;
virtual int get(const std::string &prefix, ///< [in] prefix
virtual int get(const std::string &prefix, ///< [in] prefix or CF name
const std::string &key, ///< [in] key
bufferlist *value) { ///< [out] value
bufferlist *value) { ///< [out] value
std::set<std::string> ks;
ks.insert(key);
std::map<std::string,bufferlist> om;
Expand All @@ -180,7 +201,10 @@ class KeyValueDB {
return get(prefix, string(key, keylen), value);
}

class GenericIteratorImpl {
// This superclass is used both by kv iterators *and* by the ObjectMap
// omap iterator. The class hiearchies are unfortunatley tied together
// by the legacy DBOjectMap implementation :(.
class SimplestIteratorImpl {
public:
virtual int seek_to_first() = 0;
virtual int upper_bound(const std::string &after) = 0;
Expand All @@ -190,9 +214,29 @@ class KeyValueDB {
virtual std::string key() = 0;
virtual bufferlist value() = 0;
virtual int status() = 0;
virtual ~GenericIteratorImpl() {}
virtual ~SimplestIteratorImpl() {}
};

class IteratorImpl : public SimplestIteratorImpl {
public:
virtual ~IteratorImpl() {}
virtual int seek_to_last() = 0;
virtual int prev(bool validate=true) = 0;
virtual std::pair<std::string, std::string> raw_key() = 0;
virtual bufferptr value_as_ptr() {
bufferlist bl = value();
if (bl.length() == 1) {
return *bl.buffers().begin();
} else if (bl.length() == 0) {
return bufferptr();
} else {
ceph_abort();
}
}
};
typedef ceph::shared_ptr< IteratorImpl > Iterator;

// This is the low-level iterator implemented by the underlying KV store.
class WholeSpaceIteratorImpl {
public:
virtual int seek_to_first() = 0;
Expand Down Expand Up @@ -227,18 +271,20 @@ class KeyValueDB {
};
typedef ceph::shared_ptr< WholeSpaceIteratorImpl > WholeSpaceIterator;

class IteratorImpl : public GenericIteratorImpl {
private:
// This class filters a WholeSpaceIterator by a prefix.
class PrefixIteratorImpl : public IteratorImpl {
const std::string prefix;
WholeSpaceIterator generic_iter;
public:
IteratorImpl(const std::string &prefix, WholeSpaceIterator iter) :
PrefixIteratorImpl(const std::string &prefix, WholeSpaceIterator iter) :
prefix(prefix), generic_iter(iter) { }
~IteratorImpl() override { }
~PrefixIteratorImpl() override { }

int seek_to_first() override {
return generic_iter->seek_to_first(prefix);
}
int seek_to_last() {
int seek_to_last() override {
return generic_iter->seek_to_last(prefix);
}
int upper_bound(const std::string &after) override {
Expand All @@ -264,7 +310,7 @@ class KeyValueDB {
}
}

int prev(bool validate=true) {
int prev(bool validate=true) override {
if (validate) {
if (valid())
return generic_iter->prev();
Expand All @@ -276,28 +322,34 @@ class KeyValueDB {
std::string key() override {
return generic_iter->key();
}
std::pair<std::string, std::string> raw_key() {
std::pair<std::string, std::string> raw_key() override {
return generic_iter->raw_key();
}
bufferlist value() override {
return generic_iter->value();
}
bufferptr value_as_ptr() {
bufferptr value_as_ptr() override {
return generic_iter->value_as_ptr();
}
int status() override {
return generic_iter->status();
}
};
public:

typedef ceph::shared_ptr< IteratorImpl > Iterator;
virtual WholeSpaceIterator get_wholespace_iterator() = 0;
virtual Iterator get_iterator(const std::string &prefix) {
return std::make_shared<PrefixIteratorImpl>(
prefix,
get_wholespace_iterator());
}

WholeSpaceIterator get_iterator() {
return _get_iterator();
void add_column_family(const std::string& cf_name, void *handle) {
cf_handles.insert(std::make_pair(cf_name, handle));
}

Iterator get_iterator(const std::string &prefix) {
return std::make_shared<IteratorImpl>(prefix, get_iterator());
bool is_column_family(const std::string& prefix) {
return cf_handles.count(prefix);
}

virtual uint64_t get_estimated_size(std::map<std::string,uint64_t> &extra) = 0;
Expand Down Expand Up @@ -361,11 +413,12 @@ class KeyValueDB {
return nullptr;
}
protected:
/// List of matching prefixes and merge operators
/// List of matching prefixes/ColumnFamilies and merge operators
std::vector<std::pair<std::string,
std::shared_ptr<MergeOperator> > > merge_ops;

virtual WholeSpaceIterator _get_iterator() = 0;
/// column families in use, name->handle
std::unordered_map<std::string, void *> cf_handles;
};

#endif
5 changes: 2 additions & 3 deletions src/kv/KineticStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class KineticStore : public KeyValueDB {
return do_open(out, false);
}
/// Creates underlying db if missing and opens it
int create_and_open(ostream &out) {
int create_and_open(ostream &out) override {
return do_open(out, true);
}

Expand Down Expand Up @@ -149,8 +149,7 @@ class KineticStore : public KeyValueDB {
}


protected:
WholeSpaceIterator _get_iterator() {
WholeSpaceIterator get_wholespace_iterator() {
return std::make_shared<KineticWholeSpaceIteratorImpl>(kinetic_conn.get());
}
};
Expand Down
3 changes: 1 addition & 2 deletions src/kv/LevelDBStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ class LevelDBStore : public KeyValueDB {
}


protected:
WholeSpaceIterator _get_iterator() override {
WholeSpaceIterator get_wholespace_iterator() override {
return std::make_shared<LevelDBWholeSpaceIteratorImpl>(
db->NewIterator(leveldb::ReadOptions()));
}
Expand Down
4 changes: 1 addition & 3 deletions src/kv/MemDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,7 @@ class MemDB : public KeyValueDB
return 0;
}

protected:

WholeSpaceIterator _get_iterator() override {
WholeSpaceIterator get_wholespace_iterator() override {
return std::shared_ptr<KeyValueDB::WholeSpaceIteratorImpl>(
new MDBWholeSpaceIteratorImpl(&m_map, &m_lock, &iterator_seq_no, m_using_btree));
}
Expand Down