1 // Copyright (C) 2007-2020 Codership Oy <info@codership.com>
2
3 // $Id$
4
5 #define GCS_STATE_MSG_ACCESS
6 #include "../gcs_state_msg.hpp"
7
8 #include "gcs_state_msg_test.hpp" // must be included last
9 #include "gu_inttypes.hpp"
10
11 static int const QUORUM_VERSION = 6;
12
START_TEST(gcs_state_msg_test_basic)13 START_TEST (gcs_state_msg_test_basic)
14 {
15 ssize_t send_len, ret;
16 gu_uuid_t state_uuid;
17 gu_uuid_t group_uuid;
18 gu_uuid_t prim_uuid;
19 gcs_state_msg_t* send_state;
20 gcs_state_msg_t* recv_state;
21
22 gu_uuid_generate (&state_uuid, NULL, 0);
23 gu_uuid_generate (&group_uuid, NULL, 0);
24 gu_uuid_generate (&prim_uuid, NULL, 0);
25
26 gcs_seqno_t const prim_seqno(457);
27 gcs_seqno_t const received(3456);
28 gcs_seqno_t const cached(2345);
29 gcs_seqno_t const last_applied(3450);
30 gcs_seqno_t const vote_seqno(3449);
31 int64_t const vote_res(0x1244567879012345ULL);
32 int const vote_policy(0);
33 int const prim_joined(5);
34 gcs_node_state_t const prim_state(GCS_NODE_STATE_JOINED);
35 gcs_node_state_t const current_state(GCS_NODE_STATE_NON_PRIM);
36 const char* const name("MyName");
37 const char* const inc_addr("192.168.0.1:2345");
38 int const gcs_proto_ver(2);
39 int const repl_proto_ver(1);
40 int const appl_proto_ver(2);
41 int const prim_gcs_ver(0);
42 int const prim_repl_ver(1);
43 int const prim_appl_ver(1);
44 int const desync_count(0);
45 int const flags(GCS_STATE_FREP);
46
47 send_state = gcs_state_msg_create (&state_uuid,
48 &group_uuid,
49 &prim_uuid,
50 prim_seqno,
51 received, // last received seqno
52 cached, // last cached seqno
53 last_applied, // last applied
54 vote_seqno, // last vote seqno
55 vote_res, // last vote result
56 vote_policy, // voting protocol
57 prim_joined, // prim_joined
58 prim_state, // prim_state
59 current_state, // current_state
60 name, // name
61 inc_addr, // inc_addr
62 gcs_proto_ver, // gcs_proto_ver
63 repl_proto_ver, // repl_proto_ver
64 appl_proto_ver, // appl_proto_ver
65 prim_gcs_ver, // prim_gcs_ver
66 prim_repl_ver, // prim_repl_ver
67 prim_appl_ver, // prim_appl_ver
68 desync_count, // desync_count
69 flags // flags
70 );
71
72 ck_assert(NULL != send_state);
73
74 ck_assert(send_state->flags == flags);
75 ck_assert(send_state->gcs_proto_ver == gcs_proto_ver);
76 ck_assert(send_state->repl_proto_ver == repl_proto_ver);
77 ck_assert(send_state->appl_proto_ver == appl_proto_ver);
78 ck_assert_msg(send_state->received == received,
79 "Last received seqno: sent %" PRId64 ", recv %" PRId64,
80 send_state->received, received);
81 ck_assert_msg(send_state->cached == cached,
82 "Last cached seqno: sent %" PRId64 ", recv %" PRId64,
83 send_state->cached, cached);
84 ck_assert(send_state->prim_seqno == prim_seqno);
85 ck_assert(send_state->current_state == current_state);
86 ck_assert(send_state->prim_state == prim_state);
87 ck_assert(send_state->prim_joined == prim_joined);
88 ck_assert(!gu_uuid_compare (&send_state->state_uuid, &state_uuid));
89 ck_assert(!gu_uuid_compare (&send_state->group_uuid, &group_uuid));
90 ck_assert(!gu_uuid_compare (&send_state->prim_uuid, &prim_uuid));
91 ck_assert(!strcmp(send_state->name, name));
92 ck_assert(!strcmp(send_state->inc_addr, inc_addr));
93
94 {
95 size_t str_len = 1024;
96 char send_str[str_len];
97 ck_assert(gcs_state_msg_snprintf(send_str, str_len, send_state) > 0);
98 }
99
100 //v1-2
101 ck_assert(send_state->appl_proto_ver == appl_proto_ver);
102 //v3
103 ck_assert(send_state->cached == cached);
104 //v4
105 ck_assert(send_state->desync_count == desync_count);
106 //v5
107 ck_assert(send_state->last_applied == last_applied);
108 ck_assert(send_state->vote_seqno == vote_seqno);
109 ck_assert(send_state->vote_res == vote_res);
110 ck_assert(send_state->vote_policy == vote_policy);
111
112 send_len = gcs_state_msg_len (send_state);
113 ck_assert_msg(send_len >= 0, "gcs_state_msg_len() returned %zd (%s)",
114 send_len, strerror (-send_len));
115 {
116 uint8_t send_buf[send_len];
117
118 ret = gcs_state_msg_write (send_buf, send_state);
119 ck_assert_msg(ret == send_len, "Return value does not match send_len: "
120 "expected %zd, got %zd", send_len, ret);
121
122 recv_state = gcs_state_msg_read (send_buf, send_len);
123 ck_assert(NULL != recv_state);
124 }
125
126 ck_assert(send_state->flags == recv_state->flags);
127 ck_assert(send_state->gcs_proto_ver == recv_state->gcs_proto_ver);
128 ck_assert(send_state->repl_proto_ver == recv_state->repl_proto_ver);
129 ck_assert_msg(recv_state->repl_proto_ver == 1, "repl_proto_ver: %d",
130 recv_state->repl_proto_ver);
131 ck_assert(send_state->appl_proto_ver == recv_state->appl_proto_ver);
132 ck_assert_msg(recv_state->appl_proto_ver == 2, "appl_proto_ver: %d",
133 recv_state->appl_proto_ver);
134 ck_assert(send_state->prim_gcs_ver == recv_state->prim_gcs_ver);
135 ck_assert_msg(recv_state->prim_gcs_ver == 0, "prim_gcs_ver: %d",
136 recv_state->prim_appl_ver);
137 ck_assert(send_state->prim_repl_ver == recv_state->prim_repl_ver);
138 ck_assert_msg(recv_state->prim_repl_ver == 1, "prim_repl_ver: %d",
139 recv_state->prim_appl_ver);
140 ck_assert(send_state->prim_appl_ver == recv_state->prim_appl_ver);
141 ck_assert_msg(recv_state->prim_appl_ver == 1, "prim_appl_ver: %d",
142 recv_state->prim_appl_ver);
143 ck_assert_msg(send_state->received == recv_state->received,
144 "Last received seqno: sent %" PRId64 " , recv %" PRId64,
145 send_state->received, recv_state->received);
146 ck_assert_msg(send_state->cached == recv_state->cached,
147 "Last cached seqno: sent %" PRId64 ", recv %" PRId64,
148 send_state->cached, recv_state->cached);
149 ck_assert(send_state->prim_seqno == recv_state->prim_seqno);
150 ck_assert(send_state->current_state == recv_state->current_state);
151 ck_assert(send_state->prim_state == recv_state->prim_state);
152 ck_assert(send_state->prim_joined == recv_state->prim_joined);
153 ck_assert(!gu_uuid_compare(&recv_state->state_uuid, &state_uuid));
154 ck_assert(!gu_uuid_compare(&recv_state->group_uuid, &group_uuid));
155 ck_assert(!gu_uuid_compare(&recv_state->prim_uuid, &prim_uuid));
156 ck_assert(!strcmp(send_state->name, recv_state->name));
157 ck_assert(!strcmp(send_state->inc_addr, recv_state->inc_addr));
158
159 {
160 size_t str_len = 1024;
161 char str[str_len];
162
163 ck_assert(gcs_state_msg_snprintf(str, str_len, send_state) > 0);
164 ck_assert(gcs_state_msg_snprintf(str, str_len, recv_state) > 0);
165 }
166
167 //v1-2
168 ck_assert(send_state->appl_proto_ver == recv_state->appl_proto_ver);
169 //v3
170 ck_assert(send_state->cached == recv_state->cached);
171 //v4
172 ck_assert(send_state->desync_count == recv_state->desync_count);
173 //v5
174 ck_assert(send_state->last_applied == recv_state->last_applied);
175 ck_assert(send_state->vote_seqno == recv_state->vote_seqno);
176 ck_assert(send_state->vote_res == recv_state->vote_res);
177 ck_assert(send_state->vote_policy == recv_state->vote_policy);
178
179 gcs_state_msg_destroy (send_state);
180 gcs_state_msg_destroy (recv_state);
181 }
182 END_TEST
183
START_TEST(gcs_state_msg_test_quorum_inherit)184 START_TEST (gcs_state_msg_test_quorum_inherit)
185 {
186 gcs_state_msg_t* st[3] = { NULL, };
187
188 gu_uuid_t state_uuid;
189 gu_uuid_t group1_uuid, group2_uuid;
190 gu_uuid_t prim1_uuid, prim2_uuid;
191
192 gu_uuid_generate (&state_uuid, NULL, 0);
193 gu_uuid_generate (&group1_uuid, NULL, 0);
194 gu_uuid_generate (&group2_uuid, NULL, 0);
195 gu_uuid_generate (&prim1_uuid, NULL, 0);
196 gu_uuid_generate (&prim2_uuid, NULL, 0);
197
198 gcs_seqno_t prim1_seqno = 123;
199 gcs_seqno_t prim2_seqno = 834;
200
201 gcs_seqno_t act1_seqno = 345;
202 gcs_seqno_t act2_seqno = 239472508908LL;
203
204 gcs_state_quorum_t quorum;
205
206 mark_point();
207
208 /* First just nodes from different groups and configurations, none JOINED */
209 st[0] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim2_uuid,
210 prim2_seqno - 1, act2_seqno - 1, act2_seqno -1,
211 act2_seqno - 1, GCS_SEQNO_ILL, 0,
212 GCS_VOTE_ZERO_WINS, 5,
213 GCS_NODE_STATE_PRIM, GCS_NODE_STATE_PRIM,
214 "node0", "",
215 0, 1, 1, 0, 0, 0,
216 0, 0);
217 ck_assert(NULL != st[0]);
218
219 st[1] = gcs_state_msg_create (&state_uuid, &group1_uuid, &prim1_uuid,
220 prim1_seqno, act1_seqno, act1_seqno - 1,
221 act1_seqno - 1, GCS_SEQNO_ILL, 0,
222 GCS_VOTE_ZERO_WINS, 3,
223 GCS_NODE_STATE_PRIM, GCS_NODE_STATE_PRIM,
224 "node1", "",
225 0, 1, 0, 0, 0, 0,
226 0, 0);
227 ck_assert(NULL != st[1]);
228
229 st[2] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim2_uuid,
230 prim2_seqno, act2_seqno, act2_seqno - 2,
231 act2_seqno - 1, GCS_SEQNO_ILL, 0,
232 GCS_VOTE_ZERO_WINS, 5,
233 GCS_NODE_STATE_PRIM, GCS_NODE_STATE_PRIM,
234 "node2", "",
235 0, 1, 1, 0, 0, 0,
236 0, 1);
237 ck_assert(NULL != st[2]);
238
239 gu_info (" Inherited 1");
240 int ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
241 sizeof(st)/sizeof(gcs_state_msg_t*),
242 &quorum);
243 ck_assert(0 == ret);
244 ck_assert(QUORUM_VERSION == quorum.version);
245 ck_assert(false == quorum.primary);
246 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &GU_UUID_NIL));
247 ck_assert(GCS_SEQNO_ILL == quorum.act_id);
248 ck_assert(GCS_SEQNO_ILL == quorum.conf_id);
249 ck_assert(-1 == quorum.gcs_proto_ver);
250 ck_assert(-1 == quorum.repl_proto_ver);
251 ck_assert(-1 == quorum.appl_proto_ver);
252
253 /* now make node1 inherit PC */
254 gcs_state_msg_destroy (st[1]);
255 st[1] = gcs_state_msg_create (&state_uuid, &group1_uuid, &prim1_uuid,
256 prim1_seqno, act1_seqno, act1_seqno - 3,
257 act1_seqno - 2, GCS_SEQNO_ILL, 0,
258 GCS_VOTE_ZERO_WINS, 3,
259 GCS_NODE_STATE_JOINED, GCS_NODE_STATE_DONOR,
260 "node1", "",
261 0, 1, 0, 0, 0, 0,
262 0, 0);
263 ck_assert(NULL != st[1]);
264
265 gu_info (" Inherited 2");
266 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
267 sizeof(st)/sizeof(gcs_state_msg_t*),
268 &quorum);
269 ck_assert(0 == ret);
270 ck_assert(QUORUM_VERSION == quorum.version);
271 ck_assert(true == quorum.primary);
272 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group1_uuid));
273 ck_assert(act1_seqno == quorum.act_id);
274 ck_assert(prim1_seqno == quorum.conf_id);
275 ck_assert(0 == quorum.gcs_proto_ver);
276 ck_assert(1 == quorum.repl_proto_ver);
277 ck_assert(0 == quorum.appl_proto_ver);
278
279 /* now make node0 inherit PC (should yield conflicting uuids) */
280 gcs_state_msg_destroy (st[0]);
281 st[0] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim2_uuid,
282 prim2_seqno - 1, act2_seqno - 1, -1,
283 act2_seqno - 1, GCS_SEQNO_ILL, 0,
284 GCS_VOTE_ZERO_WINS, 5,
285 GCS_NODE_STATE_SYNCED, GCS_NODE_STATE_SYNCED,
286 "node0", "",
287 0, 1, 1, 0, 0, 0,
288 0, 0);
289 ck_assert(NULL != st[0]);
290
291 gu_info (" Inherited 3");
292 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
293 sizeof(st)/sizeof(gcs_state_msg_t*),
294 &quorum);
295 ck_assert(0 == ret);
296 ck_assert(QUORUM_VERSION == quorum.version);
297 ck_assert(false == quorum.primary);
298 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &GU_UUID_NIL));
299 ck_assert(GCS_SEQNO_ILL == quorum.act_id);
300 ck_assert(GCS_SEQNO_ILL == quorum.conf_id);
301 ck_assert(-1 == quorum.gcs_proto_ver);
302 ck_assert(-1 == quorum.repl_proto_ver);
303 ck_assert(-1 == quorum.appl_proto_ver);
304
305 /* now make node1 non-joined again: group2 should win */
306 gcs_state_msg_destroy (st[1]);
307 st[1] = gcs_state_msg_create (&state_uuid, &group1_uuid, &prim1_uuid,
308 prim1_seqno, act1_seqno, act1_seqno -3,
309 act1_seqno - 1, GCS_SEQNO_ILL, 0,
310 GCS_VOTE_ZERO_WINS, 3,
311 GCS_NODE_STATE_JOINED, GCS_NODE_STATE_PRIM,
312 "node1", "",
313 0, 1, 0, 0, 0, 0,
314 0, 0);
315 ck_assert(NULL != st[1]);
316
317 gu_info (" Inherited 4");
318 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
319 sizeof(st)/sizeof(gcs_state_msg_t*),
320 &quorum);
321 ck_assert(0 == ret);
322 ck_assert(QUORUM_VERSION == quorum.version);
323 ck_assert(true == quorum.primary);
324 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group2_uuid));
325 ck_assert(act2_seqno - 1 == quorum.act_id);
326 ck_assert(prim2_seqno - 1 == quorum.conf_id);
327 ck_assert(0 == quorum.gcs_proto_ver);
328 ck_assert(1 == quorum.repl_proto_ver);
329 ck_assert(0 == quorum.appl_proto_ver);
330
331 /* now make node2 joined: it should become a representative */
332 gcs_state_msg_destroy (st[2]);
333 st[2] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim2_uuid,
334 prim2_seqno, act2_seqno, act2_seqno - 2,
335 act2_seqno - 1, GCS_SEQNO_ILL, 0,
336 GCS_VOTE_ZERO_WINS, 5,
337 GCS_NODE_STATE_SYNCED, GCS_NODE_STATE_SYNCED,
338 "node2", "",
339 0, 1, 1, 0, 1, 0,
340 0, 0);
341 ck_assert(NULL != st[2]);
342
343 gu_info (" Inherited 5");
344 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
345 sizeof(st)/sizeof(gcs_state_msg_t*),
346 &quorum);
347 ck_assert(0 == ret);
348 ck_assert(QUORUM_VERSION == quorum.version);
349 ck_assert(true == quorum.primary);
350 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group2_uuid));
351 ck_assert(act2_seqno == quorum.act_id);
352 ck_assert(prim2_seqno == quorum.conf_id);
353 ck_assert(0 == quorum.gcs_proto_ver);
354 ck_assert(1 == quorum.repl_proto_ver);
355 ck_assert(0 == quorum.appl_proto_ver);
356
357 gcs_state_msg_destroy (st[0]);
358 gcs_state_msg_destroy (st[1]);
359 gcs_state_msg_destroy (st[2]);
360 }
361 END_TEST
362
START_TEST(gcs_state_msg_test_quorum_remerge)363 START_TEST (gcs_state_msg_test_quorum_remerge)
364 {
365 gcs_state_msg_t* st[3] = { NULL, };
366
367 gu_uuid_t state_uuid;
368 gu_uuid_t group1_uuid, group2_uuid;
369 gu_uuid_t prim0_uuid, prim1_uuid, prim2_uuid;
370
371 gu_uuid_generate (&state_uuid, NULL, 0);
372 gu_uuid_generate (&group1_uuid, NULL, 0);
373 gu_uuid_generate (&group2_uuid, NULL, 0);
374 gu_uuid_generate (&prim0_uuid, NULL, 0);
375 gu_uuid_generate (&prim1_uuid, NULL, 0);
376 gu_uuid_generate (&prim2_uuid, NULL, 0);
377
378 gcs_seqno_t prim1_seqno = 123;
379 gcs_seqno_t prim2_seqno = 834;
380
381 gcs_seqno_t act1_seqno = 345;
382 gcs_seqno_t act2_seqno = 239472508908LL;
383
384 gcs_state_quorum_t quorum;
385
386 mark_point();
387
388 /* First just nodes from different groups and configurations, none JOINED */
389 st[0] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim0_uuid,
390 prim2_seqno - 1, act2_seqno - 1,act2_seqno -2,
391 act2_seqno - 1, GCS_SEQNO_ILL, 0,
392 GCS_VOTE_ZERO_WINS, 5,
393 GCS_NODE_STATE_JOINER,GCS_NODE_STATE_NON_PRIM,
394 "node0", "",
395 0, 1, 1, 0, 0, 0,
396 0, 0);
397 ck_assert(NULL != st[0]);
398
399 st[1] = gcs_state_msg_create (&state_uuid, &group1_uuid, &prim1_uuid,
400 prim1_seqno, act1_seqno, act1_seqno - 3,
401 act1_seqno - 2, GCS_SEQNO_ILL, 0,
402 GCS_VOTE_ZERO_WINS, 3,
403 GCS_NODE_STATE_JOINER,GCS_NODE_STATE_NON_PRIM,
404 "node1", "",
405 0, 1, 0, 0, 0, 0,
406 0, 0);
407 ck_assert(NULL != st[1]);
408
409 st[2] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim2_uuid,
410 prim2_seqno, act2_seqno, -1,
411 act2_seqno - 1, GCS_SEQNO_ILL, 0,
412 GCS_VOTE_ZERO_WINS, 5,
413 GCS_NODE_STATE_JOINER,GCS_NODE_STATE_NON_PRIM,
414 "node2", "",
415 0, 1, 1, 0, 0, 0,
416 0, 1);
417 ck_assert(NULL != st[2]);
418
419 gu_info (" Remerged 1");
420 int ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
421 sizeof(st)/sizeof(gcs_state_msg_t*),
422 &quorum);
423 ck_assert(0 == ret);
424 ck_assert(QUORUM_VERSION == quorum.version);
425 ck_assert(false == quorum.primary);
426 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &GU_UUID_NIL));
427 ck_assert(GCS_SEQNO_ILL == quorum.act_id);
428 ck_assert(GCS_SEQNO_ILL == quorum.conf_id);
429 ck_assert(-1 == quorum.gcs_proto_ver);
430 ck_assert(-1 == quorum.repl_proto_ver);
431 ck_assert(-1 == quorum.appl_proto_ver);
432
433 /* Now make node0 to be joined at least once */
434 gcs_state_msg_destroy (st[0]);
435 st[0] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim0_uuid,
436 prim2_seqno - 1, act2_seqno - 1, -1,
437 act2_seqno - 1, GCS_SEQNO_ILL, 0,
438 GCS_VOTE_ZERO_WINS, 5,
439 GCS_NODE_STATE_DONOR, GCS_NODE_STATE_NON_PRIM,
440 "node0", "",
441 0, 1, 1, 0, 0, 0,
442 3, 0);
443 ck_assert(NULL != st[0]);
444 ck_assert(3 == gcs_state_msg_get_desync_count(st[0]));
445
446 gu_info (" Remerged 2");
447 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
448 sizeof(st)/sizeof(gcs_state_msg_t*),
449 &quorum);
450 ck_assert(0 == ret);
451 ck_assert(QUORUM_VERSION == quorum.version);
452 ck_assert(true == quorum.primary);
453 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group2_uuid));
454 ck_assert(act2_seqno - 1 == quorum.act_id);
455 ck_assert(prim2_seqno - 1 == quorum.conf_id);
456 ck_assert(0 == quorum.gcs_proto_ver);
457 ck_assert(1 == quorum.repl_proto_ver);
458 ck_assert(0 == quorum.appl_proto_ver);
459
460 /* Now make node2 to be joined too */
461 gcs_state_msg_destroy (st[2]);
462 st[2] = gcs_state_msg_create (&state_uuid, &group2_uuid, &prim2_uuid,
463 prim2_seqno, act2_seqno, act2_seqno - 3,
464 act2_seqno - 1, GCS_SEQNO_ILL, 0,
465 GCS_VOTE_ZERO_WINS, 5,
466 GCS_NODE_STATE_JOINED,GCS_NODE_STATE_NON_PRIM,
467 "node2", "",
468 0, 1, 1, 0, 0, 0,
469 0, 1);
470 ck_assert(NULL != st[2]);
471
472 gu_info (" Remerged 3");
473 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
474 sizeof(st)/sizeof(gcs_state_msg_t*),
475 &quorum);
476 ck_assert(0 == ret);
477 ck_assert(QUORUM_VERSION == quorum.version);
478 ck_assert(true == quorum.primary);
479 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group2_uuid));
480 ck_assert(act2_seqno == quorum.act_id);
481 ck_assert(prim2_seqno == quorum.conf_id);
482 ck_assert(0 == quorum.gcs_proto_ver);
483 ck_assert(1 == quorum.repl_proto_ver);
484 ck_assert(0 == quorum.appl_proto_ver);
485
486 /* now make node1 joined too: conflict */
487 gcs_state_msg_destroy (st[1]);
488 st[1] = gcs_state_msg_create (&state_uuid, &group1_uuid, &prim1_uuid,
489 prim1_seqno, act1_seqno, act1_seqno,
490 act1_seqno - 1, GCS_SEQNO_ILL, 0,
491 GCS_VOTE_ZERO_WINS, 3,
492 GCS_NODE_STATE_SYNCED,GCS_NODE_STATE_NON_PRIM,
493 "node1", "",
494 0, 1, 0, 0, 0, 0,
495 0, 0);
496 ck_assert(NULL != st[1]);
497
498 gu_info (" Remerged 4");
499 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
500 sizeof(st)/sizeof(gcs_state_msg_t*),
501 &quorum);
502 ck_assert(0 == ret);
503 ck_assert(QUORUM_VERSION == quorum.version);
504 ck_assert(false == quorum.primary);
505 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &GU_UUID_NIL));
506 ck_assert(GCS_SEQNO_ILL == quorum.act_id);
507 ck_assert(GCS_SEQNO_ILL == quorum.conf_id);
508 ck_assert(-1 == quorum.gcs_proto_ver);
509 ck_assert(-1 == quorum.repl_proto_ver);
510 ck_assert(-1 == quorum.appl_proto_ver);
511
512 /* now make node1 current joiner: should be ignored */
513 gcs_state_msg_destroy (st[1]);
514 st[1] = gcs_state_msg_create (&state_uuid, &group1_uuid, &prim1_uuid,
515 prim1_seqno, act1_seqno, act1_seqno - 2,
516 act1_seqno - 1, GCS_SEQNO_ILL, 0,
517 GCS_VOTE_ZERO_WINS, 3,
518 GCS_NODE_STATE_SYNCED, GCS_NODE_STATE_JOINER,
519 "node1", "",
520 0, 1, 0, 0, 0, 0,
521 0, 0);
522 ck_assert(NULL != st[1]);
523
524 gu_info (" Remerged 5");
525 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
526 sizeof(st)/sizeof(gcs_state_msg_t*),
527 &quorum);
528 ck_assert(0 == ret);
529 ck_assert(QUORUM_VERSION == quorum.version);
530 ck_assert(true == quorum.primary);
531 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group2_uuid));
532 ck_assert(act2_seqno == quorum.act_id);
533 ck_assert(prim2_seqno == quorum.conf_id);
534 ck_assert(0 == quorum.gcs_proto_ver);
535 ck_assert(1 == quorum.repl_proto_ver);
536 ck_assert(0 == quorum.appl_proto_ver);
537
538 gcs_state_msg_destroy (st[0]);
539 gcs_state_msg_destroy (st[1]);
540 gcs_state_msg_destroy (st[2]);
541 }
542 END_TEST
543
gcs_state_msg_test_gh24(int const gcs_proto_ver)544 void gcs_state_msg_test_gh24(int const gcs_proto_ver)
545 {
546 gcs_state_msg_t* st[7] = { NULL, };
547 gu_uuid_t state_uuid, group_uuid;
548 gu_uuid_generate(&state_uuid, NULL, 0);
549 gu_uuid_generate(&group_uuid, NULL, 0);
550 gu_uuid_t prim_uuid1, prim_uuid2;
551 gu_uuid_generate(&prim_uuid1, NULL, 0);
552 gu_uuid_generate(&prim_uuid2, NULL, 0);
553
554 gcs_seqno_t const prim_seqno1 = 37;
555 int const prim_joined1 = 3;
556 uint8_t const vp1(0);
557 gcs_seqno_t const prim_seqno2 = 35;
558 int const prim_joined2 = 6;
559 uint8_t const vp2(2);
560 gcs_seqno_t const received = prim_seqno2;
561 gcs_seqno_t const cached = 0;
562
563 gcs_state_quorum_t quorum;
564 // first three are 35.
565 st[0] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid2,
566 prim_seqno2, received, cached,
567 received - 7, GCS_SEQNO_ILL, 0, vp2,
568 prim_joined2,
569 GCS_NODE_STATE_SYNCED,
570 GCS_NODE_STATE_NON_PRIM,
571 "home0", "",
572 gcs_proto_ver, 4, 2, 0, 0, 0,
573 0, 2);
574 ck_assert(st[0] != 0);
575 ck_assert(gcs_state_msg_vote_policy(st[0]) == vp2);
576 st[1] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid2,
577 prim_seqno2, received, cached,
578 received - 11, GCS_SEQNO_ILL, 0, vp2,
579 prim_joined2,
580 GCS_NODE_STATE_SYNCED,
581 GCS_NODE_STATE_NON_PRIM,
582 "home1", "",
583 gcs_proto_ver, 4, 2, 0, 0, 0,
584 0, 2);
585 ck_assert(st[1] != 0);
586 st[2] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid2,
587 prim_seqno2, received, cached,
588 received - 5, GCS_SEQNO_ILL, 0, vp2,
589 prim_joined2,
590 GCS_NODE_STATE_SYNCED,
591 GCS_NODE_STATE_NON_PRIM,
592 "home2", "",
593 gcs_proto_ver, 4, 2, 0, 0, 0,
594 0, 2);
595 ck_assert(st[2] != 0);
596
597 // last four are 37.
598 st[3] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid1,
599 prim_seqno1, received, cached,
600 received - 8, GCS_SEQNO_ILL, 0, vp1,
601 prim_joined1,
602 GCS_NODE_STATE_SYNCED,
603 GCS_NODE_STATE_NON_PRIM,
604 "home3", "",
605 gcs_proto_ver, 4, 2, 0, 0, 0,
606 0, 3);
607 ck_assert(st[3] != 0);
608 ck_assert(gcs_state_msg_vote_policy(st[3]) == vp1);
609 st[4] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid1,
610 prim_seqno1, received, cached,
611 received - 3, GCS_SEQNO_ILL, 0, vp1,
612 prim_joined1,
613 GCS_NODE_STATE_SYNCED,
614 GCS_NODE_STATE_NON_PRIM,
615 "home4", "",
616 gcs_proto_ver, 4, 2, 0, 0, 0,
617 0, 2);
618 ck_assert(st[4] != 0);
619 st[5] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid1,
620 prim_seqno1, received, cached,
621 received - 10, GCS_SEQNO_ILL, 0, vp1,
622 prim_joined1,
623 GCS_NODE_STATE_SYNCED,
624 GCS_NODE_STATE_NON_PRIM,
625 "home5", "",
626 gcs_proto_ver, 4, 2, 0, 0, 0,
627 0, 2);
628 ck_assert(st[5] != 0);
629 st[6] = gcs_state_msg_create(&state_uuid, &group_uuid, &prim_uuid1,
630 prim_seqno1, received, cached,
631 received - 13, GCS_SEQNO_ILL, 0, vp1,
632 prim_joined1,
633 GCS_NODE_STATE_PRIM,
634 GCS_NODE_STATE_NON_PRIM,
635 "home6", "",
636 gcs_proto_ver, 4, 2, 0, 0, 0,
637 0, 2);
638 ck_assert(st[6] != 0);
639 int ret = gcs_state_msg_get_quorum((const gcs_state_msg_t**)st, 7,
640 &quorum);
641 ck_assert(ret == 0);
642 ck_assert(quorum.primary == true);
643 ck_assert(quorum.conf_id == prim_seqno1);
644 switch (gcs_proto_ver)
645 {
646 case 0:
647 ck_assert_msg(quorum.vote_policy == GCS_VOTE_ZERO_WINS,
648 "found policy %d, expected %d", quorum.vote_policy,
649 GCS_VOTE_ZERO_WINS);
650 break;
651 case 1:
652 ck_assert_msg(quorum.vote_policy == vp1,
653 "found policy %d, expected %d", quorum.vote_policy, vp1);
654 break;
655 default:
656 ck_abort_msg("unsupported GCS protocol: %d", gcs_proto_ver);
657 }
658
659 for(int i=0;i<7;i++) gcs_state_msg_destroy(st[i]);
660 }
661
START_TEST(gcs_state_msg_test_gh24_0)662 START_TEST(gcs_state_msg_test_gh24_0) // also tests vote policy switch
663 {
664 gcs_state_msg_test_gh24(0);
665 }
666 END_TEST
667
START_TEST(gcs_state_msg_test_gh24_1)668 START_TEST(gcs_state_msg_test_gh24_1) // also tests vote policy switch
669 {
670 gcs_state_msg_test_gh24(1);
671 }
672 END_TEST
673
674 /* This test is to test that protocol downgrade is disabled with state
675 * excahnge >= v6 */
676 static void
gcs_state_msg_test_v6_upgrade(int const from_ver)677 gcs_state_msg_test_v6_upgrade(int const from_ver)
678 {
679 gcs_state_msg_t* st[3] = { NULL, };
680
681 gu_uuid_t state_uuid;
682 gu_uuid_t group_uuid;
683 gu_uuid_t prim_uuid;
684
685 gu_uuid_generate (&state_uuid, NULL, 0);
686 gu_uuid_generate (&group_uuid, NULL, 0);
687 gu_uuid_generate (&prim_uuid, NULL, 0);
688
689 gcs_seqno_t prim_seqno = 123;
690 gcs_seqno_t act_seqno = 345;
691
692 gcs_state_quorum_t quorum;
693
694 mark_point();
695
696 /* Start with "heterogeneous" PC, where node2 is a v4 node */
697 st[0] = gcs_state_msg_create (&state_uuid, &group_uuid, &prim_uuid,
698 prim_seqno - 1, act_seqno - 1, act_seqno - 1,
699 0, 0, 0, 0,
700 3,
701 GCS_NODE_STATE_PRIM, GCS_NODE_STATE_PRIM,
702 "node0", "",
703 4, 4, 4, 0, 0, 0,
704 0, 0);
705 ck_assert(NULL != st[0]);
706
707 st[1] = gcs_state_msg_create (&state_uuid, &group_uuid, &prim_uuid,
708 prim_seqno, act_seqno, act_seqno - 3,
709 0, 0, 0, 0,
710 3,
711 GCS_NODE_STATE_JOINED, GCS_NODE_STATE_JOINED,
712 "node1", "",
713 3, 3, 3, 0, 0, 0,
714 0, 0);
715 ck_assert(NULL != st[1]);
716
717 st[2] = gcs_state_msg_create (&state_uuid, &group_uuid, &prim_uuid,
718 prim_seqno, act_seqno, act_seqno - 3,
719 0, 0, 0, 0,
720 3,
721 GCS_NODE_STATE_JOINED, GCS_NODE_STATE_JOINED,
722 "node2", "",
723 0, 1, 1, 0, 0, 0,
724 0, 0);
725 ck_assert(NULL != st[2]);
726 st[2]->version = from_ver;
727
728 gu_info (" proto_ver I");
729 int
730 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
731 sizeof(st)/sizeof(gcs_state_msg_t*),
732 &quorum);
733 ck_assert(0 == ret);
734 ck_assert(from_ver == quorum.version);
735 ck_assert(true == quorum.primary);
736 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group_uuid));
737 ck_assert(act_seqno == quorum.act_id);
738 ck_assert(prim_seqno == quorum.conf_id);
739 ck_assert(0 == quorum.gcs_proto_ver);
740 ck_assert(1 == quorum.repl_proto_ver);
741 ck_assert(1 == quorum.appl_proto_ver);
742 ck_assert(GCS_VOTE_ZERO_WINS == quorum.vote_policy);
743
744 #define UPDATE_STATE_MSG(x) \
745 st[x]->prim_seqno = prim_seqno; \
746 st[x]->received = act_seqno; \
747 st[x]->prim_gcs_ver = quorum.gcs_proto_ver; \
748 st[x]->prim_repl_ver = quorum.repl_proto_ver; \
749 st[x]->prim_appl_ver = quorum.appl_proto_ver;
750
751 /* disconnect node2: protocol versions should go up (also bump seqnos) */
752 prim_seqno++;
753 act_seqno++;
754 UPDATE_STATE_MSG(0);
755 UPDATE_STATE_MSG(1);
756 gu_info (" proto_ver II");
757 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
758 2,
759 &quorum);
760 ck_assert(0 == ret);
761 ck_assert(QUORUM_VERSION == quorum.version);
762 ck_assert(true == quorum.primary);
763 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group_uuid));
764 ck_assert(act_seqno == quorum.act_id);
765 ck_assert(prim_seqno == quorum.conf_id);
766 ck_assert(3 == quorum.gcs_proto_ver);
767 ck_assert(3 == quorum.repl_proto_ver);
768 ck_assert(3 == quorum.appl_proto_ver);
769 ck_assert(0 == quorum.vote_policy);
770
771 /* reconnect node2: protocol versions should go down for backward
772 * compatibility */
773 prim_seqno++;
774 act_seqno++;
775 UPDATE_STATE_MSG(0);
776 UPDATE_STATE_MSG(1);
777 gu_info (" proto_ver III");
778 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
779 3,
780 &quorum);
781 ck_assert(0 == ret);
782 ck_assert(from_ver == quorum.version);
783 ck_assert(true == quorum.primary);
784 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group_uuid));
785 ck_assert(act_seqno == quorum.act_id);
786 ck_assert(prim_seqno == quorum.conf_id);
787 ck_assert(0 == quorum.gcs_proto_ver);
788 ck_assert(1 == quorum.repl_proto_ver);
789 ck_assert(1 == quorum.appl_proto_ver);
790 ck_assert(GCS_VOTE_ZERO_WINS == quorum.vote_policy);
791
792
793 /* disconnect node2 */
794 prim_seqno++;
795 act_seqno++;
796 UPDATE_STATE_MSG(0);
797 UPDATE_STATE_MSG(1);
798 gu_info (" proto_ver IV");
799 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
800 2,
801 &quorum);
802 ck_assert(0 == ret);
803 ck_assert(QUORUM_VERSION == quorum.version);
804 ck_assert(true == quorum.primary);
805 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group_uuid));
806 ck_assert(act_seqno == quorum.act_id);
807 ck_assert(prim_seqno == quorum.conf_id);
808 ck_assert(3 == quorum.gcs_proto_ver);
809 ck_assert(3 == quorum.repl_proto_ver);
810 ck_assert(3 == quorum.appl_proto_ver);
811 ck_assert(0 == quorum.vote_policy);
812
813 /* upgrade node2 */
814 st[2]->version = QUORUM_VERSION;
815 st[2]->gcs_proto_ver = 2;
816 st[2]->repl_proto_ver = 2;
817 st[2]->appl_proto_ver = 2;
818
819 /* reconnect node2: this time protocol versions should stay */
820 prim_seqno++;
821 act_seqno++;
822 UPDATE_STATE_MSG(0);
823 UPDATE_STATE_MSG(1);
824 gu_info (" proto_ver V");
825 ret = gcs_state_msg_get_quorum ((const gcs_state_msg_t**)st,
826 3,
827 &quorum);
828 ck_assert(0 == ret);
829 ck_assert(QUORUM_VERSION == quorum.version);
830 ck_assert(true == quorum.primary);
831 ck_assert(0 == gu_uuid_compare(&quorum.group_uuid, &group_uuid));
832 ck_assert(act_seqno == quorum.act_id);
833 ck_assert(prim_seqno == quorum.conf_id);
834 ck_assert(3 == quorum.gcs_proto_ver);
835 ck_assert(3 == quorum.repl_proto_ver);
836 ck_assert(3 == quorum.appl_proto_ver);
837 ck_assert(0 == quorum.vote_policy);
838
839 gcs_state_msg_destroy (st[0]);
840 gcs_state_msg_destroy (st[1]);
841 gcs_state_msg_destroy (st[2]);
842 #undef UPDATE_STATE_MSG
843 }
844
START_TEST(gcs_state_msg_test_v4v6_upgrade)845 START_TEST (gcs_state_msg_test_v4v6_upgrade)
846 {
847 gcs_state_msg_test_v6_upgrade(4);
848 }
849 END_TEST
850
START_TEST(gcs_state_msg_test_v5v6_upgrade)851 START_TEST (gcs_state_msg_test_v5v6_upgrade)
852 {
853 gcs_state_msg_test_v6_upgrade(5);
854 }
855 END_TEST
856
gcs_state_msg_suite(void)857 Suite *gcs_state_msg_suite(void)
858 {
859 Suite *s = suite_create("GCS state message");
860 TCase *tc_basic = tcase_create("gcs_state_msg_basic");
861 TCase *tc_inherit = tcase_create("gcs_state_msg_inherit");
862 TCase *tc_remerge = tcase_create("gcs_state_msg_remerge");
863 TCase *tc_proto_ver = tcase_create("gcs_state_msg_proto_ver");
864
865 suite_add_tcase (s, tc_basic);
866 tcase_add_test (tc_basic, gcs_state_msg_test_basic);
867
868 suite_add_tcase (s, tc_inherit);
869 tcase_add_test (tc_inherit, gcs_state_msg_test_quorum_inherit);
870
871 suite_add_tcase (s, tc_remerge);
872 tcase_add_test (tc_remerge, gcs_state_msg_test_quorum_remerge);
873 tcase_add_test (tc_remerge, gcs_state_msg_test_gh24_0);
874 tcase_add_test (tc_remerge, gcs_state_msg_test_gh24_1);
875
876 suite_add_tcase (s, tc_proto_ver);
877 tcase_add_test (tc_proto_ver, gcs_state_msg_test_v4v6_upgrade);
878 tcase_add_test (tc_proto_ver, gcs_state_msg_test_v5v6_upgrade);
879
880 return s;
881 }
882