in src/replica/replica_stub.cpp [2502:2683]
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_command(
{"replica.kill_partition"},
"replica.kill_partition [app_id [partition_index]]",
"replica.kill_partition: kill partitions by (all, one app, one partition)",
[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_command(
{"replica.deny-client"},
"replica.deny-client <true|false>",
"replica.deny-client - control if deny client read & write request",
[this](const std::vector<std::string> &args) {
return remote_command_set_bool_flag(_deny_client, "deny-client", args);
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.verbose-client-log"},
"replica.verbose-client-log <true|false>",
"replica.verbose-client-log - control if print verbose error log when reply read & "
"write request",
[this](const std::vector<std::string> &args) {
return remote_command_set_bool_flag(
_verbose_client_log, "verbose-client-log", args);
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.verbose-commit-log"},
"replica.verbose-commit-log <true|false>",
"replica.verbose-commit-log - control if print verbose log when commit mutation",
[this](const std::vector<std::string> &args) {
return remote_command_set_bool_flag(
_verbose_commit_log, "verbose-commit-log", args);
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.trigger-checkpoint"},
"replica.trigger-checkpoint [id1,id2,...] (where id is 'app_id' or "
"'app_id.partition_id')",
"replica.trigger-checkpoint - trigger replicas to do checkpoint",
[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_command(
{"replica.query-compact"},
"replica.query-compact [id1,id2,...] (where id is 'app_id' or 'app_id.partition_id')",
"replica.query-compact - query full compact status on the underlying storage engine",
[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_command(
{"replica.query-app-envs"},
"replica.query-app-envs [id1,id2,...] (where id is 'app_id' or 'app_id.partition_id')",
"replica.query-app-envs - query app envs on the underlying storage engine",
[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, ',', '=');
});
}));
#ifdef DSN_ENABLE_GPERF
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.release-tcmalloc-memory"},
"replica.release-tcmalloc-memory <true|false>",
"replica.release-tcmalloc-memory - control if try to release tcmalloc memory",
[this](const std::vector<std::string> &args) {
return remote_command_set_bool_flag(
_release_tcmalloc_memory, "release-tcmalloc-memory", args);
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.get-tcmalloc-status"},
"replica.get-tcmalloc-status - get status of tcmalloc",
"get 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_command(
{"replica.mem-release-max-reserved-percentage"},
"replica.mem-release-max-reserved-percentage [num | DEFAULT]",
"control tcmalloc max reserved but not-used memory percentage",
[this](const std::vector<std::string> &args) {
std::string result("OK");
if (args.empty()) {
// show current value
result = "mem-release-max-reserved-percentage = " +
std::to_string(_mem_release_max_reserved_mem_percentage);
return result;
}
if (args[0] == "DEFAULT") {
// set to default value
_mem_release_max_reserved_mem_percentage =
FLAGS_mem_release_max_reserved_mem_percentage;
return result;
}
int32_t percentage = 0;
if (!dsn::buf2int32(args[0], percentage) || percentage <= 0 || percentage > 100) {
result = std::string("ERR: invalid arguments");
} else {
_mem_release_max_reserved_mem_percentage = percentage;
}
return result;
}));
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.release-all-reserved-memory"},
"replica.release-all-reserved-memory - release tcmalloc all reserved-not-used memory",
"release tcmalloc all reserverd 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
// TODO(yingchun): use http
_cmds.emplace_back(::dsn::command_manager::instance().register_command(
{"replica.max-concurrent-bulk-load-downloading-count"},
"replica.max-concurrent-bulk-load-downloading-count [num | DEFAULT]",
"control stub max_concurrent_bulk_load_downloading_count",
[this](const std::vector<std::string> &args) {
std::string result("OK");
if (args.empty()) {
result = "max_concurrent_bulk_load_downloading_count=" +
std::to_string(_max_concurrent_bulk_load_downloading_count);
return result;
}
if (args[0] == "DEFAULT") {
_max_concurrent_bulk_load_downloading_count =
_options.max_concurrent_bulk_load_downloading_count;
return result;
}
int32_t count = 0;
if (!dsn::buf2int32(args[0], count) || count <= 0) {
result = std::string("ERR: invalid arguments");
} else {
_max_concurrent_bulk_load_downloading_count = count;
}
return result;
}));
});
}