From: John Spray Date: Sun, 31 Jul 2016 22:23:09 +0000 (+0100) Subject: mon: move "df" dump code from PGMonitor to PGMap X-Git-Tag: v11.0.1~60^2~28 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=519a01d973f10b97e4ba497e065fdf53b6064029;p=ceph.git mon: move "df" dump code from PGMonitor to PGMap ...so that ceph-mgr can use it too. Signed-off-by: John Spray --- diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index 67cf14304a87..4a0c1ac3dfaf 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -2909,10 +2909,10 @@ void Monitor::handle_command(MonOpRequestRef op) if (f) f->open_object_section("stats"); - pgmon()->dump_fs_stats(ds, f.get(), verbose); + pgmon()->pg_map.dump_fs_stats(&ds, f.get(), verbose); if (!f) ds << '\n'; - pgmon()->dump_pool_stats(ds, f.get(), verbose); + pgmon()->pg_map.dump_pool_stats(osdmon()->osdmap, &ds, f.get(), verbose); if (f) { f->close_section(); diff --git a/src/mon/PGMap.cc b/src/mon/PGMap.cc index 2b2f6c3f03da..96e2ada53119 100644 --- a/src/mon/PGMap.cc +++ b/src/mon/PGMap.cc @@ -5,10 +5,12 @@ #define dout_subsys ceph_subsys_mon #include "common/debug.h" -#include "common/TextTable.h" #include "common/Formatter.h" #include "include/ceph_features.h" +#include "include/stringify.h" + #include "osd/osd_types.h" +#include "osd/OSDMap.h" // -- @@ -1821,3 +1823,250 @@ void PGMap::dump_filtered_pg_stats(ostream& ss, set& pgs) ss << tab; } +int64_t PGMap::get_rule_avail(const OSDMap& osdmap, int ruleno) const +{ + map wm; + int r = osdmap.crush->get_rule_weight_osd_map(ruleno, &wm); + if (r < 0) + return r; + + if(wm.empty()) + return 0; + + int64_t min = -1; + for (map::iterator p = wm.begin(); p != wm.end(); ++p) { + ceph::unordered_map::const_iterator osd_info = osd_stat.find(p->first); + if (osd_info != osd_stat.end()) { + if (osd_info->second.kb == 0 || p->second == 0) { + // osd must be out, hence its stats have been zeroed + // (unless we somehow managed to have a disk with size 0...) + // + // (p->second == 0), if osd weight is 0, no need to + // calculate proj below. + continue; + } + int64_t proj = (int64_t)((double)((osd_info->second).kb_avail * 1024ull) / + (double)p->second); + if (min < 0 || proj < min) + min = proj; + } else { + dout(0) << "Cannot get stat of OSD " << p->first << dendl; + } + } + return min; +} + +inline std::string percentify(const float& a) { + std::stringstream ss; + if (a < 0.01) + ss << "0"; + else + ss << std::fixed << std::setprecision(2) << a; + return ss.str(); +} + +void PGMap::dump_pool_stats(const OSDMap &osd_map, stringstream *ss, + Formatter *f, bool verbose) const +{ + TextTable tbl; + + if (f) { + f->open_array_section("pools"); + } else { + tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT); + tbl.define_column("ID", TextTable::LEFT, TextTable::LEFT); + if (verbose) { + tbl.define_column("CATEGORY", TextTable::LEFT, TextTable::LEFT); + tbl.define_column("QUOTA OBJECTS", TextTable::LEFT, TextTable::LEFT); + tbl.define_column("QUOTA BYTES", TextTable::LEFT, TextTable::LEFT); + } + + tbl.define_column("USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("%USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("MAX AVAIL", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + if (verbose) { + tbl.define_column("DIRTY", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("READ", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("WRITE", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); + } + } + + map avail_by_rule; + for (map::const_iterator p = osd_map.get_pools().begin(); + p != osd_map.get_pools().end(); ++p) { + int64_t pool_id = p->first; + if ((pool_id < 0) || (pg_pool_sum.count(pool_id) == 0)) + continue; + const string& pool_name = osd_map.get_pool_name(pool_id); + const pool_stat_t &stat = pg_pool_sum.at(pool_id); + + const pg_pool_t *pool = osd_map.get_pg_pool(pool_id); + int ruleno = osd_map.crush->find_rule(pool->get_crush_ruleset(), + pool->get_type(), + pool->get_size()); + int64_t avail; + float raw_used_rate; + if (avail_by_rule.count(ruleno) == 0) { + avail = get_rule_avail(osd_map, ruleno); + if (avail < 0) + avail = 0; + avail_by_rule[ruleno] = avail; + } else { + avail = avail_by_rule[ruleno]; + } + switch (pool->get_type()) { + case pg_pool_t::TYPE_REPLICATED: + avail /= pool->get_size(); + raw_used_rate = pool->get_size(); + break; + case pg_pool_t::TYPE_ERASURE: + { + const map& ecp = + osd_map.get_erasure_code_profile(pool->erasure_code_profile); + map::const_iterator pm = ecp.find("m"); + map::const_iterator pk = ecp.find("k"); + if (pm != ecp.end() && pk != ecp.end()) { + int k = atoi(pk->second.c_str()); + int m = atoi(pm->second.c_str()); + avail = avail * k / (m + k); + raw_used_rate = (float)(m + k) / k; + } else { + raw_used_rate = 0.0; + } + } + break; + default: + assert(0 == "unrecognized pool type"); + } + + if (f) { + f->open_object_section("pool"); + f->dump_string("name", pool_name); + f->dump_int("id", pool_id); + f->open_object_section("stats"); + } else { + tbl << pool_name + << pool_id; + if (verbose) { + tbl << "-"; + + if (pool->quota_max_objects == 0) + tbl << "N/A"; + else + tbl << si_t(pool->quota_max_objects); + + if (pool->quota_max_bytes == 0) + tbl << "N/A"; + else + tbl << si_t(pool->quota_max_bytes); + } + + } + dump_object_stat_sum(tbl, f, stat.stats.sum, avail, raw_used_rate, verbose, pool); + if (f) + f->close_section(); // stats + else + tbl << TextTable::endrow; + + if (f) + f->close_section(); // pool + } + if (f) + f->close_section(); + else { + assert(ss != nullptr); + *ss << "POOLS:\n"; + tbl.set_indent(4); + *ss << tbl; + } +} + +void PGMap::dump_fs_stats( + stringstream *ss, Formatter *f, bool verbose) const +{ + if (f) { + f->open_object_section("stats"); + f->dump_int("total_bytes", osd_sum.kb * 1024ull); + f->dump_int("total_used_bytes", osd_sum.kb_used * 1024ull); + f->dump_int("total_avail_bytes", osd_sum.kb_avail * 1024ull); + if (verbose) { + f->dump_int("total_objects", pg_sum.stats.sum.num_objects); + } + f->close_section(); + } else { + assert(ss != nullptr); + TextTable tbl; + tbl.define_column("SIZE", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("%RAW USED", TextTable::LEFT, TextTable::RIGHT); + if (verbose) { + tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); + } + tbl << stringify(si_t(osd_sum.kb*1024)) + << stringify(si_t(osd_sum.kb_avail*1024)) + << stringify(si_t(osd_sum.kb_used*1024)); + float used = 0.0; + if (osd_sum.kb > 0) { + used = ((float)osd_sum.kb_used / osd_sum.kb); + } + tbl << percentify(used*100); + if (verbose) { + tbl << stringify(si_t(pg_sum.stats.sum.num_objects)); + } + tbl << TextTable::endrow; + + *ss << "GLOBAL:\n"; + tbl.set_indent(4); + *ss << tbl; + } +} + +void PGMap::dump_object_stat_sum(TextTable &tbl, Formatter *f, + const object_stat_sum_t &sum, uint64_t avail, + float raw_used_rate, bool verbose, + const pg_pool_t *pool) +{ + float curr_object_copies_rate = 0.0; + if (sum.num_object_copies > 0) + curr_object_copies_rate = (float)(sum.num_object_copies - sum.num_objects_degraded) / sum.num_object_copies; + + if (f) { + f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10)); + f->dump_int("bytes_used", sum.num_bytes); + f->dump_unsigned("max_avail", avail); + f->dump_int("objects", sum.num_objects); + if (verbose) { + f->dump_int("quota_objects", pool->quota_max_objects); + f->dump_int("quota_bytes", pool->quota_max_bytes); + f->dump_int("dirty", sum.num_objects_dirty); + f->dump_int("rd", sum.num_rd); + f->dump_int("rd_bytes", sum.num_rd_kb * 1024ull); + f->dump_int("wr", sum.num_wr); + f->dump_int("wr_bytes", sum.num_wr_kb * 1024ull); + f->dump_int("raw_bytes_used", sum.num_bytes * raw_used_rate * curr_object_copies_rate); + } + } else { + tbl << stringify(si_t(sum.num_bytes)); + float used = 0.0; + if (avail) { + used = sum.num_bytes * curr_object_copies_rate; + used /= used + avail; + } else if (sum.num_bytes) { + used = 1.0; + } + tbl << percentify(used*100); + tbl << si_t(avail); + tbl << sum.num_objects; + if (verbose) { + tbl << stringify(si_t(sum.num_objects_dirty)) + << stringify(si_t(sum.num_rd)) + << stringify(si_t(sum.num_wr)) + << stringify(si_t(sum.num_bytes * raw_used_rate * curr_object_copies_rate)); + } + } +} + + diff --git a/src/mon/PGMap.h b/src/mon/PGMap.h index 97f24305a57d..9fc98fbcd2cd 100644 --- a/src/mon/PGMap.h +++ b/src/mon/PGMap.h @@ -22,6 +22,7 @@ #define CEPH_PGMAP_H #include "common/debug.h" +#include "common/TextTable.h" #include "osd/osd_types.h" #include @@ -176,6 +177,8 @@ public: epoch_t calc_min_last_epoch_clean() const; + int64_t get_rule_avail(const OSDMap& osdmap, int ruleno) const; + public: set creating_pgs; @@ -269,6 +272,14 @@ public: void dirty_all(Incremental& inc); void dump(Formatter *f) const; + void dump_pool_stats(const OSDMap &osd_map, stringstream *ss, Formatter *f, + bool verbose) const; + void dump_fs_stats(stringstream *ss, Formatter *f, bool verbose) const; + static void dump_object_stat_sum(TextTable &tbl, Formatter *f, + const object_stat_sum_t &sum, + uint64_t avail, + float raw_used_rate, + bool verbose, const pg_pool_t *pool); void dump_basic(Formatter *f) const; void dump_pg_stats(Formatter *f, bool brief) const; void dump_pool_stats(Formatter *f) const; diff --git a/src/mon/PGMonitor.cc b/src/mon/PGMonitor.cc index 5edc22d95b9a..ad05ef2676a4 100644 --- a/src/mon/PGMonitor.cc +++ b/src/mon/PGMonitor.cc @@ -32,7 +32,6 @@ #include "messages/MOSDScrub.h" #include "common/Formatter.h" -#include "common/TextTable.h" #include "common/config.h" #include "include/stringify.h" @@ -1359,250 +1358,6 @@ void PGMonitor::check_down_pgs() need_check_down_pg_osds.clear(); } -inline string percentify(const float& a) { - stringstream ss; - if (a < 0.01) - ss << "0"; - else - ss << std::fixed << std::setprecision(2) << a; - return ss.str(); -} - -//void PGMonitor::dump_object_stat_sum(stringstream& ss, Formatter *f, -void PGMonitor::dump_object_stat_sum(TextTable &tbl, Formatter *f, - object_stat_sum_t &sum, uint64_t avail, - float raw_used_rate, bool verbose, const pg_pool_t *pool) -{ - float curr_object_copies_rate = 0.0; - if (sum.num_object_copies > 0) - curr_object_copies_rate = (float)(sum.num_object_copies - sum.num_objects_degraded) / sum.num_object_copies; - - if (f) { - f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10)); - f->dump_int("bytes_used", sum.num_bytes); - f->dump_unsigned("max_avail", avail); - f->dump_int("objects", sum.num_objects); - if (verbose) { - f->dump_int("quota_objects", pool->quota_max_objects); - f->dump_int("quota_bytes", pool->quota_max_bytes); - f->dump_int("dirty", sum.num_objects_dirty); - f->dump_int("rd", sum.num_rd); - f->dump_int("rd_bytes", sum.num_rd_kb * 1024ull); - f->dump_int("wr", sum.num_wr); - f->dump_int("wr_bytes", sum.num_wr_kb * 1024ull); - f->dump_int("raw_bytes_used", sum.num_bytes * raw_used_rate * curr_object_copies_rate); - } - } else { - tbl << stringify(si_t(sum.num_bytes)); - float used = 0.0; - if (avail) { - used = sum.num_bytes * curr_object_copies_rate; - used /= used + avail; - } else if (sum.num_bytes) { - used = 1.0; - } - tbl << percentify(used*100); - tbl << si_t(avail); - tbl << sum.num_objects; - if (verbose) { - tbl << stringify(si_t(sum.num_objects_dirty)) - << stringify(si_t(sum.num_rd)) - << stringify(si_t(sum.num_wr)) - << stringify(si_t(sum.num_bytes * raw_used_rate * curr_object_copies_rate)); - } - } -} - -int64_t PGMonitor::get_rule_avail(OSDMap& osdmap, int ruleno) const -{ - map wm; - int r = osdmap.crush->get_rule_weight_osd_map(ruleno, &wm); - if (r < 0) - return r; - - if(wm.empty()) - return 0; - - int64_t min = -1; - for (map::iterator p = wm.begin(); p != wm.end(); ++p) { - ceph::unordered_map::const_iterator osd_info = pg_map.osd_stat.find(p->first); - if (osd_info != pg_map.osd_stat.end()) { - if (osd_info->second.kb == 0 || p->second == 0) { - // osd must be out, hence its stats have been zeroed - // (unless we somehow managed to have a disk with size 0...) - // - // (p->second == 0), if osd weight is 0, no need to - // calculate proj below. - continue; - } - int64_t proj = (int64_t)((double)((osd_info->second).kb_avail * 1024ull) / - (double)p->second); - if (min < 0 || proj < min) - min = proj; - } else { - dout(0) << "Cannot get stat of OSD " << p->first << dendl; - } - } - return min; -} - -void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) -{ - TextTable tbl; - - if (f) { - f->open_array_section("pools"); - } else { - tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT); - tbl.define_column("ID", TextTable::LEFT, TextTable::LEFT); - if (verbose) { - tbl.define_column("CATEGORY", TextTable::LEFT, TextTable::LEFT); - tbl.define_column("QUOTA OBJECTS", TextTable::LEFT, TextTable::LEFT); - tbl.define_column("QUOTA BYTES", TextTable::LEFT, TextTable::LEFT); - } - - tbl.define_column("USED", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("%USED", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("MAX AVAIL", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); - if (verbose) { - tbl.define_column("DIRTY", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("READ", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("WRITE", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); - } - } - - map avail_by_rule; - OSDMap &osdmap = mon->osdmon()->osdmap; - for (map::const_iterator p = osdmap.get_pools().begin(); - p != osdmap.get_pools().end(); ++p) { - int64_t pool_id = p->first; - if ((pool_id < 0) || (pg_map.pg_pool_sum.count(pool_id) == 0)) - continue; - const string& pool_name = osdmap.get_pool_name(pool_id); - pool_stat_t &stat = pg_map.pg_pool_sum[pool_id]; - - const pg_pool_t *pool = osdmap.get_pg_pool(pool_id); - int ruleno = osdmap.crush->find_rule(pool->get_crush_ruleset(), - pool->get_type(), - pool->get_size()); - int64_t avail; - float raw_used_rate; - if (avail_by_rule.count(ruleno) == 0) { - avail = get_rule_avail(osdmap, ruleno); - if (avail < 0) - avail = 0; - avail_by_rule[ruleno] = avail; - } else { - avail = avail_by_rule[ruleno]; - } - switch (pool->get_type()) { - case pg_pool_t::TYPE_REPLICATED: - avail /= pool->get_size(); - raw_used_rate = pool->get_size(); - break; - case pg_pool_t::TYPE_ERASURE: - { - const map& ecp = - osdmap.get_erasure_code_profile(pool->erasure_code_profile); - map::const_iterator pm = ecp.find("m"); - map::const_iterator pk = ecp.find("k"); - if (pm != ecp.end() && pk != ecp.end()) { - int k = atoi(pk->second.c_str()); - int m = atoi(pm->second.c_str()); - avail = avail * k / (m + k); - raw_used_rate = (float)(m + k) / k; - } else { - raw_used_rate = 0.0; - } - } - break; - default: - assert(0 == "unrecognized pool type"); - } - - if (f) { - f->open_object_section("pool"); - f->dump_string("name", pool_name); - f->dump_int("id", pool_id); - f->open_object_section("stats"); - } else { - tbl << pool_name - << pool_id; - if (verbose) { - tbl << "-"; - - if (pool->quota_max_objects == 0) - tbl << "N/A"; - else - tbl << si_t(pool->quota_max_objects); - - if (pool->quota_max_bytes == 0) - tbl << "N/A"; - else - tbl << si_t(pool->quota_max_bytes); - } - - } - dump_object_stat_sum(tbl, f, stat.stats.sum, avail, raw_used_rate, verbose, pool); - if (f) - f->close_section(); // stats - else - tbl << TextTable::endrow; - - if (f) - f->close_section(); // pool - } - if (f) - f->close_section(); - else { - ss << "POOLS:\n"; - tbl.set_indent(4); - ss << tbl; - } -} - -void PGMonitor::dump_fs_stats(stringstream &ss, Formatter *f, bool verbose) const -{ - if (f) { - f->open_object_section("stats"); - f->dump_int("total_bytes", pg_map.osd_sum.kb * 1024ull); - f->dump_int("total_used_bytes", pg_map.osd_sum.kb_used * 1024ull); - f->dump_int("total_avail_bytes", pg_map.osd_sum.kb_avail * 1024ull); - if (verbose) { - f->dump_int("total_objects", pg_map.pg_sum.stats.sum.num_objects); - } - f->close_section(); - } else { - TextTable tbl; - tbl.define_column("SIZE", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("RAW USED", TextTable::LEFT, TextTable::RIGHT); - tbl.define_column("%RAW USED", TextTable::LEFT, TextTable::RIGHT); - if (verbose) { - tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); - } - tbl << stringify(si_t(pg_map.osd_sum.kb*1024)) - << stringify(si_t(pg_map.osd_sum.kb_avail*1024)) - << stringify(si_t(pg_map.osd_sum.kb_used*1024)); - float used = 0.0; - if (pg_map.osd_sum.kb > 0) { - used = ((float)pg_map.osd_sum.kb_used / pg_map.osd_sum.kb); - } - tbl << percentify(used*100); - if (verbose) { - tbl << stringify(si_t(pg_map.pg_sum.stats.sum.num_objects)); - } - tbl << TextTable::endrow; - - ss << "GLOBAL:\n"; - tbl.set_indent(4); - ss << tbl; - } -} - - void PGMonitor::dump_info(Formatter *f) const { f->open_object_section("pgmap"); diff --git a/src/mon/PGMonitor.h b/src/mon/PGMonitor.h index 509213d3361e..9c92d231bb07 100644 --- a/src/mon/PGMonitor.h +++ b/src/mon/PGMonitor.h @@ -128,14 +128,6 @@ private: int threshold, vector& args) const; - static void dump_object_stat_sum(TextTable &tbl, Formatter *f, - object_stat_sum_t &sum, - uint64_t avail, - float raw_used_rate, - bool verbose, const pg_pool_t *pool); - - int64_t get_rule_avail(OSDMap& osdmap, int ruleno) const; - public: PGMonitor(Monitor *mn, Paxos *p, const string& service_name) : PaxosService(mn, p, service_name), @@ -172,9 +164,6 @@ public: void check_osd_map(epoch_t epoch); - void dump_pool_stats(stringstream &ss, Formatter *f, bool verbose); - void dump_fs_stats(stringstream &ss, Formatter *f, bool verbose) const; - void dump_info(Formatter *f) const; int _warn_slow_request_histogram(const pow2_hist_t& h, string suffix, diff --git a/src/test/mon/CMakeLists.txt b/src/test/mon/CMakeLists.txt index c89bcdc29c0e..70270f86fe7c 100644 --- a/src/test/mon/CMakeLists.txt +++ b/src/test/mon/CMakeLists.txt @@ -46,8 +46,3 @@ add_executable(unittest_mon_pgmap add_ceph_unittest(unittest_mon_pgmap ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_mon_pgmap) target_link_libraries(unittest_mon_pgmap mon global) -add_executable(unittest_mon_pgmonitor - PGMonitor.cc - ) -add_ceph_unittest(unittest_mon_pgmonitor ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_mon_pgmonitor) -target_link_libraries(unittest_mon_pgmonitor mon global) diff --git a/src/test/mon/PGMap.cc b/src/test/mon/PGMap.cc index f13fa8936669..5cc3c89ee751 100644 --- a/src/test/mon/PGMap.cc +++ b/src/test/mon/PGMap.cc @@ -17,6 +17,7 @@ #include "common/ceph_argparse.h" #include "global/global_init.h" #include "global/global_context.h" +#include "include/stringify.h" TEST(pgmap, min_last_epoch_clean) { @@ -116,6 +117,135 @@ TEST(pgmap, calc_stats) } } +namespace { + class CheckTextTable : public TextTable { + public: + CheckTextTable(bool verbose) { + for (int i = 0; i < 4; i++) { + define_column("", TextTable::LEFT, TextTable::LEFT); + } + if (verbose) { + for (int i = 0; i < 4; i++) { + define_column("", TextTable::LEFT, TextTable::LEFT); + } + } + } + const string& get(unsigned r, unsigned c) const { + assert(r < row.size()); + assert(c < row[r].size()); + return row[r][c]; + } + }; + + // copied from PGMap.cc + string percentify(float a) { + stringstream ss; + if (a < 0.01) + ss << "0"; + else + ss << std::fixed << std::setprecision(2) << a; + return ss.str(); + } +} + +// dump_object_stat_sum() is called by "ceph df" command +// with table, without formatter, verbose = true, not empty, avail > 0 +TEST(pgmap, dump_object_stat_sum_0) +{ + bool verbose = true; + CheckTextTable tbl(verbose); + object_stat_sum_t sum; + sum.num_bytes = 42 * 1024 * 1024; + sum.num_objects = 42; + sum.num_objects_degraded = 13; // there are 13 missings + not_yet_backfilled + sum.num_objects_dirty = 2; + sum.num_rd = 100; + sum.num_rd_kb = 123; + sum.num_wr = 101; + sum.num_wr_kb = 321; + + sum.calc_copies(3); // assuming we have 3 copies for each obj + // nominal amount of space available for new objects in this pool + uint64_t avail = 2016 * 1024 * 1024; + pg_pool_t pool; + pool.quota_max_objects = 2000; + pool.quota_max_bytes = 2000 * 1024 * 1024; + pool.size = 2; + pool.type = pg_pool_t::TYPE_REPLICATED; + PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail, + pool.get_size(), verbose, &pool); + ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, 0)); + float copies_rate = + (static_cast(sum.num_object_copies - sum.num_objects_degraded) / + sum.num_object_copies); + float used_bytes = sum.num_bytes * copies_rate; + float used_percent = used_bytes / (used_bytes + avail) * 100; + unsigned col = 0; + ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, col++)); + ASSERT_EQ(percentify(used_percent), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++)); + ASSERT_EQ(stringify(sum.num_objects), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(sum.num_objects_dirty)), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(sum.num_rd)), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(sum.num_wr)), tbl.get(0, col++)); + // we can use pool.size for raw_used_rate if it is a replica pool + uint64_t raw_bytes_used = sum.num_bytes * pool.get_size() * copies_rate; + ASSERT_EQ(stringify(si_t(raw_bytes_used)), tbl.get(0, col++)); +} + +// with table, without formatter, verbose = true, empty, avail > 0 +TEST(pgmap, dump_object_stat_sum_1) +{ + bool verbose = true; + CheckTextTable tbl(verbose); + object_stat_sum_t sum; // zero by default + ASSERT_TRUE(sum.is_zero()); + // nominal amount of space available for new objects in this pool + uint64_t avail = 2016 * 1024 * 1024; + pg_pool_t pool; + pool.quota_max_objects = 2000; + pool.quota_max_bytes = 2000 * 1024 * 1024; + pool.size = 2; + pool.type = pg_pool_t::TYPE_REPLICATED; + PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail, + pool.get_size(), verbose, &pool); + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0)); + unsigned col = 0; + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); + ASSERT_EQ(percentify(0), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++)); + ASSERT_EQ(stringify(0), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); +} + +// with table, without formatter, verbose = false, empty, avail = 0 +TEST(pgmap, dump_object_stat_sum_2) +{ + bool verbose = false; + CheckTextTable tbl(verbose); + object_stat_sum_t sum; // zero by default + ASSERT_TRUE(sum.is_zero()); + // nominal amount of space available for new objects in this pool + uint64_t avail = 0; + pg_pool_t pool; + pool.quota_max_objects = 2000; + pool.quota_max_bytes = 2000 * 1024 * 1024; + pool.size = 2; + pool.type = pg_pool_t::TYPE_REPLICATED; + + PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail, + pool.get_size(), verbose, &pool); + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0)); + unsigned col = 0; + ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); + ASSERT_EQ(percentify(0), tbl.get(0, col++)); + ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++)); + ASSERT_EQ(stringify(0), tbl.get(0, col++)); +} + int main(int argc, char **argv) { vector args; argv_to_vec(argc, (const char **)argv, args); diff --git a/src/test/mon/PGMonitor.cc b/src/test/mon/PGMonitor.cc deleted file mode 100644 index 84703228e017..000000000000 --- a/src/test/mon/PGMonitor.cc +++ /dev/null @@ -1,152 +0,0 @@ -// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "gtest/gtest.h" - -#include "common/ceph_argparse.h" -#include "common/TextTable.h" -#include "global/global_init.h" -#include "global/global_context.h" -#include "include/stringify.h" -#include "mon/PGMonitor.h" - -namespace { - class CheckTextTable : public TextTable { - public: - CheckTextTable(bool verbose) { - for (int i = 0; i < 4; i++) { - define_column("", TextTable::LEFT, TextTable::LEFT); - } - if (verbose) { - for (int i = 0; i < 4; i++) { - define_column("", TextTable::LEFT, TextTable::LEFT); - } - } - } - const string& get(unsigned r, unsigned c) const { - assert(r < row.size()); - assert(c < row[r].size()); - return row[r][c]; - } - }; - - // copied from PGMonitor.cc - string percentify(float a) { - stringstream ss; - if (a < 0.01) - ss << "0"; - else - ss << std::fixed << std::setprecision(2) << a; - return ss.str(); - } -} - -// dump_object_stat_sum() is called by "ceph df" command -// with table, without formatter, verbose = true, not empty, avail > 0 -TEST(pgmonitor, dump_object_stat_sum_0) -{ - bool verbose = true; - CheckTextTable tbl(verbose); - object_stat_sum_t sum; - sum.num_bytes = 42 * 1024 * 1024; - sum.num_objects = 42; - sum.num_objects_degraded = 13; // there are 13 missings + not_yet_backfilled - sum.num_objects_dirty = 2; - sum.num_rd = 100; - sum.num_rd_kb = 123; - sum.num_wr = 101; - sum.num_wr_kb = 321; - - sum.calc_copies(3); // assuming we have 3 copies for each obj - // nominal amount of space available for new objects in this pool - uint64_t avail = 2016 * 1024 * 1024; - pg_pool_t pool; - pool.quota_max_objects = 2000; - pool.quota_max_bytes = 2000 * 1024 * 1024; - pool.size = 2; - pool.type = pg_pool_t::TYPE_REPLICATED; - PGMonitor::dump_object_stat_sum(tbl, nullptr, sum, avail, - pool.get_size(), verbose, &pool); - ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, 0)); - float copies_rate = - (static_cast(sum.num_object_copies - sum.num_objects_degraded) / - sum.num_object_copies); - float used_bytes = sum.num_bytes * copies_rate; - float used_percent = used_bytes / (used_bytes + avail) * 100; - unsigned col = 0; - ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, col++)); - ASSERT_EQ(percentify(used_percent), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++)); - ASSERT_EQ(stringify(sum.num_objects), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(sum.num_objects_dirty)), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(sum.num_rd)), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(sum.num_wr)), tbl.get(0, col++)); - // we can use pool.size for raw_used_rate if it is a replica pool - uint64_t raw_bytes_used = sum.num_bytes * pool.get_size() * copies_rate; - ASSERT_EQ(stringify(si_t(raw_bytes_used)), tbl.get(0, col++)); -} - -// with table, without formatter, verbose = true, empty, avail > 0 -TEST(pgmonitor, dump_object_stat_sum_1) -{ - bool verbose = true; - CheckTextTable tbl(verbose); - object_stat_sum_t sum; // zero by default - ASSERT_TRUE(sum.is_zero()); - // nominal amount of space available for new objects in this pool - uint64_t avail = 2016 * 1024 * 1024; - pg_pool_t pool; - pool.quota_max_objects = 2000; - pool.quota_max_bytes = 2000 * 1024 * 1024; - pool.size = 2; - pool.type = pg_pool_t::TYPE_REPLICATED; - PGMonitor::dump_object_stat_sum(tbl, nullptr, sum, avail, - pool.get_size(), verbose, &pool); - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0)); - unsigned col = 0; - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); - ASSERT_EQ(percentify(0), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++)); - ASSERT_EQ(stringify(0), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); -} - -// with table, without formatter, verbose = false, empty, avail = 0 -TEST(pgmonitor, dump_object_stat_sum_2) -{ - bool verbose = false; - CheckTextTable tbl(verbose); - object_stat_sum_t sum; // zero by default - ASSERT_TRUE(sum.is_zero()); - // nominal amount of space available for new objects in this pool - uint64_t avail = 0; - pg_pool_t pool; - pool.quota_max_objects = 2000; - pool.quota_max_bytes = 2000 * 1024 * 1024; - pool.size = 2; - pool.type = pg_pool_t::TYPE_REPLICATED; - - PGMonitor::dump_object_stat_sum(tbl, nullptr, sum, avail, - pool.get_size(), verbose, &pool); - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0)); - unsigned col = 0; - ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++)); - ASSERT_EQ(percentify(0), tbl.get(0, col++)); - ASSERT_EQ(stringify(si_t(avail)), tbl.get(0, col++)); - ASSERT_EQ(stringify(0), tbl.get(0, col++)); -} - -int main(int argc, char **argv) { - vector args; - argv_to_vec(argc, (const char **)argv, args); - env_to_vec(args); - - vector def_args; - global_init(&def_args, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); - common_init_finish(g_ceph_context); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -}