From 372f8309ca9e23bf0baf7085e01e592685b71b24 Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Mon, 9 Dec 2019 16:39:19 +0800 Subject: [PATCH 01/18] meta env check --- .../dsn/dist/replication/replication_types.h | 6 + .../replication/common/replication_common.cpp | 2 - .../replication/common/replication_common.h | 2 - .../replication/common/replication_types.cpp | 9 ++ src/dist/replication/lib/replica_throttle.cpp | 5 +- .../replication/meta_server/server_state.cpp | 103 +++++++++++++++--- .../replication/meta_server/server_state.h | 9 ++ .../unit_test/meta_app_envs_test.cpp | 84 ++++++++++++-- .../test/meta_test/unit_test/meta_test_base.h | 8 +- 9 files changed, 189 insertions(+), 39 deletions(-) diff --git a/include/dsn/dist/replication/replication_types.h b/include/dsn/dist/replication/replication_types.h index efac7641ac..1e7da6c865 100644 --- a/include/dsn/dist/replication/replication_types.h +++ b/include/dsn/dist/replication/replication_types.h @@ -162,6 +162,12 @@ struct duplication_status extern const std::map _duplication_status_VALUES_TO_NAMES; +// app envs +extern const std::string ENV_SLOW_QUERY_THRESHOLD; +extern const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; +extern const std::string ENV_WRITE_QPS_THROTTLING; +extern const std::string ENV_WRITE_SIZE_THROTTLING; + class mutation_header; class mutation_update; diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 6e5c46685b..186fbda09a 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -590,8 +590,6 @@ const std::string backup_restore_constant::BACKUP_ID("restore.backup_id"); const std::string backup_restore_constant::SKIP_BAD_PARTITION("restore.skip_bad_partition"); const std::string replica_envs::DENY_CLIENT_WRITE("replica.deny_client_write"); -const std::string replica_envs::WRITE_QPS_THROTTLING("replica.write_throttling"); -const std::string replica_envs::WRITE_SIZE_THROTTLING("replica.write_throttling_by_size"); namespace cold_backup { std::string get_policy_path(const std::string &root, const std::string &policy_name) diff --git a/src/dist/replication/common/replication_common.h b/src/dist/replication/common/replication_common.h index 1630dcdad2..bb08322d6e 100644 --- a/src/dist/replication/common/replication_common.h +++ b/src/dist/replication/common/replication_common.h @@ -152,8 +152,6 @@ class replica_envs { public: static const std::string DENY_CLIENT_WRITE; - static const std::string WRITE_QPS_THROTTLING; - static const std::string WRITE_SIZE_THROTTLING; }; namespace cold_backup { diff --git a/src/dist/replication/common/replication_types.cpp b/src/dist/replication/common/replication_types.cpp index 04c77d74e7..c416e5d711 100644 --- a/src/dist/replication/common/replication_types.cpp +++ b/src/dist/replication/common/replication_types.cpp @@ -14,6 +14,15 @@ namespace dsn { namespace replication { +/// +/// app envs +/// +// min value for slow query threshold, less than this value will be refused +const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS = 20; +const std::string ENV_SLOW_QUERY_THRESHOLD("replica.slow_query_threshold"); +const std::string ENV_WRITE_QPS_THROTTLING("replica.write_throttling"); +const std::string ENV_WRITE_SIZE_THROTTLING("replica.write_throttling_by_size"); + int _kpartition_statusValues[] = {partition_status::PS_INVALID, partition_status::PS_INACTIVE, partition_status::PS_ERROR, diff --git a/src/dist/replication/lib/replica_throttle.cpp b/src/dist/replication/lib/replica_throttle.cpp index 0ba6dc84e6..eb81449bd3 100644 --- a/src/dist/replication/lib/replica_throttle.cpp +++ b/src/dist/replication/lib/replica_throttle.cpp @@ -52,10 +52,9 @@ bool replica::throttle_request(throttling_controller &controller, void replica::update_throttle_envs(const std::map &envs) { + update_throttle_env_internal(envs, ENV_WRITE_QPS_THROTTLING, _write_qps_throttling_controller); update_throttle_env_internal( - envs, replica_envs::WRITE_QPS_THROTTLING, _write_qps_throttling_controller); - update_throttle_env_internal( - envs, replica_envs::WRITE_SIZE_THROTTLING, _write_size_throttling_controller); + envs, ENV_WRITE_SIZE_THROTTLING, _write_size_throttling_controller); } void replica::update_throttle_env_internal(const std::map &envs, diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 2a5f6f883d..2fae07450e 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -56,10 +56,6 @@ namespace replication { static const char *lock_state = "lock"; static const char *unlock_state = "unlock"; -// env name of slow query -static const std::string ENV_SLOW_QUERY_THRESHOLD("replica.slow_query_threshold"); -// min value for slow query threshold, less than this value will be refused -static const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS = 20; server_state::server_state() : _meta_svc(nullptr), @@ -69,6 +65,7 @@ server_state::server_state() _ctrl_add_secondary_enable_flow_control(nullptr), _ctrl_add_secondary_max_count_for_one_node(nullptr) { + init_env_check_functions(); } server_state::~server_state() @@ -90,6 +87,86 @@ server_state::~server_state() } } +void server_state::init_env_check_functions() +{ + env_check_functions[ENV_SLOW_QUERY_THRESHOLD] = std::bind( + &server_state::check_slow_query, this, std::placeholders::_1, std::placeholders::_2); + env_check_functions[ENV_WRITE_QPS_THROTTLING] = std::bind( + &server_state::check_write_throttling, this, std::placeholders::_1, std::placeholders::_2); + env_check_functions[ENV_WRITE_SIZE_THROTTLING] = std::bind( + &server_state::check_write_throttling, this, std::placeholders::_1, std::placeholders::_2); +} + +bool server_state::check_slow_query(const std::string &env_value, std::string &hint_message) +{ + uint64_t threshold = 0; + if (!dsn::buf2uint64(env_value, threshold) || threshold < MIN_SLOW_QUERY_THRESHOLD_MS) { + hint_message = + fmt::format("Slow query threshold must be >= {}ms", MIN_SLOW_QUERY_THRESHOLD_MS); + return false; + } + return true; +} + +bool server_state::check_write_throttling(const std::string &env_value, std::string &hint_message) +{ + std::vector sargs; + utils::split_args(env_value.c_str(), sargs, ','); + if (sargs.empty()) { + hint_message = "The value shouldn't be empty"; + return false; + } + + // example for arg: 100K*delay*100 / 100M*reject*100 + for (std::string &sarg : sargs) { + std::vector sub_sargs; + utils::split_args(sarg.c_str(), sub_sargs, '*'); + if (sub_sargs.size() != 3) { + hint_message = fmt::format("The field count of {} should be 3", sarg); + return false; + } + + int64_t units = 0; + if (!sub_sargs[0].empty() && + ('M' == *sub_sargs[0].rbegin() || 'K' == *sub_sargs[0].rbegin())) { + sub_sargs[0].pop_back(); + } + if (!buf2int64(sub_sargs[0], units) || units < 0) { + hint_message = fmt::format("{} should be non-negative int", sub_sargs[0]); + return false; + } + + if (sub_sargs[1] != "delay" && sub_sargs[1] != "reject") { + hint_message = fmt::format("{} should be \"delay\" or \"reject\"", sub_sargs[1]); + return false; + } + + int64_t ms = 0; + if (!buf2int64(sub_sargs[2], ms) || ms < 0) { + hint_message = fmt::format("{} should be non-negative int", sub_sargs[2]); + return false; + }; + } + + return true; +} + +bool server_state::check_app_envs(const std::string &key, + const std::string &value, + std::string &hint_message) +{ + + auto func_iter = env_check_functions.find(key); + if (func_iter != env_check_functions.end()) { + if (!func_iter->second(value, hint_message)) { + dwarn("{}={} is invalid.", key.c_str(), value.c_str()); + return false; + } + } + + return true; +} + void server_state::register_cli_commands() { _cli_dump_handle = dsn::command_manager::instance().register_app_command( @@ -2616,20 +2693,14 @@ void server_state::set_app_envs(const app_env_rpc &env_rpc) std::ostringstream os; for (int i = 0; i < keys.size(); i++) { - // check whether if slow query threshold is abnormal - if (0 == keys[i].compare(ENV_SLOW_QUERY_THRESHOLD)) { - uint64_t threshold = 0; - if (!dsn::buf2uint64(values[i], threshold) || threshold < MIN_SLOW_QUERY_THRESHOLD_MS) { - dwarn("{}={} is invalid.", keys[i].c_str(), threshold); - env_rpc.response().err = ERR_INVALID_PARAMETERS; - env_rpc.response().hint_message = fmt::format( - "slow query threshold must be >= {}ms", MIN_SLOW_QUERY_THRESHOLD_MS); - return; - } - } - if (i != 0) os << ", "; + + if (!check_app_envs(keys[i], values[i], env_rpc.response().hint_message)) { + env_rpc.response().err = ERR_INVALID_PARAMETERS; + return; + } + os << keys[i] << "=" << values[i]; } ddebug("set app envs for app(%s) from remote(%s): kvs = {%s}", diff --git a/src/dist/replication/meta_server/server_state.h b/src/dist/replication/meta_server/server_state.h index 1d41960ea6..96d1b9f4d5 100644 --- a/src/dist/replication/meta_server/server_state.h +++ b/src/dist/replication/meta_server/server_state.h @@ -297,6 +297,12 @@ class server_state void process_one_partition(std::shared_ptr &app); void transition_staging_state(std::shared_ptr &app); + void init_env_check_functions(); + bool check_slow_query(const std::string &env_value, std::string &hint_message); + bool check_write_throttling(const std::string &env_value, std::string &hint_message); + bool + check_app_envs(const std::string &key, const std::string &value, std::string &hint_message); + private: friend class replication_checker; friend class test::test_checker; @@ -340,6 +346,9 @@ 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; + + std::map> + env_check_functions; }; } // namespace replication diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index a235f733e3..290283ca19 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -39,32 +39,92 @@ class meta_app_envs_test : public meta_test_base create_app(app_name); } + void TearDown() override { drop_app(app_name); } + const std::string app_name = "test_app_env"; - const std::string env_slow_query_threshold = "replica.slow_query_threshold"; }; TEST_F(meta_app_envs_test, set_slow_query_threshold) { + struct test_case + { + error_code err; + std::string env_value; + std::string hint; + std::string expect_value; + } tests[] = {{ERR_OK, "30", "", "30"}, + {ERR_OK, "20", "", "20"}, + {ERR_INVALID_PARAMETERS, "19", "Slow query threshold must be >= 20ms", "20"}, + {ERR_INVALID_PARAMETERS, "0", "Slow query threshold must be >= 20ms", "20"}}; + + const std::string env_slow_query_threshold = "replica.slow_query_threshold"; auto app = find_app(app_name); + for (auto test : tests) { + configuration_update_app_env_response response = + update_app_envs(app_name, {env_slow_query_threshold}, {test.env_value}); + ASSERT_EQ(response.err, test.err); + ASSERT_EQ(response.hint_message, test.hint); + ASSERT_EQ(app->envs.at(env_slow_query_threshold), test.expect_value); + } +} + +TEST_F(meta_app_envs_test, set_write_throttling) +{ struct test_case { - error_code err; + std::string env_key; std::string env_value; - std::string expect_env_value; - } tests[] = {{ERR_OK, "30", "30"}, - {ERR_OK, "21", "21"}, - {ERR_OK, "20", "20"}, - {ERR_INVALID_PARAMETERS, "19", "20"}, - {ERR_INVALID_PARAMETERS, "10", "20"}, - {ERR_INVALID_PARAMETERS, "0", "20"}}; + error_code err; + std::string hint; + std::string expect_value; + } tests[] = { + {"replica.write_throttling", "100*delay*100", ERR_OK, "", "100*delay*100"}, + {"replica.write_throttling", "20K*delay*100", ERR_OK, "", "20K*delay*100"}, + {"replica.write_throttling", "20M*delay*100", ERR_OK, "", "20M*delay*100"}, + {"replica.write_throttling", + "20A*delay*100", + ERR_INVALID_PARAMETERS, + "20A should be non-negative int", + "20M*delay*100"}, + {"replica.write_throttling", + "-20*delay*100", + ERR_INVALID_PARAMETERS, + "-20 should be non-negative int", + "20M*delay*100"}, + {"replica.write_throttling", + "", + ERR_INVALID_PARAMETERS, + "The value shouldn't be empty", + "20M*delay*100"}, + {"replica.write_throttling", + "20A*delay", + ERR_INVALID_PARAMETERS, + "The field count of 20A*delay should be 3", + "20M*delay*100"}, + {"replica.write_throttling", + "20K*pass*100", + ERR_INVALID_PARAMETERS, + "pass should be \"delay\" or \"reject\"", + "20M*delay*100"}, + {"replica.write_throttling", + "20K*delay*-100", + ERR_INVALID_PARAMETERS, + "-100 should be non-negative int", + "20M*delay*100"}, + {"replica.write_throttling", "20M*reject*100", ERR_OK, "", "20M*reject*100"}, + {"replica.write_throttling_by_size", "300*delay*100", ERR_OK, "", "300*delay*100"}}; + auto app = find_app(app_name); for (auto test : tests) { - error_code err = update_app_envs(app_name, {env_slow_query_threshold}, {test.env_value}); + configuration_update_app_env_response response = + update_app_envs(app_name, {test.env_key}, {test.env_value}); - ASSERT_EQ(err, test.err); - ASSERT_EQ(app->envs.at(env_slow_query_threshold), test.expect_env_value); + ASSERT_EQ(response.err, test.err); + ASSERT_EQ(response.hint_message, test.hint); + ASSERT_EQ(app->envs.at(test.env_key), test.expect_value); } } + } // namespace replication } // namespace dsn diff --git a/src/dist/replication/test/meta_test/unit_test/meta_test_base.h b/src/dist/replication/test/meta_test/unit_test/meta_test_base.h index 3483e77b5c..259eb87d78 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_test_base.h +++ b/src/dist/replication/test/meta_test/unit_test/meta_test_base.h @@ -101,9 +101,9 @@ class meta_test_base : public testing::Test ASSERT_TRUE(_ss->spin_wait_staging(30)); } - error_code update_app_envs(const std::string &app_name, - const std::vector &env_keys, - const std::vector &env_vals) + configuration_update_app_env_response update_app_envs(const std::string &app_name, + const std::vector &env_keys, + const std::vector &env_vals) { auto req = make_unique(); req->__set_app_name(std::move(app_name)); @@ -114,7 +114,7 @@ class meta_test_base : public testing::Test app_env_rpc rpc(std::move(req), RPC_CM_UPDATE_APP_ENV); // don't need reply _ss->set_app_envs(rpc); _ss->wait_all_task(); - return rpc.response().err; + return rpc.response(); } std::shared_ptr find_app(const std::string &name) { return _ss->get_app(name); } From 5c4c0de230d4a5b5bbc92fa86e3cb0a90db24fd2 Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Mon, 9 Dec 2019 18:58:18 +0800 Subject: [PATCH 02/18] fix --- .../dsn/dist/replication/replication_types.h | 6 ----- .../replication/common/replication_common.cpp | 4 +++ .../replication/common/replication_common.h | 4 +++ .../replication/common/replication_types.cpp | 9 ------- src/dist/replication/lib/replica_throttle.cpp | 5 ++-- .../replication/meta_server/server_state.cpp | 13 ++++----- .../unit_test/meta_app_envs_test.cpp | 27 +++++++++---------- 7 files changed, 31 insertions(+), 37 deletions(-) diff --git a/include/dsn/dist/replication/replication_types.h b/include/dsn/dist/replication/replication_types.h index 1e7da6c865..efac7641ac 100644 --- a/include/dsn/dist/replication/replication_types.h +++ b/include/dsn/dist/replication/replication_types.h @@ -162,12 +162,6 @@ struct duplication_status extern const std::map _duplication_status_VALUES_TO_NAMES; -// app envs -extern const std::string ENV_SLOW_QUERY_THRESHOLD; -extern const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; -extern const std::string ENV_WRITE_QPS_THROTTLING; -extern const std::string ENV_WRITE_SIZE_THROTTLING; - class mutation_header; class mutation_update; diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 186fbda09a..bda7224dca 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -590,6 +590,10 @@ const std::string backup_restore_constant::BACKUP_ID("restore.backup_id"); const std::string backup_restore_constant::SKIP_BAD_PARTITION("restore.skip_bad_partition"); const std::string replica_envs::DENY_CLIENT_WRITE("replica.deny_client_write"); +const std::string replica_envs::WRITE_QPS_THROTTLING("replica.write_throttling"); +const std::string replica_envs::WRITE_SIZE_THROTTLING("replica.write_throttling_by_size"); +const uint64_t replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS = 20; +const std::string replica_envs::SLOW_QUERY_THRESHOLD("replica.slow_query_threshold"); namespace cold_backup { std::string get_policy_path(const std::string &root, const std::string &policy_name) diff --git a/src/dist/replication/common/replication_common.h b/src/dist/replication/common/replication_common.h index bb08322d6e..1f769006dd 100644 --- a/src/dist/replication/common/replication_common.h +++ b/src/dist/replication/common/replication_common.h @@ -152,6 +152,10 @@ class replica_envs { public: static const std::string DENY_CLIENT_WRITE; + static const std::string WRITE_QPS_THROTTLING; + static const std::string WRITE_SIZE_THROTTLING; + static const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; + static const std::string SLOW_QUERY_THRESHOLD; }; namespace cold_backup { diff --git a/src/dist/replication/common/replication_types.cpp b/src/dist/replication/common/replication_types.cpp index c416e5d711..04c77d74e7 100644 --- a/src/dist/replication/common/replication_types.cpp +++ b/src/dist/replication/common/replication_types.cpp @@ -14,15 +14,6 @@ namespace dsn { namespace replication { -/// -/// app envs -/// -// min value for slow query threshold, less than this value will be refused -const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS = 20; -const std::string ENV_SLOW_QUERY_THRESHOLD("replica.slow_query_threshold"); -const std::string ENV_WRITE_QPS_THROTTLING("replica.write_throttling"); -const std::string ENV_WRITE_SIZE_THROTTLING("replica.write_throttling_by_size"); - int _kpartition_statusValues[] = {partition_status::PS_INVALID, partition_status::PS_INACTIVE, partition_status::PS_ERROR, diff --git a/src/dist/replication/lib/replica_throttle.cpp b/src/dist/replication/lib/replica_throttle.cpp index eb81449bd3..0ba6dc84e6 100644 --- a/src/dist/replication/lib/replica_throttle.cpp +++ b/src/dist/replication/lib/replica_throttle.cpp @@ -52,9 +52,10 @@ bool replica::throttle_request(throttling_controller &controller, void replica::update_throttle_envs(const std::map &envs) { - update_throttle_env_internal(envs, ENV_WRITE_QPS_THROTTLING, _write_qps_throttling_controller); update_throttle_env_internal( - envs, ENV_WRITE_SIZE_THROTTLING, _write_size_throttling_controller); + envs, replica_envs::WRITE_QPS_THROTTLING, _write_qps_throttling_controller); + update_throttle_env_internal( + envs, replica_envs::WRITE_SIZE_THROTTLING, _write_size_throttling_controller); } void replica::update_throttle_env_internal(const std::map &envs, diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 2fae07450e..8b23b0dfb6 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -89,20 +89,21 @@ server_state::~server_state() void server_state::init_env_check_functions() { - env_check_functions[ENV_SLOW_QUERY_THRESHOLD] = std::bind( + env_check_functions[replica_envs::SLOW_QUERY_THRESHOLD] = std::bind( &server_state::check_slow_query, this, std::placeholders::_1, std::placeholders::_2); - env_check_functions[ENV_WRITE_QPS_THROTTLING] = std::bind( + env_check_functions[replica_envs::WRITE_QPS_THROTTLING] = std::bind( &server_state::check_write_throttling, this, std::placeholders::_1, std::placeholders::_2); - env_check_functions[ENV_WRITE_SIZE_THROTTLING] = std::bind( + env_check_functions[replica_envs::WRITE_SIZE_THROTTLING] = std::bind( &server_state::check_write_throttling, this, std::placeholders::_1, std::placeholders::_2); } bool server_state::check_slow_query(const std::string &env_value, std::string &hint_message) { uint64_t threshold = 0; - if (!dsn::buf2uint64(env_value, threshold) || threshold < MIN_SLOW_QUERY_THRESHOLD_MS) { - hint_message = - fmt::format("Slow query threshold must be >= {}ms", MIN_SLOW_QUERY_THRESHOLD_MS); + if (!dsn::buf2uint64(env_value, threshold) || + threshold < replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS) { + hint_message = fmt::format("Slow query threshold must be >= {}ms", + replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS); return false; } return true; diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index 290283ca19..4c1424813f 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -57,15 +57,14 @@ TEST_F(meta_app_envs_test, set_slow_query_threshold) {ERR_INVALID_PARAMETERS, "19", "Slow query threshold must be >= 20ms", "20"}, {ERR_INVALID_PARAMETERS, "0", "Slow query threshold must be >= 20ms", "20"}}; - const std::string env_slow_query_threshold = "replica.slow_query_threshold"; auto app = find_app(app_name); for (auto test : tests) { configuration_update_app_env_response response = - update_app_envs(app_name, {env_slow_query_threshold}, {test.env_value}); + update_app_envs(app_name, {replica_envs::SLOW_QUERY_THRESHOLD}, {test.env_value}); ASSERT_EQ(response.err, test.err); ASSERT_EQ(response.hint_message, test.hint); - ASSERT_EQ(app->envs.at(env_slow_query_threshold), test.expect_value); + ASSERT_EQ(app->envs.at(replica_envs::SLOW_QUERY_THRESHOLD), test.expect_value); } } @@ -79,41 +78,41 @@ TEST_F(meta_app_envs_test, set_write_throttling) std::string hint; std::string expect_value; } tests[] = { - {"replica.write_throttling", "100*delay*100", ERR_OK, "", "100*delay*100"}, - {"replica.write_throttling", "20K*delay*100", ERR_OK, "", "20K*delay*100"}, - {"replica.write_throttling", "20M*delay*100", ERR_OK, "", "20M*delay*100"}, - {"replica.write_throttling", + {replica_envs::WRITE_QPS_THROTTLING, "100*delay*100", ERR_OK, "", "100*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, "20K*delay*100", ERR_OK, "", "20K*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, "20M*delay*100", ERR_OK, "", "20M*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, "20A*delay*100", ERR_INVALID_PARAMETERS, "20A should be non-negative int", "20M*delay*100"}, - {"replica.write_throttling", + {replica_envs::WRITE_QPS_THROTTLING, "-20*delay*100", ERR_INVALID_PARAMETERS, "-20 should be non-negative int", "20M*delay*100"}, - {"replica.write_throttling", + {replica_envs::WRITE_QPS_THROTTLING, "", ERR_INVALID_PARAMETERS, "The value shouldn't be empty", "20M*delay*100"}, - {"replica.write_throttling", + {replica_envs::WRITE_QPS_THROTTLING, "20A*delay", ERR_INVALID_PARAMETERS, "The field count of 20A*delay should be 3", "20M*delay*100"}, - {"replica.write_throttling", + {replica_envs::WRITE_QPS_THROTTLING, "20K*pass*100", ERR_INVALID_PARAMETERS, "pass should be \"delay\" or \"reject\"", "20M*delay*100"}, - {"replica.write_throttling", + {replica_envs::WRITE_QPS_THROTTLING, "20K*delay*-100", ERR_INVALID_PARAMETERS, "-100 should be non-negative int", "20M*delay*100"}, - {"replica.write_throttling", "20M*reject*100", ERR_OK, "", "20M*reject*100"}, - {"replica.write_throttling_by_size", "300*delay*100", ERR_OK, "", "300*delay*100"}}; + {replica_envs::WRITE_QPS_THROTTLING, "20M*reject*100", ERR_OK, "", "20M*reject*100"}, + {replica_envs::WRITE_SIZE_THROTTLING, "300*delay*100", ERR_OK, "", "300*delay*100"}}; auto app = find_app(app_name); for (auto test : tests) { From dd2aa5044d361b531a7b167bdd2e5529b24fe85e Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Tue, 10 Dec 2019 19:57:38 +0800 Subject: [PATCH 03/18] fix --- .../replication/meta_server/server_state.cpp | 84 +++++++++---------- .../replication/meta_server/server_state.h | 2 - 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 3d3c4492bc..e115c6ff43 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -57,47 +57,7 @@ namespace replication { static const char *lock_state = "lock"; static const char *unlock_state = "unlock"; -server_state::server_state() - : _meta_svc(nullptr), - _add_secondary_enable_flow_control(false), - _add_secondary_max_count_for_one_node(0), - _cli_dump_handle(nullptr), - _ctrl_add_secondary_enable_flow_control(nullptr), - _ctrl_add_secondary_max_count_for_one_node(nullptr) -{ - init_env_check_functions(); -} - -server_state::~server_state() -{ - _tracker.cancel_outstanding_tasks(); - if (_cli_dump_handle != nullptr) { - dsn::command_manager::instance().deregister_command(_cli_dump_handle); - _cli_dump_handle = nullptr; - } - if (_ctrl_add_secondary_enable_flow_control != nullptr) { - dsn::command_manager::instance().deregister_command( - _ctrl_add_secondary_enable_flow_control); - _ctrl_add_secondary_enable_flow_control = nullptr; - } - if (_ctrl_add_secondary_max_count_for_one_node != nullptr) { - dsn::command_manager::instance().deregister_command( - _ctrl_add_secondary_max_count_for_one_node); - _ctrl_add_secondary_max_count_for_one_node = nullptr; - } -} - -void server_state::init_env_check_functions() -{ - env_check_functions[replica_envs::SLOW_QUERY_THRESHOLD] = std::bind( - &server_state::check_slow_query, this, std::placeholders::_1, std::placeholders::_2); - env_check_functions[replica_envs::WRITE_QPS_THROTTLING] = std::bind( - &server_state::check_write_throttling, this, std::placeholders::_1, std::placeholders::_2); - env_check_functions[replica_envs::WRITE_SIZE_THROTTLING] = std::bind( - &server_state::check_write_throttling, this, std::placeholders::_1, std::placeholders::_2); -} - -bool server_state::check_slow_query(const std::string &env_value, std::string &hint_message) +bool check_slow_query(const std::string &env_value, std::string &hint_message) { uint64_t threshold = 0; if (!dsn::buf2uint64(env_value, threshold) || @@ -109,7 +69,7 @@ bool server_state::check_slow_query(const std::string &env_value, std::string &h return true; } -bool server_state::check_write_throttling(const std::string &env_value, std::string &hint_message) +bool check_write_throttling(const std::string &env_value, std::string &hint_message) { std::vector sargs; utils::split_args(env_value.c_str(), sargs, ','); @@ -152,6 +112,46 @@ bool server_state::check_write_throttling(const std::string &env_value, std::str return true; } +server_state::server_state() + : _meta_svc(nullptr), + _add_secondary_enable_flow_control(false), + _add_secondary_max_count_for_one_node(0), + _cli_dump_handle(nullptr), + _ctrl_add_secondary_enable_flow_control(nullptr), + _ctrl_add_secondary_max_count_for_one_node(nullptr) +{ + init_env_check_functions(); +} + +server_state::~server_state() +{ + _tracker.cancel_outstanding_tasks(); + if (_cli_dump_handle != nullptr) { + dsn::command_manager::instance().deregister_command(_cli_dump_handle); + _cli_dump_handle = nullptr; + } + if (_ctrl_add_secondary_enable_flow_control != nullptr) { + dsn::command_manager::instance().deregister_command( + _ctrl_add_secondary_enable_flow_control); + _ctrl_add_secondary_enable_flow_control = nullptr; + } + if (_ctrl_add_secondary_max_count_for_one_node != nullptr) { + dsn::command_manager::instance().deregister_command( + _ctrl_add_secondary_max_count_for_one_node); + _ctrl_add_secondary_max_count_for_one_node = nullptr; + } +} + +void server_state::init_env_check_functions() +{ + env_check_functions[replica_envs::SLOW_QUERY_THRESHOLD] = + std::bind(&check_slow_query, std::placeholders::_1, std::placeholders::_2); + env_check_functions[replica_envs::WRITE_QPS_THROTTLING] = + std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2); + env_check_functions[replica_envs::WRITE_SIZE_THROTTLING] = + std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2); +} + bool server_state::check_app_envs(const std::string &key, const std::string &value, std::string &hint_message) diff --git a/src/dist/replication/meta_server/server_state.h b/src/dist/replication/meta_server/server_state.h index 96d1b9f4d5..16f83ab836 100644 --- a/src/dist/replication/meta_server/server_state.h +++ b/src/dist/replication/meta_server/server_state.h @@ -298,8 +298,6 @@ class server_state void transition_staging_state(std::shared_ptr &app); void init_env_check_functions(); - bool check_slow_query(const std::string &env_value, std::string &hint_message); - bool check_write_throttling(const std::string &env_value, std::string &hint_message); bool check_app_envs(const std::string &key, const std::string &value, std::string &hint_message); From 1b13416e16ed3ee05cce085fc5f69a6b07168f25 Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Wed, 11 Dec 2019 19:21:07 +0800 Subject: [PATCH 04/18] meta env check --- src/dist/replication/common/replication_common.cpp | 14 ++++++++++++++ src/dist/replication/common/replication_common.h | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 6c1bb4b706..14baf50564 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -602,6 +602,20 @@ const std::string replica_envs::WRITE_QPS_THROTTLING("replica.write_throttling") const std::string replica_envs::WRITE_SIZE_THROTTLING("replica.write_throttling_by_size"); const uint64_t replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS = 20; const std::string replica_envs::SLOW_QUERY_THRESHOLD("replica.slow_query_threshold"); +const std::string replica_envs::ROCKSDB_USAGE_SCENARIO("rocksdb.usage_scenario"); +const std::string replica_envs::TABLE_LEVEL_DEFAULT_TTL("default_ttl"); +const std::string MANUAL_COMPACT_PREFIX("manual_compact."); +const std::string MANUAL_COMPACT_PERIODIC_PREFIX(MANUAL_COMPACT_PREFIX + "periodic."); +const std::string MANUAL_COMPACT_ONCE_PREFIX(MANUAL_COMPACT_PREFIX + "once."); +const std::string replica_envs::MANUAL_COMPACT_DISABLED(MANUAL_COMPACT_PREFIX + "disabled"); +const std::string replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT(MANUAL_COMPACT_PREFIX + + "max_concurrent_running_count"); +const std::string replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME(MANUAL_COMPACT_PERIODIC_PREFIX + + "trigger_time"); +const std::string replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME(MANUAL_COMPACT_ONCE_PREFIX + + "trigger_time"); +const std::string replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL_KEY(MANUAL_COMPACT_ONCE_PREFIX + "target_level"); +const std::string replica_envs::MANUAL_COMPACT_ONCE_PERIODIC_LEVEL_KEY(MANUAL_COMPACT_PERIODIC_PREFIX + "target_level"); namespace cold_backup { std::string get_policy_path(const std::string &root, const std::string &policy_name) diff --git a/src/dist/replication/common/replication_common.h b/src/dist/replication/common/replication_common.h index b104883e04..5b77b9f980 100644 --- a/src/dist/replication/common/replication_common.h +++ b/src/dist/replication/common/replication_common.h @@ -157,6 +157,14 @@ class replica_envs static const std::string WRITE_SIZE_THROTTLING; static const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; static const std::string SLOW_QUERY_THRESHOLD; + static const std::string ROCKSDB_USAGE_SCENARIO; + static const std::string TABLE_LEVEL_DEFAULT_TTL; + static const std::string MANUAL_COMPACT_DISABLED; + static const std::string MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT; + static const std::string MANUAL_COMPACT_PERIODIC_TRIGGER_TIME; + static const std::string MANUAL_COMPACT_ONCE_TRIGGER_TIME; + static const std::string MANUAL_COMPACT_ONCE_TARGET_LEVEL_KEY; + static const std::string MANUAL_COMPACT_ONCE_PERIODIC_LEVEL_KEY; }; namespace cold_backup { From cbe123f77a3888fb882236b91ad90717e0d1476a Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Thu, 12 Dec 2019 13:44:47 +0800 Subject: [PATCH 05/18] meta env check --- .../replication/common/replication_common.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 14baf50564..3cdec9eea0 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -608,14 +608,16 @@ const std::string MANUAL_COMPACT_PREFIX("manual_compact."); const std::string MANUAL_COMPACT_PERIODIC_PREFIX(MANUAL_COMPACT_PREFIX + "periodic."); const std::string MANUAL_COMPACT_ONCE_PREFIX(MANUAL_COMPACT_PREFIX + "once."); const std::string replica_envs::MANUAL_COMPACT_DISABLED(MANUAL_COMPACT_PREFIX + "disabled"); -const std::string replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT(MANUAL_COMPACT_PREFIX + - "max_concurrent_running_count"); -const std::string replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME(MANUAL_COMPACT_PERIODIC_PREFIX + - "trigger_time"); +const std::string replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT( + MANUAL_COMPACT_PREFIX + "max_concurrent_running_count"); +const std::string replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME( + MANUAL_COMPACT_PERIODIC_PREFIX + "trigger_time"); const std::string replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME(MANUAL_COMPACT_ONCE_PREFIX + - "trigger_time"); -const std::string replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL_KEY(MANUAL_COMPACT_ONCE_PREFIX + "target_level"); -const std::string replica_envs::MANUAL_COMPACT_ONCE_PERIODIC_LEVEL_KEY(MANUAL_COMPACT_PERIODIC_PREFIX + "target_level"); + "trigger_time"); +const std::string replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL_KEY(MANUAL_COMPACT_ONCE_PREFIX + + "target_level"); +const std::string replica_envs::MANUAL_COMPACT_ONCE_PERIODIC_LEVEL_KEY( + MANUAL_COMPACT_PERIODIC_PREFIX + "target_level"); namespace cold_backup { std::string get_policy_path(const std::string &root, const std::string &policy_name) From f67510458584d82ff6c67095c928f8fe23260c8a Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Thu, 12 Dec 2019 14:54:50 +0800 Subject: [PATCH 06/18] meta env check --- .../replication/common/replication_common.cpp | 23 +++++++++++++------ .../replication/common/replication_common.h | 13 +++++++---- .../replication/meta_server/server_state.cpp | 23 +++++++++++++++++-- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 3cdec9eea0..039876db8c 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -605,19 +605,28 @@ const std::string replica_envs::SLOW_QUERY_THRESHOLD("replica.slow_query_thresho const std::string replica_envs::ROCKSDB_USAGE_SCENARIO("rocksdb.usage_scenario"); const std::string replica_envs::TABLE_LEVEL_DEFAULT_TTL("default_ttl"); const std::string MANUAL_COMPACT_PREFIX("manual_compact."); -const std::string MANUAL_COMPACT_PERIODIC_PREFIX(MANUAL_COMPACT_PREFIX + "periodic."); -const std::string MANUAL_COMPACT_ONCE_PREFIX(MANUAL_COMPACT_PREFIX + "once."); const std::string replica_envs::MANUAL_COMPACT_DISABLED(MANUAL_COMPACT_PREFIX + "disabled"); const std::string replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT( MANUAL_COMPACT_PREFIX + "max_concurrent_running_count"); -const std::string replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME( - MANUAL_COMPACT_PERIODIC_PREFIX + "trigger_time"); +const std::string MANUAL_COMPACT_ONCE_PREFIX(MANUAL_COMPACT_PREFIX + "once."); const std::string replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME(MANUAL_COMPACT_ONCE_PREFIX + "trigger_time"); -const std::string replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL_KEY(MANUAL_COMPACT_ONCE_PREFIX + - "target_level"); -const std::string replica_envs::MANUAL_COMPACT_ONCE_PERIODIC_LEVEL_KEY( +const std::string replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL(MANUAL_COMPACT_ONCE_PREFIX + + "target_level"); +const std::string replica_envs::MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION( + MANUAL_COMPACT_ONCE_PREFIX + "bottommost_level_compaction"); +const std::string MANUAL_COMPACT_PERIODIC_PREFIX(MANUAL_COMPACT_PREFIX + "periodic."); +const std::string replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME( + MANUAL_COMPACT_PERIODIC_PREFIX + "trigger_time"); +const std::string replica_envs::MANUAL_COMPACT_PERIODIC_TARGET_LEVEL( MANUAL_COMPACT_PERIODIC_PREFIX + "target_level"); +const std::string replica_envs::MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION( + MANUAL_COMPACT_PERIODIC_PREFIX + "bottommost_level_compaction"); +const std::string + replica_envs::ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT("rocksdb.checkpoint.reserve_min_count"); +const std::string replica_envs::ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS( + "rocksdb.checkpoint.reserve_time_seconds"); +const std::string replica_envs::BUSINESS_INFO("business.info"); namespace cold_backup { std::string get_policy_path(const std::string &root, const std::string &policy_name) diff --git a/src/dist/replication/common/replication_common.h b/src/dist/replication/common/replication_common.h index 5b77b9f980..692cd79f6e 100644 --- a/src/dist/replication/common/replication_common.h +++ b/src/dist/replication/common/replication_common.h @@ -157,14 +157,19 @@ class replica_envs static const std::string WRITE_SIZE_THROTTLING; static const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; static const std::string SLOW_QUERY_THRESHOLD; - static const std::string ROCKSDB_USAGE_SCENARIO; static const std::string TABLE_LEVEL_DEFAULT_TTL; + static const std::string ROCKSDB_USAGE_SCENARIO; + static const std::string ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT; + static const std::string ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS; static const std::string MANUAL_COMPACT_DISABLED; static const std::string MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT; - static const std::string MANUAL_COMPACT_PERIODIC_TRIGGER_TIME; static const std::string MANUAL_COMPACT_ONCE_TRIGGER_TIME; - static const std::string MANUAL_COMPACT_ONCE_TARGET_LEVEL_KEY; - static const std::string MANUAL_COMPACT_ONCE_PERIODIC_LEVEL_KEY; + static const std::string MANUAL_COMPACT_ONCE_TARGET_LEVEL; + static const std::string MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION; + static const std::string MANUAL_COMPACT_PERIODIC_TRIGGER_TIME; + static const std::string MANUAL_COMPACT_PERIODIC_TARGET_LEVEL; + static const std::string MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION; + static const std::string BUSINESS_INFO; }; namespace cold_backup { diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 0fcff1850d..30caa13bbb 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -150,6 +150,22 @@ void server_state::init_env_check_functions() std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2); env_check_functions[replica_envs::WRITE_SIZE_THROTTLING] = std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2); + // TODO: not implemented + env_check_functions[replica_envs::BUSINESS_INFO] = nullptr; + env_check_functions[replica_envs::DENY_CLIENT_WRITE] = nullptr; + env_check_functions[replica_envs::TABLE_LEVEL_DEFAULT_TTL] = nullptr; + env_check_functions[replica_envs::ROCKSDB_USAGE_SCENARIO] = nullptr; + env_check_functions[replica_envs::ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT] = nullptr; + env_check_functions[replica_envs::ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_DISABLED] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_PERIODIC_TARGET_LEVEL] = nullptr; + env_check_functions[replica_envs::MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION] = + nullptr; } bool server_state::check_app_envs(const std::string &key, @@ -159,13 +175,16 @@ bool server_state::check_app_envs(const std::string &key, auto func_iter = env_check_functions.find(key); if (func_iter != env_check_functions.end()) { - if (!func_iter->second(value, hint_message)) { + // check function == nullptr means no check + if (nullptr != func_iter->second && !func_iter->second(value, hint_message)) { dwarn("{}={} is invalid.", key.c_str(), value.c_str()); return false; } + + return true; } - return true; + return false; } void server_state::register_cli_commands() From 829f0db8de731b03bb40261191522f3ba8356c2d Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Thu, 12 Dec 2019 17:40:10 +0800 Subject: [PATCH 07/18] fix --- .../replication/meta_server/server_state.cpp | 1 + .../unit_test/meta_app_envs_test.cpp | 66 +++++++++++-------- .../unit_test/meta_http_service_test.cpp | 4 +- .../meta_test/unit_test/server_state_test.cpp | 21 ++++-- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 30caa13bbb..7a23402a1f 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -184,6 +184,7 @@ bool server_state::check_app_envs(const std::string &key, return true; } + hint_message = fmt::format("The env of {} is not supported", key); return false; } diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index 4c1424813f..ed6cb4fd81 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -44,31 +44,7 @@ class meta_app_envs_test : public meta_test_base const std::string app_name = "test_app_env"; }; -TEST_F(meta_app_envs_test, set_slow_query_threshold) -{ - struct test_case - { - error_code err; - std::string env_value; - std::string hint; - std::string expect_value; - } tests[] = {{ERR_OK, "30", "", "30"}, - {ERR_OK, "20", "", "20"}, - {ERR_INVALID_PARAMETERS, "19", "Slow query threshold must be >= 20ms", "20"}, - {ERR_INVALID_PARAMETERS, "0", "Slow query threshold must be >= 20ms", "20"}}; - - auto app = find_app(app_name); - for (auto test : tests) { - configuration_update_app_env_response response = - update_app_envs(app_name, {replica_envs::SLOW_QUERY_THRESHOLD}, {test.env_value}); - - ASSERT_EQ(response.err, test.err); - ASSERT_EQ(response.hint_message, test.hint); - ASSERT_EQ(app->envs.at(replica_envs::SLOW_QUERY_THRESHOLD), test.expect_value); - } -} - -TEST_F(meta_app_envs_test, set_write_throttling) +TEST_F(meta_app_envs_test, update_app_envs_test) { struct test_case { @@ -112,7 +88,41 @@ TEST_F(meta_app_envs_test, set_write_throttling) "-100 should be non-negative int", "20M*delay*100"}, {replica_envs::WRITE_QPS_THROTTLING, "20M*reject*100", ERR_OK, "", "20M*reject*100"}, - {replica_envs::WRITE_SIZE_THROTTLING, "300*delay*100", ERR_OK, "", "300*delay*100"}}; + {replica_envs::WRITE_SIZE_THROTTLING, "300*delay*100", ERR_OK, "", "300*delay*100"}, + {replica_envs::SLOW_QUERY_THRESHOLD, "30", ERR_OK, "", "30"}, + {replica_envs::SLOW_QUERY_THRESHOLD, "20", ERR_OK, "", "20"}, + {replica_envs::SLOW_QUERY_THRESHOLD, + "19", + ERR_INVALID_PARAMETERS, + "Slow query threshold must be >= 20ms", + "20"}, + {replica_envs::SLOW_QUERY_THRESHOLD, + "0", + ERR_INVALID_PARAMETERS, + "Slow query threshold must be >= 20ms", + "20"}, + {replica_envs::TABLE_LEVEL_DEFAULT_TTL, "10", ERR_OK, "", "10"}, + {replica_envs::ROCKSDB_USAGE_SCENARIO, "20", ERR_OK, "", "20"}, + {replica_envs::ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT, "30", ERR_OK, "", "30"}, + {replica_envs::ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS, "40", ERR_OK, "", "40"}, + {replica_envs::MANUAL_COMPACT_DISABLED, "50", ERR_OK, "", "50"}, + {replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT, "60", ERR_OK, "", "60"}, + {replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME, "70", ERR_OK, "", "70"}, + {replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL, "80", ERR_OK, "", "80"}, + {replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME, "90", ERR_OK, "", "90"}, + {replica_envs::MANUAL_COMPACT_PERIODIC_TARGET_LEVEL, "100", ERR_OK, "", "100"}, + {replica_envs::MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION, + "200", + ERR_OK, + "", + "200"}, + {replica_envs::BUSINESS_INFO, "300", ERR_OK, "", "300"}, + {replica_envs::DENY_CLIENT_WRITE, "400", ERR_OK, "", "400"}, + {"not_exist_env", + "500", + ERR_INVALID_PARAMETERS, + "The env of not_exist_env is not supported", + ""}}; auto app = find_app(app_name); for (auto test : tests) { @@ -121,7 +131,9 @@ TEST_F(meta_app_envs_test, set_write_throttling) ASSERT_EQ(response.err, test.err); ASSERT_EQ(response.hint_message, test.hint); - ASSERT_EQ(app->envs.at(test.env_key), test.expect_value); + if (app->envs.find(test.env_key) != app->envs.end()) { + ASSERT_EQ(app->envs.at(test.env_key), test.expect_value); + } } } diff --git a/src/dist/replication/test/meta_test/unit_test/meta_http_service_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_http_service_test.cpp index edc1adc311..8656a8edcc 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_http_service_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_http_service_test.cpp @@ -41,8 +41,8 @@ class meta_http_service_test : public meta_test_base void test_get_app_envs() { // set app env - std::string env_key = "test_env"; - std::string env_value = "test_value"; + std::string env_key = "replica.slow_query_threshold"; + std::string env_value = "100"; update_app_envs(test_app, {env_key}, {env_value}); // http get app envs diff --git a/src/dist/replication/test/meta_test/unit_test/server_state_test.cpp b/src/dist/replication/test/meta_test/unit_test/server_state_test.cpp index 01917cbb4f..6f3748fec8 100644 --- a/src/dist/replication/test/meta_test/unit_test/server_state_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/server_state_test.cpp @@ -8,15 +8,26 @@ using namespace ::dsn::replication; -static const std::vector keys = { - "p1.k1", "p1.k2", "p1.k3", "p2.k1", "p2.k2", "p2.k3", "p3.k1", "p3.k2", "p3.k3"}; +static const std::vector keys = {"manual_compact.once.trigger_time", + "manual_compact.once.target_level", + "manual_compact.once.bottommost_level_compaction", + "manual_compact.periodic.trigger_time", + "manual_compact.periodic.target_level", + "manual_compact.periodic.bottommost_level_compaction", + "rocksdb.usage_scenario", + "rocksdb.checkpoint.reserve_min_count", + "rocksdb.checkpoint.reserve_time_seconds"}; static const std::vector values = { "p1v1", "p1v2", "p1v3", "p2v1", "p2v2", "p2v3", "p3v1", "p3v2", "p3v3"}; -static const std::vector del_keys = {"p1.k1", "p2.k1", "p3.k1"}; -static const std::set del_keys_set = {"p1.k1", "p2.k1", "p3.k1"}; +static const std::vector del_keys = {"manual_compact.once.trigger_time", + "manual_compact.periodic.trigger_time", + "rocksdb.usage_scenario"}; +static const std::set del_keys_set = {"manual_compact.once.trigger_time", + "manual_compact.periodic.trigger_time", + "rocksdb.usage_scenario"}; -static const std::string clear_prefix = "p1"; +static const std::string clear_prefix = "rocksdb"; // if str = "prefix.xxx" then return prefix // else return "" From c446c75dcf02a8335837f45e11188919f372185a Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Mon, 20 Jan 2020 19:14:24 +0800 Subject: [PATCH 08/18] meta env check --- .../meta_server/app_env_validator.cpp | 139 ++++++++++++++++++ .../meta_server/app_env_validator.h | 50 +++++++ .../replication/meta_server/server_state.cpp | 107 +------------- .../replication/meta_server/server_state.h | 4 - 4 files changed, 192 insertions(+), 108 deletions(-) create mode 100644 src/dist/replication/meta_server/app_env_validator.cpp create mode 100644 src/dist/replication/meta_server/app_env_validator.h diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp new file mode 100644 index 0000000000..cf714986e2 --- /dev/null +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -0,0 +1,139 @@ +/* + + * 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. + */ + +#include +#include +#include +#include +#include +#include "app_env_validator.h" + +namespace dsn { +namespace replication { + +bool check_slow_query(const std::string &env_value, std::string &hint_message) +{ + uint64_t threshold = 0; + if (!dsn::buf2uint64(env_value, threshold) || + threshold < replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS) { + hint_message = fmt::format("Slow query threshold must be >= {}ms", + replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS); + return false; + } + return true; +} + +bool check_write_throttling(const std::string &env_value, std::string &hint_message) +{ + std::vector sargs; + utils::split_args(env_value.c_str(), sargs, ','); + if (sargs.empty()) { + hint_message = "The value shouldn't be empty"; + return false; + } + + // example for sarg: 100K*delay*100 / 100M*reject*100 + for (std::string &sarg : sargs) { + std::vector sub_sargs; + utils::split_args(sarg.c_str(), sub_sargs, '*'); + if (sub_sargs.size() != 3) { + hint_message = fmt::format("The field count of {} should be 3", sarg); + return false; + } + + int64_t units = 0; + if (!sub_sargs[0].empty() && + ('M' == *sub_sargs[0].rbegin() || 'K' == *sub_sargs[0].rbegin())) { + sub_sargs[0].pop_back(); + } + if (!buf2int64(sub_sargs[0], units) || units < 0) { + hint_message = fmt::format("{} should be non-negative int", sub_sargs[0]); + return false; + } + + if (sub_sargs[1] != "delay" && sub_sargs[1] != "reject") { + hint_message = fmt::format("{} should be \"delay\" or \"reject\"", sub_sargs[1]); + return false; + } + + int64_t ms = 0; + if (!buf2int64(sub_sargs[2], ms) || ms < 0) { + hint_message = fmt::format("{} should be non-negative int", sub_sargs[2]); + return false; + } + } + + return true; +} + +bool app_env_validator::validate_app_env(const std::string &env_name, + const std::string &env_value, + std::string &hint_message) +{ + auto func_iter = validator_funcs.find(env_name); + if (func_iter != validator_funcs.end()) { + // check function == nullptr means no check + if (nullptr != func_iter->second && !func_iter->second(env_value, hint_message)) { + dwarn_f("{}={} is invalid.", env_name, env_value); + return false; + } + + return true; + } + + hint_message = fmt::format("The env of {} is not supported", env_name); + return false; +} + +void app_env_validator::register_all_validators() +{ + validator_funcs = { + {replica_envs::SLOW_QUERY_THRESHOLD, + std::bind(&check_slow_query, std::placeholders::_1, std::placeholders::_2)}, + {replica_envs::WRITE_QPS_THROTTLING, + std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2)}, + {replica_envs::WRITE_SIZE_THROTTLING, + std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2)}, + // TODO(zhaoliwei): not implemented + {replica_envs::BUSINESS_INFO, nullptr}, + {replica_envs::DENY_CLIENT_WRITE, nullptr}, + {replica_envs::TABLE_LEVEL_DEFAULT_TTL, nullptr}, + {replica_envs::ROCKSDB_USAGE_SCENARIO, nullptr}, + {replica_envs::ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT, nullptr}, + {replica_envs::ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS, nullptr}, + {replica_envs::MANUAL_COMPACT_DISABLED, nullptr}, + {replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT, nullptr}, + {replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME, nullptr}, + {replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL, nullptr}, + {replica_envs::MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION, nullptr}, + {replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME, nullptr}, + {replica_envs::MANUAL_COMPACT_PERIODIC_TARGET_LEVEL, nullptr}, + {replica_envs::MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION, nullptr}}; +} + +} // namespace replication +} // namespace dsn diff --git a/src/dist/replication/meta_server/app_env_validator.h b/src/dist/replication/meta_server/app_env_validator.h new file mode 100644 index 0000000000..fd7a29fe2e --- /dev/null +++ b/src/dist/replication/meta_server/app_env_validator.h @@ -0,0 +1,50 @@ +/* + * 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 + +namespace dsn { +namespace replication { + +class app_env_validator : public ::dsn::utils::singleton +{ +public: + app_env_validator() { register_all_validators(); } + bool validate_app_env(const std::string &env_name, + const std::string &env_value, + std::string &hint_message); + +private: + void register_all_validators(); + + using validator_func = std::function; + std::map validator_funcs; +}; + +} // namespace replication +} // namespace dsn diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index 7a23402a1f..e5c3cfa656 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -46,8 +46,8 @@ #include "server_state.h" #include "server_load_balancer.h" - #include "dump_file.h" +#include "app_env_validator.h" using namespace dsn; @@ -57,61 +57,6 @@ namespace replication { static const char *lock_state = "lock"; static const char *unlock_state = "unlock"; -bool check_slow_query(const std::string &env_value, std::string &hint_message) -{ - uint64_t threshold = 0; - if (!dsn::buf2uint64(env_value, threshold) || - threshold < replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS) { - hint_message = fmt::format("Slow query threshold must be >= {}ms", - replica_envs::MIN_SLOW_QUERY_THRESHOLD_MS); - return false; - } - return true; -} - -bool check_write_throttling(const std::string &env_value, std::string &hint_message) -{ - std::vector sargs; - utils::split_args(env_value.c_str(), sargs, ','); - if (sargs.empty()) { - hint_message = "The value shouldn't be empty"; - return false; - } - - // example for arg: 100K*delay*100 / 100M*reject*100 - for (std::string &sarg : sargs) { - std::vector sub_sargs; - utils::split_args(sarg.c_str(), sub_sargs, '*'); - if (sub_sargs.size() != 3) { - hint_message = fmt::format("The field count of {} should be 3", sarg); - return false; - } - - int64_t units = 0; - if (!sub_sargs[0].empty() && - ('M' == *sub_sargs[0].rbegin() || 'K' == *sub_sargs[0].rbegin())) { - sub_sargs[0].pop_back(); - } - if (!buf2int64(sub_sargs[0], units) || units < 0) { - hint_message = fmt::format("{} should be non-negative int", sub_sargs[0]); - return false; - } - - if (sub_sargs[1] != "delay" && sub_sargs[1] != "reject") { - hint_message = fmt::format("{} should be \"delay\" or \"reject\"", sub_sargs[1]); - return false; - } - - int64_t ms = 0; - if (!buf2int64(sub_sargs[2], ms) || ms < 0) { - hint_message = fmt::format("{} should be non-negative int", sub_sargs[2]); - return false; - }; - } - - return true; -} - server_state::server_state() : _meta_svc(nullptr), _add_secondary_enable_flow_control(false), @@ -120,7 +65,6 @@ server_state::server_state() _ctrl_add_secondary_enable_flow_control(nullptr), _ctrl_add_secondary_max_count_for_one_node(nullptr) { - init_env_check_functions(); } server_state::~server_state() @@ -142,52 +86,6 @@ server_state::~server_state() } } -void server_state::init_env_check_functions() -{ - env_check_functions[replica_envs::SLOW_QUERY_THRESHOLD] = - std::bind(&check_slow_query, std::placeholders::_1, std::placeholders::_2); - env_check_functions[replica_envs::WRITE_QPS_THROTTLING] = - std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2); - env_check_functions[replica_envs::WRITE_SIZE_THROTTLING] = - std::bind(&check_write_throttling, std::placeholders::_1, std::placeholders::_2); - // TODO: not implemented - env_check_functions[replica_envs::BUSINESS_INFO] = nullptr; - env_check_functions[replica_envs::DENY_CLIENT_WRITE] = nullptr; - env_check_functions[replica_envs::TABLE_LEVEL_DEFAULT_TTL] = nullptr; - env_check_functions[replica_envs::ROCKSDB_USAGE_SCENARIO] = nullptr; - env_check_functions[replica_envs::ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT] = nullptr; - env_check_functions[replica_envs::ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_DISABLED] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_ONCE_TRIGGER_TIME] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_ONCE_TARGET_LEVEL] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_PERIODIC_TRIGGER_TIME] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_PERIODIC_TARGET_LEVEL] = nullptr; - env_check_functions[replica_envs::MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION] = - nullptr; -} - -bool server_state::check_app_envs(const std::string &key, - const std::string &value, - std::string &hint_message) -{ - - auto func_iter = env_check_functions.find(key); - if (func_iter != env_check_functions.end()) { - // check function == nullptr means no check - if (nullptr != func_iter->second && !func_iter->second(value, hint_message)) { - dwarn("{}={} is invalid.", key.c_str(), value.c_str()); - return false; - } - - return true; - } - - hint_message = fmt::format("The env of {} is not supported", key); - return false; -} - void server_state::register_cli_commands() { _cli_dump_handle = dsn::command_manager::instance().register_app_command( @@ -2728,7 +2626,8 @@ void server_state::set_app_envs(const app_env_rpc &env_rpc) if (i != 0) os << ", "; - if (!check_app_envs(keys[i], values[i], env_rpc.response().hint_message)) { + if (!app_env_validator::instance().validate_app_env( + keys[i], values[i], env_rpc.response().hint_message)) { env_rpc.response().err = ERR_INVALID_PARAMETERS; return; } diff --git a/src/dist/replication/meta_server/server_state.h b/src/dist/replication/meta_server/server_state.h index 16f83ab836..52f45cb6fd 100644 --- a/src/dist/replication/meta_server/server_state.h +++ b/src/dist/replication/meta_server/server_state.h @@ -297,10 +297,6 @@ class server_state void process_one_partition(std::shared_ptr &app); void transition_staging_state(std::shared_ptr &app); - void init_env_check_functions(); - bool - check_app_envs(const std::string &key, const std::string &value, std::string &hint_message); - private: friend class replication_checker; friend class test::test_checker; From e334e57494d68363b4f5383fdcf71d387640c997 Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Tue, 21 Jan 2020 13:57:10 +0800 Subject: [PATCH 09/18] format --- src/dist/replication/meta_server/app_env_validator.cpp | 6 +++--- src/dist/replication/meta_server/app_env_validator.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index cf714986e2..baed94a176 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -94,8 +94,8 @@ bool app_env_validator::validate_app_env(const std::string &env_name, const std::string &env_value, std::string &hint_message) { - auto func_iter = validator_funcs.find(env_name); - if (func_iter != validator_funcs.end()) { + auto func_iter = _validator_funcs.find(env_name); + if (func_iter != _validator_funcs.end()) { // check function == nullptr means no check if (nullptr != func_iter->second && !func_iter->second(env_value, hint_message)) { dwarn_f("{}={} is invalid.", env_name, env_value); @@ -111,7 +111,7 @@ bool app_env_validator::validate_app_env(const std::string &env_name, void app_env_validator::register_all_validators() { - validator_funcs = { + _validator_funcs = { {replica_envs::SLOW_QUERY_THRESHOLD, std::bind(&check_slow_query, std::placeholders::_1, std::placeholders::_2)}, {replica_envs::WRITE_QPS_THROTTLING, diff --git a/src/dist/replication/meta_server/app_env_validator.h b/src/dist/replication/meta_server/app_env_validator.h index fd7a29fe2e..5f2f33f5ae 100644 --- a/src/dist/replication/meta_server/app_env_validator.h +++ b/src/dist/replication/meta_server/app_env_validator.h @@ -43,7 +43,7 @@ class app_env_validator : public ::dsn::utils::singleton void register_all_validators(); using validator_func = std::function; - std::map validator_funcs; + std::map _validator_funcs; }; } // namespace replication From b4c95d1397144d275ed65d90879b10e87a432925 Mon Sep 17 00:00:00 2001 From: zhaoliwei Date: Tue, 21 Jan 2020 14:32:22 +0800 Subject: [PATCH 10/18] format --- include/dsn/env/replica_envs.h | 59 +++++++++++++++++++ .../replication/common/replication_common.cpp | 1 + .../replication/common/replication_common.h | 23 -------- src/dist/replication/lib/replica_config.cpp | 1 + src/dist/replication/lib/replica_throttle.cpp | 1 + .../meta_server/app_env_validator.cpp | 3 +- .../unit_test/meta_app_envs_test.cpp | 11 ++++ 7 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 include/dsn/env/replica_envs.h diff --git a/include/dsn/env/replica_envs.h b/include/dsn/env/replica_envs.h new file mode 100644 index 0000000000..464427ec45 --- /dev/null +++ b/include/dsn/env/replica_envs.h @@ -0,0 +1,59 @@ +/* + * 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 + +namespace dsn { +namespace replication { + +class replica_envs +{ +public: + static const std::string DENY_CLIENT_WRITE; + static const std::string WRITE_QPS_THROTTLING; + static const std::string WRITE_SIZE_THROTTLING; + static const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; + static const std::string SLOW_QUERY_THRESHOLD; + static const std::string TABLE_LEVEL_DEFAULT_TTL; + static const std::string ROCKSDB_USAGE_SCENARIO; + static const std::string ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT; + static const std::string ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS; + static const std::string MANUAL_COMPACT_DISABLED; + static const std::string MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT; + static const std::string MANUAL_COMPACT_ONCE_TRIGGER_TIME; + static const std::string MANUAL_COMPACT_ONCE_TARGET_LEVEL; + static const std::string MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION; + static const std::string MANUAL_COMPACT_PERIODIC_TRIGGER_TIME; + static const std::string MANUAL_COMPACT_PERIODIC_TARGET_LEVEL; + static const std::string MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION; + static const std::string BUSINESS_INFO; +}; + +} // namespace replication +} // namespace dsn diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 039876db8c..82f670acb3 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -27,6 +27,7 @@ #include "replication_common.h" #include #include +#include namespace dsn { namespace replication { diff --git a/src/dist/replication/common/replication_common.h b/src/dist/replication/common/replication_common.h index 692cd79f6e..148a6f149f 100644 --- a/src/dist/replication/common/replication_common.h +++ b/src/dist/replication/common/replication_common.h @@ -149,29 +149,6 @@ class backup_restore_constant static const std::string SKIP_BAD_PARTITION; }; -class replica_envs -{ -public: - static const std::string DENY_CLIENT_WRITE; - static const std::string WRITE_QPS_THROTTLING; - static const std::string WRITE_SIZE_THROTTLING; - static const uint64_t MIN_SLOW_QUERY_THRESHOLD_MS; - static const std::string SLOW_QUERY_THRESHOLD; - static const std::string TABLE_LEVEL_DEFAULT_TTL; - static const std::string ROCKSDB_USAGE_SCENARIO; - static const std::string ROCKSDB_CHECKPOINT_RESERVE_MIN_COUNT; - static const std::string ROCKSDB_CHECKPOINT_RESERVE_TIME_SECONDS; - static const std::string MANUAL_COMPACT_DISABLED; - static const std::string MANUAL_COMPACT_MAX_CONCURRENT_RUNNING_COUNT; - static const std::string MANUAL_COMPACT_ONCE_TRIGGER_TIME; - static const std::string MANUAL_COMPACT_ONCE_TARGET_LEVEL; - static const std::string MANUAL_COMPACT_ONCE_BOTTOMMOST_LEVEL_COMPACTION; - static const std::string MANUAL_COMPACT_PERIODIC_TRIGGER_TIME; - static const std::string MANUAL_COMPACT_PERIODIC_TARGET_LEVEL; - static const std::string MANUAL_COMPACT_PERIODIC_BOTTOMMOST_LEVEL_COMPACTION; - static const std::string BUSINESS_INFO; -}; - namespace cold_backup { // // Attention: when compose the path on block service, we use appname_appid, because appname_appid diff --git a/src/dist/replication/lib/replica_config.cpp b/src/dist/replication/lib/replica_config.cpp index df1381daed..d89fbfe67d 100644 --- a/src/dist/replication/lib/replica_config.cpp +++ b/src/dist/replication/lib/replica_config.cpp @@ -41,6 +41,7 @@ #include #include #include +#include namespace dsn { namespace replication { diff --git a/src/dist/replication/lib/replica_throttle.cpp b/src/dist/replication/lib/replica_throttle.cpp index 0ba6dc84e6..6352a99e93 100644 --- a/src/dist/replication/lib/replica_throttle.cpp +++ b/src/dist/replication/lib/replica_throttle.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace dsn { namespace replication { diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index baed94a176..6435011fe5 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "app_env_validator.h" namespace dsn { @@ -59,7 +60,7 @@ bool check_write_throttling(const std::string &env_value, std::string &hint_mess // example for sarg: 100K*delay*100 / 100M*reject*100 for (std::string &sarg : sargs) { std::vector sub_sargs; - utils::split_args(sarg.c_str(), sub_sargs, '*'); + utils::split_args(sarg.c_str(), sub_sargs, '*', true); if (sub_sargs.size() != 3) { hint_message = fmt::format("The field count of {} should be 3", sarg); return false; diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index ed6cb4fd81..dd53044053 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include "meta_test_base.h" namespace dsn { @@ -87,6 +88,16 @@ TEST_F(meta_app_envs_test, update_app_envs_test) ERR_INVALID_PARAMETERS, "-100 should be non-negative int", "20M*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, + "2K**delay*100", + ERR_INVALID_PARAMETERS, + "The field count of 2K**delay*100 should be 3", + "20M*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, + "2K*delay**100", + ERR_INVALID_PARAMETERS, + "The field count of 2K*delay**100 should be 3", + "20M*delay*100"}, {replica_envs::WRITE_QPS_THROTTLING, "20M*reject*100", ERR_OK, "", "20M*reject*100"}, {replica_envs::WRITE_SIZE_THROTTLING, "300*delay*100", ERR_OK, "", "300*delay*100"}, {replica_envs::SLOW_QUERY_THRESHOLD, "30", ERR_OK, "", "30"}, From 14d3f527f06e385f8877cab710b6244b3be5b3ad Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 17:08:44 +0800 Subject: [PATCH 11/18] fix --- src/dist/replication/meta_server/app_env_validator.cpp | 4 +--- src/dist/replication/meta_server/app_env_validator.h | 2 +- src/dist/replication/meta_server/server_state.h | 3 --- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index 6435011fe5..5d2e010a8d 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -1,5 +1,4 @@ /* - * The MIT License (MIT) * * Copyright (c) 2015 Microsoft Corporation @@ -25,7 +24,6 @@ * THE SOFTWARE. */ -#include #include #include #include @@ -106,7 +104,7 @@ bool app_env_validator::validate_app_env(const std::string &env_name, return true; } - hint_message = fmt::format("The env of {} is not supported", env_name); + hint_message = fmt::format("app_env \"{}\" is not supported", env_name); return false; } diff --git a/src/dist/replication/meta_server/app_env_validator.h b/src/dist/replication/meta_server/app_env_validator.h index 5f2f33f5ae..1bdb41a18e 100644 --- a/src/dist/replication/meta_server/app_env_validator.h +++ b/src/dist/replication/meta_server/app_env_validator.h @@ -31,7 +31,7 @@ namespace dsn { namespace replication { -class app_env_validator : public ::dsn::utils::singleton +class app_env_validator : public utils::singleton { public: app_env_validator() { register_all_validators(); } diff --git a/src/dist/replication/meta_server/server_state.h b/src/dist/replication/meta_server/server_state.h index 89f1894123..f4fb5fa7de 100644 --- a/src/dist/replication/meta_server/server_state.h +++ b/src/dist/replication/meta_server/server_state.h @@ -339,9 +339,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; - - std::map> - env_check_functions; }; } // namespace replication From aa1b36167c4097d10297ed2cd3edbf660c5c4268 Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 17:21:48 +0800 Subject: [PATCH 12/18] fix --- src/dist/replication/meta_server/app_env_validator.cpp | 7 +++++++ src/dist/replication/meta_server/app_env_validator.h | 4 ++++ src/dist/replication/meta_server/server_state.cpp | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index 5d2e010a8d..310acd2a48 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -34,6 +34,13 @@ namespace dsn { namespace replication { +bool validate_app_env(const std::string &env_name, + const std::string &env_value, + std::string &hint_message) +{ + return app_env_validator::instance().validate_app_env(env_name, env_value, hint_message); +} + bool check_slow_query(const std::string &env_value, std::string &hint_message) { uint64_t threshold = 0; diff --git a/src/dist/replication/meta_server/app_env_validator.h b/src/dist/replication/meta_server/app_env_validator.h index 1bdb41a18e..110575cd46 100644 --- a/src/dist/replication/meta_server/app_env_validator.h +++ b/src/dist/replication/meta_server/app_env_validator.h @@ -31,6 +31,10 @@ namespace dsn { namespace replication { +bool validate_app_env(const std::string &env_name, + const std::string &env_value, + std::string &hint_message); + class app_env_validator : public utils::singleton { public: diff --git a/src/dist/replication/meta_server/server_state.cpp b/src/dist/replication/meta_server/server_state.cpp index e5c3cfa656..1786464b4b 100644 --- a/src/dist/replication/meta_server/server_state.cpp +++ b/src/dist/replication/meta_server/server_state.cpp @@ -2626,8 +2626,7 @@ void server_state::set_app_envs(const app_env_rpc &env_rpc) if (i != 0) os << ", "; - if (!app_env_validator::instance().validate_app_env( - keys[i], values[i], env_rpc.response().hint_message)) { + if (!validate_app_env(keys[i], values[i], env_rpc.response().hint_message)) { env_rpc.response().err = ERR_INVALID_PARAMETERS; return; } From d5b69420c9e60190c6e1524844a6c04a5382d0b3 Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 17:46:38 +0800 Subject: [PATCH 13/18] fix --- .../meta_server/app_env_validator.cpp | 19 ++++++++++++++++++- .../unit_test/meta_app_envs_test.cpp | 10 ++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index 310acd2a48..abd8a3de7c 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -63,6 +63,8 @@ bool check_write_throttling(const std::string &env_value, std::string &hint_mess } // example for sarg: 100K*delay*100 / 100M*reject*100 + bool reject_parsed = false; + bool delay_parsed = false; for (std::string &sarg : sargs) { std::vector sub_sargs; utils::split_args(sarg.c_str(), sub_sargs, '*', true); @@ -71,6 +73,7 @@ bool check_write_throttling(const std::string &env_value, std::string &hint_mess return false; } + // check the first part, which is must be a positive number followed with 'K' or 'M' int64_t units = 0; if (!sub_sargs[0].empty() && ('M' == *sub_sargs[0].rbegin() || 'K' == *sub_sargs[0].rbegin())) { @@ -81,11 +84,25 @@ bool check_write_throttling(const std::string &env_value, std::string &hint_mess return false; } - if (sub_sargs[1] != "delay" && sub_sargs[1] != "reject") { + // check the second part, which is must be "delay" or "reject" + if (sargs1[1] == "delay") { + if (delay_parsed) { + hint_message = "duplicate delay config"; + return false; + } + delay_parsed = true; + } else if (sargs1[1] == "reject") { + if (reject_parsed) { + hint_message = "duplicate reject config"; + return false; + } + reject_parsed = true; + } else { hint_message = fmt::format("{} should be \"delay\" or \"reject\"", sub_sargs[1]); return false; } + // check the third part, which is must be a positive number or 0 int64_t ms = 0; if (!buf2int64(sub_sargs[2], ms) || ms < 0) { hint_message = fmt::format("{} should be non-negative int", sub_sargs[2]); diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index dd53044053..1e57ac7748 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -98,6 +98,16 @@ TEST_F(meta_app_envs_test, update_app_envs_test) ERR_INVALID_PARAMETERS, "The field count of 2K*delay**100 should be 3", "20M*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, + "2K*delay*100,3K*delay*100", + ERR_INVALID_PARAMETERS, + "duplicate delay config", + "20M*delay*100"}, + {replica_envs::WRITE_QPS_THROTTLING, + "2K*reject*100,3K*reject*100", + ERR_INVALID_PARAMETERS, + "duplicate reject config", + "20M*delay*100"}, {replica_envs::WRITE_QPS_THROTTLING, "20M*reject*100", ERR_OK, "", "20M*reject*100"}, {replica_envs::WRITE_SIZE_THROTTLING, "300*delay*100", ERR_OK, "", "300*delay*100"}, {replica_envs::SLOW_QUERY_THRESHOLD, "30", ERR_OK, "", "30"}, From 5bd22ad5d9837c1239ec49a5cc75fab3f98d7eef Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 18:17:40 +0800 Subject: [PATCH 14/18] fix --- src/dist/replication/meta_server/app_env_validator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index abd8a3de7c..355ed889f3 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -85,13 +85,13 @@ bool check_write_throttling(const std::string &env_value, std::string &hint_mess } // check the second part, which is must be "delay" or "reject" - if (sargs1[1] == "delay") { + if (sub_sargs[1] == "delay") { if (delay_parsed) { hint_message = "duplicate delay config"; return false; } delay_parsed = true; - } else if (sargs1[1] == "reject") { + } else if (sub_sargs[1] == "reject") { if (reject_parsed) { hint_message = "duplicate reject config"; return false; From 8c9ed4954c7007cd8ace50e5903b09a1a50276a5 Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 18:31:04 +0800 Subject: [PATCH 15/18] fix --- src/dist/replication/meta_server/app_env_validator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index 355ed889f3..29d564eb49 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -103,8 +103,8 @@ bool check_write_throttling(const std::string &env_value, std::string &hint_mess } // check the third part, which is must be a positive number or 0 - int64_t ms = 0; - if (!buf2int64(sub_sargs[2], ms) || ms < 0) { + int64_t delay_ms = 0; + if (!buf2int64(sub_sargs[2], delay_ms) || delay_ms < 0) { hint_message = fmt::format("{} should be non-negative int", sub_sargs[2]); return false; } From 3fc3c980446d75b171d49df9687adcfb88d6ee2b Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 18:39:02 +0800 Subject: [PATCH 16/18] fix --- include/dsn/{env => dist/replication}/replica_envs.h | 0 src/dist/replication/common/replication_common.cpp | 2 +- src/dist/replication/lib/replica_config.cpp | 2 +- src/dist/replication/lib/replica_throttle.cpp | 2 +- src/dist/replication/meta_server/app_env_validator.cpp | 2 +- .../replication/test/meta_test/unit_test/meta_app_envs_test.cpp | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename include/dsn/{env => dist/replication}/replica_envs.h (100%) diff --git a/include/dsn/env/replica_envs.h b/include/dsn/dist/replication/replica_envs.h similarity index 100% rename from include/dsn/env/replica_envs.h rename to include/dsn/dist/replication/replica_envs.h diff --git a/src/dist/replication/common/replication_common.cpp b/src/dist/replication/common/replication_common.cpp index 82f670acb3..369d70dd0b 100644 --- a/src/dist/replication/common/replication_common.cpp +++ b/src/dist/replication/common/replication_common.cpp @@ -27,7 +27,7 @@ #include "replication_common.h" #include #include -#include +#include namespace dsn { namespace replication { diff --git a/src/dist/replication/lib/replica_config.cpp b/src/dist/replication/lib/replica_config.cpp index d89fbfe67d..9e8b99a5ac 100644 --- a/src/dist/replication/lib/replica_config.cpp +++ b/src/dist/replication/lib/replica_config.cpp @@ -41,7 +41,7 @@ #include #include #include -#include +#include namespace dsn { namespace replication { diff --git a/src/dist/replication/lib/replica_throttle.cpp b/src/dist/replication/lib/replica_throttle.cpp index 6352a99e93..42da66af40 100644 --- a/src/dist/replication/lib/replica_throttle.cpp +++ b/src/dist/replication/lib/replica_throttle.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace dsn { namespace replication { diff --git a/src/dist/replication/meta_server/app_env_validator.cpp b/src/dist/replication/meta_server/app_env_validator.cpp index 29d564eb49..25e7174cfb 100644 --- a/src/dist/replication/meta_server/app_env_validator.cpp +++ b/src/dist/replication/meta_server/app_env_validator.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include "app_env_validator.h" namespace dsn { diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index 1e57ac7748..8d1e866498 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include +#include #include "meta_test_base.h" namespace dsn { From 1e6e104cd995dbf387fa6571290899b79788425f Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 19:15:09 +0800 Subject: [PATCH 17/18] fix --- .../replication/test/meta_test/unit_test/meta_app_envs_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index 8d1e866498..63f03929d0 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -142,7 +142,7 @@ TEST_F(meta_app_envs_test, update_app_envs_test) {"not_exist_env", "500", ERR_INVALID_PARAMETERS, - "The env of not_exist_env is not supported", + "The env of \"not_exist_env\" is not supported", ""}}; auto app = find_app(app_name); From 54c41fe4d8ced7b9fcf36b33bdad0d84df003d75 Mon Sep 17 00:00:00 2001 From: levy5307 Date: Mon, 3 Feb 2020 19:18:44 +0800 Subject: [PATCH 18/18] fix --- .../replication/test/meta_test/unit_test/meta_app_envs_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp index 63f03929d0..57f0fe3f59 100644 --- a/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp +++ b/src/dist/replication/test/meta_test/unit_test/meta_app_envs_test.cpp @@ -142,7 +142,7 @@ TEST_F(meta_app_envs_test, update_app_envs_test) {"not_exist_env", "500", ERR_INVALID_PARAMETERS, - "The env of \"not_exist_env\" is not supported", + "app_env \"not_exist_env\" is not supported", ""}}; auto app = find_app(app_name);