]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/ConfigMap: move option mask parsing into helper
authorSage Weil <sage@redhat.com>
Mon, 4 Dec 2017 22:52:31 +0000 (16:52 -0600)
committerSage Weil <sage@redhat.com>
Tue, 6 Mar 2018 20:44:48 +0000 (14:44 -0600)
Signed-off-by: Sage Weil <sage@redhat.com>
src/mon/ConfigMap.cc
src/mon/ConfigMap.h
src/mon/ConfigMonitor.cc

index 585d4c43c61eab0e7b95c26ae6483b03412274b2..35d433e64d8915d29b135b564fce819d113650be 100644 (file)
@@ -1,21 +1,24 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
+#include <boost/algorithm/string/split.hpp>
+
 #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<std::string> 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;
+}
index c05abba86ef7e38ba5e8c03a0cb1fa77d13f503f..38b9296d391b5c0a5ca160647989f7b538acaa55 100644 (file)
@@ -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<std::string,std::string> *out);
+
+  static bool parse_mask(
+    const std::string& in,
+    std::string *section,
+    OptionMask *mask);
 };
index f49e957256ccd4198a7737a27e8e9944c589f65b..3c93473fb499f22360797bf26d4e5b2c9d66f5bd 100644 (file)
@@ -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<string> 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, &section_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;