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

wangdan 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 68310cbcc refactor: extract and encapsulate the aggregation process of 
single-table statistics for reuse (#2318)
68310cbcc is described below

commit 68310cbccdd19df74a36d33f1cc3d8697d6d28f6
Author: Dan Wang <[email protected]>
AuthorDate: Fri Nov 21 18:08:59 2025 +0800

    refactor: extract and encapsulate the aggregation process of single-table 
statistics for reuse (#2318)
    
    Both shell and HTTP interfaces now support displaying a table's statistics 
in
    multiple sections. Since the logic for this was largely duplicated, a lot of
    redundant code existed. This PR extracts the common logic and introduces
    an `add_app_info` interface to encapsulate it, allowing a table’s 
statistics to
    be added to a `multi_printer` in multiple sections for later output.
    
    Additionally, a `resolve` interface is introduced for `host_port` itself, 
replacing
    `replication_ddl_client::node_name`.
---
 src/client/replication_ddl_client.cpp   | 136 +++++---------------------------
 src/client/replication_ddl_client.h     |  13 +--
 src/common/replication_common.cpp       | 123 +++++++++++++++++++++++++++--
 src/common/replication_common.h         |  37 ++++++++-
 src/meta/meta_http_service.cpp          | 104 ++++--------------------
 src/rpc/rpc_host_port.cpp               |  10 +++
 src/rpc/rpc_host_port.h                 |   4 +
 src/shell/commands/node_management.cpp  |  49 ++++++------
 src/shell/commands/table_management.cpp |  27 ++++---
 src/utils/output_utils.h                |   7 ++
 10 files changed, 256 insertions(+), 254 deletions(-)

diff --git a/src/client/replication_ddl_client.cpp 
b/src/client/replication_ddl_client.cpp
index 9bd69b174..46398c963 100644
--- a/src/client/replication_ddl_client.cpp
+++ b/src/client/replication_ddl_client.cpp
@@ -35,7 +35,6 @@
 #include <fstream>
 #include <iomanip>
 #include <iostream>
-#include <type_traits>
 
 #include "backup_types.h"
 #include "common//duplication_common.h"
@@ -531,15 +530,6 @@ struct list_nodes_helper
     }
 };
 
