1 /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
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 Foundation,
21   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 /**
24   @file storage/perfschema/table_setup_instruments.cc
25   Table SETUP_INSTRUMENTS (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_builtin_memory.h"
32 #include "pfs_instr.h"
33 #include "pfs_column_types.h"
34 #include "pfs_column_values.h"
35 #include "table_setup_instruments.h"
36 #include "pfs_global.h"
37 #include "pfs_setup_object.h"
38 #include "field.h"
39 
40 THR_LOCK table_setup_instruments::m_table_lock;
41 
42 static const TABLE_FIELD_TYPE field_types[]=
43 {
44   {
45     { C_STRING_WITH_LEN("NAME") },
46     { C_STRING_WITH_LEN("varchar(128)") },
47     { NULL, 0}
48   },
49   {
50     { C_STRING_WITH_LEN("ENABLED") },
51     { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
52     { NULL, 0}
53   },
54   {
55     { C_STRING_WITH_LEN("TIMED") },
56     { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
57     { NULL, 0}
58   }
59 };
60 
61 TABLE_FIELD_DEF
62 table_setup_instruments::m_field_def=
63 { 3, field_types };
64 
65 PFS_engine_table_share
66 table_setup_instruments::m_share=
67 {
68   { C_STRING_WITH_LEN("setup_instruments") },
69   &pfs_updatable_acl,
70   table_setup_instruments::create,
71   NULL, /* write_row */
72   NULL, /* delete_all_rows */
73   table_setup_instruments::get_row_count,
74   sizeof(pos_setup_instruments),
75   &m_table_lock,
76   &m_field_def,
77   false, /* checked */
78   false  /* perpetual */
79 };
80 
create(void)81 PFS_engine_table* table_setup_instruments::create(void)
82 {
83   return new table_setup_instruments();
84 }
85 
86 ha_rows
get_row_count(void)87 table_setup_instruments::get_row_count(void)
88 {
89   return wait_class_max
90     + stage_class_max
91     + statement_class_max
92     + transaction_class_max
93     + memory_class_max;
94 }
95 
table_setup_instruments()96 table_setup_instruments::table_setup_instruments()
97   : PFS_engine_table(&m_share, &m_pos),
98     m_pos(), m_next_pos()
99 {}
100 
reset_position(void)101 void table_setup_instruments::reset_position(void)
102 {
103   m_pos.reset();
104   m_next_pos.reset();
105 }
106 
rnd_next(void)107 int table_setup_instruments::rnd_next(void)
108 {
109   PFS_instr_class *instr_class= NULL;
110   PFS_builtin_memory_class *pfs_builtin;
111   bool update_enabled;
112   bool update_timed;
113 
114   /* Do not advertise hard coded instruments when disabled. */
115   if (! pfs_initialized)
116     return HA_ERR_END_OF_FILE;
117 
118   for (m_pos.set_at(&m_next_pos);
119        m_pos.has_more_view();
120        m_pos.next_view())
121   {
122     update_enabled= true;
123     update_timed= true;
124 
125     switch (m_pos.m_index_1)
126     {
127     case pos_setup_instruments::VIEW_MUTEX:
128       instr_class= find_mutex_class(m_pos.m_index_2);
129       break;
130     case pos_setup_instruments::VIEW_RWLOCK:
131       instr_class= find_rwlock_class(m_pos.m_index_2);
132       break;
133     case pos_setup_instruments::VIEW_COND:
134       instr_class= find_cond_class(m_pos.m_index_2);
135       break;
136     case pos_setup_instruments::VIEW_THREAD:
137       /* Not used yet  */
138       break;
139     case pos_setup_instruments::VIEW_FILE:
140       instr_class= find_file_class(m_pos.m_index_2);
141       break;
142     case pos_setup_instruments::VIEW_TABLE:
143       instr_class= find_table_class(m_pos.m_index_2);
144       break;
145     case pos_setup_instruments::VIEW_STAGE:
146       instr_class= find_stage_class(m_pos.m_index_2);
147       break;
148     case pos_setup_instruments::VIEW_STATEMENT:
149       instr_class= find_statement_class(m_pos.m_index_2);
150       break;
151     case pos_setup_instruments::VIEW_TRANSACTION:
152       instr_class= find_transaction_class(m_pos.m_index_2);
153       break;
154     case pos_setup_instruments::VIEW_SOCKET:
155       instr_class= find_socket_class(m_pos.m_index_2);
156       break;
157     case pos_setup_instruments::VIEW_IDLE:
158       instr_class= find_idle_class(m_pos.m_index_2);
159       break;
160     case pos_setup_instruments::VIEW_BUILTIN_MEMORY:
161       update_enabled= false;
162       update_timed= false;
163       pfs_builtin= find_builtin_memory_class(m_pos.m_index_2);
164       if (pfs_builtin != NULL)
165         instr_class= & pfs_builtin->m_class;
166       else
167         instr_class= NULL;
168       break;
169     case pos_setup_instruments::VIEW_MEMORY:
170       update_timed= false;
171       instr_class= find_memory_class(m_pos.m_index_2);
172       break;
173     case pos_setup_instruments::VIEW_METADATA:
174       instr_class= find_metadata_class(m_pos.m_index_2);
175       break;
176     }
177     if (instr_class)
178     {
179       make_row(instr_class, update_enabled, update_timed);
180       m_next_pos.set_after(&m_pos);
181       return 0;
182     }
183   }
184 
185   return HA_ERR_END_OF_FILE;
186 }
187 
rnd_pos(const void * pos)188 int table_setup_instruments::rnd_pos(const void *pos)
189 {
190   PFS_instr_class *instr_class= NULL;
191   PFS_builtin_memory_class *pfs_builtin;
192   bool update_enabled;
193   bool update_timed;
194 
195   /* Do not advertise hard coded instruments when disabled. */
196   if (! pfs_initialized)
197     return HA_ERR_END_OF_FILE;
198 
199   set_position(pos);
200 
201   update_enabled= true;
202   update_timed= true;
203 
204   switch (m_pos.m_index_1)
205   {
206   case pos_setup_instruments::VIEW_MUTEX:
207     instr_class= find_mutex_class(m_pos.m_index_2);
208     break;
209   case pos_setup_instruments::VIEW_RWLOCK:
210     instr_class= find_rwlock_class(m_pos.m_index_2);
211     break;
212   case pos_setup_instruments::VIEW_COND:
213     instr_class= find_cond_class(m_pos.m_index_2);
214     break;
215   case pos_setup_instruments::VIEW_THREAD:
216     /* Not used yet */
217     break;
218   case pos_setup_instruments::VIEW_FILE:
219     instr_class= find_file_class(m_pos.m_index_2);
220     break;
221   case pos_setup_instruments::VIEW_TABLE:
222     instr_class= find_table_class(m_pos.m_index_2);
223     break;
224   case pos_setup_instruments::VIEW_STAGE:
225     instr_class= find_stage_class(m_pos.m_index_2);
226     break;
227   case pos_setup_instruments::VIEW_STATEMENT:
228     instr_class= find_statement_class(m_pos.m_index_2);
229     break;
230   case pos_setup_instruments::VIEW_TRANSACTION:
231     instr_class= find_transaction_class(m_pos.m_index_2);
232     break;
233   case pos_setup_instruments::VIEW_SOCKET:
234     instr_class= find_socket_class(m_pos.m_index_2);
235     break;
236   case pos_setup_instruments::VIEW_IDLE:
237     instr_class= find_idle_class(m_pos.m_index_2);
238     break;
239   case pos_setup_instruments::VIEW_BUILTIN_MEMORY:
240     update_enabled= false;
241     update_timed= false;
242     pfs_builtin= find_builtin_memory_class(m_pos.m_index_2);
243     if (pfs_builtin != NULL)
244       instr_class= & pfs_builtin->m_class;
245     else
246       instr_class= NULL;
247     break;
248   case pos_setup_instruments::VIEW_MEMORY:
249     update_timed= false;
250     instr_class= find_memory_class(m_pos.m_index_2);
251     break;
252   case pos_setup_instruments::VIEW_METADATA:
253     instr_class= find_metadata_class(m_pos.m_index_2);
254     break;
255   }
256   if (instr_class)
257   {
258     make_row(instr_class, update_enabled, update_timed);
259     return 0;
260   }
261 
262   return HA_ERR_RECORD_DELETED;
263 }
264 
make_row(PFS_instr_class * klass,bool update_enabled,bool update_timed)265 void table_setup_instruments::make_row(PFS_instr_class *klass, bool update_enabled, bool update_timed)
266 {
267   m_row.m_instr_class= klass;
268   m_row.m_update_enabled= update_enabled;
269   m_row.m_update_timed= update_timed;
270 }
271 
read_row_values(TABLE * table,unsigned char *,Field ** fields,bool read_all)272 int table_setup_instruments::read_row_values(TABLE *table,
273                                              unsigned char *,
274                                              Field **fields,
275                                              bool read_all)
276 {
277   Field *f;
278 
279   assert(table->s->null_bytes == 0);
280 
281   /*
282     The row always exist, the instrument classes
283     are static and never disappear.
284   */
285 
286   for (; (f= *fields) ; fields++)
287   {
288     if (read_all || bitmap_is_set(table->read_set, f->field_index))
289     {
290       switch(f->field_index)
291       {
292       case 0: /* NAME */
293         set_field_varchar_utf8(f, m_row.m_instr_class->m_name, m_row.m_instr_class->m_name_length);
294         break;
295       case 1: /* ENABLED */
296         set_field_enum(f, m_row.m_instr_class->m_enabled ? ENUM_YES : ENUM_NO);
297         break;
298       case 2: /* TIMED */
299         set_field_enum(f, m_row.m_instr_class->m_timed ? ENUM_YES : ENUM_NO);
300         break;
301       default:
302         assert(false);
303       }
304     }
305   }
306 
307   return 0;
308 }
309 
update_row_values(TABLE * table,const unsigned char *,unsigned char *,Field ** fields)310 int table_setup_instruments::update_row_values(TABLE *table,
311                                                const unsigned char *,
312                                                unsigned char *,
313                                                Field **fields)
314 {
315   Field *f;
316   enum_yes_no value;
317 
318   for (; (f= *fields) ; fields++)
319   {
320     if (bitmap_is_set(table->write_set, f->field_index))
321     {
322       switch(f->field_index)
323       {
324       case 0: /* NAME */
325         return HA_ERR_WRONG_COMMAND;
326       case 1: /* ENABLED */
327         /* Do not raise error if m_update_enabled is false, silently ignore. */
328         if (m_row.m_update_enabled)
329         {
330           value= (enum_yes_no) get_field_enum(f);
331           m_row.m_instr_class->m_enabled= (value == ENUM_YES) ? true : false;
332         }
333         break;
334       case 2: /* TIMED */
335         /* Do not raise error if m_update_timed is false, silently ignore. */
336         if (m_row.m_update_timed)
337         {
338           value= (enum_yes_no) get_field_enum(f);
339           m_row.m_instr_class->m_timed= (value == ENUM_YES) ? true : false;
340         }
341         break;
342       default:
343         assert(false);
344       }
345     }
346   }
347 
348   switch (m_pos.m_index_1)
349   {
350     case pos_setup_instruments::VIEW_MUTEX:
351       update_mutex_derived_flags();
352       break;
353     case pos_setup_instruments::VIEW_RWLOCK:
354       update_rwlock_derived_flags();
355       break;
356     case pos_setup_instruments::VIEW_COND:
357       update_cond_derived_flags();
358       break;
359     case pos_setup_instruments::VIEW_THREAD:
360       /* Not used yet  */
361       break;
362     case pos_setup_instruments::VIEW_FILE:
363       update_file_derived_flags();
364       break;
365     case pos_setup_instruments::VIEW_TABLE:
366       update_table_derived_flags();
367       break;
368     case pos_setup_instruments::VIEW_STAGE:
369     case pos_setup_instruments::VIEW_STATEMENT:
370     case pos_setup_instruments::VIEW_TRANSACTION:
371       /* No flag to update. */
372       break;
373     case pos_setup_instruments::VIEW_SOCKET:
374       update_socket_derived_flags();
375       break;
376     case pos_setup_instruments::VIEW_IDLE:
377       /* No flag to update. */
378       break;
379     case pos_setup_instruments::VIEW_BUILTIN_MEMORY:
380     case pos_setup_instruments::VIEW_MEMORY:
381       /* No flag to update. */
382       break;
383     case pos_setup_instruments::VIEW_METADATA:
384       update_metadata_derived_flags();
385       break;
386     default:
387       assert(false);
388       break;
389   }
390 
391   return 0;
392 }
393 
394