1 /* Copyright (c) 2010, 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
21   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22 
23 /**
24   @file storage/perfschema/table_os_global_by_type.cc
25   Table OBJECTS_SUMMARY_GLOBAL_BY_TYPE (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "table_os_global_by_type.h"
34 #include "pfs_global.h"
35 #include "pfs_buffer_container.h"
36 #include "field.h"
37 
38 THR_LOCK table_os_global_by_type::m_table_lock;
39 
40 static const TABLE_FIELD_TYPE field_types[]=
41 {
42   {
43     { C_STRING_WITH_LEN("OBJECT_TYPE") },
44     { C_STRING_WITH_LEN("varchar(64)") },
45     { NULL, 0}
46   },
47   {
48     { C_STRING_WITH_LEN("OBJECT_SCHEMA") },
49     { C_STRING_WITH_LEN("varchar(64)") },
50     { NULL, 0}
51   },
52   {
53     { C_STRING_WITH_LEN("OBJECT_NAME") },
54     { C_STRING_WITH_LEN("varchar(64)") },
55     { NULL, 0}
56   },
57   {
58     { C_STRING_WITH_LEN("COUNT_STAR") },
59     { C_STRING_WITH_LEN("bigint(20)") },
60     { NULL, 0}
61   },
62   {
63     { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
64     { C_STRING_WITH_LEN("bigint(20)") },
65     { NULL, 0}
66   },
67   {
68     { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
69     { C_STRING_WITH_LEN("bigint(20)") },
70     { NULL, 0}
71   },
72   {
73     { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
74     { C_STRING_WITH_LEN("bigint(20)") },
75     { NULL, 0}
76   },
77   {
78     { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
79     { C_STRING_WITH_LEN("bigint(20)") },
80     { NULL, 0}
81   }
82 };
83 
84 TABLE_FIELD_DEF
85 table_os_global_by_type::m_field_def=
86 { 8, field_types };
87 
88 PFS_engine_table_share
89 table_os_global_by_type::m_share=
90 {
91   { C_STRING_WITH_LEN("objects_summary_global_by_type") },
92   &pfs_truncatable_acl,
93   table_os_global_by_type::create,
94   NULL, /* write_row */
95   table_os_global_by_type::delete_all_rows,
96   table_os_global_by_type::get_row_count,
97   sizeof(pos_os_global_by_type),
98   &m_table_lock,
99   &m_field_def,
100   false, /* checked */
101   false  /* perpetual */
102 };
103 
104 PFS_engine_table*
create(void)105 table_os_global_by_type::create(void)
106 {
107   return new table_os_global_by_type();
108 }
109 
110 int
delete_all_rows(void)111 table_os_global_by_type::delete_all_rows(void)
112 {
113   reset_table_waits_by_table_handle();
114   reset_table_waits_by_table();
115   return 0;
116 }
117 
118 ha_rows
get_row_count(void)119 table_os_global_by_type::get_row_count(void)
120 {
121   return global_table_share_container.get_row_count() +
122     global_program_container.get_row_count();
123 }
124 
table_os_global_by_type()125 table_os_global_by_type::table_os_global_by_type()
126   : PFS_engine_table(&m_share, &m_pos),
127     m_row_exists(false), m_pos(), m_next_pos()
128 {}
129 
reset_position(void)130 void table_os_global_by_type::reset_position(void)
131 {
132   m_pos.reset();
133   m_next_pos.reset();
134 }
135 
rnd_next(void)136 int table_os_global_by_type::rnd_next(void)
137 {
138   for (m_pos.set_at(&m_next_pos);
139        m_pos.has_more_view();
140        m_pos.next_view())
141   {
142     switch (m_pos.m_index_1) {
143     case pos_os_global_by_type::VIEW_TABLE:
144       {
145         PFS_table_share *table_share;
146         bool has_more_share= true;
147 
148         for (;
149              has_more_share;
150              m_pos.m_index_2++)
151         {
152           table_share= global_table_share_container.get(m_pos.m_index_2, & has_more_share);
153           if (table_share != NULL)
154           {
155             make_table_row(table_share);
156             m_next_pos.set_after(&m_pos);
157             return 0;
158           }
159         }
160       }
161       break;
162     case pos_os_global_by_type::VIEW_PROGRAM:
163       {
164         PFS_program *pfs_program;
165         bool has_more_program= true;
166 
167         for (;
168              has_more_program;
169              m_pos.m_index_2++)
170         {
171           pfs_program= global_program_container.get(m_pos.m_index_2, & has_more_program);
172           if (pfs_program != NULL)
173           {
174             make_program_row(pfs_program);
175             m_next_pos.set_after(&m_pos);
176             return 0;
177           }
178         }
179       }
180       break;
181     default:
182       break;
183     }
184   }
185 
186   return HA_ERR_END_OF_FILE;
187 }
188 
189 int
rnd_pos(const void * pos)190 table_os_global_by_type::rnd_pos(const void *pos)
191 {
192   set_position(pos);
193 
194   switch (m_pos.m_index_1) {
195   case pos_os_global_by_type::VIEW_TABLE:
196     {
197       PFS_table_share *table_share;
198       table_share= global_table_share_container.get(m_pos.m_index_2);
199       if (table_share != NULL)
200       {
201         make_table_row(table_share);
202         return 0;
203       }
204     }
205     break;
206   case pos_os_global_by_type::VIEW_PROGRAM:
207     {
208       PFS_program *pfs_program;
209       pfs_program= global_program_container.get(m_pos.m_index_2);
210       if (pfs_program != NULL)
211       {
212         make_program_row(pfs_program);
213         return 0;
214       }
215     }
216     break;
217   default:
218     break;
219   }
220 
221   return HA_ERR_RECORD_DELETED;
222 }
223 
make_program_row(PFS_program * pfs_program)224 void table_os_global_by_type::make_program_row(PFS_program *pfs_program)
225 {
226   pfs_optimistic_state lock;
227   PFS_single_stat cumulated_stat;
228 
229   m_row_exists= false;
230 
231   pfs_program->m_lock.begin_optimistic_lock(&lock);
232 
233   m_row.m_object.make_row(pfs_program);
234 
235   time_normalizer *normalizer= time_normalizer::get(wait_timer);
236   m_row.m_stat.set(normalizer, &pfs_program->m_sp_stat.m_timer1_stat);
237 
238   if (! pfs_program->m_lock.end_optimistic_lock(&lock))
239     return;
240 
241   m_row_exists= true;
242 }
243 
make_table_row(PFS_table_share * share)244 void table_os_global_by_type::make_table_row(PFS_table_share *share)
245 {
246   pfs_optimistic_state lock;
247   PFS_single_stat cumulated_stat;
248   uint safe_key_count;
249 
250   m_row_exists= false;
251 
252   share->m_lock.begin_optimistic_lock(&lock);
253 
254   m_row.m_object.make_row(share);
255 
256   /* This is a dirty read, some thread can write data while we are reading it */
257   safe_key_count= sanitize_index_count(share->m_key_count);
258 
259   share->sum(& cumulated_stat, safe_key_count);
260 
261   if (! share->m_lock.end_optimistic_lock(&lock))
262     return;
263 
264   m_row_exists= true;
265 
266   if (share->get_refcount() > 0)
267   {
268     /* For all the table handles still opened ... */
269     PFS_table_iterator it= global_table_container.iterate();
270     PFS_table *table= it.scan_next();
271 
272     while (table != NULL)
273     {
274       if (table->m_share == share)
275       {
276         /*
277           If the opened table handle is for this table share,
278           aggregate the table handle statistics.
279         */
280         table->m_table_stat.sum(& cumulated_stat, safe_key_count);
281       }
282       table= it.scan_next();
283     }
284   }
285 
286   time_normalizer *normalizer= time_normalizer::get(wait_timer);
287   m_row.m_stat.set(normalizer, &cumulated_stat);
288 }
289 
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)290 int table_os_global_by_type::read_row_values(TABLE *table,
291                                              unsigned char *buf,
292                                              Field **fields,
293                                              bool read_all)
294 {
295   Field *f;
296 
297   if (unlikely(! m_row_exists))
298     return HA_ERR_RECORD_DELETED;
299 
300   /* Set the null bits */
301   assert(table->s->null_bytes == 1);
302   buf[0]= 0;
303 
304   for (; (f= *fields) ; fields++)
305   {
306     if (read_all || bitmap_is_set(table->read_set, f->field_index))
307     {
308       switch(f->field_index)
309       {
310       case 0: /* OBJECT_TYPE */
311         set_field_object_type(f, m_row.m_object.m_object_type);
312         break;
313       case 1: /* SCHEMA_NAME */
314         set_field_varchar_utf8(f, m_row.m_object.m_schema_name,
315                                m_row.m_object.m_schema_name_length);
316         break;
317       case 2: /* OBJECT_NAME */
318         set_field_varchar_utf8(f, m_row.m_object.m_object_name,
319                                m_row.m_object.m_object_name_length);
320         break;
321       case 3: /* COUNT */
322         set_field_ulonglong(f, m_row.m_stat.m_count);
323         break;
324       case 4: /* SUM */
325         set_field_ulonglong(f, m_row.m_stat.m_sum);
326         break;
327       case 5: /* MIN */
328         set_field_ulonglong(f, m_row.m_stat.m_min);
329         break;
330       case 6: /* AVG */
331         set_field_ulonglong(f, m_row.m_stat.m_avg);
332         break;
333       case 7: /* MAX */
334         set_field_ulonglong(f, m_row.m_stat.m_max);
335         break;
336       default:
337         assert(false);
338       }
339     }
340   }
341 
342   return 0;
343 }
344 
345