]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | #pragma once | |
4 | /** | |
5 | * \file fmtlib formatters for some types.h classes | |
6 | */ | |
7 | ||
8 | #include "common/hobject_fmt.h" | |
9 | #include "osd/osd_types.h" | |
1e59de90 TL |
10 | #include <fmt/chrono.h> |
11 | #if FMT_VERSION >= 90000 | |
12 | #include <fmt/ostream.h> | |
13 | #endif | |
20effc67 TL |
14 | |
15 | template <> | |
16 | struct fmt::formatter<osd_reqid_t> { | |
17 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
18 | ||
19 | template <typename FormatContext> | |
1e59de90 | 20 | auto format(const osd_reqid_t& req_id, FormatContext& ctx) const |
20effc67 TL |
21 | { |
22 | return fmt::format_to(ctx.out(), "{}.{}:{}", req_id.name, req_id.inc, | |
23 | req_id.tid); | |
24 | } | |
25 | }; | |
26 | ||
27 | template <> | |
28 | struct fmt::formatter<pg_shard_t> { | |
29 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
30 | ||
31 | template <typename FormatContext> | |
1e59de90 | 32 | auto format(const pg_shard_t& shrd, FormatContext& ctx) const |
20effc67 TL |
33 | { |
34 | if (shrd.is_undefined()) { | |
35 | return fmt::format_to(ctx.out(), "?"); | |
36 | } | |
37 | if (shrd.shard == shard_id_t::NO_SHARD) { | |
38 | return fmt::format_to(ctx.out(), "{}", shrd.get_osd()); | |
39 | } | |
40 | return fmt::format_to(ctx.out(), "{}({})", shrd.get_osd(), shrd.shard); | |
41 | } | |
42 | }; | |
43 | ||
44 | template <> | |
45 | struct fmt::formatter<eversion_t> { | |
46 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
47 | ||
48 | template <typename FormatContext> | |
1e59de90 | 49 | auto format(const eversion_t& ev, FormatContext& ctx) const |
20effc67 TL |
50 | { |
51 | return fmt::format_to(ctx.out(), "{}'{}", ev.epoch, ev.version); | |
52 | } | |
53 | }; | |
54 | ||
55 | template <> | |
56 | struct fmt::formatter<chunk_info_t> { | |
57 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
58 | ||
59 | template <typename FormatContext> | |
60 | auto format(const chunk_info_t& ci, FormatContext& ctx) | |
61 | { | |
62 | return fmt::format_to(ctx.out(), "(len: {} oid: {} offset: {} flags: {})", | |
63 | ci.length, ci.oid, ci.offset, | |
64 | ci.get_flag_string(ci.flags)); | |
65 | } | |
66 | }; | |
67 | ||
68 | template <> | |
69 | struct fmt::formatter<object_manifest_t> { | |
70 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
71 | ||
72 | template <typename FormatContext> | |
1e59de90 | 73 | auto format(const object_manifest_t& om, FormatContext& ctx) const |
20effc67 TL |
74 | { |
75 | fmt::format_to(ctx.out(), "manifest({}", om.get_type_name()); | |
76 | if (om.is_redirect()) { | |
77 | fmt::format_to(ctx.out(), " {}", om.redirect_target); | |
78 | } else if (om.is_chunked()) { | |
79 | fmt::format_to(ctx.out(), " {}", om.chunk_map); | |
80 | } | |
81 | return fmt::format_to(ctx.out(), ")"); | |
82 | } | |
83 | }; | |
84 | ||
85 | template <> | |
86 | struct fmt::formatter<object_info_t> { | |
87 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
88 | ||
89 | template <typename FormatContext> | |
1e59de90 | 90 | auto format(const object_info_t& oi, FormatContext& ctx) const |
20effc67 TL |
91 | { |
92 | fmt::format_to(ctx.out(), "{}({} {} {} s {} uv {}", oi.soid, oi.version, | |
93 | oi.last_reqid, (oi.flags ? oi.get_flag_string() : ""), oi.size, | |
94 | oi.user_version); | |
95 | if (oi.is_data_digest()) { | |
96 | fmt::format_to(ctx.out(), " dd {:x}", oi.data_digest); | |
97 | } | |
98 | if (oi.is_omap_digest()) { | |
99 | fmt::format_to(ctx.out(), " od {:x}", oi.omap_digest); | |
100 | } | |
101 | ||
102 | fmt::format_to(ctx.out(), " alloc_hint [{} {} {}]", oi.expected_object_size, | |
103 | oi.expected_write_size, oi.alloc_hint_flags); | |
104 | ||
105 | if (oi.has_manifest()) { | |
106 | fmt::format_to(ctx.out(), " {}", oi.manifest); | |
107 | } | |
108 | return fmt::format_to(ctx.out(), ")"); | |
109 | } | |
110 | }; | |
2a845540 TL |
111 | |
112 | template <> | |
113 | struct fmt::formatter<pg_t> { | |
114 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
115 | ||
116 | template <typename FormatContext> | |
1e59de90 | 117 | auto format(const pg_t& pg, FormatContext& ctx) const |
2a845540 TL |
118 | { |
119 | return fmt::format_to(ctx.out(), "{}.{:x}", pg.pool(), pg.m_seed); | |
120 | } | |
121 | }; | |
1e59de90 TL |
122 | |
123 | ||
124 | template <> | |
125 | struct fmt::formatter<spg_t> { | |
126 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
127 | ||
128 | template <typename FormatContext> | |
129 | auto format(const spg_t& spg, FormatContext& ctx) const | |
130 | { | |
131 | if (shard_id_t::NO_SHARD == spg.shard.id) { | |
132 | return fmt::format_to(ctx.out(), "{}", spg.pgid); | |
133 | } else { | |
134 | return fmt::format_to(ctx.out(), "{}s{}>", spg.pgid, spg.shard.id); | |
135 | } | |
136 | } | |
137 | }; | |
138 | ||
139 | template <> | |
140 | struct fmt::formatter<pg_history_t> { | |
141 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
142 | ||
143 | template <typename FormatContext> | |
144 | auto format(const pg_history_t& pgh, FormatContext& ctx) const | |
145 | { | |
146 | fmt::format_to(ctx.out(), | |
147 | "ec={}/{} lis/c={}/{} les/c/f={}/{}/{} sis={}", | |
148 | pgh.epoch_created, | |
149 | pgh.epoch_pool_created, | |
150 | pgh.last_interval_started, | |
151 | pgh.last_interval_clean, | |
152 | pgh.last_epoch_started, | |
153 | pgh.last_epoch_clean, | |
154 | pgh.last_epoch_marked_full, | |
155 | pgh.same_interval_since); | |
156 | ||
157 | if (pgh.prior_readable_until_ub != ceph::timespan::zero()) { | |
158 | return fmt::format_to(ctx.out(), | |
159 | " pruub={}", | |
160 | pgh.prior_readable_until_ub); | |
161 | } else { | |
162 | return ctx.out(); | |
163 | } | |
164 | } | |
165 | }; | |
166 | ||
167 | template <> | |
168 | struct fmt::formatter<pg_info_t> { | |
169 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
170 | ||
171 | template <typename FormatContext> | |
172 | auto format(const pg_info_t& pgi, FormatContext& ctx) | |
173 | { | |
174 | fmt::format_to(ctx.out(), "{}({}", pgi.pgid, (pgi.dne() ? " DNE" : "")); | |
175 | if (pgi.is_empty()) { | |
176 | fmt::format_to(ctx.out(), " empty"); | |
177 | } else { | |
178 | fmt::format_to(ctx.out(), " v {}", pgi.last_update); | |
179 | if (pgi.last_complete != pgi.last_update) { | |
180 | fmt::format_to(ctx.out(), " lc {}", pgi.last_complete); | |
181 | } | |
182 | fmt::format_to(ctx.out(), " ({},{}]", pgi.log_tail, pgi.last_update); | |
183 | } | |
184 | if (pgi.is_incomplete()) { | |
185 | fmt::format_to(ctx.out(), " lb {}", pgi.last_backfill); | |
186 | } | |
187 | fmt::format_to(ctx.out(), | |
188 | " local-lis/les={}/{}", | |
189 | pgi.last_interval_started, | |
190 | pgi.last_epoch_started); | |
191 | return fmt::format_to(ctx.out(), | |
192 | " n={} {})", | |
193 | pgi.stats.stats.sum.num_objects, | |
194 | pgi.history); | |
195 | } | |
196 | }; | |
197 | ||
198 | // snaps and snap-sets | |
199 | ||
200 | template <> | |
201 | struct fmt::formatter<SnapSet> { | |
202 | template <typename ParseContext> | |
203 | constexpr auto parse(ParseContext& ctx) | |
204 | { | |
205 | auto it = ctx.begin(); | |
206 | if (it != ctx.end() && *it == 'D') { | |
207 | verbose = true; | |
208 | ++it; | |
209 | } | |
210 | return it; | |
211 | } | |
212 | ||
213 | template <typename FormatContext> | |
214 | auto format(const SnapSet& snps, FormatContext& ctx) | |
215 | { | |
216 | if (verbose) { | |
217 | // similar to SnapSet::dump() | |
218 | fmt::format_to(ctx.out(), | |
219 | "snaps{{{}: clns ({}): ", | |
220 | snps.seq, | |
221 | snps.clones.size()); | |
222 | for (auto cln : snps.clones) { | |
223 | ||
224 | fmt::format_to(ctx.out(), "[{}: sz:", cln); | |
225 | ||
226 | auto cs = snps.clone_size.find(cln); | |
227 | if (cs != snps.clone_size.end()) { | |
228 | fmt::format_to(ctx.out(), "{} ", cs->second); | |
229 | } else { | |
230 | fmt::format_to(ctx.out(), "??"); | |
231 | } | |
232 | ||
233 | auto co = snps.clone_overlap.find(cln); | |
234 | if (co != snps.clone_overlap.end()) { | |
235 | fmt::format_to(ctx.out(), "olp:{} ", co->second); | |
236 | } else { | |
237 | fmt::format_to(ctx.out(), "olp:?? "); | |
238 | } | |
239 | ||
240 | auto cln_snps = snps.clone_snaps.find(cln); | |
241 | if (cln_snps != snps.clone_snaps.end()) { | |
242 | fmt::format_to(ctx.out(), "cl-snps:{} ]", cln_snps->second); | |
243 | } else { | |
244 | fmt::format_to(ctx.out(), "cl-snps:?? ]"); | |
245 | } | |
246 | } | |
247 | ||
248 | return fmt::format_to(ctx.out(), "}}"); | |
249 | ||
250 | } else { | |
251 | return fmt::format_to(ctx.out(), | |
252 | "{}={}:{}", | |
253 | snps.seq, | |
254 | snps.snaps, | |
255 | snps.clone_snaps); | |
256 | } | |
257 | } | |
258 | ||
259 | bool verbose{false}; | |
260 | }; | |
261 | ||
262 | template <> | |
263 | struct fmt::formatter<ScrubMap::object> { | |
264 | constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } | |
265 | ||
266 | ///\todo: consider passing the 'D" flag to control snapset dump | |
267 | template <typename FormatContext> | |
268 | auto format(const ScrubMap::object& so, FormatContext& ctx) | |
269 | { | |
270 | fmt::format_to(ctx.out(), | |
271 | "so{{ sz:{} dd:{} od:{} ", | |
272 | so.size, | |
273 | so.digest, | |
274 | so.digest_present); | |
275 | ||
276 | // note the special handling of (1) OI_ATTR and (2) non-printables | |
277 | for (auto [k, v] : so.attrs) { | |
278 | std::string bkstr{v.raw_c_str(), v.raw_length()}; | |
279 | if (k == std::string{OI_ATTR}) { | |
280 | /// \todo consider parsing the OI args here. Maybe add a specific format | |
281 | /// specifier | |
282 | fmt::format_to(ctx.out(), "{{{}:<<OI_ATTR>>({})}} ", k, bkstr.length()); | |
283 | } else if (k == std::string{SS_ATTR}) { | |
284 | bufferlist bl; | |
285 | bl.push_back(v); | |
286 | SnapSet sns{bl}; | |
287 | fmt::format_to(ctx.out(), "{{{}:{:D}}} ", k, sns); | |
288 | } else { | |
289 | fmt::format_to(ctx.out(), "{{{}:{}({})}} ", k, bkstr, bkstr.length()); | |
290 | } | |
291 | } | |
292 | ||
293 | return fmt::format_to(ctx.out(), "}}"); | |
294 | } | |
295 | }; | |
296 | ||
297 | template <> | |
298 | struct fmt::formatter<ScrubMap> { | |
299 | template <typename ParseContext> | |
300 | constexpr auto parse(ParseContext& ctx) | |
301 | { | |
302 | auto it = ctx.begin(); | |
303 | if (it != ctx.end() && *it == 'D') { | |
304 | debug_log = true; // list the objects | |
305 | ++it; | |
306 | } | |
307 | return it; | |
308 | } | |
309 | ||
310 | template <typename FormatContext> | |
311 | auto format(const ScrubMap& smap, FormatContext& ctx) | |
312 | { | |
313 | fmt::format_to(ctx.out(), | |
314 | "smap{{ valid:{} incr-since:{} #:{}", | |
315 | smap.valid_through, | |
316 | smap.incr_since, | |
317 | smap.objects.size()); | |
318 | if (debug_log) { | |
319 | fmt::format_to(ctx.out(), " objects:"); | |
320 | for (const auto& [ho, so] : smap.objects) { | |
321 | fmt::format_to(ctx.out(), "\n\th.o<{}>:<{}> ", ho, so); | |
322 | } | |
323 | fmt::format_to(ctx.out(), "\n"); | |
324 | } | |
325 | return fmt::format_to(ctx.out(), "}}"); | |
326 | } | |
327 | ||
328 | bool debug_log{false}; | |
329 | }; | |
330 | ||
331 | #if FMT_VERSION >= 90000 | |
332 | template <> struct fmt::formatter<ObjectRecoveryInfo> : fmt::ostream_formatter {}; | |
333 | template <> struct fmt::formatter<ObjectRecoveryProgress> : fmt::ostream_formatter {}; | |
334 | template <> struct fmt::formatter<PastIntervals> : fmt::ostream_formatter {}; | |
335 | template <> struct fmt::formatter<pg_log_op_return_item_t> : fmt::ostream_formatter {}; | |
336 | template <> struct fmt::formatter<watch_info_t> : fmt::ostream_formatter {}; | |
337 | template <> struct fmt::formatter<pg_log_entry_t> : fmt::ostream_formatter {}; | |
338 | template <bool TrackChanges> struct fmt::formatter<pg_missing_set<TrackChanges>> : fmt::ostream_formatter {}; | |
339 | #endif |