Files
scylladb/gms/feature_service.cc
Piotr Sarna dd085b146a gms: add comments for deprecated features
Features which are propagated to other nodes via gossip,
but assumed they are supported in the code, are now marked
with comments.
2020-09-14 12:59:19 +02:00

278 lines
11 KiB
C++

/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 ScyllaDB
*/
#include <any>
#include <seastar/core/sstring.hh>
#include <seastar/core/seastar.hh>
#include <seastar/core/smp.hh>
#include "log.hh"
#include "db/config.hh"
#include "gms/feature.hh"
#include "gms/feature_service.hh"
namespace gms {
// Deprecated features - sent to other nodes via gossip, but assumed true in the code
constexpr std::string_view features::RANGE_TOMBSTONES = "RANGE_TOMBSTONES";
constexpr std::string_view features::LARGE_PARTITIONS = "LARGE_PARTITIONS";
constexpr std::string_view features::MATERIALIZED_VIEWS = "MATERIALIZED_VIEWS";
constexpr std::string_view features::COUNTERS = "COUNTERS";
constexpr std::string_view features::INDEXES = "INDEXES";
constexpr std::string_view features::DIGEST_MULTIPARTITION_READ = "DIGEST_MULTIPARTITION_READ";
constexpr std::string_view features::CORRECT_COUNTER_ORDER = "CORRECT_COUNTER_ORDER";
constexpr std::string_view features::SCHEMA_TABLES_V3 = "SCHEMA_TABLES_V3";
constexpr std::string_view features::CORRECT_NON_COMPOUND_RANGE_TOMBSTONES = "CORRECT_NON_COMPOUND_RANGE_TOMBSTONES";
constexpr std::string_view features::WRITE_FAILURE_REPLY = "WRITE_FAILURE_REPLY";
constexpr std::string_view features::XXHASH = "XXHASH";
constexpr std::string_view features::ROLES = "ROLES";
constexpr std::string_view features::LA_SSTABLE = "LA_SSTABLE_FORMAT";
constexpr std::string_view features::STREAM_WITH_RPC_STREAM = "STREAM_WITH_RPC_STREAM";
// Up-to-date features
constexpr std::string_view features::UDF = "UDF";
constexpr std::string_view features::MC_SSTABLE = "MC_SSTABLE_FORMAT";
constexpr std::string_view features::MD_SSTABLE = "MD_SSTABLE_FORMAT";
constexpr std::string_view features::ROW_LEVEL_REPAIR = "ROW_LEVEL_REPAIR";
constexpr std::string_view features::TRUNCATION_TABLE = "TRUNCATION_TABLE";
constexpr std::string_view features::CORRECT_STATIC_COMPACT_IN_MC = "CORRECT_STATIC_COMPACT_IN_MC";
constexpr std::string_view features::UNBOUNDED_RANGE_TOMBSTONES = "UNBOUNDED_RANGE_TOMBSTONES";
constexpr std::string_view features::VIEW_VIRTUAL_COLUMNS = "VIEW_VIRTUAL_COLUMNS";
constexpr std::string_view features::DIGEST_INSENSITIVE_TO_EXPIRY = "DIGEST_INSENSITIVE_TO_EXPIRY";
constexpr std::string_view features::COMPUTED_COLUMNS = "COMPUTED_COLUMNS";
constexpr std::string_view features::CDC = "CDC";
constexpr std::string_view features::NONFROZEN_UDTS = "NONFROZEN_UDTS";
constexpr std::string_view features::HINTED_HANDOFF_SEPARATE_CONNECTION = "HINTED_HANDOFF_SEPARATE_CONNECTION";
constexpr std::string_view features::LWT = "LWT";
constexpr std::string_view features::PER_TABLE_PARTITIONERS = "PER_TABLE_PARTITIONERS";
constexpr std::string_view features::PER_TABLE_CACHING = "PER_TABLE_CACHING";
constexpr std::string_view features::DIGEST_FOR_NULL_VALUES = "DIGEST_FOR_NULL_VALUES";
static logging::logger logger("features");
feature_config::feature_config() {
}
feature_service::feature_service(feature_config cfg) : _config(cfg)
, _udf_feature(*this, features::UDF)
, _mc_sstable_feature(*this, features::MC_SSTABLE)
, _md_sstable_feature(*this, features::MD_SSTABLE)
, _row_level_repair_feature(*this, features::ROW_LEVEL_REPAIR)
, _truncation_table(*this, features::TRUNCATION_TABLE)
, _correct_static_compact_in_mc(*this, features::CORRECT_STATIC_COMPACT_IN_MC)
, _unbounded_range_tombstones_feature(*this, features::UNBOUNDED_RANGE_TOMBSTONES)
, _view_virtual_columns(*this, features::VIEW_VIRTUAL_COLUMNS)
, _digest_insensitive_to_expiry(*this, features::DIGEST_INSENSITIVE_TO_EXPIRY)
, _computed_columns(*this, features::COMPUTED_COLUMNS)
, _cdc_feature(*this, features::CDC)
, _nonfrozen_udts(*this, features::NONFROZEN_UDTS)
, _hinted_handoff_separate_connection(*this, features::HINTED_HANDOFF_SEPARATE_CONNECTION)
, _lwt_feature(*this, features::LWT)
, _per_table_partitioners_feature(*this, features::PER_TABLE_PARTITIONERS)
, _per_table_caching_feature(*this, features::PER_TABLE_CACHING)
, _digest_for_null_values_feature(*this, features::DIGEST_FOR_NULL_VALUES)
{}
feature_config feature_config_from_db_config(db::config& cfg, std::set<sstring> disabled) {
feature_config fcfg;
fcfg._masked_features.insert(sstring(gms::features::UNBOUNDED_RANGE_TOMBSTONES));
fcfg._disabled_features = std::move(disabled);
if (!cfg.enable_sstables_mc_format()) {
if (cfg.enable_sstables_md_format()) {
throw std::runtime_error(
"You must use both enable_sstables_mc_format and enable_sstables_md_format "
"to enable SSTables md format support");
}
fcfg._disabled_features.insert(sstring(gms::features::MC_SSTABLE));
}
if (!cfg.enable_sstables_md_format()) {
fcfg._disabled_features.insert(sstring(gms::features::MD_SSTABLE));
}
if (!cfg.enable_user_defined_functions()) {
fcfg._disabled_features.insert(sstring(gms::features::UDF));
} else {
if (!cfg.check_experimental(db::experimental_features_t::UDF)) {
throw std::runtime_error(
"You must use both enable_user_defined_functions and experimental_features:udf "
"to enable user-defined functions");
}
}
if (!cfg.check_experimental(db::experimental_features_t::CDC)) {
fcfg._disabled_features.insert(sstring(gms::features::CDC));
}
return fcfg;
}
future<> feature_service::stop() {
return make_ready_future<>();
}
void feature_service::register_feature(feature& f) {
auto i = _registered_features.emplace(f.name(), f);
assert(i.second);
}
void feature_service::unregister_feature(feature& f) {
_registered_features.erase(f.name());
}
void feature_service::enable(const sstring& name) {
if (auto it = _registered_features.find(name); it != _registered_features.end()) {
auto&& f = it->second;
f.get().enable();
}
}
void feature_service::support(const std::string_view& name) {
_config._masked_features.erase(sstring(name));
}
std::set<std::string_view> feature_service::known_feature_set() {
// Add features known by this local node. When a new feature is
// introduced in scylla, update it here, e.g.,
// return sstring("FEATURE1,FEATURE2")
std::set<std::string_view> features = {
// Deprecated features - sent to other nodes via gossip, but assumed true in the code
gms::features::RANGE_TOMBSTONES,
gms::features::LARGE_PARTITIONS,
gms::features::COUNTERS,
gms::features::DIGEST_MULTIPARTITION_READ,
gms::features::CORRECT_COUNTER_ORDER,
gms::features::SCHEMA_TABLES_V3,
gms::features::CORRECT_NON_COMPOUND_RANGE_TOMBSTONES,
gms::features::WRITE_FAILURE_REPLY,
gms::features::XXHASH,
gms::features::ROLES,
gms::features::LA_SSTABLE,
gms::features::STREAM_WITH_RPC_STREAM,
gms::features::MATERIALIZED_VIEWS,
gms::features::INDEXES,
// Up-to-date features
gms::features::ROW_LEVEL_REPAIR,
gms::features::TRUNCATION_TABLE,
gms::features::CORRECT_STATIC_COMPACT_IN_MC,
gms::features::VIEW_VIRTUAL_COLUMNS,
gms::features::DIGEST_INSENSITIVE_TO_EXPIRY,
gms::features::COMPUTED_COLUMNS,
gms::features::NONFROZEN_UDTS,
gms::features::UNBOUNDED_RANGE_TOMBSTONES,
gms::features::HINTED_HANDOFF_SEPARATE_CONNECTION,
gms::features::PER_TABLE_PARTITIONERS,
gms::features::PER_TABLE_CACHING,
gms::features::LWT,
gms::features::MC_SSTABLE,
gms::features::MD_SSTABLE,
gms::features::UDF,
gms::features::CDC,
gms::features::DIGEST_FOR_NULL_VALUES,
};
for (const sstring& s : _config._disabled_features) {
features.erase(s);
}
return features;
}
std::set<std::string_view> feature_service::supported_feature_set() {
auto features = known_feature_set();
for (const sstring& s : _config._masked_features) {
features.erase(s);
}
return features;
}
feature::feature(feature_service& service, std::string_view name, bool enabled)
: _service(&service)
, _name(name)
, _enabled(enabled) {
_service->register_feature(*this);
}
feature::~feature() {
if (_service) {
_service->unregister_feature(*this);
}
}
feature& feature::operator=(feature&& other) {
_service->unregister_feature(*this);
_service = std::exchange(other._service, nullptr);
_name = other._name;
_enabled = other._enabled;
_s = std::move(other._s);
_service->register_feature(*this);
return *this;
}
void feature::enable() {
if (!_enabled) {
if (this_shard_id() == 0) {
logger.info("Feature {} is enabled", name());
}
_enabled = true;
_s();
}
}
db::schema_features feature_service::cluster_schema_features() const {
db::schema_features f;
f.set_if<db::schema_feature::VIEW_VIRTUAL_COLUMNS>(bool(_view_virtual_columns));
f.set_if<db::schema_feature::DIGEST_INSENSITIVE_TO_EXPIRY>(bool(_digest_insensitive_to_expiry));
f.set_if<db::schema_feature::COMPUTED_COLUMNS>(bool(_computed_columns));
f.set_if<db::schema_feature::CDC_OPTIONS>(bool(_cdc_feature));
f.set_if<db::schema_feature::PER_TABLE_PARTITIONERS>(bool(_per_table_partitioners_feature));
return f;
}
void feature_service::enable(const std::set<std::string_view>& list) {
for (gms::feature& f : {
std::ref(_udf_feature),
std::ref(_mc_sstable_feature),
std::ref(_md_sstable_feature),
std::ref(_row_level_repair_feature),
std::ref(_truncation_table),
std::ref(_correct_static_compact_in_mc),
std::ref(_unbounded_range_tombstones_feature),
std::ref(_view_virtual_columns),
std::ref(_digest_insensitive_to_expiry),
std::ref(_computed_columns),
std::ref(_cdc_feature),
std::ref(_nonfrozen_udts),
std::ref(_hinted_handoff_separate_connection),
std::ref(_lwt_feature),
std::ref(_per_table_partitioners_feature),
std::ref(_per_table_caching_feature),
std::ref(_digest_for_null_values_feature),
})
{
if (list.contains(f.name())) {
f.enable();
}
}
}
} // namespace gms