1 /* Copyright (c) 2008, 2016, 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, 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 #ifndef PFS_INSTR_CLASS_H
24 #define PFS_INSTR_CLASS_H
25
26 #include "my_global.h"
27 #include "mysql_com.h" /* NAME_LEN */
28 #include "lf.h"
29 #include "pfs_global.h"
30 #include "pfs_atomic.h"
31 #include "prealloced_array.h"
32
33 /**
34 @file storage/perfschema/pfs_instr_class.h
35 Performance schema instruments meta data (declarations).
36 */
37
38 /**
39 Maximum length of an instrument name.
40 For example, 'wait/sync/mutex/sql/LOCK_open' is an instrument name.
41 */
42 #define PFS_MAX_INFO_NAME_LENGTH 128
43
44 /**
45 Maximum length of the 'full' prefix of an instrument name.
46 For example, for the instrument name 'wait/sync/mutex/sql/LOCK_open',
47 the full prefix is 'wait/sync/mutex/sql/', which in turn derives from
48 a prefix 'wait/sync/mutex' for mutexes, and a category of 'sql' for mutexes
49 of the sql layer in the server.
50 */
51 #define PFS_MAX_FULL_PREFIX_NAME_LENGTH 32
52
53 #include <my_global.h>
54 #include <my_sys.h>
55 #include <mysql/psi/psi.h>
56 #include "pfs_lock.h"
57 #include "pfs_stat.h"
58 #include "pfs_column_types.h"
59
60 struct PFS_global_param;
61 struct PFS_table_share;
62 class PFS_opaque_container_page;
63
64 /**
65 @addtogroup Performance_schema_buffers
66 @{
67 */
68
69 extern my_bool pfs_enabled;
70 extern enum_timer_name *class_timers[];
71
72 /** Key, naming a synch instrument (mutex, rwlock, cond). */
73 typedef unsigned int PFS_sync_key;
74 /** Key, naming a thread instrument. */
75 typedef unsigned int PFS_thread_key;
76 /** Key, naming a file instrument. */
77 typedef unsigned int PFS_file_key;
78 /** Key, naming a stage instrument. */
79 typedef unsigned int PFS_stage_key;
80 /** Key, naming a statement instrument. */
81 typedef unsigned int PFS_statement_key;
82 /** Key, naming a transaction instrument. */
83 typedef unsigned int PFS_transaction_key;
84 /** Key, naming a socket instrument. */
85 typedef unsigned int PFS_socket_key;
86 /** Key, naming a memory instrument. */
87 typedef unsigned int PFS_memory_key;
88
89 enum PFS_class_type
90 {
91 PFS_CLASS_NONE= 0,
92 PFS_CLASS_MUTEX= 1,
93 PFS_CLASS_RWLOCK= 2,
94 PFS_CLASS_COND= 3,
95 PFS_CLASS_FILE= 4,
96 PFS_CLASS_TABLE= 5,
97 PFS_CLASS_STAGE= 6,
98 PFS_CLASS_STATEMENT= 7,
99 PFS_CLASS_TRANSACTION= 8,
100 PFS_CLASS_SOCKET= 9,
101 PFS_CLASS_TABLE_IO= 10,
102 PFS_CLASS_TABLE_LOCK= 11,
103 PFS_CLASS_IDLE= 12,
104 PFS_CLASS_MEMORY= 13,
105 PFS_CLASS_METADATA= 14,
106 PFS_CLASS_LAST= PFS_CLASS_METADATA,
107 PFS_CLASS_MAX= PFS_CLASS_LAST + 1
108 };
109
110 /** User-defined instrument configuration. */
111 struct PFS_instr_config
112 {
113 /* Instrument name. */
114 char *m_name;
115 /* Name length. */
116 uint m_name_length;
117 /** Enabled flag. */
118 bool m_enabled;
119 /** Timed flag. */
120 bool m_timed;
121 };
122
123 typedef Prealloced_array<PFS_instr_config*, 10> Pfs_instr_config_array;
124 extern Pfs_instr_config_array *pfs_instr_config_array;
125
126 struct PFS_thread;
127
128 extern uint mutex_class_start;
129 extern uint rwlock_class_start;
130 extern uint cond_class_start;
131 extern uint file_class_start;
132 extern uint socket_class_start;
133 extern uint wait_class_max;
134
135 /** Information for all instrumentation. */
136 struct PFS_instr_class
137 {
138 /** Class type */
139 PFS_class_type m_type;
140 /** True if this instrument is enabled. */
141 bool m_enabled;
142 /** True if this instrument is timed. */
143 bool m_timed;
144 /** Instrument flags. */
145 int m_flags;
146 /** Volatility index. */
147 int m_volatility;
148 /**
149 Instrument name index.
150 Self index in:
151 - EVENTS_WAITS_SUMMARY_*_BY_EVENT_NAME for waits
152 - EVENTS_STAGES_SUMMARY_*_BY_EVENT_NAME for stages
153 - EVENTS_STATEMENTS_SUMMARY_*_BY_EVENT_NAME for statements
154 - EVENTS_TRANSACTIONS_SUMMARY_*_BY_EVENT_NAME for transactions
155 */
156 uint m_event_name_index;
157 /** Instrument name. */
158 char m_name[PFS_MAX_INFO_NAME_LENGTH];
159 /** Length in bytes of @c m_name. */
160 uint m_name_length;
161 /** Timer associated with this class. */
162 enum_timer_name *m_timer;
163
is_singletonPFS_instr_class164 bool is_singleton() const
165 {
166 return m_flags & PSI_FLAG_GLOBAL;
167 }
168
is_mutablePFS_instr_class169 bool is_mutable() const
170 {
171 return m_flags & PSI_FLAG_MUTABLE;
172 }
173
is_progressPFS_instr_class174 bool is_progress() const
175 {
176 DBUG_ASSERT(m_type == PFS_CLASS_STAGE);
177 return m_flags & PSI_FLAG_STAGE_PROGRESS;
178 }
179
is_shared_exclusivePFS_instr_class180 bool is_shared_exclusive() const
181 {
182 DBUG_ASSERT(m_type == PFS_CLASS_RWLOCK);
183 return m_flags & PSI_RWLOCK_FLAG_SX;
184 }
185
186 static void set_enabled(PFS_instr_class *pfs, bool enabled);
187 static void set_timed(PFS_instr_class *pfs, bool timed);
188
is_deferredPFS_instr_class189 bool is_deferred() const
190 {
191 switch(m_type)
192 {
193 case PFS_CLASS_SOCKET:
194 return true;
195 break;
196 default:
197 return false;
198 break;
199 };
200 }
201 };
202
203 struct PFS_mutex;
204
205 /** Instrumentation metadata for a MUTEX. */
206 struct PFS_ALIGNED PFS_mutex_class : public PFS_instr_class
207 {
208 /** Mutex usage statistics. */
209 PFS_mutex_stat m_mutex_stat;
210 /** Singleton instance. */
211 PFS_mutex *m_singleton;
212 };
213
214 struct PFS_rwlock;
215
216 /** Instrumentation metadata for a RWLOCK. */
217 struct PFS_ALIGNED PFS_rwlock_class : public PFS_instr_class
218 {
219 /** Rwlock usage statistics. */
220 PFS_rwlock_stat m_rwlock_stat;
221 /** Singleton instance. */
222 PFS_rwlock *m_singleton;
223 };
224
225 struct PFS_cond;
226
227 /** Instrumentation metadata for a COND. */
228 struct PFS_ALIGNED PFS_cond_class : public PFS_instr_class
229 {
230 /**
231 Condition usage statistics.
232 This statistic is not exposed in user visible tables yet.
233 */
234 PFS_cond_stat m_cond_stat;
235 /** Singleton instance. */
236 PFS_cond *m_singleton;
237 };
238
239 /** Instrumentation metadata of a thread. */
240 struct PFS_ALIGNED PFS_thread_class
241 {
242 /** True if this thread instrument is enabled. */
243 bool m_enabled;
244 /** Singleton instance. */
245 PFS_thread *m_singleton;
246 /** Thread instrument name. */
247 char m_name[PFS_MAX_INFO_NAME_LENGTH];
248 /** Length in bytes of @c m_name. */
249 uint m_name_length;
250 };
251
252 /** Key identifying a table share. */
253 struct PFS_table_share_key
254 {
255 /**
256 Hash search key.
257 This has to be a string for LF_HASH,
258 the format is "<enum_object_type><schema_name><0x00><object_name><0x00>"
259 @see create_table_def_key
260 */
261 char m_hash_key[1 + NAME_LEN + 1 + NAME_LEN + 1];
262 /** Length in bytes of @c m_hash_key. */
263 uint m_key_length;
264 };
265
266 /** Table index or 'key' */
267 struct PFS_table_key
268 {
269 /** Index name */
270 char m_name[NAME_LEN];
271 /** Length in bytes of @c m_name. */
272 uint m_name_length;
273 };
274
275 /** Index statistics of a table.*/
276 struct PFS_table_share_index
277 {
278 pfs_lock m_lock;
279 /** The index name */
280 PFS_table_key m_key;
281 /** The index stat */
282 PFS_table_io_stat m_stat;
283 /** Owner table share. To be used later. */
284 PFS_table_share* m_owner;
285 /** Container page. */
286 PFS_opaque_container_page *m_page;
287 };
288
289 /** Lock statistics of a table.*/
290 struct PFS_table_share_lock
291 {
292 pfs_lock m_lock;
293 /** Lock stats. */
294 PFS_table_lock_stat m_stat;
295 /** Owner table share. To be used later. */
296 PFS_table_share* m_owner;
297 /** Container page. */
298 PFS_opaque_container_page *m_page;
299 };
300
301 /** Instrumentation metadata for a table share. */
302 struct PFS_ALIGNED PFS_table_share
303 {
304 public:
get_versionPFS_table_share305 uint32 get_version()
306 { return m_lock.get_version(); }
307
get_object_typePFS_table_share308 enum_object_type get_object_type()
309 {
310 return (enum_object_type) m_key.m_hash_key[0];
311 }
312
313 void aggregate_io(void);
314 void aggregate_lock(void);
315
316 void sum_io(PFS_single_stat *result, uint key_count);
317 void sum_lock(PFS_single_stat *result);
318 void sum(PFS_single_stat *result, uint key_count);
319
aggregatePFS_table_share320 inline void aggregate(void)
321 {
322 aggregate_io();
323 aggregate_lock();
324 }
325
init_refcountPFS_table_share326 inline void init_refcount(void)
327 {
328 PFS_atomic::store_32(& m_refcount, 1);
329 }
330
get_refcountPFS_table_share331 inline int get_refcount(void)
332 {
333 return PFS_atomic::load_32(& m_refcount);
334 }
335
inc_refcountPFS_table_share336 inline void inc_refcount(void)
337 {
338 PFS_atomic::add_32(& m_refcount, 1);
339 }
340
dec_refcountPFS_table_share341 inline void dec_refcount(void)
342 {
343 PFS_atomic::add_32(& m_refcount, -1);
344 }
345
346 void refresh_setup_object_flags(PFS_thread *thread);
347
348 /** Internal lock. */
349 pfs_lock m_lock;
350 /**
351 True if table instrumentation is enabled.
352 This flag is computed from the content of table setup_objects.
353 */
354 bool m_enabled;
355 /**
356 True if table instrumentation is timed.
357 This flag is computed from the content of table setup_objects.
358 */
359 bool m_timed;
360
361 /** Search key. */
362 PFS_table_share_key m_key;
363 /** Schema name. */
364 const char *m_schema_name;
365 /** Length in bytes of @c m_schema_name. */
366 uint m_schema_name_length;
367 /** Table name. */
368 const char *m_table_name;
369 /** Length in bytes of @c m_table_name. */
370 uint m_table_name_length;
371 /** Number of indexes. */
372 uint m_key_count;
373 /** Container page. */
374 PFS_opaque_container_page *m_page;
375
376 PFS_table_share_lock *find_lock_stat() const;
377 PFS_table_share_lock *find_or_create_lock_stat();
378 void destroy_lock_stat();
379
380 PFS_table_share_index *find_index_stat(uint index) const;
381 PFS_table_share_index *find_or_create_index_stat(const TABLE_SHARE *server_share, uint index);
382 void destroy_index_stats();
383
384 private:
385 /** Number of opened table handles. */
386 int m_refcount;
387 /** Table locks statistics. */
388 PFS_table_share_lock *m_race_lock_stat;
389 /** Table indexes' stats. */
390 PFS_table_share_index *m_race_index_stat[MAX_INDEXES + 1];
391 };
392
393 /** Statistics for the IDLE instrument. */
394 extern PFS_single_stat global_idle_stat;
395 /** Statistics for dropped table io. */
396 extern PFS_table_io_stat global_table_io_stat;
397 /** Statistics for dropped table lock. */
398 extern PFS_table_lock_stat global_table_lock_stat;
399 /** Statistics for the METADATA instrument. */
400 extern PFS_single_stat global_metadata_stat;
401 /** Statistics for the transaction instrument. */
402 extern PFS_transaction_stat global_transaction_stat;
403
sanitize_index_count(uint count)404 inline uint sanitize_index_count(uint count)
405 {
406 if (likely(count <= MAX_INDEXES))
407 return count;
408 return 0;
409 }
410
411 #define GLOBAL_TABLE_IO_EVENT_INDEX 0
412 #define GLOBAL_TABLE_LOCK_EVENT_INDEX 1
413 #define GLOBAL_IDLE_EVENT_INDEX 2
414 #define GLOBAL_METADATA_EVENT_INDEX 3
415 /** Number of global wait events. */
416 #define COUNT_GLOBAL_EVENT_INDEX 4
417
418 /** Transaction events are not wait events .*/
419 #define GLOBAL_TRANSACTION_INDEX 0
420
421 /**
422 Instrument controlling all table io.
423 This instrument is used with table SETUP_OBJECTS.
424 */
425 extern PFS_instr_class global_table_io_class;
426
427 /**
428 Instrument controlling all table lock.
429 This instrument is used with table SETUP_OBJECTS.
430 */
431 extern PFS_instr_class global_table_lock_class;
432
433 /**
434 Instrument controlling all idle waits.
435 */
436 extern PFS_instr_class global_idle_class;
437
438 extern PFS_instr_class global_metadata_class;
439
440 struct PFS_file;
441
442 /** Instrumentation metadata for a file. */
443 struct PFS_ALIGNED PFS_file_class : public PFS_instr_class
444 {
445 /** File usage statistics. */
446 PFS_file_stat m_file_stat;
447 /** Singleton instance. */
448 PFS_file *m_singleton;
449 };
450
451 /** Instrumentation metadata for a stage. */
452 struct PFS_ALIGNED PFS_stage_class : public PFS_instr_class
453 {
454 /**
455 Length of the 'stage/<component>/' prefix.
456 This is to extract 'foo' from 'stage/sql/foo'.
457 */
458 uint m_prefix_length;
459 /** Stage usage statistics. */
460 PFS_stage_stat m_stage_stat;
461 };
462
463 /** Instrumentation metadata for a statement. */
464 struct PFS_ALIGNED PFS_statement_class : public PFS_instr_class
465 {
466 };
467
468 /** Instrumentation metadata for a transaction. */
469 struct PFS_ALIGNED PFS_transaction_class : public PFS_instr_class
470 {
471 };
472
473 extern PFS_transaction_class global_transaction_class;
474
475 struct PFS_socket;
476
477 /** Instrumentation metadata for a socket. */
478 struct PFS_ALIGNED PFS_socket_class : public PFS_instr_class
479 {
480 /** Socket usage statistics. */
481 PFS_socket_stat m_socket_stat;
482 /** Singleton instance. */
483 PFS_socket *m_singleton;
484 };
485
486 /** Instrumentation metadata for a memory. */
487 struct PFS_ALIGNED PFS_memory_class : public PFS_instr_class
488 {
is_globalPFS_memory_class489 bool is_global() const
490 {
491 return m_flags & PSI_FLAG_GLOBAL;
492 }
493
is_transferablePFS_memory_class494 bool is_transferable() const
495 {
496 return m_flags & PSI_FLAG_TRANSFER;
497 }
498 };
499
500 void init_event_name_sizing(const PFS_global_param *param);
501
502 void register_global_classes();
503
504 int init_sync_class(uint mutex_class_sizing,
505 uint rwlock_class_sizing,
506 uint cond_class_sizing);
507
508 void cleanup_sync_class();
509 int init_thread_class(uint thread_class_sizing);
510 void cleanup_thread_class();
511 int init_table_share(uint table_share_sizing);
512 void cleanup_table_share();
513
514 int init_table_share_lock_stat(uint table_stat_sizing);
515 void cleanup_table_share_lock_stat();
516 PFS_table_share_lock* create_table_share_lock_stat();
517 void release_table_share_lock_stat(PFS_table_share_lock *pfs);
518
519 int init_table_share_index_stat(uint index_stat_sizing);
520 void cleanup_table_share_index_stat();
521 PFS_table_share_index* create_table_share_index_stat(const TABLE_SHARE *share, uint index);
522 void release_table_share_index_stat(PFS_table_share_index *pfs);
523
524 int init_table_share_hash(const PFS_global_param *param);
525 void cleanup_table_share_hash();
526 int init_file_class(uint file_class_sizing);
527 void cleanup_file_class();
528 int init_stage_class(uint stage_class_sizing);
529 void cleanup_stage_class();
530 int init_statement_class(uint statement_class_sizing);
531 void cleanup_statement_class();
532 int init_socket_class(uint socket_class_sizing);
533 void cleanup_socket_class();
534 int init_memory_class(uint memory_class_sizing);
535 void cleanup_memory_class();
536
537 PFS_sync_key register_mutex_class(const char *name, uint name_length,
538 int flags);
539
540 PFS_sync_key register_rwlock_class(const char *name, uint name_length,
541 int flags);
542
543 PFS_sync_key register_cond_class(const char *name, uint name_length,
544 int flags);
545
546 PFS_thread_key register_thread_class(const char *name, uint name_length,
547 int flags);
548
549 PFS_file_key register_file_class(const char *name, uint name_length,
550 int flags);
551
552 PFS_stage_key register_stage_class(const char *name,
553 uint prefix_length,
554 uint name_length,
555 int flags);
556
557 PFS_statement_key register_statement_class(const char *name, uint name_length,
558 int flags);
559
560 PFS_socket_key register_socket_class(const char *name, uint name_length,
561 int flags);
562
563 PFS_memory_key register_memory_class(const char *name, uint name_length,
564 int flags);
565
566 PFS_mutex_class *find_mutex_class(PSI_mutex_key key);
567 PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe);
568 PFS_rwlock_class *find_rwlock_class(PSI_rwlock_key key);
569 PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe);
570 PFS_cond_class *find_cond_class(PSI_cond_key key);
571 PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe);
572 PFS_thread_class *find_thread_class(PSI_thread_key key);
573 PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe);
574 PFS_file_class *find_file_class(PSI_file_key key);
575 PFS_file_class *sanitize_file_class(PFS_file_class *unsafe);
576 PFS_stage_class *find_stage_class(PSI_stage_key key);
577 PFS_stage_class *sanitize_stage_class(PFS_stage_class *unsafe);
578 PFS_statement_class *find_statement_class(PSI_statement_key key);
579 PFS_statement_class *sanitize_statement_class(PFS_statement_class *unsafe);
580 PFS_instr_class *find_table_class(uint index);
581 PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe);
582 PFS_socket_class *find_socket_class(PSI_socket_key key);
583 PFS_socket_class *sanitize_socket_class(PFS_socket_class *unsafe);
584 PFS_memory_class *find_memory_class(PSI_memory_key key);
585 PFS_memory_class *sanitize_memory_class(PFS_memory_class *unsafe);
586 PFS_instr_class *find_idle_class(uint index);
587 PFS_instr_class *sanitize_idle_class(PFS_instr_class *unsafe);
588 PFS_instr_class *find_metadata_class(uint index);
589 PFS_instr_class *sanitize_metadata_class(PFS_instr_class *unsafe);
590 PFS_transaction_class *find_transaction_class(uint index);
591 PFS_transaction_class *sanitize_transaction_class(PFS_transaction_class *unsafe);
592
593 PFS_table_share *find_or_create_table_share(PFS_thread *thread,
594 bool temporary,
595 const TABLE_SHARE *share);
596 void release_table_share(PFS_table_share *pfs);
597 void drop_table_share(PFS_thread *thread,
598 bool temporary,
599 const char *schema_name, uint schema_name_length,
600 const char *table_name, uint table_name_length);
601
602 PFS_table_share *sanitize_table_share(PFS_table_share *unsafe);
603
604 extern ulong mutex_class_max;
605 extern ulong mutex_class_lost;
606 extern ulong rwlock_class_max;
607 extern ulong rwlock_class_lost;
608 extern ulong cond_class_max;
609 extern ulong cond_class_lost;
610 extern ulong thread_class_max;
611 extern ulong thread_class_lost;
612 extern ulong file_class_max;
613 extern ulong file_class_lost;
614 extern ulong stage_class_max;
615 extern ulong stage_class_lost;
616 extern ulong statement_class_max;
617 extern ulong statement_class_lost;
618 extern ulong transaction_class_max;
619 extern ulong socket_class_max;
620 extern ulong socket_class_lost;
621 extern ulong memory_class_max;
622 extern ulong memory_class_lost;
623
624 /* Exposing the data directly, for iterators. */
625
626 extern PFS_mutex_class *mutex_class_array;
627 extern PFS_rwlock_class *rwlock_class_array;
628 extern PFS_cond_class *cond_class_array;
629 extern PFS_file_class *file_class_array;
630
631 void reset_events_waits_by_class();
632 void reset_file_class_io();
633 void reset_socket_class_io();
634
635 /** Update derived flags for all table shares. */
636 void update_table_share_derived_flags(PFS_thread *thread);
637
638 /** Update derived flags for all stored procedure shares. */
639 void update_program_share_derived_flags(PFS_thread *thread);
640
641 extern LF_HASH table_share_hash;
642
643 /** @} */
644 #endif
645
646