1 %/* Copyright (c) 2010, 2020, 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 
24 
25 %#include "xcom/xcom_vp_platform.h"
26 
27 %#include "xcom/xcom_limits.h"
28 %#include "xcom/xcom_profile.h"
29 #ifdef RPC_XDR
30 %extern synode_no const null_synode;
31 %extern synode_no get_delivered_msg();
32 #endif
33 
34 /*
35 The xcom protocol version numbers.
36 
37 Zero is not used, so a zero protocol version indicates an error.
38 To add a new protocol version, add a new value to this enum.
39 To change an existing struct, add the new member with an #ifdef
40 guard corresponding to the protocol version.
41 For example, to add a member corresponding to protocol version
42 x_1_7, the definition would look like this:
43 
44 #if (XCOM_PROTO_VERS > 107)
45 	new_member_t new_member;
46 #else
47 #ifdef RPC_XDR
48 %BEGIN
49 %  if (xdrs->x_op == XDR_DECODE) {
50 %	 new_member = suitable_default_value;
51 %  }
52 %END
53 #endif
54 #endif
55 
56 In this example, 107 corresponds to x_1_7.
57 The code in the BEGIN..END block will be inserted immediately before the
58 final return in the generated xdr function. Members which are not in
59 earlier protocol versions are not serialized, since they are excluded
60 by the #if guard. When deserializing, the code in the BEGIN..END block
61 takes care of insering a suitable value instead of actually reading
62 the value from the serialized struct, since the earlier protocol
63 version does not contain the new member.
64 
65 After adding a new protocol version, set MY_XCOM_PROTO to this version in xcom_transport.cc (xcom_transport.cc:/MY_XCOM_PROTO)
66 In addition, the xdr_pax_msg, in this case xdr_pax_msg_1_7 must be added to the dispatch table pax_msg_func in xcom_transport.cc (xcom_transport.cc:/pax_msg_func)
67 
68 For conversion of the new enum value to a string, add an entry in xcom_proto_to_str (xcom_vp_str.cc:/xcom_proto_to_str)
69 
70 To actually generate the xdr functions for the new protocol version, see comments in rpcgen.cmake
71 */
72 
73 enum xcom_proto {
74   x_unknown_proto = 0,
75   x_1_0 = 1,
76   x_1_1 = 2,
77   x_1_2 = 3,
78   x_1_3 = 4,
79   x_1_4 = 5,
80   x_1_5 = 6,
81   x_1_6 = 7,
82   x_1_7 = 8,
83   x_1_8 = 9
84 };
85 
86 enum delivery_status {
87   delivery_ok = 0,
88   delivery_failure = 1
89 };
90 
91 /* Consensus type */
92 enum cons_type {
93   cons_majority = 0          /* Plain majority */,
94   cons_all = 1               /* Everyone must agree */
95 /*   cons_none = 2 */             /* NOT USED */
96 };
97 
98 enum cargo_type {
99   unified_boot_type = 0,
100   xcom_boot_type = 1,
101   xcom_set_group = 2,
102 /*   xcom_recover = 3, */
103   app_type = 4,
104 /*   query_type = 5, */
105 /*   query_next_log = 6, */
106   exit_type = 7,
107   reset_type = 8,
108   begin_trans = 9,
109   prepared_trans = 10,
110   abort_trans = 11,
111   view_msg = 12,
112   remove_reset_type = 13,
113   add_node_type = 14,
114   remove_node_type = 15,
115   enable_arbitrator = 16,
116   disable_arbitrator = 17,
117   force_config_type = 18,
118   x_terminate_and_exit = 19,
119   set_cache_limit = 20,
120   get_event_horizon_type = 21,
121   set_event_horizon_type = 22,
122   get_synode_app_data_type = 23,
123   convert_into_local_server_type = 24
124 };
125 
126 enum recover_action {
127   rec_block = 0,
128   rec_delay = 1,
129   rec_send = 2
130 };
131 
132 enum pax_op {
133   client_msg = 0,
134   initial_op = 1,
135   prepare_op = 2,
136   ack_prepare_op = 3,
137   ack_prepare_empty_op = 4,
138   accept_op = 5,
139   ack_accept_op = 6,
140   learn_op = 7,
141   recover_learn_op = 8,
142   multi_prepare_op = 9,
143   multi_ack_prepare_empty_op = 10,
144   multi_accept_op = 11,
145   multi_ack_accept_op = 12,
146   multi_learn_op = 13,
147   skip_op = 14,
148   i_am_alive_op = 15,
149   are_you_alive_op = 16,
150   need_boot_op = 17,
151   snapshot_op = 18,
152   die_op = 19,
153   read_op = 20,
154   gcs_snapshot_op = 21,
155   xcom_client_reply = 22,
156   tiny_learn_op = 23,
157   LAST_OP
158 };
159 
160 enum pax_msg_type {
161   normal = 0,
162   no_op = 1,
163   multi_no_op = 2
164 };
165 
166 enum client_reply_code {
167      REQUEST_OK = 0,
168      REQUEST_FAIL = 1,
169      REQUEST_RETRY = 2
170 };
171 
172 enum start_t {
173      IDLE = 0,
174      BOOT = 1,
175      RECOVER = 2
176 };
177 
178 typedef uint32_t xcom_event_horizon;
179 
180 typedef uint32_t node_no;
181 
182 typedef bool node_set<NSERVERS>;
183 
184 /* A portable bit set */
185 
186 typedef uint32_t bit_mask;
187 
188 struct bit_set {
189   bit_mask bits<NSERVERS>;
190 };
191 
192 %#define	BITS_PER_BYTE 8
193 %#define	MASK_BITS	((bit_mask)(sizeof (bit_mask) * BITS_PER_BYTE))	/* bits per mask */
194 %#define	howmany_words(x, y)	(((x)+((y)-1))/(y))
195 %
196 
197 %#define BIT_OP(__n, __p, __op, __inv) ((__p)->bits.bits_val[(__n)/MASK_BITS] __op  __inv (1u << ((__n) % MASK_BITS)))
198 %#define BIT_XOR(__n, __p) BIT_OP(__n, __p, ^=,(bit_mask))
199 %#define BIT_SET(__n, __p) BIT_OP(__n, __p, |=,(bit_mask))
200 %#define BIT_CLR(__n, __p) BIT_OP(__n, __p, &=,(bit_mask) ~)
201 %#define BIT_ISSET(__n, __p) (BIT_OP(__n, __p, &,(bit_mask)) != 0ul)
202 %#define BIT_ZERO(__p) memset((__p)->bits.bits_val, 0, (__p)->bits.bits_len * sizeof(*(__p)->bits.bits_val))
203 
204 %extern bit_set *new_bit_set(uint32_t bits);
205 %extern bit_set *clone_bit_set(bit_set *orig);
206 %extern void free_bit_set(bit_set *bs);
207 
208 %#ifndef CHECKED_DATA
209 %#define CHECKED_DATA
210 %typedef struct {
211 %	u_int data_len;
212 %	char *data_val;
213 %} checked_data;
214 %extern  bool_t xdr_checked_data (XDR *, checked_data*);
215 %#endif
216 
217 struct blob {
218 	opaque data<MAXBLOB>;
219 };
220 
221 struct x_proto_range {
222 	xcom_proto min_proto;
223 	xcom_proto max_proto;
224 };
225 
226 /* Message number will wrap in 5.8E5 years if we run at 1000000 messages per second */
227 /* Change to circular hyper int if this is not desirable */
228 
229 struct synode_no {
230   uint32_t group_id; /* The group this synode belongs to */
231   uint64_t msgno; /* Monotonically increasing number */
232   node_no node;         /* Node number */
233 };
234 
235 struct trans_id{
236   synode_no cfg;
237   uint32_t pc;
238 };
239 
240 struct node_address{
241 	string address<MAXNAME>;
242 	blob  uuid;
243 #if (XCOM_PROTO_VERS > 100)
244 	x_proto_range proto; /* Supported protocols */
245 #else
246 #ifdef RPC_XDR
247 %BEGIN
248 %  if (xdrs->x_op == XDR_DECODE) {
249 %	 objp->proto.min_proto = x_1_0;
250 %	 objp->proto.max_proto = x_1_0;
251 %  }
252 %END
253 #endif
254 #endif
255 };
256 
257 typedef node_address node_list<NSERVERS>;
258 
259 typedef node_no node_no_array<NSERVERS>;
260 typedef synode_no synode_no_array<MAX_SYNODE_ARRAY>;
261 
262 struct uncommitted_list{
263   uint32_t active;
264   synode_no_array vers;
265 };
266 
267 struct repository {
268   synode_no vers;
269   synode_no_array msg_list;
270   uncommitted_list u_list;
271 };
272 
273 struct x_error
274 {
275   int32_t nodeid;
276   int32_t code;
277   string message<MAXERROR>;
278 };
279 
280 struct trans_data{
281   trans_id tid;
282   int32_t pc;
283   string cluster_name<MAXNAME>;
284   x_error errmsg;
285 };
286 
287 /* Application-specific data */
288 union app_u switch(cargo_type c_t){
289  case unified_boot_type:
290  case add_node_type:
291  case remove_node_type:
292  case force_config_type:
293  case xcom_boot_type:
294  case xcom_set_group:
295    node_list nodes;
296  case app_type:
297    checked_data data;
298  case exit_type:
299  case reset_type:
300    void;
301  case remove_reset_type:
302    void;
303  case begin_trans:
304    void;
305  case prepared_trans:
306  case abort_trans:
307    trans_data td;
308  case view_msg:
309    node_set present;
310  case set_cache_limit:
311    uint64_t cache_limit;
312  case get_event_horizon_type:
313    void;
314  case set_event_horizon_type:
315    xcom_event_horizon event_horizon;
316  case get_synode_app_data_type:
317    synode_no_array synodes;
318  case convert_into_local_server_type:
319    void;
320  default:
321    void;
322 };
323 
324 struct app_data{
325   synode_no unique_id; /* Unique id of message */
326   uint32_t group_id; /* Unique ID shared by our group */
327   uint64_t lsn; /* Local sequence number */
328   synode_no app_key;   /* Typically message number/log sequence number, but could be object ID  */
329   cons_type consensus; /* Type of consensus needed for delivery of this message */
330   double expiry_time; /* How long to wait before delivery fails */
331   bool notused; /* not used  */
332   bool log_it; /* Put this message in the log */
333   bool chosen; /* Finished phase 3, may be executed */
334   recover_action recover; /* Sent as part of recovery */
335   app_u body;
336   app_data *next; /* Link to next in list */
337 };
338 
339 typedef app_data *app_data_ptr;
340 typedef app_data_ptr app_data_ptr_array<MAX_APP_PTR_ARRAY>;
341 typedef app_data_ptr *app_data_list;
342 
343 struct key_range{
344     synode_no k1;
345     synode_no k2;
346 };
347 
348 /* Ballot defined by count and node number */
349 struct ballot{
350   int32_t cnt;
351   node_no node;
352 };
353 
354 struct snapshot{
355   synode_no vers;
356   app_data_ptr_array snap;
357   uncommitted_list u_list;
358 };
359 
360 struct config{
361 	synode_no start; 	/* Config is active from this message number */
362 	synode_no boot_key; /* The message number of the original unified_boot */
363 	node_list nodes;	/* Set of nodes in this config */
364 #if (XCOM_PROTO_VERS == 103) || (XCOM_PROTO_VERS > 106)
365 	node_set global_node_set; /* The global node set for this site */
366 #else
367 #ifdef RPC_XDR
368 %BEGIN
369 %  if (xdrs->x_op == XDR_DECODE) {
370 %    objp->global_node_set.node_set_len = 0;
371 %    objp->global_node_set.node_set_val = 0;
372 %  }
373 %END
374 #endif
375 #endif
376 #if (XCOM_PROTO_VERS > 103)
377 	xcom_event_horizon event_horizon;
378 #else
379 #ifdef RPC_XDR
380 %BEGIN
381 %      if (xdrs->x_op == XDR_DECODE) {
382 %        objp->event_horizon = EVENT_HORIZON_MIN;
383 %      }
384 %END
385 #endif
386 #endif
387 };
388 
389 typedef config *config_ptr;
390 typedef config_ptr configs<MAX_SITE_DEFS>;
391 
392 struct gcs_snapshot{
393   synode_no log_start;
394 #if (XCOM_PROTO_VERS == 103) || (XCOM_PROTO_VERS > 106)
395   synode_no log_end;
396 #else
397 #ifdef RPC_XDR
398 %BEGIN
399 %  if (xdrs->x_op == XDR_DECODE) {
400 %    objp->log_end = null_synode;
401 %  }
402 %END
403 #endif
404 #endif
405   configs cfg;
406   blob app_snap;
407 };
408 
409 struct synode_app_data {
410    synode_no synode;
411    checked_data data;
412 };
413 typedef synode_app_data synode_app_data_array<MAX_SYNODE_ARRAY>;
414 
415 /*
416   protocol x_1_2 and x_1_3 differ only in the definition of gcs_snapshot,
417   which is taken care of by xdr_gcs_snapshot
418 */
419 
420 /*
421   pax_msg_1_5 is identical to pax_msg_1_4,
422   but nodes running protocol version 1_5 or greater support IPv6.
423   xdr_pax_msg for protocol x_1_6 and greater must grok the incompatible
424   gcs_snapshot and config versions of x_1_3 and x_1_4.
425 */
426 
427 struct pax_msg{
428   node_no to;             /* To node */
429   node_no from;           /* From node */
430   uint32_t group_id; /* Unique ID shared by our group */
431   synode_no max_synode; /* Gossip about the max real synode */
432   start_t start_type; /* Boot or recovery? DEPRECATED */
433   ballot reply_to;    /* Reply to which ballot */
434   ballot proposal;    /* Proposal number */
435   pax_op op;          /* Opcode: prepare, propose, learn, etc */
436   synode_no synode;   /* The message number */
437   pax_msg_type msg_type; /* normal, noop, or multi_noop */
438   bit_set *receivers;
439   app_data *a;      /* Payload */
440   snapshot *snap;	/* Not used */
441   gcs_snapshot *gcs_snap; /* gcs_snapshot if op == gcs_snapshot_op */
442   client_reply_code cli_err;
443   bool force_delivery; /* Deliver this message even if we do not have majority */
444   int32_t refcnt;
445 #if (XCOM_PROTO_VERS > 101)
446   synode_no delivered_msg; /* Gossip about the last delivered message */
447 #else
448 #ifdef RPC_XDR
449 %BEGIN
450 %  if (xdrs->x_op == XDR_DECODE) {
451 %    objp->delivered_msg = get_delivered_msg(); /* Use our own minimum */
452 %  }
453 %END
454 #endif
455 #endif
456 #if (XCOM_PROTO_VERS > 103)
457   xcom_event_horizon event_horizon; /* Group's event horizon */
458 #else
459 #ifdef RPC_XDR
460 %BEGIN
461 %  if (xdrs->x_op == XDR_DECODE) {
462 %    objp->event_horizon = 0;
463 %  }
464 %END
465 #endif
466 #endif
467 #if (XCOM_PROTO_VERS > 105)
468   synode_app_data_array requested_synode_app_data; /* The decided data for the requested synodes */
469 #else
470 #ifdef RPC_XDR
471 %BEGIN
472 %  if (xdrs->x_op == XDR_DECODE) {
473 %        objp->requested_synode_app_data.synode_app_data_array_len = 0;
474 %        objp->requested_synode_app_data.synode_app_data_array_val = NULL;
475 %  }
476 %END
477 #endif
478 #endif
479 };
480