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 St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @file storage/perfschema/table_ews_by_thread_by_event_name.cc
25 Table EVENTS_WAITS_SUMMARY_BY_HOST_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_thread_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_thread_by_event_name::m_table_lock;
40
41 static const TABLE_FIELD_TYPE field_types[]=
42 {
43 {
44 { C_STRING_WITH_LEN("THREAD_ID") },
45 { C_STRING_WITH_LEN("bigint(20)") },
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_thread_by_event_name::m_field_def=
82 { 7, field_types };
83
84 PFS_engine_table_share
85 table_ews_by_thread_by_event_name::m_share=
86 {
87 { C_STRING_WITH_LEN("events_waits_summary_by_thread_by_event_name") },
88 &pfs_truncatable_acl,
89 table_ews_by_thread_by_event_name::create,
90 NULL, /* write_row */
91 table_ews_by_thread_by_event_name::delete_all_rows,
92 table_ews_by_thread_by_event_name::get_row_count,
93 sizeof(pos_ews_by_thread_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_thread_by_event_name::create(void)
102 {
103 return new table_ews_by_thread_by_event_name();
104 }
105
106 int
delete_all_rows(void)107 table_ews_by_thread_by_event_name::delete_all_rows(void)
108 {
109 reset_events_waits_by_thread();
110 return 0;
111 }
112
113 ha_rows
get_row_count(void)114 table_ews_by_thread_by_event_name::get_row_count(void)
115 {
116 return global_thread_container.get_row_count() * wait_class_max;
117 }
118
table_ews_by_thread_by_event_name()119 table_ews_by_thread_by_event_name::table_ews_by_thread_by_event_name()
120 : PFS_engine_table(&m_share, &m_pos),
121 m_row_exists(false), m_pos(), m_next_pos()
122 {}
123
reset_position(void)124 void table_ews_by_thread_by_event_name::reset_position(void)
125 {
126 m_pos.reset();
127 m_next_pos.reset();
128 }
129
rnd_next(void)130 int table_ews_by_thread_by_event_name::rnd_next(void)
131 {
132 PFS_thread *thread;
133 PFS_instr_class *instr_class;
134 bool has_more_thread= true;
135
136 for (m_pos.set_at(&m_next_pos);
137 has_more_thread;
138 m_pos.next_thread())
139 {
140 thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
141 if (thread != NULL)
142 {
143 for ( ;
144 m_pos.has_more_view();
145 m_pos.next_view())
146 {
147 switch (m_pos.m_index_2)
148 {
149 case pos_ews_by_thread_by_event_name::VIEW_MUTEX:
150 instr_class= find_mutex_class(m_pos.m_index_3);
151 break;
152 case pos_ews_by_thread_by_event_name::VIEW_RWLOCK:
153 instr_class= find_rwlock_class(m_pos.m_index_3);
154 break;
155 case pos_ews_by_thread_by_event_name::VIEW_COND:
156 instr_class= find_cond_class(m_pos.m_index_3);
157 break;
158 case pos_ews_by_thread_by_event_name::VIEW_FILE:
159 instr_class= find_file_class(m_pos.m_index_3);
160 break;
161 case pos_ews_by_thread_by_event_name::VIEW_TABLE:
162 instr_class= find_table_class(m_pos.m_index_3);
163 break;
164 case pos_ews_by_thread_by_event_name::VIEW_SOCKET:
165 instr_class= find_socket_class(m_pos.m_index_3);
166 break;
167 case pos_ews_by_thread_by_event_name::VIEW_IDLE:
168 instr_class= find_idle_class(m_pos.m_index_3);
169 break;
170 case pos_ews_by_thread_by_event_name::VIEW_METADATA:
171 instr_class= find_metadata_class(m_pos.m_index_3);
172 break;
173 default:
174 assert(false);
175 instr_class= NULL;
176 break;
177 }
178
179 if (instr_class != NULL)
180 {
181 make_row(thread, instr_class);
182 m_next_pos.set_after(&m_pos);
183 return 0;
184 }
185 }
186 }
187 }
188
189 return HA_ERR_END_OF_FILE;
190 }
191
192 int
rnd_pos(const void * pos)193 table_ews_by_thread_by_event_name::rnd_pos(const void *pos)
194 {
195 PFS_thread *thread;
196 PFS_instr_class *instr_class;
197
198 set_position(pos);
199
200 thread= global_thread_container.get(m_pos.m_index_1);
201 if (thread != NULL)
202 {
203 switch (m_pos.m_index_2)
204 {
205 case pos_ews_by_thread_by_event_name::VIEW_MUTEX:
206 instr_class= find_mutex_class(m_pos.m_index_3);
207 break;
208 case pos_ews_by_thread_by_event_name::VIEW_RWLOCK:
209 instr_class= find_rwlock_class(m_pos.m_index_3);
210 break;
211 case pos_ews_by_thread_by_event_name::VIEW_COND:
212 instr_class= find_cond_class(m_pos.m_index_3);
213 break;
214 case pos_ews_by_thread_by_event_name::VIEW_FILE:
215 instr_class= find_file_class(m_pos.m_index_3);
216 break;
217 case pos_ews_by_thread_by_event_name::VIEW_TABLE:
218 instr_class= find_table_class(m_pos.m_index_3);
219 break;
220 case pos_ews_by_thread_by_event_name::VIEW_SOCKET:
221 instr_class= find_socket_class(m_pos.m_index_3);
222 break;
223 case pos_ews_by_thread_by_event_name::VIEW_IDLE:
224 instr_class= find_idle_class(m_pos.m_index_3);
225 break;
226 case pos_ews_by_thread_by_event_name::VIEW_METADATA:
227 instr_class= find_metadata_class(m_pos.m_index_3);
228 break;
229 default:
230 assert(false);
231 instr_class= NULL;
232 }
233
234 if (instr_class)
235 {
236 make_row(thread, instr_class);
237 return 0;
238 }
239 }
240
241 return HA_ERR_RECORD_DELETED;
242 }
243
244 void table_ews_by_thread_by_event_name
make_row(PFS_thread * thread,PFS_instr_class * klass)245 ::make_row(PFS_thread *thread, PFS_instr_class *klass)
246 {
247 pfs_optimistic_state lock;
248 m_row_exists= false;
249
250 /* Protect this reader against a thread termination */
251 thread->m_lock.begin_optimistic_lock(&lock);
252
253 m_row.m_thread_internal_id= thread->m_thread_internal_id;
254
255 m_row.m_event_name.make_row(klass);
256
257 PFS_connection_wait_visitor visitor(klass);
258 PFS_connection_iterator::visit_thread(thread, &visitor);
259
260 /*
261 If the aggregation for this class is deferred, then we must pull the
262 current wait stats from the instances associated with this thread.
263 */
264 if (klass->is_deferred())
265 {
266 /* Visit instances owned by this thread. Do not visit the class. */
267 PFS_instance_wait_visitor inst_visitor;
268 PFS_instance_iterator::visit_instances(klass, &inst_visitor,
269 thread, false);
270 /* Combine the deferred stats and global stats */
271 visitor.m_stat.aggregate(&inst_visitor.m_stat);
272 }
273
274 if (! thread->m_lock.end_optimistic_lock(&lock))
275 return;
276
277 m_row_exists= true;
278
279 get_normalizer(klass);
280 m_row.m_stat.set(m_normalizer, & visitor.m_stat);
281 }
282
283 int table_ews_by_thread_by_event_name
read_row_values(TABLE * table,unsigned char *,Field ** fields,bool read_all)284 ::read_row_values(TABLE *table, unsigned char *, Field **fields,
285 bool read_all)
286 {
287 Field *f;
288
289 if (unlikely(! m_row_exists))
290 return HA_ERR_RECORD_DELETED;
291
292 /* Set the null bits */
293 assert(table->s->null_bytes == 0);
294
295 for (; (f= *fields) ; fields++)
296 {
297 if (read_all || bitmap_is_set(table->read_set, f->field_index))
298 {
299 switch(f->field_index)
300 {
301 case 0: /* THREAD_ID */
302 set_field_ulonglong(f, m_row.m_thread_internal_id);
303 break;
304 case 1: /* EVENT_NAME */
305 m_row.m_event_name.set_field(f);
306 break;
307 default: /* 2, ... COUNT/SUM/MIN/AVG/MAX */
308 m_row.m_stat.set_field(f->field_index - 2, f);
309 break;
310 }
311 }
312 }
313
314 return 0;
315 }
316
317