Files
scylladb/database.hh
Glauber Costa 7f96fc9509 db: read all keyspaces from directory structure
This patch includes a helper function that executes a function for each entry
in a directory. It is future based and can include in the future, future-based
code to asychronously read, for instance, an sstable.

At the moment, it only scan all keyspaces and make sure they appear in the
keyspaces hash.

Both the database and keyspace classes gain a populate<T> factory that returns a
populated database. At this point, the names found are just listed, but not really
stored anywhere.

Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
2015-01-13 10:41:13 +02:00

235 lines
6.3 KiB
C++

/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*/
#ifndef DATABASE_HH_
#define DATABASE_HH_
#include "core/sstring.hh"
#include "core/shared_ptr.hh"
#include "net/byteorder.hh"
#include "utils/UUID.hh"
#include "db_clock.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>
#include <experimental/optional>
#include "core/future.hh"
// FIXME: should be int8_t
using bytes = basic_sstring<char, uint32_t, 31>;
using bytes_opt = std::experimental::optional<bytes>;
sstring to_hex(const bytes& b);
sstring to_hex(const bytes_opt& b);
using object_opt = std::experimental::optional<boost::any>;
class marshal_exception : public std::exception {
sstring _why;
public:
marshal_exception() : _why("marshalling error") {}
marshal_exception(sstring why) : _why(sstring("marshaling error: ") + why) {}
virtual const char* why() const { return _why.c_str(); }
};
struct runtime_exception : public std::exception {
sstring _why;
public:
runtime_exception(sstring why) : _why(sstring("runtime error: ") + why) {}
virtual const char* why() const { return _why.c_str(); }
};
class abstract_type {
sstring _name;
public:
abstract_type(sstring name) : _name(name) {}
virtual ~abstract_type() {}
virtual void serialize(const boost::any& value, std::ostream& out) = 0;
virtual object_opt deserialize(std::istream& in) = 0;
virtual bool less(const bytes& v1, const bytes& v2) = 0;
object_opt deserialize(const bytes& v) {
// FIXME: optimize
std::istringstream iss(v);
return deserialize(iss);
}
virtual void validate(const bytes& v) {
// FIXME
}
virtual object_opt compose(const bytes& v) {
return deserialize(v);
}
bytes decompose(const boost::any& value) {
// FIXME: optimize
std::ostringstream oss;
serialize(value, oss);
auto s = oss.str();
return bytes(s.data(), s.size());
}
sstring name() const {
return _name;
}
protected:
template <typename T, typename Compare = std::less<T>>
bool default_less(const bytes& b1, const bytes& b2, Compare compare = Compare());
};
using data_type = shared_ptr<abstract_type>;
inline
size_t hash_value(const shared_ptr<abstract_type>& x) {
return std::hash<abstract_type*>()(x.get());
}
template <typename Type>
shared_ptr<abstract_type> data_type_for();
class key_compare {
shared_ptr<abstract_type> _type;
public:
key_compare(shared_ptr<abstract_type> type) : _type(type) {}
bool operator()(const bytes& v1, const bytes& v2) const {
return _type->less(v1, v2);
}
};
struct row;
struct paritition;
struct column_family;
struct row {
std::vector<bytes> cells;
};
struct partition {
explicit partition(column_family& cf);
row static_columns;
// row key within partition -> row
std::map<bytes, row, key_compare> rows;
};
// FIXME: add missing types
extern thread_local shared_ptr<abstract_type> int32_type;
extern thread_local shared_ptr<abstract_type> long_type;
extern thread_local shared_ptr<abstract_type> ascii_type;
extern thread_local shared_ptr<abstract_type> bytes_type;
extern thread_local shared_ptr<abstract_type> utf8_type;
extern thread_local shared_ptr<abstract_type> boolean_type;
extern thread_local shared_ptr<abstract_type> timeuuid_type;
extern thread_local shared_ptr<abstract_type> timestamp_type;
extern thread_local shared_ptr<abstract_type> uuid_type;
template <>
inline
shared_ptr<abstract_type> data_type_for<int32_t>() {
return int32_type;
}
template <>
inline
shared_ptr<abstract_type> data_type_for<int64_t>() {
return long_type;
}
template <>
inline
shared_ptr<abstract_type> data_type_for<sstring>() {
return utf8_type;
}
struct column_definition {
sstring name;
shared_ptr<abstract_type> type;
struct name_compare {
bool operator()(const column_definition& cd1, const column_definition& cd2) const {
return std::lexicographical_compare(
cd1.name.begin(), cd1.name.end(),
cd2.name.begin(), cd2.name.end(),
[] (char c1, char c2) { return uint8_t(c1) < uint8_t(c1); });
}
};
};
struct column_family {
column_family(shared_ptr<abstract_type> partition_key_type, shared_ptr<abstract_type> clustering_key_type);
// primary key = paritition key + clustering_key
shared_ptr<abstract_type> partition_key_type;
shared_ptr<abstract_type> clustering_key_type;
std::vector<column_definition> partition_key;
std::vector<column_definition> clustering_key;
std::vector<column_definition> column_defs; // sorted by name
partition& find_or_create_partition(const bytes& key);
row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
partition* find_partition(const bytes& key);
row* find_row(const bytes& partition_key, const bytes& clustering_key);
// partition key -> partition
std::map<bytes, partition, key_compare> partitions;
};
class keyspace {
public:
std::unordered_map<sstring, column_family> column_families;
static future<keyspace> populate(sstring datadir);
};
class database {
public:
std::unordered_map<sstring, keyspace> keyspaces;
static future<database> populate(sstring datadir);
};
namespace std {
template <>
struct hash<shared_ptr<abstract_type>> : boost::hash<shared_ptr<abstract_type>> {
};
}
inline
bytes
to_bytes(const char* x) {
return bytes(reinterpret_cast<const char*>(x), std::strlen(x));
}
inline
bytes
to_bytes(const std::string& x) {
return bytes(reinterpret_cast<const char*>(x.data()), x.size());
}
inline
bytes
to_bytes(const sstring& x) {
return bytes(reinterpret_cast<const char*>(x.c_str()), x.size());
}
inline
bytes
to_bytes(const utils::UUID& uuid) {
struct {
uint64_t msb;
uint64_t lsb;
} tmp = { net::hton(uint64_t(uuid.get_most_significant_bits())),
net::hton(uint64_t(uuid.get_least_significant_bits())) };
return bytes(reinterpret_cast<char*>(&tmp), 16);
}
// This follows java.util.Comparator
// FIXME: Choose a better place than database.hh
template <typename T>
struct comparator {
virtual ~comparator() {}
virtual bool operator()(const T& v1, const T& v2) const = 0;
};
#endif /* DATABASE_HH_ */