GComm  0.2.3
protolay.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009-2014 Codership Oy <info@codership.com>
3  */
4 
15 #ifndef GCOMM_PROTOLAY_HPP
16 #define GCOMM_PROTOLAY_HPP
17 
18 #include "gcomm/view.hpp"
19 #include "gcomm/exception.hpp"
20 #include "gcomm/order.hpp"
21 #include "gcomm/datagram.hpp"
22 
23 #include "gu_logger.hpp"
24 #include "gu_datetime.hpp"
25 #include "gu_config.hpp"
26 
27 #include <cerrno>
28 
29 #include <list>
30 #include <utility>
31 
32 
33 // Declarations
34 namespace gcomm
35 {
41  class ProtoUpMeta;
42  std::ostream& operator<<(std::ostream&, const ProtoUpMeta&);
43 
49  class ProtoDownMeta;
50 
56  class Protolay;
57 
63  class Toplay;
64 
70  class Bottomlay;
71 
72  void connect(Protolay*, Protolay*);
73  void disconnect(Protolay*, Protolay*);
74 }
75 
76 /* message context to pass up with the data buffer? */
78 {
79 public:
80  ProtoUpMeta(const int err_no) :
81  source_(),
82  source_view_id_(),
83  user_type_(),
84  order_(),
85  to_seq_(),
86  err_no_(err_no),
87  view_(0)
88  { }
89 
90  ProtoUpMeta(const UUID source = UUID::nil(),
91  const ViewId source_view_id = ViewId(),
92  const View* view = 0,
93  const uint8_t user_type = 0xff,
94  const Order order = O_DROP,
95  const int64_t to_seq = -1,
96  const int err_no = 0) :
97  source_ (source ),
98  source_view_id_ (source_view_id ),
99  user_type_ (user_type ),
100  order_ (order ),
101  to_seq_ (to_seq ),
102  err_no_ (err_no ),
103  view_ (view != 0 ? new View(*view) : 0)
104  { }
105 
106  ProtoUpMeta(const ProtoUpMeta& um) :
107  source_ (um.source_ ),
108  source_view_id_ (um.source_view_id_ ),
109  user_type_ (um.user_type_ ),
110  order_ (um.order_ ),
111  to_seq_ (um.to_seq_ ),
112  err_no_ (um.err_no_ ),
113  view_ (um.view_ ? new View(*um.view_) : 0)
114  { }
115 
116  ~ProtoUpMeta() { delete view_; }
117 
118  const UUID& source() const { return source_; }
119 
120  const ViewId& source_view_id() const { return source_view_id_; }
121 
122  uint8_t user_type() const { return user_type_; }
123 
124  Order order() const { return order_; }
125 
126  int64_t to_seq() const { return to_seq_; }
127 
128  int err_no() const { return err_no_; }
129 
130  bool has_view() const { return view_ != 0; }
131 
132  const View& view() const { return *view_; }
133 
134 private:
135  ProtoUpMeta& operator=(const ProtoUpMeta&);
136 
137  UUID const source_;
138  ViewId const source_view_id_;
139  uint8_t const user_type_;
140  Order const order_;
141  int64_t const to_seq_;
142  int const err_no_;
143  View* const view_;
144 };
145 
146 inline std::ostream& gcomm::operator<<(std::ostream& os, const ProtoUpMeta& um)
147 {
148  os << "proto_up_meta: { ";
149  if (not (um.source() == UUID::nil()))
150  {
151  os << "source=" << um.source() << ",";
152  }
153  if (um.source_view_id().type() != V_NONE)
154  {
155  os << "source_view_id=" << um.source_view_id() << ",";
156  }
157  os << "user_type=" << static_cast<int>(um.user_type()) << ",";
158  os << "to_seq=" << um.to_seq() << ",";
159  if (um.has_view() == true)
160  {
161  os << "view=" << um.view();
162  }
163  os << "}";
164  return os;
165 }
166 
167 /* message context to pass down? */
169 {
170 public:
171  ProtoDownMeta(const uint8_t user_type = 0xff,
172  const Order order = O_SAFE,
173  const UUID& uuid = UUID::nil(),
174  const int segment = 0) :
175  user_type_ (user_type),
176  order_ (order),
177  source_ (uuid),
178  segment_ (segment)
179  { }
180 
181  uint8_t user_type() const { return user_type_; }
182  Order order() const { return order_; }
183  const UUID& source() const { return source_; }
184  int segment() const { return segment_; }
185 private:
186  const uint8_t user_type_;
187  const Order order_;
188  const UUID source_;
189  const int segment_;
190 };
191 
193 {
194  typedef std::list<Protolay*> CtxList;
195  CtxList up_context_;
196  CtxList down_context_;
197 
198  Protolay (const Protolay&);
199  Protolay& operator=(const Protolay&);
200 
201 protected:
202 
203  gu::Config& conf_;
204 
205  Protolay(gu::Config& conf)
206  :
207  up_context_(0),
208  down_context_(0),
209  conf_(conf)
210  { }
211 
212 public:
213 
214  virtual ~Protolay() {}
215 
216  virtual void connect(bool) { }
217  virtual void close(bool force = false) { }
218  virtual void close(const UUID& uuid) { }
219 
220  /* apparently handles data from upper layer. what is return value? */
221  virtual int handle_down (Datagram&, const ProtoDownMeta&) = 0;
222  virtual void handle_up (const void*, const Datagram&, const ProtoUpMeta&) = 0;
223 
224  void set_up_context(Protolay *up)
225  {
226  if (std::find(up_context_.begin(),
227  up_context_.end(),
228  up) != up_context_.end())
229  {
230  gu_throw_fatal << "up context already exists";
231  }
232  up_context_.push_back(up);
233  }
234 
235  void set_down_context(Protolay *down)
236  {
237  if (std::find(down_context_.begin(),
238  down_context_.end(),
239  down) != down_context_.end())
240  {
241  gu_throw_fatal << "down context already exists";
242  }
243  down_context_.push_back(down);
244  }
245 
246  void unset_up_context(Protolay* up)
247  {
248  CtxList::iterator i;
249  if ((i = std::find(up_context_.begin(),
250  up_context_.end(),
251  up)) == up_context_.end())
252  {
253  gu_throw_fatal << "up context does not exist";
254  }
255  up_context_.erase(i);
256  }
257 
258 
259  void unset_down_context(Protolay* down)
260  {
261  CtxList::iterator i;
262  if ((i = std::find(down_context_.begin(),
263  down_context_.end(),
264  down)) == down_context_.end())
265  {
266  gu_throw_fatal << "down context does not exist";
267  }
268  down_context_.erase(i);
269  }
270 
271  /* apparently passed data buffer to the upper layer */
272  void send_up(const Datagram& dg, const ProtoUpMeta& up_meta)
273  {
274  if (up_context_.empty() == true)
275  {
276  gu_throw_fatal << this << " up context(s) not set";
277  }
278 
279  CtxList::iterator i, i_next;
280  for (i = up_context_.begin(); i != up_context_.end(); i = i_next)
281  {
282  i_next = i, ++i_next;
283  (*i)->handle_up(this, dg, up_meta);
284  }
285  }
286 
287  /* apparently passes data buffer to lower layer, what is return value? */
288  int send_down(Datagram& dg, const ProtoDownMeta& down_meta)
289  {
290  if (down_context_.empty() == true)
291  {
292  log_warn << this << " down context(s) not set";
293  return ENOTCONN;
294  }
295 
296  int ret = 0;
297  for (CtxList::iterator i = down_context_.begin();
298  i != down_context_.end(); ++i)
299  {
300  const size_t hdr_offset(dg.header_offset());
301  int err = (*i)->handle_down(dg, down_meta);
302  // Verify that lower layer rolls back any modifications to
303  // header
304  if (hdr_offset != dg.header_offset())
305  {
306  gu_throw_fatal;
307  }
308  if (err != 0)
309  {
310  ret = err;
311  }
312  }
313  return ret;
314  }
315 
316  virtual void handle_stable_view(const View& view) { }
317 
318  void set_stable_view(const View& view)
319  {
320  for (CtxList::iterator i(down_context_.begin());
321  i != down_context_.end(); ++i)
322  {
323  (*i)->handle_stable_view(view);
324  }
325  }
326 
327  virtual gu::datetime::Date handle_timers()
328  {
329  return gu::datetime::Date::max();
330  }
331 
332  virtual bool set_param(const std::string& key, const std::string& val)
333  {
334  return false;
335  }
336 
337  const Protolay* id() const { return this; }
338 
339 };
340 
341 class gcomm::Toplay : public Protolay
342 {
343 public:
344  Toplay(gu::Config& conf) : Protolay(conf) { }
345 private:
346  int handle_down(Datagram& dg, const ProtoDownMeta& dm)
347  {
348  gu_throw_fatal << "Toplay handle_down() called";
349  }
350 };
351 
353 {
354 public:
355  Bottomlay(gu::Config& conf) : Protolay(conf) { }
356 private:
357  void handle_up(const void* id, const Datagram&, const ProtoUpMeta& um)
358  {
359  gu_throw_fatal << "Bottomlay handle_up() called";
360  }
361 };
362 
363 inline void gcomm::connect(Protolay* down, Protolay* up)
364 {
365  down->set_up_context(up);
366  up->set_down_context(down);
367 }
368 
369 inline void gcomm::disconnect(Protolay* down, Protolay* up)
370 {
371  down->unset_up_context(up);
372  up->unset_down_context(down);
373 }
374 
375 
376 #endif /* GCOMM_PROTOLAY_HPP */
Definition: view.hpp:29
Definition: protolay.hpp:352
Message order type enumeration.
Definition: view.hpp:119
GComm exception definitions.
Definition: protolay.hpp:341
Definition: protolay.hpp:192
Definition: protolay.hpp:77
Definition: uuid.hpp:26
Definition: protolay.hpp:168
Datagram container.
Definition: datagram.hpp:151