...so that ceph-mgr can use it too.
Signed-off-by: John Spray <john.spray@redhat.com>
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();
#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"
// --
ss << tab;
}
+int64_t PGMap::get_rule_avail(const OSDMap& osdmap, int ruleno) const
+{
+ map<int,float> 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<int,float>::iterator p = wm.begin(); p != wm.end(); ++p) {
+ ceph::unordered_map<int32_t,osd_stat_t>::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<int,uint64_t> avail_by_rule;
+ for (map<int64_t,pg_pool_t>::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<string,string>& ecp =
+ osd_map.get_erasure_code_profile(pool->erasure_code_profile);
+ map<string,string>::const_iterator pm = ecp.find("m");
+ map<string,string>::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));
+ }
+ }
+}
+
+
#define CEPH_PGMAP_H
#include "common/debug.h"
+#include "common/TextTable.h"
#include "osd/osd_types.h"
#include <sstream>
epoch_t calc_min_last_epoch_clean() const;
+ int64_t get_rule_avail(const OSDMap& osdmap, int ruleno) const;
+
public:
set<pg_t> creating_pgs;
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;
#include "messages/MOSDScrub.h"
#include "common/Formatter.h"
-#include "common/TextTable.h"
#include "common/config.h"
#include "include/stringify.h"
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<int,float> 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<int,float>::iterator p = wm.begin(); p != wm.end(); ++p) {
- ceph::unordered_map<int32_t,osd_stat_t>::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<int,uint64_t> avail_by_rule;
- OSDMap &osdmap = mon->osdmon()->osdmap;
- for (map<int64_t,pg_pool_t>::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<string,string>& ecp =
- osdmap.get_erasure_code_profile(pool->erasure_code_profile);
- map<string,string>::const_iterator pm = ecp.find("m");
- map<string,string>::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");
int threshold,
vector<string>& 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),
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,
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)
#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)
{
}
}
+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<float>(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<const char*> args;
argv_to_vec(argc, (const char **)argv, args);
+++ /dev/null
-// -*- 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<float>(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<const char*> args;
- argv_to_vec(argc, (const char **)argv, args);
- env_to_vec(args);
-
- vector<const char*> 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();
-}