mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-26 03:20:37 +00:00
Merge "Thrift and keyspaces"
From Paweł: "These series contains some improvements in the way thrift keyspace-related operations are handled (checks whether set_keyspace was given an existing keyspace, more informative error message when adding keyspace with invalid/unsupported placement strategy) and initial implementation of describe_keyspace and describe_keyspaces."
This commit is contained in:
@@ -55,7 +55,7 @@ public:
|
||||
|
||||
compound_type(compound_type&&) = default;
|
||||
|
||||
auto const& types() {
|
||||
auto const& types() const {
|
||||
return _types;
|
||||
}
|
||||
|
||||
|
||||
@@ -531,7 +531,8 @@ void database::drop_keyspace(const sstring& name) {
|
||||
}
|
||||
|
||||
void database::add_column_family(const utils::UUID& uuid, column_family&& cf) {
|
||||
if (_keyspaces.count(cf.schema()->ks_name()) == 0) {
|
||||
auto ks = _keyspaces.find(cf.schema()->ks_name());
|
||||
if (ks == _keyspaces.end()) {
|
||||
throw std::invalid_argument("Keyspace " + cf.schema()->ks_name() + " not defined");
|
||||
}
|
||||
if (_column_families.count(uuid) != 0) {
|
||||
@@ -541,6 +542,7 @@ void database::add_column_family(const utils::UUID& uuid, column_family&& cf) {
|
||||
if (_ks_cf_to_uuid.count(kscf) != 0) {
|
||||
throw std::invalid_argument("Column family " + cf.schema()->cf_name() + " exists");
|
||||
}
|
||||
ks->second.add_column_family(cf.schema());
|
||||
_column_families.emplace(uuid, std::move(cf));
|
||||
_ks_cf_to_uuid.emplace(std::move(kscf), uuid);
|
||||
}
|
||||
|
||||
@@ -187,6 +187,9 @@ public:
|
||||
const lw_shared_ptr<user_types_metadata>& user_types() const {
|
||||
return _user_types;
|
||||
}
|
||||
void add_column_family(const schema_ptr& s) {
|
||||
_cf_meta_data.emplace(s->cf_name(), s);
|
||||
}
|
||||
};
|
||||
|
||||
class keyspace {
|
||||
@@ -213,6 +216,9 @@ public:
|
||||
locator::abstract_replication_strategy& get_replication_strategy();
|
||||
column_family::config make_column_family_config(const schema& s) const;
|
||||
future<> make_directory_for_column_family(const sstring& name, utils::UUID uuid);
|
||||
void add_column_family(const schema_ptr& s) {
|
||||
_metadata->add_column_family(s);
|
||||
}
|
||||
private:
|
||||
sstring column_family_directory(const sstring& name, utils::UUID uuid) const;
|
||||
};
|
||||
@@ -271,6 +277,7 @@ public:
|
||||
bool has_keyspace(const sstring& name) const;
|
||||
void update_keyspace(const sstring& name);
|
||||
void drop_keyspace(const sstring& name);
|
||||
const auto& keyspaces() const { return _keyspaces; }
|
||||
column_family& find_column_family(const sstring& ks, const sstring& name) throw (no_such_column_family);
|
||||
const column_family& find_column_family(const sstring& ks, const sstring& name) const throw (no_such_column_family);
|
||||
column_family& find_column_family(const utils::UUID&) throw (no_such_column_family);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "utils/UUID_gen.hh"
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <boost/move/iterator.hpp>
|
||||
#include "utils/class_registrator.hh"
|
||||
|
||||
using namespace ::apache::thrift;
|
||||
using namespace ::apache::thrift::protocol;
|
||||
@@ -61,6 +62,8 @@ public:
|
||||
// It's an expected exception, so assume the message
|
||||
// is fine. Also, we don't want to change its type.
|
||||
throw;
|
||||
} catch (no_such_class& nc) {
|
||||
throw make_exception<InvalidRequestException>("unable to find class '%s'", nc.what());
|
||||
} catch (std::exception& e) {
|
||||
// Unexpected exception, wrap it
|
||||
throw ::apache::thrift::TException(std::string("Internal server error: ") + e.what());
|
||||
@@ -111,12 +114,12 @@ public:
|
||||
}
|
||||
|
||||
void set_keyspace(tcxx::function<void()> cob, tcxx::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, const std::string& keyspace) {
|
||||
try {
|
||||
if (!_db.local().has_keyspace(keyspace)) {
|
||||
complete_with_exception<InvalidRequestException>(std::move(exn_cob),
|
||||
"keyspace %s does not exist", keyspace);
|
||||
} else {
|
||||
_ks_name = keyspace;
|
||||
cob();
|
||||
} catch (std::out_of_range& e) {
|
||||
return complete_with_exception<InvalidRequestException>(std::move(exn_cob),
|
||||
"keyspace %s does not exist", keyspace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,9 +352,11 @@ public:
|
||||
}
|
||||
|
||||
void describe_keyspaces(tcxx::function<void(std::vector<KsDef> const& _return)> cob, tcxx::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob) {
|
||||
std::vector<KsDef> _return;
|
||||
// FIXME: implement
|
||||
return pass_unimplemented(exn_cob);
|
||||
std::vector<KsDef> ret;
|
||||
for (auto&& ks : _db.local().keyspaces()) {
|
||||
ret.emplace_back(get_keyspace_definition(ks.second));
|
||||
}
|
||||
cob(ret);
|
||||
}
|
||||
|
||||
void describe_cluster_name(tcxx::function<void(std::string const& _return)> cob) {
|
||||
@@ -397,9 +402,15 @@ public:
|
||||
}
|
||||
|
||||
void describe_keyspace(tcxx::function<void(KsDef const& _return)> cob, tcxx::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, const std::string& keyspace) {
|
||||
KsDef _return;
|
||||
// FIXME: implement
|
||||
return pass_unimplemented(exn_cob);
|
||||
try {
|
||||
auto& ks = _db.local().find_keyspace(keyspace);
|
||||
KsDef ret = get_keyspace_definition(ks);
|
||||
cob(ret);
|
||||
}
|
||||
catch (no_such_keyspace& nsk) {
|
||||
complete_with_exception<InvalidRequestException>(std::move(exn_cob),
|
||||
"keyspace %s does not exist", keyspace);
|
||||
}
|
||||
}
|
||||
|
||||
void describe_splits(tcxx::function<void(std::vector<std::string> const& _return)> cob, tcxx::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, const std::string& cfName, const std::string& start_token, const std::string& end_token, const int32_t keys_per_split) {
|
||||
@@ -556,6 +567,80 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static sstring class_from_data_type(const data_type& dt) {
|
||||
static const std::unordered_map<sstring, sstring> types = {
|
||||
{ "boolean", "BooleanType" },
|
||||
{ "bytes", "BytesType" },
|
||||
{ "double", "DoubleType" },
|
||||
{ "int32", "Int32Type" },
|
||||
{ "long", "LongType" },
|
||||
{ "timestamp", "DateType" },
|
||||
{ "timeuuid", "TimeUUIDType" },
|
||||
{ "utf8", "UTF8Type" },
|
||||
{ "uuid", "UUIDType" },
|
||||
// FIXME: missing types
|
||||
};
|
||||
auto it = types.find(dt->name());
|
||||
if (it == types.end()) {
|
||||
return sstring("<unknown> ") + dt->name();
|
||||
}
|
||||
return sstring("org.apache.cassandra.db.marshal.") + it->second;
|
||||
}
|
||||
static sstring class_from_compound_type(const compound_type<allow_prefixes::no>& ct) {
|
||||
if (ct.is_singular()) {
|
||||
return class_from_data_type(ct.types().front());
|
||||
}
|
||||
sstring type = "org.apache.cassandra.db.marshal.CompositeType(";
|
||||
for (auto& dt : ct.types()) {
|
||||
type += class_from_data_type(dt);
|
||||
if (&dt != &*ct.types().rbegin()) {
|
||||
type += ",";
|
||||
}
|
||||
}
|
||||
type += ")";
|
||||
return type;
|
||||
}
|
||||
static KsDef get_keyspace_definition(const keyspace& ks) {
|
||||
auto&& meta = ks.metadata();
|
||||
KsDef def;
|
||||
def.__set_name(meta->name());
|
||||
def.__set_strategy_class(meta->strategy_name());
|
||||
std::map<std::string, std::string> options(
|
||||
meta->strategy_options().begin(),
|
||||
meta->strategy_options().end());
|
||||
def.__set_strategy_options(options);
|
||||
std::vector<CfDef> cfs;
|
||||
for (auto&& cf : meta->cf_meta_data()) {
|
||||
// FIXME: skip cql3 column families
|
||||
auto&& s = cf.second;
|
||||
CfDef cf_def;
|
||||
cf_def.__set_keyspace(s->ks_name());
|
||||
cf_def.__set_name(s->cf_name());
|
||||
cf_def.__set_key_validation_class(class_from_compound_type(*s->partition_key_type()));
|
||||
if (s->clustering_key_size()) {
|
||||
cf_def.__set_comparator_type(class_from_compound_type(*s->clustering_key_type()));
|
||||
} else {
|
||||
cf_def.__set_comparator_type(class_from_data_type(s->regular_column_name_type()));
|
||||
}
|
||||
cf_def.__set_comment(s->comment());
|
||||
cf_def.__set_bloom_filter_fp_chance(s->bloom_filter_fp_chance());
|
||||
if (s->regular_columns_count()) {
|
||||
std::vector<ColumnDef> columns;
|
||||
for (auto&& c : s->regular_columns()) {
|
||||
ColumnDef c_def;
|
||||
c_def.__set_name(c.name_as_text());
|
||||
c_def.__set_validation_class(class_from_data_type(c.type));
|
||||
columns.emplace_back(std::move(c_def));
|
||||
}
|
||||
cf_def.__set_column_metadata(columns);
|
||||
}
|
||||
// FIXME: there are more fields that should be filled...
|
||||
cfs.emplace_back(std::move(cf_def));
|
||||
}
|
||||
def.__set_cf_defs(cfs);
|
||||
def.__set_durable_writes(meta->durable_writes());
|
||||
return std::move(def);
|
||||
}
|
||||
static column_family& lookup_column_family(database& db, const sstring& ks_name, const sstring& cf_name) {
|
||||
try {
|
||||
return db.find_column_family(ks_name, cf_name);
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class no_such_class : public std::runtime_error {
|
||||
public:
|
||||
using runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
// BaseType is a base type of a type hierarchy that this registry will hold
|
||||
// Args... are parameters for object's constructor
|
||||
template<typename BaseType, typename... Args>
|
||||
@@ -45,7 +50,11 @@ struct class_registrator {
|
||||
|
||||
template<typename BaseType, typename... Args>
|
||||
std::unique_ptr<BaseType> class_registry<BaseType, Args...>::create(const sstring& name, Args... args) {
|
||||
return _classes[name](args...);
|
||||
auto it = _classes.find(name);
|
||||
if (it == _classes.end()) {
|
||||
throw no_such_class(name);
|
||||
}
|
||||
return it->second(args...);
|
||||
}
|
||||
|
||||
template<typename BaseType, typename... Args>
|
||||
|
||||
Reference in New Issue
Block a user