You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pegasus.apache.org by GitBox <gi...@apache.org> on 2022/06/06 09:23:35 UTC

[GitHub] [incubator-pegasus] acelyc111 commented on a diff in pull request #914: feat(update_replication_factor#10): support to get/set the replication factor of each table by shell and add max_reserved_dropped_replicas to config file

acelyc111 commented on code in PR #914:
URL: https://github.com/apache/incubator-pegasus/pull/914#discussion_r889958361


##########
src/shell/command_utils.cpp:
##########
@@ -45,3 +45,35 @@ bool validate_ip(shell_context *sc,
     err_info = fmt::format("invalid ip:port={}, can't find it in the cluster", ip_str);
     return false;
 }
+
+bool confirm_unsafe_command(const std::string &action)
+{
+    const int max_attempts = 5;
+    int attempts = 0;
+    for (; attempts < max_attempts; ++attempts) {
+        fmt::print(stdout,
+                   "PLEASE be CAUTIOUS with this operation ! "
+                   "Are you sure to {} ? [Y/n]: ",
+                   action);
+
+        int choice = fgetc(stdin);
+        int len = 0;
+        for (int c = choice; c != '\n' && c != EOF; ++len) {
+            c = fgetc(stdin);
+        }
+        if (len != 1) {
+            continue;
+        }
+
+        if (choice == 'Y') {

Review Comment:
   If 'Y' is not the default selection, use 'y'



##########
src/shell/commands/table_management.cpp:
##########
@@ -886,3 +888,105 @@ bool clear_app_envs(command_executor *e, shell_context *sc, arguments args)
     }
     return true;
 }
+
+bool get_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 2) {
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+
+    auto err_resp = sc->ddl_client->get_max_replica_count(app_name);
+    auto err = err_resp.get_error();
+    const auto &resp = err_resp.get_value();
+
+    if (err.is_ok()) {
+        err = dsn::error_s::make(resp.err);
+    }
+
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    if (err.is_ok()) {
+        fmt::print(stdout,
+                   "the replica count of app({}) is {}\n",
+                   escaped_app_name,
+                   resp.max_replica_count);

Review Comment:
   It's better to output also in JSON, so we can parse easily in 3rd party tools.



##########
src/shell/commands/table_management.cpp:
##########
@@ -886,3 +888,105 @@ bool clear_app_envs(command_executor *e, shell_context *sc, arguments args)
     }
     return true;
 }
+
+bool get_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 2) {
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+
+    auto err_resp = sc->ddl_client->get_max_replica_count(app_name);
+    auto err = err_resp.get_error();
+    const auto &resp = err_resp.get_value();
+
+    if (err.is_ok()) {
+        err = dsn::error_s::make(resp.err);
+    }
+
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    if (err.is_ok()) {
+        fmt::print(stdout,
+                   "the replica count of app({}) is {}\n",
+                   escaped_app_name,
+                   resp.max_replica_count);
+    } else {
+        fmt::print(stdout, "get replica count of app({}) failed: {}\n", escaped_app_name, err);
+    }
+
+    return true;
+}
+
+bool set_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 3) {
+        return false;
+    }
+
+    int new_max_replica_count;
+    if (!dsn::buf2int32(args.argv[2], new_max_replica_count)) {
+        fmt::print(stderr, "parse {} as replica count failed\n", args.argv[2]);
+        return false;
+    }
+
+    if (new_max_replica_count < 1) {
+        fmt::print(stderr, "replica count should be >= 1\n");
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    std::string action(fmt::format(
+        "set the replica count of app({}) to {}", escaped_app_name, new_max_replica_count));
+    if (!confirm_unsafe_command(action)) {
+        return true;
+    }
+
+    auto err_resp = sc->ddl_client->set_max_replica_count(app_name, new_max_replica_count);
+    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()) {
+        if (new_max_replica_count == resp.old_max_replica_count) {
+            fmt::print(stdout,
+                       "set replica count of app({}) from {} to {}: {}\n",
+                       escaped_app_name,
+                       resp.old_max_replica_count,
+                       new_max_replica_count,
+                       resp.hint_message);
+        } else {
+            fmt::print(stdout,
+                       "set replica count of app({}) from {} to {} successfully\n",
+                       escaped_app_name,
+                       resp.old_max_replica_count,
+                       new_max_replica_count);
+        }
+    } else {
+        std::string error_message(resp.err.to_string());
+        if (!resp.hint_message.empty()) {
+            error_message += ", ";
+            error_message += resp.hint_message;
+        }
+
+        if (resp.old_max_replica_count > 0) {
+            fmt::print(stdout,
+                       "set replica count of app({}) from {} to {} failed: {}\n",
+                       escaped_app_name,
+                       resp.old_max_replica_count,
+                       new_max_replica_count,
+                       error_message);
+        } else {
+            fmt::print(stdout,

Review Comment:
   How this case happend?



##########
src/shell/commands/table_management.cpp:
##########
@@ -886,3 +888,105 @@ bool clear_app_envs(command_executor *e, shell_context *sc, arguments args)
     }
     return true;
 }
+
+bool get_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 2) {
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+
+    auto err_resp = sc->ddl_client->get_max_replica_count(app_name);
+    auto err = err_resp.get_error();
+    const auto &resp = err_resp.get_value();
+
+    if (err.is_ok()) {
+        err = dsn::error_s::make(resp.err);
+    }
+
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    if (err.is_ok()) {
+        fmt::print(stdout,
+                   "the replica count of app({}) is {}\n",
+                   escaped_app_name,
+                   resp.max_replica_count);
+    } else {
+        fmt::print(stdout, "get replica count of app({}) failed: {}\n", escaped_app_name, err);
+    }
+
+    return true;
+}
+
+bool set_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 3) {
+        return false;
+    }
+
+    int new_max_replica_count;
+    if (!dsn::buf2int32(args.argv[2], new_max_replica_count)) {
+        fmt::print(stderr, "parse {} as replica count failed\n", args.argv[2]);

Review Comment:
   ```suggestion
           fmt::print(stderr, "parse '{}' as replica count failed\n", args.argv[2]);
   ```



##########
src/shell/commands/table_management.cpp:
##########
@@ -886,3 +888,105 @@ bool clear_app_envs(command_executor *e, shell_context *sc, arguments args)
     }
     return true;
 }
