template<LockPolicy lp>
md_config_impl<lp>::md_config_impl(ConfigValues& values,
bool is_daemon)
- : is_daemon(is_daemon),
- lock("md_config_t", true, false)
+ : is_daemon(is_daemon)
{
// Load the compile-time list of Option into
// a map so that we can resolve keys quickly.
void md_config_impl<lp>::set_val_default(ConfigValues& values,
const string& name, const std::string& val)
{
- auto locker = lock();
const Option *o = find_option(name);
assert(o);
string err;
const map<string,string>& kv,
config_callback config_cb)
{
- auto locker = lock();
ignored_mon_values.clear();
if (!config_cb) {
template<LockPolicy lp>
void md_config_impl<lp>::add_observer(md_config_obs_impl<lp>* observer_)
{
- auto locker = lock();
const char **keys = observer_->get_tracked_conf_keys();
for (const char ** k = keys; *k; ++k) {
observers.emplace(*k, observer_);
template<LockPolicy lp>
void md_config_impl<lp>::remove_observer(md_config_obs_impl<lp>* observer_)
{
- auto locker = lock();
bool found_obs = false;
for (auto o = observers.begin(); o != observers.end(); ) {
if (o->second == observer_) {
std::ostream *warnings,
int flags)
{
- auto locker = lock();
if (safe_to_start_threads)
return -ENOSYS;
args_var = "CEPH_ARGS";
}
if (getenv("CEPH_KEYRING")) {
- auto locker = lock();
_set_val(values, getenv("CEPH_KEYRING"), *find_option("keyring"),
CONF_ENV, nullptr);
}
if (const char *dir = getenv("CEPH_LIB")) {
- auto locker = lock();
for (auto name : { "erasure_code_dir", "plugin_dir", "osd_class_dir" }) {
std::string err;
const Option *o = find_option(name);
template<LockPolicy lp>
void md_config_impl<lp>::show_config(const ConfigValues& values, std::ostream& out)
{
- auto locker = lock();
_show_config(values, &out, nullptr);
}
template<LockPolicy lp>
void md_config_impl<lp>::show_config(const ConfigValues& values, Formatter *f)
{
- auto locker = lock();
_show_config(values, nullptr, f);
}
template<LockPolicy lp>
void md_config_impl<lp>::config_options(Formatter *f)
{
- auto locker = lock();
f->open_array_section("options");
for (const auto& i: schema) {
f->dump_object("option", i.second);
int md_config_impl<lp>::parse_argv(ConfigValues& values,
std::vector<const char*>& args, int level)
{
- auto locker = lock();
if (safe_to_start_threads) {
return -ENOSYS;
}
template<LockPolicy lp>
void md_config_impl<lp>::do_argv_commands(const ConfigValues& values)
{
- auto locker = lock();
if (do_show_config) {
_show_config(values, &cout, NULL);
const ConfigProxy& proxy,
std::ostream *oss)
{
- auto locker = lock();
/*
* apply changes until the cluster name is assigned
*/
// An alternative might be to pass a std::unique_lock to
// handle_conf_change and have a version of get_var that can take it
// by reference and lock as appropriate.
- auto locker = lock();
{
for (auto r = observers.begin(); r != observers.end(); ++r) {
obs[r->second].insert(r->first);
const std::string& s, std::ostream *oss)
{
int ret;
- auto locker = lock();
char b[s.length()+1];
strcpy(b, s.c_str());
std::vector<const char*> nargs;
const std::string &key, const char *val,
std::stringstream *err_ss)
{
- auto locker = lock();
if (key.empty()) {
if (err_ss) *err_ss << "No key specified";
return -EINVAL;
template<LockPolicy lp>
int md_config_impl<lp>::rm_val(ConfigValues& values, const std::string& key)
{
- auto locker = lock();
return _rm_val(values, key, CONF_OVERRIDE);
}
void md_config_impl<lp>::get_defaults_bl(const ConfigValues& values,
bufferlist *bl)
{
- auto locker = lock();
if (defaults_bl.length() == 0) {
uint32_t n = 0;
bufferlist bl;
bufferlist *bl,
uint64_t *got_version)
{
- auto locker = lock();
if (values_bl.length() == 0) {
uint32_t n = 0;
bufferlist bl;
int md_config_impl<lp>::get_val(const ConfigValues& values,
const std::string &key, char **buf, int len) const
{
- auto locker = lock();
string k(ConfFile::normalize_key_name(key));
return _get_val_cstr(values, k, buf, len);
}
const ConfigValues& values,
const std::string &key) const
{
- auto locker = lock();
string k(ConfFile::normalize_key_name(key));
return _get_val(values, k);
}
expand_stack_t *stack,
std::ostream *err) const
{
- assert(lock.is_locked());
if (key.empty()) {
return Option::value_t(boost::blank());
}
std::string &val,
std::ostream *err) const
{
- auto locker = lock();
expand_stack_t stack;
Option::value_t v = _expand_meta(values,
Option::value_t(val),
const ConfigValues& values,
const std::string &key, char **buf, int len) const
{
- assert(lock.is_locked());
-
if (key.empty())
return -EINVAL;
void md_config_impl<lp>::get_my_sections(const ConfigValues& values,
std::vector <std::string> §ions) const
{
- auto locker = lock();
_get_my_sections(values, sections);
}
void md_config_impl<lp>::_get_my_sections(const ConfigValues& values,
std::vector <std::string> §ions) const
{
- assert(lock.is_locked());
sections.push_back(values.name.to_str());
sections.push_back(values.name.get_type_name());
template<LockPolicy lp>
int md_config_impl<lp>::get_all_sections(std::vector <std::string> §ions) const
{
- auto locker = lock();
for (ConfFile::const_section_iter_t s = cf.sections_begin();
s != cf.sections_end(); ++s) {
sections.push_back(s->first);
std::string &out,
bool emeta) const
{
- auto locker = lock();
int r = _get_val_from_conf_file(sections, key, out);
if (r < 0) {
return r;
const std::string &key,
std::string &out) const
{
- assert(lock.is_locked());
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 level,
std::string *error_message)
{
- assert(lock.is_locked());
-
Option::value_t new_value;
int r = opt.parse_value(raw_val, &new_value, error_message);
if (r < 0) {
Formatter *f,
string name) const
{
- auto locker = lock();
values.for_each([this, f, &values] (auto& name, auto& configs) {
if (configs.size() == 1 &&
configs.begin()->first == CONF_DEFAULT) {
#include <type_traits>
#include "common/config.h"
#include "common/config_fwd.h"
+#include "common/Mutex.h"
class ConfigProxy {
/**
*/
ConfigValues values;
md_config_t config;
+ /** A lock that protects the md_config_t internals. It is
+ * recursive, for simplicity.
+ * It is best if this lock comes first in the lock hierarchy. We will
+ * hold this lock when calling configuration observers. */
+ mutable Mutex lock;
public:
explicit ConfigProxy(bool is_daemon)
- : config{values, is_daemon}
+ : config{values, is_daemon},
+ lock{"ConfigProxy", true, false}
{}
const ConfigValues* operator->() const noexcept {
return &values;
return &values;
}
int get_val(const std::string& key, char** buf, int len) const {
+ Mutex::Locker l{lock};
return config.get_val(values, key, buf, len);
}
int get_val(const std::string &key, std::string *val) const {
+ Mutex::Locker l{lock};
return config.get_val(values, key, val);
}
template<typename T>
const T get_val(const std::string& key) const {
+ Mutex::Locker l{lock};
return config.template get_val<T>(values, key);
}
template<typename T, typename Callback, typename...Args>
auto with_val(const string& key, Callback&& cb, Args&&... args) const {
+ Mutex::Locker l{lock};
return config.template with_val<T>(values, key,
std::forward<Callback>(cb),
std::forward<Args>(args)...);
}
void diff(Formatter *f, const std::string& name=string{}) const {
return config.diff(values, f, name);
+ Mutex::Locker l{lock};
}
void get_my_sections(std::vector <std::string> §ions) const {
+ Mutex::Locker l{lock};
config.get_my_sections(values, sections);
}
int get_all_sections(std::vector<std::string>& sections) const {
+ Mutex::Locker l{lock};
return config.get_all_sections(sections);
}
int get_val_from_conf_file(const std::vector<std::string>& sections,
const std::string& key, std::string& out,
bool emeta) const {
+ Mutex::Locker l{lock};
return config.get_val_from_conf_file(values,
sections, key, out, emeta);
}
}
void early_expand_meta(std::string &val,
std::ostream *oss) const {
+ Mutex::Locker l{lock};
return config.early_expand_meta(values, val, oss);
}
// change `values` in-place
void finalize_reexpand_meta() {
+<<<<<<< HEAD
+ Mutex::Locker l(lock);
config.finalize_reexpand_meta(values, *this);
}
void add_observer(md_config_obs_t* obs) {
+ Mutex::Locker l(lock);
config.add_observer(obs);
}
void remove_observer(md_config_obs_t* obs) {
+ Mutex::Locker l(lock);
config.remove_observer(obs);
}
+ void call_all_observers() {
+ Mutex::Locker l(lock);
+ config.call_all_observers(*this);
+=======
+ Mutex::Locker l{lock};
+ if (config.finalize_reexpand_meta(values, obs_mgr)) {
+ obs_mgr.apply_changes(values.changed, *this, nullptr);
+ values.changed.clear();
+ }
+ }
+ void add_observer(md_config_obs_t* obs) {
+ Mutex::Locker l{lock};
+ obs_mgr.add_observer(obs);
+ }
+ void remove_observer(md_config_obs_t* obs) {
+ Mutex::Locker l{lock};
+ obs_mgr.remove_observer(obs);
+ }
+ void call_all_observers() {
+ Mutex::Locker l{lock};
+ // Have the scope of the lock extend to the scope of
+ // handle_conf_change since that function expects to be called with
+ // the lock held. (And the comment in config.h says that is the
+ // expected behavior.)
+ //
+ // An alternative might be to pass a std::unique_lock to
+ // handle_conf_change and have a version of get_var that can take it
+ // by reference and lock as appropriate.
+ obs_mgr.call_all_observers(*this);
+>>>>>>> 9a2bc3c2eb... wip
+ }
void set_safe_to_start_threads() {
config.set_safe_to_start_threads();
}
void _clear_safe_to_start_threads() {
config._clear_safe_to_start_threads();
}
- void call_all_observers() {
- config.call_all_observers(*this);
- }
void show_config(std::ostream& out) {
+ Mutex::Locker l{lock};
config.show_config(values, out);
}
void show_config(Formatter *f) {
+ Mutex::Locker l{lock};
config.show_config(values, f);
}
void config_options(Formatter *f) {
+ Mutex::Locker l{lock};
config.config_options(f);
}
int rm_val(const std::string& key) {
+ Mutex::Locker l{lock};
return config.rm_val(values, key);
}
void apply_changes(std::ostream* oss) {
+ Mutex::Locker l{lock};
config.apply_changes(values, *this, oss);
}
int set_val(const std::string& key, const std::string& s,
std::stringstream* err_ss=nullptr) {
+ Mutex::Locker l{lock};
return config.set_val(values, key, s);
}
void set_val_default(const std::string& key, const std::string& val) {
+ Mutex::Locker l{lock};
config.set_val_default(values, key, val);
}
void set_val_or_die(const std::string& key, const std::string& val) {
+ Mutex::Locker l{lock};
config.set_val_or_die(values, key, val);
}
int set_mon_vals(CephContext *cct,
const map<std::string,std::string>& kv,
md_config_t::config_callback config_cb) {
+ Mutex::Locker l{lock};
config.set_mon_vals(cct, values, *this, kv, config_cb);
}
int injectargs(const std::string &s, std::ostream *oss) {
+ Mutex::Locker l{lock};
config.injectargs(values, *this, s, oss);
}
void parse_env(const char *env_var = "CEPH_ARGS") {
+ Mutex::Locker l{lock};
config.parse_env(values, env_var);
}
int parse_argv(std::vector<const char*>& args, int level=CONF_CMDLINE) {
+ Mutex::Locker l{lock};
return config.parse_argv(values, args, level);
}
int parse_config_files(const char *conf_files,
std::ostream *warnings, int flags) {
+ Mutex::Locker l{lock};
return config.parse_config_files(values, conf_files, warnings, flags);
}
size_t num_parse_errors() const {
return config.complain_about_parse_errors(cct);
}
void do_argv_commands() {
+ Mutex::Locker l{lock};
config.do_argv_commands(values);
}
void get_config_bl(uint64_t have_version,
bufferlist *bl,
uint64_t *got_version) {
+ Mutex::Locker l{lock};
config.get_config_bl(values, have_version, bl, got_version);
}
void get_defaults_bl(bufferlist *bl) {
+ Mutex::Locker l{lock};
config.get_defaults_bl(values, bl);
}
};