// 遍历可变参数,注意 va_start(ap, oss) 在外层函数 ceph_argparse_binary_flag 中被调用 // does this argument match any of the possibilities? while (1) { // 得到指定进行对比的选项 constchar *a = va_arg(ap, char*); if (a == NULL) // 最后一个可变参数是 NULL,因此 while 循环能够正常结束,注意 va_end(ap) 在外层函数 ceph_argparse_binary_flag 中被调用 returnfalse;
// 遍历可变参数,注意 va_start(ap, oss) 在外层函数 ceph_argparse_witharg 中被调用 // does this argument match any of the possibilities? while (1) { // 得到指定进行对比的选项 constchar *a = va_arg(ap, char*); if (a == NULL) // 最后一个可变参数是 NULL,因此 while 循环能够正常结束,注意 va_end(ap) 在外层函数 ceph_argparse_witharg 中被调用 return0;
// open new conf list<string>::const_iterator c; for (c = conf_files.begin(); c != conf_files.end(); ++c) { // 遍历配置文件 cf.clear(); string fn = *c; expand_meta(fn, warnings); // 调用 ConfFile::parse_file 逐行解析配置文件,并形成按节(section)组织的结构(以节名为 key):map<string, ConfSection> // 其中 ConfSection 为:set<ConfLine>,而 ConfLine 是一组 kv 键值对 // 在 ConfFile::process_line 过程中 ConfLine 可能会用来保存节名,但在最终的 set<ConfLine> 结构中,ConfLine 只保存着键值对 int ret = cf.parse_file(fn.c_str(), &parse_errors, warnings); if (ret == 0) // 任何一个配置文件解析成功,就不再遍历下一个配置文件了,因此用户在命令行指定多个配置文件没有意义 break; elseif (ret != -ENOENT) return ret; } // it must have been all ENOENTs, that's the only way we got here if (c == conf_files.end()) return -ENOENT;
if (cluster.size() == 0) { // 如果没有定义集群名,则截取找到的配置文件的文件名作为集群名,即 xxx.conf -> xxx /* * 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'. */ cluster = "ceph"; } else { cluster = c->substr(start, end - start); } }
std::string val; for (std::vector<constchar*>::iterator i = args.begin(); i != args.end();) { if (strcmp(*i, "--") == 0) { /* Normally we would use ceph_argparse_double_dash. However, in this * function we *don't* want to remove the double dash, because later * argument parses will still need to see it. */ break; } elseif (ceph_argparse_flag(args, i, "--show_conf", (char*) NULL)) { // 打印找到的配置文件中的内容 cerr << cf << std::endl; _exit(0); } elseif (ceph_argparse_flag(args, i, "--show_config", (char*) NULL)) { // 显示与指定 entity 相关的所有选项,会对 $变量 进行展开 show_config = true; } elseif (ceph_argparse_witharg(args, i, &val, "--show_config_value", // 显示与指定 entity 的指定选项,会对 $变量 进行展开 (char*) NULL)) { show_config_value = true; show_config_value_arg = val; } elseif (ceph_argparse_flag(args, i, "--foreground", "-f", (char*) NULL)) { set_val_or_die("daemonize", "false"); } elseif (ceph_argparse_flag(args, i, "-d", (char*) NULL)) { set_val_or_die("daemonize", "false"); set_val_or_die("log_file", ""); set_val_or_die("log_to_stderr", "true"); set_val_or_die("err_to_stderr", "true"); set_val_or_die("log_to_syslog", "false"); } // Some stuff that we wanted to give universal single-character options for // Careful: you can burn through the alphabet pretty quickly by adding // to this list. elseif (ceph_argparse_witharg(args, i, &val, "--monmap", "-M", (char*) NULL)) { set_val_or_die("monmap", val.c_str()); } elseif (ceph_argparse_witharg(args, i, &val, "--mon_host", "-m", (char*) NULL)) { set_val_or_die("mon_host", val.c_str()); } elseif (ceph_argparse_witharg(args, i, &val, "--bind", (char*) NULL)) { set_val_or_die("public_addr", val.c_str()); } elseif (ceph_argparse_witharg(args, i, &val, "--keyfile", "-K", (char*) NULL)) { set_val_or_die("keyfile", val.c_str()); } elseif (ceph_argparse_witharg(args, i, &val, "--keyring", "-k", (char*) NULL)) { set_val_or_die("keyring", val.c_str()); } elseif (ceph_argparse_witharg(args, i, &val, "--client_mountpoint", "-r", (char*) NULL)) { set_val_or_die("client_mountpoint", val.c_str()); } else { int r = parse_option(args, i, NULL); if (r < 0) { return r; } } }
intmd_config_t::parse_option(std::vector<constchar*>& args, std::vector<constchar*>::iterator& i, ostream *oss){ int ret = 0; size_t o = 0; std::string val;
// 遍历日志子系统 // subsystems? for (o = 0; o < subsys.get_num(); o++) { // 构建待匹配的日志级别选项 --debug_xxx,注意默认的日志子系统名称是 none std::string as_option("--"); as_option += "debug_"; as_option += subsys.get_name(o);
// 将命令行与对应的日志打印级别选项 --debug_xxx 进行匹配 ostringstream err; if (ceph_argparse_witharg(args, i, &val, err, as_option.c_str(), (char*) NULL)) { // 命令行是一个 --debug_xxx 选项 if (err.tellp()) { if (oss) { *oss << err.str(); } ret = -EINVAL; break; } int log, gather; int r = sscanf(val.c_str(), "%d/%d", &log, &gather); // --debug_xxx 是 option 选项类型,选项值 arg 保存在出参 val 中 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); if (oss) *oss << "debug_" << subsys.get_name(o) << "=" << log << "/" << gather << " "; } break; } } if (o < subsys.get_num()) { return ret; }