Ceph Observer动态更新配置参数

来源:互联网 发布:51单片机da转换 编辑:程序博客网 时间:2024/06/04 17:57

ceph Observer(观察者模式),可以动态的更改系统配置参数,而不需重启服务。

md_config_t:    //multimap 类型key为option,value为关注该可以的对象。    observers     (typedef std::multimap <std::string, md_config_obs_t*> obs_map_t)    //发生变动的option    changed        (typedef std::set < std::string >)

//将观察者与其观察的key放入observer中。

void md_config_t::add_observer(md_config_obs_t* observer_){  Mutex::Locker l(lock);  const char **keys = observer_->get_tracked_conf_keys();  for (const char ** k = keys; *k; ++k) {    obs_map_t::value_type val(*k, observer_);    observers.insert(val);  }}

//将制定的观察者从observers集合中去除

void md_config_t::remove_observer(md_config_obs_t* observer_){  Mutex::Locker l(lock);  bool found_obs = false;  for (obs_map_t::iterator o = observers.begin(); o != observers.end(); ) {    if (o->second == observer_) {      observers.erase(o++);      found_obs = true;    }    else {      ++o;    }  }  assert(found_obs);}

//获取observer的配置参数集,不同的的子系统实现不同

get_tracked_conf_keys()

//更新全局配置参数,然后把发生变动的参数的key放入到changed集合中
//配置参数集合大致可以分为两类,一:与子系统相关的日志级别参数、二: 普通服务配置参数

//set_val()->set_val_impl()->set_val_impl()  int set_val(const char *key, const string& s, bool meta=true, bool safe=true) {    return set_val(key, s.c_str(), meta, safe);  }int md_config_t::set_val(const char *key, const char *val, bool meta, bool safe){  Mutex::Locker l(lock);  if (!key)    return -EINVAL;  if (!val)    return -EINVAL;  std::string v(val);  if (meta)    expand_meta(v, &std::cerr);  string k(ConfFile::normalize_key_name(key));  // subsystems?  if (strncmp(k.c_str(), "debug_", 6) == 0) {    for (int o = 0; o < subsys.get_num(); o++) {      std::string as_option = "debug_" + subsys.get_name(o);      if (k == as_option) {    int log, gather;    int r = sscanf(v.c_str(), "%d/%d", &log, &gather);    if (r >= 1) {      if (r < 2)        gather = log;      //      cout << "subsys " << subsys.get_name(o) << " log " << log << " gather " << gather << std::endl;      subsys.set_log_level(o, log);      subsys.set_gather_level(o, gather);      return 0;    }    return -EINVAL;      }    }     }  for (int i = 0; i < NUM_CONFIG_OPTIONS; ++i) {    config_option *opt = &config_optionsp[i];    if (strcmp(opt->name, k.c_str()) == 0) {      if (safe && internal_safe_to_start_threads) {    // If threads have been started...    if ((opt->type == OPT_STR) || (opt->type == OPT_ADDR) ||        (opt->type == OPT_UUID)) {      // And this is NOT an integer valued variable....      if (observers.find(opt->name) == observers.end()) {        // And there is no observer to safely change it...        // You lose.        return -ENOSYS;      }    }      }      return set_val_impl(v.c_str(), opt);    }  }  // couldn't find a configuration option with key 'key'  return -ENOENT;}int md_config_t::set_val_impl(const char *val, const config_option *opt){  assert(lock.is_locked());  int ret = set_val_raw(val, opt);  if (ret)    return ret;  changed.insert(opt->name);  return 0;}int md_config_t::set_val_raw(const char *val, const config_option *opt){  assert(lock.is_locked());  switch (opt->type) {    case OPT_INT: {      std::string err;      int f = strict_si_cast<int>(val, &err);      if (!err.empty())    return -EINVAL;      *(int*)opt->conf_ptr(this) = f;      return 0;    }    case OPT_LONGLONG: {      std::string err;      long long f = strict_si_cast<long long>(val, &err);      if (!err.empty())    return -EINVAL;      *(long long*)opt->conf_ptr(this) = f;      return 0;    }    case OPT_STR:      *(std::string*)opt->conf_ptr(this) = val ? val : "";      return 0;    case OPT_FLOAT: {      std::string err;      float f = strict_strtof(val, &err);      if (!err.empty())    return -EINVAL;      *(float*)opt->conf_ptr(this) = f;      return 0;    }  ....    case OPT_UUID: {      uuid_d *u = (uuid_d*)opt->conf_ptr(this);      if (!u->parse(val))    return -EINVAL;      return 0;    }  }  return -ENOSYS;}
void md_config_t::apply_changes(std::ostream *oss){  Mutex::Locker l(lock);  _apply_changes(oss);}void md_config_t::_apply_changes(std::ostream *oss){  /* Maps observers to the configuration options that they care about which   * have changed. */  typedef std::map < md_config_obs_t*, std::set <std::string> > rev_obs_map_t;  expand_all_meta();  // create the reverse observer mapping, mapping observers to the set of  // changed keys that they'll get.  rev_obs_map_t robs;  std::set <std::string> empty_set;  char buf[128];  char *bufptr = (char*)buf;//将更新后的配置参数与oberver相关联。  for (changed_set_t::const_iterator c = changed.begin();       c != changed.end(); ++c) {    const std::string &key(*c);    if ((oss) &&    (!_get_val(key.c_str(), &bufptr, sizeof(buf))) &&    !_internal_field(key)) {      (*oss) << key << " = '" << buf << "' ";    }    pair < obs_map_t::iterator, obs_map_t::iterator >      range(observers.equal_range(key));    for (obs_map_t::iterator r = range.first; r != range.second; ++r) {      rev_obs_map_t::value_type robs_val(r->second, empty_set);      pair < rev_obs_map_t::iterator, bool > robs_ret(robs.insert(robs_val));      std::set <std::string> &keys(robs_ret.first->second);      keys.insert(key);    }  }  // Make any pending observer callbacks  //调用observer的回调函数handle_conf_change() 更新系统参数。  for (rev_obs_map_t::const_iterator r = robs.begin(); r != robs.end(); ++r) {    md_config_obs_t *obs = r->first;    obs->handle_conf_change(this, r->second);  }  changed.clear();}
0 0
原创粉丝点击