1 /*
2 Copyright (c) 2014, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24 /**
25 @file storage/perfschema/table_replication_group_member_stats.cc
26 Table replication_group_member_stats (implementation).
27 */
28
29 #define HAVE_REPLICATION
30
31 #include "my_global.h"
32 #include "table_replication_group_member_stats.h"
33 #include "pfs_instr_class.h"
34 #include "pfs_instr.h"
35 #include "log.h"
36 #include "rpl_group_replication.h"
37
38 /*
39 Callbacks implementation for GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS.
40 */
set_channel_name(void * const context,const char & value,size_t length)41 static void set_channel_name(void* const context, const char& value,
42 size_t length)
43 {
44 struct st_row_group_member_stats* row=
45 static_cast<struct st_row_group_member_stats*>(context);
46 const size_t max= CHANNEL_NAME_LENGTH;
47 length= std::min(length, max);
48
49 row->channel_name_length= length;
50 memcpy(row->channel_name, &value, length);
51 }
52
set_view_id(void * const context,const char & value,size_t length)53 static void set_view_id(void* const context, const char& value, size_t length)
54 {
55 struct st_row_group_member_stats* row=
56 static_cast<struct st_row_group_member_stats*>(context);
57 const size_t max= HOSTNAME_LENGTH;
58 length= std::min(length, max);
59
60 row->view_id_length= length;
61 memcpy(row->view_id, &value, length);
62 }
63
set_member_id(void * const context,const char & value,size_t length)64 static void set_member_id(void* const context, const char& value, size_t length)
65 {
66 struct st_row_group_member_stats* row=
67 static_cast<struct st_row_group_member_stats*>(context);
68 const size_t max= UUID_LENGTH;
69 length= std::min(length, max);
70
71 row->member_id_length= length;
72 memcpy(row->member_id, &value, length);
73 }
74
set_transactions_committed(void * const context,const char & value,size_t length)75 static void set_transactions_committed(void* const context, const char& value,
76 size_t length)
77 {
78 struct st_row_group_member_stats* row=
79 static_cast<struct st_row_group_member_stats*>(context);
80
81 if (row->trx_committed != NULL)
82 my_free(row->trx_committed);
83
84 row->trx_committed_length= length;
85 row->trx_committed= (char*) my_malloc(PSI_NOT_INSTRUMENTED,
86 length,
87 MYF(0));
88 memcpy(row->trx_committed, &value, length);
89 }
90
set_last_conflict_free_transaction(void * const context,const char & value,size_t length)91 static void set_last_conflict_free_transaction(void* const context,
92 const char& value, size_t length)
93 {
94 struct st_row_group_member_stats* row=
95 static_cast<struct st_row_group_member_stats*>(context);
96 const size_t max= Gtid::MAX_TEXT_LENGTH+1;
97 length= std::min(length, max);
98
99 row->last_cert_trx_length= length;
100 memcpy(row->last_cert_trx, &value, length);
101 }
102
set_transactions_in_queue(void * const context,unsigned long long int value)103 static void set_transactions_in_queue(void* const context,
104 unsigned long long int value)
105 {
106 struct st_row_group_member_stats* row=
107 static_cast<struct st_row_group_member_stats*>(context);
108 row->trx_in_queue= value;
109 }
110
set_transactions_certified(void * const context,unsigned long long int value)111 static void set_transactions_certified(void* const context,
112 unsigned long long int value)
113 {
114 struct st_row_group_member_stats* row=
115 static_cast<struct st_row_group_member_stats*>(context);
116 row->trx_checked= value;
117 }
118
set_transactions_conflicts_detected(void * const context,unsigned long long int value)119 static void set_transactions_conflicts_detected(void* const context,
120 unsigned long long int value)
121 {
122 struct st_row_group_member_stats* row=
123 static_cast<struct st_row_group_member_stats*>(context);
124 row->trx_conflicts= value;
125 }
126
set_transactions_rows_in_validation(void * const context,unsigned long long int value)127 static void set_transactions_rows_in_validation(void* const context,
128 unsigned long long int value)
129 {
130 struct st_row_group_member_stats* row=
131 static_cast<struct st_row_group_member_stats*>(context);
132 row->trx_rows_validating= value;
133 }
134
135
136 THR_LOCK table_replication_group_member_stats::m_table_lock;
137
138 static const TABLE_FIELD_TYPE field_types[]=
139 {
140 {
141 {C_STRING_WITH_LEN("CHANNEL_NAME")},
142 {C_STRING_WITH_LEN("char(64)")},
143 {NULL, 0}
144 },
145 {
146 {C_STRING_WITH_LEN("VIEW_ID")},
147 {C_STRING_WITH_LEN("char(60)")},
148 {NULL, 0}
149 },
150 {
151 {C_STRING_WITH_LEN("MEMBER_ID")},
152 {C_STRING_WITH_LEN("char(36)")},
153 {NULL, 0}
154 },
155 {
156 {C_STRING_WITH_LEN("COUNT_TRANSACTIONS_IN_QUEUE")},
157 {C_STRING_WITH_LEN("bigint")},
158 {NULL, 0}
159 },
160 {
161 {C_STRING_WITH_LEN("COUNT_TRANSACTIONS_CHECKED")},
162 {C_STRING_WITH_LEN("bigint")},
163 {NULL, 0}
164 },
165 {
166 {C_STRING_WITH_LEN("COUNT_CONFLICTS_DETECTED")},
167 {C_STRING_WITH_LEN("bigint")},
168 {NULL, 0}
169 },
170 {
171 {C_STRING_WITH_LEN("COUNT_TRANSACTIONS_ROWS_VALIDATING")},
172 {C_STRING_WITH_LEN("bigint")},
173 {NULL, 0}
174 },
175 {
176 {C_STRING_WITH_LEN("TRANSACTIONS_COMMITTED_ALL_MEMBERS")},
177 {C_STRING_WITH_LEN("longtext")},
178 {NULL, 0}
179 },
180 {
181 {C_STRING_WITH_LEN("LAST_CONFLICT_FREE_TRANSACTION")},
182 {C_STRING_WITH_LEN("text")},
183 {NULL, 0}
184 }
185 };
186
187 TABLE_FIELD_DEF
188 table_replication_group_member_stats::m_field_def=
189 { 9, field_types };
190
191 PFS_engine_table_share
192 table_replication_group_member_stats::m_share=
193 {
194 { C_STRING_WITH_LEN("replication_group_member_stats") },
195 &pfs_readonly_acl,
196 &table_replication_group_member_stats::create,
197 NULL, /* write_row */
198 NULL, /* delete_all_rows */
199 table_replication_group_member_stats::get_row_count,
200 sizeof(PFS_simple_index), /* ref length */
201 &m_table_lock,
202 &m_field_def,
203 false, /* checked */
204 false /* perpetual */
205 };
206
create(void)207 PFS_engine_table* table_replication_group_member_stats::create(void)
208 {
209 return new table_replication_group_member_stats();
210 }
211
table_replication_group_member_stats()212 table_replication_group_member_stats::table_replication_group_member_stats()
213 : PFS_engine_table(&m_share, &m_pos),
214 m_row_exists(false), m_pos(0), m_next_pos(0)
215 {
216 m_row.trx_committed= NULL;
217 }
218
~table_replication_group_member_stats()219 table_replication_group_member_stats::~table_replication_group_member_stats()
220 {
221 if (m_row.trx_committed != NULL)
222 {
223 my_free(m_row.trx_committed);
224 m_row.trx_committed= NULL;
225 }
226 }
227
reset_position(void)228 void table_replication_group_member_stats::reset_position(void)
229 {
230 m_pos.m_index= 0;
231 m_next_pos.m_index= 0;
232 }
233
get_row_count()234 ha_rows table_replication_group_member_stats::get_row_count()
235 {
236 uint row_count= 0;
237
238 if (is_group_replication_plugin_loaded())
239 row_count= 1;
240
241 return row_count;
242 }
243
rnd_next(void)244 int table_replication_group_member_stats::rnd_next(void)
245 {
246 if (!is_group_replication_plugin_loaded())
247 return HA_ERR_END_OF_FILE;
248
249 m_pos.set_at(&m_next_pos);
250 if (m_pos.m_index == 0)
251 {
252 make_row();
253 m_next_pos.set_after(&m_pos);
254 return 0;
255 }
256
257 return HA_ERR_END_OF_FILE;
258 }
259
rnd_pos(const void * pos)260 int table_replication_group_member_stats::rnd_pos(const void *pos)
261 {
262 if (get_row_count() == 0)
263 return HA_ERR_END_OF_FILE;
264
265 set_position(pos);
266 assert(m_pos.m_index < 1);
267 make_row();
268
269 return 0;
270 }
271
make_row()272 void table_replication_group_member_stats::make_row()
273 {
274 DBUG_ENTER("table_replication_group_member_stats::make_row");
275 // Set default values.
276 m_row_exists= false;
277 m_row.channel_name_length= 0;
278 m_row.view_id_length= 0;
279 m_row.member_id_length= 0;
280 m_row.trx_committed_length= 0;
281 m_row.last_cert_trx_length= 0;
282 m_row.trx_in_queue= 0;
283 m_row.trx_checked= 0;
284 m_row.trx_conflicts= 0;
285 m_row.trx_rows_validating= 0;
286
287 // Set callbacks on GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS.
288 const GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS callbacks=
289 {
290 &m_row,
291 &set_channel_name,
292 &set_view_id,
293 &set_member_id,
294 &set_transactions_committed,
295 &set_last_conflict_free_transaction,
296 &set_transactions_in_queue,
297 &set_transactions_certified,
298 &set_transactions_conflicts_detected,
299 &set_transactions_rows_in_validation,
300 };
301
302 // Query plugin and let callbacks do their job.
303 if (get_group_replication_group_member_stats_info(callbacks))
304 {
305 DBUG_PRINT("info", ("Group Replication stats not available!"));
306 }
307 else
308 {
309 m_row_exists= true;
310 }
311
312 DBUG_VOID_RETURN;
313 }
314
315
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)316 int table_replication_group_member_stats::read_row_values(TABLE *table,
317 unsigned char *buf,
318 Field **fields,
319 bool read_all)
320 {
321 Field *f;
322
323 if (unlikely(! m_row_exists))
324 return HA_ERR_RECORD_DELETED;
325
326 assert(table->s->null_bytes == 0);
327 buf[0]= 0;
328
329 for (; (f= *fields) ; fields++)
330 {
331 if (read_all || bitmap_is_set(table->read_set, f->field_index))
332 {
333 switch(f->field_index)
334 {
335 case 0: /** channel_name */
336 set_field_char_utf8(f, m_row.channel_name,
337 m_row.channel_name_length);
338 break;
339 case 1: /** view id */
340 set_field_char_utf8(f, m_row.view_id, m_row.view_id_length);
341 break;
342 case 2: /** member_id */
343 set_field_char_utf8(f, m_row.member_id, m_row.member_id_length);
344 break;
345 case 3: /** transaction_in_queue */
346 set_field_ulonglong(f, m_row.trx_in_queue);
347 break;
348 case 4: /** transactions_certified */
349 set_field_ulonglong(f, m_row.trx_checked);
350 break;
351 case 5: /** negatively_certified_transaction */
352 set_field_ulonglong(f, m_row.trx_conflicts);
353 break;
354 case 6: /** certification_db_size */
355 set_field_ulonglong(f, m_row.trx_rows_validating);
356 break;
357 case 7: /** stable_set */
358 set_field_longtext_utf8(f, m_row.trx_committed,
359 m_row.trx_committed_length);
360 break;
361 case 8: /** last_certified_transaction */
362 set_field_longtext_utf8(f, m_row.last_cert_trx,
363 m_row.last_cert_trx_length);
364
365 break;
366 default:
367 assert(false);
368 }
369 }
370 }
371 return 0;
372 }
373