]> git.proxmox.com Git - ceph.git/blob - ceph/src/msg/msg_types.h
update sources to ceph Nautilus 14.2.1
[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
22 #include "include/ceph_features.h"
23 #include "include/types.h"
24 #include "include/blobhash.h"
25 #include "include/encoding.h"
26
27 #define MAX_PORT_NUMBER 65535
28
29 namespace ceph {
30 class Formatter;
31 }
32
33 extern ostream& operator<<(ostream& out, const sockaddr_storage &ss);
34 extern ostream& operator<<(ostream& out, const sockaddr *sa);
35
36 typedef uint8_t entity_type_t;
37
38 class entity_name_t {
39 public:
40 entity_type_t _type;
41 int64_t _num;
42
43 public:
44 static const int TYPE_MON = CEPH_ENTITY_TYPE_MON;
45 static const int TYPE_MDS = CEPH_ENTITY_TYPE_MDS;
46 static const int TYPE_OSD = CEPH_ENTITY_TYPE_OSD;
47 static const int TYPE_CLIENT = CEPH_ENTITY_TYPE_CLIENT;
48 static const int TYPE_MGR = CEPH_ENTITY_TYPE_MGR;
49
50 static const int64_t NEW = -1;
51
52 // cons
53 entity_name_t() : _type(0), _num(0) { }
54 entity_name_t(int t, int64_t n) : _type(t), _num(n) { }
55 explicit entity_name_t(const ceph_entity_name &n) :
56 _type(n.type), _num(n.num) { }
57
58 // static cons
59 static entity_name_t MON(int64_t i=NEW) { return entity_name_t(TYPE_MON, i); }
60 static entity_name_t MDS(int64_t i=NEW) { return entity_name_t(TYPE_MDS, i); }
61 static entity_name_t OSD(int64_t i=NEW) { return entity_name_t(TYPE_OSD, i); }
62 static entity_name_t CLIENT(int64_t i=NEW) { return entity_name_t(TYPE_CLIENT, i); }
63 static entity_name_t MGR(int64_t i=NEW) { return entity_name_t(TYPE_MGR, i); }
64
65 int64_t num() const { return _num; }
66 int type() const { return _type; }
67 const char *type_str() const {
68 return ceph_entity_type_name(type());
69 }
70
71 bool is_new() const { return num() < 0; }
72
73 bool is_client() const { return type() == TYPE_CLIENT; }
74 bool is_mds() const { return type() == TYPE_MDS; }
75 bool is_osd() const { return type() == TYPE_OSD; }
76 bool is_mon() const { return type() == TYPE_MON; }
77 bool is_mgr() const { return type() == TYPE_MGR; }
78
79 operator ceph_entity_name() const {
80 ceph_entity_name n = { _type, init_le64(_num) };
81 return n;
82 }
83
84 bool parse(const string& s) {
85 const char *start = s.c_str();
86 char *end;
87 bool got = parse(start, &end);
88 return got && end == start + s.length();
89 }
90 bool parse(const char *start, char **end) {
91 if (strstr(start, "mon.") == start) {
92 _type = TYPE_MON;
93 start += 4;
94 } else if (strstr(start, "osd.") == start) {
95 _type = TYPE_OSD;
96 start += 4;
97 } else if (strstr(start, "mds.") == start) {
98 _type = TYPE_MDS;
99 start += 4;
100 } else if (strstr(start, "client.") == start) {
101 _type = TYPE_CLIENT;
102 start += 7;
103 } else if (strstr(start, "mgr.") == start) {
104 _type = TYPE_MGR;
105 start += 4;
106 } else {
107 return false;
108 }
109 if (isspace(*start))
110 return false;
111 _num = strtoll(start, end, 10);
112 if (*end == NULL || *end == start)
113 return false;
114 return true;
115 }
116
117 DENC(entity_name_t, v, p) {
118 denc(v._type, p);
119 denc(v._num, p);
120 }
121 void dump(Formatter *f) const;
122
123 static void generate_test_instances(list<entity_name_t*>& o);
124 };
125 WRITE_CLASS_DENC(entity_name_t)
126
127 inline bool operator== (const entity_name_t& l, const entity_name_t& r) {
128 return (l.type() == r.type()) && (l.num() == r.num()); }
129 inline bool operator!= (const entity_name_t& l, const entity_name_t& r) {
130 return (l.type() != r.type()) || (l.num() != r.num()); }
131 inline bool operator< (const entity_name_t& l, const entity_name_t& r) {
132 return (l.type() < r.type()) || (l.type() == r.type() && l.num() < r.num()); }
133
134 inline std::ostream& operator<<(std::ostream& out, const entity_name_t& addr) {
135 //if (addr.is_namer()) return out << "namer";
136 if (addr.is_new() || addr.num() < 0)
137 return out << addr.type_str() << ".?";
138 else
139 return out << addr.type_str() << '.' << addr.num();
140 }
141 inline std::ostream& operator<<(std::ostream& out, const ceph_entity_name& addr) {
142 return out << entity_name_t{addr.type, static_cast<int64_t>(addr.num)};
143 }
144
145 namespace std {
146 template<> struct hash< entity_name_t >
147 {
148 size_t operator()( const entity_name_t &m ) const
149 {
150 return rjhash32(m.type() ^ m.num());
151 }
152 };
153 } // namespace std
154
155 // define a wire format for sockaddr that matches Linux's.
156 struct ceph_sockaddr_storage {
157 __le16 ss_family;
158 __u8 __ss_padding[128 - sizeof(__le16)];
159
160 void encode(bufferlist& bl) const {
161 struct ceph_sockaddr_storage ss = *this;
162 ss.ss_family = htons(ss.ss_family);
163 ::encode_raw(ss, bl);
164 }
165
166 void decode(bufferlist::const_iterator& bl) {
167 struct ceph_sockaddr_storage ss;
168 ::decode_raw(ss, bl);
169 ss.ss_family = ntohs(ss.ss_family);
170 *this = ss;
171 }
172 } __attribute__ ((__packed__));
173 WRITE_CLASS_ENCODER(ceph_sockaddr_storage)
174
175 /*
176 * encode sockaddr.ss_family as network byte order
177 */
178 static inline void encode(const sockaddr_storage& a, bufferlist& bl) {
179 #if defined(__linux__)
180 struct sockaddr_storage ss = a;
181 ss.ss_family = htons(ss.ss_family);
182 ::encode_raw(ss, bl);
183 #elif defined(__FreeBSD__) || defined(__APPLE__)
184 ceph_sockaddr_storage ss{};
185 auto src = (unsigned char const *)&a;
186 auto dst = (unsigned char *)&ss;
187 src += sizeof(a.ss_len);
188 ss.ss_family = a.ss_family;
189 src += sizeof(a.ss_family);
190 dst += sizeof(ss.ss_family);
191 const auto copy_size = std::min((unsigned char*)(&a + 1) - src,
192 (unsigned char*)(&ss + 1) - dst);
193 ::memcpy(dst, src, copy_size);
194 encode(ss, bl);
195 #else
196 ceph_sockaddr_storage ss{};
197 ::memset(&ss, '\0', sizeof(ss));
198 ::memcpy(&wireaddr, &ss, std::min(sizeof(ss), sizeof(a)));
199 encode(ss, bl);
200 #endif
201 }
202 static inline void decode(sockaddr_storage& a, bufferlist::const_iterator& bl) {
203 #if defined(__linux__)
204 ::decode_raw(a, bl);
205 a.ss_family = ntohs(a.ss_family);
206 #elif defined(__FreeBSD__) || defined(__APPLE__)
207 ceph_sockaddr_storage ss{};
208 decode(ss, bl);
209 auto src = (unsigned char const *)&ss;
210 auto dst = (unsigned char *)&a;
211 a.ss_len = 0;
212 dst += sizeof(a.ss_len);
213 a.ss_family = ss.ss_family;
214 src += sizeof(ss.ss_family);
215 dst += sizeof(a.ss_family);
216 auto const copy_size = std::min((unsigned char*)(&ss + 1) - src,
217 (unsigned char*)(&a + 1) - dst);
218 ::memcpy(dst, src, copy_size);
219 #else
220 ceph_sockaddr_storage ss{};
221 decode(ss, bl);
222 ::memcpy(&a, &ss, std::min(sizeof(ss), sizeof(a)));
223 #endif
224 }
225
226 /*
227 * an entity's network address.
228 * includes a random value that prevents it from being reused.
229 * thus identifies a particular process instance.
230 * ipv4 for now.
231 */
232 struct entity_addr_t {
233 typedef enum {
234 TYPE_NONE = 0,
235 TYPE_LEGACY = 1, ///< legacy msgr1 protocol (ceph jewel and older)
236 TYPE_MSGR2 = 2, ///< msgr2 protocol (new in ceph kraken)
237 TYPE_ANY = 3, ///< ambiguous
238 } type_t;
239 static const type_t TYPE_DEFAULT = TYPE_MSGR2;
240 static std::string_view get_type_name(int t) {
241 switch (t) {
242 case TYPE_NONE: return "none";
243 case TYPE_LEGACY: return "v1";
244 case TYPE_MSGR2: return "v2";
245 case TYPE_ANY: return "any";
246 default: return "???";
247 }
248 };
249
250 __u32 type;
251 __u32 nonce;
252 union {
253 sockaddr sa;
254 sockaddr_in sin;
255 sockaddr_in6 sin6;
256 } u;
257
258 entity_addr_t() : type(0), nonce(0) {
259 memset(&u, 0, sizeof(u));
260 }
261 entity_addr_t(__u32 _type, __u32 _nonce) : type(_type), nonce(_nonce) {
262 memset(&u, 0, sizeof(u));
263 }
264 explicit entity_addr_t(const ceph_entity_addr &o) {
265 type = o.type;
266 nonce = o.nonce;
267 memcpy(&u, &o.in_addr, sizeof(u));
268 #if !defined(__FreeBSD__)
269 u.sa.sa_family = ntohs(u.sa.sa_family);
270 #endif
271 }
272
273 uint32_t get_type() const { return type; }
274 void set_type(uint32_t t) { type = t; }
275 bool is_legacy() const { return type == TYPE_LEGACY; }
276 bool is_msgr2() const { return type == TYPE_MSGR2; }
277 bool is_any() const { return type == TYPE_ANY; }
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 break;
371 case AF_INET6:
372 return ntohs(u.sin6.sin6_port);
373 break;
374 }
375 return 0;
376 }
377
378 operator ceph_entity_addr() const {
379 ceph_entity_addr a;
380 a.type = 0;
381 a.nonce = nonce;
382 a.in_addr = get_sockaddr_storage();
383 #if !defined(__FreeBSD__)
384 a.in_addr.ss_family = htons(a.in_addr.ss_family);
385 #endif
386 return a;
387 }
388
389 bool probably_equals(const entity_addr_t &o) const {
390 if (get_port() != o.get_port())
391 return false;
392 if (get_nonce() != o.get_nonce())
393 return false;
394 if (is_blank_ip() || o.is_blank_ip())
395 return true;
396 if (memcmp(&u, &o.u, sizeof(u)) == 0)
397 return true;
398 return false;
399 }
400
401 bool is_same_host(const entity_addr_t &o) const {
402 if (u.sa.sa_family != o.u.sa.sa_family)
403 return false;
404 if (u.sa.sa_family == AF_INET)
405 return u.sin.sin_addr.s_addr == o.u.sin.sin_addr.s_addr;
406 if (u.sa.sa_family == AF_INET6)
407 return memcmp(u.sin6.sin6_addr.s6_addr,
408 o.u.sin6.sin6_addr.s6_addr,
409 sizeof(u.sin6.sin6_addr.s6_addr)) == 0;
410 return false;
411 }
412
413 bool is_blank_ip() const {
414 switch (u.sa.sa_family) {
415 case AF_INET:
416 return u.sin.sin_addr.s_addr == INADDR_ANY;
417 case AF_INET6:
418 return memcmp(&u.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0;
419 default:
420 return true;
421 }
422 }
423
424 bool is_ip() const {
425 switch (u.sa.sa_family) {
426 case AF_INET:
427 case AF_INET6:
428 return true;
429 default:
430 return false;
431 }
432 }
433
434 std::string ip_only_to_str() const;
435
436 std::string get_legacy_str() const {
437 ostringstream ss;
438 ss << get_sockaddr() << "/" << get_nonce();
439 return ss.str();
440 }
441
442 bool parse(const char *s, const char **end = 0, int type=0);
443
444 void decode_legacy_addr_after_marker(bufferlist::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(bufferlist& 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 blacklist, 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 encode(elen, bl);
492 if (elen) {
493 #if (__FreeBSD__) || defined(__APPLE__)
494 __le16 ss_family = u.sa.sa_family;
495 encode(ss_family, bl);
496 bl.append(u.sa.sa_data,
497 elen - sizeof(u.sa.sa_len) - sizeof(u.sa.sa_family));
498 #else
499 bl.append((char*)get_sockaddr(), elen);
500 #endif
501 }
502 ENCODE_FINISH(bl);
503 }
504 void decode(bufferlist::const_iterator& bl) {
505 using ceph::decode;
506 __u8 marker;
507 decode(marker, bl);
508 if (marker == 0) {
509 decode_legacy_addr_after_marker(bl);
510 return;
511 }
512 if (marker != 1)
513 throw buffer::malformed_input("entity_addr_t marker != 1");
514 DECODE_START(1, bl);
515 decode(type, bl);
516 decode(nonce, bl);
517 __u32 elen;
518 decode(elen, bl);
519 if (elen) {
520 #if defined(__FreeBSD__) || defined(__APPLE__)
521 u.sa.sa_len = 0;
522 __le16 ss_family;
523 if (elen < sizeof(ss_family)) {
524 throw buffer::malformed_input("elen smaller than family len");
525 }
526 decode(ss_family, bl);
527 u.sa.sa_family = ss_family;
528 elen -= sizeof(ss_family);
529 if (elen > get_sockaddr_len() - sizeof(u.sa.sa_family)) {
530 throw buffer::malformed_input("elen exceeds sockaddr len");
531 }
532 bl.copy(elen, u.sa.sa_data);
533 #else
534 if (elen < sizeof(u.sa.sa_family)) {
535 throw buffer::malformed_input("elen smaller than family len");
536 }
537 bl.copy(sizeof(u.sa.sa_family), (char*)&u.sa.sa_family);
538 if (elen > get_sockaddr_len()) {
539 throw buffer::malformed_input("elen exceeds sockaddr len");
540 }
541 elen -= sizeof(u.sa.sa_family);
542 bl.copy(elen, u.sa.sa_data);
543 #endif
544 }
545 DECODE_FINISH(bl);
546 }
547
548 void dump(Formatter *f) const;
549
550 static void generate_test_instances(list<entity_addr_t*>& o);
551 };
552 WRITE_CLASS_ENCODER_FEATURES(entity_addr_t)
553
554 ostream& operator<<(ostream& out, const entity_addr_t &addr);
555
556 inline bool operator==(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) == 0; }
557 inline bool operator!=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) != 0; }
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
563 namespace std {
564 template<> struct hash< entity_addr_t >
565 {
566 size_t operator()( const entity_addr_t& x ) const
567 {
568 static blobhash H;
569 return H((const char*)&x, sizeof(x));
570 }
571 };
572 } // namespace std
573
574 struct entity_addrvec_t {
575 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 for (auto& a : v) {
585 if (a.type == entity_addr_t::TYPE_LEGACY) {
586 return a;
587 }
588 }
589 return entity_addr_t();
590 }
591 entity_addr_t as_legacy_addr() const {
592 for (auto& a : v) {
593 if (a.is_legacy()) {
594 return a;
595 }
596 if (a.is_any()) {
597 auto b = a;
598 b.set_type(entity_addr_t::TYPE_LEGACY);
599 return b;
600 }
601 }
602 // hrm... lie!
603 auto a = front();
604 a.set_type(entity_addr_t::TYPE_LEGACY);
605 return a;
606 }
607 entity_addr_t front() const {
608 if (!v.empty()) {
609 return v.front();
610 }
611 return entity_addr_t();
612 }
613 entity_addr_t legacy_or_front_addr() const {
614 for (auto& a : v) {
615 if (a.type == entity_addr_t::TYPE_LEGACY) {
616 return a;
617 }
618 }
619 if (!v.empty()) {
620 return v.front();
621 }
622 return entity_addr_t();
623 }
624 string get_legacy_str() const {
625 return legacy_or_front_addr().get_legacy_str();
626 }
627
628 entity_addr_t msgr2_addr() const {
629 for (auto &a : v) {
630 if (a.type == entity_addr_t::TYPE_MSGR2) {
631 return a;
632 }
633 }
634 return entity_addr_t();
635 }
636 bool has_msgr2() const {
637 for (auto& a : v) {
638 if (a.is_msgr2()) {
639 return true;
640 }
641 }
642 return false;
643 }
644
645 bool parse(const char *s, const char **end = 0);
646
647 void get_ports(set<int> *ports) const {
648 for (auto& a : v) {
649 ports->insert(a.get_port());
650 }
651 }
652 set<int> get_ports() const {
653 set<int> r;
654 get_ports(&r);
655 return r;
656 }
657
658 void encode(bufferlist& bl, uint64_t features) const;
659 void decode(bufferlist::const_iterator& bl);
660 void dump(Formatter *f) const;
661 static void generate_test_instances(list<entity_addrvec_t*>& ls);
662
663 bool legacy_equals(const entity_addrvec_t& o) const {
664 if (v == o.v) {
665 return true;
666 }
667 if (v.size() == 1 &&
668 front().is_legacy() &&
669 front() == o.legacy_addr()) {
670 return true;
671 }
672 if (o.v.size() == 1 &&
673 o.front().is_legacy() &&
674 o.front() == legacy_addr()) {
675 return true;
676 }
677 return false;
678 }
679
680 bool probably_equals(const entity_addrvec_t& o) const {
681 for (unsigned i = 0; i < v.size(); ++i) {
682 if (!v[i].probably_equals(o.v[i])) {
683 return false;
684 }
685 }
686 return true;
687 }
688 bool contains(const entity_addr_t& a) const {
689 for (auto& i : v) {
690 if (a == i) {
691 return true;
692 }
693 }
694 return false;
695 }
696 bool is_same_host(const entity_addr_t& a) const {
697 for (auto& i : v) {
698 if (i.is_same_host(a)) {
699 return true;
700 }
701 }
702 return false;
703 }
704
705 friend ostream& operator<<(ostream& out, const entity_addrvec_t& av) {
706 if (av.v.empty()) {
707 return out;
708 } else if (av.v.size() == 1) {
709 return out << av.v[0];
710 } else {
711 return out << av.v;
712 }
713 }
714
715 friend bool operator==(const entity_addrvec_t& l, const entity_addrvec_t& r) {
716 return l.v == r.v;
717 }
718 friend bool operator!=(const entity_addrvec_t& l, const entity_addrvec_t& r) {
719 return l.v != r.v;
720 }
721 friend bool operator<(const entity_addrvec_t& l, const entity_addrvec_t& r) {
722 return l.v < r.v; // see lexicographical_compare()
723 }
724 };
725 WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t);
726
727 namespace std {
728 template<> struct hash< entity_addrvec_t >
729 {
730 size_t operator()( const entity_addrvec_t& x ) const
731 {
732 static blobhash H;
733 size_t r = 0;
734 for (auto& i : x.v) {
735 r += H((const char*)&i, sizeof(i));
736 }
737 return r;
738 }
739 };
740 } // namespace std
741
742 /*
743 * a particular entity instance
744 */
745 struct entity_inst_t {
746 entity_name_t name;
747 entity_addr_t addr;
748 entity_inst_t() {}
749 entity_inst_t(entity_name_t n, const entity_addr_t& a) : name(n), addr(a) {}
750 // cppcheck-suppress noExplicitConstructor
751 entity_inst_t(const ceph_entity_inst& i) : name(i.name), addr(i.addr) { }
752 entity_inst_t(const ceph_entity_name& n, const ceph_entity_addr &a) : name(n), addr(a) {}
753 operator ceph_entity_inst() {
754 ceph_entity_inst i = {name, addr};
755 return i;
756 }
757
758 void encode(bufferlist& bl, uint64_t features) const {
759 using ceph::encode;
760 encode(name, bl);
761 encode(addr, bl, features);
762 }
763 void decode(bufferlist::const_iterator& bl) {
764 using ceph::decode;
765 decode(name, bl);
766 decode(addr, bl);
767 }
768
769 void dump(Formatter *f) const;
770 static void generate_test_instances(list<entity_inst_t*>& o);
771 };
772 WRITE_CLASS_ENCODER_FEATURES(entity_inst_t)
773
774
775 inline bool operator==(const entity_inst_t& a, const entity_inst_t& b) {
776 return a.name == b.name && a.addr == b.addr;
777 }
778 inline bool operator!=(const entity_inst_t& a, const entity_inst_t& b) {
779 return a.name != b.name || a.addr != b.addr;
780 }
781 inline bool operator<(const entity_inst_t& a, const entity_inst_t& b) {
782 return a.name < b.name || (a.name == b.name && a.addr < b.addr);
783 }
784 inline bool operator<=(const entity_inst_t& a, const entity_inst_t& b) {
785 return a.name < b.name || (a.name == b.name && a.addr <= b.addr);
786 }
787 inline bool operator>(const entity_inst_t& a, const entity_inst_t& b) { return b < a; }
788 inline bool operator>=(const entity_inst_t& a, const entity_inst_t& b) { return b <= a; }
789
790 namespace std {
791 template<> struct hash< entity_inst_t >
792 {
793 size_t operator()( const entity_inst_t& x ) const
794 {
795 static hash< entity_name_t > H;
796 static hash< entity_addr_t > I;
797 return H(x.name) ^ I(x.addr);
798 }
799 };
800 } // namespace std
801
802
803 inline ostream& operator<<(ostream& out, const entity_inst_t &i)
804 {
805 return out << i.name << " " << i.addr;
806 }
807 inline ostream& operator<<(ostream& out, const ceph_entity_inst &i)
808 {
809 entity_inst_t n = i;
810 return out << n;
811 }
812
813 #endif