From 313daef12ddc4c69897ea447b74764bd4ceb0c75 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 16 Jun 2024 15:42:17 +0300 Subject: [PATCH] Slightly decopypaste etcd key parsing --- src/cmd/cli.h | 4 ++ src/cmd/cli_alloc_osd.cpp | 13 +----- src/cmd/cli_common.cpp | 40 +++++++++++++++++ src/cmd/cli_pool_ls.cpp | 95 +++++++++++---------------------------- src/cmd/cli_status.cpp | 25 ++++------- 5 files changed, 79 insertions(+), 98 deletions(-) diff --git a/src/cmd/cli.h b/src/cmd/cli.h index 8e325ecb..a8598393 100644 --- a/src/cmd/cli.h +++ b/src/cmd/cli.h @@ -7,6 +7,7 @@ #include "json11/json11.hpp" #include "object_id.h" +#include "osd_id.h" #include "ringloop.h" #include @@ -77,6 +78,9 @@ public: void loop_and_wait(std::function loop_cb, std::function complete_cb); void etcd_txn(json11::Json txn); + + void iterate_kvs_1(json11::Json kvs, const std::string & prefix, std::function cb); + void iterate_kvs_2(json11::Json kvs, const std::string & prefix, std::function cb); }; std::string print_table(json11::Json items, json11::Json header, bool use_esc); diff --git a/src/cmd/cli_alloc_osd.cpp b/src/cmd/cli_alloc_osd.cpp index cdc3d189..8914dad3 100644 --- a/src/cmd/cli_alloc_osd.cpp +++ b/src/cmd/cli_alloc_osd.cpp @@ -72,19 +72,10 @@ struct alloc_osd_t if (!parent->etcd_result["succeeded"].bool_value()) { std::vector used; - for (auto kv: parent->etcd_result["responses"][0]["response_range"]["kvs"].array_items()) + parent->iterate_kvs_1(parent->etcd_result["responses"][0]["response_range"]["kvs"], "/osd/stats/", [&](uint64_t cur_osd, json11::Json value) { - std::string key = base64_decode(kv["key"].string_value()); - osd_num_t cur_osd; - char null_byte = 0; - int scanned = sscanf(key.c_str() + parent->cli->st_cli.etcd_prefix.length(), "/osd/stats/%ju%c", &cur_osd, &null_byte); - if (scanned != 1 || !cur_osd) - { - fprintf(stderr, "Invalid key in etcd: %s\n", key.c_str()); - continue; - } used.push_back(cur_osd); - } + }); std::sort(used.begin(), used.end()); if (used[used.size()-1] == used.size()) { diff --git a/src/cmd/cli_common.cpp b/src/cmd/cli_common.cpp index d1915970..c0805e8b 100644 --- a/src/cmd/cli_common.cpp +++ b/src/cmd/cli_common.cpp @@ -165,3 +165,43 @@ void cli_tool_t::loop_and_wait(std::function loop_cb, std: ringloop->wakeup(); }); } + +void cli_tool_t::iterate_kvs_1(json11::Json kvs, const std::string & prefix, std::function cb) +{ + bool is_pool = prefix == "/pool/stats/"; + for (auto & kv_item: kvs.array_items()) + { + auto kv = cli->st_cli.parse_etcd_kv(kv_item); + uint64_t num = 0; + char null_byte = 0; + // OSD or pool number + int scanned = sscanf(kv.key.substr(cli->st_cli.etcd_prefix.size() + prefix.size()).c_str(), "%ju%c", &num, &null_byte); + if (scanned != 1 || !num || is_pool && num >= POOL_ID_MAX) + { + fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); + continue; + } + cb(num, kv.value); + } +} + +void cli_tool_t::iterate_kvs_2(json11::Json kvs, const std::string & prefix, std::function cb) +{ + bool is_inode = prefix == "/config/inode/" || prefix == "/inode/stats/"; + for (auto & kv_item: kvs.array_items()) + { + auto kv = cli->st_cli.parse_etcd_kv(kv_item); + pool_id_t pool_id = 0; + uint64_t num = 0; + char null_byte = 0; + // pool+pg or pool+inode + int scanned = sscanf(kv.key.substr(cli->st_cli.etcd_prefix.size() + prefix.size()).c_str(), + "%u/%ju%c", &pool_id, &num, &null_byte); + if (scanned != 2 || !pool_id || is_inode && INODE_POOL(num) || !is_inode && num >= UINT32_MAX) + { + fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); + continue; + } + cb(pool_id, num, kv.value); + } +} diff --git a/src/cmd/cli_pool_ls.cpp b/src/cmd/cli_pool_ls.cpp index 5d3a70aa..ad807715 100644 --- a/src/cmd/cli_pool_ls.cpp +++ b/src/cmd/cli_pool_ls.cpp @@ -104,37 +104,16 @@ resume_1: { config_pools = parent->cli->st_cli.parse_etcd_kv(config_pools).value; } - for (auto & kv_item: space_info["responses"][0]["response_range"]["kvs"].array_items()) + parent->iterate_kvs_1(space_info["responses"][0]["response_range"]["kvs"], "/pool/stats/", [&](uint64_t pool_id, json11::Json value) { - auto kv = parent->cli->st_cli.parse_etcd_kv(kv_item); - // pool ID - pool_id_t pool_id; - char null_byte = 0; - int scanned = sscanf(kv.key.substr(parent->cli->st_cli.etcd_prefix.length()).c_str(), "/pool/stats/%u%c", &pool_id, &null_byte); - if (scanned != 1 || !pool_id || pool_id >= POOL_ID_MAX) - { - fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); - continue; - } - // pool/stats/ - pool_stats[pool_id] = kv.value.object_items(); - } + pool_stats[pool_id] = value.object_items(); + }); std::map osd_free; - for (auto & kv_item: space_info["responses"][1]["response_range"]["kvs"].array_items()) + parent->iterate_kvs_1(space_info["responses"][1]["response_range"]["kvs"], "/osd/stats/", [&](uint64_t osd_num, json11::Json value) { - auto kv = parent->cli->st_cli.parse_etcd_kv(kv_item); - // osd ID - osd_num_t osd_num; - char null_byte = 0; - int scanned = sscanf(kv.key.substr(parent->cli->st_cli.etcd_prefix.length()).c_str(), "/osd/stats/%ju%c", &osd_num, &null_byte); - if (scanned != 1 || !osd_num || osd_num >= POOL_ID_MAX) - { - fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); - continue; - } // osd/stats/::free - osd_free[osd_num] = kv.value["free"].uint64_value(); - } + osd_free[osd_num] = value["free"].uint64_value(); + }); // Calculate max_avail for each pool for (auto & pp: parent->cli->st_cli.pool_config) { @@ -254,29 +233,17 @@ resume_1: state = 100; return; } - auto pg_stats = parent->etcd_result["responses"][0]["response_range"]["kvs"]; // Calculate recovery percent std::map counts; - for (auto & kv_item: pg_stats.array_items()) + parent->iterate_kvs_2(parent->etcd_result["responses"][0]["response_range"]["kvs"], "/pg/stats/", + [&](pool_id_t pool_id, uint64_t pg_num, json11::Json value) { - auto kv = parent->cli->st_cli.parse_etcd_kv(kv_item); - // pool ID & pg number - pool_id_t pool_id; - pg_num_t pg_num = 0; - char null_byte = 0; - int scanned = sscanf(kv.key.substr(parent->cli->st_cli.etcd_prefix.length()).c_str(), - "/pg/stats/%u/%u%c", &pool_id, &pg_num, &null_byte); - if (scanned != 2 || !pool_id || pool_id >= POOL_ID_MAX) - { - fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); - continue; - } auto & cnt = counts[pool_id]; - cnt.object_count += kv.value["object_count"].uint64_value(); - cnt.misplaced_count += kv.value["misplaced_count"].uint64_value(); - cnt.degraded_count += kv.value["degraded_count"].uint64_value(); - cnt.incomplete_count += kv.value["incomplete_count"].uint64_value(); - } + cnt.object_count += value["object_count"].uint64_value(); + cnt.misplaced_count += value["misplaced_count"].uint64_value(); + cnt.degraded_count += value["degraded_count"].uint64_value(); + cnt.incomplete_count += value["incomplete_count"].uint64_value(); + }); for (auto & pp: pool_stats) { auto & cnt = counts[pp.first]; @@ -317,35 +284,23 @@ resume_1: state = 100; return; } - auto inode_stats = parent->etcd_result["responses"][0]["response_range"]["kvs"]; // Performance statistics std::map pool_io; - for (auto & kv_item: inode_stats.array_items()) + parent->iterate_kvs_2(parent->etcd_result["responses"][0]["response_range"]["kvs"], "/inode/stats/", + [&](pool_id_t pool_id, uint64_t inode_num, json11::Json value) { - auto kv = parent->cli->st_cli.parse_etcd_kv(kv_item); - // pool ID & inode number - pool_id_t pool_id; - inode_t only_inode_num; - char null_byte = 0; - int scanned = sscanf(kv.key.substr(parent->cli->st_cli.etcd_prefix.length()).c_str(), - "/inode/stats/%u/%ju%c", &pool_id, &only_inode_num, &null_byte); - if (scanned != 2 || !pool_id || pool_id >= POOL_ID_MAX || INODE_POOL(only_inode_num) != 0) - { - fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); - continue; - } auto & io = pool_io[pool_id]; - io.read_iops += kv.value["read"]["iops"].uint64_value(); - io.read_bps += kv.value["read"]["bps"].uint64_value(); - io.read_lat += kv.value["read"]["lat"].uint64_value(); - io.write_iops += kv.value["write"]["iops"].uint64_value(); - io.write_bps += kv.value["write"]["bps"].uint64_value(); - io.write_lat += kv.value["write"]["lat"].uint64_value(); - io.delete_iops += kv.value["delete"]["iops"].uint64_value(); - io.delete_bps += kv.value["delete"]["bps"].uint64_value(); - io.delete_lat += kv.value["delete"]["lat"].uint64_value(); + io.read_iops += value["read"]["iops"].uint64_value(); + io.read_bps += value["read"]["bps"].uint64_value(); + io.read_lat += value["read"]["lat"].uint64_value(); + io.write_iops += value["write"]["iops"].uint64_value(); + io.write_bps += value["write"]["bps"].uint64_value(); + io.write_lat += value["write"]["lat"].uint64_value(); + io.delete_iops += value["delete"]["iops"].uint64_value(); + io.delete_bps += value["delete"]["bps"].uint64_value(); + io.delete_lat += value["delete"]["lat"].uint64_value(); io.count++; - } + }); for (auto & pp: pool_stats) { auto & io = pool_io[pp.first]; diff --git a/src/cmd/cli_status.cpp b/src/cmd/cli_status.cpp index 213ca8e0..893c407d 100644 --- a/src/cmd/cli_status.cpp +++ b/src/cmd/cli_status.cpp @@ -18,7 +18,7 @@ struct status_printer_t cli_tool_t *parent; int state = 0; - json11::Json::array mon_members, osd_stats; + json11::Json::array mon_members; json11::Json agg_stats; std::map pool_stats; json11::Json::array etcd_states; @@ -93,7 +93,7 @@ resume_2: return; } mon_members = parent->etcd_result["responses"][0]["response_range"]["kvs"].array_items(); - osd_stats = parent->etcd_result["responses"][1]["response_range"]["kvs"].array_items(); + auto osd_stats = parent->etcd_result["responses"][1]["response_range"]["kvs"]; if (parent->etcd_result["responses"][2]["response_range"]["kvs"].array_items().size() > 0) { agg_stats = parent->cli->st_cli.parse_etcd_kv(parent->etcd_result["responses"][2]["response_range"]["kvs"][0]).value; @@ -133,20 +133,11 @@ resume_2: } int osd_count = 0, osd_up = 0; uint64_t total_raw = 0, free_raw = 0, free_down_raw = 0, down_raw = 0; - for (int i = 0; i < osd_stats.size(); i++) + parent->iterate_kvs_1(osd_stats, "/osd/stats", [&](uint64_t stat_osd_num, json11::Json value) { - auto kv = parent->cli->st_cli.parse_etcd_kv(osd_stats[i]); - osd_num_t stat_osd_num = 0; - char null_byte = 0; - int scanned = sscanf(kv.key.c_str() + parent->cli->st_cli.etcd_prefix.size(), "/osd/stats/%ju%c", &stat_osd_num, &null_byte); - if (scanned != 1 || !stat_osd_num) - { - fprintf(stderr, "Invalid key in etcd: %s\n", kv.key.c_str()); - continue; - } osd_count++; - auto osd_size = kv.value["size"].uint64_value(); - auto osd_free = kv.value["free"].uint64_value(); + auto osd_size = value["size"].uint64_value(); + auto osd_free = value["free"].uint64_value(); total_raw += osd_size; free_raw += osd_free; if (!osd_free) @@ -164,10 +155,10 @@ resume_2: } else { - down_raw += kv.value["size"].uint64_value(); - free_down_raw += kv.value["free"].uint64_value(); + down_raw += value["size"].uint64_value(); + free_down_raw += value["free"].uint64_value(); } - } + }); int pool_count = 0, pools_active = 0; std::map pgs_by_state; std::string pgs_by_state_str;