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