]> git.proxmox.com Git - ceph.git/blob - ceph/src/msg/msg_types.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / msg / msg_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
15 #ifndef CEPH_MSG_TYPES_H
16 #define CEPH_MSG_TYPES_H
17
18 #include <sstream>
19
20 #include <netinet/in.h>
21 #include <fmt/format.h>
22 #if FMT_VERSION >= 90000
23 #include <fmt/ostream.h>
24 #endif
25
26 #include "include/ceph_features.h"
27 #include "include/types.h"
28 #include "include/blobhash.h"
29 #include "include/encoding.h"
30
31 #define MAX_PORT_NUMBER 65535
32
33 #ifdef _WIN32
34 // ceph_sockaddr_storage matches the Linux format.
35 #define AF_INET6_LINUX 10
36 #endif
37
38 namespace ceph {
39 class Formatter;
40 }
41
42 std::ostream& operator<<(std::ostream& out, const sockaddr_storage &ss);
43 std::ostream& operator<<(std::ostream& out, const sockaddr *sa);
44
45 typedef uint8_t entity_type_t;
46
47 class entity_name_t {
48 public:
49 entity_type_t _type;
50 int64_t _num;
51
52 public:
53 static const int TYPE_MON = CEPH_ENTITY_TYPE_MON;
54 static const int TYPE_MDS = CEPH_ENTITY_TYPE_MDS;
55 static const int TYPE_OSD = CEPH_ENTITY_TYPE_OSD;
56 static const int TYPE_CLIENT = CEPH_ENTITY_TYPE_CLIENT;
57 static const int TYPE_MGR = CEPH_ENTITY_TYPE_MGR;
58
59 static const int64_t NEW = -1;
60
61 // cons
62 entity_name_t() : _type(0), _num(0) { }
63 entity_name_t(int t, int64_t n) : _type(t), _num(n) { }
64 explicit entity_name_t(const ceph_entity_name &n) :
65 _type(n.type), _num(n.num) { }
66
67 // static cons
68 static entity_name_t MON(int64_t i=NEW) { return entity_name_t(TYPE_MON, i); }
69 static entity_name_t MDS(int64_t i=NEW) { return entity_name_t(TYPE_MDS, i); }
70 static entity_name_t OSD(int64_t i=NEW) { return entity_name_t(TYPE_OSD, i); }
71 static entity_name_t CLIENT(int64_t i=NEW) { return entity_name_t(TYPE_CLIENT, i); }
72 static entity_name_t MGR(int64_t i=NEW) { return entity_name_t(TYPE_MGR, i); }
73
74 int64_t num() const { return _num; }
75 int type() const { return _type; }
76 const char *type_str() const {
77 return ceph_entity_type_name(type());
78 }
79
80 bool is_new() const { return num() < 0; }
81
82 bool is_client() const { return type() == TYPE_CLIENT; }
83 bool is_mds() const { return type() == TYPE_MDS; }
84 bool is_osd() const { return type() == TYPE_OSD; }
85 bool is_mon() const { return type() == TYPE_MON; }
86 bool is_mgr() const { return type() == TYPE_MGR; }
87
88 operator ceph_entity_name() const {
89 ceph_entity_name n = { _type, ceph_le64(_num) };
90 return n;
91 }
92
93 bool parse(std::string_view s);
94
95 DENC(entity_name_t, v, p) {
96 denc(v._type, p);
97 denc(v._num, p);
98 }
99 void dump(ceph::Formatter *f) const;
100
101 static void generate_test_instances(std::list<entity_name_t*>& o);
102 };
103 WRITE_CLASS_DENC(entity_name_t)
104
105 inline bool operator== (const entity_name_t& l, const entity_name_t& r) {
106 return (l.type() == r.type()) && (l.num() == r.num()); }
107 inline bool operator!= (const entity_name_t& l, const entity_name_t& r) {
108 return (l.type() != r.type()) || (l.num() != r.num()); }
109 inline bool operator< (const entity_name_t& l, const entity_name_t& r) {
110 return (l.type() < r.type()) || (l.type() == r.type() && l.num() < r.num()); }
111
112 inline std::ostream& operator<<(std::ostream& out, const entity_name_t& addr) {
113 //if (addr.is_namer()) return out << "namer";
114 if (addr.is_new() || addr.num() < 0)
115 return out << addr.type_str() << ".?";
116 else
117 return out << addr.type_str() << '.' << addr.num();
118 }
119 inline std::ostream& operator<<(std::ostream& out, const ceph_entity_name& addr) {
120 return out << entity_name_t{addr.type, static_cast<int64_t>(addr.num)};
121 }
122
123 namespace std {
124 template<> struct hash< entity_name_t >
125 {
126 size_t operator()( const entity_name_t &m ) const
127 {
128 return rjhash32(m.type() ^ m.num());
129 }
130 };
131 } // namespace std
132
133 // define a wire format for sockaddr that matches Linux's.
134 struct ceph_sockaddr_storage {
135 ceph_le16 ss_family;
136 __u8 __ss_padding[128 - sizeof(ceph_le16)];
137
138 void encode(ceph::buffer::list& bl) const {
139 struct ceph_sockaddr_storage ss = *this;
140 ss.ss_family = htons(ss.ss_family);
141 ceph::encode_raw(ss, bl);
142 }
143
144 void decode(ceph::buffer::list::const_iterator& bl) {
145 struct ceph_sockaddr_storage ss;
146 ceph::decode_raw(ss, bl);
147 ss.ss_family = ntohs(ss.ss_family);
148 *this = ss;
149 }
150 } __attribute__ ((__packed__));
151 WRITE_CLASS_ENCODER(ceph_sockaddr_storage)
152
153 /*
154 * encode sockaddr.ss_family as network byte order
155 */
156 static inline void encode(const sockaddr_storage& a, ceph::buffer::list& bl) {
157 #if defined(__linux__)
158 struct sockaddr_storage ss = a;
159 ss.ss_family = htons(ss.ss_family);
160 ceph::encode_raw(ss, bl);
161 #elif defined(__FreeBSD__) || defined(__APPLE__)
162 ceph_sockaddr_storage ss{};
163 auto src = (unsigned char const *)&a;
164 auto dst = (unsigned char *)&ss;
165 src += sizeof(a.ss_len);
166 ss.ss_family = a.ss_family;
167 src += sizeof(a.ss_family);
168 dst += sizeof(ss.ss_family);
169 const auto copy_size = std::min((unsigned char*)(&a + 1) - src,
170 (unsigned char*)(&ss + 1) - dst);
171 ::memcpy(dst, src, copy_size);
172 encode(ss, bl);
173 #elif defined(_WIN32)
174 ceph_sockaddr_storage ss{};
175 ::memcpy(&ss, &a, std::min(sizeof(ss), sizeof(a)));
176 // The Windows AF_INET6 definition doesn't match the Linux one.
177 if (a.ss_family == AF_INET6) {
178 ss.ss_family = AF_INET6_LINUX;
179 }
180 encode(ss, bl);
181 #else
182 ceph_sockaddr_storage ss;
183 ::memset(&ss, '\0', sizeof(ss));
184 ::memcpy(&ss, &a, std::min(sizeof(ss), sizeof(a)));
185 encode(ss, bl);
186 #endif
187 }
188 static inline void decode(sockaddr_storage& a,
189 ceph::buffer::list::const_iterator& bl) {
190 #if defined(__linux__)
191 ceph::decode_raw(a, bl);
192 a.ss_family = ntohs(a.ss_family);
193 #elif defined(__FreeBSD__) || defined(__APPLE__)
194 ceph_sockaddr_storage ss{};
195 decode(ss, bl);
196 auto src = (unsigned char const *)&ss;
197 auto dst = (unsigned char *)&a;
198 a.ss_len = 0;
199 dst += sizeof(a.ss_len);
200 a.ss_family = ss.ss_family;
201 src += sizeof(ss.ss_family);
202 dst += sizeof(a.ss_family);
203 auto const copy_size = std::min((unsigned char*)(&ss + 1) - src,
204 (unsigned char*)(&a + 1) - dst);
205 ::memcpy(dst, src, copy_size);
206 #elif defined(_WIN32)
207 ceph_sockaddr_storage ss{};
208 decode(ss, bl);
209 ::memcpy(&a, &ss, std::min(sizeof(ss), sizeof(a)));
210 if (a.ss_family == AF_INET6_LINUX) {
211 a.ss_family = AF_INET6;
212 }
213 #else
214 ceph_sockaddr_storage ss{};
215 decode(ss, bl);
216 ::memcpy(&a, &ss, std::min(sizeof(ss), sizeof(a)));
217 #endif
218 }
219
220 /*
221 * an entity's network address.
222 * includes a random value that prevents it from being reused.
223 * thus identifies a particular process instance.
224 *
225 * This also happens to work to support cidr ranges, in which
226 * case the nonce contains the netmask. It's great!
227 */
228 struct entity_addr_t {
229 typedef enum {
230 TYPE_NONE = 0,
231 TYPE_LEGACY = 1, ///< legacy msgr1 protocol (ceph jewel and older)
232 TYPE_MSGR2 = 2, ///< msgr2 protocol (new in ceph kraken)
233 TYPE_ANY = 3, ///< ambiguous
234 TYPE_CIDR = 4,
235 } type_t;
236 static const type_t TYPE_DEFAULT = TYPE_MSGR2;
237 static std::string_view get_type_name(int t) {
238 switch (t) {
239 case TYPE_NONE: return "none";
240 case TYPE_LEGACY: return "v1";
241 case TYPE_MSGR2: return "v2";
242 case TYPE_ANY: return "any";
243 case TYPE_CIDR: return "cidr";
244 default: return "???";
245 }
246 };
247
248 __u32 type;
249 __u32 nonce;
250 union {
251 sockaddr sa;
252 sockaddr_in sin;
253 sockaddr_in6 sin6;
254 } u;
255
256 entity_addr_t() : type(0), nonce(0) {
257 memset(&u, 0, sizeof(u));
258 }
259 entity_addr_t(__u32 _type, __u32 _nonce) : type(_type), nonce(_nonce) {
260 memset(&u, 0, sizeof(u));
261 }
262 explicit entity_addr_t(const ceph_entity_addr &o) {
263 type = o.type;
264 nonce = o.nonce;
265 memcpy(&u, &o.in_addr, sizeof(u));
266 #if !defined(__FreeBSD__)
267 u.sa.sa_family = ntohs(u.sa.sa_family);
268 #endif
269 }
270
271 uint32_t get_type() const { return type; }
272 void set_type(uint32_t t) { type = t; }
273 bool is_legacy() const { return type == TYPE_LEGACY; }
274 bool is_msgr2() const { return type == TYPE_MSGR2; }
275 bool is_any() const { return type == TYPE_ANY; }
276 // this isn't a guarantee; some client addrs will match it
277 bool maybe_cidr() const { return get_port() == 0 && nonce != 0; }
278
279 __u32 get_nonce() const { return nonce; }
280 void set_nonce(__u32 n) { nonce = n; }
281
282 int get_family() const {
283 return u.sa.sa_family;
284 }
285 void set_family(int f) {
286 u.sa.sa_family = f;
287 }
288
289 bool is_ipv4() const {
290 return u.sa.sa_family == AF_INET;
291 }
292 bool is_ipv6() const {
293 return u.sa.sa_family == AF_INET6;
294 }
295
296 sockaddr_in &in4_addr() {
297 return u.sin;
298 }
299 const sockaddr_in &in4_addr() const{
300 return u.sin;
301 }
302 sockaddr_in6 &in6_addr(){
303 return u.sin6;
304 }
305 const sockaddr_in6 &in6_addr() const{
306 return u.sin6;
307 }
308 const sockaddr *get_sockaddr() const {
309 return &u.sa;
310 }
311 size_t get_sockaddr_len() const {
312 switch (u.sa.sa_family) {
313 case AF_INET:
314 return sizeof(u.sin);
315 case AF_INET6:
316 return sizeof(u.sin6);
317 }
318 return sizeof(u);
319 }
320 bool set_sockaddr(const struct sockaddr *sa)
321 {
322 switch (sa->sa_family) {
323 case AF_INET:
324 // pre-zero, since we're only copying a portion of the source
325 memset(&u, 0, sizeof(u));
326 memcpy(&u.sin, sa, sizeof(u.sin));
327 break;
328 case AF_INET6:
329 // pre-zero, since we're only copying a portion of the source
330 memset(&u, 0, sizeof(u));
331 memcpy(&u.sin6, sa, sizeof(u.sin6));
332 break;
333 case AF_UNSPEC:
334 memset(&u, 0, sizeof(u));
335 break;
336 default:
337 return false;
338 }
339 return true;
340 }
341
342 sockaddr_storage get_sockaddr_storage() const {
343 sockaddr_storage ss;
344 memcpy(&ss, &u, sizeof(u));
345 memset((char*)&ss + sizeof(u), 0, sizeof(ss) - sizeof(u));
346 return ss;
347 }
348
349 void set_in4_quad(int pos, int val) {
350 u.sin.sin_family = AF_INET;
351 unsigned char *ipq = (unsigned char*)&u.sin.sin_addr.s_addr;
352 ipq[pos] = val;
353 }
354 void set_port(int port) {
355 switch (u.sa.sa_family) {
356 case AF_INET:
357 u.sin.sin_port = htons(port);
358 break;
359 case AF_INET6:
360 u.sin6.sin6_port = htons(port);
361 break;
362 default:
363 ceph_abort();
364 }
365 }
366 int get_port() const {
367 switch (u.sa.sa_family) {
368 case AF_INET:
369 return ntohs(u.sin.sin_port);
370 case AF_INET6:
371 return ntohs(u.sin6.sin6_port);
372 }
373 return 0;
374 }
375
376 operator ceph_entity_addr() const {
377 ceph_entity_addr a;
378 a.type = 0;
379 a.nonce = nonce;
380 a.in_addr = get_sockaddr_storage();
381 #if !defined(__FreeBSD__)
382 a.in_addr.ss_family = htons(a.in_addr.ss_family);
383 #endif
384 return a;
385 }
386
387 bool probably_equals(const entity_addr_t &o) const {
388 if (get_port() != o.get_port())
389 return false;
390 if (get_nonce() != o.get_nonce())
391 return false;
392 if (is_blank_ip() || o.is_blank_ip())
393 return true;
394 if (memcmp(&u, &o.u, sizeof(u)) == 0)
395 return true;
396 return false;
397 }
398
399 bool is_same_host(const entity_addr_t &o) const {
400 if (u.sa.sa_family != o.u.sa.sa_family)
401 return false;
402 if (u.sa.sa_family == AF_INET)
403 return u.sin.sin_addr.s_addr == o.u.sin.sin_addr.s_addr;
404 if (u.sa.sa_family == AF_INET6)
405 return memcmp(u.sin6.sin6_addr.s6_addr,
406 o.u.sin6.sin6_addr.s6_addr,
407 sizeof(u.sin6.sin6_addr.s6_addr)) == 0;
408 return false;
409 }
410
411 bool is_blank_ip() const {
412 switch (u.sa.sa_family) {
413 case AF_INET:
414 return u.sin.sin_addr.s_addr == INADDR_ANY;
415 case AF_INET6:
416 return memcmp(&u.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0;
417 default:
418 return true;
419 }
420 }
421
422 bool is_ip() const {
423 switch (u.sa.sa_family) {
424 case AF_INET:
425 case AF_INET6:
426 return true;
427 default:
428 return false;
429 }
430 }
431
432 std::string ip_only_to_str() const;
433 std::string ip_n_port_to_str() const;
434
435 std::string get_legacy_str() const {
436 std::ostringstream ss;
437 ss << get_sockaddr() << "/" << get_nonce();
438 return ss.str();
439 }
440
441 bool parse(const std::string_view s, int default_type=TYPE_DEFAULT);
442 bool parse(const char *s, const char **end = 0, int default_type=TYPE_DEFAULT);
443
444 void decode_legacy_addr_after_marker(ceph::buffer::list::const_iterator& bl)
445 {
446 using ceph::decode;
447 __u8 marker;
448 __u16 rest;
449 decode(marker, bl);
450 decode(rest, bl);
451 decode(nonce, bl);
452 sockaddr_storage ss;
453 decode(ss, bl);
454 set_sockaddr((sockaddr*)&ss);
455 if (get_family() == AF_UNSPEC) {
456 type = TYPE_NONE;
457 } else {
458 type = TYPE_LEGACY;
459 }
460 }
461
462 // Right now, these only deal with sockaddr_storage that have only family and content.
463 // Apparently on BSD there is also an ss_len that we need to handle; this requires
464 // broader study
465
466 void encode(ceph::buffer::list& bl, uint64_t features) const {
467 using ceph::encode;
468 if ((features & CEPH_FEATURE_MSG_ADDR2) == 0) {
469 encode((__u32)0, bl);
470 encode(nonce, bl);
471 sockaddr_storage ss = get_sockaddr_storage();
472 encode(ss, bl);
473 return;
474 }
475 encode((__u8)1, bl);
476 ENCODE_START(1, 1, bl);
477 if (HAVE_FEATURE(features, SERVER_NAUTILUS)) {
478 encode(type, bl);
479 } else {
480 // map any -> legacy for old clients. this is primary for the benefit
481 // of OSDMap's blocklist, but is reasonable in general since any: is
482 // meaningless for pre-nautilus clients or daemons.
483 auto t = type;
484 if (t == TYPE_ANY) {
485 t = TYPE_LEGACY;
486 }
487 encode(t, bl);
488 }
489 encode(nonce, bl);
490 __u32 elen = get_sockaddr_len();
491 #if (__FreeBSD__) || defined(__APPLE__)
492 elen -= sizeof(u.sa.sa_len);
493 #endif
494 encode(elen, bl);
495 if (elen) {
496 uint16_t ss_family = u.sa.sa_family;
497 #if defined(_WIN32)
498 if (ss_family == AF_INET6) {
499 ss_family = AF_INET6_LINUX;
500 }
501 #endif
502 encode(ss_family, bl);
503 elen -= sizeof(u.sa.sa_family);
504 bl.append(u.sa.sa_data, elen);
505 }
506 ENCODE_FINISH(bl);
507 }
508 void decode(ceph::buffer::list::const_iterator& bl) {
509 using ceph::decode;
510 __u8 marker;
511 decode(marker, bl);
512 if (marker == 0) {
513 decode_legacy_addr_after_marker(bl);
514 return;
515 }
516 if (marker != 1)
517 throw ceph::buffer::malformed_input("entity_addr_t marker != 1");
518 DECODE_START(1, bl);
519 decode(type, bl);
520 decode(nonce, bl);
521 __u32 elen;
522 decode(elen, bl);
523 if (elen) {
524 #if defined(__FreeBSD__) || defined(__APPLE__)
525 u.sa.sa_len = 0;
526 #endif
527 uint16_t ss_family;
528 if (elen < sizeof(ss_family)) {
529 throw ceph::buffer::malformed_input("elen smaller than family len");
530 }
531 decode(ss_family, bl);
532 #if defined(_WIN32)
533 if (ss_family == AF_INET6_LINUX) {
534 ss_family = AF_INET6;
535 }
536 #endif
537 u.sa.sa_family = ss_family;
538 elen -= sizeof(ss_family);
539 if (elen > get_sockaddr_len() - sizeof(u.sa.sa_family)) {
540 throw ceph::buffer::malformed_input("elen exceeds sockaddr len");
541 }
542 bl.copy(elen, u.sa.sa_data);
543 }
544 DECODE_FINISH(bl);
545 }
546
547 void dump(ceph::Formatter *f) const;
548
549 static void generate_test_instances(std::list<entity_addr_t*>& o);
550 };
551 WRITE_CLASS_ENCODER_FEATURES(entity_addr_t)
552
553 std::ostream& operator<<(std::ostream& out, const entity_addr_t &addr);
554 #if FMT_VERSION >= 90000
555 template <> struct fmt::formatter<entity_addr_t> : fmt::ostream_formatter {};
556 #endif
557
558 inline bool operator==(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) == 0; }
559 inline bool operator!=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) != 0; }
560 inline bool operator<(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) < 0; }
561 inline bool operator<=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) <= 0; }
562 inline bool operator>(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) > 0; }
563 inline bool operator>=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) >= 0; }
564
565 namespace std {
566 template<> struct hash<entity_addr_t> {
567 size_t operator()( const entity_addr_t& x ) const {
568 static blobhash H;
569 return H(&x, sizeof(x));
570 }
571 };
572 } // namespace std
573
574 struct entity_addrvec_t {
575 std::vector<entity_addr_t> v;
576
577 entity_addrvec_t() {}
578 explicit entity_addrvec_t(const entity_addr_t& a) : v({ a }) {}
579
580 unsigned size() const { return v.size(); }
581 bool empty() const { return v.empty(); }
582
583 entity_addr_t legacy_addr() const {
584 return addr_of_type(entity_addr_t::TYPE_LEGACY);
585 }
586 entity_addr_t as_legacy_addr() const {
587 for (auto& a : v) {
588 if (a.is_legacy()) {
589 return a;
590 }
591 if (a.is_any()) {
592 auto b = a;
593 b.set_type(entity_addr_t::TYPE_LEGACY);
594 return b;
595 }
596 }
597 // hrm... lie!
598 auto a = front();
599 a.set_type(entity_addr_t::TYPE_LEGACY);
600 return a;
601 }
602 entity_addr_t front() const {
603 if (!v.empty()) {
604 return v.front();
605 }
606 return entity_addr_t();
607 }
608 entity_addr_t legacy_or_front_addr() const {
609 for (auto& a : v) {
610 if (a.type == entity_addr_t::TYPE_LEGACY) {
611 return a;
612 }
613 }
614 return front();
615 }
616 std::string get_legacy_str() const {
617 return legacy_or_front_addr().get_legacy_str();
618 }
619
620 entity_addr_t msgr2_addr() const {
621 return addr_of_type(entity_addr_t::TYPE_MSGR2);
622 }
623 bool has_msgr2() const {
624 for (auto& a : v) {
625 if (a.is_msgr2()) {
626 return true;
627 }
628 }
629 return false;
630 }
631
632 entity_addr_t pick_addr(uint32_t type) const {
633 entity_addr_t picked_addr;
634 switch (type) {
635 case entity_addr_t::TYPE_LEGACY:
636 [[fallthrough]];
637 case entity_addr_t::TYPE_MSGR2:
638 picked_addr = addr_of_type(type);
639 break;
640 case entity_addr_t::TYPE_ANY:
641 return front();
642 default:
643 return {};
644 }
645 if (!picked_addr.is_blank_ip()) {
646 return picked_addr;
647 } else {
648 return addr_of_type(entity_addr_t::TYPE_ANY);
649 }
650 }
651
652 entity_addr_t addr_of_type(uint32_t type) const {
653 for (auto &a : v) {
654 if (a.type == type) {
655 return a;
656 }
657 }
658 return entity_addr_t();
659 }
660
661 bool parse(const char *s, const char **end = 0);
662
663 void get_ports(std::set<int> *ports) const {
664 for (auto& a : v) {
665 ports->insert(a.get_port());
666 }
667 }
668 std::set<int> get_ports() const {
669 std::set<int> r;
670 get_ports(&r);
671 return r;
672 }
673
674 void encode(ceph::buffer::list& bl, uint64_t features) const;
675 void decode(ceph::buffer::list::const_iterator& bl);
676 void dump(ceph::Formatter *f) const;
677 static void generate_test_instances(std::list<entity_addrvec_t*>& ls);
678
679 bool legacy_equals(const entity_addrvec_t& o) const {
680 if (v == o.v) {
681 return true;
682 }
683 if (v.size() == 1 &&
684 front().is_legacy() &&
685 front() == o.legacy_addr()) {
686 return true;
687 }
688 if (o.v.size() == 1 &&
689 o.front().is_legacy() &&
690 o.front() == legacy_addr()) {
691 return true;
692 }
693 return false;
694 }
695
696 bool probably_equals(const entity_addrvec_t& o) const {
697 for (unsigned i = 0; i < v.size(); ++i) {
698 if (!v[i].probably_equals(o.v[i])) {
699 return false;
700 }
701 }
702 return true;
703 }
704 bool contains(const entity_addr_t& a) const {
705 for (auto& i : v) {
706 if (a == i) {
707 return true;
708 }
709 }
710 return false;
711 }
712 bool is_same_host(const entity_addr_t& a) const {
713 for (auto& i : v) {
714 if (i.is_same_host(a)) {
715 return true;
716 }
717 }
718 return false;
719 }
720
721 friend std::ostream& operator<<(std::ostream& out, const entity_addrvec_t& av) {
722 if (av.v.empty()) {
723 return out;
724 } else if (av.v.size() == 1) {
725 return out << av.v[0];
726 } else {
727 return out << av.v;
728 }
729 }
730
731 friend bool operator==(const entity_addrvec_t& l, const entity_addrvec_t& r) {
732 return l.v == r.v;
733 }
734 friend bool operator!=(const entity_addrvec_t& l, const entity_addrvec_t& r) {
735 return l.v != r.v;
736 }
737 friend bool operator<(const entity_addrvec_t& l, const entity_addrvec_t& r) {
738 return l.v < r.v; // see lexicographical_compare()
739 }
740 friend bool operator>(const entity_addrvec_t& l, const entity_addrvec_t& r) {
741 return l.v > r.v; // see lexicographical_compare()
742 }
743 };
744 WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t);
745 #if FMT_VERSION >= 90000
746 template <> struct fmt::formatter<entity_addrvec_t> : fmt::ostream_formatter {};
747 #endif
748
749 namespace std {
750 template<> struct hash<entity_addrvec_t> {
751 size_t operator()( const entity_addrvec_t& x) const {
752 static blobhash H;
753 size_t r = 0;
754 for (auto& i : x.v) {
755 r += H((const char*)&i, sizeof(i));
756 }
757 return r;
758 }
759 };
760 } // namespace std
761
762 /*
763 * a particular entity instance
764 */
765 struct entity_inst_t {
766 entity_name_t name;
767 entity_addr_t addr;
768 entity_inst_t() {}
769 entity_inst_t(entity_name_t n, const entity_addr_t& a) : name(n), addr(a) {}
770 // cppcheck-suppress noExplicitConstructor
771 entity_inst_t(const ceph_entity_inst& i) : name(i.name), addr(i.addr) { }
772 entity_inst_t(const ceph_entity_name& n, const ceph_entity_addr &a) : name(n), addr(a) {}
773 operator ceph_entity_inst() {
774 ceph_entity_inst i = {name, addr};
775 return i;
776 }
777
778 void encode(ceph::buffer::list& bl, uint64_t features) const {
779 using ceph::encode;
780 encode(name, bl);
781 encode(addr, bl, features);
782 }
783 void decode(ceph::buffer::list::const_iterator& bl) {
784 using ceph::decode;
785 decode(name, bl);
786 decode(addr, bl);
787 }
788
789 void dump(ceph::Formatter *f) const;
790 static void generate_test_instances(std::list<entity_inst_t*>& o);
791 };
792 WRITE_CLASS_ENCODER_FEATURES(entity_inst_t)
793
794
795 inline bool operator==(const entity_inst_t& a, const entity_inst_t& b) {
796 return a.name == b.name && a.addr == b.addr;
797 }
798 inline bool operator!=(const entity_inst_t& a, const entity_inst_t& b) {
799 return a.name != b.name || a.addr != b.addr;
800 }
801 inline bool operator<(const entity_inst_t& a, const entity_inst_t& b) {
802 return a.name < b.name || (a.name == b.name && a.addr < b.addr);
803 }
804 inline bool operator<=(const entity_inst_t& a, const entity_inst_t& b) {
805 return a.name < b.name || (a.name == b.name && a.addr <= b.addr);
806 }
807 inline bool operator>(const entity_inst_t& a, const entity_inst_t& b) { return b < a; }
808 inline bool operator>=(const entity_inst_t& a, const entity_inst_t& b) { return b <= a; }
809
810 namespace std {
811 template<> struct hash< entity_inst_t >
812 {
813 size_t operator()( const entity_inst_t& x ) const
814 {
815 static hash< entity_name_t > H;
816 static hash< entity_addr_t > I;
817 return H(x.name) ^ I(x.addr);
818 }
819 };
820 } // namespace std
821
822
823 inline std::ostream& operator<<(std::ostream& out, const entity_inst_t &i)
824 {
825 return out << i.name << " " << i.addr;
826 }
827 inline std::ostream& operator<<(std::ostream& out, const ceph_entity_inst &i)
828 {
829 entity_inst_t n = i;
830 return out << n;
831 }
832
833 #endif