-std::string replication_ddl_client::node_name(const host_port &hp, bool 
resolve_ip)
-{
-    if (!resolve_ip) {
-        return hp.to_string();
-    }
-
-    return dns_resolver::instance().resolve_address(hp).to_string();
-}
-
 dsn::error_code replication_ddl_client::cluster_name(int64_t timeout_ms, 
std::string &cluster_name)
 {
     auto req = std::make_shared<configuration_cluster_info_request>();
@@ -614,123 +604,35 @@ replication_ddl_client::cluster_info(const std::string 
&file_name, bool resolve_
 dsn::error_code replication_ddl_client::list_app(const std::string &app_name,
                                                  bool detailed,
                                                  bool json,
-                                                 const std::string &file_name,
+                                                 const std::string 
&output_file,
                                                  bool resolve_ip)
 {
-    dsn::utils::multi_table_printer mtp;
-    dsn::utils::table_printer tp_params("parameters");
-    if (!(app_name.empty() && file_name.empty())) {
-        if (!app_name.empty())
-            tp_params.add_row_name_and_data("app_name", app_name);
-        if (!file_name.empty())
-            tp_params.add_row_name_and_data("out_file", file_name);
-    }
-    tp_params.add_row_name_and_data("detailed", detailed);
-    mtp.add(std::move(tp_params));
-    int32_t app_id = 0;
-    int32_t partition_count = 0;
-    int32_t max_replica_count = 0;
+    utils::table_printer params_printer("parameters");
+    if (!app_name.empty()) {
+        params_printer.add_row_name_and_data("app_name", app_name);
+    }
+    if (!output_file.empty()) {
+        params_printer.add_row_name_and_data("out_file", output_file);
+    }
+
+    params_printer.add_row_name_and_data("detailed", detailed);
+
+    utils::multi_table_printer multi_printer;
+    multi_printer.add(std::move(params_printer));
+
+    int32_t app_id{0};
+    int32_t partition_count{0};
     std::vector<partition_configuration> pcs;
-    dsn::error_code err = list_app(app_name, app_id, partition_count, pcs);
+    const auto err = list_app(app_name, app_id, partition_count, pcs);
     if (err != dsn::ERR_OK) {
         return err;
     }
-    if (!pcs.empty()) {
-        max_replica_count = pcs[0].max_replica_count;
-    }
 
-    // print query_cfg_response
-    std::streambuf *buf;
-    std::ofstream of;
+    add_app_info(app_name, app_id, partition_count, pcs, detailed, resolve_ip, 
"", multi_printer);
 
-    if (!file_name.empty()) {
-        of.open(file_name);
-        buf = of.rdbuf();
-    } else {
-        buf = std::cout.rdbuf();
-    }
-    std::ostream out(buf);
+    utils::output(output_file, json, multi_printer);
 
-    dsn::utils::table_printer tp_general("general");
-    tp_general.add_row_name_and_data("app_name", app_name);
-    tp_general.add_row_name_and_data("app_id", app_id);
-    tp_general.add_row_name_and_data("partition_count", partition_count);
-    tp_general.add_row_name_and_data("max_replica_count", max_replica_count);
-    mtp.add(std::move(tp_general));
-
-    if (detailed) {
-        dsn::utils::table_printer tp_details("replicas");
-        tp_details.add_title("pidx");
-        tp_details.add_column("ballot");
-        tp_details.add_column("replica_count");
-        tp_details.add_column("primary");
-        tp_details.add_column("secondaries");
-        std::map<host_port, std::pair<int, int>> node_stat;
-
-        int total_prim_count = 0;
-        int total_sec_count = 0;
-        int fully_healthy = 0;
-        int write_unhealthy = 0;
-        int read_unhealthy = 0;
-        for (const auto &pc : pcs) {
-            int replica_count = 0;
-            if (pc.hp_primary) {
-                replica_count++;
-                node_stat[pc.hp_primary].first++;
-                total_prim_count++;
-            }
-            replica_count += pc.hp_secondaries.size();
-            total_sec_count += pc.hp_secondaries.size();
-            if (pc.hp_primary) {
-                if (replica_count >= pc.max_replica_count) {
-                    fully_healthy++;
-                } else if (replica_count < 2) {
-                    write_unhealthy++;
-                }
-            } else {
-                write_unhealthy++;
-                read_unhealthy++;
-            }
-            for (const auto &secondary : pc.hp_secondaries) {
-                node_stat[secondary].second++;
-            }
-            tp_details.add_row(pc.pid.get_partition_index());
-            tp_details.append_data(pc.ballot);
-            tp_details.append_data(fmt::format("{}/{}", replica_count, 
pc.max_replica_count));
-            tp_details.append_data(pc.hp_primary ? pc.hp_primary.to_string() : 
"-");
-            tp_details.append_data(fmt::format("[{}]", 
fmt::join(pc.hp_secondaries, ",")));
-        }
-        mtp.add(std::move(tp_details));
-
-        // 'node' section.
-        dsn::utils::table_printer tp_nodes("nodes");
-        tp_nodes.add_title("node");
-        tp_nodes.add_column("primary");
-        tp_nodes.add_column("secondary");
-        tp_nodes.add_column("total");
-        for (const auto &[hp, pri_and_sec_rep_cnts] : node_stat) {
-            tp_nodes.add_row(node_name(hp, resolve_ip));
-            tp_nodes.append_data(pri_and_sec_rep_cnts.first);
-            tp_nodes.append_data(pri_and_sec_rep_cnts.second);
-            tp_nodes.append_data(pri_and_sec_rep_cnts.first + 
pri_and_sec_rep_cnts.second);
-        }
-        tp_nodes.add_row("");
-        tp_nodes.append_data(total_prim_count);
-        tp_nodes.append_data(total_sec_count);
-        tp_nodes.append_data(total_prim_count + total_sec_count);
-        mtp.add(std::move(tp_nodes));
-
-        // healthy partition count section.
-        dsn::utils::table_printer tp_hpc("healthy");
-        tp_hpc.add_row_name_and_data("fully_healthy_partition_count", 
fully_healthy);
-        tp_hpc.add_row_name_and_data("unhealthy_partition_count", 
partition_count - fully_healthy);
-        tp_hpc.add_row_name_and_data("write_unhealthy_partition_count", 
write_unhealthy);
-        tp_hpc.add_row_name_and_data("read_unhealthy_partition_count", 
read_unhealthy);
-        mtp.add(std::move(tp_hpc));
-    }
-    mtp.output(out, json ? tp_output_format::kJsonPretty : 
tp_output_format::kTabular);
     return dsn::ERR_OK;
-#undef RESOLVE
 }
 
 dsn::error_code replication_ddl_client::list_app(const std::string &app_name,
diff --git a/src/client/replication_ddl_client.h 
b/src/client/replication_ddl_client.h
index 47220372c..d2651bc2f 100644
--- a/src/client/replication_ddl_client.h
+++ b/src/client/replication_ddl_client.h
@@ -156,8 +156,8 @@ public:
     dsn::error_code list_app(const std::string &app_name,
                              bool detailed,
                              bool json,
-                             const std::string &file_name,
-                             bool resolve_ip = false);
+                             const std::string &output_file,
+                             bool resolve_ip);
 
     dsn::error_code list_app(const std::string &app_name,
                              int32_t &app_id,
@@ -317,10 +317,12 @@ public:
     void set_max_wait_app_ready_secs(uint32_t max_wait_secs) { _max_wait_secs 
= max_wait_secs; }
     void set_meta_servers_leader();
 
-    static error_s validate_app_name(const std::string &app_name, bool 
allow_empty_name = false);
+    static error_s validate_app_name(const std::string &app_name, bool 
allow_empty_name);
 
-    // Resolve the host:port 'hp' to ip:port if 'resolve_ip' is true.
-    static std::string node_name(const host_port &hp, bool resolve_ip);
+    static error_s validate_app_name(const std::string &app_name)
+    {
+        return validate_app_name(app_name, false);
+    }
 
 private:
     void end_meta_request(const rpc_response_task_ptr &callback,
@@ -528,7 +530,6 @@ private:
         }
     }
 
-private:
     dsn::host_port _meta_server;
     dsn::task_tracker _tracker;
     uint32_t _max_wait_secs = 3600; // Wait at most 1 hour by default.
diff --git a/src/common/replication_common.cpp 
b/src/common/replication_common.cpp
index 7e18163cd..c7abae722 100644
--- a/src/common/replication_common.cpp
+++ b/src/common/replication_common.cpp
@@ -26,14 +26,18 @@
 
 #include "common/replication_common.h"
 
-#include <string.h>
+#include <cstring>
 #include <fstream>
+#include <map>
 #include <memory>
+#include <type_traits>
+#include <utility>
 
 #include "common/gpid.h"
 #include "common/replication_other_types.h"
 #include "dsn.layer2_types.h"
 #include "fmt/core.h"
+#include "fmt/format.h"
 #include "rpc/dns_resolver.h" // IWYU pragma: keep
 #include "rpc/rpc_address.h"
 #include "runtime/service_app.h"
@@ -41,6 +45,7 @@
 #include "utils/filesystem.h"
 #include "utils/flags.h"
 #include "utils/fmt_logging.h"
+#include "utils/output_utils.h"
 #include "utils/strings.h"
 #include "utils/utils.h"
 
@@ -112,8 +117,8 @@ DSN_DEFINE_string(meta_server,
                   "",
                   "Comma-separated list of MetaServers in the Pegasus 
cluster");
 
-namespace dsn {
-namespace replication {
+namespace dsn::replication {
+
 const std::string replication_options::kRepsDir = "reps";
 const std::string replication_options::kReplicaAppType = "replica";
 
@@ -333,5 +338,113 @@ replication_options::check_if_in_black_list(const 
std::vector<std::string> &blac
     return false;
 }
 
-} // namespace replication
-} // namespace dsn
+void add_app_info(const std::string &app_name,
+                  int32_t app_id,
+                  int32_t partition_count,
+                  const std::vector<partition_configuration> &pcs,
+                  bool detailed,
+                  bool resolve_ip,
+                  std::string_view total_row_name,
+                  utils::multi_table_printer &multi_printer)
+{
+    // "general" section.
+    utils::table_printer general_printer("general");
+    general_printer.add_row_name_and_data("app_name", app_name);
+    general_printer.add_row_name_and_data("app_id", app_id);
+    general_printer.add_row_name_and_data("partition_count", partition_count);
+    general_printer.add_row_name_and_data("max_replica_count",
+                                          pcs.empty() ? 0 : 
pcs[0].max_replica_count);
+
+    multi_printer.add(std::move(general_printer));
+
+    if (!detailed) {
+        return;
+    }
+
+    // "replicas" section.
+    utils::table_printer partitions_printer("replicas");
+    partitions_printer.add_title("pidx");
+    partitions_printer.add_column("ballot");
+    partitions_printer.add_column("replica_count");
+    partitions_printer.add_column("primary");
+    partitions_printer.add_column("secondaries");
+
+    struct node_stat
+    {
+        int primary_count{0};
+        int secondary_count{0};
+    };
+    std::map<host_port, node_stat> node_stats;
+
+    int total_prim_count = 0;
+    int total_sec_count = 0;
+    int fully_healthy = 0;
+    int write_unhealthy = 0;
+    int read_unhealthy = 0;
+    for (const auto &pc : pcs) {
+        int replica_count = 0;
+        if (pc.hp_primary) {
+            ++replica_count;
+            ++node_stats[pc.hp_primary].primary_count;
+            ++total_prim_count;
+        }
+        replica_count += static_cast<int>(pc.hp_secondaries.size());
+        total_sec_count += static_cast<int>(pc.hp_secondaries.size());
+
+        if (pc.hp_primary) {
+            if (replica_count >= pc.max_replica_count) {
+                ++fully_healthy;
+            } else if (replica_count < 2) {
+                ++write_unhealthy;
+            }
+        } else {
+            ++write_unhealthy;
+            ++read_unhealthy;
+        }
+
+        partitions_printer.add_row(pc.pid.get_partition_index());
+        partitions_printer.append_data(pc.ballot);
+        partitions_printer.append_data(fmt::format("{}/{}", replica_count, 
pc.max_replica_count));
+        partitions_printer.append_data(pc.hp_primary ? 
pc.hp_primary.to_string() : "-");
+        partitions_printer.append_data(fmt::format("[{}]", 
fmt::join(pc.hp_secondaries, ",")));
+
+        for (const auto &secondary : pc.hp_secondaries) {
+            ++node_stats[secondary].secondary_count;
+        }
+    }
+
+    multi_printer.add(std::move(partitions_printer));
+
+    // "nodes" section.
+    utils::table_printer nodes_printer("nodes");
+    nodes_printer.add_title("node");
+    nodes_printer.add_column("primary");
+    nodes_printer.add_column("secondary");
+    nodes_printer.add_column("total");
+
+    for (const auto &[addr, stat] : node_stats) {
+        nodes_printer.add_row(addr.resolve(resolve_ip));
+        nodes_printer.append_data(stat.primary_count);
+        nodes_printer.append_data(stat.secondary_count);
+        nodes_printer.append_data(stat.primary_count + stat.secondary_count);
+    }
+
+    nodes_printer.add_row(total_row_name);
+    nodes_printer.append_data(total_prim_count);
+    nodes_printer.append_data(total_sec_count);
+    nodes_printer.append_data(total_prim_count + total_sec_count);
+
+    multi_printer.add(std::move(nodes_printer));
+
+    // "healthy" partition count section.
+    utils::table_printer healthy_printer("healthy");
+    healthy_printer.add_row_name_and_data("fully_healthy_partition_count", 
fully_healthy);
+    healthy_printer.add_row_name_and_data("unhealthy_partition_count",
+                                          partition_count - fully_healthy);
+    healthy_printer.add_row_name_and_data("write_unhealthy_partition_count", 
write_unhealthy);
+    healthy_printer.add_row_name_and_data("read_unhealthy_partition_count", 
read_unhealthy);
+
+    multi_printer.add(std::move(healthy_printer));
+}
+
+} // namespace dsn::replication
diff --git a/src/common/replication_common.h b/src/common/replication_common.h
index efa78f13f..37c15d91d 100644
--- a/src/common/replication_common.h
+++ b/src/common/replication_common.h
@@ -26,8 +26,9 @@
 
 #pragma once
 
-#include <stdint.h>
+#include <cstdint>
 #include <string>
+#include <string_view>
 #include <unordered_map>
 #include <vector>
 
@@ -37,7 +38,14 @@
 #include "task/task.h"
 
 namespace dsn {
-namespace replication {
+class partition_configuration;
+namespace utils {
+class multi_table_printer;
+} // namespace utils
+} // namespace dsn
+
+namespace dsn::replication {
+
 class configuration_update_app_env_request;
 class configuration_update_app_env_response;
 class query_app_info_request;
@@ -85,5 +93,26 @@ public:
     static bool check_if_in_black_list(const std::vector<std::string> 
&black_list_dir,
                                        const std::string &dir);
 };
-} // namespace replication
-} // namespace dsn
+
+// Add base info and statistics for an app into `multi_printer`.
+//
+// Parameters:
+// - app_name: the name of the app.
+// - app_id: the id of the app.
+// - partition_count: the number of the app partitions.
+// - pcs: the configuration for each partition.
+// - detailed: false means only base info would be added into `multi_printer`, 
while true
+//             means more detailed statistics would also be added.
+// - resolve_ip: whether host would be resolved into ip.
+// - total_row_name: the name of the total row for "nodes" section.
+// - multi_printer: the target printer which has multiple sections.
+void add_app_info(const std::string &app_name,
+                  int32_t app_id,
+                  int32_t partition_count,
+                  const std::vector<partition_configuration> &pcs,
+                  bool detailed,
+                  bool resolve_ip,
+                  std::string_view total_row_name,
+                  utils::multi_table_printer &multi_printer);
+
+} // namespace dsn::replication
diff --git a/src/meta/meta_http_service.cpp b/src/meta/meta_http_service.cpp
index 22e732737..a15ae60a8 100644
--- a/src/meta/meta_http_service.cpp
+++ b/src/meta/meta_http_service.cpp
@@ -15,11 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#include <cstddef>
 #include <fmt/core.h>
-#include <fmt/format.h>
 #include <rapidjson/ostreamwrapper.h>
 #include <algorithm>
+#include <cstddef>
 #include <map>
 #include <memory>
 #include <set>
@@ -30,9 +29,8 @@
 
 #include "backup_types.h"
 #include "bulk_load_types.h"
-#include "common//duplication_common.h"
 #include "common/bulk_load_common.h"
-#include "common/gpid.h"
+#include "common/duplication_common.h"
 #include "common/replica_envs.h"
 #include "common/replication.codes.h"
 #include "common/replication_common.h"
@@ -129,94 +127,20 @@ void meta_http_service::get_app_handler(const 
http_request &req, http_response &
         return;
     }
 
-    // output as json format
-    dsn::utils::multi_table_printer mtp;
-    std::ostringstream out;
-    dsn::utils::table_printer tp_general("general");
-    tp_general.add_row_name_and_data("app_name", app_name);
-    tp_general.add_row_name_and_data("app_id", response.app_id);
-    tp_general.add_row_name_and_data("partition_count", 
response.partition_count);
-    if (!response.partitions.empty()) {
-        tp_general.add_row_name_and_data("max_replica_count",
-                                         
response.partitions[0].max_replica_count);
-    } else {
-        tp_general.add_row_name_and_data("max_replica_count", 0);
-    }
-    mtp.add(std::move(tp_general));
+    dsn::utils::multi_table_printer multi_printer;
+    add_app_info(app_name,
+                 response.app_id,
+                 response.partition_count,
+                 response.partitions,
+                 detailed,
+                 false,
+                 "total",
+                 multi_printer);
 
-    if (detailed) {
-        dsn::utils::table_printer tp_details("replicas");
-        tp_details.add_title("pidx");
-        tp_details.add_column("ballot");
-        tp_details.add_column("replica_count");
-        tp_details.add_column("primary");
-        tp_details.add_column("secondaries");
-        std::map<host_port, std::pair<int, int>> node_stat;
-
-        int total_prim_count = 0;
-        int total_sec_count = 0;
-        int fully_healthy = 0;
-        int write_unhealthy = 0;
-        int read_unhealthy = 0;
-        for (const auto &pc : response.partitions) {
-            int replica_count = 0;
-            if (pc.hp_primary) {
-                replica_count++;
-                node_stat[pc.hp_primary].first++;
-                total_prim_count++;
-            }
-            replica_count += pc.hp_secondaries.size();
-            total_sec_count += pc.hp_secondaries.size();
-            if (pc.hp_primary) {
-                if (replica_count >= pc.max_replica_count) {
-                    fully_healthy++;
-                } else if (replica_count < 2) {
-                    write_unhealthy++;
-                }
-            } else {
-                write_unhealthy++;
-                read_unhealthy++;
-            }
-            tp_details.add_row(pc.pid.get_partition_index());
-            tp_details.append_data(pc.ballot);
-            tp_details.append_data(fmt::format("{}/{}", replica_count, 
pc.max_replica_count));
-            tp_details.append_data(pc.hp_primary ? pc.hp_primary.to_string() : 
"-");
-            tp_details.append_data(fmt::format("[{}]", 
fmt::join(pc.hp_secondaries, ",")));
-            for (const auto &secondary : pc.hp_secondaries) {
-                node_stat[secondary].second++;
-            }
-        }
-        mtp.add(std::move(tp_details));
-
-        // 'node' section.
-        dsn::utils::table_printer tp_nodes("nodes");
-        tp_nodes.add_title("node");
-        tp_nodes.add_column("primary");
-        tp_nodes.add_column("secondary");
-        tp_nodes.add_column("total");
-        for (auto &kv : node_stat) {
-            tp_nodes.add_row(kv.first.to_string());
-            tp_nodes.append_data(kv.second.first);
-            tp_nodes.append_data(kv.second.second);
-            tp_nodes.append_data(kv.second.first + kv.second.second);
-        }
-        tp_nodes.add_row("total");
-        tp_nodes.append_data(total_prim_count);
-        tp_nodes.append_data(total_sec_count);
-        tp_nodes.append_data(total_prim_count + total_sec_count);
-        mtp.add(std::move(tp_nodes));
-
-        // healthy partition count section.
-        dsn::utils::table_printer tp_hpc("healthy");
-        tp_hpc.add_row_name_and_data("fully_healthy_partition_count", 
fully_healthy);
-        tp_hpc.add_row_name_and_data("unhealthy_partition_count",
-                                     response.partition_count - fully_healthy);
-        tp_hpc.add_row_name_and_data("write_unhealthy_partition_count", 
write_unhealthy);
-        tp_hpc.add_row_name_and_data("read_unhealthy_partition_count", 
read_unhealthy);
-        mtp.add(std::move(tp_hpc));
-    }
+    // Output as json format.
+    std::ostringstream out;
+    multi_printer.output(out, 
dsn::utils::table_printer::output_format::kJsonCompact);
 
-    mtp.output(out, dsn::utils::table_printer::output_format::kJsonCompact);
     resp.body = out.str();
     resp.status_code = http_status_code::kOk;
 }
