#include "common/hobject_fmt.h"
#include "osd/osd_types.h"
+#include <fmt/chrono.h>
+#if FMT_VERSION >= 90000
+#include <fmt/ostream.h>
+#endif
template <>
struct fmt::formatter<osd_reqid_t> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
- auto format(const osd_reqid_t& req_id, FormatContext& ctx)
+ auto format(const osd_reqid_t& req_id, FormatContext& ctx) const
{
return fmt::format_to(ctx.out(), "{}.{}:{}", req_id.name, req_id.inc,
req_id.tid);
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
- auto format(const pg_shard_t& shrd, FormatContext& ctx)
+ auto format(const pg_shard_t& shrd, FormatContext& ctx) const
{
if (shrd.is_undefined()) {
return fmt::format_to(ctx.out(), "?");
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
- auto format(const eversion_t& ev, FormatContext& ctx)
+ auto format(const eversion_t& ev, FormatContext& ctx) const
{
return fmt::format_to(ctx.out(), "{}'{}", ev.epoch, ev.version);
}
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
- auto format(const object_manifest_t& om, FormatContext& ctx)
+ auto format(const object_manifest_t& om, FormatContext& ctx) const
{
fmt::format_to(ctx.out(), "manifest({}", om.get_type_name());
if (om.is_redirect()) {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
- auto format(const object_info_t& oi, FormatContext& ctx)
+ auto format(const object_info_t& oi, FormatContext& ctx) const
{
fmt::format_to(ctx.out(), "{}({} {} {} s {} uv {}", oi.soid, oi.version,
oi.last_reqid, (oi.flags ? oi.get_flag_string() : ""), oi.size,
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
- auto format(const pg_t& pg, FormatContext& ctx)
+ auto format(const pg_t& pg, FormatContext& ctx) const
{
return fmt::format_to(ctx.out(), "{}.{:x}", pg.pool(), pg.m_seed);
}
};
+
+
+template <>
+struct fmt::formatter<spg_t> {
+ constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
+
+ template <typename FormatContext>
+ auto format(const spg_t& spg, FormatContext& ctx) const
+ {
+ if (shard_id_t::NO_SHARD == spg.shard.id) {
+ return fmt::format_to(ctx.out(), "{}", spg.pgid);
+ } else {
+ return fmt::format_to(ctx.out(), "{}s{}>", spg.pgid, spg.shard.id);
+ }
+ }
+};
+
+template <>
+struct fmt::formatter<pg_history_t> {
+ constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
+
+ template <typename FormatContext>
+ auto format(const pg_history_t& pgh, FormatContext& ctx) const
+ {
+ fmt::format_to(ctx.out(),
+ "ec={}/{} lis/c={}/{} les/c/f={}/{}/{} sis={}",
+ pgh.epoch_created,
+ pgh.epoch_pool_created,
+ pgh.last_interval_started,
+ pgh.last_interval_clean,
+ pgh.last_epoch_started,
+ pgh.last_epoch_clean,
+ pgh.last_epoch_marked_full,
+ pgh.same_interval_since);
+
+ if (pgh.prior_readable_until_ub != ceph::timespan::zero()) {
+ return fmt::format_to(ctx.out(),
+ " pruub={}",
+ pgh.prior_readable_until_ub);
+ } else {
+ return ctx.out();
+ }
+ }
+};
+
+template <>
+struct fmt::formatter<pg_info_t> {
+ constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
+
+ template <typename FormatContext>
+ auto format(const pg_info_t& pgi, FormatContext& ctx)
+ {
+ fmt::format_to(ctx.out(), "{}({}", pgi.pgid, (pgi.dne() ? " DNE" : ""));
+ if (pgi.is_empty()) {
+ fmt::format_to(ctx.out(), " empty");
+ } else {
+ fmt::format_to(ctx.out(), " v {}", pgi.last_update);
+ if (pgi.last_complete != pgi.last_update) {
+ fmt::format_to(ctx.out(), " lc {}", pgi.last_complete);
+ }
+ fmt::format_to(ctx.out(), " ({},{}]", pgi.log_tail, pgi.last_update);
+ }
+ if (pgi.is_incomplete()) {
+ fmt::format_to(ctx.out(), " lb {}", pgi.last_backfill);
+ }
+ fmt::format_to(ctx.out(),
+ " local-lis/les={}/{}",
+ pgi.last_interval_started,
+ pgi.last_epoch_started);
+ return fmt::format_to(ctx.out(),
+ " n={} {})",
+ pgi.stats.stats.sum.num_objects,
+ pgi.history);
+ }
+};
+
+// snaps and snap-sets
+
+template <>
+struct fmt::formatter<SnapSet> {
+ template <typename ParseContext>
+ constexpr auto parse(ParseContext& ctx)
+ {
+ auto it = ctx.begin();
+ if (it != ctx.end() && *it == 'D') {
+ verbose = true;
+ ++it;
+ }
+ return it;
+ }
+
+ template <typename FormatContext>
+ auto format(const SnapSet& snps, FormatContext& ctx)
+ {
+ if (verbose) {
+ // similar to SnapSet::dump()
+ fmt::format_to(ctx.out(),
+ "snaps{{{}: clns ({}): ",
+ snps.seq,
+ snps.clones.size());
+ for (auto cln : snps.clones) {
+
+ fmt::format_to(ctx.out(), "[{}: sz:", cln);
+
+ auto cs = snps.clone_size.find(cln);
+ if (cs != snps.clone_size.end()) {
+ fmt::format_to(ctx.out(), "{} ", cs->second);
+ } else {
+ fmt::format_to(ctx.out(), "??");
+ }
+
+ auto co = snps.clone_overlap.find(cln);
+ if (co != snps.clone_overlap.end()) {
+ fmt::format_to(ctx.out(), "olp:{} ", co->second);
+ } else {
+ fmt::format_to(ctx.out(), "olp:?? ");
+ }
+
+ auto cln_snps = snps.clone_snaps.find(cln);
+ if (cln_snps != snps.clone_snaps.end()) {
+ fmt::format_to(ctx.out(), "cl-snps:{} ]", cln_snps->second);
+ } else {
+ fmt::format_to(ctx.out(), "cl-snps:?? ]");
+ }
+ }
+
+ return fmt::format_to(ctx.out(), "}}");
+
+ } else {
+ return fmt::format_to(ctx.out(),
+ "{}={}:{}",
+ snps.seq,
+ snps.snaps,
+ snps.clone_snaps);
+ }
+ }
+
+ bool verbose{false};
+};
+
+template <>
+struct fmt::formatter<ScrubMap::object> {
+ constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
+
+ ///\todo: consider passing the 'D" flag to control snapset dump
+ template <typename FormatContext>
+ auto format(const ScrubMap::object& so, FormatContext& ctx)
+ {
+ fmt::format_to(ctx.out(),
+ "so{{ sz:{} dd:{} od:{} ",
+ so.size,
+ so.digest,
+ so.digest_present);
+
+ // note the special handling of (1) OI_ATTR and (2) non-printables
+ for (auto [k, v] : so.attrs) {
+ std::string bkstr{v.raw_c_str(), v.raw_length()};
+ if (k == std::string{OI_ATTR}) {
+ /// \todo consider parsing the OI args here. Maybe add a specific format
+ /// specifier
+ fmt::format_to(ctx.out(), "{{{}:<<OI_ATTR>>({})}} ", k, bkstr.length());
+ } else if (k == std::string{SS_ATTR}) {
+ bufferlist bl;
+ bl.push_back(v);
+ SnapSet sns{bl};
+ fmt::format_to(ctx.out(), "{{{}:{:D}}} ", k, sns);
+ } else {
+ fmt::format_to(ctx.out(), "{{{}:{}({})}} ", k, bkstr, bkstr.length());
+ }
+ }
+
+ return fmt::format_to(ctx.out(), "}}");
+ }
+};
+
+template <>
+struct fmt::formatter<ScrubMap> {
+ template <typename ParseContext>
+ constexpr auto parse(ParseContext& ctx)
+ {
+ auto it = ctx.begin();
+ if (it != ctx.end() && *it == 'D') {
+ debug_log = true; // list the objects
+ ++it;
+ }
+ return it;
+ }
+
+ template <typename FormatContext>
+ auto format(const ScrubMap& smap, FormatContext& ctx)
+ {
+ fmt::format_to(ctx.out(),
+ "smap{{ valid:{} incr-since:{} #:{}",
+ smap.valid_through,
+ smap.incr_since,
+ smap.objects.size());
+ if (debug_log) {
+ fmt::format_to(ctx.out(), " objects:");
+ for (const auto& [ho, so] : smap.objects) {
+ fmt::format_to(ctx.out(), "\n\th.o<{}>:<{}> ", ho, so);
+ }
+ fmt::format_to(ctx.out(), "\n");
+ }
+ return fmt::format_to(ctx.out(), "}}");
+ }
+
+ bool debug_log{false};
+};
+
+#if FMT_VERSION >= 90000
+template <> struct fmt::formatter<ObjectRecoveryInfo> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<ObjectRecoveryProgress> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<PastIntervals> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<pg_log_op_return_item_t> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<watch_info_t> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<pg_log_entry_t> : fmt::ostream_formatter {};
+template <bool TrackChanges> struct fmt::formatter<pg_missing_set<TrackChanges>> : fmt::ostream_formatter {};
+#endif
}
void PgScrubber::apply_snap_mapper_fixes(
- const std::vector<snap_mapper_fix_t>& fix_list)
+ const std::vector<Scrub::snap_mapper_fix_t>& fix_list)
{
dout(15) << __func__ << " " << fix_list.size() << " fixes" << dendl;
}
-std::vector<snap_mapper_fix_t> PgScrubber::_scan_snaps(ScrubMap& smap)
+std::vector<Scrub::snap_mapper_fix_t> PgScrubber::_scan_snaps(ScrubMap& smap)
{
- std::vector<snap_mapper_fix_t> out_orders;
+ std::vector<Scrub::snap_mapper_fix_t> out_orders;
hobject_t head;
SnapSet snapset;
return out_orders;
}
-std::optional<snap_mapper_fix_t> PgScrubber::scan_object_snaps(
+std::optional<Scrub::snap_mapper_fix_t> PgScrubber::scan_object_snaps(
const hobject_t& hoid,
const SnapSet& snapset,
SnapMapReaderI& snaps_getter)
case result_t::code_t::not_found:
dout(10) << __func__ << ": no snaps for " << hoid << ". Adding."
<< dendl;
- return snap_mapper_fix_t{snap_mapper_op_t::add, hoid, obj_snaps, {}};
+ return Scrub::snap_mapper_fix_t{snap_mapper_op_t::add, hoid, obj_snaps, {}};
case result_t::code_t::inconsistent:
dout(10) << __func__ << ": inconsistent snapmapper data for " << hoid
<< ". Recreating." << dendl;
- return snap_mapper_fix_t{
+ return Scrub::snap_mapper_fix_t{
snap_mapper_op_t::overwrite, hoid, obj_snaps, {}};
default:
dout(10) << __func__ << ": error (" << cpp_strerror(e.backend_error)
<< ") fetching snapmapper data for " << hoid << ". Recreating."
<< dendl;
- return snap_mapper_fix_t{
+ return Scrub::snap_mapper_fix_t{
snap_mapper_op_t::overwrite, hoid, obj_snaps, {}};
}
__builtin_unreachable();
"{}: obj {}: was: {} updating to: {}", __func__, hoid,
*cur_snaps, obj_snaps)
<< dendl;
- return snap_mapper_fix_t{
+ return Scrub::snap_mapper_fix_t{
snap_mapper_op_t::update, hoid, obj_snaps, *cur_snaps};
}