void replica_stub::register_ctrl_command()

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
    });
}