]> git.proxmox.com Git - ceph.git/blob - ceph/src/include/types.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / include / types.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14 #ifndef CEPH_TYPES_H
15 #define CEPH_TYPES_H
16
17 // this is needed for ceph_fs to compile in userland
18 #include "int_types.h"
19 #include "byteorder.h"
20
21 #include "uuid.h"
22
23 #include <netinet/in.h>
24 #include <fcntl.h>
25 #include <string.h>
26
27 #include "ceph_fs.h"
28 #include "ceph_frag.h"
29 #include "rbd_types.h"
30
31 #ifdef __cplusplus
32 #ifndef _BACKWARD_BACKWARD_WARNING_H
33 #define _BACKWARD_BACKWARD_WARNING_H // make gcc 4.3 shut up about hash_*
34 #endif
35 #endif
36
37 extern "C" {
38 #include <stdint.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include "statlite.h"
42 }
43
44 #include <string>
45 #include <list>
46 #include <set>
47 #include <boost/container/flat_set.hpp>
48 #include <boost/container/flat_map.hpp>
49 #include <map>
50 #include <vector>
51 #include <optional>
52 #include <ostream>
53 #include <iomanip>
54
55
56 #include "include/unordered_map.h"
57
58 #include "object.h"
59 #include "intarith.h"
60
61 #include "acconfig.h"
62
63 #include "assert.h"
64
65 // DARWIN compatibility
66 #ifdef __APPLE__
67 typedef long long loff_t;
68 typedef long long off64_t;
69 #define O_DIRECT 00040000
70 #endif
71
72 // FreeBSD compatibility
73 #ifdef __FreeBSD__
74 typedef off_t loff_t;
75 typedef off_t off64_t;
76 #endif
77
78 #if defined(__sun) || defined(_AIX)
79 typedef off_t loff_t;
80 #endif
81
82
83 // -- io helpers --
84
85 // Forward declare all the I/O helpers so strict ADL can find them in
86 // the case of containers of containers. I'm tempted to abstract this
87 // stuff using template templates like I did for denc.
88
89 namespace std {
90 template<class A, class B>
91 inline std::ostream& operator<<(std::ostream&out, const std::pair<A,B>& v);
92 template<class A, class Alloc>
93 inline std::ostream& operator<<(std::ostream& out, const std::vector<A,Alloc>& v);
94 template<class A, std::size_t N, class Alloc>
95 inline std::ostream& operator<<(std::ostream& out, const boost::container::small_vector<A,N,Alloc>& v);
96 template<class A, class Comp, class Alloc>
97 inline std::ostream& operator<<(std::ostream& out, const std::deque<A,Alloc>& v);
98 template<typename... Ts>
99 inline std::ostream& operator<<(std::ostream& out, const std::tuple<Ts...> &t);
100 template<typename T>
101 inline std::ostream& operator<<(std::ostream& out, const std::optional<T> &t);
102 template<class A, class Alloc>
103 inline std::ostream& operator<<(std::ostream& out, const std::list<A,Alloc>& ilist);
104 template<class A, class Comp, class Alloc>
105 inline std::ostream& operator<<(std::ostream& out, const std::set<A, Comp, Alloc>& iset);
106 template<class A, class Comp, class Alloc>
107 inline std::ostream& operator<<(std::ostream& out, const std::multiset<A,Comp,Alloc>& iset);
108 template<class A, class B, class Comp, class Alloc>
109 inline std::ostream& operator<<(std::ostream& out, const std::map<A,B,Comp,Alloc>& m);
110 template<class A, class B, class Comp, class Alloc>
111 inline std::ostream& operator<<(std::ostream& out, const std::multimap<A,B,Comp,Alloc>& m);
112 }
113
114 namespace boost {
115 template<typename... Ts>
116 inline std::ostream& operator<<(std::ostream& out, const boost::tuple<Ts...> &t);
117
118 namespace container {
119 template<class A, class Comp, class Alloc>
120 inline std::ostream& operator<<(std::ostream& out, const boost::container::flat_set<A, Comp, Alloc>& iset);
121 template<class A, class B, class Comp, class Alloc>
122 inline std::ostream& operator<<(std::ostream& out, const boost::container::flat_map<A, B, Comp, Alloc>& iset);
123 }
124 }
125
126 namespace std {
127 template<class A, class B>
128 inline std::ostream& operator<<(std::ostream& out, const std::pair<A,B>& v) {
129 return out << v.first << "," << v.second;
130 }
131
132 template<class A, class Alloc>
133 inline std::ostream& operator<<(std::ostream& out, const std::vector<A,Alloc>& v) {
134 bool first = true;
135 out << "[";
136 for (const auto& p : v) {
137 if (!first) out << ",";
138 out << p;
139 first = false;
140 }
141 out << "]";
142 return out;
143 }
144
145 template<class A, std::size_t N, class Alloc>
146 inline std::ostream& operator<<(std::ostream& out, const boost::container::small_vector<A,N,Alloc>& v) {
147 bool first = true;
148 out << "[";
149 for (const auto& p : v) {
150 if (!first) out << ",";
151 out << p;
152 first = false;
153 }
154 out << "]";
155 return out;
156 }
157
158 template<class A, class Alloc>
159 inline std::ostream& operator<<(std::ostream& out, const std::deque<A,Alloc>& v) {
160 out << "<";
161 for (auto p = v.begin(); p != v.end(); ++p) {
162 if (p != v.begin()) out << ",";
163 out << *p;
164 }
165 out << ">";
166 return out;
167 }
168
169 template<typename... Ts>
170 inline std::ostream& operator<<(std::ostream& out, const std::tuple<Ts...> &t) {
171 auto f = [n = sizeof...(Ts), i = 0U, &out](const auto& e) mutable {
172 out << e;
173 if (++i != n)
174 out << ",";
175 };
176 ceph::for_each(t, f);
177 return out;
178 }
179
180 // Mimics boost::optional
181 template<typename T>
182 inline std::ostream& operator<<(std::ostream& out, const std::optional<T> &t) {
183 if (!t)
184 out << "--" ;
185 else
186 out << ' ' << *t ;
187 return out;
188 }
189
190 template<class A, class Alloc>
191 inline std::ostream& operator<<(std::ostream& out, const std::list<A,Alloc>& ilist) {
192 for (auto it = ilist.begin();
193 it != ilist.end();
194 ++it) {
195 if (it != ilist.begin()) out << ",";
196 out << *it;
197 }
198 return out;
199 }
200
201 template<class A, class Comp, class Alloc>
202 inline std::ostream& operator<<(std::ostream& out, const std::set<A, Comp, Alloc>& iset) {
203 for (auto it = iset.begin();
204 it != iset.end();
205 ++it) {
206 if (it != iset.begin()) out << ",";
207 out << *it;
208 }
209 return out;
210 }
211
212 template<class A, class Comp, class Alloc>
213 inline std::ostream& operator<<(std::ostream& out, const std::multiset<A,Comp,Alloc>& iset) {
214 for (auto it = iset.begin();
215 it != iset.end();
216 ++it) {
217 if (it != iset.begin()) out << ",";
218 out << *it;
219 }
220 return out;
221 }
222
223 template<class A, class B, class Comp, class Alloc>
224 inline std::ostream& operator<<(std::ostream& out, const std::map<A,B,Comp,Alloc>& m)
225 {
226 out << "{";
227 for (auto it = m.begin();
228 it != m.end();
229 ++it) {
230 if (it != m.begin()) out << ",";
231 out << it->first << "=" << it->second;
232 }
233 out << "}";
234 return out;
235 }
236
237 template<class A, class B, class Comp, class Alloc>
238 inline std::ostream& operator<<(std::ostream& out, const std::multimap<A,B,Comp,Alloc>& m)
239 {
240 out << "{{";
241 for (auto it = m.begin();
242 it != m.end();
243 ++it) {
244 if (it != m.begin()) out << ",";
245 out << it->first << "=" << it->second;
246 }
247 out << "}}";
248 return out;
249 }
250
251 } // namespace std
252
253 namespace boost {
254 namespace tuples {
255 template<typename A, typename B, typename C>
256 inline std::ostream& operator<<(std::ostream& out, const boost::tuples::tuple<A, B, C> &t) {
257 return out << boost::get<0>(t) << ","
258 << boost::get<1>(t) << ","
259 << boost::get<2>(t);
260 }
261 }
262 namespace container {
263 template<class A, class Comp, class Alloc>
264 inline std::ostream& operator<<(std::ostream& out, const boost::container::flat_set<A, Comp, Alloc>& iset) {
265 for (auto it = iset.begin();
266 it != iset.end();
267 ++it) {
268 if (it != iset.begin()) out << ",";
269 out << *it;
270 }
271 return out;
272 }
273
274 template<class A, class B, class Comp, class Alloc>
275 inline std::ostream& operator<<(std::ostream& out, const boost::container::flat_map<A, B, Comp, Alloc>& m) {
276 for (auto it = m.begin();
277 it != m.end();
278 ++it) {
279 if (it != m.begin()) out << ",";
280 out << it->first << "=" << it->second;
281 }
282 return out;
283 }
284 }
285 } // namespace boost
286
287
288
289 /*
290 * comparators for stl containers
291 */
292 // for ceph::unordered_map:
293 // ceph::unordered_map<const char*, long, hash<const char*>, eqstr> vals;
294 struct eqstr
295 {
296 bool operator()(const char* s1, const char* s2) const
297 {
298 return strcmp(s1, s2) == 0;
299 }
300 };
301
302 // for set, map
303 struct ltstr
304 {
305 bool operator()(const char* s1, const char* s2) const
306 {
307 return strcmp(s1, s2) < 0;
308 }
309 };
310
311
312 namespace ceph {
313 class Formatter;
314 }
315
316 #include "encoding.h"
317
318 WRITE_RAW_ENCODER(ceph_fsid)
319 WRITE_RAW_ENCODER(ceph_file_layout)
320 WRITE_RAW_ENCODER(ceph_dir_layout)
321 WRITE_RAW_ENCODER(ceph_mds_session_head)
322 WRITE_RAW_ENCODER(ceph_mds_request_head_legacy)
323 WRITE_RAW_ENCODER(ceph_mds_request_release)
324 WRITE_RAW_ENCODER(ceph_filelock)
325 WRITE_RAW_ENCODER(ceph_mds_caps_head)
326 WRITE_RAW_ENCODER(ceph_mds_caps_export_body)
327 WRITE_RAW_ENCODER(ceph_mds_caps_non_export_body)
328 WRITE_RAW_ENCODER(ceph_mds_cap_peer)
329 WRITE_RAW_ENCODER(ceph_mds_cap_release)
330 WRITE_RAW_ENCODER(ceph_mds_cap_item)
331 WRITE_RAW_ENCODER(ceph_mds_lease)
332 WRITE_RAW_ENCODER(ceph_mds_snap_head)
333 WRITE_RAW_ENCODER(ceph_mds_snap_realm)
334 WRITE_RAW_ENCODER(ceph_mds_reply_head)
335 WRITE_RAW_ENCODER(ceph_mds_reply_cap)
336 WRITE_RAW_ENCODER(ceph_mds_cap_reconnect)
337 WRITE_RAW_ENCODER(ceph_mds_snaprealm_reconnect)
338 WRITE_RAW_ENCODER(ceph_frag_tree_split)
339 WRITE_RAW_ENCODER(ceph_osd_reply_head)
340 WRITE_RAW_ENCODER(ceph_osd_op)
341 WRITE_RAW_ENCODER(ceph_msg_header)
342 WRITE_RAW_ENCODER(ceph_msg_footer)
343 WRITE_RAW_ENCODER(ceph_msg_footer_old)
344 WRITE_RAW_ENCODER(ceph_mon_subscribe_item)
345
346 WRITE_RAW_ENCODER(ceph_mon_statfs)
347 WRITE_RAW_ENCODER(ceph_mon_statfs_reply)
348
349 // ----------------------
350 // some basic types
351
352 // NOTE: these must match ceph_fs.h typedefs
353 typedef uint64_t ceph_tid_t; // transaction id
354 typedef uint64_t version_t;
355 typedef __u32 epoch_t; // map epoch (32bits -> 13 epochs/second for 10 years)
356
357 // --------------------------------------
358 // identify individual mount clients by 64bit value
359
360 struct client_t {
361 int64_t v;
362
363 // cppcheck-suppress noExplicitConstructor
364 client_t(int64_t _v = -2) : v(_v) {}
365
366 void encode(ceph::buffer::list& bl) const {
367 using ceph::encode;
368 encode(v, bl);
369 }
370 void decode(ceph::buffer::list::const_iterator& bl) {
371 using ceph::decode;
372 decode(v, bl);
373 }
374 };
375 WRITE_CLASS_ENCODER(client_t)
376
377 static inline bool operator==(const client_t& l, const client_t& r) { return l.v == r.v; }
378 static inline bool operator!=(const client_t& l, const client_t& r) { return l.v != r.v; }
379 static inline bool operator<(const client_t& l, const client_t& r) { return l.v < r.v; }
380 static inline bool operator<=(const client_t& l, const client_t& r) { return l.v <= r.v; }
381 static inline bool operator>(const client_t& l, const client_t& r) { return l.v > r.v; }
382 static inline bool operator>=(const client_t& l, const client_t& r) { return l.v >= r.v; }
383
384 static inline bool operator>=(const client_t& l, int64_t o) { return l.v >= o; }
385 static inline bool operator<(const client_t& l, int64_t o) { return l.v < o; }
386
387 inline std::ostream& operator<<(std::ostream& out, const client_t& c) {
388 return out << c.v;
389 }
390
391
392
393 // --
394
395 namespace {
396 inline std::ostream& format_u(std::ostream& out, const uint64_t v, const uint64_t n,
397 const int index, const uint64_t mult, const char* u)
398 {
399 char buffer[32];
400
401 if (index == 0) {
402 (void) snprintf(buffer, sizeof(buffer), "%" PRId64 "%s", n, u);
403 } else if ((v % mult) == 0) {
404 // If this is an even multiple of the base, always display
405 // without any decimal fraction.
406 (void) snprintf(buffer, sizeof(buffer), "%" PRId64 "%s", n, u);
407 } else {
408 // We want to choose a precision that reflects the best choice
409 // for fitting in 5 characters. This can get rather tricky when
410 // we have numbers that are very close to an order of magnitude.
411 // For example, when displaying 10239 (which is really 9.999K),
412 // we want only a single place of precision for 10.0K. We could
413 // develop some complex heuristics for this, but it's much
414 // easier just to try each combination in turn.
415 int i;
416 for (i = 2; i >= 0; i--) {
417 if (snprintf(buffer, sizeof(buffer), "%.*f%s", i,
418 static_cast<double>(v) / mult, u) <= 7)
419 break;
420 }
421 }
422
423 return out << buffer;
424 }
425 }
426
427 /*
428 * Use this struct to pretty print values that should be formatted with a
429 * decimal unit prefix (the classic SI units). No actual unit will be added.
430 */
431 struct si_u_t {
432 uint64_t v;
433 explicit si_u_t(uint64_t _v) : v(_v) {};
434 };
435
436 inline std::ostream& operator<<(std::ostream& out, const si_u_t& b)
437 {
438 uint64_t n = b.v;
439 int index = 0;
440 uint64_t mult = 1;
441 const char* u[] = {"", "k", "M", "G", "T", "P", "E"};
442
443 while (n >= 1000 && index < 7) {
444 n /= 1000;
445 index++;
446 mult *= 1000;
447 }
448
449 return format_u(out, b.v, n, index, mult, u[index]);
450 }
451
452 /*
453 * Use this struct to pretty print values that should be formatted with a
454 * binary unit prefix (IEC units). Since binary unit prefixes are to be used for
455 * "multiples of units in data processing, data transmission, and digital
456 * information" (so bits and bytes) and so far bits are not printed, the unit
457 * "B" for "byte" is added besides the multiplier.
458 */
459 struct byte_u_t {
460 uint64_t v;
461 explicit byte_u_t(uint64_t _v) : v(_v) {};
462 };
463
464 inline std::ostream& operator<<(std::ostream& out, const byte_u_t& b)
465 {
466 uint64_t n = b.v;
467 int index = 0;
468 const char* u[] = {" B", " KiB", " MiB", " GiB", " TiB", " PiB", " EiB"};
469
470 while (n >= 1024 && index < 7) {
471 n /= 1024;
472 index++;
473 }
474
475 return format_u(out, b.v, n, index, 1ULL << (10 * index), u[index]);
476 }
477
478 inline std::ostream& operator<<(std::ostream& out, const ceph_mon_subscribe_item& i)
479 {
480 return out << (long)i.start
481 << ((i.flags & CEPH_SUBSCRIBE_ONETIME) ? "" : "+");
482 }
483
484 struct weightf_t {
485 float v;
486 // cppcheck-suppress noExplicitConstructor
487 weightf_t(float _v) : v(_v) {}
488 };
489
490 inline std::ostream& operator<<(std::ostream& out, const weightf_t& w)
491 {
492 if (w.v < -0.01F) {
493 return out << "-";
494 } else if (w.v < 0.000001F) {
495 return out << "0";
496 } else {
497 std::streamsize p = out.precision();
498 return out << std::fixed << std::setprecision(5) << w.v << std::setprecision(p);
499 }
500 }
501
502 struct shard_id_t {
503 int8_t id;
504
505 shard_id_t() : id(0) {}
506 explicit shard_id_t(int8_t _id) : id(_id) {}
507
508 operator int8_t() const { return id; }
509
510 const static shard_id_t NO_SHARD;
511
512 void encode(ceph::buffer::list &bl) const {
513 using ceph::encode;
514 encode(id, bl);
515 }
516 void decode(ceph::buffer::list::const_iterator &bl) {
517 using ceph::decode;
518 decode(id, bl);
519 }
520
521 bool operator==(const shard_id_t&) const = default;
522 auto operator<=>(const shard_id_t&) const = default;
523 };
524 WRITE_CLASS_ENCODER(shard_id_t)
525 std::ostream &operator<<(std::ostream &lhs, const shard_id_t &rhs);
526
527 #if defined(__sun) || defined(_AIX) || defined(__APPLE__) || \
528 defined(__FreeBSD__) || defined(_WIN32)
529 extern "C" {
530 __s32 ceph_to_hostos_errno(__s32 e);
531 __s32 hostos_to_ceph_errno(__s32 e);
532 }
533 #else
534 #define ceph_to_hostos_errno(e) (e)
535 #define hostos_to_ceph_errno(e) (e)
536 #endif
537
538 struct errorcode32_t {
539 int32_t code;
540
541 errorcode32_t() : code(0) {}
542 // cppcheck-suppress noExplicitConstructor
543 explicit errorcode32_t(int32_t i) : code(i) {}
544
545 operator int() const { return code; }
546 int* operator&() { return &code; }
547 errorcode32_t& operator=(int32_t i) {
548 code = i;
549 return *this;
550 }
551 bool operator==(const errorcode32_t&) const = default;
552 auto operator<=>(const errorcode32_t&) const = default;
553
554 void encode(ceph::buffer::list &bl) const {
555 using ceph::encode;
556 __s32 newcode = hostos_to_ceph_errno(code);
557 encode(newcode, bl);
558 }
559 void decode(ceph::buffer::list::const_iterator &bl) {
560 using ceph::decode;
561 decode(code, bl);
562 code = ceph_to_hostos_errno(code);
563 }
564 };
565 WRITE_CLASS_ENCODER(errorcode32_t)
566
567 template <uint8_t S>
568 struct sha_digest_t {
569 constexpr static uint32_t SIZE = S;
570 // TODO: we might consider std::array in the future. Avoiding it for now
571 // as sha_digest_t is a part of our public API.
572 unsigned char v[S] = {0};
573
574 std::string to_str() const {
575 char str[S * 2 + 1] = {0};
576 str[0] = '\0';
577 for (size_t i = 0; i < S; i++) {
578 ::sprintf(&str[i * 2], "%02x", static_cast<int>(v[i]));
579 }
580 return std::string(str);
581 }
582 sha_digest_t(const unsigned char *_v) { memcpy(v, _v, SIZE); };
583 sha_digest_t() {}
584
585 bool operator==(const sha_digest_t& r) const {
586 return ::memcmp(v, r.v, SIZE) == 0;
587 }
588 bool operator!=(const sha_digest_t& r) const {
589 return ::memcmp(v, r.v, SIZE) != 0;
590 }
591
592 void encode(ceph::buffer::list &bl) const {
593 // copy to avoid reinterpret_cast, is_pod and other nasty things
594 using ceph::encode;
595 std::array<unsigned char, SIZE> tmparr;
596 memcpy(tmparr.data(), v, SIZE);
597 encode(tmparr, bl);
598 }
599 void decode(ceph::buffer::list::const_iterator &bl) {
600 using ceph::decode;
601 std::array<unsigned char, SIZE> tmparr;
602 decode(tmparr, bl);
603 memcpy(v, tmparr.data(), SIZE);
604 }
605 };
606
607 template<uint8_t S>
608 inline std::ostream &operator<<(std::ostream &out, const sha_digest_t<S> &b) {
609 std::string str = b.to_str();
610 return out << str;
611 }
612
613 #if FMT_VERSION >= 90000
614 template <uint8_t S> struct fmt::formatter<sha_digest_t<S>> : fmt::ostream_formatter {};
615 #endif
616
617 using sha1_digest_t = sha_digest_t<20>;
618 WRITE_CLASS_ENCODER(sha1_digest_t)
619
620 using sha256_digest_t = sha_digest_t<32>;
621 WRITE_CLASS_ENCODER(sha256_digest_t)
622
623 using sha512_digest_t = sha_digest_t<64>;
624
625 using md5_digest_t = sha_digest_t<16>;
626 WRITE_CLASS_ENCODER(md5_digest_t)
627
628
629 #endif