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