From 7806dc147147a588fa3a590c030b0fdcdd56e6f2 Mon Sep 17 00:00:00 2001 From: heyuchen Date: Thu, 24 Dec 2020 15:43:34 +0800 Subject: [PATCH] feat: add update rocksdb scenario interface --- src/meta/meta_http_service.cpp | 60 ++++++++++++++++++++++++ src/meta/meta_http_service.h | 20 ++++++++ src/meta/test/meta_http_service_test.cpp | 37 +++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/src/meta/meta_http_service.cpp b/src/meta/meta_http_service.cpp index c9552b29ee..9c29247736 100644 --- a/src/meta/meta_http_service.cpp +++ b/src/meta/meta_http_service.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -699,6 +700,39 @@ void meta_http_service::query_bulk_load_handler(const http_request &req, http_re resp.status_code = http_status_code::ok; } +void meta_http_service::update_scenario_handler(const http_request &req, http_response &resp) +{ + if (!redirect_if_not_primary(req, resp)) { + return; + } + + // validate paramters + usage_scenario_info info; + bool ret = json::json_forwarder::decode(req.body, info); + if (!ret) { + resp.body = "invalid request structure"; + resp.status_code = http_status_code::bad_request; + return; + } + if (info.app_name.empty()) { + resp.body = "app_name should not be empty"; + resp.status_code = http_status_code::bad_request; + return; + } + if (info.scenario.empty() || (info.scenario != "bulk_load" && info.scenario != "normal")) { + resp.body = "scenario should ony be 'normal' or 'bulk_load'"; + resp.status_code = http_status_code::bad_request; + return; + } + + // create configuration_update_app_env_request + std::vector keys; + std::vector values; + keys.emplace_back(replica_envs::ROCKSDB_USAGE_SCENARIO); + values.emplace_back(info.scenario); + update_app_env(info.app_name, keys, values, resp); +} + bool meta_http_service::redirect_if_not_primary(const http_request &req, http_response &resp) { #ifdef DSN_MOCK_TEST @@ -722,5 +756,31 @@ bool meta_http_service::redirect_if_not_primary(const http_request &req, http_re return false; } +void meta_http_service::update_app_env(const std::string &app_name, + const std::vector &keys, + const std::vector &values, + http_response &resp) +{ + configuration_update_app_env_request request; + request.app_name = app_name; + request.op = app_env_operation::APP_ENV_OP_SET; + request.__set_keys(keys); + request.__set_values(values); + + auto rpc_req = dsn::make_unique(request); + update_app_env_rpc rpc(std::move(rpc_req), LPC_META_STATE_NORMAL); + _service->_state->set_app_envs(rpc); + + auto rpc_resp = rpc.response(); + // output as json format + dsn::utils::table_printer tp; + tp.add_row_name_and_data("error", rpc_resp.err.to_string()); + tp.add_row_name_and_data("hint_message", rpc_resp.hint_message); + std::ostringstream out; + tp.output(out, dsn::utils::table_printer::output_format::kJsonCompact); + resp.body = out.str(); + resp.status_code = http_status_code::ok; +} + } // namespace replication } // namespace dsn diff --git a/src/meta/meta_http_service.h b/src/meta/meta_http_service.h index e857df176f..a66e28cf72 100644 --- a/src/meta/meta_http_service.h +++ b/src/meta/meta_http_service.h @@ -15,6 +15,13 @@ namespace replication { NON_MEMBER_JSON_SERIALIZATION( start_bulk_load_request, app_name, cluster_name, file_provider_type, remote_root_path) +struct usage_scenario_info +{ + std::string app_name; + std::string scenario; // normal or bulk_load + DEFINE_JSON_SERIALIZATION(app_name, scenario) +}; + class meta_service; class meta_http_service : public http_service { @@ -76,6 +83,13 @@ class meta_http_service : public http_service std::placeholders::_1, std::placeholders::_2), "ip:port/meta/query_bulk_load?name=temp"); + // request body should be usage_scenario_info + register_handler("app/usage_scenario", + std::bind(&meta_http_service::update_scenario_handler, + this, + std::placeholders::_1, + std::placeholders::_2), + "ip:port/meta/app/usage_scenario"); } std::string path() const override { return "meta"; } @@ -89,11 +103,17 @@ class meta_http_service : public http_service void query_duplication_handler(const http_request &req, http_response &resp); void start_bulk_load_handler(const http_request &req, http_response &resp); void query_bulk_load_handler(const http_request &req, http_response &resp); + void update_scenario_handler(const http_request &req, http_response &resp); private: // set redirect location if current server is not primary bool redirect_if_not_primary(const http_request &req, http_response &resp); + void update_app_env(const std::string &app_name, + const std::vector &keys, + const std::vector &values, + http_response &resp); + meta_service *_service; }; diff --git a/src/meta/test/meta_http_service_test.cpp b/src/meta/test/meta_http_service_test.cpp index 7902e17199..eddf925b09 100644 --- a/src/meta/test/meta_http_service_test.cpp +++ b/src/meta/test/meta_http_service_test.cpp @@ -214,6 +214,15 @@ class meta_bulk_load_http_test : public meta_test_base return resp.body; } + http_response test_update_scenario(std::string req_body_json) + { + http_request req; + http_response resp; + req.body = blob::create_from_bytes(std::move(req_body_json)); + _mhs->update_scenario_handler(req, resp); + return resp; + } + void mock_bulk_load_context(const bulk_load_status::type &status) { auto app = find_app(APP_NAME); @@ -300,5 +309,33 @@ TEST_F(meta_bulk_load_http_test, query_bulk_load_request) drop_app(NOT_BULK_LOAD); } +TEST_F(meta_bulk_load_http_test, update_scenario_test) +{ + struct update_scenario_test + { + std::string request_json; + http_status_code expected_code; + std::string expected_response_json; + } tests[] = {{R"({"app":"test_bulk_load","scenario":"normal"})", + http_status_code::bad_request, + "invalid request structure"}, + {R"({"app_name":"test_bulk_load","scenario":"wrong"})", + http_status_code::bad_request, + "scenario should ony be 'normal' or 'bulk_load'"}, + {R"({"app_name":"test_bulk_load","scenario":"bulk_load"})", + http_status_code::ok, + R"({"error":"ERR_OK","hint_message":""})"}}; + + for (const auto &test : tests) { + http_response resp = test_update_scenario(test.request_json); + ASSERT_EQ(resp.status_code, test.expected_code); + std::string expected_json = test.expected_response_json; + if (test.expected_code == http_status_code::ok) { + expected_json += "\n"; + } + ASSERT_EQ(resp.body, expected_json); + } +} + } // namespace replication } // namespace dsn