GComm  0.2.3
pc_message.hpp
1 /*
2  * Copyright (C) 2009-2012 Codership Oy <info@codership.com>
3  */
4 
5 #ifndef PC_MESSAGE_HPP
6 #define PC_MESSAGE_HPP
7 
8 #include "gcomm/view.hpp"
9 #include "gcomm/types.hpp"
10 #include "gcomm/uuid.hpp"
11 #include "gcomm/map.hpp"
12 
13 #include "gu_serialize.hpp"
14 
15 #include <limits>
16 
17 namespace gcomm
18 {
19  namespace pc
20  {
21  class Node;
22  class NodeMap;
23  class Message;
24  class UserMessage;
25  class StateMessage;
26  class InstallMessage;
27  std::ostream& operator<<(std::ostream&, const Node&);
28  std::ostream& operator<<(std::ostream&, const Message&);
29  bool operator==(const Message&, const Message&);
30  }
31 }
32 
33 
35 {
36 public:
37  enum Flags
38  {
39  F_PRIM = 0x1,
40  F_WEIGHT = 0x2,
41  F_UN = 0x4
42  };
43 
44  Node(const bool prim = false,
45  const bool un = false,
46  const uint32_t last_seq = std::numeric_limits<uint32_t>::max(),
47  const ViewId& last_prim = ViewId(V_NON_PRIM),
48  const int64_t to_seq = -1,
49  const int weight = -1,
50  const SegmentId segment = 0)
51  :
52  prim_ (prim ),
53  un_ (un ),
54  last_seq_ (last_seq ),
55  last_prim_ (last_prim),
56  to_seq_ (to_seq ),
57  weight_ (weight),
58  segment_ (segment)
59  { }
60 
61  void set_prim (const bool val) { prim_ = val ; }
62  void set_un (const bool un) { un_ = un ; }
63  void set_last_seq (const uint32_t seq) { last_seq_ = seq ; }
64  void set_last_prim (const ViewId& last_prim) { last_prim_ = last_prim; }
65  void set_to_seq (const uint64_t seq) { to_seq_ = seq ; }
66  void set_weight (const int weight) { weight_ = weight ; }
67  void set_segment (const SegmentId segment) { segment_ = segment ; }
68 
69  bool prim() const { return prim_ ; }
70  bool un() const { return un_ ; }
71  uint32_t last_seq() const { return last_seq_ ; }
72  const ViewId& last_prim() const { return last_prim_; }
73  int64_t to_seq() const { return to_seq_ ; }
74  int weight() const { return weight_ ; }
75  SegmentId segment() const { return segment_ ; }
76 
77  size_t unserialize(const gu::byte_t* buf, const size_t buflen, const size_t offset)
78  {
79  size_t off = offset;
80  uint32_t flags;
81 
82  gu_trace (off = gu::unserialize4(buf, buflen, off, flags));
83 
84  prim_ = flags & F_PRIM;
85  un_ = flags & F_UN;
86  if (flags & F_WEIGHT)
87  {
88  weight_ = flags >> 24;
89  }
90  else
91  {
92  weight_ = -1;
93  }
94  segment_ = (flags >> 16) & 0xff;
95  gu_trace (off = gu::unserialize4(buf, buflen, off, last_seq_));
96  gu_trace (off = last_prim_.unserialize(buf, buflen, off));
97  gu_trace (off = gu::unserialize8(buf, buflen, off, to_seq_));
98 
99  return off;
100  }
101 
102  size_t serialize(gu::byte_t* buf, const size_t buflen, const size_t offset) const
103  {
104  size_t off = offset;
105  uint32_t flags = 0;
106 
107  flags |= prim_ ? F_PRIM : 0;
108  flags |= un_ ? F_UN : 0;
109  if (weight_ >= 0)
110  {
111  flags |= F_WEIGHT;
112  flags |= weight_ << 24;
113  }
114  flags |= static_cast<uint32_t>(segment_) << 16;
115  gu_trace (off = gu::serialize4(flags, buf, buflen, off));
116  gu_trace (off = gu::serialize4(last_seq_, buf, buflen, off));
117  gu_trace (off = last_prim_.serialize(buf, buflen, off));
118  gu_trace (off = gu::serialize8(to_seq_, buf, buflen, off));
119 
120  assert (serial_size() == (off - offset));
121 
122  return off;
123  }
124 
125  static size_t serial_size()
126  {
127  Node* node(reinterpret_cast<Node*>(0));
128 
129  // flags
130  return (sizeof(uint32_t) + sizeof(node->last_seq_) +
131  ViewId::serial_size() + sizeof(node->to_seq_));
132  }
133 
134  bool operator==(const Node& cmp) const
135  {
136  return (prim() == cmp.prim() &&
137  un() == cmp.un() &&
138  last_seq() == cmp.last_seq() &&
139  last_prim() == cmp.last_prim() &&
140  to_seq() == cmp.to_seq() &&
141  weight() == cmp.weight() &&
142  segment() == cmp.segment() );
143  }
144 
145  std::string to_string() const
146  {
147  std::ostringstream ret;
148 
149  ret << "prim=" << prim_
150  << ",un=" << un_
151  << ",last_seq=" << last_seq_
152  << ",last_prim=" << last_prim_
153  << ",to_seq=" << to_seq_
154  << ",weight=" << weight_
155  << ",segment=" << static_cast<int>(segment_);
156 
157  return ret.str();
158  }
159 
160 private:
161 
162  bool prim_; // Is node in prim comp
163  bool un_; // The prim status of the node is unknown
164  uint32_t last_seq_; // Last seen message seq from the node
165  ViewId last_prim_; // Last known prim comp view id for the node
166  int64_t to_seq_; // Last known TO seq for the node
167  int weight_; // Node weight
168  SegmentId segment_;
169 };
170 
171 
172 inline std::ostream& gcomm::pc::operator<<(std::ostream& os, const Node& n)
173 {
174  return (os << n.to_string());
175 }
176 
177 
178 class gcomm::pc::NodeMap : public Map<UUID, Node> { };
179 
180 
182 {
183 public:
184 
185  enum Type {T_NONE, T_STATE, T_INSTALL, T_USER, T_MAX};
186  enum
187  {
188  F_CRC16 = 0x1,
189  F_BOOTSTRAP = 0x2,
190  F_WEIGHT_CHANGE = 0x4
191  };
192 
193  static const char* to_string(Type t)
194  {
195  static const char* str[T_MAX] =
196  { "NONE", "STATE", "INSTALL", "USER" };
197 
198  if (t < T_MAX) return str[t];
199 
200  return "unknown";
201  }
202 
203 
204  Message(const int version = -1,
205  const Type type = T_NONE,
206  const uint32_t seq = 0,
207  const NodeMap& node_map = NodeMap())
208  :
209  version_ (version ),
210  flags_ (0 ),
211  type_ (type ),
212  seq_ (seq ),
213  crc16_ (0 ),
214  node_map_(node_map)
215  { }
216 
217  Message(const Message& msg)
218  :
219  version_ (msg.version_ ),
220  flags_ (msg.flags_ ),
221  type_ (msg.type_ ),
222  seq_ (msg.seq_ ),
223  crc16_ (msg.crc16_ ),
224  node_map_(msg.node_map_)
225  { }
226 
227  virtual ~Message() { }
228 
229 
230  int version() const { return version_; }
231  Type type() const { return type_; }
232  uint32_t seq() const { return seq_; }
233 
234  void flags(int flags) { flags_ = flags; }
235  int flags() const { return flags_; }
236  void checksum(uint16_t crc16, bool flag)
237  {
238  crc16_ = crc16;
239  if (flag == true)
240  {
241  flags_ |= F_CRC16;
242  }
243  else
244  {
245  flags_ &= ~F_CRC16;
246  }
247  }
248  uint16_t checksum() const { return crc16_; }
249 
250  const NodeMap& node_map() const { return node_map_; }
251  NodeMap& node_map() { return node_map_; }
252 
253  const Node& node(const UUID& uuid) const
254  { return NodeMap::value(node_map_.find_checked(uuid)); }
255  Node& node(const UUID& uuid)
256  { return NodeMap::value(node_map_.find_checked(uuid)); }
257 
258  size_t unserialize(const gu::byte_t* buf, const size_t buflen, const size_t offset)
259  {
260  size_t off;
261  uint32_t b;
262 
263  node_map_.clear();
264 
265  gu_trace (off = gu::unserialize4(buf, buflen, offset, b));
266 
267  version_ = b & 0x0f;
268  flags_ = (b & 0xf0) >> 4;
269  if (version_ != 0)
270  gu_throw_error (EPROTONOSUPPORT)
271  << "Unsupported protocol varsion: " << version_;
272 
273  type_ = static_cast<Type>((b >> 8) & 0xff);
274  if (type_ <= T_NONE || type_ >= T_MAX)
275  gu_throw_error (EINVAL) << "Bad type value: " << type_;
276 
277  crc16_ = ((b >> 16) & 0xffff);
278 
279  gu_trace (off = gu::unserialize4(buf, buflen, off, seq_));
280 
281  if (type_ == T_STATE || type_ == T_INSTALL)
282  {
283  gu_trace (off = node_map_.unserialize(buf, buflen, off));
284  }
285 
286  return off;
287  }
288 
289  size_t serialize(gu::byte_t* buf, const size_t buflen, const size_t offset) const
290  {
291  size_t off;
292  uint32_t b;
293 
294  b = crc16_;
295  b <<= 8;
296  b |= type_ & 0xff;
297  b <<= 8;
298  b |= version_ & 0x0f;
299  b |= (flags_ << 4) & 0xf0;
300 
301  gu_trace (off = gu::serialize4(b, buf, buflen, offset));
302  gu_trace (off = gu::serialize4(seq_, buf, buflen, off));
303 
304 
305  if (type_ == T_STATE || type_ == T_INSTALL)
306  {
307  gu_trace (off = node_map_.serialize(buf, buflen, off));
308  }
309 
310  assert (serial_size() == (off - offset));
311 
312  return off;
313  }
314 
315  size_t serial_size() const
316  {
317  // header
318  return (sizeof(uint32_t)
319  + sizeof(seq_)
320  + (type_ == T_STATE || type_ == T_INSTALL ?
321  node_map_.serial_size() :
322  0));
323  }
324 
325 
326  std::string to_string() const
327  {
328  std::ostringstream ret;
329 
330  ret << "pcmsg{ type=" << to_string(type_) << ", seq=" << seq_;
331  ret << ", flags=" << std::setw(2) << std::hex << flags_;
332  ret << ", node_map {" << node_map() << "}";
333  ret << '}';
334 
335  return ret.str();
336  }
337 
338 private:
339  Message& operator=(const Message&);
340 
341  int version_; // Message version
342  int flags_; // Flags
343  Type type_; // Message type
344  uint32_t seq_; // Message seqno
345  uint16_t crc16_; // 16-bit crc
346  NodeMap node_map_; // Message node map
347 };
348 
349 
350 inline std::ostream& gcomm::pc::operator<<(std::ostream& os, const Message& m)
351 {
352  return (os << m.to_string());
353 }
354 
355 
357 {
358 public:
359  StateMessage(int version) : Message(version, Message::T_STATE, 0) {}
360 };
361 
362 
364 {
365 public:
366  InstallMessage(int version) : Message(version, Message::T_INSTALL, 0) {}
367 };
368 
369 
371 {
372 public:
373  UserMessage(int version, uint32_t seq) : Message(version, Message::T_USER, seq) {}
374 };
375 
376 
377 inline bool gcomm::pc::operator==(const Message& a, const Message& b)
378 {
379  return (a.version() == b.version() &&
380  a.checksum() == b.checksum() &&
381  a.type() == b.type() &&
382  a.seq() == b.seq() &&
383  a.node_map() == b.node_map());
384 }
385 
386 
387 #endif // PC_MESSAGE_HPP
Definition: view.hpp:29
Definition: pc_message.hpp:34
Definition: map.hpp:210
Definition: pc_message.hpp:181
Definition: pc_message.hpp:363
Definition: pc_message.hpp:356
Definition: pc_message.hpp:178
Definition: pc_message.hpp:370
Definition: uuid.hpp:26