diff --git a/src/rpc/rpc_host_port.cpp b/src/rpc/rpc_host_port.cpp
index 6235147d6..e0b35e63c 100644
--- a/src/rpc/rpc_host_port.cpp
+++ b/src/rpc/rpc_host_port.cpp
@@ -29,6 +29,7 @@
 #include <utility>
 
 #include "fmt/core.h"
+#include "rpc/dns_resolver.h"
 #include "rpc/group_host_port.h"
 #include "rpc/rpc_host_port.h"
 #include "utils/api_utilities.h"
@@ -161,6 +162,15 @@ void host_port::assign_group(const char *name)
     _group_host_port = std::make_shared<rpc_group_host_port>(name);
 }
 
+std::string host_port::resolve(bool resolve_ip) const
+{
+    if (!resolve_ip) {
+        return to_string();
+    }
+
+    return dns_resolver::instance().resolve_address(*this).to_string();
+}
+
 error_s host_port::resolve_addresses(std::vector<rpc_address> &addresses) const
 {
     CHECK(addresses.empty(), "");
diff --git a/src/rpc/rpc_host_port.h b/src/rpc/rpc_host_port.h
index fa467ef2a..a0ba48a9f 100644
--- a/src/rpc/rpc_host_port.h
+++ b/src/rpc/rpc_host_port.h
@@ -305,6 +305,10 @@ public:
     }
     void assign_group(const char *name);
 
