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/pfs_events_waits.cc
25 Events waits data structures (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_sys.h"
30 #include "pfs_global.h"
31 #include "pfs_instr_class.h"
32 #include "pfs_instr.h"
33 #include "pfs_user.h"
34 #include "pfs_host.h"
35 #include "pfs_account.h"
36 #include "pfs_events_waits.h"
37 #include "pfs_atomic.h"
38 #include "pfs_buffer_container.h"
39 #include "pfs_builtin_memory.h"
40 #include "m_string.h"
41
42 PFS_ALIGNED ulong events_waits_history_long_size= 0;
43 /** Consumer flag for table EVENTS_WAITS_CURRENT. */
44 PFS_ALIGNED bool flag_events_waits_current= false;
45 /** Consumer flag for table EVENTS_WAITS_HISTORY. */
46 PFS_ALIGNED bool flag_events_waits_history= false;
47 /** Consumer flag for table EVENTS_WAITS_HISTORY_LONG. */
48 PFS_ALIGNED bool flag_events_waits_history_long= false;
49 /** Consumer flag for the global instrumentation. */
50 PFS_ALIGNED bool flag_global_instrumentation= false;
51 /** Consumer flag for the per thread instrumentation. */
52 PFS_ALIGNED bool flag_thread_instrumentation= false;
53
54 /** True if EVENTS_WAITS_HISTORY_LONG circular buffer is full. */
55 PFS_ALIGNED bool events_waits_history_long_full= false;
56 /** Index in EVENTS_WAITS_HISTORY_LONG circular buffer. */
57 PFS_ALIGNED PFS_cacheline_uint32 events_waits_history_long_index;
58 /** EVENTS_WAITS_HISTORY_LONG circular buffer. */
59 PFS_ALIGNED PFS_events_waits *events_waits_history_long_array= NULL;
60
61 /**
62 Initialize table EVENTS_WAITS_HISTORY_LONG.
63 @param events_waits_history_long_sizing table sizing
64 */
init_events_waits_history_long(uint events_waits_history_long_sizing)65 int init_events_waits_history_long(uint events_waits_history_long_sizing)
66 {
67 events_waits_history_long_size= events_waits_history_long_sizing;
68 events_waits_history_long_full= false;
69 PFS_atomic::store_u32(&events_waits_history_long_index.m_u32, 0);
70
71 if (events_waits_history_long_size == 0)
72 return 0;
73
74 events_waits_history_long_array=
75 PFS_MALLOC_ARRAY(& builtin_memory_waits_history_long,
76 events_waits_history_long_size,
77 sizeof(PFS_events_waits), PFS_events_waits,
78 MYF(MY_ZEROFILL));
79
80 return (events_waits_history_long_array ? 0 : 1);
81 }
82
83 /** Cleanup table EVENTS_WAITS_HISTORY_LONG. */
cleanup_events_waits_history_long(void)84 void cleanup_events_waits_history_long(void)
85 {
86 PFS_FREE_ARRAY(& builtin_memory_waits_history_long,
87 events_waits_history_long_size, sizeof(PFS_events_waits),
88 events_waits_history_long_array);
89 events_waits_history_long_array= NULL;
90 }
91
copy_events_waits(PFS_events_waits * dest,const PFS_events_waits * source)92 static inline void copy_events_waits(PFS_events_waits *dest,
93 const PFS_events_waits *source)
94 {
95 memcpy(dest, source, sizeof(PFS_events_waits));
96 }
97
98 /**
99 Insert a wait record in table EVENTS_WAITS_HISTORY.
100 @param thread thread that executed the wait
101 @param wait record to insert
102 */
insert_events_waits_history(PFS_thread * thread,PFS_events_waits * wait)103 void insert_events_waits_history(PFS_thread *thread, PFS_events_waits *wait)
104 {
105 if (unlikely(events_waits_history_per_thread == 0))
106 return;
107
108 uint index= thread->m_waits_history_index;
109
110 /*
111 A concurrent thread executing TRUNCATE TABLE EVENTS_WAITS_CURRENT
112 could alter the data that this thread is inserting,
113 causing a potential race condition.
114 We are not testing for this and insert a possibly empty record,
115 to make this thread (the writer) faster.
116 This is ok, the readers of m_waits_history will filter this out.
117 */
118 copy_events_waits(&thread->m_waits_history[index], wait);
119
120 index++;
121 if (index >= events_waits_history_per_thread)
122 {
123 index= 0;
124 thread->m_waits_history_full= true;
125 }
126 thread->m_waits_history_index= index;
127 }
128
129 /**
130 Insert a wait record in table EVENTS_WAITS_HISTORY_LONG.
131 @param wait record to insert
132 */
insert_events_waits_history_long(PFS_events_waits * wait)133 void insert_events_waits_history_long(PFS_events_waits *wait)
134 {
135 if (unlikely(events_waits_history_long_size == 0))
136 return;
137
138 uint index= PFS_atomic::add_u32(&events_waits_history_long_index.m_u32, 1);
139
140 index= index % events_waits_history_long_size;
141 if (index == 0)
142 events_waits_history_long_full= true;
143
144 /* See related comment in insert_events_waits_history. */
145 copy_events_waits(&events_waits_history_long_array[index], wait);
146 }
147
fct_reset_events_waits_current(PFS_thread * pfs_thread)148 static void fct_reset_events_waits_current(PFS_thread *pfs_thread)
149 {
150 PFS_events_waits *pfs_wait= pfs_thread->m_events_waits_stack;
151 PFS_events_waits *pfs_wait_last= pfs_wait + WAIT_STACK_SIZE;
152
153 for ( ; pfs_wait < pfs_wait_last; pfs_wait++)
154 pfs_wait->m_wait_class= NO_WAIT_CLASS;
155 }
156
157
158 /** Reset table EVENTS_WAITS_CURRENT data. */
reset_events_waits_current(void)159 void reset_events_waits_current(void)
160 {
161 global_thread_container.apply_all(fct_reset_events_waits_current);
162 }
163
fct_reset_events_waits_history(PFS_thread * pfs_thread)164 static void fct_reset_events_waits_history(PFS_thread *pfs_thread)
165 {
166 PFS_events_waits *wait= pfs_thread->m_waits_history;
167 PFS_events_waits *wait_last= wait + events_waits_history_per_thread;
168
169 pfs_thread->m_waits_history_index= 0;
170 pfs_thread->m_waits_history_full= false;
171 for ( ; wait < wait_last; wait++)
172 wait->m_wait_class= NO_WAIT_CLASS;
173 }
174
175 /** Reset table EVENTS_WAITS_HISTORY data. */
reset_events_waits_history(void)176 void reset_events_waits_history(void)
177 {
178 global_thread_container.apply_all(fct_reset_events_waits_history);
179 }
180
181 /** Reset table EVENTS_WAITS_HISTORY_LONG data. */
reset_events_waits_history_long(void)182 void reset_events_waits_history_long(void)
183 {
184 PFS_atomic::store_u32(&events_waits_history_long_index.m_u32, 0);
185 events_waits_history_long_full= false;
186
187 PFS_events_waits *wait= events_waits_history_long_array;
188 PFS_events_waits *wait_last= wait + events_waits_history_long_size;
189 for ( ; wait < wait_last; wait++)
190 wait->m_wait_class= NO_WAIT_CLASS;
191 }
192
fct_reset_events_waits_by_thread(PFS_thread * thread)193 static void fct_reset_events_waits_by_thread(PFS_thread *thread)
194 {
195 PFS_account *account= sanitize_account(thread->m_account);
196 PFS_user *user= sanitize_user(thread->m_user);
197 PFS_host *host= sanitize_host(thread->m_host);
198 aggregate_thread_waits(thread, account, user, host);
199 }
200
201 /** Reset table EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME data. */
reset_events_waits_by_thread()202 void reset_events_waits_by_thread()
203 {
204 global_thread_container.apply(fct_reset_events_waits_by_thread);
205 }
206
fct_reset_events_waits_by_account(PFS_account * pfs)207 static void fct_reset_events_waits_by_account(PFS_account *pfs)
208 {
209 PFS_user *user= sanitize_user(pfs->m_user);
210 PFS_host *host= sanitize_host(pfs->m_host);
211 pfs->aggregate_waits(user, host);
212 }
213
214 /** Reset table EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME data. */
reset_events_waits_by_account()215 void reset_events_waits_by_account()
216 {
217 global_account_container.apply(fct_reset_events_waits_by_account);
218 }
219
fct_reset_events_waits_by_user(PFS_user * pfs)220 static void fct_reset_events_waits_by_user(PFS_user *pfs)
221 {
222 pfs->aggregate_waits();
223 }
224
225 /** Reset table EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME data. */
reset_events_waits_by_user()226 void reset_events_waits_by_user()
227 {
228 global_user_container.apply(fct_reset_events_waits_by_user);
229 }
230
fct_reset_events_waits_by_host(PFS_host * pfs)231 static void fct_reset_events_waits_by_host(PFS_host *pfs)
232 {
233 pfs->aggregate_waits();
234 }
235
236 /** Reset table EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME data. */
reset_events_waits_by_host()237 void reset_events_waits_by_host()
238 {
239 global_host_container.apply(fct_reset_events_waits_by_host);
240 }
241
fct_reset_table_waits_by_table(PFS_table_share * pfs)242 static void fct_reset_table_waits_by_table(PFS_table_share *pfs)
243 {
244 pfs->aggregate();
245 }
246
reset_table_waits_by_table()247 void reset_table_waits_by_table()
248 {
249 global_table_share_container.apply(fct_reset_table_waits_by_table);
250 }
251
fct_reset_table_io_waits_by_table(PFS_table_share * pfs)252 static void fct_reset_table_io_waits_by_table(PFS_table_share *pfs)
253 {
254 pfs->aggregate_io();
255 }
256
reset_table_io_waits_by_table()257 void reset_table_io_waits_by_table()
258 {
259 global_table_share_container.apply(fct_reset_table_io_waits_by_table);
260 }
261
fct_reset_table_lock_waits_by_table(PFS_table_share * pfs)262 static void fct_reset_table_lock_waits_by_table(PFS_table_share *pfs)
263 {
264 pfs->aggregate_lock();
265 }
266
reset_table_lock_waits_by_table()267 void reset_table_lock_waits_by_table()
268 {
269 global_table_share_container.apply(fct_reset_table_lock_waits_by_table);
270 }
271
fct_reset_table_waits_by_table_handle(PFS_table * pfs)272 void fct_reset_table_waits_by_table_handle(PFS_table *pfs)
273 {
274 pfs->sanitized_aggregate();
275 }
276
reset_table_waits_by_table_handle()277 void reset_table_waits_by_table_handle()
278 {
279 global_table_container.apply(fct_reset_table_waits_by_table_handle);
280 }
281
fct_reset_table_io_waits_by_table_handle(PFS_table * pfs)282 void fct_reset_table_io_waits_by_table_handle(PFS_table *pfs)
283 {
284 pfs->sanitized_aggregate_io();
285 }
286
reset_table_io_waits_by_table_handle()287 void reset_table_io_waits_by_table_handle()
288 {
289 global_table_container.apply(fct_reset_table_io_waits_by_table_handle);
290 }
291
fct_reset_table_lock_waits_by_table_handle(PFS_table * pfs)292 void fct_reset_table_lock_waits_by_table_handle(PFS_table *pfs)
293 {
294 pfs->sanitized_aggregate_lock();
295 }
296
reset_table_lock_waits_by_table_handle()297 void reset_table_lock_waits_by_table_handle()
298 {
299 global_table_container.apply(fct_reset_table_lock_waits_by_table_handle);
300 }
301
302