+
+bool get_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 2) {
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+
+    auto err_resp = sc->ddl_client->get_max_replica_count(app_name);
+    auto err = err_resp.get_error();
+    const auto &resp = err_resp.get_value();
+
+    if (err.is_ok()) {
+        err = dsn::error_s::make(resp.err);
+    }
+
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    if (err.is_ok()) {
+        fmt::print(stdout,
+                   "the replica count of app({}) is {}\n",
+                   escaped_app_name,
+                   resp.max_replica_count);
+    } else {
+        fmt::print(stdout, "get replica count of app({}) failed: {}\n", escaped_app_name, err);
+    }
+
+    return true;
+}
+
+bool set_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 3) {
+        return false;
+    }
+
+    int new_max_replica_count;
+    if (!dsn::buf2int32(args.argv[2], new_max_replica_count)) {
+        fmt::print(stderr, "parse {} as replica count failed\n", args.argv[2]);
+        return false;
+    }
+
+    if (new_max_replica_count < 1) {
+        fmt::print(stderr, "replica count should be >= 1\n");
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    std::string action(fmt::format(
+        "set the replica count of app({}) to {}", escaped_app_name, new_max_replica_count));
+    if (!confirm_unsafe_command(action)) {
+        return true;
+    }
+
+    auto err_resp = sc->ddl_client->set_max_replica_count(app_name, new_max_replica_count);
+    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()) {
+        if (new_max_replica_count == resp.old_max_replica_count) {
+            fmt::print(stdout,
+                       "set replica count of app({}) from {} to {}: {}\n",
+                       escaped_app_name,
+                       resp.old_max_replica_count,
+                       new_max_replica_count,
+                       resp.hint_message);
+        } else {
+            fmt::print(stdout,
+                       "set replica count of app({}) from {} to {} successfully\n",
+                       escaped_app_name,
+                       resp.old_max_replica_count,
+                       new_max_replica_count);
+        }

Review Comment:
   Is it necesssary to split these two cases? There is little difference.



##########
src/shell/commands/table_management.cpp:
##########
@@ -886,3 +888,105 @@ bool clear_app_envs(command_executor *e, shell_context *sc, arguments args)
     }
     return true;
 }
+
+bool get_max_replica_count(command_executor *e, shell_context *sc, arguments args)
+{
+    if (args.argc < 2) {
+        return false;
+    }
+
+    std::string app_name(args.argv[1]);
+
+    auto err_resp = sc->ddl_client->get_max_replica_count(app_name);
+    auto err = err_resp.get_error();
+    const auto &resp = err_resp.get_value();
+
+    if (err.is_ok()) {
+        err = dsn::error_s::make(resp.err);
+    }
+
+    std::string escaped_app_name(pegasus::utils::c_escape_string(app_name));
+    if (err.is_ok()) {
+        fmt::print(stdout,
+                   "the replica count of app({}) is {}\n",
+                   escaped_app_name,
+                   resp.max_replica_count);
+    } else {
+        fmt::print(stdout, "get replica count of app({}) failed: {}\n", escaped_app_name, err);
+    }
+
+    return true;

Review Comment:
   If we use the command in some 3rd party tools, we often depend on the return value and output data streams(stdout or stderr), so it's better to return false and output in stderr.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@pegasus.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pegasus.apache.org
For additional commands, e-mail: dev-help@pegasus.apache.org