/* * 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 "gc_clock.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include "types.hh" #include "tuple.hh" #include "core/future.hh" #include "cql3/column_specification.hh" struct row; struct paritition; struct column_family; struct row { std::vector cells; }; struct partition { explicit partition(column_family& cf); row static_columns; // row key within partition -> row std::map rows; }; using column_id = uint32_t; class column_definition final { private: bytes _name; public: enum column_kind { PARTITION, CLUSTERING, REGULAR, STATIC }; column_definition(bytes name, data_type type, column_id id, column_kind kind); data_type type; column_id id; // unique within (kind, schema instance) column_kind kind; ::shared_ptr column_specification; bool is_static() const { return kind == column_kind::STATIC; } bool is_partition_key() const { return kind == column_kind::PARTITION; } const sstring& name_as_text() const; const bytes& name() const; }; struct thrift_schema { shared_ptr partition_key_type; }; /* * Keep this effectively immutable. */ class schema final { private: std::unordered_map _columns_by_name; std::map _regular_columns_by_name; public: struct column { bytes name; data_type type; struct name_compare { shared_ptr type; name_compare(shared_ptr type) : type(type) {} bool operator()(const column& cd1, const column& cd2) const { return type->less(cd1.name, cd2.name); } }; }; private: void build_columns(std::vector columns, column_definition::column_kind kind, std::vector& dst); ::shared_ptr make_column_specification(column_definition& def); public: gc_clock::duration default_time_to_live = gc_clock::duration::zero(); const sstring ks_name; const sstring cf_name; std::vector partition_key; std::vector clustering_key; std::vector regular_columns; // sorted by name shared_ptr> partition_key_type; shared_ptr> clustering_key_type; shared_ptr clustering_key_prefix_type; data_type regular_column_name_type; thrift_schema thrift; public: schema(sstring ks_name, sstring cf_name, std::vector partition_key, std::vector clustering_key, std::vector regular_columns, shared_ptr regular_column_name_type); bool is_dense() const { return false; } bool is_counter() const { return false; } column_definition* get_column_definition(const bytes& name); auto regular_begin() { return regular_columns.begin(); } auto regular_end() { return regular_columns.end(); } auto regular_lower_bound(const bytes& name) { // TODO: use regular_columns and a version of std::lower_bound() with heterogeneous comparator auto i = _regular_columns_by_name.lower_bound(name); if (i == _regular_columns_by_name.end()) { return regular_end(); } else { return regular_columns.begin() + i->second->id; } } auto regular_upper_bound(const bytes& name) { // TODO: use regular_columns and a version of std::upper_bound() with heterogeneous comparator auto i = _regular_columns_by_name.upper_bound(name); if (i == _regular_columns_by_name.end()) { return regular_end(); } else { return regular_columns.begin() + i->second->id; } } column_id get_regular_columns_count() { return regular_columns.size(); } data_type column_name_type(column_definition& def) { return def.kind == column_definition::REGULAR ? regular_column_name_type : utf8_type; } }; using schema_ptr = lw_shared_ptr; struct column_family { column_family(schema_ptr schema); 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); schema_ptr _schema; // partition key -> partition std::map partitions; }; class keyspace { public: std::unordered_map column_families; static future populate(sstring datadir); schema_ptr find_schema(sstring cf_name); }; class database { public: std::unordered_map keyspaces; static future populate(sstring datadir); keyspace* find_keyspace(sstring name); }; #endif /* DATABASE_HH_ */