1 /* Copyright (c) 2008, 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 Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 /**
24 @file storage/perfschema/table_events_waits_summary.cc
25 Table EVENTS_WAITS_SUMMARY_BY_xxx (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_events_waits_summary.h"
34 #include "pfs_global.h"
35 #include "field.h"
36
37 THR_LOCK table_events_waits_summary_by_instance::m_table_lock;
38
39 static const TABLE_FIELD_TYPE ews_by_instance_field_types[]=
40 {
41 {
42 { C_STRING_WITH_LEN("EVENT_NAME") },
43 { C_STRING_WITH_LEN("varchar(128)") },
44 { NULL, 0}
45 },
46 {
47 { C_STRING_WITH_LEN("OBJECT_INSTANCE_BEGIN") },
48 { C_STRING_WITH_LEN("bigint(20)") },
49 { NULL, 0}
50 },
51 {
52 { C_STRING_WITH_LEN("COUNT_STAR") },
53 { C_STRING_WITH_LEN("bigint(20)") },
54 { NULL, 0}
55 },
56 {
57 { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
58 { C_STRING_WITH_LEN("bigint(20)") },
59 { NULL, 0}
60 },
61 {
62 { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
63 { C_STRING_WITH_LEN("bigint(20)") },
64 { NULL, 0}
65 },
66 {
67 { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
68 { C_STRING_WITH_LEN("bigint(20)") },
69 { NULL, 0}
70 },
71 {
72 { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
73 { C_STRING_WITH_LEN("bigint(20)") },
74 { NULL, 0}
75 }
76 };
77
78 TABLE_FIELD_DEF
79 table_events_waits_summary_by_instance::m_field_def=
80 { 7, ews_by_instance_field_types };
81
82 PFS_engine_table_share
83 table_events_waits_summary_by_instance::m_share=
84 {
85 { C_STRING_WITH_LEN("events_waits_summary_by_instance") },
86 &pfs_truncatable_acl,
87 table_events_waits_summary_by_instance::create,
88 NULL, /* write_row */
89 table_events_waits_summary_by_instance::delete_all_rows,
90 table_all_instr::get_row_count,
91 sizeof(pos_all_instr),
92 &m_table_lock,
93 &m_field_def,
94 false, /* checked */
95 false /* perpetual */
96 };
97
create(void)98 PFS_engine_table* table_events_waits_summary_by_instance::create(void)
99 {
100 return new table_events_waits_summary_by_instance();
101 }
102
delete_all_rows(void)103 int table_events_waits_summary_by_instance::delete_all_rows(void)
104 {
105 reset_events_waits_by_instance();
106 return 0;
107 }
108
109 table_events_waits_summary_by_instance
table_events_waits_summary_by_instance()110 ::table_events_waits_summary_by_instance()
111 : table_all_instr(&m_share), m_row_exists(false)
112 {}
113
114 void table_events_waits_summary_by_instance
make_instr_row(PFS_instr * pfs,PFS_instr_class * klass,const void * object_instance_begin,PFS_single_stat * pfs_stat)115 ::make_instr_row(PFS_instr *pfs, PFS_instr_class *klass,
116 const void *object_instance_begin,
117 PFS_single_stat *pfs_stat)
118 {
119 pfs_optimistic_state lock;
120 m_row_exists= false;
121
122 /*
123 Protect this reader against a mutex/rwlock/cond destroy,
124 file delete, table drop.
125 */
126 pfs->m_lock.begin_optimistic_lock(&lock);
127
128 m_row.m_name= klass->m_name;
129 m_row.m_name_length= klass->m_name_length;
130 m_row.m_object_instance_addr= (intptr) object_instance_begin;
131
132 get_normalizer(klass);
133 m_row.m_stat.set(m_normalizer, pfs_stat);
134
135 if (pfs->m_lock.end_optimistic_lock(&lock))
136 m_row_exists= true;
137 }
138
139 /**
140 Build a row, for mutex statistics in a thread.
141 @param pfs the mutex this cursor is reading
142 */
make_mutex_row(PFS_mutex * pfs)143 void table_events_waits_summary_by_instance::make_mutex_row(PFS_mutex *pfs)
144 {
145 PFS_mutex_class *safe_class;
146 safe_class= sanitize_mutex_class(pfs->m_class);
147 if (unlikely(safe_class == NULL))
148 return;
149
150 make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_mutex_stat.m_wait_stat);
151 }
152
153 /**
154 Build a row, for rwlock statistics in a thread.
155 @param pfs the rwlock this cursor is reading
156 */
make_rwlock_row(PFS_rwlock * pfs)157 void table_events_waits_summary_by_instance::make_rwlock_row(PFS_rwlock *pfs)
158 {
159 PFS_rwlock_class *safe_class;
160 safe_class= sanitize_rwlock_class(pfs->m_class);
161 if (unlikely(safe_class == NULL))
162 return;
163
164 make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_rwlock_stat.m_wait_stat);
165 }
166
167 /**
168 Build a row, for condition statistics in a thread.
169 @param pfs the condition this cursor is reading
170 */
make_cond_row(PFS_cond * pfs)171 void table_events_waits_summary_by_instance::make_cond_row(PFS_cond *pfs)
172 {
173 PFS_cond_class *safe_class;
174 safe_class= sanitize_cond_class(pfs->m_class);
175 if (unlikely(safe_class == NULL))
176 return;
177
178 make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_cond_stat.m_wait_stat);
179 }
180
181 /**
182 Build a row, for file statistics in a thread.
183 @param pfs the file this cursor is reading
184 */
make_file_row(PFS_file * pfs)185 void table_events_waits_summary_by_instance::make_file_row(PFS_file *pfs)
186 {
187 PFS_file_class *safe_class;
188 safe_class= sanitize_file_class(pfs->m_class);
189 if (unlikely(safe_class == NULL))
190 return;
191
192 PFS_single_stat sum;
193 pfs->m_file_stat.m_io_stat.sum_waits(& sum);
194 /*
195 Files don't have a in memory structure associated to it,
196 so we use the address of the PFS_file buffer as object_instance_begin
197 */
198 make_instr_row(pfs, safe_class, pfs, & sum);
199 }
200
201 /**
202 Build a row, for socket statistics in a thread.
203 @param pfs the socket this cursor is reading
204 */
make_socket_row(PFS_socket * pfs)205 void table_events_waits_summary_by_instance::make_socket_row(PFS_socket *pfs)
206 {
207 PFS_socket_class *safe_class;
208 safe_class= sanitize_socket_class(pfs->m_class);
209 if (unlikely(safe_class == NULL))
210 return;
211
212 /*
213 Consolidate wait times and byte counts for individual operations. This is
214 done by the consumer in order to reduce overhead on the socket instrument.
215 */
216 PFS_byte_stat pfs_stat;
217 pfs->m_socket_stat.m_io_stat.sum(&pfs_stat);
218
219 /*
220 Sockets don't have an associated in-memory structure, so use the address of
221 the PFS_socket buffer as object_instance_begin.
222 */
223 make_instr_row(pfs, safe_class, pfs, &pfs_stat);
224 }
225
226 int table_events_waits_summary_by_instance
read_row_values(TABLE * table,unsigned char *,Field ** fields,bool read_all)227 ::read_row_values(TABLE *table, unsigned char *, Field **fields,
228 bool read_all)
229 {
230 Field *f;
231
232 if (unlikely(! m_row_exists))
233 return HA_ERR_RECORD_DELETED;
234
235 /* Set the null bits */
236 assert(table->s->null_bytes == 0);
237
238 for (; (f= *fields) ; fields++)
239 {
240 if (read_all || bitmap_is_set(table->read_set, f->field_index))
241 {
242 switch(f->field_index)
243 {
244 case 0: /* NAME */
245 set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
246 break;
247 case 1: /* OBJECT_INSTANCE */
248 set_field_ulonglong(f, m_row.m_object_instance_addr);
249 break;
250 case 2: /* COUNT */
251 set_field_ulonglong(f, m_row.m_stat.m_count);
252 break;
253 case 3: /* SUM */
254 set_field_ulonglong(f, m_row.m_stat.m_sum);
255 break;
256 case 4: /* MIN */
257 set_field_ulonglong(f, m_row.m_stat.m_min);
258 break;
259 case 5: /* AVG */
260 set_field_ulonglong(f, m_row.m_stat.m_avg);
261 break;
262 case 6: /* MAX */
263 set_field_ulonglong(f, m_row.m_stat.m_max);
264 break;
265 default:
266 assert(false);
267 }
268 }
269 }
270
271 return 0;
272 }
273
274