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 | #ifndef PFS_INSTR_CLASS_H |
17 | #define PFS_INSTR_CLASS_H |
18 | |
19 | #include "my_global.h" |
20 | #include "mysql_com.h" /* NAME_LEN */ |
21 | #include "lf.h" |
22 | #include "pfs_global.h" |
23 | |
24 | /** |
25 | @file storage/perfschema/pfs_instr_class.h |
26 | Performance schema instruments meta data (declarations). |
27 | */ |
28 | |
29 | /** |
30 | Maximum length of an instrument name. |
31 | For example, 'wait/sync/mutex/sql/LOCK_open' is an instrument name. |
32 | */ |
33 | #define PFS_MAX_INFO_NAME_LENGTH 128 |
34 | |
35 | /** |
36 | Maximum length of the 'full' prefix of an instrument name. |
37 | For example, for the instrument name 'wait/sync/mutex/sql/LOCK_open', |
38 | the full prefix is 'wait/sync/mutex/sql/', which in turn derives from |
39 | a prefix 'wait/sync/mutex' for mutexes, and a category of 'sql' for mutexes |
40 | of the sql layer in the server. |
41 | */ |
42 | #define PFS_MAX_FULL_PREFIX_NAME_LENGTH 32 |
43 | |
44 | #include <my_global.h> |
45 | #include <my_sys.h> |
46 | #include <mysql/psi/psi.h> |
47 | #include "pfs_lock.h" |
48 | #include "pfs_stat.h" |
49 | #include "pfs_column_types.h" |
50 | |
51 | struct PFS_global_param; |
52 | |
53 | /** |
54 | @addtogroup Performance_schema_buffers |
55 | @{ |
56 | */ |
57 | |
58 | extern my_bool pfs_enabled; |
59 | extern enum_timer_name *class_timers[]; |
60 | |
61 | /** Key, naming a synch instrument (mutex, rwlock, cond). */ |
62 | typedef unsigned int PFS_sync_key; |
63 | /** Key, naming a thread instrument. */ |
64 | typedef unsigned int PFS_thread_key; |
65 | /** Key, naming a file instrument. */ |
66 | typedef unsigned int PFS_file_key; |
67 | /** Key, naming a stage instrument. */ |
68 | typedef unsigned int PFS_stage_key; |
69 | /** Key, naming a statement instrument. */ |
70 | typedef unsigned int PFS_statement_key; |
71 | /** Key, naming a socket instrument. */ |
72 | typedef unsigned int PFS_socket_key; |
73 | |
74 | enum PFS_class_type |
75 | { |
76 | PFS_CLASS_NONE= 0, |
77 | PFS_CLASS_MUTEX= 1, |
78 | PFS_CLASS_RWLOCK= 2, |
79 | PFS_CLASS_COND= 3, |
80 | PFS_CLASS_FILE= 4, |
81 | PFS_CLASS_TABLE= 5, |
82 | PFS_CLASS_STAGE= 6, |
83 | PFS_CLASS_STATEMENT= 7, |
84 | PFS_CLASS_SOCKET= 8, |
85 | PFS_CLASS_TABLE_IO= 9, |
86 | PFS_CLASS_TABLE_LOCK= 10, |
87 | PFS_CLASS_IDLE= 11, |
88 | PFS_CLASS_LAST= PFS_CLASS_IDLE, |
89 | PFS_CLASS_MAX= PFS_CLASS_LAST + 1 |
90 | }; |
91 | |
92 | /** User-defined instrument configuration. */ |
93 | struct PFS_instr_config |
94 | { |
95 | /* Instrument name. */ |
96 | char *m_name; |
97 | /* Name length. */ |
98 | uint m_name_length; |
99 | /** Enabled flag. */ |
100 | bool m_enabled; |
101 | /** Timed flag. */ |
102 | bool m_timed; |
103 | }; |
104 | |
105 | extern DYNAMIC_ARRAY pfs_instr_config_array; |
106 | extern int pfs_instr_config_state; |
107 | |
108 | static const int PFS_INSTR_CONFIG_NOT_INITIALIZED= 0; |
109 | static const int PFS_INSTR_CONFIG_ALLOCATED= 1; |
110 | static const int PFS_INSTR_CONFIG_DEALLOCATED= 2; |
111 | |
112 | struct PFS_thread; |
113 | |
114 | extern uint mutex_class_start; |
115 | extern uint rwlock_class_start; |
116 | extern uint cond_class_start; |
117 | extern uint file_class_start; |
118 | extern uint socket_class_start; |
119 | extern uint wait_class_max; |
120 | |
121 | /** Information for all instrumentation. */ |
122 | struct PFS_instr_class |
123 | { |
124 | /** Class type */ |
125 | PFS_class_type m_type; |
126 | /** True if this instrument is enabled. */ |
127 | bool m_enabled; |
128 | /** True if this instrument is timed. */ |
129 | bool m_timed; |
130 | /** Instrument flags. */ |
131 | int m_flags; |
132 | /** |
133 | Instrument name index. |
134 | Self index in: |
135 | - EVENTS_WAITS_SUMMARY_*_BY_EVENT_NAME for waits |
136 | - EVENTS_STAGES_SUMMARY_*_BY_EVENT_NAME for stages |
137 | - EVENTS_STATEMENTS_SUMMARY_*_BY_EVENT_NAME for statements |
138 | */ |
139 | uint m_event_name_index; |
140 | /** Instrument name. */ |
141 | char m_name[PFS_MAX_INFO_NAME_LENGTH]; |
142 | /** Length in bytes of @c m_name. */ |
143 | uint m_name_length; |
144 | /** Timer associated with this class. */ |
145 | enum_timer_name *m_timer; |
146 | |
147 | bool is_singleton() const |
148 | { |
149 | return m_flags & PSI_FLAG_GLOBAL; |
150 | } |
151 | |
152 | bool is_mutable() const |
153 | { |
154 | return m_flags & PSI_FLAG_MUTABLE; |
155 | } |
156 | |
157 | static void set_enabled(PFS_instr_class *pfs, bool enabled); |
158 | static void set_timed(PFS_instr_class *pfs, bool timed); |
159 | |
160 | bool is_deferred() const |
161 | { |
162 | switch(m_type) |
163 | { |
164 | case PFS_CLASS_SOCKET: |
165 | return true; |
166 | break; |
167 | default: |
168 | return false; |
169 | break; |
170 | }; |
171 | } |
172 | }; |
173 | |
174 | struct PFS_mutex; |
175 | |
176 | /** Instrumentation metadata for a MUTEX. */ |
177 | struct PFS_ALIGNED PFS_mutex_class : public PFS_instr_class |
178 | { |
179 | /** Mutex usage statistics. */ |
180 | PFS_mutex_stat m_mutex_stat; |
181 | /** Singleton instance. */ |
182 | PFS_mutex *m_singleton; |
183 | }; |
184 | |
185 | struct PFS_rwlock; |
186 | |
187 | /** Instrumentation metadata for a RWLOCK. */ |
188 | struct PFS_ALIGNED PFS_rwlock_class : public PFS_instr_class |
189 | { |
190 | /** Rwlock usage statistics. */ |
191 | PFS_rwlock_stat m_rwlock_stat; |
192 | /** Singleton instance. */ |
193 | PFS_rwlock *m_singleton; |
194 | }; |
195 | |
196 | struct PFS_cond; |
197 | |
198 | /** Instrumentation metadata for a COND. */ |
199 | struct PFS_ALIGNED PFS_cond_class : public PFS_instr_class |
200 | { |
201 | /** |
202 | Condition usage statistics. |
203 | This statistic is not exposed in user visible tables yet. |
204 | */ |
205 | PFS_cond_stat m_cond_stat; |
206 | /** Singleton instance. */ |
207 | PFS_cond *m_singleton; |
208 | }; |
209 | |
210 | /** Instrumentation metadata of a thread. */ |
211 | struct PFS_ALIGNED PFS_thread_class |
212 | { |
213 | /** True if this thread instrument is enabled. */ |
214 | bool m_enabled; |
215 | /** Singleton instance. */ |
216 | PFS_thread *m_singleton; |
217 | /** Thread instrument name. */ |
218 | char m_name[PFS_MAX_INFO_NAME_LENGTH]; |
219 | /** Length in bytes of @c m_name. */ |
220 | uint m_name_length; |
221 | }; |
222 | |
223 | #define PFS_TABLESHARE_HASHKEY_SIZE (NAME_LEN + 1 + NAME_LEN + 1) |
224 | |
225 | /** Key identifying a table share. */ |
226 | struct PFS_table_share_key |
227 | { |
228 | /** |
229 | Hash search key. |
230 | This has to be a string for LF_HASH, |
231 | the format is "<enum_object_type><schema_name><0x00><object_name><0x00>" |
232 | @see create_table_def_key |
233 | */ |
234 | char m_hash_key[PFS_TABLESHARE_HASHKEY_SIZE]; |
235 | /** Length in bytes of @c m_hash_key. */ |
236 | uint m_key_length; |
237 | }; |
238 | |
239 | /** Table index or 'key' */ |
240 | struct PFS_table_key |
241 | { |
242 | /** Index name */ |
243 | char m_name[NAME_LEN]; |
244 | /** Length in bytes of @c m_name. */ |
245 | uint m_name_length; |
246 | }; |
247 | |
248 | /** Instrumentation metadata for a table share. */ |
249 | struct PFS_ALIGNED PFS_table_share |
250 | { |
251 | public: |
252 | uint32 get_version() |
253 | { return m_lock.get_version(); } |
254 | |
255 | enum_object_type get_object_type() |
256 | { |
257 | return (enum_object_type) m_key.m_hash_key[0]; |
258 | } |
259 | |
260 | void aggregate_io(void); |
261 | void aggregate_lock(void); |
262 | |
263 | inline void aggregate(void) |
264 | { |
265 | aggregate_io(); |
266 | aggregate_lock(); |
267 | } |
268 | |
269 | inline void init_refcount(void) |
270 | { |
271 | PFS_atomic::store_32(& m_refcount, 1); |
272 | } |
273 | |
274 | inline int get_refcount(void) |
275 | { |
276 | return PFS_atomic::load_32(& m_refcount); |
277 | } |
278 | |
279 | inline void inc_refcount(void) |
280 | { |
281 | PFS_atomic::add_32(& m_refcount, 1); |
282 | } |
283 | |
284 | inline void dec_refcount(void) |
285 | { |
286 | PFS_atomic::add_32(& m_refcount, -1); |
287 | } |
288 | |
289 | void refresh_setup_object_flags(PFS_thread *thread); |
290 | |
291 | /** Internal lock. */ |
292 | pfs_lock m_lock; |
293 | /** |
294 | True if table instrumentation is enabled. |
295 | This flag is computed from the content of table setup_objects. |
296 | */ |
297 | bool m_enabled; |
298 | /** |
299 | True if table instrumentation is timed. |
300 | This flag is computed from the content of table setup_objects. |
301 | */ |
302 | bool m_timed; |
303 | /** Search key. */ |
304 | PFS_table_share_key m_key; |
305 | /** Schema name. */ |
306 | const char *m_schema_name; |
307 | /** Length in bytes of @c m_schema_name. */ |
308 | uint m_schema_name_length; |
309 | /** Table name. */ |
310 | const char *m_table_name; |
311 | /** Length in bytes of @c m_table_name. */ |
312 | uint m_table_name_length; |
313 | /** Number of indexes. */ |
314 | uint m_key_count; |
315 | /** Table statistics. */ |
316 | PFS_table_stat m_table_stat; |
317 | /** Index names. */ |
318 | PFS_table_key m_keys[MAX_INDEXES]; |
319 | |
320 | private: |
321 | /** Number of opened table handles. */ |
322 | int m_refcount; |
323 | }; |
324 | |
325 | /** Statistics for the IDLE instrument. */ |
326 | extern PFS_single_stat global_idle_stat; |
327 | /** Statistics for dropped table io. */ |
328 | extern PFS_table_io_stat global_table_io_stat; |
329 | /** Statistics for dropped table lock. */ |
330 | extern PFS_table_lock_stat global_table_lock_stat; |
331 | |
332 | inline uint sanitize_index_count(uint count) |
333 | { |
334 | if (likely(count <= MAX_INDEXES)) |
335 | return count; |
336 | return 0; |
337 | } |
338 | |
339 | #define GLOBAL_TABLE_IO_EVENT_INDEX 0 |
340 | #define GLOBAL_TABLE_LOCK_EVENT_INDEX 1 |
341 | #define GLOBAL_IDLE_EVENT_INDEX 2 |
342 | |
343 | /** |
344 | Instrument controlling all table io. |
345 | This instrument is used with table SETUP_OBJECTS. |
346 | */ |
347 | extern PFS_instr_class global_table_io_class; |
348 | |
349 | /** |
350 | Instrument controlling all table lock. |
351 | This instrument is used with table SETUP_OBJECTS. |
352 | */ |
353 | extern PFS_instr_class global_table_lock_class; |
354 | |
355 | /** |
356 | Instrument controlling all idle waits. |
357 | */ |
358 | extern PFS_instr_class global_idle_class; |
359 | |
360 | struct PFS_file; |
361 | |
362 | /** Instrumentation metadata for a file. */ |
363 | struct PFS_ALIGNED PFS_file_class : public PFS_instr_class |
364 | { |
365 | /** File usage statistics. */ |
366 | PFS_file_stat m_file_stat; |
367 | /** Singleton instance. */ |
368 | PFS_file *m_singleton; |
369 | }; |
370 | |
371 | /** Instrumentation metadata for a stage. */ |
372 | struct PFS_ALIGNED PFS_stage_class : public PFS_instr_class |
373 | { |
374 | /** |
375 | Length of the 'stage/<component>/' prefix. |
376 | This is to extract 'foo' from 'stage/sql/foo'. |
377 | */ |
378 | uint m_prefix_length; |
379 | /** Stage usage statistics. */ |
380 | PFS_stage_stat m_stage_stat; |
381 | }; |
382 | |
383 | /** Instrumentation metadata for a statement. */ |
384 | struct PFS_ALIGNED PFS_statement_class : public PFS_instr_class |
385 | { |
386 | }; |
387 | |
388 | struct PFS_socket; |
389 | |
390 | /** Instrumentation metadata for a socket. */ |
391 | struct PFS_ALIGNED PFS_socket_class : public PFS_instr_class |
392 | { |
393 | /** Socket usage statistics. */ |
394 | PFS_socket_stat m_socket_stat; |
395 | /** Singleton instance. */ |
396 | PFS_socket *m_singleton; |
397 | }; |
398 | |
399 | void init_event_name_sizing(const PFS_global_param *param); |
400 | |
401 | void register_global_classes(); |
402 | |
403 | int init_sync_class(uint mutex_class_sizing, |
404 | uint rwlock_class_sizing, |
405 | uint cond_class_sizing); |
406 | |
407 | void cleanup_sync_class(); |
408 | int init_thread_class(uint thread_class_sizing); |
409 | void cleanup_thread_class(); |
410 | int init_table_share(uint table_share_sizing); |
411 | void cleanup_table_share(); |
412 | int init_table_share_hash(); |
413 | void cleanup_table_share_hash(); |
414 | int init_file_class(uint file_class_sizing); |
415 | void cleanup_file_class(); |
416 | int init_stage_class(uint stage_class_sizing); |
417 | void cleanup_stage_class(); |
418 | int init_statement_class(uint statement_class_sizing); |
419 | void cleanup_statement_class(); |
420 | int init_socket_class(uint socket_class_sizing); |
421 | void cleanup_socket_class(); |
422 | |
423 | PFS_sync_key register_mutex_class(const char *name, uint name_length, |
424 | int flags); |
425 | |
426 | PFS_sync_key register_rwlock_class(const char *name, uint name_length, |
427 | int flags); |
428 | |
429 | PFS_sync_key register_cond_class(const char *name, uint name_length, |
430 | int flags); |
431 | |
432 | PFS_thread_key register_thread_class(const char *name, uint name_length, |
433 | int flags); |
434 | |
435 | PFS_file_key register_file_class(const char *name, uint name_length, |
436 | int flags); |
437 | |
438 | PFS_stage_key register_stage_class(const char *name, |
439 | uint prefix_length, |
440 | uint name_length, |
441 | int flags); |
442 | |
443 | PFS_statement_key register_statement_class(const char *name, uint name_length, |
444 | int flags); |
445 | |
446 | PFS_socket_key register_socket_class(const char *name, uint name_length, |
447 | int flags); |
448 | |
449 | PFS_mutex_class *find_mutex_class(PSI_mutex_key key); |
450 | PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe); |
451 | PFS_rwlock_class *find_rwlock_class(PSI_rwlock_key key); |
452 | PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe); |
453 | PFS_cond_class *find_cond_class(PSI_cond_key key); |
454 | PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe); |
455 | PFS_thread_class *find_thread_class(PSI_thread_key key); |
456 | PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe); |
457 | PFS_file_class *find_file_class(PSI_file_key key); |
458 | PFS_file_class *sanitize_file_class(PFS_file_class *unsafe); |
459 | PFS_stage_class *find_stage_class(PSI_stage_key key); |
460 | PFS_stage_class *sanitize_stage_class(PFS_stage_class *unsafe); |
461 | PFS_statement_class *find_statement_class(PSI_statement_key key); |
462 | PFS_statement_class *sanitize_statement_class(PFS_statement_class *unsafe); |
463 | PFS_instr_class *find_table_class(uint index); |
464 | PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe); |
465 | PFS_socket_class *find_socket_class(PSI_socket_key key); |
466 | PFS_socket_class *sanitize_socket_class(PFS_socket_class *unsafe); |
467 | PFS_instr_class *find_idle_class(uint index); |
468 | PFS_instr_class *sanitize_idle_class(PFS_instr_class *unsafe); |
469 | |
470 | PFS_table_share *find_or_create_table_share(PFS_thread *thread, |
471 | bool temporary, |
472 | const TABLE_SHARE *share); |
473 | void release_table_share(PFS_table_share *pfs); |
474 | void drop_table_share(PFS_thread *thread, |
475 | bool temporary, |
476 | const char *schema_name, uint schema_name_length, |
477 | const char *table_name, uint table_name_length); |
478 | |
479 | PFS_table_share *sanitize_table_share(PFS_table_share *unsafe); |
480 | |
481 | extern ulong mutex_class_max; |
482 | extern ulong mutex_class_lost; |
483 | extern ulong rwlock_class_max; |
484 | extern ulong rwlock_class_lost; |
485 | extern ulong cond_class_max; |
486 | extern ulong cond_class_lost; |
487 | extern ulong thread_class_max; |
488 | extern ulong thread_class_lost; |
489 | extern ulong file_class_max; |
490 | extern ulong file_class_lost; |
491 | extern ulong stage_class_max; |
492 | extern ulong stage_class_lost; |
493 | extern ulong statement_class_max; |
494 | extern ulong statement_class_lost; |
495 | extern ulong socket_class_max; |
496 | extern ulong socket_class_lost; |
497 | extern ulong table_share_max; |
498 | extern ulong table_share_lost; |
499 | |
500 | /* Exposing the data directly, for iterators. */ |
501 | |
502 | extern PFS_mutex_class *mutex_class_array; |
503 | extern PFS_rwlock_class *rwlock_class_array; |
504 | extern PFS_cond_class *cond_class_array; |
505 | extern PFS_file_class *file_class_array; |
506 | extern PFS_table_share *table_share_array; |
507 | |
508 | void reset_events_waits_by_class(); |
509 | void reset_file_class_io(); |
510 | void reset_socket_class_io(); |
511 | |
512 | /** Update derived flags for all table shares. */ |
513 | void update_table_share_derived_flags(PFS_thread *thread); |
514 | |
515 | extern LF_HASH table_share_hash; |
516 | |
517 | /** @} */ |
518 | #endif |
519 | |
520 | |