1 /*
2  * Copyright (C) 2009 Codership Oy <info@codership.com>
3  */
4 
5 
6 /*!
7  * @file Group view class (used in the ProtoUpMeta (protolay.hpp)
8  */
9 
10 #ifndef _GCOMM_VIEW_HPP_
11 #define _GCOMM_VIEW_HPP_
12 
13 
14 #include "gcomm/uuid.hpp"
15 #include "gcomm/types.hpp"
16 #include "gcomm/map.hpp"
17 #include "gcomm/conf.hpp"
18 
19 namespace gcomm
20 {
21     typedef enum
22     {
23         V_NONE     = -1,
24         V_REG      = 0,
25         V_TRANS    = 1,
26         V_NON_PRIM = 2,
27         V_PRIM     = 3
28     } ViewType;
29 
30     class ViewId
31     {
32     public:
33 
34 
ViewId(const ViewType type=V_NONE,const UUID & uuid=UUID::nil (),const uint32_t seq=0)35         ViewId(const ViewType type    = V_NONE,
36                const UUID&    uuid    = UUID::nil(),
37                const uint32_t seq     = 0) :
38             type_(type),
39             uuid_(uuid),
40             seq_ (seq)
41         { }
42 
ViewId(const ViewType type,const ViewId & vi)43         ViewId(const ViewType type,
44                const ViewId& vi) :
45             type_(type),
46             uuid_(vi.uuid()),
47             seq_ (vi.seq())
48         { }
49 
~ViewId()50         virtual ~ViewId() { }
51 
type() const52         ViewType    type() const { return type_; }
53 
uuid() const54         const UUID& uuid() const { return uuid_; }
55 
seq() const56         uint32_t    seq()  const { return seq_; }
57 
58         size_t unserialize(const gu::byte_t* buf, size_t buflen, size_t offset);
59 
60         size_t serialize(gu::byte_t* buf, size_t buflen, size_t offset) const;
61 
serial_size()62         static size_t serial_size()
63         {
64             return UUID::serial_size() + sizeof(reinterpret_cast<ViewId*>(0)->seq_);
65         }
66 
operator <(const ViewId & cmp) const67         bool operator<(const ViewId& cmp) const
68         {
69             // View ordering:
70             // 1) view seq less than
71             // 2) uuid newer than
72             // 3) type less than
73             return (seq_ < cmp.seq_ ||
74                     (seq_ == cmp.seq_ &&
75                      (cmp.uuid_.older(uuid_) ||
76                       (uuid_ == cmp.uuid_ && type_ < cmp.type_) ) ) );
77         }
78 
operator ==(const ViewId & cmp) const79         bool operator==(const ViewId& cmp) const
80         {
81             return (seq_  == cmp.seq_  &&
82                     type_ == cmp.type_ &&
83                     uuid_ == cmp.uuid_);
84         }
85 
operator !=(const ViewId & cmp) const86         bool operator!=(const ViewId& cmp) const
87         {
88             return !(*this == cmp);
89         }
90 
write_stream(std::ostream & os) const91         std::ostream& write_stream(std::ostream& os) const {
92             os << static_cast<int>(type_) << " ";
93             uuid_.write_stream(os);
94             os << " " << seq_;
95             return os;
96         }
read_stream(std::istream & is)97         std::istream& read_stream(std::istream& is) {
98             int t;
99             is >> t;
100             type_ = static_cast<ViewType>(t);
101             uuid_.read_stream(is);
102             is >> seq_;
103             return is;
104         }
105 
106     private:
107         ViewType type_;
108         UUID     uuid_; // uniquely identifies the sequence of group views (?)
109         uint32_t seq_;  // position in the sequence                        (?)
110     };
111 
112     std::ostream& operator<<(std::ostream&, const ViewId&);
113 
114     typedef uint8_t SegmentId;
115 
116     class Node
117     {
118     public:
Node(SegmentId segment=0)119         Node(SegmentId segment = 0) : segment_(segment)
120         { }
segment() const121         SegmentId segment() const { return segment_; }
operator ==(const Node & cmp) const122         bool operator==(const Node& cmp) const { return true; }
operator <(const Node & cmp) const123         bool operator<(const Node& cmp) const { return true; }
write_stream(std::ostream & os) const124         std::ostream& write_stream(std::ostream& os) const
125         {
126             os << static_cast<int>(segment_);
127             return os;
128         }
read_stream(std::istream & is)129         std::istream& read_stream(std::istream& is)
130         {
131             int seg;
132             is >> seg;
133             segment_ = static_cast<SegmentId>(seg);
134             return is;
135         }
136     private:
137         SegmentId segment_;
138     };
139 
operator <<(std::ostream & os,const Node & n)140     inline std::ostream& operator<<(std::ostream& os, const Node& n)
141     {
142         return (os << static_cast<int>(n.segment()) );
143     }
144 
145 
146     class NodeList : public gcomm::Map<UUID, Node> { };
147 
148     class View
149     {
150     public:
151 
View()152         View() :
153             version_     (-1),
154             bootstrap_   (false),
155             view_id_     (V_NONE),
156             members_     (),
157             joined_      (),
158             left_        (),
159             partitioned_ ()
160         { }
161 
View(int version,const ViewId & view_id,bool bootstrap=false)162         View(int version, const ViewId& view_id, bool bootstrap = false) :
163             version_     (version),
164             bootstrap_   (bootstrap),
165             view_id_     (view_id),
166             members_     (),
167             joined_      (),
168             left_        (),
169             partitioned_ ()
170         { }
171 
~View()172         ~View() {}
173 
version() const174         int version() const { return version_; }
175 
176         void add_member  (const UUID& pid, SegmentId segment);
177 
178         void add_members (NodeList::const_iterator begin,
179                           NodeList::const_iterator end);
180 
181         void add_joined      (const UUID& pid, SegmentId segment);
182         void add_left        (const UUID& pid, SegmentId segment);
183         void add_partitioned (const UUID& pid, SegmentId segment);
184 
185         const NodeList& members     () const;
186         const NodeList& joined      () const;
187         const NodeList& left        () const;
188         const NodeList& partitioned () const;
189 
members()190         NodeList& members() { return members_; }
191 
is_member(const UUID & uuid) const192         bool is_member(const UUID& uuid) const
193         { return members_.find(uuid) != members_.end(); }
194 
is_joining(const UUID & uuid) const195         bool is_joining(const UUID& uuid) const
196         { return joined_.find(uuid) != joined_.end(); }
197 
is_leaving(const UUID & uuid) const198         bool is_leaving(const UUID& uuid) const
199         { return left_.find(uuid) != left_.end(); }
200 
is_partitioning(const UUID & uuid) const201         bool is_partitioning(const UUID& uuid) const
202         { return partitioned_.find(uuid) != partitioned_.end(); }
203 
204 
205         ViewType      type           () const;
206         const ViewId& id             () const;
207         const UUID&   representative () const;
208 
209         bool is_empty() const;
is_bootstrap() const210         bool is_bootstrap() const { return bootstrap_; }
211 
212         std::ostream& write_stream(std::ostream& os) const;
213         std::istream& read_stream(std::istream& is);
214     private:
215         int      version_;     // view protocol version, derived from evs group
216         bool     bootstrap_;   // Flag indicating if view was bootstrapped
217         ViewId   view_id_;     // View identifier
218         NodeList members_;     // List of members in view
219         NodeList joined_;      // List of newly joined members in view
220         NodeList left_;        // Fracefully left members from previous view
221         NodeList partitioned_; // Partitioned members from previous view
222     };
223 
224     bool operator==(const gcomm::View&, const gcomm::View&);
225     std::ostream& operator<<(std::ostream&, const View&);
226 
227     class ViewState
228     {
229     public:
ViewState(UUID & my_uuid,View & view,gu::Config & conf)230         ViewState(UUID& my_uuid, View& view, gu::Config& conf):
231                 my_uuid_(my_uuid),
232                 view_(view),
233                 file_name_(get_viewstate_file_name(conf))
234         { }
235         std::ostream& write_stream(std::ostream& os) const;
236         std::istream& read_stream(std::istream& is);
237         void write_file() const;
238         bool read_file();
239         static void remove_file(gu::Config& conf);
operator ==(const ViewState & vst) const240         bool operator== (const ViewState& vst) const
241         {
242             return my_uuid_ == vst.my_uuid_ &&
243                     view_ == vst.view_;
244         }
245     private:
246         UUID& my_uuid_;
247         View& view_;
248         std::string file_name_;
249 
250         static std::string get_viewstate_file_name(gu::Config& conf);
251     };
252 } // namespace gcomm
253 
254 #endif // _GCOMM_VIEW_HPP_
255