This is an automated email from the ASF dual-hosted git repository.

laiyingchun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pegasus.git


The following commit(s) were added to refs/heads/master by this push:
     new 2fe716b5e feat: add rename_app interface  (#1272)
2fe716b5e is described below

commit 2fe716b5ef4f714412ebf27ed39a827d6a8769fd
Author: liguohao <[email protected]>
AuthorDate: Wed Dec 14 19:53:44 2022 +0800

    feat: add rename_app interface  (#1272)
---
 idl/meta_admin.thrift                     | 12 +++++
 src/client/replication_ddl_client.cpp     | 20 ++++++++
 src/client/replication_ddl_client.h       |  3 ++
 src/common/replication.codes.h            |  1 +
 src/meta/meta_rpc_types.h                 |  2 +
 src/meta/meta_service.cpp                 | 14 ++++++
 src/meta/meta_service.h                   |  1 +
 src/meta/server_state.cpp                 | 79 +++++++++++++++++++++++++++++++
 src/meta/server_state.h                   |  1 +
 src/meta/test/meta_app_operation_test.cpp | 44 +++++++++++++++++
 src/replica/replica.h                     |  1 +
 src/replica/replica_config.cpp            | 19 ++++++++
 src/shell/commands.h                      |  2 +
 src/shell/commands/table_management.cpp   | 37 +++++++++++++++
 src/shell/main.cpp                        |  3 ++
 15 files changed, 239 insertions(+)

diff --git a/idl/meta_admin.thrift b/idl/meta_admin.thrift
index 9db6758db..fd29a2a77 100644
--- a/idl/meta_admin.thrift
+++ b/idl/meta_admin.thrift
@@ -166,6 +166,18 @@ struct configuration_drop_app_response
     1:dsn.error_code   err;
 }
 
+struct configuration_rename_app_request
+{
+    1:string old_app_name;
+    2:string new_app_name;
+}
+
+struct configuration_rename_app_response
+{
+    1:dsn.error_code err;
+    2:string hint_message;
+}
+
 struct configuration_recall_app_request
 {
     1:i32 app_id;
diff --git a/src/client/replication_ddl_client.cpp 
b/src/client/replication_ddl_client.cpp
index 406b9d073..63e275484 100644
--- a/src/client/replication_ddl_client.cpp
+++ b/src/client/replication_ddl_client.cpp
@@ -53,6 +53,15 @@
 namespace dsn {
 namespace replication {
 
+#define VALIDATE_TABLE_NAME(app_name)                                          
                    \
+    do {                                                                       
                    \
+        if (app_name.empty() ||                                                
                    \
+            !std::all_of(app_name.cbegin(),                                    
                    \
+                         app_name.cend(),                                      
                    \
+                         (bool 
(*)(int))replication_ddl_client::valid_app_char))                   \
+            return FMT_ERR(ERR_INVALID_PARAMETERS, "Invalid name. Only 
0-9a-zA-Z.:_ are valid!");  \
+    } while (false)
+
 using tp_output_format = ::dsn::utils::table_printer::output_format;
 
 replication_ddl_client::replication_ddl_client(const 
std::vector<dsn::rpc_address> &meta_servers)
@@ -1740,5 +1749,16 @@ replication_ddl_client::set_max_replica_count(const 
std::string &app_name,
         configuration_set_max_replica_count_rpc(std::move(req), 
RPC_CM_SET_MAX_REPLICA_COUNT));
 }
 
+error_with<configuration_rename_app_response>
+replication_ddl_client::rename_app(const std::string &old_app_name, const 
std::string &new_app_name)
+{
+    VALIDATE_TABLE_NAME(old_app_name);
+    VALIDATE_TABLE_NAME(new_app_name);
+
+    auto req = std::make_unique<configuration_rename_app_request>();
+    req->__set_old_app_name(old_app_name);
+    req->__set_new_app_name(new_app_name);
+    return call_rpc_sync(configuration_rename_app_rpc(std::move(req), 
RPC_CM_RENAME_APP));
+}
 } // namespace replication
 } // namespace dsn
diff --git a/src/client/replication_ddl_client.h 
b/src/client/replication_ddl_client.h
index 5b562f7bb..f3350f5fe 100644
--- a/src/client/replication_ddl_client.h
+++ b/src/client/replication_ddl_client.h
@@ -72,6 +72,9 @@ public:
 
     dsn::error_code recall_app(int32_t app_id, const std::string 
&new_app_name);
 
+    error_with<configuration_rename_app_response> rename_app(const std::string 
&old_app_name,
+                                                             const std::string 
&new_app_name);
+
     dsn::error_code list_apps(const dsn::app_status::type status,
                               bool show_all,
                               bool detailed,
diff --git a/src/common/replication.codes.h b/src/common/replication.codes.h
index c39a969d4..73df12497 100644
--- a/src/common/replication.codes.h
+++ b/src/common/replication.codes.h
@@ -93,6 +93,7 @@ MAKE_EVENT_CODE_RPC(RPC_CM_UPDATE_PARTITION_CONFIGURATION, 
TASK_PRIORITY_COMMON)
 MAKE_EVENT_CODE_RPC(RPC_CM_CREATE_APP, TASK_PRIORITY_COMMON)
 MAKE_EVENT_CODE_RPC(RPC_CM_DROP_APP, TASK_PRIORITY_COMMON)
 MAKE_EVENT_CODE_RPC(RPC_CM_RECALL_APP, TASK_PRIORITY_COMMON)
+MAKE_EVENT_CODE_RPC(RPC_CM_RENAME_APP, TASK_PRIORITY_COMMON)
 MAKE_EVENT_CODE_RPC(RPC_CM_LIST_APPS, TASK_PRIORITY_COMMON)
 MAKE_EVENT_CODE_RPC(RPC_CM_LIST_NODES, TASK_PRIORITY_COMMON)
 MAKE_EVENT_CODE_RPC(RPC_CM_CLUSTER_INFO, TASK_PRIORITY_COMMON)
diff --git a/src/meta/meta_rpc_types.h b/src/meta/meta_rpc_types.h
index 746158915..7044e09b9 100644
--- a/src/meta/meta_rpc_types.h
+++ b/src/meta/meta_rpc_types.h
@@ -68,6 +68,8 @@ typedef 
rpc_holder<configuration_get_max_replica_count_request,
 typedef rpc_holder<configuration_set_max_replica_count_request,
                    configuration_set_max_replica_count_response>
     configuration_set_max_replica_count_rpc;
+typedef rpc_holder<configuration_rename_app_request, 
configuration_rename_app_response>
+    configuration_rename_app_rpc;
 
 } // namespace replication
 } // namespace dsn
diff --git a/src/meta/meta_service.cpp b/src/meta/meta_service.cpp
index 176b811a4..9b1de0997 100644
--- a/src/meta/meta_service.cpp
+++ b/src/meta/meta_service.cpp
@@ -401,6 +401,8 @@ void meta_service::register_rpc_handlers()
     register_rpc_handler(RPC_CM_CREATE_APP, "create_app", 
&meta_service::on_create_app);
     register_rpc_handler(RPC_CM_DROP_APP, "drop_app", 
&meta_service::on_drop_app);
     register_rpc_handler(RPC_CM_RECALL_APP, "recall_app", 
&meta_service::on_recall_app);
+    register_rpc_handler_with_rpc_holder(
+        RPC_CM_RENAME_APP, "rename_app", &meta_service::on_rename_app);
     register_rpc_handler_with_rpc_holder(
         RPC_CM_LIST_APPS, "list_apps", &meta_service::on_list_apps);
     register_rpc_handler_with_rpc_holder(
@@ -527,6 +529,18 @@ void meta_service::on_drop_app(dsn::message_ex *req)
                      server_state::sStateHash);
 }
 
+void meta_service::on_rename_app(configuration_rename_app_rpc rpc)
+{
+    if (!check_status(rpc)) {
+        return;
+    }
+
+    tasking::enqueue(LPC_META_STATE_NORMAL,
+                     tracker(),
+                     std::bind(&server_state::rename_app, _state.get(), rpc),
+                     server_state::sStateHash);
+}
+
 void meta_service::on_recall_app(dsn::message_ex *req)
 {
     configuration_recall_app_response response;
diff --git a/src/meta/meta_service.h b/src/meta/meta_service.h
index 3cfb23518..f41819cb9 100644
--- a/src/meta/meta_service.h
+++ b/src/meta/meta_service.h
@@ -194,6 +194,7 @@ private:
     void on_create_app(dsn::message_ex *req);
     void on_drop_app(dsn::message_ex *req);
     void on_recall_app(dsn::message_ex *req);
+    void on_rename_app(configuration_rename_app_rpc rpc);
     void on_list_apps(configuration_list_apps_rpc rpc);
     void on_list_nodes(configuration_list_nodes_rpc rpc);
 
diff --git a/src/meta/server_state.cpp b/src/meta/server_state.cpp
index 558acb53b..475504f29 100644
--- a/src/meta/server_state.cpp
+++ b/src/meta/server_state.cpp
@@ -1259,6 +1259,85 @@ void server_state::drop_app(dsn::message_ex *msg)
     }
 }
 
