1 /* Copyright (c) 2015, 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 #include "xcom/xcom_interface.h"
24 
25 #include <assert.h>
26 #include <stdlib.h>
27 
28 #include "xcom/app_data.h"
29 #include "xcom/bitset.h"
30 #include "xcom/node_list.h"
31 #include "xcom/node_no.h"
32 #include "xcom/node_set.h"
33 #include "xcom/pax_msg.h"
34 #include "xcom/server_struct.h"
35 #include "xcom/simset.h"
36 #include "xcom/site_def.h"
37 #include "xcom/site_struct.h"
38 #include "xcom/synode_no.h"
39 #include "xcom/task.h"
40 #include "xcom/task_debug.h"
41 #include "xcom/xcom_base.h"
42 #include "xcom/xcom_cache.h"
43 #include "xcom/xcom_common.h"
44 #include "xcom/xcom_detector.h"
45 #include "xcom/xcom_profile.h"
46 #include "xcom/xcom_transport.h"
47 #include "xcom/xcom_vp_str.h"
48 #include "xdr_gen/xcom_vp.h"
49 
50 static xcom_full_data_receiver xcom_full_receive_data;
51 static xcom_full_local_view_receiver xcom_full_receive_local_view;
52 static xcom_full_global_view_receiver xcom_full_receive_global_view;
53 
54 static xcom_data_receiver xcom_receive_data;
55 static xcom_local_view_receiver xcom_receive_local_view;
56 static xcom_global_view_receiver xcom_receive_global_view;
57 
58 /* purecov: begin deadcode */
set_xcom_full_data_receiver(xcom_full_data_receiver x)59 void set_xcom_full_data_receiver(xcom_full_data_receiver x) {
60   xcom_full_receive_data = x;
61 }
62 /* purecov: end */
63 
64 /* purecov: begin deadcode */
set_xcom_full_local_view_receiver(xcom_full_local_view_receiver x)65 void set_xcom_full_local_view_receiver(xcom_full_local_view_receiver x) {
66   xcom_full_receive_local_view = x;
67 }
68 /* purecov: end */
69 
70 /* purecov: begin deadcode */
set_xcom_full_global_view_receiver(xcom_full_global_view_receiver x)71 void set_xcom_full_global_view_receiver(xcom_full_global_view_receiver x) {
72   xcom_full_receive_global_view = x;
73 }
74 /* purecov: end */
75 
set_xcom_data_receiver(xcom_data_receiver x)76 void set_xcom_data_receiver(xcom_data_receiver x) { xcom_receive_data = x; }
77 
set_xcom_local_view_receiver(xcom_local_view_receiver x)78 void set_xcom_local_view_receiver(xcom_local_view_receiver x) {
79   xcom_receive_local_view = x;
80 }
81 
set_xcom_global_view_receiver(xcom_global_view_receiver x)82 void set_xcom_global_view_receiver(xcom_global_view_receiver x) {
83   xcom_receive_global_view = x;
84 }
85 
86 static xcom_config_receiver xcom_receive_config = 0;
87 
88 /* purecov: begin deadcode */
set_xcom_config_receiver(xcom_config_receiver x)89 void set_xcom_config_receiver(xcom_config_receiver x) {
90   xcom_receive_config = x;
91 }
92 /* purecov: end */
93 
94 xcom_logger xcom_log = NULL;
95 xcom_debugger xcom_debug = NULL;
96 xcom_debugger_check xcom_debug_check = NULL;
97 int64_t xcom_debug_options = GCS_DEBUG_NONE;
98 
set_xcom_logger(xcom_logger x)99 void set_xcom_logger(xcom_logger x) { xcom_log = x; }
100 
set_xcom_debugger(xcom_debugger x)101 void set_xcom_debugger(xcom_debugger x) { xcom_debug = x; }
102 
set_xcom_debugger_check(xcom_debugger_check x)103 void set_xcom_debugger_check(xcom_debugger_check x) { xcom_debug_check = x; }
104 
105 /* Deliver message to application */
106 
deliver_to_app(pax_machine * pma,app_data_ptr app,delivery_status app_status)107 void deliver_to_app(pax_machine *pma, app_data_ptr app,
108                     delivery_status app_status) {
109   site_def const *site = 0;
110   int full_doit = xcom_full_receive_data != 0;
111   int doit = (xcom_receive_data != 0 && app_status == delivery_ok);
112 
113   if (app_status == delivery_ok) {
114     if (!pma) {
115       g_critical(
116           "A fatal error ocurred that prevents XCom from delivering a message "
117           "that achieved consensus. XCom cannot proceed without compromising "
118           "correctness. XCom will now crash.");
119     }
120     assert(pma && "pma must not be a null pointer");
121   }
122 
123   if (!(full_doit || doit)) return;
124 
125   IFDBG(D_NONE, FN; PTREXP(pma); PTREXP(app); NDBG(app_status, d);
126         COPY_AND_FREE_GOUT(dbg_app_data(app)));
127   if (pma)
128     site = find_site_def(pma->synode);
129   else
130     site = get_site_def();
131 
132   while (app) {
133     if (app->body.c_t == app_type) { /* Decode application data */
134       if (full_doit) {
135         /* purecov: begin deadcode */
136         xcom_full_receive_data(site, pma, app, app_status);
137         /* purecov: end */
138       } else {
139         if (doit) {
140           u_int copy_len = 0;
141           char *copy = (char *)malloc(app->body.app_u_u.data.data_len);
142           if (copy == NULL) {
143             /* purecov: begin inspected */
144             G_ERROR("Unable to allocate memory for the received message.");
145             /* purecov: end */
146           } else {
147             memcpy(copy, app->body.app_u_u.data.data_val,
148                    app->body.app_u_u.data.data_len);
149             copy_len = app->body.app_u_u.data.data_len;
150           }
151           ADD_DBG(D_EXEC, add_synode_event(pma->synode););
152 
153           xcom_receive_data(pma->synode, detector_node_set(site), copy_len,
154                             cache_get_last_removed(), copy);
155         } else {
156           /* purecov: begin deadcode */
157           G_TRACE("Data message was not delivered.");
158           /* purecov: end */
159         }
160       }
161     } else if (app_status == delivery_ok) {
162       G_ERROR("Data message has wrong type %s ",
163               cargo_type_to_str(app->body.c_t));
164     }
165     app = app->next;
166   }
167 }
168 
169 /**
170    Deliver a view message
171 */
172 
deliver_view_msg(site_def const * site)173 void deliver_view_msg(site_def const *site) {
174   if (site) {
175     if (xcom_full_receive_local_view) {
176       /* purecov: begin deadcode */
177       xcom_full_receive_local_view(site, detector_node_set(site));
178       /* purecov: end */
179     } else if (xcom_receive_local_view) {
180       xcom_receive_local_view(site->start, detector_node_set(site));
181     }
182   }
183 }
184 
185 #ifdef SUPPRESS_DUPLICATE_VIEWS
186 static node_set delivered_node_set;
187 static site_def const *delivered_site;
188 
not_duplicate_view(site_def const * site)189 static int not_duplicate_view(site_def const *site) {
190   int retval;
191   retval = !(site == delivered_site &&
192              equal_node_set(delivered_node_set, site->global_node_set));
193   delivered_site = site;
194   copy_node_set(&site->global_node_set, &delivered_node_set);
195   return retval;
196 }
197 #endif
198 
deliver_global_view_msg(site_def const * site,synode_no message_id)199 void deliver_global_view_msg(site_def const *site, synode_no message_id) {
200   if (site) {
201 #ifdef SUPPRESS_DUPLICATE_VIEWS
202     if (not_duplicate_view(site)) {
203 #endif
204       if (xcom_full_receive_global_view) {
205         /* purecov: begin deadcode */
206         xcom_full_receive_global_view(site, message_id,
207                                       clone_node_set(site->global_node_set));
208         /* purecov: end */
209       } else if (xcom_receive_global_view) {
210         xcom_receive_global_view(site->start, message_id,
211                                  clone_node_set(site->global_node_set),
212                                  site->event_horizon);
213       }
214 #ifdef SUPPRESS_DUPLICATE_VIEWS
215     }
216 #endif
217   }
218 }
219 
deliver_config(app_data_ptr a)220 void deliver_config(app_data_ptr a) {
221   if (xcom_receive_config) {
222     /* purecov: begin deadcode */
223     xcom_receive_config(a);
224     /* purecov: end */
225   }
226 }
227 
deinit_xcom_interface()228 void deinit_xcom_interface() {
229 #ifdef SUPPRESS_DUPLICATE_VIEWS
230   free_node_set(&delivered_node_set);
231 #endif
232 }
233