1 /* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include <stdlib.h>
24 #include <assert.h>
25 
26 #include "x_platform.h"
27 
28 #include "xcom_common.h"
29 #include "xcom_vp.h"
30 #include "node_list.h"
31 #include "simset.h"
32 #include "task.h"
33 #include "server_struct.h"
34 #include "xcom_detector.h"
35 #include "site_struct.h"
36 #include "xcom_base.h"
37 #include "bitset.h"
38 #include "xcom_memory.h"
39 #include "synode_no.h"
40 #include "node_no.h"
41 #include "task_debug.h"
42 #include "xcom_transport.h"
43 #include "site_def.h"
44 #include "node_set.h"
45 
46 typedef site_def *site_def_ptr;
47 
48 struct site_def_ptr_array {
49 	u_int count;
50 	u_int site_def_ptr_array_len;
51 	site_def_ptr *site_def_ptr_array_val;
52 };
53 typedef struct site_def_ptr_array site_def_ptr_array;
54 
55 init_xdr_array(site_def_ptr)
56 free_xdr_array(site_def_ptr)
57 set_xdr_array(site_def_ptr)
58 
59 /* FIFO of site definitions */
60 static site_def_ptr_array site_defs;
61 static site_def *incoming = 0;
62 static inline node_no _get_maxnodes(site_def const *site);
63 
64 /* purecov: begin deadcode */
65 /* Save incoming site def, but do not make it available yet */
begin_site_def(site_def * s)66 site_def *begin_site_def(site_def *s)
67 {
68 	assert(!incoming);
69 	incoming = s;
70 	assert(s->global_node_set.node_set_len == _get_maxnodes(s));
71 	return incoming;
72 }
73 
74 
75 /* Push saved site def, making it active from synode start */
end_site_def(synode_no start)76 site_def *end_site_def(synode_no start)
77 {
78 	assert(incoming);
79 	incoming->start = start;
80 	return push_site_def(incoming);
81 }
82 /* purecov: end */
83 
84 /* Rteurn pointer to array of site defs */
get_all_site_defs(site_def *** s,uint32_t * n)85 void	get_all_site_defs(site_def ***s, uint32_t *n)
86 {
87 	*s = site_defs.site_def_ptr_array_val;
88 	*n = site_defs.site_def_ptr_array_len;
89 }
90 
91 
92 /* Module initialization */
init_site_vars()93 void	init_site_vars()
94 {
95 	init_site_def_ptr_array(&site_defs);
96 	site_defs.count = 0;
97 	incoming = 0;
98 }
99 
100 
101 /* Recursively free a complete site_def.  Only free the site_def, not
102  the servers that it points to, since servers are shared by multiple
103  site_defs, and will eventually be deallocated by garbage_collect_servers
104 */
free_site_def(site_def * s)105 void	free_site_def(site_def *s)
106 {
107 	if (s) {
108 		invalidate_detector_sites(s);
109 		xdr_free((xdrproc_t) xdr_node_list, (char *)(&s->nodes));
110 		free_node_set(&s->global_node_set);
111 		free_node_set(&s->local_node_set);
112 		free(s);
113 	}
114 }
115 
116 
117 /* Free all resources in this module */
free_site_defs()118 void	free_site_defs()
119 {
120 	u_int	i;
121 	for(i = 0; i < site_defs.count; i++) {
122 		free_site_def(site_defs.site_def_ptr_array_val[i]);
123 	}
124 	free_site_def_ptr_array(&site_defs);
125 	site_defs.count = 0;
126 	free_site_def(incoming);
127 }
128 
129 
130 /* Add a new site definition to the list */
push_site_def(site_def * s)131 site_def *push_site_def(site_def *s)
132 {
133 	uint32_t	i;
134 	set_site_def_ptr(&site_defs, 0, site_defs.count);
135 	DBGOUT(FN;
136 	NDBG(site_defs.count,u);
137 	PTREXP(s);
138 	if (s) {
139 		SYCEXP(s->start);
140 		SYCEXP(s->boot_key);
141 	}
142 	);
143 	for (i = site_defs.count; i > 0; i--) {
144 		DBGOUT(NDBG(i-1,d);
145 		PTREXP(site_defs.site_def_ptr_array_val[i-1]);
146 		if (site_defs.site_def_ptr_array_val[i-1]) {
147 			SYCEXP(site_defs.site_def_ptr_array_val[i-1]->start);
148 			SYCEXP(site_defs.site_def_ptr_array_val[i-1]->boot_key);
149 		}
150 		);
151 		site_defs.site_def_ptr_array_val[i] = site_defs.site_def_ptr_array_val[i-1];
152 	}
153 	set_site_def_ptr(&site_defs, s, 0);
154 	if(s){
155 		s->x_proto =  set_latest_common_proto(common_xcom_version(s));
156 		G_DEBUG("latest common protocol is now %d",s->x_proto);
157 	}
158 	site_defs.count++;
159 	assert(!s  || (s->global_node_set.node_set_len == _get_maxnodes(s)));
160 	return s;
161 }
162 
163 /* Return first site def */
_get_site_def()164 static inline site_def const *_get_site_def()
165 {
166 	assert(site_defs.count == 0 || !site_defs.site_def_ptr_array_val[0] || site_defs.site_def_ptr_array_val[0]->global_node_set.node_set_len ==
167 	    _get_maxnodes(site_defs.site_def_ptr_array_val[0]));
168 	if (site_defs.count > 0)
169 		return site_defs.site_def_ptr_array_val[0];
170 	else
171 		return 0;
172 }
173 
174 
175 /* Return first site def */
get_site_def_rw()176 site_def *get_site_def_rw()
177 {
178 	if (site_defs.count > 0)
179 		return site_defs.site_def_ptr_array_val[0];
180 	else
181 		return 0;
182 }
183 
184 /* purecov: begin deadcode */
185 /* Return previous site def */
_get_prev_site_def()186 static inline site_def const *_get_prev_site_def()
187 {
188 	assert(site_defs.count == 0 || !site_defs.site_def_ptr_array_val[1] || site_defs.site_def_ptr_array_val[1]->global_node_set.node_set_len ==
189 	    _get_maxnodes(site_defs.site_def_ptr_array_val[1]));
190 	if (site_defs.count > 0)
191 		return site_defs.site_def_ptr_array_val[1];
192 	else
193 		return 0;
194 }
195 /* purecov: end */
196 
197 
198 
199 /* Return first site def */
get_site_def()200 site_def const *get_site_def()
201 {
202 	return _get_site_def();
203 }
204 
205 /* purecov: begin deadcode */
206 /* Return previous site def */
get_prev_site_def()207 site_def const *get_prev_site_def()
208 {
209 	return _get_prev_site_def();
210 }
211 /* purecov: end */
212 
match_def(site_def const * site,synode_no synode)213 static inline int match_def(site_def const *site, synode_no synode)
214 {
215 	return site && (synode.group_id == 0 || synode.group_id == site->start.group_id)
216 	&& !synode_lt(synode, site->start);
217 }
218 
219 /* Return first site def which has start less than or equal to synode */
find_site_def(synode_no synode)220 site_def const *find_site_def(synode_no synode)
221 {
222 	site_def const * retval = 0;
223 	u_int i;
224 
225 	for(i = 0; i < site_defs.count; i++)
226 		if (match_def(site_defs.site_def_ptr_array_val[i], synode)){
227 		retval =  site_defs.site_def_ptr_array_val[i];
228 		break;
229 	}
230 	assert(!retval || retval->global_node_set.node_set_len == _get_maxnodes(retval));
231 	return retval;
232 }
233 
234 /* As find_site_def, but return pointer to non-const object */
find_site_def_rw(synode_no synode)235 site_def *find_site_def_rw(synode_no synode)
236 {
237 	site_def * retval = 0;
238 	u_int i;
239 
240 	for(i = 0; i < site_defs.count; i++)
241 		if (match_def(site_defs.site_def_ptr_array_val[i], synode)){
242 		retval =  site_defs.site_def_ptr_array_val[i];
243 		break;
244 	}
245 	assert(!retval || retval->global_node_set.node_set_len == _get_maxnodes(retval));
246 	return retval;
247 }
248 
249 
garbage_collect_site_defs(synode_no x)250 void garbage_collect_site_defs(synode_no x)
251 {
252 	u_int	i;
253 	u_int s_max = site_defs.count;
254 
255 	DBGOUT(FN;
256 	    NDBG(site_defs.count, u);
257 	    SYCEXP(x);
258 	    );
259 	for (i = 3; i < s_max; i++) {
260 		if (match_def(site_defs.site_def_ptr_array_val[i], x)) {
261 			break;
262 		}
263 	}
264 	i++;
265 	for (; i < s_max; i++) {
266 		site_def * site = site_defs.site_def_ptr_array_val[i];
267 		DBGOUT(NDBG(i, d);
268 		    PTREXP(site_defs.site_def_ptr_array_val[i]); );
269 		if (site) {
270 			DBGOUT(SYCEXP(site->start);
271 			    SYCEXP(site->boot_key); );
272 			free_site_def(site);
273 			site_defs.site_def_ptr_array_val[i] = 0;
274 		}
275 		site_defs.count--;
276 	}
277 }
278 
279 /* purecov: begin deadcode */
dbg_site_def(site_def const * site)280 char *dbg_site_def(site_def const *site)
281 {
282 	assert(site->global_node_set.node_set_len == _get_maxnodes(site));
283 	return dbg_list(&site->nodes);
284 }
285 /* purecov: end */
286 
287 /* Create a new empty site_def */
new_site_def()288 site_def *new_site_def()
289 {
290 	site_def * retval =  (site_def * ) calloc(1, sizeof(site_def));
291 	retval->nodeno = VOID_NODE_NO;
292 	return retval;
293 }
294 
295 
296 /* {{{ Clone a site definition */
297 
clone_site_def(site_def const * site)298 site_def *clone_site_def(site_def const *site)
299 {
300 	site_def * retval = new_site_def();
301 	assert(site->global_node_set.node_set_len == _get_maxnodes(site));
302 	*retval = *site;
303 	init_node_list(site->nodes.node_list_len, site->nodes.node_list_val, &retval->nodes);
304 	retval->global_node_set = clone_node_set(site->global_node_set);
305 	retval->local_node_set = clone_node_set(site->local_node_set);
306 	assert(retval->global_node_set.node_set_len == _get_maxnodes(retval));
307 	DBGOUT(FN; PTREXP(site); PTREXP(retval));
308 	return retval;
309 }
310 
311 
312 /* }}} */
313 
314 /* {{{ Initialize a site definition from array of string pointers */
315 
init_site_def(u_int n,node_address * names,site_def * site)316 void	init_site_def(u_int n, node_address *names, site_def *site)
317 {
318 	site->start = null_synode;
319 	site->boot_key = null_synode;
320 	site->nodeno = VOID_NODE_NO;
321 	init_detector(site->detected);
322 	init_node_list(n, names, &site->nodes);
323 	site->global_node_count = 0;
324 	alloc_node_set(&site->global_node_set, NSERVERS);
325 	site->global_node_set.node_set_len = site->nodes.node_list_len;
326 	set_node_set(&site->global_node_set); /* Assume everyone is there */
327 	assert(site->global_node_set.node_set_len == _get_maxnodes(site));
328 	alloc_node_set(&site->local_node_set, NSERVERS);
329 	site->local_node_set.node_set_len = site->nodes.node_list_len;
330 	set_node_set(&site->local_node_set); /* Assume everyone is there */
331 	assert(site->local_node_set.node_set_len == _get_maxnodes(site));
332 	site->detector_updated = 0;
333 	site->x_proto = my_xcom_version;
334 }
335 
336 
337 /* }}} */
338 
339 
340 /* Add nodes to site definition, avoid duplicates */
add_site_def(u_int n,node_address * names,site_def * site)341 void	add_site_def(u_int n, node_address *names, site_def *site)
342 {
343 	if (n > 0) {
344 		add_node_list(n, names, &site->nodes);
345 	}
346 	realloc_node_set(&site->global_node_set, _get_maxnodes(site));
347 	realloc_node_set(&site->local_node_set, _get_maxnodes(site));
348 }
349 
350 /* Remove nodes from site definition, ignore missing nodes */
remove_site_def(u_int n,node_address * names,site_def * site)351 void	remove_site_def(u_int n, node_address *names, site_def *site)
352 {
353 	if (n > 0) {
354 		remove_node_list(n, names, &site->nodes);
355 	}
356 	init_detector(site->detected); /* Zero all unused timestamps */
357 	realloc_node_set(&site->global_node_set, _get_maxnodes(site));
358 	realloc_node_set(&site->local_node_set, _get_maxnodes(site));
359 }
360 
361 /* purecov: begin deadcode */
362 /* Return boot_key of first site def */
get_boot_key()363 synode_no get_boot_key()
364 {
365 	assert(!_get_site_def() || _get_site_def()->global_node_set.node_set_len == _get_maxnodes(_get_site_def()));
366 	if (get_site_def()) {
367 		return get_site_def()->boot_key;
368 	} else {
369 		return null_synode;
370 	}
371 }
372 
373 
374 /* Set boot_key of first site def */
set_boot_key(synode_no const x)375 void	set_boot_key(synode_no const x)
376 {
377 	assert(_get_site_def());
378 	assert(_get_site_def()->global_node_set.node_set_len == _get_maxnodes(_get_site_def()));
379 	if (site_defs.site_def_ptr_array_val[0]) {
380 		site_defs.site_def_ptr_array_val[0]->boot_key = x;
381 	}
382 }
383 /* purecov: end */
384 
385 /* Return group id of site */
get_group_id(site_def const * site)386 uint32_t get_group_id(site_def const *site)
387 {
388 	if (site) {
389 		uint32_t	group_id = site->start.group_id;
390 		assert(site->global_node_set.node_set_len == _get_maxnodes(site));
391 		MAY_DBG(FN; NDBG(group_id, lx); );
392 		return group_id;
393 	} else {
394 		return null_id;
395 	}
396 }
397 
398 
399 #if 0
400 void	set_group_id(site_def *site, uint32_t id)
401 {
402 	MAY_DBG(FN; STRLIT("changing group id from ");
403 	    NDBG(get_group_id(site), lx);
404 	    STRLIT("to ");
405 	    NDBG(id, lu);
406 	    );
407 	site->group_id = id;
408 }
409 
410 
411 #endif
412 
_get_maxnodes(site_def const * site)413 static inline node_no _get_maxnodes(site_def const *site)
414 {
415 	if (site) {
416 		return site->nodes.node_list_len;
417 	} else
418 		return 0;
419 }
420 
421 
422 /* Return maxnodes of site */
get_maxnodes(site_def const * site)423 node_no get_maxnodes(site_def const *site)
424 {
425 	return _get_maxnodes(site);
426 }
427 
428 /* purecov: begin deadcode */
get_prev_maxnodes()429 node_no get_prev_maxnodes()
430 {
431 	return _get_maxnodes(_get_prev_site_def());
432 }
433 /* purecov: end */
434 
435 /* Return nodeno of site */
_get_nodeno(site_def const * site)436 static inline node_no _get_nodeno(site_def const *site)
437 {
438 	if (site) {
439 		assert(site->global_node_set.node_set_len == _get_maxnodes(site));
440 		return site->nodeno;
441 	} else
442 		return VOID_NODE_NO;
443 }
444 
445 /* purecov: begin deadcode */
446 /* Return nodeno of site */
get_nodeno(site_def const * site)447 node_no get_nodeno(site_def const *site)
448 {
449 	return _get_nodeno(site);
450 }
451 /* purecov: end */
452 
get_prev_nodeno()453 node_no get_prev_nodeno()
454 {
455 	return _get_nodeno(_get_prev_site_def());
456 }
457 
458 
import_config(gcs_snapshot * gcs_snap)459 void import_config(gcs_snapshot *gcs_snap)
460 {
461 	int	i;
462 	DBGOUT(FN; SYCEXP(gcs_snap->log_start));
463 	for (i = (int)gcs_snap->cfg.configs_len-1; i >= 0; i--) {
464 		config_ptr cp = gcs_snap->cfg.configs_val[i];
465 		if (cp) {
466 			site_def * site = new_site_def();
467 			DBGOUT(FN; SYCEXP(cp->start); SYCEXP(cp->boot_key));
468 			init_site_def(cp->nodes.node_list_len,
469 			    cp->nodes.node_list_val, site);
470 			site->start = cp->start;
471 			site->boot_key = cp->boot_key;
472 			site_install_action(site, app_type);
473 		}
474 	}
475 }
476 
477 extern synode_no executed_msg;
478 
export_config()479 gcs_snapshot *export_config()
480 {
481 	u_int	i;
482 	gcs_snapshot *gcs_snap = calloc(1, sizeof(gcs_snapshot));
483 	gcs_snap->cfg.configs_val = calloc(site_defs.count, sizeof(config_ptr));
484 	gcs_snap->cfg.configs_len = site_defs.count;
485 
486 	for (i = 0; i < site_defs.count; i++) {
487 		site_def *site = site_defs.site_def_ptr_array_val[i];
488 		if(site) {
489 			config_ptr cp = calloc(1, sizeof(config));
490 			init_node_list(site->nodes.node_list_len,
491 			    site->nodes.node_list_val, &cp->nodes);
492 			cp->start = site->start;
493 			cp->boot_key = site->boot_key;
494 			DBGOUT(FN; SYCEXP(cp->start); SYCEXP(cp->boot_key));
495 			gcs_snap->cfg.configs_val[i] = cp;
496 		}
497 	}
498 	gcs_snap->log_start = get_delivered_msg();
499 	return gcs_snap;
500 }
501 
502 
503 /* Return the global minimum delivered message number, based on incoming gossip */
get_min_delivered_msg(site_def const * s)504 synode_no get_min_delivered_msg(site_def const *s)
505 {
506 	u_int i;
507 	synode_no retval = null_synode;
508 	int	init = 1;
509 
510 	for (i = 0; i < s->nodes.node_list_len; i++) {
511 		if (s->servers[i]->detected + DETECTOR_LIVE_TIMEOUT > task_now()) {
512 			if (init) {
513 				init = 0;
514 				retval = s->delivered_msg[i];
515 			} else {
516 				if (synode_lt(s->delivered_msg[i], retval)) {
517 					retval = s->delivered_msg[i];
518 				}
519 			}
520 		}
521 	}
522 	DBGOUT(FN; SYCEXP(retval));
523 	return retval;
524 }
525 
526 
527 /* Track the minimum delivered message numbers based on incoming messages */
update_delivered(site_def * s,node_no node,synode_no msgno)528 void update_delivered(site_def *s, node_no node, synode_no msgno)
529 {
530 	if(node < s->nodes.node_list_len){
531 		s->delivered_msg[node] = msgno;
532 		DBGOUT(FN; SYCEXP(s->delivered_msg[node]); NDBG(node,u));
533 	}
534 }
535