1 /*
2  * Copyright (C) 2015-2017 Codership Oy <info@codership.com>
3  */
4 
5 #ifndef _gu_gtid_hpp_
6 #define _gu_gtid_hpp_
7 
8 #include "gu_uuid.hpp"
9 #include "gu_serialize.hpp"
10 
11 #include "gu_hash.h"
12 #include <stdint.h>
13 
14 namespace gu
15 {
16     class GTID;
17 
18     typedef int64_t seqno_t;
19 } /* namespace gu */
20 
21 class gu::GTID
22 {
23 public:
24 
25     static seqno_t const SEQNO_UNDEFINED = -1;
26 
GTID()27     GTID() : uuid_(), seqno_(SEQNO_UNDEFINED) {}
28 
GTID(const UUID & u,seqno_t s)29     GTID(const UUID& u, seqno_t s) : uuid_(u), seqno_(s) {}
30 
GTID(const gu_uuid_t & u,seqno_t s)31     GTID(const gu_uuid_t& u, seqno_t s) : uuid_(u), seqno_(s) {}
32 
GTID(const GTID & g)33     GTID(const GTID& g) : uuid_(g.uuid_), seqno_(g.seqno_) {}
34 
GTID(const void * const buf,size_t const buflen)35     GTID(const void* const buf, size_t const buflen)
36         :
37         uuid_ (),
38         seqno_(SEQNO_UNDEFINED)
39     {
40         (void) unserialize(buf, buflen, 0);
41     }
42 
43     // this constuftor modifies offset
GTID(const void * const buf,size_t const buflen,size_t & offset)44     GTID(const void* const buf, size_t const buflen, size_t& offset)
45         :
46         uuid_ (),
47         seqno_(SEQNO_UNDEFINED)
48     {
49         offset = unserialize(buf, buflen, offset);
50     }
51 
52     GTID& operator=(const GTID& other) = default;
53 
uuid() const54     const UUID& uuid()  const { return uuid_;  }
seqno() const55     seqno_t     seqno() const { return seqno_; }
56 
set(const gu::UUID & u)57     void set(const gu::UUID& u) { uuid_  = u; }
set(seqno_t const s)58     void set(seqno_t const   s) { seqno_ = s; }
59 
set(const gu::UUID & u,seqno_t const s)60     void set(const gu::UUID& u, seqno_t const s) { set(u); set(s); }
61 
operator ==(const GTID & other) const62     bool operator==(const GTID& other) const
63     {
64         return (seqno_ == other.seqno_ && uuid_ == other.uuid_);
65     }
66 
operator !=(const GTID & other) const67     bool operator!=(const GTID& other) const { return !(*this == other); }
68 
is_undefined() const69     bool is_undefined() const
70     {
71         static GTID undefined;
72         return *this == undefined;
73     }
74 
75     void print(std::ostream& os) const;
76 
77     void scan(std::istream& is);
78 
serial_size()79     static size_t serial_size() { return UUID::serial_size() +sizeof(int64_t); }
80 
serialize(void * const buf,size_t offset) const81     size_t serialize(void* const buf, size_t offset) const
82     {
83         assert(serial_size() == (uuid_.serial_size() + sizeof(int64_t)));
84 
85         offset = uuid_.serialize(buf, offset);
86         offset = gu::serialize8(seqno_, buf, offset);
87 
88         return offset;
89     }
90 
unserialize(const void * const buf,size_t offset)91     size_t unserialize(const void* const buf, size_t offset)
92     {
93         assert(serial_size() == (uuid_.serial_size() + sizeof(seqno_)));
94 
95         offset = uuid_.unserialize(buf, offset);
96         offset = gu::unserialize8(buf, offset, seqno_);
97 
98         return offset;
99     }
100 
unserialize(const void * const buf,const size_t buflen,const size_t offset)101     size_t unserialize(const void* const buf, const size_t buflen,
102                        const size_t offset)
103     {
104         gu_trace(gu::check_bounds(offset + serial_size(), buflen));
105         return unserialize(buf, offset);
106     }
107 
serialize(void * const buf,const size_t buflen,const size_t offset) const108     size_t serialize  (void* const buf, const size_t buflen,
109                        const size_t offset) const
110     {
111         gu_trace(gu::check_bounds(offset + serial_size(), buflen));
112         return serialize(buf, offset);
113     }
114 
115     class TableHash // for std::map, does not have to be endian independent
116     {
117     public:
operator ()(const GTID & gtid) const118         size_t operator()(const GTID& gtid) const
119         {
120             // UUID is 16 bytes and seqno_t is 8 bytes so all should be
121             // properly aligned into a continuous buffer
122             return gu_table_hash(&gtid, sizeof(UUID) + sizeof(seqno_t));
123         }
124     };
125 
126 private:
127 
128     UUID    uuid_;
129     seqno_t seqno_;
130 
131 }; /* class GTID */
132 
133 namespace gu
134 {
operator <<(std::ostream & os,const GTID & gtid)135 inline std::ostream& operator<< (std::ostream& os, const GTID& gtid)
136 {
137     gtid.print(os); return os;
138 }
139 
operator >>(std::istream & is,GTID & gtid)140 inline std::istream& operator>> (std::istream& is, GTID& gtid)
141 {
142     gtid.scan(is); return is;
143 }
144 } /* namespace gu */
145 
146 #endif /* _gu_gtid_hpp_ */
147