]> git.proxmox.com Git - ceph.git/blob - ceph/src/msg/msg_types.h
import ceph 14.2.5
[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 ceph_le16 ss_family;
158 __u8 __ss_padding[128 - sizeof(ceph_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 #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
498 encode(ss_family, bl);
499 elen -= sizeof(u.sa.sa_family);
500 bl.append(u.sa.sa_data, elen);
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 #endif
523 uint16_t ss_family;
524 if (elen < sizeof(ss_family)) {
525 throw buffer::malformed_input("elen smaller than family len");
526 }
527 decode(ss_family, bl);
528 u.sa.sa_family = ss_family;
529 elen -= sizeof(ss_family);
530 if (elen > get_sockaddr_len() - sizeof(u.sa.sa_family)) {
531 throw buffer::malformed_input("elen exceeds sockaddr len");
532 }
533 bl.copy(elen, u.sa.sa_data);
534 }
535 DECODE_FINISH(bl);
536 }
537
538 void dump(Formatter *f) const;
539
540 static void generate_test_instances(list<entity_addr_t*>& o);
541 };
542 WRITE_CLASS_ENCODER_FEATURES(entity_addr_t)
543
544 ostream& operator<<(ostream& out, const entity_addr_t &addr);
545
546 inline bool operator==(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) == 0; }
547 inline bool operator!=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) != 0; }
548 inline bool operator<(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) < 0; }
549 inline bool operator<=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) <= 0; }
550 inline bool operator>(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) > 0; }
551 inline bool operator>=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) >= 0; }
552
553 namespace std {
554 template<> struct hash< entity_addr_t >
555 {
556 size_t operator()( const entity_addr_t& x ) const
557 {
558 static blobhash H;
559 return H((const char*)&x, sizeof(x));
560 }
561 };
562 } // namespace std
563
564 struct entity_addrvec_t {
565 vector<entity_addr_t> v;
566
567 entity_addrvec_t() {}
568 explicit entity_addrvec_t(const entity_addr_t& a) : v({ a }) {}
569
570 unsigned size() const { return v.size(); }
571 bool empty() const { return v.empty(); }
572
573 entity_addr_t legacy_addr() const {
574 for (auto& a : v) {
575 if (a.type == entity_addr_t::TYPE_LEGACY) {
576 return a;
577 }
578 }
579 return entity_addr_t();
580 }
581 entity_addr_t as_legacy_addr() const {
582 for (auto& a : v) {
583 if (a.is_legacy()) {
584 return a;
585 }
586 if (a.is_any()) {
587 auto b = a;
588 b.set_type(entity_addr_t::TYPE_LEGACY);
589 return b;
590 }
591 }
592 // hrm... lie!
593 auto a = front();
594 a.set_type(entity_addr_t::TYPE_LEGACY);
595 return a;
596 }
597 entity_addr_t front() const {
598 if (!v.empty()) {
599 return v.front();
600 }
601 return entity_addr_t();
602 }
603 entity_addr_t legacy_or_front_addr() const {
604 for (auto& a : v) {
605 if (a.type == entity_addr_t::TYPE_LEGACY) {
606 return a;
607 }
608 }
609 if (!v.empty()) {
610 return v.front();
611 }
612 return entity_addr_t();
613 }
614 string get_legacy_str() const {
615 return legacy_or_front_addr().get_legacy_str();
616 }
617
618 entity_addr_t msgr2_addr() const {
619 for (auto &a : v) {
620 if (a.type == entity_addr_t::TYPE_MSGR2) {
621 return a;
622 }
623 }
624 return entity_addr_t();
625 }
626 bool has_msgr2() const {
627 for (auto& a : v) {
628 if (a.is_msgr2()) {
629 return true;
630 }
631 }
632 return false;
633 }
634
635 bool parse(const char *s, const char **end = 0);
636
637 void get_ports(set<int> *ports) const {
638 for (auto& a : v) {
639 ports->insert(a.get_port());
640 }
641 }
642 set<int> get_ports() const {
643 set<int> r;
644 get_ports(&r);
645 return r;
646 }
647
648 void encode(bufferlist& bl, uint64_t features) const;
649 void decode(bufferlist::const_iterator& bl);
650 void dump(Formatter *f) const;
651 static void generate_test_instances(list<entity_addrvec_t*>& ls);
652
653 bool legacy_equals(const entity_addrvec_t& o) const {
654 if (v == o.v) {
655 return true;
656 }
657 if (v.size() == 1 &&
658 front().is_legacy() &&
659 front() == o.legacy_addr()) {
660 return true;
661 }
662 if (o.v.size() == 1 &&
663 o.front().is_legacy() &&
664 o.front() == legacy_addr()) {
665 return true;
666 }
667 return false;
668 }
669
670 bool probably_equals(const entity_addrvec_t& o) const {
671 for (unsigned i = 0; i < v.size(); ++i) {
672 if (!v[i].probably_equals(o.v[i])) {
673 return false;
674 }
675 }
676 return true;
677 }
678 bool contains(const entity_addr_t& a) const {
679 for (auto& i : v) {
680 if (a == i) {
681 return true;
682 }
683 }
684 return false;
685 }
686 bool is_same_host(const entity_addr_t& a) const {
687 for (auto& i : v) {
688 if (i.is_same_host(a)) {
689 return true;
690 }
691 }
692 return false;
693 }
694
695 friend ostream& operator<<(ostream& out, const entity_addrvec_t& av) {
696 if (av.v.empty()) {
697 return out;
698 } else if (av.v.size() == 1) {
699 return out << av.v[0];
700 } else {
701 return out << av.v;
702 }
703 }
704
705 friend bool operator==(const entity_addrvec_t& l, const entity_addrvec_t& r) {
706 return l.v == r.v;
707 }
708 friend bool operator!=(const entity_addrvec_t& l, const entity_addrvec_t& r) {
709 return l.v != r.v;
710 }
711 friend bool operator<(const entity_addrvec_t& l, const entity_addrvec_t& r) {
712 return l.v < r.v; // see lexicographical_compare()
713 }
714 };
715 WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t);
716
717 namespace std {
718 template<> struct hash< entity_addrvec_t >
719 {
720 size_t operator()( const entity_addrvec_t& x ) const
721 {
722 static blobhash H;
723 size_t r = 0;
724 for (auto& i : x.v) {
725 r += H((const char*)&i, sizeof(i));
726 }
727 return r;
728 }
729 };
730 } // namespace std
731
732 /*
733 * a particular entity instance
734 */
735 struct entity_inst_t {
736 entity_name_t name;
737 entity_addr_t addr;
738 entity_inst_t() {}
739 entity_inst_t(entity_name_t n, const entity_addr_t& a) : name(n), addr(a) {}
740 // cppcheck-suppress noExplicitConstructor
741 entity_inst_t(const ceph_entity_inst& i) : name(i.name), addr(i.addr) { }
742 entity_inst_t(const ceph_entity_name& n, const ceph_entity_addr &a) : name(n), addr(a) {}
743 operator ceph_entity_inst() {
744 ceph_entity_inst i = {name, addr};
745 return i;
746 }
747
748 void encode(bufferlist& bl, uint64_t features) const {
749 using ceph::encode;
750 encode(name, bl);
751 encode(addr, bl, features);
752 }
753 void decode(bufferlist::const_iterator& bl) {
754 using ceph::decode;
755 decode(name, bl);
756 decode(addr, bl);
757 }
758
759 void dump(Formatter *f) const;
760 static void generate_test_instances(list<entity_inst_t*>& o);
761 };
762 WRITE_CLASS_ENCODER_FEATURES(entity_inst_t)
763
764
765 inline bool operator==(const entity_inst_t& a, const entity_inst_t& b) {
766 return a.name == b.name && a.addr == b.addr;
767 }
768 inline bool operator!=(const entity_inst_t& a, const entity_inst_t& b) {
769 return a.name != b.name || a.addr != b.addr;
770 }
771 inline bool operator<(const entity_inst_t& a, const entity_inst_t& b) {
772 return a.name < b.name || (a.name == b.name && a.addr < b.addr);
773 }
774 inline bool operator<=(const entity_inst_t& a, const entity_inst_t& b) {
775 return a.name < b.name || (a.name == b.name && a.addr <= b.addr);
776 }
777 inline bool operator>(const entity_inst_t& a, const entity_inst_t& b) { return b < a; }
778 inline bool operator>=(const entity_inst_t& a, const entity_inst_t& b) { return b <= a; }
779
780 namespace std {
781 template<> struct hash< entity_inst_t >
782 {
783 size_t operator()( const entity_inst_t& x ) const
784 {
785 static hash< entity_name_t > H;
786 static hash< entity_addr_t > I;
787 return H(x.name) ^ I(x.addr);
788 }
789 };
790 } // namespace std
791
792
793 inline ostream& operator<<(ostream& out, const entity_inst_t &i)
794 {
795 return out << i.name << " " << i.addr;
796 }
797 inline ostream& operator<<(ostream& out, const ceph_entity_inst &i)
798 {
799 entity_inst_t n = i;
800 return out << n;
801 }
802
803 #endif