+void server_state::rename_app(configuration_rename_app_rpc rpc)
+{
+    auto &response = rpc.response();
+    bool do_rename = false;
+
+    const auto &old_app_name = rpc.request().old_app_name;
+    const auto &new_app_name = rpc.request().new_app_name;
+    LOG_INFO_F(
+        "rename app request, old_app_name({}), new_app_name({})", 
old_app_name, new_app_name);
+
+    zauto_write_lock l(_lock);
+    auto target_app = get_app(old_app_name);
+
+    if (target_app == nullptr) {
+        response.err = ERR_APP_NOT_EXIST;
+        response.hint_message = fmt::format("ERROR: app({}) not exist!", 
old_app_name);
+        return;
+    }
+
+    switch (target_app->status) {
+    case app_status::AS_AVAILABLE: {
+        if (_exist_apps.find(new_app_name) != _exist_apps.end()) {
+            response.err = ERR_INVALID_PARAMETERS;
+            response.hint_message = fmt::format("ERROR: app({}) already 
exist!", new_app_name);
+            return;
+        }
+        do_rename = true;
+    } break;
+    case app_status::AS_CREATING:
+    case app_status::AS_RECALLING: {
+        response.err = ERR_BUSY_CREATING;
+    } break;
+    case app_status::AS_DROPPING: {
+        response.err = ERR_BUSY_DROPPING;
+    } break;
+    case app_status::AS_DROPPED: {
+        response.err = ERR_APP_DROPPED;
+    } break;
+    default: {
+        response.err = ERR_INVALID_STATE;
+    } break;
+    }
+
+    if (!do_rename) {
+        response.hint_message =
+            fmt::format("ERROR: app({}) status can't execute rename.", 
old_app_name);
+        return;
+    }
+
+    auto app_id = target_app->app_id;
+
+    auto ainfo = *(reinterpret_cast<app_info *>(target_app.get()));
+    ainfo.app_name = new_app_name;
+    auto app_path = get_app_path(*target_app);
+
+    target_app->app_name = new_app_name;
+    _exist_apps.emplace(new_app_name, target_app);
+
+    do_update_app_info(
+        app_path, ainfo, [this, app_id, new_app_name, old_app_name](error_code 
ec) mutable {
+            CHECK_EQ_MSG(
+                ec,
+                ERR_OK,
+                "update remote app info failed: app_id={}, old_app_name={}, 
new_app_name={}",
+                app_id,
+                old_app_name,
+                new_app_name);
+
+            zauto_write_lock l(_lock);
+            _exist_apps.erase(old_app_name);
+
+            LOG_INFO_F("both remote and local app info of app_name have been 
updated "
+                       "successfully: app_id={}, old_app_name={}, 
new_app_name={}",
+                       app_id,
+                       old_app_name,
+                       new_app_name);
+        });
+}
+
 void server_state::do_app_recall(std::shared_ptr<app_state> &app)
 {
     auto after_recall_app = [this, app](dsn::error_code ec) mutable {
diff --git a/src/meta/server_state.h b/src/meta/server_state.h
index 374823a92..e761a42e0 100644
--- a/src/meta/server_state.h
+++ b/src/meta/server_state.h
@@ -144,6 +144,7 @@ public:
     void create_app(dsn::message_ex *msg);
     void drop_app(dsn::message_ex *msg);
     void recall_app(dsn::message_ex *msg);
+    void rename_app(configuration_rename_app_rpc rpc);
     void list_apps(const configuration_list_apps_request &request,
                    configuration_list_apps_response &response);
     void restore_app(dsn::message_ex *msg);
diff --git a/src/meta/test/meta_app_operation_test.cpp 
b/src/meta/test/meta_app_operation_test.cpp
index b9f034e32..33246addf 100644
--- a/src/meta/test/meta_app_operation_test.cpp
+++ b/src/meta/test/meta_app_operation_test.cpp
@@ -171,6 +171,20 @@ public:
         return rpc.response();
     }
 
+    configuration_rename_app_response rename_app(const std::string 
&old_app_name,
+                                                 const std::string 
&new_app_name)
+    {
+        auto req = dsn::make_unique<configuration_rename_app_request>();
+        req->__set_old_app_name(old_app_name);
+        req->__set_new_app_name(new_app_name);
+
+        configuration_rename_app_rpc rpc(std::move(req), RPC_CM_RENAME_APP);
+        _ss->rename_app(rpc);
+        _ss->wait_all_task();
+
+        return rpc.response();
+    }
+
     void set_app_and_all_partitions_max_replica_count(const std::string 
&app_name,
                                                       int32_t 
max_replica_count)
     {
@@ -795,5 +809,35 @@ TEST_F(meta_app_operation_test, 
recover_from_max_replica_count_env)
     verify_app_max_replica_count(APP_NAME, new_max_replica_count);
 }
 
+TEST_F(meta_app_operation_test, rename_app)
+{
+    const std::string app_name_1 = APP_NAME + "_rename_1";
+    create_app(app_name_1);
+    auto app = find_app(app_name_1);
+    ASSERT_TRUE(app) << fmt::format("app({}) does not exist", app_name_1);
+    auto app_id_1 = app->app_id;
+
+    const std::string app_name_2 = APP_NAME + "_rename_2";
+    create_app(app_name_2);
+    app = find_app(app_name_2);
+    ASSERT_TRUE(app) << fmt::format("app({}) does not exist", app_name_2);
+    auto app_id_2 = app->app_id;
+
+    // case 1: new_app_name table exist
+    auto resp = rename_app(app_name_1, app_name_2);
+    ASSERT_EQ(ERR_INVALID_PARAMETERS, resp.err);
+
+    const std::string app_name_3 = APP_NAME + "_rename_3";
+    // case 2: old_app_name table not exist
+    resp = rename_app(APP_NAME + "_rename_invaild", app_name_3);
+    ASSERT_EQ(ERR_APP_NOT_EXIST, resp.err);
+
+    // case 3: rename successful
+    resp = rename_app(app_name_1, app_name_3);
+    ASSERT_EQ(ERR_OK, resp.err);
+    app = find_app(app_name_3);
+    ASSERT_TRUE(app) << fmt::format("app({}) does not exist", app_name_3);
+    ASSERT_EQ(app_id_1, app->app_id);
+}
 } // namespace replication
 } // namespace dsn
