1 /*
2  * Copyright (C) 2008-2013 Codership Oy <info@codership.com>
3  *
4  * $Id$
5  */
6 /*
7  * Interface to membership messages - implementation
8  *
9  */
10 
11 #include <string.h>
12 #include <errno.h>
13 #include <stddef.h>
14 #include <galerautils.h>
15 
16 #define   GCS_COMP_MSG_ACCESS
17 #include "gcs_comp_msg.hpp"
18 
19 static inline int
comp_msg_size(int memb_num)20 comp_msg_size (int memb_num)
21 { return (sizeof(gcs_comp_msg_t) + memb_num * sizeof(gcs_comp_memb_t)); }
22 
23 /*! Allocates membership object and zeroes it */
24 gcs_comp_msg_t*
gcs_comp_msg_new(bool prim,bool bootstrap,int my_idx,int memb_num,int error)25 gcs_comp_msg_new (bool prim, bool bootstrap, int my_idx, int memb_num, int error)
26 {
27     gcs_comp_msg_t* ret;
28 
29     assert ((memb_num > 0 && my_idx >= 0) || (memb_num == 0 && my_idx == -1));
30 
31     ret = static_cast<gcs_comp_msg_t*>(gu_calloc (1, comp_msg_size(memb_num)));
32 
33     if (NULL != ret) {
34         ret->primary   = prim;
35         ret->bootstrap = bootstrap;
36         ret->my_idx    = my_idx;
37         ret->memb_num  = memb_num;
38         ret->error     = error;
39     }
40 
41     return ret;
42 }
43 
44 gcs_comp_msg_t*
gcs_comp_msg_leave(int error)45 gcs_comp_msg_leave (int error)
46 {
47     return gcs_comp_msg_new (false, false, -1, 0, error);
48 }
49 
50 /*! Destroys component message */
51 void
gcs_comp_msg_delete(gcs_comp_msg_t * comp)52 gcs_comp_msg_delete (gcs_comp_msg_t* comp)
53 {
54     gu_free (comp);
55 }
56 
57 /*! Returns total size of the component message */
58 int
gcs_comp_msg_size(const gcs_comp_msg_t * comp)59 gcs_comp_msg_size   (const gcs_comp_msg_t* comp)
60 {
61     assert (comp);
62     return comp_msg_size (comp->memb_num);
63 }
64 
65 /*! Adds a member to the component message
66  *  Returns an index of the member or negative error code */
67 int
gcs_comp_msg_add(gcs_comp_msg_t * comp,const char * id,gcs_segment_t const segment)68 gcs_comp_msg_add (gcs_comp_msg_t* comp, const char* id,
69                   gcs_segment_t const segment)
70 {
71     size_t id_len;
72     int    i;
73 
74     assert (comp);
75     assert (id);
76 
77     /* check id length */
78     id_len = strlen (id);
79     if (!id_len) return -EINVAL;
80     if (id_len > GCS_COMP_MEMB_ID_MAX_LEN) return -ENAMETOOLONG;
81 
82     int free_slot = -1;
83 
84     /* find the free id slot and check for id uniqueness */
85     for (i = 0; i < comp->memb_num; i++) {
86         if (0 == comp->memb[i].id[0] && free_slot < 0) free_slot = i;
87         if (0 == strcmp (comp->memb[i].id, id)) return -ENOTUNIQ;
88     }
89 
90     if (free_slot < 0) return -1;
91 
92     memcpy (comp->memb[free_slot].id, id, id_len);
93     comp->memb[free_slot].segment = segment;
94 
95     return free_slot;
96 }
97 
98 /*! Creates a copy of the component message */
99 gcs_comp_msg_t*
gcs_comp_msg_copy(const gcs_comp_msg_t * comp)100 gcs_comp_msg_copy   (const gcs_comp_msg_t* comp)
101 {
102     size_t size         = gcs_comp_msg_size(comp);
103     gcs_comp_msg_t* ret = static_cast<gcs_comp_msg_t*>(gu_malloc (size));
104 
105     if (ret) memcpy (ret, comp, size);
106 
107     return ret;
108 }
109 
110 /*! Returns member ID by index, NULL if none */
111 const gcs_comp_memb_t*
gcs_comp_msg_member(const gcs_comp_msg_t * comp,int idx)112 gcs_comp_msg_member (const gcs_comp_msg_t* comp, int idx)
113 {
114     if (0 <= idx && idx < comp->memb_num)
115         return &comp->memb[idx];
116     else
117         return NULL;
118 }
119 
120 /*! Returns member index by ID, -1 if none */
121 int
gcs_comp_msg_idx(const gcs_comp_msg_t * comp,const char * id)122 gcs_comp_msg_idx (const gcs_comp_msg_t* comp, const char* id)
123 {
124     size_t id_len = strlen(id);
125     int    idx = comp->memb_num;
126 
127     if (id_len > 0 && id_len <= GCS_COMP_MEMB_ID_MAX_LEN)
128         for (idx = 0; idx < comp->memb_num; idx++)
129             if (0 == strcmp (comp->memb[idx].id, id)) break;
130 
131     if (comp->memb_num == idx)
132         return -1;
133     else
134         return idx;
135 }
136 
137 /*! Returns primary status of the component */
138 bool
gcs_comp_msg_primary(const gcs_comp_msg_t * comp)139 gcs_comp_msg_primary (const gcs_comp_msg_t* comp)
140 {
141     return comp->primary;
142 }
143 
144 /*! Retruns bootstrap flag of the component */
145 bool
gcs_comp_msg_bootstrap(const gcs_comp_msg_t * comp)146 gcs_comp_msg_bootstrap(const gcs_comp_msg_t* comp)
147 {
148     return comp->bootstrap;
149 }
150 
151 /*! Returns our own index in the membership */
152 int
gcs_comp_msg_self(const gcs_comp_msg_t * comp)153 gcs_comp_msg_self   (const gcs_comp_msg_t* comp)
154 {
155     return comp->my_idx;
156 }
157 
158 /*! Returns number of members in the component */
159 int
gcs_comp_msg_num(const gcs_comp_msg_t * comp)160 gcs_comp_msg_num    (const gcs_comp_msg_t* comp)
161 {
162     return comp->memb_num;
163 }
164 
165 
gcs_comp_msg_error(const gcs_comp_msg_t * comp)166 int gcs_comp_msg_error(const gcs_comp_msg_t* comp)
167 {
168     return comp->error;
169 }
170