本文共 3982 字,大约阅读时间需要 13 分钟。
在CephContext 的构造函数中会新建一个AdminSocket和一个CephContextHookCephContext::CephContext(uint32_t module_type_, enum code_environment_t code_env, int init_flags_){ #新建一个AdminSocket 用于接收命令 _admin_socket = new AdminSocket(this); #新建一个CephContextHook,为这个CephContextHook 添加命令,这样我们就可以通过调用这些命令 _admin_hook = new CephContextHook(this); _admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, ""); _admin_socket->register_command("1", "1", _admin_hook, ""); _admin_socket->register_command("perf dump", "perf dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perfcounters value"); _admin_socket->register_command("perfcounters_schema", "perfcounters_schema", _admin_hook, "");}新建AdminSocket后在start_service_thread中启动这个socketvoid CephContext::start_service_thread(){ // start admin socket if (_conf->admin_socket.length()) _admin_socket->init(_conf->admin_socket);}bool AdminSocket::init(const std::string &path){#开始绑定并监听 int sock_fd; err = bind_and_listen(path, &sock_fd); if (!err.empty()) { lderr(m_cct) << "AdminSocketConfigObs::init: failed: " << err << dendl; close(pipe_rd); close(pipe_wr); return false; }}std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd){ ldout(m_cct, 5) << "bind_and_listen " << sock_path << dendl;#新建socket int sock_fd = socket(PF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { int err = errno; ostringstream oss; oss << "AdminSocket::bind_and_listen: " << "failed to create socket: " << cpp_strerror(err); return oss.str(); }#开始bind if (::bind(sock_fd, (struct sockaddr*)&address, sizeof(struct sockaddr_un)) != 0) { int err = errno; if (err == EADDRINUSE) { AdminSocketClient client(sock_path); bool ok; client.ping(&ok); if (ok) { ldout(m_cct, 20) << "socket " << sock_path << " is in use" << dendl; err = EEXIST; } #开始监听 if (listen(sock_fd, 5) != 0) { int err = errno; ostringstream oss; oss << "AdminSocket::bind_and_listen: " << "failed to listen to socket: " << cpp_strerror(err); close(sock_fd); VOID_TEMP_FAILURE_RETRY(unlink(sock_path.c_str())); return oss.str(); }}这样当收到命令时就会调用bool AdminSocket::do_accept(){ bufferlist out; if (p == m_hooks.end()) { lderr(m_cct) << "AdminSocket: request '" << c << "' not defined" << dendl; } else { string args; if (match != c) { args = c.substr(match.length() + 1); } in_hook = true; auto match_hook = p->second; m_lock.Unlock(); #调用命令注册时对应的call函数 bool success = match_hook->call(match, cmdmap, format, out); }这里我们首先看一下hoook的call函数我们首先看下一CephContextHook的构造函数,class CephContextHook : public AdminSocketHook { CephContext *m_cct;public: explicit CephContextHook(CephContext *cct) : m_cct(cct) {} bool call(std::string command, cmdmap_t& cmdmap, std::string format, bufferlist& out) override { m_cct->do_command(command, cmdmap, format, &out); return true; }};原来就是调用CephContext的do_commandvoid CephContext::do_command(std::string command, cmdmap_t& cmdmap, std::string format, bufferlist *out){ Formatter *f = Formatter::create(format, "json-pretty", "json-pretty"); stringstream ss; for (cmdmap_t::iterator it = cmdmap.begin(); it != cmdmap.end(); ++it) { if (it->first != "prefix") { ss << it->first << ":" << cmd_vartype_stringify(it->second) << " "; } } lgeneric_dout(this, 1) << "do_command '" << command << "' '" << ss.str() << dendl; if (command == "perfcounters_dump" || command == "1" || command == "perf dump") { std::string logger; std::string counter; cmd_getval(this, cmdmap, "logger", logger); cmd_getval(this, cmdmap, "counter", counter); _perf_counters_collection->dump_formatted(f, false, logger, counter); } }这里根据command 不同来走不同的分支,以前面注册的perfcounters_dump 为例,对比看看就很清楚了_admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, "");
转载地址:http://ijnmi.baihongyu.com/