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