在CephContext 的构造函数中会新建一个AdminSocket和一个CephContextHook
CephContext::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中启动这个socket
void 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_command
void 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, "");
CephContext 中的AdminSocket
最新推荐文章于 2022-06-02 21:43:47 发布