<< std::endl;
}
-void PGMap::get_stuck_stats(PGMap::StuckPG type, utime_t cutoff,
+void PGMap::get_stuck_stats(int types, utime_t cutoff,
ceph::unordered_map<pg_t, pg_stat_t>& stuck_pgs) const
{
+ assert(types != 0);
for (ceph::unordered_map<pg_t, pg_stat_t>::const_iterator i = pg_stat.begin();
i != pg_stat.end();
++i) {
- utime_t val;
- switch (type) {
- case STUCK_INACTIVE:
- if (i->second.state & PG_STATE_ACTIVE)
- continue;
- val = i->second.last_active;
- break;
- case STUCK_UNCLEAN:
- if (i->second.state & PG_STATE_CLEAN)
- continue;
- val = i->second.last_clean;
- break;
- case STUCK_DEGRADED:
- if ((i->second.state & PG_STATE_DEGRADED) == 0)
- continue;
- val = i->second.last_undegraded;
- break;
- case STUCK_UNDERSIZED:
- if ((i->second.state & PG_STATE_UNDERSIZED) == 0)
- continue;
- val = i->second.last_fullsized;
- break;
- case STUCK_STALE:
- if ((i->second.state & PG_STATE_STALE) == 0)
- continue;
- val = i->second.last_unstale;
- break;
- default:
- assert(0 == "invalid type");
+ utime_t val = cutoff; // don't care about >= cutoff so that is infinity
+
+ if ((types & STUCK_INACTIVE) && ! (i->second.state & PG_STATE_ACTIVE)) {
+ if (i->second.last_active < val)
+ val = i->second.last_active;
+ }
+
+ if ((types & STUCK_UNCLEAN) && ! (i->second.state & PG_STATE_CLEAN)) {
+ if (i->second.last_clean < val)
+ val = i->second.last_clean;
+ }
+
+ if ((types & STUCK_DEGRADED) && (i->second.state & PG_STATE_DEGRADED)) {
+ if (i->second.last_undegraded < val)
+ val = i->second.last_undegraded;
+ }
+
+ if ((types & STUCK_UNDERSIZED) && (i->second.state & PG_STATE_UNDERSIZED)) {
+ if (i->second.last_fullsized < val)
+ val = i->second.last_fullsized;
+ }
+
+ if ((types & STUCK_STALE) && (i->second.state & PG_STATE_STALE)) {
+ if (i->second.last_unstale < val)
+ val = i->second.last_unstale;
}
+ // val is now the earliest any of the requested stuck states began
if (val < cutoff) {
stuck_pgs[i->first] = i->second;
}
}
}
-void PGMap::dump_stuck(Formatter *f, PGMap::StuckPG type, utime_t cutoff) const
+void PGMap::dump_stuck(Formatter *f, int types, utime_t cutoff) const
{
ceph::unordered_map<pg_t, pg_stat_t> stuck_pg_stats;
- get_stuck_stats(type, cutoff, stuck_pg_stats);
+ get_stuck_stats(types, cutoff, stuck_pg_stats);
f->open_array_section("stuck_pg_stats");
for (ceph::unordered_map<pg_t,pg_stat_t>::const_iterator i = stuck_pg_stats.begin();
i != stuck_pg_stats.end();
f->close_section();
}
-void PGMap::dump_stuck_plain(ostream& ss, PGMap::StuckPG type, utime_t cutoff) const
+void PGMap::dump_stuck_plain(ostream& ss, int types, utime_t cutoff) const
{
ceph::unordered_map<pg_t, pg_stat_t> stuck_pg_stats;
- get_stuck_stats(type, cutoff, stuck_pg_stats);
+ get_stuck_stats(types, cutoff, stuck_pg_stats);
if (!stuck_pg_stats.empty())
dump_pg_stats_plain(ss, stuck_pg_stats, true);
}
set<pg_t> creating_pgs; // lru: front = new additions, back = recently pinged
map<int,set<pg_t> > creating_pgs_by_osd;
- enum StuckPG {
- STUCK_INACTIVE,
- STUCK_UNCLEAN,
- STUCK_UNDERSIZED,
- STUCK_DEGRADED,
- STUCK_STALE,
- STUCK_NONE
- };
+ // Bits that use to be enum StuckPG
+ static const int STUCK_INACTIVE = (1<<0);
+ static const int STUCK_UNCLEAN = (1<<1);
+ static const int STUCK_UNDERSIZED = (1<<2);
+ static const int STUCK_DEGRADED = (1<<3);
+ static const int STUCK_STALE = (1<<4);
PGMap()
: version(0),
void dump_pg_stats_plain(ostream& ss,
const ceph::unordered_map<pg_t, pg_stat_t>& pg_stats,
bool brief) const;
- void get_stuck_stats(StuckPG type, utime_t cutoff,
+ void get_stuck_stats(int types, utime_t cutoff,
ceph::unordered_map<pg_t, pg_stat_t>& stuck_pgs) const;
- void dump_stuck(Formatter *f, StuckPG type, utime_t cutoff) const;
- void dump_stuck_plain(ostream& ss, StuckPG type, utime_t cutoff) const;
+ void dump_stuck(Formatter *f, int types, utime_t cutoff) const;
+ void dump_stuck_plain(ostream& ss, int types, utime_t cutoff) const;
void dump(ostream& ss) const;
void dump_basic(ostream& ss) const;
return true;
}
-static void note_stuck_detail(enum PGMap::StuckPG what,
+// Only called with a single bit set in "what"
+static void note_stuck_detail(int what,
ceph::unordered_map<pg_t,pg_stat_t>& stuck_pgs,
list<pair<health_status_t,string> > *detail)
{
int threshold,
vector<string>& args) const
{
- PGMap::StuckPG stuck_type;
- string type = args[0];
-
- if (type == "inactive")
- stuck_type = PGMap::STUCK_INACTIVE;
- else if (type == "unclean")
- stuck_type = PGMap::STUCK_UNCLEAN;
- else if (type == "undersized")
- stuck_type = PGMap::STUCK_UNDERSIZED;
- else if (type == "degraded")
- stuck_type = PGMap::STUCK_DEGRADED;
- else if (type == "stale")
- stuck_type = PGMap::STUCK_STALE;
- else {
- ds << "Unknown type: " << type << std::endl;
- return 0;
+ int stuck_types = 0;
+
+ for (vector<string>::iterator i = args.begin() ; i != args.end(); ++i) {
+ if (*i == "inactive")
+ stuck_types |= PGMap::STUCK_INACTIVE;
+ else if (*i == "unclean")
+ stuck_types |= PGMap::STUCK_UNCLEAN;
+ else if (*i == "undersized")
+ stuck_types |= PGMap::STUCK_UNDERSIZED;
+ else if (*i == "degraded")
+ stuck_types |= PGMap::STUCK_DEGRADED;
+ else if (*i == "stale")
+ stuck_types |= PGMap::STUCK_STALE;
+ else {
+ ds << "Unknown type: " << *i << std::endl;
+ return 0;
+ }
}
utime_t now(ceph_clock_now(g_ceph_context));
utime_t cutoff = now - utime_t(threshold, 0);
if (!f) {
- pg_map.dump_stuck_plain(ds, stuck_type, cutoff);
+ pg_map.dump_stuck_plain(ds, stuck_types, cutoff);
} else {
- pg_map.dump_stuck(f, stuck_type, cutoff);
+ pg_map.dump_stuck(f, stuck_types, cutoff);
f->flush(ds);
}