GCS  0.2.3
gcs_group.h
1 /*
2  * Copyright (C) 2008 Codership Oy <info@codership.com>
3  *
4  * $Id: gcs_group.h 3259 2013-09-01 22:35:30Z alex $
5  */
6 
7 /*
8  * This header defines node specific context we need to maintain
9  */
10 
11 #ifndef _gcs_group_h_
12 #define _gcs_group_h_
13 
14 #include <stdbool.h>
15 
16 #include <galerautils.h>
17 
18 #include "gcs_node.h"
19 #include "gcs_recv_msg.h"
20 #include "gcs_seqno.h"
21 #include "gcs_state_msg.h"
22 
23 #include <gcache.h>
24 
25 typedef enum gcs_group_state
26 {
27  GCS_GROUP_NON_PRIMARY,
28  GCS_GROUP_WAIT_STATE_UUID,
29  GCS_GROUP_WAIT_STATE_MSG,
30  GCS_GROUP_PRIMARY,
31  GCS_GROUP_STATE_MAX
32 }
33 gcs_group_state_t;
34 
35 extern const char* gcs_group_state_str[];
36 
37 typedef struct gcs_group
38 {
39  gcache_t* cache;
40  gcs_seqno_t act_id; // current(last) action seqno
41  gcs_seqno_t conf_id; // current configuration seqno
42  gu_uuid_t state_uuid; // state exchange id
43  gu_uuid_t group_uuid; // group UUID
44  long num; // number of nodes
45  long my_idx; // my index in the group
46  const char* my_name;
47  const char* my_address;
48  gcs_group_state_t state; // group state: PRIMARY | NON_PRIMARY
49  gcs_seqno_t last_applied; // last_applied action group-wide
50  long last_node; // node that reported last_applied
51  bool frag_reset; // indicate that fragmentation was reset
52  gcs_node_t* nodes; // array of node contexts
53 
54  /* values from the last primary component */
55  gu_uuid_t prim_uuid;
56  gu_seqno_t prim_seqno;
57  long prim_num;
58  gcs_node_state_t prim_state;
59 
60  /* max supported protocols */
61  gcs_proto_t const gcs_proto_ver;
62  int const repl_proto_ver;
63  int const appl_proto_ver;
64 
65  gcs_state_quorum_t quorum;
66  int last_applied_proto_ver;
67 }
69 
73 extern int
74 gcs_group_init (gcs_group_t* group,
75  gcache_t* cache,
76  const char* node_name,
77  const char* inc_addr,
78  gcs_proto_t gcs_proto_ver,
79  int repl_proto_ver,
80  int appl_proto_ver);
81 
85 extern int
86 gcs_group_init_history (gcs_group_t* group,
87  gcs_seqno_t seqno,
88  const gu_uuid_t* uuid);
89 
93 extern void
94 gcs_group_free (gcs_group_t* group);
95 
97 extern void
98 gcs_group_ignore_action (gcs_group_t* group, struct gcs_act_rcvd* rcvd);
99 
108 extern gcs_group_state_t
109 gcs_group_handle_comp_msg (gcs_group_t* group, const gcs_comp_msg_t* msg);
110 
111 extern gcs_group_state_t
112 gcs_group_handle_uuid_msg (gcs_group_t* group, const gcs_recv_msg_t* msg);
113 
114 extern gcs_group_state_t
115 gcs_group_handle_state_msg (gcs_group_t* group, const gcs_recv_msg_t* msg);
116 
117 extern gcs_seqno_t
118 gcs_group_handle_last_msg (gcs_group_t* group, const gcs_recv_msg_t* msg);
119 
122 extern int
123 gcs_group_handle_join_msg (gcs_group_t* group, const gcs_recv_msg_t* msg);
124 
127 extern int
128 gcs_group_handle_sync_msg (gcs_group_t* group, const gcs_recv_msg_t* msg);
129 
131 extern int
132 gcs_group_handle_state_request (gcs_group_t* group,
133  struct gcs_act_rcvd* act);
139 static inline ssize_t
140 gcs_group_handle_act_msg (gcs_group_t* const group,
141  const gcs_act_frag_t* const frg,
142  const gcs_recv_msg_t* const msg,
143  struct gcs_act_rcvd* const rcvd)
144 {
145  long const sender_idx = msg->sender_idx;
146  bool const local = (sender_idx == group->my_idx);
147  ssize_t ret;
148 
149  assert (GCS_MSG_ACTION == msg->type);
150  assert (sender_idx < group->num);
151  assert (frg->act_id > 0);
152  assert (frg->act_size > 0);
153 
154  // clear reset flag if set by own first fragment after reset flag was set
155  group->frag_reset = (group->frag_reset && (!local || (0 != frg->frag_no)));
156 
157  ret = gcs_node_handle_act_frag (&group->nodes[sender_idx], frg, &rcvd->act,
158  local);
159 
160  if (ret > 0) {
161 
162  assert (ret == rcvd->act.buf_len);
163 
164  rcvd->act.type = frg->act_type;
165 
166  if (gu_likely(GCS_ACT_TORDERED == rcvd->act.type &&
167  GCS_GROUP_PRIMARY == group->state &&
168  group->nodes[sender_idx].status >= GCS_NODE_STATE_DONOR &&
169  !(group->frag_reset && local))) {
170  /* Common situation -
171  * increment and assign act_id only for totally ordered actions
172  * and only in PRIM (skip messages while in state exchange) */
173  rcvd->id = ++group->act_id;
174  }
175  else if (GCS_ACT_TORDERED == rcvd->act.type) {
176  /* Rare situations */
177  if (local) {
178  /* Let the sender know that it failed */
179  rcvd->id = -ERESTART;
180  gu_debug("Returning -ERESTART for TORDERED action: group->state"
181  " = %s, sender->status = %s, frag_reset = %s, "
182  "buf = %p",
183  gcs_group_state_str[group->state],
184  gcs_node_state_to_str(group->nodes[sender_idx].status),
185  group->frag_reset ? "true" : "false", rcvd->act.buf);
186  }
187  else {
188  /* Just ignore it */
189  ret = 0;
190  gcs_group_ignore_action (group, rcvd);
191  }
192  }
193  }
194 
195  return ret;
196 }
197 
198 static inline gcs_group_state_t
199 gcs_group_state (gcs_group_t* group)
200 {
201  return group->state;
202 }
203 
204 static inline bool
205 gcs_group_is_primary (gcs_group_t* group)
206 {
207  return (GCS_GROUP_PRIMARY == group->state);
208 }
209 
210 static inline int
211 gcs_group_my_idx (gcs_group_t* group)
212 {
213  return group->my_idx;
214 }
215 
222 extern ssize_t
223 gcs_group_act_conf (gcs_group_t* group, struct gcs_act* act, int* proto);
224 
226 extern gcs_state_msg_t*
227 gcs_group_get_state (gcs_group_t* group);
228 
229 #endif /* _gcs_group_h_ */
Definition: gcs_group.h:37
Definition: gcs_node.h:27
const char * gcs_node_state_to_str(gcs_node_state_t state)
Definition: gcs.c:29
Definition: gcs_act.h:19
Definition: gcs_act_proto.h:24
Definition: gcs_recv_msg.h:16
Definition: gcs_act.h:12
Definition: gcs_state_msg.h:53