diff --git a/include/dsn/c/api_utilities.h b/include/dsn/c/api_utilities.h index 0ad1942bed..cd2585f5f0 100644 --- a/include/dsn/c/api_utilities.h +++ b/include/dsn/c/api_utilities.h @@ -89,88 +89,6 @@ extern DSN_API const char *dsn_error_to_string(dsn_error_t err); extern DSN_API dsn_error_t dsn_error_from_string(const char *s, dsn_error_t default_err); /*@}*/ -/*! -@defgroup app-cli Command-Line Interface (cli) -@ingroup service-api-utilities - - Built-in command line interface that can be accessed via local/tcp/http consoles. - - @{ - */ - -/*! - run a given cli command - - \param command_line given command line. - - \return null if it fails, else execution response - */ -extern DSN_API const char *dsn_cli_run(const char *command_line); - -/*! - free memory occupied by cli response - - \param command_output result from \ref dsn_cli_run - */ -extern DSN_API void dsn_cli_free(const char *command_output); - -/*! cli response definition */ -typedef struct dsn_cli_reply -{ - const char *message; ///< zero-ended reply message - uint64_t size; ///< message_size - void *context; ///< context for free_handler -} dsn_cli_reply; - -/*! cli request handler definition */ -typedef void (*dsn_cli_handler)(void *context, ///< context registered by \ref dsn_cli_register - int argc, ///< argument count - const char **argv, ///< arguments - /*out*/ dsn_cli_reply *reply ///< reply message - ); - -/*! cli response resource gc handler definition */ -typedef void (*dsn_cli_free_handler)(dsn_cli_reply reply); - -/*! - register a customized cli command handler - - \param command command name - \param help_one_line one line help information - \param help_long long help information - \param context context used by \ref cmd_handler - \param cmd_handler command handler - \param output_freer command result resource free handler - - \return the handle of this registered command - */ -extern DSN_API dsn_handle_t dsn_cli_register(const char *command, - const char *help_one_line, - const char *help_long, - void *context, - dsn_cli_handler cmd_handler, - dsn_cli_free_handler output_freer); - -/*! - same as \ref dsn_cli_register, except that the command - name is auto-augmented by rDSN as $app_full_name.$command - */ -extern DSN_API dsn_handle_t dsn_cli_app_register(const char *command, - const char *help_one_line, - const char *help_long, - void *context, - dsn_cli_handler cmd_handler, - dsn_cli_free_handler output_freer); - -/*! - remove a cli handler - - \param cli_handle handle of the cli returned from \ref dsn_cli_register or \ref - dsn_cli_app_register - */ -extern DSN_API void dsn_cli_deregister(dsn_handle_t cli_handle); -/*@}*/ - /*! @defgroup config Configuration Service @ingroup service-api-utilities @@ -366,7 +284,6 @@ extern DSN_API uint64_t dsn_crc64_concatenate(uint32_t xy_init, uint64_t y_init, uint64_t y_final, size_t y_size); -/*@}*/ /*! @defgroup memory Memory Management diff --git a/include/dsn/tool-api/command.h b/include/dsn/tool-api/command.h deleted file mode 100644 index fd2820e785..0000000000 --- a/include/dsn/tool-api/command.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Microsoft Corporation - * - * -=- Robust Distributed System Nucleus (rDSN) -=- - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Description: - * interface for command line interface in rDSN - * - * Revision history: - * May, 2015, @imzhenyu (Zhenyu Guo), first version - * xxxx-xx-xx, author, fix bug about xxx - */ -#pragma once - -#include -#include -#include -#include - -namespace dsn { - -typedef std::function &)> command_handler; - -extern DSN_API void *register_command( - const std::vector &commands, // commands, e.g., {"help", "Help", "HELP", "h", "H"} - const char *help_one_line, - const char *help_long, - command_handler handler); - -extern DSN_API void *register_command(const char *command, // commands, e.g., "help" - const char *help_one_line, - const char *help_long, - command_handler handler); - -DSN_API void deregister_command(void *cli_handle); -} diff --git a/include/dsn/tool-api/command_manager.h b/include/dsn/tool-api/command_manager.h new file mode 100644 index 0000000000..630f6d7f0c --- /dev/null +++ b/include/dsn/tool-api/command_manager.h @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Microsoft Corporation + * + * -=- Robust Distributed System Nucleus (rDSN) -=- + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include +#include + +namespace dsn { + +class command_manager : public ::dsn::utils::singleton +{ +public: + typedef std::function &)> command_handler; + command_manager(); + + dsn_handle_t register_command(const std::vector &commands, + const std::string &help_one_line, + const std::string &help_long, + command_handler handler); + dsn_handle_t register_app_command(const std::vector &commands, + const std::string &help_one_line, + const std::string &help_long, + command_handler handler); + void deregister_command(dsn_handle_t handle); + + bool run_command(const std::string &cmdline, /*out*/ std::string &output); + void start_remote_cli(); + void on_remote_cli(dsn_message_t req); + void set_cli_target_address(dsn_handle_t handle, dsn::rpc_address address); + +private: + bool run_command(const std::string &cmd, + const std::vector &args, + /*out*/ std::string &output); + +private: + struct command_instance + { + dsn::rpc_address address; + std::vector commands; + std::string help_short; + std::string help_long; + command_handler handler; + }; + + ::dsn::utils::rw_lock_nr _lock; + std::map _handlers; + std::vector _commands; +}; +} + +#define UNREGISTER_VALID_HANDLER(ptr) \ + do { \ + if (ptr != nullptr) { \ + dsn::command_manager::instance().deregister_command(ptr); \ + ptr = nullptr; \ + } \ + } while (0) + +// handle bool-flag "flag" with "args": if args are empty, then return the old flag; otherwise +// set the proper "flag" according to args +#define HANDLE_CLI_FLAGS(flag, args) \ + do { \ + std::string ret_msg("OK"); \ + if (args.size() <= 0) { \ + ret_msg = flag ? "true" : "false"; \ + } else { \ + if (strcmp(args[0].c_str(), "true") == 0) { \ + flag = true; \ + ddebug("set " #flag " to true by remote command"); \ + } else if (strcmp(args[0].c_str(), "false") == 0) { \ + flag = false; \ + ddebug("set " #flag " to false by remote command"); \ + } else { \ + ret_msg = "ERR: invalid arguments"; \ + } \ + } \ + return ret_msg; \ + } while (0) diff --git a/src/core/core/command_manager.cpp b/src/core/core/command_manager.cpp index 837a050c5c..b449911be6 100644 --- a/src/core/core/command_manager.cpp +++ b/src/core/core/command_manager.cpp @@ -33,141 +33,69 @@ * xxxx-xx-xx, author, fix bug about xxx */ -#include "command_manager.h" #include #include #include + #include #include -#include "service_engine.h" #include #include -#include "rpc_engine.h" +#include #include +#include "service_engine.h" +#include "rpc_engine.h" + #ifdef __TITLE__ #undef __TITLE__ #endif #define __TITLE__ "command_manager" -DSN_API const char *dsn_cli_run(const char *command_line) // return command output -{ - std::string cmd = command_line; - std::string output; - dsn::command_manager::instance().run_command(cmd, output); - - char *c_output = (char *)malloc(output.length() + 1); - memcpy(c_output, &output[0], output.length()); - c_output[output.length()] = '\0'; - return c_output; -} - -DSN_API void dsn_cli_free(const char *command_output) { ::free((void *)command_output); } - -DSN_API dsn_handle_t dsn_cli_register(const char *command, - const char *help_one_line, - const char *help_long, - void *context, - dsn_cli_handler cmd_handler, - dsn_cli_free_handler output_freer) -{ - return dsn::register_command( - command, help_one_line, help_long, [=](const std::vector &args) { - std::vector c_args; - for (auto &s : args) { - c_args.push_back(s.c_str()); - } - dsn_cli_reply reply; - cmd_handler(context, - (int)c_args.size(), - c_args.empty() ? nullptr : (const char **)&c_args[0], - &reply); - std::string cpp_output = std::string(reply.message, reply.message + reply.size); - output_freer(reply); - return cpp_output; - }); -} - -DSN_API dsn_handle_t dsn_cli_app_register(const char *command, // registered command, you should - // call this command by - // app_full_name.command - const char *help_one_line, - const char *help_long, - void *context, - dsn_cli_handler cmd_handler, - dsn_cli_free_handler output_freer) -{ - auto cnode = ::dsn::task::get_current_node2(); - dassert(cnode != nullptr, "tls_dsn not inited properly"); - auto handle = - dsn_cli_register((std::string(cnode->name()) + "." + command).c_str(), - (std::string(cnode->name()) + "." + command + " " + help_one_line).c_str(), - help_long, - context, - cmd_handler, - output_freer); - dsn::command_manager::instance().set_cli_target_address( - handle, dsn::task::get_current_rpc()->primary_address()); - return handle; -} - -DSN_API void dsn_cli_deregister(dsn_handle_t handle) { dsn::deregister_command(handle); } - namespace dsn { -void deregister_command(dsn_handle_t command_handle) -{ - return command_manager::instance().deregister_command(command_handle); -} - -dsn_handle_t register_command( - const std::vector &commands, // commands, e.g., {"help", "Help", "HELP", "h", "H"} - const char *help_one_line, - const char *help_long, // help info for users - command_handler handler) +dsn_handle_t command_manager::register_app_command(const std::vector &commands, + const std::string &help_one_line, + const std::string &help_long, + command_handler handler) { - return command_manager::instance().register_command( - commands, help_one_line, help_long, handler); -} - -dsn_handle_t register_command(const char *command, // commands, e.g., "help" - const char *help_one_line, - const char *help_long, - command_handler handler) -{ - std::vector cmds; - cmds.push_back(command); - return register_command(cmds, help_one_line, help_long, handler); + dsn_app_info info; + dsn_get_current_app_info(&info); + std::string app_tag = std::string(info.name) + "."; + std::vector commands_with_app_tag; + commands_with_app_tag.reserve(commands.size()); + for (const std::string &c : commands) { + commands_with_app_tag.push_back(app_tag + c); + } + return register_command( + commands_with_app_tag, app_tag + help_one_line, app_tag + help_long, handler); } -dsn_handle_t command_manager::register_command(const std::vector &commands, - const char *help_one_line, - const char *help_long, +dsn_handle_t command_manager::register_command(const std::vector &commands, + const std::string &help_one_line, + const std::string &help_long, command_handler handler) { utils::auto_write_lock l(_lock); - for (auto cmd : commands) { - if (cmd != nullptr) { - auto it = _handlers.find(std::string(cmd)); - dassert(it == _handlers.end(), "command '%s' already regisered", cmd); + for (const std::string &cmd : commands) { + if (!cmd.empty()) { + auto it = _handlers.find(cmd); + dassert(it == _handlers.end(), "command '%s' already regisered", cmd.c_str()); } } - command *c = new command; + command_instance *c = new command_instance(); c->address.set_invalid(); - c->commands.reserve(commands.size()); - for (const auto &item : commands) { - c->commands.emplace_back(std::string(item)); - } + c->commands = commands; c->help_long = help_long; c->help_short = help_one_line; c->handler = handler; _commands.push_back(c); - for (auto cmd : commands) { - if (cmd != nullptr) { - _handlers[std::string(cmd)] = c; + for (const std::string &cmd : commands) { + if (!cmd.empty()) { + _handlers[cmd] = c; } } return c; @@ -175,7 +103,7 @@ dsn_handle_t command_manager::register_command(const std::vector & void command_manager::deregister_command(dsn_handle_t handle) { - auto c = reinterpret_cast(handle); + auto c = reinterpret_cast(handle); dassert(c != nullptr, "cannot deregister a null handle"); utils::auto_write_lock l(_lock); for (const std::string &cmd : c->commands) { @@ -214,7 +142,7 @@ bool command_manager::run_command(const std::string &cmd, const std::vector &args, /*out*/ std::string &output) { - command *h = nullptr; + command_instance *h = nullptr; { utils::auto_read_lock l(_lock); auto it = _handlers.find(cmd); @@ -250,25 +178,6 @@ bool command_manager::run_command(const std::string &cmd, } } -void command_manager::run_console() -{ - std::cout << "dsn cli begin ... (type 'help' + Enter to learn more)" << std::endl; - std::cout << ">"; - - std::string cmdline; - while (std::getline(std::cin, cmdline)) { - std::string result; - run_command(cmdline, result); - std::cout << result << std::endl; - std::cout << ">"; - } -} - -void command_manager::start_local_cli() -{ - new std::thread(std::bind(&command_manager::run_console, this)); -} - void remote_cli_handler(dsn_message_t req, void *) { command_manager::instance().on_remote_cli(req); @@ -295,7 +204,7 @@ void command_manager::on_remote_cli(dsn_message_t req) void command_manager::set_cli_target_address(dsn_handle_t handle, dsn::rpc_address address) { - reinterpret_cast(handle)->address = address; + reinterpret_cast(handle)->address = address; } command_manager::command_manager() diff --git a/src/core/core/command_manager.h b/src/core/core/command_manager.h deleted file mode 100644 index 87264f08ca..0000000000 --- a/src/core/core/command_manager.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Microsoft Corporation - * - * -=- Robust Distributed System Nucleus (rDSN) -=- - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Description: - * What is this file about? - * - * Revision history: - * xxxx-xx-xx, author, first version - * xxxx-xx-xx, author, fix bug about xxx - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace dsn { - -class command_manager : public ::dsn::utils::singleton -{ -public: - command_manager(); - - dsn_handle_t register_command(const std::vector &commands, - const char *help_one_line, - const char *help_long, - command_handler handler); - void deregister_command(dsn_handle_t handle); - bool run_command(const std::string &cmdline, /*out*/ std::string &output); - void run_console(); - void start_local_cli(); - void start_remote_cli(); - void on_remote_cli(dsn_message_t req); - void set_cli_target_address(dsn_handle_t handle, dsn::rpc_address address); - -private: - bool run_command(const std::string &cmd, - const std::vector &args, - /*out*/ std::string &output); - -private: - struct command - { - dsn::rpc_address address; - std::vector commands; - std::string help_short; - std::string help_long; - command_handler handler; - }; - - ::dsn::utils::rw_lock_nr _lock; - std::map _handlers; - std::vector _commands; -}; -} diff --git a/src/core/core/logging.cpp b/src/core/core/logging.cpp index 50368c8325..f72503c9a7 100644 --- a/src/core/core/logging.cpp +++ b/src/core/core/logging.cpp @@ -35,7 +35,7 @@ */ #include -#include +#include #include #include #include "service_engine.h" @@ -71,19 +71,19 @@ void dsn_log_init() } // register command for logging - ::dsn::register_command("flush-log", - "flush-log - flush log to stderr or log file", - "flush-log", - [](const std::vector &args) { - ::dsn::logging_provider *logger = - ::dsn::service_engine::fast_instance().logging(); - if (logger != nullptr) { - logger->flush(); - } - return "Flush done."; - }); - ::dsn::register_command( - "reset-log-start-level", + ::dsn::command_manager::instance().register_command( + {"flush-log"}, + "flush-log - flush log to stderr or log file", + "flush-log", + [](const std::vector &args) { + ::dsn::logging_provider *logger = ::dsn::service_engine::fast_instance().logging(); + if (logger != nullptr) { + logger->flush(); + } + return "Flush done."; + }); + ::dsn::command_manager::instance().register_command( + {"reset-log-start-level"}, "reset-log-start-level - reset the log start level", "reset-log-start-level [INFORMATION | DEBUG | WARNING | ERROR | FATAL]", [](const std::vector &args) { diff --git a/src/core/core/perf_counters.cpp b/src/core/core/perf_counters.cpp index 58c627b64a..9f4d521af6 100644 --- a/src/core/core/perf_counters.cpp +++ b/src/core/core/perf_counters.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include "service_engine.h" @@ -45,20 +45,23 @@ namespace dsn { perf_counters::perf_counters(void) { - ::dsn::register_command("counter.list", - "counter.list - get the list of all counters", - "counter.list", - &perf_counters::list_counter); - - ::dsn::register_command("counter.value", - "counter.value - get current value of a specific counter", - "counter.value app-name*section-name*counter-name", - &perf_counters::get_counter_value); - - ::dsn::register_command("counter.sample", - "counter.sample - get latest sample of a specific counter", - "counter.sample app-name*section-name*counter-name", - &perf_counters::get_counter_sample); + ::dsn::command_manager::instance().register_command( + {"counter.list"}, + "counter.list - get the list of all counters", + "counter.list", + &perf_counters::list_counter); + + ::dsn::command_manager::instance().register_command( + {"counter.value"}, + "counter.value - get current value of a specific counter", + "counter.value app-name*section-name*counter-name", + &perf_counters::get_counter_value); + + ::dsn::command_manager::instance().register_command( + {"counter.sample"}, + "counter.sample - get latest sample of a specific counter", + "counter.sample app-name*section-name*counter-name", + &perf_counters::get_counter_sample); } perf_counters::~perf_counters(void) {} diff --git a/src/core/core/service_api_c.cpp b/src/core/core/service_api_c.cpp index e7a6fec842..cc2a4c695a 100644 --- a/src/core/core/service_api_c.cpp +++ b/src/core/core/service_api_c.cpp @@ -48,7 +48,7 @@ #include #include -#include "command_manager.h" +#include #include "service_engine.h" #include "rpc_engine.h" #include "disk_engine.h" @@ -1383,12 +1383,6 @@ bool run(const char *config_file, exit(1); } - // start cli if necessary - if (dsn_all.config->get_value( - "core", "cli_local", true, "whether to enable local command line interface (cli)")) { - ::dsn::command_manager::instance().start_local_cli(); - } - if (dsn_all.config->get_value( "core", "cli_remote", @@ -1398,23 +1392,24 @@ bool run(const char *config_file, } // register local cli commands - ::dsn::register_command("config-dump", - "config-dump - dump configuration", - "config-dump [to-this-config-file]", - [](const std::vector &args) { - std::ostringstream oss; - std::ofstream off; - std::ostream *os = &oss; - if (args.size() > 0) { - off.open(args[0]); - os = &off; - - oss << "config dump to file " << args[0] << std::endl; - } - - dsn_all.config->dump(*os); - return oss.str(); - }); + ::dsn::command_manager::instance().register_command({"config-dump"}, + "config-dump - dump configuration", + "config-dump [to-this-config-file]", + [](const std::vector &args) { + std::ostringstream oss; + std::ofstream off; + std::ostream *os = &oss; + if (args.size() > 0) { + off.open(args[0]); + os = &off; + + oss << "config dump to file " + << args[0] << std::endl; + } + + dsn_all.config->dump(*os); + return oss.str(); + }); // invoke customized init after apps are created dsn::tools::sys_init_after_app_created.execute(); diff --git a/src/core/core/service_engine.cpp b/src/core/core/service_engine.cpp index 553a3d8d3f..eff2ad8a0b 100644 --- a/src/core/core/service_engine.cpp +++ b/src/core/core/service_engine.cpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include @@ -453,14 +453,15 @@ service_engine::service_engine(void) _logging = nullptr; _memory = nullptr; - ::dsn::register_command("engine", - "engine - get engine internal information", - "engine [app-id]", - &service_engine::get_runtime_info); - ::dsn::register_command("system.queue", - "system.queue - get queue internal information", - "system.queue", - &service_engine::get_queue_info); + ::dsn::command_manager::instance().register_command({"engine"}, + "engine - get engine internal information", + "engine [app-id]", + &service_engine::get_runtime_info); + ::dsn::command_manager::instance().register_command( + {"system.queue"}, + "system.queue - get queue internal information", + "system.queue", + &service_engine::get_queue_info); } void service_engine::init_before_toollets(const service_spec &spec) diff --git a/src/core/core/task_spec.cpp b/src/core/core/task_spec.cpp index 303c6e3dc2..3cc559e134 100644 --- a/src/core/core/task_spec.cpp +++ b/src/core/core/task_spec.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -200,29 +200,30 @@ bool task_spec::init() } } - ::dsn::register_command("task-code", - "task-code - query task code containing any given keywords", - "task-code keyword1 keyword2 ...", - [](const std::vector &args) { - std::stringstream ss; - - for (int code = 0; code <= dsn_task_code_max(); code++) { - if (code == TASK_CODE_INVALID) - continue; - - std::string codes = dsn_task_code_to_string(code); - if (args.size() == 0) { - ss << " " << codes << std::endl; - } else { - for (auto &arg : args) { - if (codes.find(arg.c_str()) != std::string::npos) { - ss << " " << codes << std::endl; - } - } - } - } - return ss.str(); - }); + ::dsn::command_manager::instance().register_command( + {"task-code"}, + "task-code - query task code containing any given keywords", + "task-code keyword1 keyword2 ...", + [](const std::vector &args) { + std::stringstream ss; + + for (int code = 0; code <= dsn_task_code_max(); code++) { + if (code == TASK_CODE_INVALID) + continue; + + std::string codes = dsn_task_code_to_string(code); + if (args.size() == 0) { + ss << " " << codes << std::endl; + } else { + for (auto &arg : args) { + if (codes.find(arg.c_str()) != std::string::npos) { + ss << " " << codes << std::endl; + } + } + } + } + return ss.str(); + }); return true; } diff --git a/src/core/tests/command_manager.cpp b/src/core/tests/command_manager.cpp index 2886724499..dddce3760e 100644 --- a/src/core/tests/command_manager.cpp +++ b/src/core/tests/command_manager.cpp @@ -34,27 +34,28 @@ */ #include -#include +#include #include using namespace ::dsn; void command_manager_module_init() { - register_command("test-cmd", - "test-cmd - just for command_manager unit-test", - "test-cmd arg1 arg2 ...", - [](const std::vector &args) { - std::stringstream ss; - ss << "test-cmd response: ["; - for (size_t i = 0; i < args.size(); ++i) { - if (i != 0) - ss << " "; - ss << args[i]; - } - ss << "]"; - return ss.str(); - }); + dsn::command_manager::instance().register_command( + {"test-cmd"}, + "test-cmd - just for command_manager unit-test", + "test-cmd arg1 arg2 ...", + [](const std::vector &args) { + std::stringstream ss; + ss << "test-cmd response: ["; + for (size_t i = 0; i < args.size(); ++i) { + if (i != 0) + ss << " "; + ss << args[i]; + } + ss << "]"; + return ss.str(); + }); } /* diff --git a/src/core/tests/hpc_io_looper.cpp b/src/core/tests/hpc_io_looper.cpp index 8bb27711ba..b885b3ffc9 100644 --- a/src/core/tests/hpc_io_looper.cpp +++ b/src/core/tests/hpc_io_looper.cpp @@ -43,8 +43,8 @@ #include #include #include +#include #include "../core/group_address.h" -#include "../core/command_manager.h" #include "../core/service_engine.h" #include "test_utils.h" #include "../tools/hpc/io_looper.h" diff --git a/src/core/tests/hpc_tail_logger.cpp b/src/core/tests/hpc_tail_logger.cpp index 8522c88be0..e1a909018d 100644 --- a/src/core/tests/hpc_tail_logger.cpp +++ b/src/core/tests/hpc_tail_logger.cpp @@ -42,8 +42,9 @@ #include #include #include +#include + #include "../core/group_address.h" -#include "../core/command_manager.h" #include "test_utils.h" #include "../core/service_engine.h" #include "../tools/hpc/hpc_tail_logger.h" diff --git a/src/core/tools/common/explorer.cpp b/src/core/tools/common/explorer.cpp index 1b5f53a2c9..743e967d7b 100644 --- a/src/core/tools/common/explorer.cpp +++ b/src/core/tools/common/explorer.cpp @@ -36,7 +36,7 @@ #include #include -#include +#include namespace dsn { namespace tools { @@ -450,7 +450,7 @@ void explorer::install(service_spec &spec) message_ext_for_explorer::register_ext(); task_ext_for_explorer::register_ext(); - ::dsn::register_command({"explore", "exp"}, + ::dsn::command_manager::instance().register_command({"explore", "exp"}, "explore the task dependencies as GraphViz dot graph", "explore the task dependencies as GraphViz dot graph", [](const std::vector &args) { diff --git a/src/core/tools/common/profiler.cpp b/src/core/tools/common/profiler.cpp index 22ba75007c..9bcb0f7737 100644 --- a/src/core/tools/common/profiler.cpp +++ b/src/core/tools/common/profiler.cpp @@ -67,7 +67,7 @@ START<== queue(server) == ENQUEUE <===== net(reply) ======= REPLY <============= #include #include "shared_io_service.h" #include "profiler_header.h" -#include +#include #include #ifdef __TITLE__ @@ -389,19 +389,20 @@ void register_command_profiler() textpd << textarg.str(); textquery << textarg.str(); - register_command({"p", "P", "profile", "Profile"}, - "profile|Profile|p|P - performance profiling", - textp.str().c_str(), - profiler_output_handler); - - register_command({"pd", "PD", "profiledata", "ProfileData"}, - "profiler data - get appointed data, using by pjs", - textpd.str().c_str(), - profiler_data_handler); - register_command({"profiler.query", "pq"}, - "profiler.query|pq - query profiling data, output in json format", - textquery.str().c_str(), - query_data_handler); + command_manager::instance().register_command({"p", "P", "profile", "Profile"}, + "profile|Profile|p|P - performance profiling", + textp.str().c_str(), + profiler_output_handler); + + command_manager::instance().register_command({"pd", "PD", "profiledata", "ProfileData"}, + "profiler data - get appointed data, using by pjs", + textpd.str().c_str(), + profiler_data_handler); + command_manager::instance().register_command( + {"profiler.query", "pq"}, + "profiler.query|pq - query profiling data, output in json format", + textquery.str().c_str(), + query_data_handler); } void profiler::install(service_spec &spec) diff --git a/src/core/tools/common/tracer.cpp b/src/core/tools/common/tracer.cpp index 5736735915..5896cf143d 100644 --- a/src/core/tools/common/tracer.cpp +++ b/src/core/tools/common/tracer.cpp @@ -34,7 +34,7 @@ */ #include -#include +#include #ifdef __TITLE__ #undef __TITLE__ @@ -397,11 +397,12 @@ void tracer::install(service_spec &spec) spec->on_rpc_create_response.put_back(tracer_on_rpc_create_response, "tracer"); } - register_command({"tracer.find"}, - "tracer.find - find related logs", - "tracer.find forward|f|backward|b rpc|r|task|t trace_id|task_id(e.g., " - "a023003920302390) log_file_name(log.xx.txt)", - tracer_log_flow); + command_manager::instance().register_command( + {"tracer.find"}, + "tracer.find - find related logs", + "tracer.find forward|f|backward|b rpc|r|task|t trace_id|task_id(e.g., " + "a023003920302390) log_file_name(log.xx.txt)", + tracer_log_flow); } tracer::tracer(const char *name) : toollet(name) {} diff --git a/src/core/tools/hpc/hpc_logger.cpp b/src/core/tools/hpc/hpc_logger.cpp index 9790c427fc..b2958925a9 100644 --- a/src/core/tools/hpc/hpc_logger.cpp +++ b/src/core/tools/hpc/hpc_logger.cpp @@ -98,7 +98,7 @@ of each thread and buffers in the buffer list. #include "hpc_logger.h" #include #include -#include +#include #include #include #include diff --git a/src/core/tools/hpc/hpc_tail_logger.cpp b/src/core/tools/hpc/hpc_tail_logger.cpp index 4c1be86b5c..d3dc4388c5 100644 --- a/src/core/tools/hpc/hpc_tail_logger.cpp +++ b/src/core/tools/hpc/hpc_tail_logger.cpp @@ -36,7 +36,7 @@ #include "hpc_tail_logger.h" #include #include -#include +#include #include #include #include @@ -84,8 +84,8 @@ hpc_tail_logger::hpc_tail_logger(const char *log_dir) : logging_provider(log_dir register_it = true; // register command for tail logging - ::dsn::register_command( - "tail-log", + ::dsn::command_manager::instance().register_command( + {"tail-log"}, "tail-log keyword back-seconds [back-start-seconds = 0] [tid1,tid2,...]", "tail-log find logs with given keyword and within [now - back-seconds, now - " "back-start-seconds]", @@ -109,8 +109,8 @@ hpc_tail_logger::hpc_tail_logger(const char *log_dir) : logging_provider(log_dir } }); - ::dsn::register_command( - "tail-log-dump", + ::dsn::command_manager::instance().register_command( + {"tail-log-dump"}, "tail-log-dump", "tail-log-dump dump all tail logs to log files", [this](const std::vector &args) { diff --git a/src/dist/replication/lib/replica_stub.cpp b/src/dist/replication/lib/replica_stub.cpp index 48c9d61db2..1ddffd9329 100644 --- a/src/dist/replication/lib/replica_stub.cpp +++ b/src/dist/replication/lib/replica_stub.cpp @@ -38,7 +38,7 @@ #include "mutation_log.h" #include "mutation.h" #include -#include +#include #include #include #include @@ -59,7 +59,11 @@ replica_stub::replica_stub(replica_state_subscriber subscriber /*= nullptr*/, bool is_long_subscriber /* = true*/) : serverlet("replica_stub"), _replicas_lock(true), - /*_cli_replica_stub_json_state_handle(nullptr), */ _cli_kill_partition(nullptr), + _kill_partition_command(nullptr), + _deny_client_command(nullptr), + _verbose_client_log_command(nullptr), + _verbose_commit_log_command(nullptr), + _trigger_chkpt_command(nullptr), _deny_client(false), _verbose_client_log(false), _verbose_commit_log(false), @@ -606,29 +610,17 @@ void replica_stub::initialize_start() } } -void replica_stub::on_kill_app_cli(void *context, int argc, const char **argv, dsn_cli_reply *reply) +dsn::error_code replica_stub::on_kill_replica(gpid pid) { error_code err = ERR_INVALID_PARAMETERS; - if (argc >= 2) { - gpid gpid; - gpid.set_app_id(atoi(argv[0])); - gpid.set_partition_index(atoi(argv[1])); - - replica_ptr r = get_replica(gpid); - if (r == nullptr) { - err = ERR_OBJECT_NOT_FOUND; - } else { - r->inject_error(ERR_INJECTED); - err = ERR_OK; - } + replica_ptr r = get_replica(pid); + if (r == nullptr) { + err = ERR_OBJECT_NOT_FOUND; + } else { + r->inject_error(ERR_INJECTED); + err = ERR_OK; } - - std::string *resp_json = new std::string(); - *resp_json = err.to_string(); - reply->context = resp_json; - reply->message = (const char *)resp_json->c_str(); - reply->size = resp_json->size(); - return; + return err; } replica_ptr replica_stub::get_replica(gpid gpid, bool new_when_possible, const app_info *app) @@ -997,39 +989,6 @@ void replica_stub::on_remove(const replica_configuration &request) rep->on_remove(request); } } -// -// void replica_stub::json_state(std::stringstream& out) const -//{ -// std::vector replicas_copy; -// { -// zauto_lock _(_replicas_lock); -// for (auto& rep : _replicas) -// { -// replicas_copy.push_back(rep.second); -// } -// } -// json_encode(out, replicas_copy); -//} -// -// void replica_stub::static_replica_stub_json_state(void* context, int argc, const char** argv, -// dsn_cli_reply* reply) -//{ -// auto stub = reinterpret_cast(context); -// std::stringstream ss; -// stub->json_state(ss); -// auto danglingstr = new std::string(std::move(ss.str())); -// reply->message = danglingstr->c_str(); -// reply->size = danglingstr->size(); -// reply->context = danglingstr; -//} - -void replica_stub::static_replica_stub_json_state_freer(dsn_cli_reply reply) -{ - dassert(reply.context != nullptr, "corrupted cli reply"); - auto danglingstr = reinterpret_cast(reply.context); - dassert(danglingstr->c_str() == reply.message, "corrupted cli reply"); - delete danglingstr; -} void replica_stub::get_replica_info(replica_info &info, replica_ptr r) { @@ -1880,148 +1839,69 @@ void replica_stub::open_service() RPC_REPLICA_COPY_LAST_CHECKPOINT, "copy_checkpoint", &replica_stub::on_copy_checkpoint); register_rpc_handler(RPC_QUERY_APP_INFO, "query_app_info", &replica_stub::on_query_app_info); - register_rpc_handler(RPC_COLD_BACKUP, "ColdBackup", &replica_stub::on_cold_backup); - /*_cli_replica_stub_json_state_handle = dsn_cli_app_register("info", "get the info of - replica_stub on this node", "", - this, &static_replica_stub_json_state, &static_replica_stub_json_state_freer); - dassert(_cli_replica_stub_json_state_handle != nullptr, "register cli command failed");*/ - - _cli_kill_partition = - dsn_cli_app_register("kill_partition", - "kill partition with its global partition id", - "kill_partition app_id partition_index", - (void *)this, - [](void *context, int argc, const char **argv, dsn_cli_reply *reply) { - auto this_ = (replica_stub *)context; - this_->on_kill_app_cli(context, argc, argv, reply); - }, - [](dsn_cli_reply reply) { - std::string *s = (std::string *)reply.context; - delete s; - }); - - dsn_app_info info; - dsn_get_current_app_info(&info); - { - std::string command(info.name); - command += ".deny-client"; - std::string help1(command); - help1 += " - control if deny client read & write request"; - std::string help2(command); - help1 += " "; - ::dsn::register_command(command.c_str(), - help1.c_str(), - help2.c_str(), - [this](const std::vector &args) { - if (args.empty()) { - return _deny_client ? "true" : "false"; - } - std::string arg = args[0]; - if (arg != "true" && arg != "false") { - return "ERROR: invalid arguments"; - } - if (arg == "true") { - _deny_client = true; - } else { - _deny_client = false; - } - ddebug("set deny_client to %s by remote command", - _deny_client ? "true" : "false"); - return "OK"; - }); - } - { - std::string command(info.name); - command += ".verbose-client-log"; - std::string help1(command); - help1 += " - control if print verbose error log when reply read & write request"; - std::string help2(command); - help1 += " "; - ::dsn::register_command(command.c_str(), - help1.c_str(), - help2.c_str(), - [this](const std::vector &args) { - if (args.empty()) { - return _verbose_client_log ? "true" : "false"; - } - std::string arg = args[0]; - if (arg != "true" && arg != "false") { - return "ERROR: invalid arguments"; - } - if (arg == "true") { - _verbose_client_log = true; - } else { - _verbose_client_log = false; - } - ddebug("set verbose_client_log to %s by remote command", - _verbose_client_log ? "true" : "false"); - return "OK"; - }); - } - { - std::string command(info.name); - command += ".verbose-commit-log"; - std::string help1(command); - help1 += " - control if print verbose log when commit mutation"; - std::string help2(command); - help1 += " "; - ::dsn::register_command(command.c_str(), - help1.c_str(), - help2.c_str(), - [this](const std::vector &args) { - if (args.empty()) { - return _verbose_commit_log ? "true" : "false"; - } - std::string arg = args[0]; - if (arg != "true" && arg != "false") { - return "ERROR: invalid arguments"; - } - if (arg == "true") { - _verbose_commit_log = true; - } else { - _verbose_commit_log = false; - } - ddebug("set verbose_commit_log to %s by remote command", - _verbose_commit_log ? "true" : "false"); - return "OK"; - }); - } - { - std::string command(info.name); - command += ".trigger-checkpoint"; - std::string help1(command); - help1 += " - trigger all replicas to do checkpoint"; - std::string help2(command); - help1 += ""; - ::dsn::register_command( - command.c_str(), - help1.c_str(), - help2.c_str(), - [this](const std::vector &args) { - ddebug("start to trigger checkpoint by remote command"); - - replicas rs; - { - zauto_lock l(_replicas_lock); - rs = _replicas; - } + _kill_partition_command = ::dsn::command_manager::instance().register_app_command( + {"kill_partition"}, + "kill_partition ", + "kill_partition: kill partition with its global partition id", + [this](const std::vector &args) { + if (args.size() != 2) + return std::string(ERR_INVALID_PARAMETERS.to_string()); + dsn::gpid pid; + pid.set_app_id(atoi(args[0].c_str())); + pid.set_partition_index(atoi(args[1].c_str())); + if (pid.get_app_id() <= 0 || pid.get_partition_index() < 0) + return std::string(ERR_INVALID_PARAMETERS.to_string()); + dsn::error_code e = this->on_kill_replica(pid); + return std::string(e.to_string()); + }); - for (auto it = rs.begin(); it != rs.end(); ++it) { - tasking::enqueue( - LPC_PER_REPLICA_CHECKPOINT_TIMER, - this, - std::bind(&replica_stub::trigger_checkpoint, this, it->second, true), - gpid_to_thread_hash(it->first), - std::chrono::milliseconds( - dsn_random32(0, 3000)) // delay random to avoid write compete - ); - } + _deny_client_command = ::dsn::command_manager::instance().register_app_command( + {"deny-client"}, + "deny-client ", + "deny-client - control if deny client read & write request", + [this](const std::vector &args) { HANDLE_CLI_FLAGS(_deny_client, args); }); + + _verbose_client_log_command = ::dsn::command_manager::instance().register_app_command( + {"verbose-client-log"}, + "verbose-client-log ", + "verbose-client-log - control if print verbose error log when reply read & write request", + [this](const std::vector &args) { + HANDLE_CLI_FLAGS(_verbose_client_log, args); + }); - return "OK"; - }); - } + _verbose_commit_log_command = ::dsn::command_manager::instance().register_app_command( + {"verbose-commit-log"}, + "verbose-commit-log ", + "verbose-commit-log - control if print verbose log when commit mutation", + [this](const std::vector &args) { + HANDLE_CLI_FLAGS(_verbose_commit_log, args); + }); + + _trigger_chkpt_command = ::dsn::command_manager::instance().register_app_command( + {"trigger-checkpoint"}, + "trigger-checkpoint", + "trigger-checkpoint - trigger all replicas to do checkpoints", + [this](const std::vector &args) { + ddebug("start to trigger checkpoint by remote command"); + replicas rs; + { + zauto_lock l(_replicas_lock); + rs = _replicas; + } + for (auto it = rs.begin(); it != rs.end(); ++it) { + tasking::enqueue( + LPC_PER_REPLICA_CHECKPOINT_TIMER, + this, + std::bind(&replica_stub::trigger_checkpoint, this, it->second, true), + gpid_to_thread_hash(it->first), + std::chrono::milliseconds( + dsn_random32(0, 3000)) // delay random to avoid write compete + ); + } + return "OK"; + }); } void replica_stub::close() @@ -2029,14 +1909,21 @@ void replica_stub::close() // this replica may not be opened // or is already closed by calling tool_app::stop_all_apps() // in this case, just return - if (_cli_kill_partition == nullptr) { + if (_kill_partition_command == nullptr) { return; } - // dsn_cli_deregister(_cli_replica_stub_json_state_handle); - dsn_cli_deregister(_cli_kill_partition); - //_cli_replica_stub_json_state_handle = nullptr; - _cli_kill_partition = nullptr; + dsn::command_manager::instance().deregister_command(_kill_partition_command); + dsn::command_manager::instance().deregister_command(_deny_client_command); + dsn::command_manager::instance().deregister_command(_verbose_client_log_command); + dsn::command_manager::instance().deregister_command(_verbose_commit_log_command); + dsn::command_manager::instance().deregister_command(_trigger_chkpt_command); + + _kill_partition_command = nullptr; + _deny_client_command = nullptr; + _verbose_client_log_command = nullptr; + _verbose_commit_log_command = nullptr; + _trigger_chkpt_command = nullptr; if (_config_sync_timer_task != nullptr) { _config_sync_timer_task->cancel(true); diff --git a/src/dist/replication/lib/replica_stub.h b/src/dist/replication/lib/replica_stub.h index 62a380acb1..7b92fd7cf8 100644 --- a/src/dist/replication/lib/replica_stub.h +++ b/src/dist/replication/lib/replica_stub.h @@ -143,12 +143,6 @@ class replica_stub : public serverlet, public ref_counter replication_options &options() { return _options; } bool is_connected() const { return NS_Connected == _state; } - // void json_state(std::stringstream& out) const; - - // static void static_replica_stub_json_state(void* context, int argc, const char** argv, - // dsn_cli_reply* reply); - static void static_replica_stub_json_state_freer(dsn_cli_reply reply); - std::string get_replica_dir(const char *app_type, gpid gpid, bool create_new = true); private: @@ -193,7 +187,7 @@ class replica_stub : public serverlet, public ref_counter void handle_log_failure(error_code err); void install_perf_counters(); - void on_kill_app_cli(void *context, int argc, const char **argv, dsn_cli_reply *reply); + dsn::error_code on_kill_replica(gpid pid); void get_replica_info(/*out*/ replica_info &info, /*in*/ replica_ptr r); void get_local_replicas(/*out*/ std::vector &replicas, bool lock_protected); @@ -234,9 +228,13 @@ class replica_stub : public serverlet, public ref_counter ::dsn::task_ptr _gc_timer_task; ::dsn::task_ptr _disk_stat_timer_task; - // cli handle, for deregister cli command - // dsn_handle_t _cli_replica_stub_json_state_handle; - dsn_handle_t _cli_kill_partition; + // command_handlers + dsn_handle_t _kill_partition_command; + dsn_handle_t _deny_client_command; + dsn_handle_t _verbose_client_log_command; + dsn_handle_t _verbose_commit_log_command; + dsn_handle_t _trigger_chkpt_command; + bool _deny_client; bool _verbose_client_log; bool _verbose_commit_log; diff --git a/src/dist/replication/meta_server/greedy_load_balancer.cpp b/src/dist/replication/meta_server/greedy_load_balancer.cpp index 953ccf1d21..4f08949302 100644 --- a/src/dist/replication/meta_server/greedy_load_balancer.cpp +++ b/src/dist/replication/meta_server/greedy_load_balancer.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "greedy_load_balancer.h" #include "meta_data.h" @@ -67,53 +68,9 @@ greedy_load_balancer::greedy_load_balancer(meta_service *_svc) greedy_load_balancer::~greedy_load_balancer() { - unregister_helper(_ctrl_balancer_in_turn); - unregister_helper(_ctrl_only_move_primary); - unregister_helper(_ctrl_only_move_primary); -} - -static void free_string_in_cli_reply(dsn_cli_reply reply) -{ - std::string *s = reinterpret_cast(reply.context); - delete s; -} - -#define HANDLE_CLI_FLAGS(flag, argc, argv, reply) \ - do { \ - std::string *ret_msg = new std::string("OK"); \ - if (argc <= 0) { \ - *ret_msg = flag ? "true" : "false"; \ - } else { \ - if (strcmp(argv[0], "true") == 0) { \ - flag = true; \ - ddebug("set " #flag " to true by remote command"); \ - } else if (strcmp(argv[0], "false") == 0) { \ - flag = false; \ - ddebug("set " #flag " to false by remote command"); \ - } else { \ - *ret_msg = "ERR: invalid arguments"; \ - } \ - } \ - reply->context = ret_msg; \ - reply->message = (const char *)ret_msg->c_str(); \ - reply->size = ret_msg->size(); \ - } while (0) - -void greedy_load_balancer::ctrl_balancer_in_turn(int argc, const char **argv, dsn_cli_reply *reply) -{ - HANDLE_CLI_FLAGS(_balancer_in_turn, argc, argv, reply); -} - -void greedy_load_balancer::ctrl_only_move_primary(int argc, const char **argv, dsn_cli_reply *reply) -{ - HANDLE_CLI_FLAGS(_only_move_primary, argc, argv, reply); -} - -void greedy_load_balancer::ctrl_only_primary_balancer(int argc, - const char **argv, - dsn_cli_reply *reply) -{ - HANDLE_CLI_FLAGS(_only_primary_balancer, argc, argv, reply); + UNREGISTER_VALID_HANDLER(_ctrl_balancer_in_turn); + UNREGISTER_VALID_HANDLER(_ctrl_only_move_primary); + UNREGISTER_VALID_HANDLER(_ctrl_only_move_primary); } void greedy_load_balancer::register_ctrl_commands() @@ -121,48 +78,36 @@ void greedy_load_balancer::register_ctrl_commands() // register command that belong to simple_load_balancer simple_load_balancer::register_ctrl_commands(); - _ctrl_balancer_in_turn = - dsn_cli_app_register("lb.balancer_in_turn", - "control whether do app balancer in turn", - "lb.balancer_in_turn ", - (void *)this, - [](void *context, int argc, const char **argv, dsn_cli_reply *reply) { - greedy_load_balancer *lb = - reinterpret_cast(context); - lb->ctrl_balancer_in_turn(argc, argv, reply); - }, - free_string_in_cli_reply); - - _ctrl_only_primary_balancer = - dsn_cli_app_register("lb.only_primary_balancer", - "control whether do only primary balancer", - "lb.only_primary_balancer ", - (void *)this, - [](void *context, int argc, const char **argv, dsn_cli_reply *reply) { - greedy_load_balancer *lb = - reinterpret_cast(context); - lb->ctrl_only_primary_balancer(argc, argv, reply); - }, - free_string_in_cli_reply); - - _ctrl_only_move_primary = - dsn_cli_app_register("lb.only_move_primary", - "control whether only move primary in balancer", - "lb.only_move_primary ", - (void *)this, - [](void *context, int argc, const char **argv, dsn_cli_reply *reply) { - greedy_load_balancer *lb = - reinterpret_cast(context); - lb->ctrl_only_move_primary(argc, argv, reply); - }, - free_string_in_cli_reply); + _ctrl_balancer_in_turn = dsn::command_manager::instance().register_app_command( + {"lb.balancer_in_turn"}, + "control whether do app balancer in turn", + "lb.balancer_in_turn ", + [this](const std::vector &args) { + HANDLE_CLI_FLAGS(_balancer_in_turn, args); + }); + + _ctrl_only_primary_balancer = dsn::command_manager::instance().register_app_command( + {"lb.only_primary_balancer"}, + "control whether do only primary balancer", + "lb.only_primary_balancer ", + [this](const std::vector &args) { + HANDLE_CLI_FLAGS(_only_primary_balancer, args); + }); + + _ctrl_only_move_primary = dsn::command_manager::instance().register_app_command( + {"lb.only_move_primary"}, + "control whether only move primary in balancer", + "lb.only_move_primary ", + [this](const std::vector &args) { + HANDLE_CLI_FLAGS(_only_move_primary, args); + }); } void greedy_load_balancer::unregister_ctrl_commands() { - unregister_helper(_ctrl_balancer_in_turn); - unregister_helper(_ctrl_only_move_primary); - unregister_helper(_ctrl_only_move_primary); + UNREGISTER_VALID_HANDLER(_ctrl_balancer_in_turn); + UNREGISTER_VALID_HANDLER(_ctrl_only_move_primary); + UNREGISTER_VALID_HANDLER(_ctrl_only_move_primary); simple_load_balancer::unregister_ctrl_commands(); } diff --git a/src/dist/replication/meta_server/greedy_load_balancer.h b/src/dist/replication/meta_server/greedy_load_balancer.h index 758e42d6a3..1054e0d650 100644 --- a/src/dist/replication/meta_server/greedy_load_balancer.h +++ b/src/dist/replication/meta_server/greedy_load_balancer.h @@ -82,10 +82,6 @@ class greedy_load_balancer : public simple_load_balancer dsn_handle_t _ctrl_only_move_primary; private: - void ctrl_balancer_in_turn(int argc, const char **argv, dsn_cli_reply *reply); - void ctrl_only_primary_balancer(int argc, const char **argv, dsn_cli_reply *reply); - void ctrl_only_move_primary(int argc, const char **argv, dsn_cli_reply *reply); - void number_nodes(const node_mapper &nodes); void shortest_path(std::vector &visit, std::vector &flow, diff --git a/src/dist/replication/meta_server/meta_service.cpp b/src/dist/replication/meta_server/meta_service.cpp index fb05a25503..7ce1464194 100644 --- a/src/dist/replication/meta_server/meta_service.cpp +++ b/src/dist/replication/meta_server/meta_service.cpp @@ -38,7 +38,7 @@ #include #include -#include +#include #include // for std::remove_if #include // for ::isspace diff --git a/src/dist/replication/meta_server/server_load_balancer.cpp b/src/dist/replication/meta_server/server_load_balancer.cpp index 4f28149df1..ab6bad28d9 100644 --- a/src/dist/replication/meta_server/server_load_balancer.cpp +++ b/src/dist/replication/meta_server/server_load_balancer.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "server_load_balancer.h" @@ -750,56 +751,42 @@ pc_status simple_load_balancer::on_redundant_secondary(meta_view &view, const ds return pc_status::ill; } -static void free_string_in_cli_reply(dsn_cli_reply reply) -{ - std::string *s = reinterpret_cast(reply.context); - delete s; -} - void simple_load_balancer::register_ctrl_commands() { server_load_balancer::register_ctrl_commands(); - _ctrl_assign_delay_ms = - dsn_cli_app_register("lb.assign_delay_ms", - "control the replica_assign_delay_ms_for_dropouts config", - "lb.assign_delay_ms [num | DEFAULT]", - (void *)this, - [](void *context, int argc, const char **argv, dsn_cli_reply *reply) { - simple_load_balancer *lb = - reinterpret_cast(context); - lb->ctrl_assign_delay_ms(argc, argv, reply); - }, - free_string_in_cli_reply); + _ctrl_assign_delay_ms = dsn::command_manager::instance().register_app_command( + {"lb.assign_delay_ms"}, + "control the replica_assign_delay_ms_for_dropouts config", + "lb.assign_delay_ms [num | DEFAULT]", + [this](const std::vector &args) { return ctrl_assign_delay_ms(args); }); } void simple_load_balancer::unregister_ctrl_commands() { - unregister_helper(_ctrl_assign_delay_ms); + UNREGISTER_VALID_HANDLER(_ctrl_assign_delay_ms); server_load_balancer::unregister_ctrl_commands(); } -void simple_load_balancer::ctrl_assign_delay_ms(int argc, const char **argv, dsn_cli_reply *reply) +std::string simple_load_balancer::ctrl_assign_delay_ms(const std::vector &args) { - std::string *ret_msg = new std::string("OK"); - if (argc <= 0) { - *ret_msg = boost::lexical_cast(replica_assign_delay_ms_for_dropouts); + std::string result("OK"); + if (args.size() <= 0) { + result = std::to_string(replica_assign_delay_ms_for_dropouts); } else { - if (strcmp(argv[0], "DEFAULT") == 0) { + if (args[0] == "DEFAULT") { replica_assign_delay_ms_for_dropouts = _svc->get_meta_options()._lb_opts.replica_assign_delay_ms_for_dropouts; } else { - int v = atoi(argv[0]); + int v = atoi(args[0].c_str()); if (v <= 0) { - *ret_msg = "ERR: invalid arguments"; + result = std::string("ERR: invalid arguments"); } else { replica_assign_delay_ms_for_dropouts = v; } } } - reply->context = ret_msg; - reply->message = (const char *)ret_msg->c_str(); - reply->size = ret_msg->size(); + return result; } pc_status simple_load_balancer::cure(meta_view view, diff --git a/src/dist/replication/meta_server/server_load_balancer.h b/src/dist/replication/meta_server/server_load_balancer.h index 651a116fb6..4898661ab3 100644 --- a/src/dist/replication/meta_server/server_load_balancer.h +++ b/src/dist/replication/meta_server/server_load_balancer.h @@ -37,6 +37,7 @@ #pragma once #include +#include #include #include #include @@ -48,14 +49,6 @@ namespace dsn { namespace replication { -#define unregister_helper(ptr) \ - do { \ - if (ptr != nullptr) { \ - dsn_cli_deregister(ptr); \ - ptr = nullptr; \ - } \ - } while (0) - class server_load_balancer { public: @@ -100,7 +93,8 @@ class server_load_balancer // Try to construct a replica-group by current replica-infos of a gpid // ret: // if construct the replica successfully, return true. - // Notice: as long as we can construct something from current infos, we treat it as a success + // Notice: as long as we can construct something from current infos, we treat it as a + // success // virtual bool construct_replica(meta_view view, const gpid &pid, int max_replica_count) = 0; @@ -112,8 +106,10 @@ class server_load_balancer // // Try to register some cli-commands // - // ATTENTION: because this function will register the cli-commands to singleton-container, so - // you must unregister the commands that you have already registered or release the instance of + // ATTENTION: because this function will register the cli-commands to singleton-container, + // so + // you must unregister the commands that you have already registered or release the instance + // of // server_load_balancer before you call this function again // virtual void register_ctrl_commands() {} @@ -199,7 +195,7 @@ class simple_load_balancer : public server_load_balancer replica_assign_delay_ms_for_dropouts = 0; } } - virtual ~simple_load_balancer() { unregister_helper(_ctrl_assign_delay_ms); } + virtual ~simple_load_balancer() { UNREGISTER_VALID_HANDLER(_ctrl_assign_delay_ms); } bool balance(meta_view, migration_list &list) override { @@ -237,7 +233,7 @@ class simple_load_balancer : public server_load_balancer pc_status on_missing_secondary(meta_view &view, const dsn::gpid &gpid); pc_status on_redundant_secondary(meta_view &view, const dsn::gpid &gpid); - void ctrl_assign_delay_ms(int argc, const char **argv, dsn_cli_reply *reply); + std::string ctrl_assign_delay_ms(const std::vector &args); int32_t mutation_2pc_min_replica_count; uint64_t replica_assign_delay_ms_for_dropouts; diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 79b5e34c56..3ec581a08d 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -62,40 +62,41 @@ namespace replication { static const char *lock_state = "lock"; static const char *unlock_state = "unlock"; -server_state::server_state() - : _meta_svc(nullptr), _cli_json_state_handle(nullptr), _cli_dump_handle(nullptr) -{ -} +server_state::server_state() : _meta_svc(nullptr), _cli_dump_handle(nullptr) {} server_state::~server_state() { - if (_cli_json_state_handle != nullptr) { - dsn_cli_deregister(_cli_json_state_handle); - _cli_json_state_handle = nullptr; - } if (_cli_dump_handle != nullptr) { - dsn_cli_deregister(_cli_dump_handle); + dsn::command_manager::instance().deregister_command(_cli_dump_handle); _cli_dump_handle = nullptr; } } void server_state::register_cli_commands() { - _cli_json_state_handle = dsn_cli_app_register("info", - "get info of nodes and apps on meta_server", - "", - this, - &static_cli_json_state, - &static_cli_json_state_cleanup); - dassert(_cli_json_state_handle != nullptr, - "register cil handler failed, maybe it has been registered"); - - _cli_dump_handle = dsn_cli_app_register("dump", - "dump app_states of meta server to local file", - "usage: -t|--target target_file", - this, - &static_cli_dump_app_states, - &static_cli_dump_app_states_cleanup); + _cli_dump_handle = dsn::command_manager::instance().register_app_command( + {"dump"}, + "dump: dump app_states of meta server to local file", + "dump -t|--target target_file", + [this](const std::vector &args) { + dsn::error_code err; + if (args.size() != 2) { + err = ERR_INVALID_PARAMETERS; + } else { + const char *target_file = nullptr; + for (int i = 0; i < args.size(); i += 2) { + if (strcmp(args[i].c_str(), "-t") == 0 || + strcmp(args[i].c_str(), "--target") == 0) + target_file = args[i + 1].c_str(); + } + if (target_file == nullptr) { + err = ERR_INVALID_PARAMETERS; + } else { + err = this->dump_from_remote_storage(target_file, false); + } + } + return std::string(err.to_string()); + }); dassert(_cli_dump_handle != nullptr, "register cli handler failed"); } @@ -2473,71 +2474,6 @@ void server_state::check_consistency(const dsn::gpid &gpid) } } -void server_state::json_state(std::stringstream &out) const -{ - zauto_read_lock _(_lock); - // JSON_ENCODE_ENTRIES(out, *this, _nodes, _exist_apps); -} - -void server_state::static_cli_json_state(void *context, - int argc, - const char **argv, - dsn_cli_reply *reply) -{ - auto _server_state = reinterpret_cast(context); - std::stringstream out; - _server_state->json_state(out); - auto danglingstring = new std::string(std::move(out.str())); - reply->message = danglingstring->c_str(); - reply->size = danglingstring->size(); - reply->context = danglingstring; -} - -void server_state::static_cli_json_state_cleanup(dsn_cli_reply reply) -{ - dassert(reply.context != nullptr, "corrupted cli reply context"); - auto danglingstring = reinterpret_cast(reply.context); - dassert(reply.message == danglingstring->c_str(), "corrupted cli reply message"); - delete danglingstring; -} - -void server_state::static_cli_dump_app_states(void *context, - int argc, - const char **argv, - dsn_cli_reply *reply) -{ - server_state *_this = reinterpret_cast(context); - std::string *dump_result; - if (argc != 4) { - dump_result = new std::string("invalid command parameter"); - } else { - const char *target_file = nullptr; - for (int i = 0; i < argc; i += 2) { - if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--target") == 0) - target_file = argv[i + 1]; - } - - if (target_file == nullptr) { - dump_result = new std::string("invalid command parameter"); - } else { - error_code ec = _this->dump_from_remote_storage(target_file, false); - dump_result = new std::string("execute result: "); - dump_result->append(ec.to_string()); - } - } - - reply->message = dump_result->c_str(); - reply->size = dump_result->size(); - reply->context = dump_result; -} - -void server_state::static_cli_dump_app_states_cleanup(dsn_cli_reply reply) -{ - dassert(reply.context != nullptr, "corrupted cli context"); - std::string *dump_result = reinterpret_cast(reply.context); - delete dump_result; -} - void server_state::lock_read(zauto_read_lock &other) { zauto_read_lock l(_lock); diff --git a/src/dist/replication/meta_server/server_state.h b/src/dist/replication/meta_server/server_state.h index ddd096a9ff..67f49fc006 100644 --- a/src/dist/replication/meta_server/server_state.h +++ b/src/dist/replication/meta_server/server_state.h @@ -302,7 +302,6 @@ class server_state config_change_subscriber _config_change_subscriber; replica_migration_subscriber _replica_migration_subscriber; - dsn_handle_t _cli_json_state_handle; dsn_handle_t _cli_dump_handle; perf_counter_wrapper _dead_partition_count; @@ -313,16 +312,6 @@ class server_state perf_counter_wrapper _recent_update_config_count; perf_counter_wrapper _recent_partition_change_unwritable_count; perf_counter_wrapper _recent_partition_change_writable_count; - -public: - void json_state(std::stringstream &out) const; - static void - static_cli_json_state(void *context, int argc, const char **argv, dsn_cli_reply *reply); - static void static_cli_json_state_cleanup(dsn_cli_reply reply); - - static void - static_cli_dump_app_states(void *context, int argc, const char **argv, dsn_cli_reply *reply); - static void static_cli_dump_app_states_cleanup(dsn_cli_reply reply); }; } }