+    // Resolve this host_port object to the string of ip:port if 'resolve_ip' 
is true;
+    // otherwise, just return the string of this host_port object.
+    [[nodiscard]] std::string resolve(bool resolve_ip) const;
+
     // Construct a host_port object from 'addr'
     static host_port from_address(rpc_address addr);
 
diff --git a/src/shell/commands/node_management.cpp 
b/src/shell/commands/node_management.cpp
index 2d9c7dd2a..8b8804287 100644
--- a/src/shell/commands/node_management.cpp
+++ b/src/shell/commands/node_management.cpp
@@ -34,6 +34,7 @@
 #include <set>
 #include <string>
 #include <thread>
+#include <type_traits>
 #include <unordered_map>
 #include <utility>
 #include <vector>
@@ -437,7 +438,7 @@ bool ls_nodes(command_executor *, shell_context *sc, 
arguments args)
                                            {"sample_interval_ms", 
required_argument, nullptr, 'i'},
                                            {nullptr, 0, nullptr, 0}};
 
-    std::string status;
+    std::string target_status_str;
     std::string output_file;
     uint32_t sample_interval_ms = FLAGS_nodes_sample_interval_ms;
     bool detailed = false;
@@ -476,7 +477,7 @@ bool ls_nodes(command_executor *, shell_context *sc, 
arguments args)
             json = true;
             break;
         case 's':
