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