*
*/
-#include <boost/type_traits.hpp>
-
+#include <filesystem>
#include "common/ceph_argparse.h"
#include "common/common_init.h"
#include "common/config.h"
// set set_mon_vals()
#define dout_subsys ceph_subsys_monc
+namespace fs = std::filesystem;
+
+using std::cerr;
+using std::cout;
using std::map;
+using std::less;
using std::list;
+using std::ostream;
using std::ostringstream;
using std::pair;
using std::string;
+using std::string_view;
+using std::vector;
-static const char *CEPH_CONF_FILE_DEFAULT = "$data_dir/config, /etc/ceph/$cluster.conf, $home/.ceph/$cluster.conf, $cluster.conf"
+using ceph::bufferlist;
+using ceph::decode;
+using ceph::encode;
+using ceph::Formatter;
+
+static const char *CEPH_CONF_FILE_DEFAULT = "$data_dir/config,/etc/ceph/$cluster.conf,$home/.ceph/$cluster.conf,$cluster.conf"
#if defined(__FreeBSD__)
- ", /usr/local/etc/ceph/$cluster.conf"
+ ",/usr/local/etc/ceph/$cluster.conf"
+#elif defined(_WIN32)
+ ",$programdata/ceph/$cluster.conf"
#endif
;
std::string& result)
{
list<string> ls;
- get_str_list(filename_list, ls);
+ get_str_list(filename_list, ";,", ls);
int ret = -ENOENT;
list<string>::iterator iter;
static int conf_stringify(const Option::value_t& v, string *out)
{
- if (boost::get<boost::blank>(&v)) {
+ if (v == Option::value_t{}) {
return -ENOENT;
}
*out = Option::to_str(v);
<< std::endl;
ceph_abort();
}
- schema.emplace(std::piecewise_construct,
- std::forward_as_tuple(i.name),
- std::forward_as_tuple(i));
+ schema.emplace(i.name, i);
}
// Define the debug_* options as well.
// members if present.
legacy_values = {
#define OPTION(name, type) \
- {std::string(STRINGIFY(name)), &ConfigValues::name},
+ {STRINGIFY(name), &ConfigValues::name},
#define SAFE_OPTION(name, type) OPTION(name, type)
-#include "common/legacy_config_opts.h"
+#include "options/legacy_config_opts.h"
#undef OPTION
#undef SAFE_OPTION
};
for (const auto &i : schema) {
const Option &opt = i.second;
if (opt.type == Option::TYPE_STR) {
- bool has_daemon_default = !boost::get<boost::blank>(&opt.daemon_value);
+ bool has_daemon_default = (opt.daemon_value != Option::value_t{});
Option::value_t default_val;
if (is_daemon && has_daemon_default) {
default_val = opt.daemon_value;
}
// We call pre_validate as a sanity check, but also to get any
// side effect (value modification) from the validator.
- std::string *def_str = boost::get<std::string>(&default_val);
+ auto* def_str = std::get_if<std::string>(&default_val);
std::string val = *def_str;
std::string err;
if (opt.pre_validate(&val, &err) != 0) {
}
}
-const Option *md_config_t::find_option(const string& name) const
+const Option *md_config_t::find_option(const std::string_view name) const
{
auto p = schema.find(name);
if (p != schema.end()) {
void md_config_t::set_val_default(ConfigValues& values,
const ConfigTracker& tracker,
- const string& name, const std::string& val)
+ const string_view name, const std::string& val)
{
const Option *o = find_option(name);
ceph_assert(o);
int md_config_t::set_mon_vals(CephContext *cct,
ConfigValues& values,
const ConfigTracker& tracker,
- const map<string,string>& kv,
+ const map<string,string,less<>>& kv,
config_callback config_cb)
{
ignored_mon_values.clear();
std::string err;
int r = _set_val(values, tracker, i.second, *o, CONF_MON, &err);
if (r < 0) {
- lderr(cct) << __func__ << " failed to set " << i.first << " = "
- << i.second << ": " << err << dendl;
+ ldout(cct, 4) << __func__ << " failed to set " << i.first << " = "
+ << i.second << ": " << err << dendl;
ignored_mon_values.emplace(i);
} else if (r == ConfigValues::SET_NO_CHANGE ||
r == ConfigValues::SET_NO_EFFECT) {
<< " cleared (was " << Option::to_str(config->second) << ")"
<< dendl;
values.rm_val(name, CONF_MON);
+ // if this is a debug option, it needs to propagate to teh subsys;
+ // this isn't covered by update_legacy_vals() below. similarly,
+ // we want to trigger a config notification for these items.
+ const Option *o = find_option(name);
+ _refresh(values, *o);
});
values_bl.clear();
update_legacy_vals(values);
std::ostream *warnings,
int flags)
{
-
if (safe_to_start_threads)
return -ENOSYS;
- if (!values.cluster.size() && !conf_files_str) {
- /*
- * set the cluster name to 'ceph' when neither cluster name nor
- * configuration file are specified.
- */
- values.cluster = "ceph";
- }
-
- if (!conf_files_str) {
- const char *c = getenv("CEPH_CONF");
- if (c) {
- conf_files_str = c;
- }
- else {
- if (flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)
- return 0;
- conf_files_str = CEPH_CONF_FILE_DEFAULT;
- }
- }
-
- std::list<std::string> conf_files;
- get_str_list(conf_files_str, conf_files);
- auto p = conf_files.begin();
- while (p != conf_files.end()) {
- string &s = *p;
- if (s.find("$data_dir") != string::npos &&
- data_dir_option.empty()) {
- // useless $data_dir item, skip
- p = conf_files.erase(p);
- } else {
- early_expand_meta(values, s, warnings);
- ++p;
- }
+ if (values.cluster.empty() && !conf_files_str) {
+ values.cluster = get_cluster_name(nullptr);
}
-
// open new conf
- list<string>::const_iterator c;
- for (c = conf_files.begin(); c != conf_files.end(); ++c) {
- cf.clear();
- string fn = *c;
-
- int ret = cf.parse_file(fn.c_str(), &parse_errors, warnings);
- if (ret == 0)
+ for (auto& fn : get_conffile_paths(values, conf_files_str, warnings, flags)) {
+ bufferlist bl;
+ std::string error;
+ if (bl.read_file(fn.c_str(), &error)) {
+ parse_error = error;
+ continue;
+ }
+ ostringstream oss;
+ int ret = parse_buffer(values, tracker, bl.c_str(), bl.length(), &oss);
+ if (ret == 0) {
+ parse_error.clear();
+ conf_path = fn;
break;
- else if (ret != -ENOENT)
+ }
+ parse_error = oss.str();
+ if (ret != -ENOENT) {
return ret;
+ }
}
// it must have been all ENOENTs, that's the only way we got here
- if (c == conf_files.end())
+ if (conf_path.empty()) {
return -ENOENT;
-
- if (values.cluster.size() == 0) {
- /*
- * If cluster name is not set yet, use the prefix of the
- * basename of configuration file as cluster name.
- */
- auto start = c->rfind('/') + 1;
- auto end = c->find(".conf", start);
- if (end == c->npos) {
- /*
- * If the configuration file does not follow $cluster.conf
- * convention, we do the last try and assign the cluster to
- * 'ceph'.
- */
- values.cluster = "ceph";
- } else {
- values.cluster = c->substr(start, end - start);
- }
}
+ if (values.cluster.empty()) {
+ values.cluster = get_cluster_name(conf_path.c_str());
+ }
+ update_legacy_vals(values);
+ return 0;
+}
- std::vector <std::string> my_sections;
- _get_my_sections(values, my_sections);
+int
+md_config_t::parse_buffer(ConfigValues& values,
+ const ConfigTracker& tracker,
+ const char* buf, size_t len,
+ std::ostream* warnings)
+{
+ if (!cf.parse_buffer(string_view{buf, len}, warnings)) {
+ return -EINVAL;
+ }
+ const auto my_sections = get_my_sections(values);
for (const auto &i : schema) {
const auto &opt = i.second;
std::string val;
- int ret = _get_val_from_conf_file(my_sections, opt.name, val);
- if (ret == 0) {
- std::string error_message;
- int r = _set_val(values, tracker, val, opt, CONF_FILE, &error_message);
- if (warnings != nullptr && (r < 0 || !error_message.empty())) {
- *warnings << "parse error setting '" << opt.name << "' to '" << val
- << "'";
+ if (_get_val_from_conf_file(my_sections, opt.name, val)) {
+ continue;
+ }
+ std::string error_message;
+ if (_set_val(values, tracker, val, opt, CONF_FILE, &error_message) < 0) {
+ if (warnings != nullptr) {
+ *warnings << "parse error setting " << std::quoted(opt.name)
+ << " to " << std::quoted(val);
if (!error_message.empty()) {
*warnings << " (" << error_message << ")";
}
- *warnings << std::endl;
+ *warnings << '\n';
}
}
}
+ cf.check_old_style_section_names({"mds", "mon", "osd"}, cerr);
+ return 0;
+}
- // Warn about section names that look like old-style section names
- std::deque < std::string > old_style_section_names;
- for (ConfFile::const_section_iter_t s = cf.sections_begin();
- s != cf.sections_end(); ++s) {
- const string &str(s->first);
- if (((str.find("mds") == 0) || (str.find("mon") == 0) ||
- (str.find("osd") == 0)) && (str.size() > 3) && (str[3] != '.')) {
- old_style_section_names.push_back(str);
+std::list<std::string>
+md_config_t::get_conffile_paths(const ConfigValues& values,
+ const char *conf_files_str,
+ std::ostream *warnings,
+ int flags) const
+{
+ if (!conf_files_str) {
+ const char *c = getenv("CEPH_CONF");
+ if (c) {
+ conf_files_str = c;
+ } else {
+ if (flags & CINIT_FLAG_NO_DEFAULT_CONFIG_FILE)
+ return {};
+ conf_files_str = CEPH_CONF_FILE_DEFAULT;
}
}
- if (!old_style_section_names.empty()) {
- ostringstream oss;
- cerr << "ERROR! old-style section name(s) found: ";
- string sep;
- for (std::deque < std::string >::const_iterator os = old_style_section_names.begin();
- os != old_style_section_names.end(); ++os) {
- cerr << sep << *os;
- sep = ", ";
+
+ std::list<std::string> paths;
+ get_str_list(conf_files_str, ";,", paths);
+ for (auto i = paths.begin(); i != paths.end(); ) {
+ string& path = *i;
+ if (path.find("$data_dir") != path.npos &&
+ data_dir_option.empty()) {
+ // useless $data_dir item, skip
+ i = paths.erase(i);
+ } else {
+ early_expand_meta(values, path, warnings);
+ ++i;
}
- cerr << ". Please use the new style section names that include a period.";
}
+ return paths;
+}
- update_legacy_vals(values);
-
- return 0;
+std::string md_config_t::get_cluster_name(const char* conffile)
+{
+ if (conffile) {
+ // If cluster name is not set yet, use the prefix of the
+ // basename of configuration file as cluster name.
+ if (fs::path path{conffile}; path.extension() == ".conf") {
+ return path.stem().string();
+ } else {
+ // If the configuration file does not follow $cluster.conf
+ // convention, we do the last try and assign the cluster to
+ // 'ceph'.
+ return "ceph";
+ }
+ } else {
+ // set the cluster name to 'ceph' when configuration file is not specified.
+ return "ceph";
+ }
}
void md_config_t::parse_env(unsigned entity_type,
if (!args_var) {
args_var = "CEPH_ARGS";
}
- if (getenv("CEPH_KEYRING")) {
- _set_val(values, tracker, getenv("CEPH_KEYRING"), *find_option("keyring"),
- CONF_ENV, nullptr);
+ if (auto s = getenv("CEPH_KEYRING"); s) {
+ string err;
+ _set_val(values, tracker, s, *find_option("keyring"), CONF_ENV, &err);
}
- if (const char *dir = getenv("CEPH_LIB")) {
+ if (auto dir = getenv("CEPH_LIB"); dir) {
for (auto name : { "erasure_code_dir", "plugin_dir", "osd_class_dir" }) {
std::string err;
const Option *o = find_option(name);
_set_val(values, tracker, dir, *o, CONF_ENV, &err);
}
}
- const char *pod_req = getenv("POD_MEMORY_REQUEST");
- if (pod_req) {
- uint64_t v = atoll(pod_req);
+
+ // Apply pod memory limits:
+ //
+ // There are two types of resource requests: `limits` and `requests`.
+ //
+ // - Requests: Used by the K8s scheduler to determine on which nodes to
+ // schedule the pods. This helps spread the pods to different nodes. This
+ // value should be conservative in order to make sure all the pods are
+ // schedulable. This corresponds to POD_MEMORY_REQUEST (set by the Rook
+ // CRD) and is the target memory utilization we try to maintain for daemons
+ // that respect it.
+ //
+ // If POD_MEMORY_REQUEST is present, we use it as the target.
+ //
+ // - Limits: At runtime, the container runtime (and Linux) will use the
+ // limits to see if the pod is using too many resources. In that case, the
+ // pod will be killed/restarted automatically if the pod goes over the limit.
+ // This should be higher than what is specified for requests (potentially
+ // much higher). This corresponds to the cgroup memory limit that will
+ // trigger the Linux OOM killer.
+ //
+ // If POD_MEMORY_LIMIT is present, we use it as the /default/ value for
+ // the target, which means it will only apply if the *_memory_target option
+ // isn't set via some other path (e.g., POD_MEMORY_REQUEST, or the cluster
+ // config, or whatever.)
+ //
+ // Here are the documented best practices:
+ // https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/#motivation-for-cpu-requests-and-limits
+ //
+ // When the operator creates the CephCluster CR, it will need to generate the
+ // desired requests and limits. As long as we are conservative in our choice
+ // for requests and generous with the limits we should be in a good place to
+ // get started.
+ //
+ // The support in Rook is already there for applying the limits as seen in
+ // these links.
+ //
+ // Rook docs on the resource requests and limits:
+ // https://rook.io/docs/rook/v1.0/ceph-cluster-crd.html#cluster-wide-resources-configuration-settings
+ // Example CR settings:
+ // https://github.com/rook/rook/blob/6d2ef936698593036185aabcb00d1d74f9c7bfc1/cluster/examples/kubernetes/ceph/cluster.yaml#L90
+ //
+ uint64_t pod_limit = 0, pod_request = 0;
+ if (auto pod_lim = getenv("POD_MEMORY_LIMIT"); pod_lim) {
+ string err;
+ uint64_t v = atoll(pod_lim);
if (v) {
switch (entity_type) {
case CEPH_ENTITY_TYPE_OSD:
- _set_val(values, tracker, stringify(v),
- *find_option("osd_memory_target"),
- CONF_ENV, nullptr);
- break;
+ {
+ double cgroup_ratio = get_val<double>(
+ values, "osd_memory_target_cgroup_limit_ratio");
+ if (cgroup_ratio > 0.0) {
+ pod_limit = v * cgroup_ratio;
+ // set osd_memory_target *default* based on cgroup limit, so that
+ // it can be overridden by any explicit settings elsewhere.
+ set_val_default(values, tracker,
+ "osd_memory_target", stringify(pod_limit));
+ }
+ }
}
}
}
+ if (auto pod_req = getenv("POD_MEMORY_REQUEST"); pod_req) {
+ if (uint64_t v = atoll(pod_req); v) {
+ pod_request = v;
+ }
+ }
+ if (pod_request && pod_limit) {
+ // If both LIMIT and REQUEST are set, ensure that we use the
+ // min of request and limit*ratio. This is important
+ // because k8s set set LIMIT == REQUEST if only LIMIT is
+ // specified, and we want to apply the ratio in that case,
+ // even though REQUEST is present.
+ pod_request = std::min<uint64_t>(pod_request, pod_limit);
+ }
+ if (pod_request) {
+ string err;
+ switch (entity_type) {
+ case CEPH_ENTITY_TYPE_OSD:
+ _set_val(values, tracker, stringify(pod_request),
+ *find_option("osd_memory_target"),
+ CONF_ENV, &err);
+ break;
+ }
+ }
+
if (getenv(args_var)) {
vector<const char *> env_args;
env_to_vec(env_args, args_var);
else if (ceph_argparse_flag(args, i, "--no-mon-config", (char*)NULL)) {
values.no_mon_config = true;
}
- else if (ceph_argparse_flag(args, i, "--log-early", (char*)NULL)) {
- values.log_early = true;
- }
else if (ceph_argparse_flag(args, i, "--mon-config", (char*)NULL)) {
values.no_mon_config = false;
}
set_val_or_die(values, tracker, "daemonize", "false");
}
else if (ceph_argparse_flag(args, i, "-d", (char*)NULL)) {
+ set_val_or_die(values, tracker, "fuse_debug", "true");
set_val_or_die(values, tracker, "daemonize", "false");
set_val_or_die(values, tracker, "log_file", "");
set_val_or_die(values, tracker, "log_to_stderr", "true");
void md_config_t::set_val_or_die(ConfigValues& values,
const ConfigTracker& tracker,
- const std::string &key,
+ const std::string_view key,
const std::string &val)
{
std::stringstream err;
int md_config_t::set_val(ConfigValues& values,
const ConfigTracker& tracker,
- const std::string &key, const char *val,
+ const std::string_view key, const char *val,
std::stringstream *err_ss)
{
if (key.empty()) {
return -ENOENT;
}
-int md_config_t::rm_val(ConfigValues& values, const std::string& key)
+int md_config_t::rm_val(ConfigValues& values, const std::string_view key)
{
return _rm_val(values, key, CONF_OVERRIDE);
}
}
}
+std::optional<std::string> md_config_t::get_val_default(std::string_view key)
+{
+ std::string val;
+ const Option *opt = find_option(key);
+ if (opt && (conf_stringify(_get_val_default(*opt), &val) == 0)) {
+ return std::make_optional(std::move(val));
+ }
+ return std::nullopt;
+}
+
int md_config_t::get_val(const ConfigValues& values,
- const std::string &key, char **buf, int len) const
+ const std::string_view key, char **buf, int len) const
{
string k(ConfFile::normalize_key_name(key));
return _get_val_cstr(values, k, buf, len);
int md_config_t::get_val(
const ConfigValues& values,
- const std::string &key,
+ const std::string_view key,
std::string *val) const
{
return conf_stringify(get_val_generic(values, key), val);
Option::value_t md_config_t::get_val_generic(
const ConfigValues& values,
- const std::string &key) const
+ const std::string_view key) const
{
- string k(ConfFile::normalize_key_name(key));
- return _get_val(values, k);
+ return _get_val(values, key);
}
Option::value_t md_config_t::_get_val(
const ConfigValues& values,
- const std::string &key,
+ const std::string_view key,
expand_stack_t *stack,
std::ostream *err) const
{
if (key.empty()) {
- return Option::value_t(boost::blank());
+ return {};
}
// In key names, leading and trailing whitespace are not significant.
string k(ConfFile::normalize_key_name(key));
- const Option *o = find_option(key);
+ const Option *o = find_option(k);
if (!o) {
// not a valid config option
- return Option::value_t(boost::blank());
+ return {};
}
return _get_val(values, *o, stack, err);
const Option::value_t& md_config_t::_get_val_default(const Option& o) const
{
- bool has_daemon_default = !boost::get<boost::blank>(&o.daemon_value);
+ bool has_daemon_default = (o.daemon_value != Option::value_t{});
if (is_daemon && has_daemon_default) {
return o.daemon_value;
} else {
bool md_config_t::finalize_reexpand_meta(ConfigValues& values,
const ConfigTracker& tracker)
{
- for (auto& [name, value] : may_reexpand_meta) {
- set_val(values, tracker, name, value);
- }
-
- if (!may_reexpand_meta.empty()) {
- // meta expands could have modified anything. Copy it all out again.
- update_legacy_vals(values);
- return true;
- } else {
- return false;
+ std::vector<std::string> reexpands;
+ reexpands.swap(may_reexpand_meta);
+ for (auto& name : reexpands) {
+ // always refresh the options if they are in the may_reexpand_meta
+ // map, because the options may have already been expanded with old
+ // meta.
+ const auto &opt_iter = schema.find(name);
+ ceph_assert(opt_iter != schema.end());
+ const Option &opt = opt_iter->second;
+ _refresh(values, opt);
}
+
+ return !may_reexpand_meta.empty();
}
Option::value_t md_config_t::_expand_meta(
if (!stack) {
return in;
}
- const std::string *str = boost::get<const std::string>(&in);
+ const auto str = std::get_if<std::string>(&in);
if (!str) {
// strings only!
return in;
} else if (var == "id") {
out += values.name.get_id();
} else if (var == "pid") {
- out += stringify(getpid());
+ char *_pid = getenv("PID");
+ if (_pid) {
+ out += _pid;
+ } else {
+ out += stringify(getpid());
+ }
if (o) {
- may_reexpand_meta[o->name] = *str;
+ may_reexpand_meta.push_back(o->name);
}
} else if (var == "cctid") {
out += stringify((unsigned long long)this);
} else if (var == "home") {
const char *home = getenv("HOME");
out = home ? std::string(home) : std::string();
- } else {
+ } else if (var == "programdata") {
+ const char *home = getenv("ProgramData");
+ out = home ? std::string(home) : std::string();
+ }else {
if (var == "data_dir") {
var = data_dir_option;
}
int md_config_t::_get_val_cstr(
const ConfigValues& values,
- const std::string &key, char **buf, int len) const
+ const std::string& key, char **buf, int len) const
{
if (key.empty())
return -EINVAL;
return (l > len) ? -ENAMETOOLONG : 0;
}
- string k(ConfFile::normalize_key_name(key));
-
// couldn't find a configuration option with key 'k'
return -ENOENT;
}
* looking. The lowest priority section is the one we look in only if all
* others had nothing. This should always be the global section.
*/
-void md_config_t::get_my_sections(const ConfigValues& values,
- std::vector <std::string> §ions) const
+std::vector <std::string>
+md_config_t::get_my_sections(const ConfigValues& values) const
{
- _get_my_sections(values, sections);
-}
-
-void md_config_t::_get_my_sections(const ConfigValues& values,
- std::vector <std::string> §ions) const
-{
- sections.push_back(values.name.to_str());
-
- sections.push_back(values.name.get_type_name());
-
- sections.push_back("global");
+ return {values.name.to_str(),
+ values.name.get_type_name().data(),
+ "global"};
}
// Return a list of all sections
int md_config_t::get_all_sections(std::vector <std::string> §ions) const
{
- for (ConfFile::const_section_iter_t s = cf.sections_begin();
- s != cf.sections_end(); ++s) {
- sections.push_back(s->first);
+ for (auto [section_name, section] : cf) {
+ sections.push_back(section_name);
+ std::ignore = section;
}
return 0;
}
int md_config_t::get_val_from_conf_file(
const ConfigValues& values,
const std::vector <std::string> §ions,
- const std::string &key,
+ const std::string_view key,
std::string &out,
bool emeta) const
{
int md_config_t::_get_val_from_conf_file(
const std::vector <std::string> §ions,
- const std::string &key,
+ const std::string_view key,
std::string &out) const
{
- std::vector <std::string>::const_iterator s = sections.begin();
- std::vector <std::string>::const_iterator s_end = sections.end();
- for (; s != s_end; ++s) {
- int ret = cf.read(s->c_str(), key, out);
+ for (auto &s : sections) {
+ int ret = cf.read(s, key, out);
if (ret == 0) {
return 0;
} else if (ret != -ENOENT) {
std::string *error_message)
{
Option::value_t new_value;
+ ceph_assert(error_message);
int r = opt.parse_value(raw_val, &new_value, error_message);
if (r < 0) {
return r;
if (new_value != _get_val_nometa(values, opt)) {
*error_message = string("Configuration option '") + opt.name +
"' may not be modified at runtime";
- return -ENOSYS;
+ return -EPERM;
}
}
}
int md_config_t::_rm_val(ConfigValues& values,
- const std::string& key,
+ const std::string_view key,
int level)
{
if (schema.count(key) == 0) {
return -EINVAL;
}
- auto ret = values.rm_val(key, level);
+ auto ret = values.rm_val(std::string{key}, level);
if (ret < 0) {
return ret;
}
namespace {
template<typename Size>
-struct get_size_visitor : public boost::static_visitor<Size>
+struct get_size_visitor
{
get_size_visitor() {}
/**
* Handles assigning from a variant-of-types to a variant-of-pointers-to-types
*/
-template<class Config>
-class assign_visitor : public boost::static_visitor<>
+class assign_visitor
{
- Config *conf;
+ ConfigValues *conf;
Option::value_t val;
public:
- assign_visitor(Config *conf_, Option::value_t val_)
+ assign_visitor(ConfigValues *conf_, Option::value_t val_)
: conf(conf_), val(val_)
{}
template <typename T>
- void operator()(T Config::* ptr) const
+ void operator()(T ConfigValues::* ptr) const
{
- T *member = const_cast<T *>(&(conf->*(boost::get<const T Config::*>(ptr))));
+ T *member = const_cast<T *>(&(conf->*(ptr)));
- *member = boost::get<T>(val);
+ *member = std::get<T>(val);
}
- void operator()(uint64_t Config::* ptr) const
+ void operator()(uint64_t ConfigValues::* ptr) const
{
using T = uint64_t;
- auto member = const_cast<T*>(&(conf->*(boost::get<const T Config::*>(ptr))));
- *member = boost::apply_visitor(get_size_visitor<T>{}, val);
+ auto member = const_cast<T*>(&(conf->*(ptr)));
+ *member = std::visit(get_size_visitor<T>{}, val);
}
- void operator()(int64_t Config::* ptr) const
+ void operator()(int64_t ConfigValues::* ptr) const
{
using T = int64_t;
- auto member = const_cast<T*>(&(conf->*(boost::get<const T Config::*>(ptr))));
- *member = boost::apply_visitor(get_size_visitor<T>{}, val);
+ auto member = const_cast<T*>(&(conf->*(ptr)));
+ *member = std::visit(get_size_visitor<T>{}, val);
}
};
} // anonymous namespace
md_config_t::member_ptr_t member_ptr)
{
Option::value_t v = _get_val(values, opt);
- boost::apply_visitor(assign_visitor(&values, v), member_ptr);
+ std::visit(assign_visitor(&values, v), member_ptr);
}
static void dump(Formatter *f, int level, Option::value_t in)
{
- if (const bool *v = boost::get<const bool>(&in)) {
+ if (const auto v = std::get_if<bool>(&in)) {
f->dump_bool(ceph_conf_level_name(level), *v);
- } else if (const int64_t *v = boost::get<const int64_t>(&in)) {
+ } else if (const auto v = std::get_if<int64_t>(&in)) {
f->dump_int(ceph_conf_level_name(level), *v);
- } else if (const uint64_t *v = boost::get<const uint64_t>(&in)) {
+ } else if (const auto v = std::get_if<uint64_t>(&in)) {
f->dump_unsigned(ceph_conf_level_name(level), *v);
- } else if (const double *v = boost::get<const double>(&in)) {
+ } else if (const auto v = std::get_if<double>(&in)) {
f->dump_float(ceph_conf_level_name(level), *v);
} else {
f->dump_stream(ceph_conf_level_name(level)) << Option::to_str(in);
string name) const
{
values.for_each([this, f, &values] (auto& name, auto& configs) {
- if (configs.size() == 1 &&
- configs.begin()->first == CONF_DEFAULT) {
- // we only have a default value; exclude from diff
+ if (configs.empty()) {
return;
}
- f->open_object_section(name.c_str());
+ f->open_object_section(std::string{name}.c_str());
const Option *o = find_option(name);
- dump(f, CONF_DEFAULT, _get_val_default(*o));
+ if (configs.size() &&
+ configs.begin()->first != CONF_DEFAULT) {
+ // show compiled-in default only if an override default wasn't provided
+ dump(f, CONF_DEFAULT, _get_val_default(*o));
+ }
for (auto& j : configs) {
dump(f, j.first, j.second);
}
});
}
-void md_config_t::complain_about_parse_errors(CephContext *cct)
+void md_config_t::complain_about_parse_error(CephContext *cct)
{
- ::complain_about_parse_errors(cct, &parse_errors);
+ ::complain_about_parse_error(cct, parse_error);
}