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