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_ews_by_account_by_event_name.cc
25   Table EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME (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_ews_by_account_by_event_name.h"
34 #include "pfs_global.h"
35 #include "pfs_visitor.h"
36 #include "pfs_buffer_container.h"
37 #include "field.h"
38 
39 THR_LOCK table_ews_by_account_by_event_name::m_table_lock;
40 
41 static const TABLE_FIELD_TYPE field_types[]=
42 {
43   {
44     { C_STRING_WITH_LEN("USER") },
45     { C_STRING_WITH_LEN("char(" USERNAME_CHAR_LENGTH_STR ")") },
46     { NULL, 0}
47   },
48   {
49     { C_STRING_WITH_LEN("HOST") },
50     { C_STRING_WITH_LEN("char(60)") },
51     { NULL, 0}
52   },
53   {
54     { C_STRING_WITH_LEN("EVENT_NAME") },
55     { C_STRING_WITH_LEN("varchar(128)") },
56     { NULL, 0}
57   },
58   {
59     { C_STRING_WITH_LEN("COUNT_STAR") },
60     { C_STRING_WITH_LEN("bigint(20)") },
61     { NULL, 0}
62   },
63   {
64     { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
65     { C_STRING_WITH_LEN("bigint(20)") },
66     { NULL, 0}
67   },
68   {
69     { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
70     { C_STRING_WITH_LEN("bigint(20)") },
71     { NULL, 0}
72   },
73   {
74     { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
75     { C_STRING_WITH_LEN("bigint(20)") },
76     { NULL, 0}
77   },
78   {
79     { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
80     { C_STRING_WITH_LEN("bigint(20)") },
81     { NULL, 0}
82   }
83 };
84 
85 TABLE_FIELD_DEF
86 table_ews_by_account_by_event_name::m_field_def=
87 { 8, field_types };
88 
89 PFS_engine_table_share
90 table_ews_by_account_by_event_name::m_share=
91 {
92   { C_STRING_WITH_LEN("events_waits_summary_by_account_by_event_name") },
93   &pfs_truncatable_acl,
94   table_ews_by_account_by_event_name::create,
95   NULL, /* write_row */
96   table_ews_by_account_by_event_name::delete_all_rows,
97   table_ews_by_account_by_event_name::get_row_count,
98   sizeof(pos_ews_by_account_by_event_name),
99   &m_table_lock,
100   &m_field_def,
101   false, /* checked */
102   false  /* perpetual */
103 };
104 
105 PFS_engine_table*
create(void)106 table_ews_by_account_by_event_name::create(void)
107 {
108   return new table_ews_by_account_by_event_name();
109 }
110 
111 int
delete_all_rows(void)112 table_ews_by_account_by_event_name::delete_all_rows(void)
113 {
114   reset_events_waits_by_thread();
115   reset_events_waits_by_account();
116   return 0;
117 }
118 
119 ha_rows
get_row_count(void)120 table_ews_by_account_by_event_name::get_row_count(void)
121 {
122   return global_account_container.get_row_count() * wait_class_max;
123 }
124 
table_ews_by_account_by_event_name()125 table_ews_by_account_by_event_name::table_ews_by_account_by_event_name()
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_ews_by_account_by_event_name::reset_position(void)
131 {
132   m_pos.reset();
133   m_next_pos.reset();
134 }
135 
rnd_next(void)136 int table_ews_by_account_by_event_name::rnd_next(void)
137 {
138   PFS_account *account;
139   PFS_instr_class *instr_class;
140   bool has_more_account= true;
141 
142   for (m_pos.set_at(&m_next_pos);
143        has_more_account;
144        m_pos.next_account())
145   {
146     account= global_account_container.get(m_pos.m_index_1, & has_more_account);
147     if (account != NULL)
148     {
149       for ( ;
150            m_pos.has_more_view();
151            m_pos.next_view())
152       {
153         switch (m_pos.m_index_2)
154         {
155         case pos_ews_by_account_by_event_name::VIEW_MUTEX:
156           instr_class= find_mutex_class(m_pos.m_index_3);
157           break;
158         case pos_ews_by_account_by_event_name::VIEW_RWLOCK:
159           instr_class= find_rwlock_class(m_pos.m_index_3);
160           break;
161         case pos_ews_by_account_by_event_name::VIEW_COND:
162           instr_class= find_cond_class(m_pos.m_index_3);
163           break;
164         case pos_ews_by_account_by_event_name::VIEW_FILE:
165           instr_class= find_file_class(m_pos.m_index_3);
166           break;
167         case pos_ews_by_account_by_event_name::VIEW_TABLE:
168           instr_class= find_table_class(m_pos.m_index_3);
169           break;
170         case pos_ews_by_account_by_event_name::VIEW_SOCKET:
171           instr_class= find_socket_class(m_pos.m_index_3);
172           break;
173         case pos_ews_by_account_by_event_name::VIEW_IDLE:
174           instr_class= find_idle_class(m_pos.m_index_3);
175           break;
176         case pos_ews_by_account_by_event_name::VIEW_METADATA:
177           instr_class= find_metadata_class(m_pos.m_index_3);
178           break;
179         default:
180           instr_class= NULL;
181           assert(false);
182           break;
183         }
184 
185         if (instr_class)
186         {
187           make_row(account, instr_class);
188           m_next_pos.set_after(&m_pos);
189           return 0;
190         }
191       }
192     }
193   }
194 
195   return HA_ERR_END_OF_FILE;
196 }
197 
198 int
rnd_pos(const void * pos)199 table_ews_by_account_by_event_name::rnd_pos(const void *pos)
200 {
201   PFS_account *account;
202   PFS_instr_class *instr_class;
203 
204   set_position(pos);
205 
206   account= global_account_container.get(m_pos.m_index_1);
207   if (account == NULL)
208     return HA_ERR_RECORD_DELETED;
209 
210   switch (m_pos.m_index_2)
211   {
212   case pos_ews_by_account_by_event_name::VIEW_MUTEX:
213     instr_class= find_mutex_class(m_pos.m_index_3);
214     break;
215   case pos_ews_by_account_by_event_name::VIEW_RWLOCK:
216     instr_class= find_rwlock_class(m_pos.m_index_3);
217     break;
218   case pos_ews_by_account_by_event_name::VIEW_COND:
219     instr_class= find_cond_class(m_pos.m_index_3);
220     break;
221   case pos_ews_by_account_by_event_name::VIEW_FILE:
222     instr_class= find_file_class(m_pos.m_index_3);
223     break;
224   case pos_ews_by_account_by_event_name::VIEW_TABLE:
225     instr_class= find_table_class(m_pos.m_index_3);
226     break;
227   case pos_ews_by_account_by_event_name::VIEW_SOCKET:
228     instr_class= find_socket_class(m_pos.m_index_3);
229     break;
230   case pos_ews_by_account_by_event_name::VIEW_IDLE:
231     instr_class= find_idle_class(m_pos.m_index_3);
232     break;
233   case pos_ews_by_account_by_event_name::VIEW_METADATA:
234     instr_class= find_metadata_class(m_pos.m_index_3);
235     break;
236   default:
237     instr_class= NULL;
238     assert(false);
239   }
240   if (instr_class)
241   {
242     make_row(account, instr_class);
243     return 0;
244   }
245 
246   return HA_ERR_RECORD_DELETED;
247 }
248 
249 void table_ews_by_account_by_event_name
make_row(PFS_account * account,PFS_instr_class * klass)250 ::make_row(PFS_account *account, PFS_instr_class *klass)
251 {
252   pfs_optimistic_state lock;
253   m_row_exists= false;
254 
255   account->m_lock.begin_optimistic_lock(&lock);
256 
257   if (m_row.m_account.make_row(account))
258     return;
259 
260   m_row.m_event_name.make_row(klass);
261 
262   PFS_connection_wait_visitor visitor(klass);
263   PFS_connection_iterator::visit_account(account,
264                                          true,  /* threads */
265                                          false, /* THDs */
266                                          & visitor);
267 
268   if (! account->m_lock.end_optimistic_lock(&lock))
269     return;
270 
271   m_row_exists= true;
272 
273   get_normalizer(klass);
274   m_row.m_stat.set(m_normalizer, & visitor.m_stat);
275 }
276 
277 int table_ews_by_account_by_event_name
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)278 ::read_row_values(TABLE *table, unsigned char *buf, Field **fields,
279                   bool read_all)
280 {
281   Field *f;
282 
283   if (unlikely(! m_row_exists))
284     return HA_ERR_RECORD_DELETED;
285 
286   /* Set the null bits */
287   assert(table->s->null_bytes == 1);
288   buf[0]= 0;
289 
290   for (; (f= *fields) ; fields++)
291   {
292     if (read_all || bitmap_is_set(table->read_set, f->field_index))
293     {
294       switch(f->field_index)
295       {
296       case 0: /* USER */
297       case 1: /* HOST */
298         m_row.m_account.set_field(f->field_index, f);
299         break;
300       case 2: /* EVENT_NAME */
301         m_row.m_event_name.set_field(f);
302         break;
303       default: /* 3, ... COUNT/SUM/MIN/AVG/MAX */
304         m_row.m_stat.set_field(f->field_index - 3, f);
305         break;
306       }
307     }
308   }
309 
310   return 0;
311 }
312 
313