-            status = optarg;
+            target_status_str = optarg;
             break;
         case 'o':
             output_file = optarg;
@@ -490,10 +491,10 @@ bool ls_nodes(command_executor *, shell_context *sc, 
arguments args)
     }
 
     dsn::utils::multi_table_printer multi_printer;
-    if (!(status.empty() && output_file.empty())) {
+    if (!(target_status_str.empty() && output_file.empty())) {
         dsn::utils::table_printer tp("parameters");
-        if (!status.empty()) {
-            tp.add_row_name_and_data("status", status);
+        if (!target_status_str.empty()) {
+            tp.add_row_name_and_data("status", target_status_str);
         }
         if (!output_file.empty()) {
             tp.add_row_name_and_data("out_file", output_file);
@@ -501,18 +502,21 @@ bool ls_nodes(command_executor *, shell_context *sc, 
arguments args)
         multi_printer.add(std::move(tp));
     }
 
-    ::dsn::replication::node_status::type s = 
::dsn::replication::node_status::NS_INVALID;
-    if (!status.empty() && status != "all") {
-        s = type_from_string(dsn::replication::_node_status_VALUES_TO_NAMES,
-                             std::string("ns_") + status,
-                             ::dsn::replication::node_status::NS_INVALID);
-        SHELL_PRINT_AND_RETURN_FALSE_IF_NOT(s != 
::dsn::replication::node_status::NS_INVALID,
+    ::dsn::replication::node_status::type target_status =
+        ::dsn::replication::node_status::NS_INVALID;
+    if (!target_status_str.empty() && target_status_str != "all") {
+        target_status = 
type_from_string(dsn::replication::_node_status_VALUES_TO_NAMES,
+                                         std::string("ns_") + 
target_status_str,
+                                         
::dsn::replication::node_status::NS_INVALID);
+        SHELL_PRINT_AND_RETURN_FALSE_IF_NOT(target_status !=
+                                                
::dsn::replication::node_status::NS_INVALID,
                                             "parse {} as node_status::type 
failed",
-                                            status);
+                                            target_status_str);
     }
 
     std::map<dsn::host_port, dsn::replication::node_status::type> status_by_hp;
-    auto r = sc->ddl_client->list_nodes(s, status_by_hp);
+    // TODO(wangdan): encapsulated as a macro.
+    auto r = sc->ddl_client->list_nodes(target_status, status_by_hp);
     if (r != dsn::ERR_OK) {
         fmt::println("list nodes failed, error={}", r);
         return true;
@@ -520,14 +524,14 @@ bool ls_nodes(command_executor *, shell_context *sc, 
arguments args)
 
     std::map<dsn::host_port, list_nodes_helper> tmp_map;
     int alive_node_count = 0;
-    for (auto &kv : status_by_hp) {
-        if (kv.second == dsn::replication::node_status::NS_ALIVE) {
+    for (const auto &[addr, status] : status_by_hp) {
+        if (status == dsn::replication::node_status::NS_ALIVE) {
             ++alive_node_count;
         }
 
-        const std::string status_str(dsn::enum_to_string(kv.second));
-        tmp_map.emplace(kv.first,
-                        
list_nodes_helper(replication_ddl_client::node_name(kv.first, resolve_ip),
+        const std::string status_str(dsn::enum_to_string(status));
+        tmp_map.emplace(addr,
+                        list_nodes_helper(addr.resolve(resolve_ip),
                                           
status_str.substr(status_str.find("NS_") + 3)));
     }
 
@@ -540,9 +544,11 @@ bool ls_nodes(command_executor *, shell_context *sc, 
arguments args)
         }
 
         for (auto &app : apps) {
-            int32_t app_id;
-            int32_t partition_count;
+            int32_t app_id{0};
+            int32_t partition_count{0};
             std::vector<dsn::partition_configuration> pcs;
+
+            // TODO(wangdan): encapsulated as a macro.
             r = sc->ddl_client->list_app(app.app_name, app_id, 
partition_count, pcs);
             if (r != dsn::ERR_OK) {
                 fmt::println("list app {} failed, error={}", app.app_name, r);
@@ -868,8 +874,7 @@ bool remote_command(command_executor *e, shell_context *sc, 
arguments args)
         } else {
             failed++;
         }
-        info["details"].emplace(replication_ddl_client::node_name(nodes[i].hp, 
resolve_ip),
-                                node_info);
+        info["details"].emplace(nodes[i].hp.resolve(resolve_ip), node_info);
     }
     info["succeed_count"] = succeed;
     info["failed_count"] = failed;
diff --git a/src/shell/commands/table_management.cpp 
b/src/shell/commands/table_management.cpp
index 9890234e2..957225b12 100644
--- a/src/shell/commands/table_management.cpp
+++ b/src/shell/commands/table_management.cpp
@@ -369,17 +369,21 @@ bool app_disk(command_executor *e, shell_context *sc, 
arguments args)
                     count_value = f4->second;
                 }
             }
+
+            // TODO(wangdan): refactor as format style.
             std::stringstream oss;
-            oss << replication_ddl_client::node_name(pc.hp_primary, 
resolve_ip) << "(";
-            if (disk_found)
+            oss << pc.hp_primary.resolve(resolve_ip) << "(";
+            if (disk_found) {
                 oss << disk_value;
-            else
+            } else {
                 oss << "-";
+            }
             oss << ",";
-            if (count_found)
+            if (count_found) {
                 oss << "#" << count_value;
-            else
+            } else {
                 oss << "-";
+            }
             oss << ")";
             primary_str = oss.str();
         }
@@ -415,16 +419,19 @@ bool app_disk(command_executor *e, shell_context *sc, 
arguments args)
                     }
                 }
 
-                oss << replication_ddl_client::node_name(pc.hp_secondaries[j], 
resolve_ip) << "(";
-                if (found)
+                // TODO(wangdan): refactor as format style.
+                oss << pc.hp_secondaries[j].resolve(resolve_ip) << "(";
+                if (found) {
                     oss << value;
-                else
+                } else {
                     oss << "-";
+                }
                 oss << ",";
-                if (count_found)
+                if (count_found) {
                     oss << "#" << count_value;
-                else
+                } else {
                     oss << "-";
+                }
                 oss << ")";
             }
             oss << "]";
diff --git a/src/utils/output_utils.h b/src/utils/output_utils.h
index 7ffe16588..0018cecb1 100644
--- a/src/utils/output_utils.h
+++ b/src/utils/output_utils.h
@@ -27,6 +27,7 @@
 // IWYU pragma: no_include <new>
 #include <sstream> // IWYU pragma: keep
 #include <string>
+#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -198,6 +199,12 @@ inline std::string 
table_printer::to_string<std::string>(std::string data)
 
 template <>
 inline std::string table_printer::to_string<const char *>(const char *data)
+{
+    return {data};
+}
+
+template <>
+inline std::string table_printer::to_string<std::string_view>(std::string_view 
data)
 {
     return std::string(data);
 }


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

Reply via email to