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 #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     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     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