1 /* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
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 as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software Foundation,
14 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15
16 /**
17 @file storage/perfschema/pfs_events_waits.cc
18 Events waits data structures (implementation).
19 */
20
21 #include "my_global.h"
22 #include "my_sys.h"
23 #include "pfs_global.h"
24 #include "pfs_instr.h"
25 #include "pfs_events_waits.h"
26 #include "pfs_atomic.h"
27 #include "m_string.h"
28
29 ulong events_waits_history_long_size= 0;
30 /** Consumer flag for table EVENTS_WAITS_CURRENT. */
31 bool flag_events_waits_current= true;
32 /** Consumer flag for table EVENTS_WAITS_HISTORY. */
33 bool flag_events_waits_history= true;
34 /** Consumer flag for table EVENTS_WAITS_HISTORY_LONG. */
35 bool flag_events_waits_history_long= true;
36 /** Consumer flag for table EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
37 bool flag_events_waits_summary_by_thread_by_event_name= true;
38 /** Consumer flag for table EVENTS_WAITS_SUMMARY_BY_EVENT_NAME. */
39 bool flag_events_waits_summary_by_event_name= true;
40 /** Consumer flag for table EVENTS_WAITS_SUMMARY_BY_INSTANCE. */
41 bool flag_events_waits_summary_by_instance= true;
42 bool flag_events_locks_summary_by_event_name= true;
43 bool flag_events_locks_summary_by_instance= true;
44 /** Consumer flag for table FILE_SUMMARY_BY_EVENT_NAME. */
45 bool flag_file_summary_by_event_name= true;
46 /** Consumer flag for table FILE_SUMMARY_BY_INSTANCE. */
47 bool flag_file_summary_by_instance= true;
48
49 /** True if EVENTS_WAITS_HISTORY_LONG circular buffer is full. */
50 bool events_waits_history_long_full= false;
51 /** Index in EVENTS_WAITS_HISTORY_LONG circular buffer. */
52 volatile uint32 events_waits_history_long_index= 0;
53 /** EVENTS_WAITS_HISTORY_LONG circular buffer. */
54 PFS_events_waits *events_waits_history_long_array= NULL;
55
56 /**
57 Initialize table EVENTS_WAITS_HISTORY_LONG.
58 @param events_waits_history_long_sizing table sizing
59 */
init_events_waits_history_long(uint events_waits_history_long_sizing)60 int init_events_waits_history_long(uint events_waits_history_long_sizing)
61 {
62 events_waits_history_long_size= events_waits_history_long_sizing;
63 events_waits_history_long_full= false;
64 PFS_atomic::store_u32(&events_waits_history_long_index, 0);
65
66 if (events_waits_history_long_size == 0)
67 return 0;
68
69 events_waits_history_long_array=
70 PFS_MALLOC_ARRAY(events_waits_history_long_size, PFS_events_waits,
71 MYF(MY_ZEROFILL));
72
73 return (events_waits_history_long_array ? 0 : 1);
74 }
75
76 /** Cleanup table EVENTS_WAITS_HISTORY_LONG. */
cleanup_events_waits_history_long(void)77 void cleanup_events_waits_history_long(void)
78 {
79 pfs_free(events_waits_history_long_array);
80 events_waits_history_long_array= NULL;
81 }
82
copy_events_waits(PFS_events_waits * dest,const PFS_events_waits * source)83 static inline void copy_events_waits(PFS_events_waits *dest,
84 const PFS_events_waits *source)
85 {
86 memcpy(dest, source, sizeof(PFS_events_waits));
87 }
88
89 /**
90 Insert a wait record in table EVENTS_WAITS_HISTORY.
91 @param thread thread that executed the wait
92 @param wait record to insert
93 */
insert_events_waits_history(PFS_thread * thread,PFS_events_waits * wait)94 void insert_events_waits_history(PFS_thread *thread, PFS_events_waits *wait)
95 {
96 if (unlikely(events_waits_history_per_thread == 0))
97 return;
98
99 uint index= thread->m_waits_history_index;
100
101 /*
102 A concurrent thread executing TRUNCATE TABLE EVENTS_WAITS_CURRENT
103 could alter the data that this thread is inserting,
104 causing a potential race condition.
105 We are not testing for this and insert a possibly empty record,
106 to make this thread (the writer) faster.
107 This is ok, the readers of m_waits_history will filter this out.
108 */
109 copy_events_waits(&thread->m_waits_history[index], wait);
110
111 index++;
112 if (index >= events_waits_history_per_thread)
113 {
114 index= 0;
115 thread->m_waits_history_full= true;
116 }
117 thread->m_waits_history_index= index;
118 }
119
120 /**
121 Insert a wait record in table EVENTS_WAITS_HISTORY_LONG.
122 @param wait record to insert
123 */
insert_events_waits_history_long(PFS_events_waits * wait)124 void insert_events_waits_history_long(PFS_events_waits *wait)
125 {
126 if (unlikely(events_waits_history_long_size == 0))
127 return;
128
129 uint index= PFS_atomic::add_u32(&events_waits_history_long_index, 1);
130
131 index= index % events_waits_history_long_size;
132 if (index == 0)
133 events_waits_history_long_full= true;
134
135 /* See related comment in insert_events_waits_history. */
136 copy_events_waits(&events_waits_history_long_array[index], wait);
137 }
138
139 /** Reset table EVENTS_WAITS_CURRENT data. */
reset_events_waits_current(void)140 void reset_events_waits_current(void)
141 {
142 PFS_thread *pfs_thread= thread_array;
143 PFS_thread *pfs_thread_last= thread_array + thread_max;
144
145 for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
146 {
147 PFS_wait_locker *locker= pfs_thread->m_wait_locker_stack;
148 PFS_wait_locker *locker_last= locker + LOCKER_STACK_SIZE;
149
150 for ( ; locker < locker_last; locker++)
151 locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
152 }
153 }
154
155 /** Reset table EVENTS_WAITS_HISTORY data. */
reset_events_waits_history(void)156 void reset_events_waits_history(void)
157 {
158 PFS_thread *pfs_thread= thread_array;
159 PFS_thread *pfs_thread_last= thread_array + thread_max;
160
161 for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
162 {
163 PFS_events_waits *wait= pfs_thread->m_waits_history;
164 PFS_events_waits *wait_last= wait + events_waits_history_per_thread;
165
166 pfs_thread->m_waits_history_index= 0;
167 pfs_thread->m_waits_history_full= false;
168 for ( ; wait < wait_last; wait++)
169 wait->m_wait_class= NO_WAIT_CLASS;
170 }
171 }
172
173 /** Reset table EVENTS_WAITS_HISTORY_LONG data. */
reset_events_waits_history_long(void)174 void reset_events_waits_history_long(void)
175 {
176 PFS_atomic::store_u32(&events_waits_history_long_index, 0);
177 events_waits_history_long_full= false;
178
179 PFS_events_waits *wait= events_waits_history_long_array;
180 PFS_events_waits *wait_last= wait + events_waits_history_long_size;
181 for ( ; wait < wait_last; wait++)
182 wait->m_wait_class= NO_WAIT_CLASS;
183 }
184
185