in src/replica/replica_stub.cpp [2566:2733]
void replica_stub::register_ctrl_command()
{
/// In simple_kv test, three replica apps are created, which means that three replica_stubs are
/// initialized in simple_kv test. If we don't use std::call_once, these command are registered
/// for three times. And in command_manager, one same command is not allowed to be registered
/// more than twice times. That is why we use std::call_once here. Same situation in
/// failure_detector::register_ctrl_commands and nfs_client_impl::register_cli_commands
static std::once_flag flag;
std::call_once(flag, [&]() {
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.kill_partition",
"Kill partitions by (all, one app, one partition)",
"[app_id [partition_index]]",
[this](const std::vector<std::string> &args) {
dsn::gpid pid;
if (args.size() == 0) {
pid.set_app_id(-1);
pid.set_partition_index(-1);
} else if (args.size() == 1) {
pid.set_app_id(atoi(args[0].c_str()));
pid.set_partition_index(-1);
} else if (args.size() == 2) {
pid.set_app_id(atoi(args[0].c_str()));
pid.set_partition_index(atoi(args[1].c_str()));
} else {
return std::string(ERR_INVALID_PARAMETERS.to_string());
}
dsn::error_code e = this->on_kill_replica(pid);
return std::string(e.to_string());
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_bool_command(
_deny_client, "replica.deny-client", "control if deny client read & write request"));
_cmds.emplace_back(::dsn::command_manager::instance().register_bool_command(
_verbose_client_log,
"replica.verbose-client-log",
"control if print verbose error log when reply read & write request"));
_cmds.emplace_back(::dsn::command_manager::instance().register_bool_command(
_verbose_commit_log,
"replica.verbose-commit-log",
"control if print verbose log when commit mutation"));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.trigger-checkpoint",
"Trigger replicas to do checkpoint by app_id or app_id.partition_id",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [this](const replica_ptr &rep) {
tasking::enqueue(LPC_PER_REPLICA_CHECKPOINT_TIMER,
rep->tracker(),
std::bind(&replica_stub::trigger_checkpoint, this, rep, true),
rep->get_gpid().thread_hash());
return std::string("triggered");
});
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.query-compact",
"Query full compact status on the underlying storage engine by app_id or "
"app_id.partition_id",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [](const replica_ptr &rep) {
return rep->query_manual_compact_state();
});
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.query-app-envs",
"Query app envs on the underlying storage engine by app_id or app_id.partition_id",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [](const replica_ptr &rep) {
std::map<std::string, std::string> kv_map;
rep->query_app_envs(kv_map);
return dsn::utils::kv_map_to_string(kv_map, ',', '=');
});
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.enable-plog-gc",
"Enable plog garbage collection for replicas specified by comma-separated list "
"of 'app_id' or 'app_id.partition_id', or all replicas for empty",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [](const replica_ptr &rep) {
rep->update_plog_gc_enabled(true);
return rep->get_plog_gc_enabled_message();
});
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.disable-plog-gc",
"Disable plog garbage collection for replicas specified by comma-separated list "
"of 'app_id' or 'app_id.partition_id', or all replicas for empty",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [](const replica_ptr &rep) {
rep->update_plog_gc_enabled(false);
return rep->get_plog_gc_enabled_message();
});
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.query-plog-gc-enabled-status",
"Query if plog garbage collection is enabled or disabled for replicas specified by "
"comma-separated list of 'app_id' or 'app_id.partition_id', or all replicas for empty",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [](const replica_ptr &rep) {
return rep->get_plog_gc_enabled_message();
});
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.query-progress",
"Query the progress of decrees, including both local writes and duplications for "
"replicas specified by comma-separated list of 'app_id' or 'app_id.partition_id', "
"or all replicas for empty",
"[id1,id2,...]",
[this](const std::vector<std::string> &args) {
return exec_command_on_replica(args, true, [](const replica_ptr &rep) {
std::ostringstream out;
rapidjson::OStreamWrapper wrapper(out);
dsn::json::PrettyJsonWriter writer(wrapper);
rep->encode_progress(writer);
return out.str();
});
}));
#ifdef DSN_ENABLE_GPERF
_cmds.emplace_back(::dsn::command_manager::instance().register_bool_command(
_release_tcmalloc_memory,
"replica.release-tcmalloc-memory",
"control if try to release tcmalloc memory"));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.get-tcmalloc-status",
"Get the status of tcmalloc",
"",
[](const std::vector<std::string> &args) {
char buf[4096];
MallocExtension::instance()->GetStats(buf, 4096);
return std::string(buf);
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_int_command(
_mem_release_max_reserved_mem_percentage,
FLAGS_mem_release_max_reserved_mem_percentage,
"replica.mem-release-max-reserved-percentage",
"control tcmalloc max reserved but not-used memory percentage",
&check_mem_release_max_reserved_mem_percentage));
_cmds.emplace_back(::dsn::command_manager::instance().register_single_command(
"replica.release-all-reserved-memory",
"Release tcmalloc all reserved-not-used memory back to operating system",
"",
[this](const std::vector<std::string> &args) {
auto release_bytes = gc_tcmalloc_memory(true);
return "OK, release_bytes=" + std::to_string(release_bytes);
}));
#elif defined(DSN_USE_JEMALLOC)
register_jemalloc_ctrl_command();
#endif
});
}