From: Sage Weil Date: Mon, 4 Dec 2017 22:52:31 +0000 (-0600) Subject: mon/ConfigMap: move option mask parsing into helper X-Git-Tag: wip-pdonnell-testing-20180317.202121~121^2~116 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=7ccd515f823566e2d59b3f0d4c4baa6538670d5e;p=ceph-ci.git mon/ConfigMap: move option mask parsing into helper Signed-off-by: Sage Weil --- diff --git a/src/mon/ConfigMap.cc b/src/mon/ConfigMap.cc index 585d4c43c61..35d433e64d8 100644 --- a/src/mon/ConfigMap.cc +++ b/src/mon/ConfigMap.cc @@ -1,21 +1,24 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +#include + #include "ConfigMap.h" #include "crush/CrushWrapper.h" +#include "common/entity_name.h" int MaskedOption::get_precision(const CrushWrapper *crush) { // 0 = most precise - if (location_type.size()) { - int r = crush->get_type_id(location_type); + if (mask.location_type.size()) { + int r = crush->get_type_id(mask.location_type); if (r >= 0) { return r; } // bad type name, ignore it } int num_types = crush->get_num_type_names(); - if (device_class.size()) { + if (mask.device_class.size()) { return num_types; } return num_types + 1; @@ -25,23 +28,23 @@ void MaskedOption::dump(Formatter *f) const { f->dump_string("name", opt.name); f->dump_string("value", raw_value); - if (location_type.size()) { - f->dump_string("location_type", location_type); - f->dump_string("location_value", location_value); + if (mask.location_type.size()) { + f->dump_string("location_type", mask.location_type); + f->dump_string("location_value", mask.location_value); } - if (device_class.size()) { - f->dump_string("device_class", device_class); + if (mask.device_class.size()) { + f->dump_string("device_class", mask.device_class); } } ostream& operator<<(ostream& out, const MaskedOption& o) { out << o.opt.name; - if (o.location_type.size()) { - out << "@" << o.location_type << '=' << o.location_value; + if (o.mask.location_type.size()) { + out << "@" << o.mask.location_type << '=' << o.mask.location_value; } - if (o.device_class.size()) { - out << "@class=" << o.device_class; + if (o.mask.device_class.size()) { + out << "@class=" << o.mask.device_class; } return out; } @@ -94,14 +97,14 @@ void ConfigMap::generate_entity_map( for (auto& i : s->options) { auto& o = i.second; // match against crush location, class - if (o.device_class.size() && - o.device_class != device_class) { + if (o.mask.device_class.size() && + o.mask.device_class != device_class) { continue; } - if (o.location_type.size()) { - auto p = crush_location.find(o.location_type); + if (o.mask.location_type.size()) { + auto p = crush_location.find(o.mask.location_type); if (p == crush_location.end() || - p->second != o.location_value) { + p->second != o.mask.location_value) { continue; } } @@ -117,3 +120,42 @@ void ConfigMap::generate_entity_map( } } } + +bool ConfigMap::parse_mask( + const std::string& who, + std::string *section, + OptionMask *mask) +{ + vector split; + boost::split(split, who, [](char c){ return c == '/'; }); + for (unsigned j = 0; j < split.size(); ++j) { + auto& i = split[j]; + if (i == "global") { + continue; + } + size_t delim = i.find(':'); + if (delim != std::string::npos) { + string k = i.substr(0, delim); + if (k == "class") { + mask->device_class = i.substr(delim + 1); + } else { + mask->location_type = k; + mask->location_value = i.substr(delim + 1); + } + continue; + } + string type, id; + auto dotpos = i.find('.'); + if (dotpos != std::string::npos) { + type = i.substr(0, dotpos); + id = i.substr(dotpos + 1); + } else { + type = i; + } + if (str_to_ceph_entity_type(type.c_str()) == CEPH_ENTITY_TYPE_ANY) { + return false; + } + *section = i; + } + return true; +} diff --git a/src/mon/ConfigMap.h b/src/mon/ConfigMap.h index c05abba86ef..38b9296d391 100644 --- a/src/mon/ConfigMap.h +++ b/src/mon/ConfigMap.h @@ -30,11 +30,29 @@ class CrushWrapper; // is less precise than host, because the crush limiters are only // resolved within a section (global, per-daemon, per-instance). +struct OptionMask { + std::string location_type, location_value; ///< matches crush_location + std::string device_class; ///< matches device class + + std::string to_str() const { + std::string r; + if (location_type.size()) { + r += location_type + ":" + location_value; + } + if (device_class.size()) { + if (r.size()) { + r += "/"; + } + r += "class:" + device_class; + } + return r; + } +}; + struct MaskedOption { string raw_value; ///< raw, unparsed, unvalidated value Option opt; ///< the option - std::string location_type, location_value; ///< matches crush_location - std::string device_class; ///< matches device class + OptionMask mask; MaskedOption(const Option& o) : opt(o) {} @@ -72,4 +90,9 @@ struct ConfigMap { const CrushWrapper *crush, const std::string& device_class, std::map *out); + + static bool parse_mask( + const std::string& in, + std::string *section, + OptionMask *mask); }; diff --git a/src/mon/ConfigMonitor.cc b/src/mon/ConfigMonitor.cc index f49e957256c..3c93473fb49 100644 --- a/src/mon/ConfigMonitor.cc +++ b/src/mon/ConfigMonitor.cc @@ -118,11 +118,17 @@ void ConfigMonitor::load_config() it->key().compare(0, KEY_PREFIX.size(), KEY_PREFIX) == 0) { string key = it->key().substr(KEY_PREFIX.size()); string value = it->value().to_str(); - vector split; - boost::split(split, key, [](char c){return c == '/';}); - string name = split.back(); - split.pop_back(); - Section *section = &config_map.global; + + auto last_slash = key.rfind('/'); + string name; + string who; + if (last_slash == std::string::npos) { + name = key; + } else { + name = key.substr(last_slash + 1); + who = key.substr(0, last_slash); + } + string section_name; Option fake_opt(name, Option::TYPE_STR, Option::LEVEL_DEV); const Option *opt = g_conf->find_option(name); @@ -134,34 +140,26 @@ void ConfigMonitor::load_config() int r = opt->pre_validate(&value, &err); if (r < 0) { dout(10) << __func__ << " pre-validate failed on '" << name << "' = '" - << value << "' for " << split << dendl; + << value << "' for " << name << dendl; } MaskedOption mopt(*opt); mopt.raw_value = value; - string device_class; - string loc_type, loc_value; - for (unsigned j = 0; j < split.size(); ++j) { - auto& i = split[j]; - size_t delim = i.find(':'); - if (delim != std::string::npos) { - string k = i.substr(0, delim); - if (k == "class") { - mopt.device_class = i.substr(delim + 1); + + if (ConfigMap::parse_mask(who, §ion_name, &mopt.mask)) { + Section *section = &config_map.global;; + if (section_name.size()) { + if (section_name.find('.') != std::string::npos) { + section = &config_map.by_id[section_name]; } else { - mopt.location_type = k; - mopt.location_value = i.substr(delim + 1); + section = &config_map.by_type[section_name]; } - continue; - } - if (split.front().find('.') != std::string::npos) { - section = &config_map.by_id[i]; - } else { - section = &config_map.by_type[i]; } + section->options.insert(make_pair(name, mopt)); + ++num; + } else { + derr << __func__ << " ignoring key " << key << dendl; } - section->options.insert(make_pair(name, mopt)); - ++num; it->next(); } dout(10) << __func__ << " got " << num << " keys" << dendl;