diff --git a/src/replica/replica.h b/src/replica/replica.h
index 7c578f200..20c9877dd 100644
--- a/src/replica/replica.h
+++ b/src/replica/replica.h
@@ -496,6 +496,7 @@ private:
     clear_on_failure(replica_stub *stub, replica *rep, const std::string 
&path, const gpid &pid);
 
     void update_app_max_replica_count(int32_t max_replica_count);
+    void update_app_name(const std::string &app_name);
 
 private:
     friend class ::dsn::replication::test::test_checker;
diff --git a/src/replica/replica_config.cpp b/src/replica/replica_config.cpp
index 47347813e..9f481b7a0 100644
--- a/src/replica/replica_config.cpp
+++ b/src/replica/replica_config.cpp
@@ -1029,6 +1029,7 @@ void replica::on_config_sync(const app_info &info,
         return;
 
     update_app_max_replica_count(info.max_replica_count);
+    update_app_name(info.app_name);
     update_app_envs(info.envs);
     _is_duplication_master = info.duplicating;
 
@@ -1070,6 +1071,24 @@ void replica::on_config_sync(const app_info &info,
     }
 }
 
+void replica::update_app_name(const std::string &app_name)
+{
+    if (app_name == _app_info.app_name) {
+        return;
+    }
+
+    auto old_app_name = _app_info.app_name;
+    _app_info.app_name = app_name;
+
+    CHECK_EQ_PREFIX_MSG(store_app_info(_app_info),
+                        ERR_OK,
+                        "store_app_info for app_name failed: "
+                        "app_name={}, app_id={}, old_app_name={}",
+                        _app_info.app_name,
+                        _app_info.app_id,
+                        old_app_name);
+}
+
 void replica::update_app_max_replica_count(int32_t max_replica_count)
 {
     if (max_replica_count == _app_info.max_replica_count) {
diff --git a/src/shell/commands.h b/src/shell/commands.h
index 468532655..1245f1d3a 100644
--- a/src/shell/commands.h
+++ b/src/shell/commands.h
@@ -145,6 +145,8 @@ bool drop_app(command_executor *e, shell_context *sc, 
arguments args);
 
 bool recall_app(command_executor *e, shell_context *sc, arguments args);
 
+bool rename_app(command_executor *e, shell_context *sc, arguments args);
+
 bool get_app_envs(command_executor *e, shell_context *sc, arguments args);
 
 bool set_app_envs(command_executor *e, shell_context *sc, arguments args);
diff --git a/src/shell/commands/table_management.cpp 
b/src/shell/commands/table_management.cpp
index f78a9a755..b9a6871e8 100644
--- a/src/shell/commands/table_management.cpp
+++ b/src/shell/commands/table_management.cpp
@@ -721,6 +721,43 @@ bool drop_app(command_executor *e, shell_context *sc, 
arguments args)
     return true;
 }
 
+bool rename_app(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc <= 2) {
+        return false;
+    }
+
+    const std::string old_app_name = args.argv[1];
+    const std::string new_app_name = args.argv[2];
+
+    auto err_resp = sc->ddl_client->rename_app(old_app_name, new_app_name);
+    auto err = err_resp.get_error();
+    const auto &resp = err_resp.get_value();
+
+    if (dsn_likely(err.is_ok())) {
+        err = dsn::error_s::make(resp.err);
+    }
+
+    if (err.is_ok()) {
+        fmt::print(stdout,
+                   "rename app ok, old_app_name({}), new_app_name({})\n",
+                   old_app_name,
+                   new_app_name);
+    } else {
+        std::string error_message(resp.err.to_string());
+        if (!resp.hint_message.empty()) {
+            error_message += ", ";
+            error_message += resp.hint_message;
+        }
+        fmt::print(stderr,
+                   "rename app failed, old_app_name({}), new_app_name({}), 
failed: {}\n",
+                   old_app_name,
+                   new_app_name,
+                   error_message);
+    }
+    return true;
+}
+
 bool recall_app(command_executor *e, shell_context *sc, arguments args)
 {
     if (args.argc <= 1)
diff --git a/src/shell/main.cpp b/src/shell/main.cpp
index d58340cf1..766f5d863 100644
--- a/src/shell/main.cpp
+++ b/src/shell/main.cpp
@@ -91,6 +91,9 @@ static command_executor commands[] = {
     {
         "recall", "recall an app", "<app_id> [new_app_name]", recall_app,
     },
+    {
+        "rename", "rename an app", "<old_app_name> <new_app_name>", rename_app,
+    },
     {
         "set_meta_level",
         "set the meta function level: stopped, blind, freezed, steady, lively",


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to