1 /* Copyright (c) 2008, 2015, 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 /**
24   @file storage/perfschema/pfs_instr_class.cc
25   Performance schema instruments meta data (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_sys.h"
30 #include "structs.h"
31 #include "table.h"
32 #include "pfs_instr_class.h"
33 #include "pfs_instr.h"
34 #include "pfs_global.h"
35 #include "pfs_timer.h"
36 #include "pfs_events_waits.h"
37 #include "pfs_setup_object.h"
38 #include "pfs_atomic.h"
39 #include "mysql/psi/mysql_thread.h"
40 #include "lf.h"
41 
42 #include <string.h>
43 
44 /**
45   @defgroup Performance_schema_buffers Performance Schema Buffers
46   @ingroup Performance_schema_implementation
47   @{
48 */
49 
50 /**
51   Global performance schema flag.
52   Indicate if the performance schema is enabled.
53   This flag is set at startup, and never changes.
54 */
55 my_bool pfs_enabled= TRUE;
56 
57 /**
58   PFS_INSTRUMENT option settings array and associated state variable to
59   serialize access during shutdown.
60  */
61 DYNAMIC_ARRAY pfs_instr_config_array;
62 int pfs_instr_config_state= PFS_INSTR_CONFIG_NOT_INITIALIZED;
63 
64 static void configure_instr_class(PFS_instr_class *entry);
65 
66 static void init_instr_class(PFS_instr_class *klass,
67                              const char *name,
68                              uint name_length,
69                              int flags,
70                              PFS_class_type class_type);
71 
72 /**
73   Current number of elements in mutex_class_array.
74   This global variable is written to during:
75   - the performance schema initialization
76   - a plugin initialization
77 */
78 static volatile uint32 mutex_class_dirty_count= 0;
79 static volatile uint32 mutex_class_allocated_count= 0;
80 static volatile uint32 rwlock_class_dirty_count= 0;
81 static volatile uint32 rwlock_class_allocated_count= 0;
82 static volatile uint32 cond_class_dirty_count= 0;
83 static volatile uint32 cond_class_allocated_count= 0;
84 
85 /** Size of the mutex class array. @sa mutex_class_array */
86 ulong mutex_class_max= 0;
87 /** Number of mutex class lost. @sa mutex_class_array */
88 ulong mutex_class_lost= 0;
89 /** Size of the rwlock class array. @sa rwlock_class_array */
90 ulong rwlock_class_max= 0;
91 /** Number of rwlock class lost. @sa rwlock_class_array */
92 ulong rwlock_class_lost= 0;
93 /** Size of the condition class array. @sa cond_class_array */
94 ulong cond_class_max= 0;
95 /** Number of condition class lost. @sa cond_class_array */
96 ulong cond_class_lost= 0;
97 /** Size of the thread class array. @sa thread_class_array */
98 ulong thread_class_max= 0;
99 /** Number of thread class lost. @sa thread_class_array */
100 ulong thread_class_lost= 0;
101 /** Size of the file class array. @sa file_class_array */
102 ulong file_class_max= 0;
103 /** Number of file class lost. @sa file_class_array */
104 ulong file_class_lost= 0;
105 /** Size of the stage class array. @sa stage_class_array */
106 ulong stage_class_max= 0;
107 /** Number of stage class lost. @sa stage_class_array */
108 ulong stage_class_lost= 0;
109 /** Size of the statement class array. @sa statement_class_array */
110 ulong statement_class_max= 0;
111 /** Number of statement class lost. @sa statement_class_array */
112 ulong statement_class_lost= 0;
113 /** Size of the table share array. @sa table_share_array */
114 ulong table_share_max= 0;
115 /** Number of table share lost. @sa table_share_array */
116 ulong table_share_lost= 0;
117 /** Size of the socket class array. @sa socket_class_array */
118 ulong socket_class_max= 0;
119 /** Number of socket class lost. @sa socket_class_array */
120 ulong socket_class_lost= 0;
121 
122 PFS_mutex_class *mutex_class_array= NULL;
123 PFS_rwlock_class *rwlock_class_array= NULL;
124 PFS_cond_class *cond_class_array= NULL;
125 
126 /**
127   Current number or elements in thread_class_array.
128   This global variable is written to during:
129   - the performance schema initialization
130   - a plugin initialization
131 */
132 static volatile uint32 thread_class_dirty_count= 0;
133 static volatile uint32 thread_class_allocated_count= 0;
134 
135 static PFS_thread_class *thread_class_array= NULL;
136 
137 /**
138   Table instance array.
139   @sa table_share_max
140   @sa table_share_lost
141   @sa table_share_hash
142 */
143 PFS_table_share *table_share_array= NULL;
144 
145 PFS_ALIGNED PFS_single_stat global_idle_stat;
146 PFS_ALIGNED PFS_table_io_stat global_table_io_stat;
147 PFS_ALIGNED PFS_table_lock_stat global_table_lock_stat;
148 PFS_ALIGNED PFS_instr_class global_table_io_class;
149 PFS_ALIGNED PFS_instr_class global_table_lock_class;
150 PFS_ALIGNED PFS_instr_class global_idle_class;
151 
152 /** Class-timer map */
153 enum_timer_name *class_timers[] =
154 {&wait_timer,      /* PFS_CLASS_NONE */
155  &wait_timer,      /* PFS_CLASS_MUTEX */
156  &wait_timer,      /* PFS_CLASS_RWLOCK */
157  &wait_timer,      /* PFS_CLASS_COND */
158  &wait_timer,      /* PFS_CLASS_FILE */
159  &wait_timer,      /* PFS_CLASS_TABLE */
160  &stage_timer,     /* PFS_CLASS_STAGE */
161  &statement_timer, /* PFS_CLASS_STATEMENT */
162  &wait_timer,      /* PFS_CLASS_SOCKET */
163  &wait_timer,      /* PFS_CLASS_TABLE_IO */
164  &wait_timer,      /* PFS_CLASS_TABLE_LOCK */
165  &idle_timer       /* PFS_CLASS_IDLE */
166 };
167 
168 /**
169   Hash index for instrumented table shares.
170   This index is searched by table fully qualified name (@c PFS_table_share_key),
171   and points to instrumented table shares (@c PFS_table_share).
172   @sa table_share_array
173   @sa PFS_table_share_key
174   @sa PFS_table_share
175   @sa table_share_hash_get_key
176   @sa get_table_share_hash_pins
177 */
178 LF_HASH table_share_hash;
179 /** True if table_share_hash is initialized. */
180 static bool table_share_hash_inited= false;
181 
182 static volatile uint32 file_class_dirty_count= 0;
183 static volatile uint32 file_class_allocated_count= 0;
184 
185 PFS_file_class *file_class_array= NULL;
186 
187 static volatile uint32 stage_class_dirty_count= 0;
188 static volatile uint32 stage_class_allocated_count= 0;
189 
190 static PFS_stage_class *stage_class_array= NULL;
191 
192 static volatile uint32 statement_class_dirty_count= 0;
193 static volatile uint32 statement_class_allocated_count= 0;
194 
195 static PFS_statement_class *statement_class_array= NULL;
196 
197 static volatile uint32 socket_class_dirty_count= 0;
198 static volatile uint32 socket_class_allocated_count= 0;
199 
200 static PFS_socket_class *socket_class_array= NULL;
201 
202 uint mutex_class_start= 0;
203 uint rwlock_class_start= 0;
204 uint cond_class_start= 0;
205 uint file_class_start= 0;
206 uint wait_class_max= 0;
207 uint socket_class_start= 0;
208 
init_event_name_sizing(const PFS_global_param * param)209 void init_event_name_sizing(const PFS_global_param *param)
210 {
211   mutex_class_start= 3; /* global table io, table lock, idle */
212   rwlock_class_start= mutex_class_start + param->m_mutex_class_sizing;
213   cond_class_start= rwlock_class_start + param->m_rwlock_class_sizing;
214   file_class_start= cond_class_start + param->m_cond_class_sizing;
215   socket_class_start= file_class_start + param->m_file_class_sizing;
216   wait_class_max= socket_class_start + param->m_socket_class_sizing;
217 }
218 
register_global_classes()219 void register_global_classes()
220 {
221   /* Table IO class */
222   init_instr_class(&global_table_io_class, "wait/io/table/sql/handler", 25,
223                    0, PFS_CLASS_TABLE_IO);
224   global_table_io_class.m_event_name_index= GLOBAL_TABLE_IO_EVENT_INDEX;
225   configure_instr_class(&global_table_io_class);
226 
227   /* Table lock class */
228   init_instr_class(&global_table_lock_class, "wait/lock/table/sql/handler", 27,
229                    0, PFS_CLASS_TABLE_LOCK);
230   global_table_lock_class.m_event_name_index= GLOBAL_TABLE_LOCK_EVENT_INDEX;
231   configure_instr_class(&global_table_lock_class);
232 
233   /* Idle class */
234   init_instr_class(&global_idle_class, "idle", 4,
235                    0, PFS_CLASS_IDLE);
236   global_idle_class.m_event_name_index= GLOBAL_IDLE_EVENT_INDEX;
237   configure_instr_class(&global_idle_class);
238 }
239 
240 /**
241   Initialize the instrument synch class buffers.
242   @param mutex_class_sizing           max number of mutex class
243   @param rwlock_class_sizing          max number of rwlock class
244   @param cond_class_sizing            max number of condition class
245   @return 0 on success
246 */
init_sync_class(uint mutex_class_sizing,uint rwlock_class_sizing,uint cond_class_sizing)247 int init_sync_class(uint mutex_class_sizing,
248                     uint rwlock_class_sizing,
249                     uint cond_class_sizing)
250 {
251   mutex_class_dirty_count= mutex_class_allocated_count= 0;
252   rwlock_class_dirty_count= rwlock_class_allocated_count= 0;
253   cond_class_dirty_count= cond_class_allocated_count= 0;
254   mutex_class_max= mutex_class_sizing;
255   rwlock_class_max= rwlock_class_sizing;
256   cond_class_max= cond_class_sizing;
257   mutex_class_lost= rwlock_class_lost= cond_class_lost= 0;
258 
259   mutex_class_array= NULL;
260   rwlock_class_array= NULL;
261   cond_class_array= NULL;
262 
263   if (mutex_class_max > 0)
264   {
265     mutex_class_array= PFS_MALLOC_ARRAY(mutex_class_max, sizeof(PFS_mutex_class),
266                                         PFS_mutex_class, MYF(MY_ZEROFILL));
267     if (unlikely(mutex_class_array == NULL))
268       return 1;
269   }
270 
271   if (rwlock_class_max > 0)
272   {
273     rwlock_class_array= PFS_MALLOC_ARRAY(rwlock_class_max, sizeof(PFS_rwlock_class),
274                                          PFS_rwlock_class, MYF(MY_ZEROFILL));
275     if (unlikely(rwlock_class_array == NULL))
276       return 1;
277   }
278 
279   if (cond_class_max > 0)
280   {
281     cond_class_array= PFS_MALLOC_ARRAY(cond_class_max, sizeof(PFS_cond_class),
282                                        PFS_cond_class, MYF(MY_ZEROFILL));
283     if (unlikely(cond_class_array == NULL))
284       return 1;
285   }
286 
287   return 0;
288 }
289 
290 /** Cleanup the instrument synch class buffers. */
cleanup_sync_class(void)291 void cleanup_sync_class(void)
292 {
293   pfs_free(mutex_class_array);
294   mutex_class_array= NULL;
295   mutex_class_dirty_count= mutex_class_allocated_count= mutex_class_max= 0;
296   pfs_free(rwlock_class_array);
297   rwlock_class_array= NULL;
298   rwlock_class_dirty_count= rwlock_class_allocated_count= rwlock_class_max= 0;
299   pfs_free(cond_class_array);
300   cond_class_array= NULL;
301   cond_class_dirty_count= cond_class_allocated_count= cond_class_max= 0;
302 }
303 
304 /**
305   Initialize the thread class buffer.
306   @param thread_class_sizing          max number of thread class
307   @return 0 on success
308 */
init_thread_class(uint thread_class_sizing)309 int init_thread_class(uint thread_class_sizing)
310 {
311   int result= 0;
312   thread_class_dirty_count= thread_class_allocated_count= 0;
313   thread_class_max= thread_class_sizing;
314   thread_class_lost= 0;
315 
316   if (thread_class_max > 0)
317   {
318     thread_class_array= PFS_MALLOC_ARRAY(thread_class_max, sizeof(PFS_thread_class),
319                                          PFS_thread_class, MYF(MY_ZEROFILL));
320     if (unlikely(thread_class_array == NULL))
321       result= 1;
322   }
323   else
324     thread_class_array= NULL;
325 
326   return result;
327 }
328 
329 /** Cleanup the thread class buffers. */
cleanup_thread_class(void)330 void cleanup_thread_class(void)
331 {
332   pfs_free(thread_class_array);
333   thread_class_array= NULL;
334   thread_class_dirty_count= thread_class_allocated_count= 0;
335   thread_class_max= 0;
336 }
337 
338 /**
339   Initialize the table share buffer.
340   @param table_share_sizing           max number of table share
341   @return 0 on success
342 */
init_table_share(uint table_share_sizing)343 int init_table_share(uint table_share_sizing)
344 {
345   int result= 0;
346   table_share_max= table_share_sizing;
347   table_share_lost= 0;
348 
349   if (table_share_max > 0)
350   {
351     table_share_array= PFS_MALLOC_ARRAY(table_share_max, sizeof(PFS_table_share),
352                                         PFS_table_share, MYF(MY_ZEROFILL));
353     if (unlikely(table_share_array == NULL))
354       result= 1;
355   }
356   else
357     table_share_array= NULL;
358 
359   return result;
360 }
361 
362 /** Cleanup the table share buffers. */
cleanup_table_share(void)363 void cleanup_table_share(void)
364 {
365   pfs_free(table_share_array);
366   table_share_array= NULL;
367   table_share_max= 0;
368 }
369 
370 C_MODE_START
371 /** get_key function for @c table_share_hash. */
table_share_hash_get_key(const uchar * entry,size_t * length,my_bool)372 static uchar *table_share_hash_get_key(const uchar *entry, size_t *length,
373                                        my_bool)
374 {
375   const PFS_table_share * const *typed_entry;
376   const PFS_table_share *share;
377   const void *result;
378   typed_entry= reinterpret_cast<const PFS_table_share* const *> (entry);
379   DBUG_ASSERT(typed_entry != NULL);
380   share= *typed_entry;
381   DBUG_ASSERT(share != NULL);
382   *length= share->m_key.m_key_length;
383   result= &share->m_key.m_hash_key[0];
384   return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
385 }
386 C_MODE_END
387 
388 /** Initialize the table share hash table. */
init_table_share_hash(void)389 int init_table_share_hash(void)
390 {
391   if ((! table_share_hash_inited) && (table_share_max > 0))
392   {
393     lf_hash_init(&table_share_hash, sizeof(PFS_table_share*), LF_HASH_UNIQUE,
394                  0, 0, table_share_hash_get_key, &my_charset_bin);
395     table_share_hash.size= table_share_max;
396     table_share_hash_inited= true;
397   }
398   return 0;
399 }
400 
401 /** Cleanup the table share hash table. */
cleanup_table_share_hash(void)402 void cleanup_table_share_hash(void)
403 {
404   if (table_share_hash_inited)
405   {
406     lf_hash_destroy(&table_share_hash);
407     table_share_hash_inited= false;
408   }
409 }
410 
411 /**
412   Get the hash pins for @sa table_share_hash.
413   @param thread The running thread.
414   @returns The LF_HASH pins for the thread.
415 */
get_table_share_hash_pins(PFS_thread * thread)416 LF_PINS* get_table_share_hash_pins(PFS_thread *thread)
417 {
418   if (unlikely(thread->m_table_share_hash_pins == NULL))
419   {
420     if (! table_share_hash_inited)
421       return NULL;
422     thread->m_table_share_hash_pins= lf_hash_get_pins(&table_share_hash);
423   }
424   return thread->m_table_share_hash_pins;
425 }
426 
427 /**
428   Set a table share hash key.
429   @param [out] key The key to populate.
430   @param temporary True for TEMPORARY TABLE.
431   @param schema_name The table schema name.
432   @param schema_name_length The table schema name length.
433   @param table_name The table name.
434   @param table_name_length The table name length.
435 */
set_table_share_key(PFS_table_share_key * key,bool temporary,const char * schema_name,uint schema_name_length,const char * table_name,uint table_name_length)436 static void set_table_share_key(PFS_table_share_key *key,
437                                 bool temporary,
438                                 const char *schema_name, uint schema_name_length,
439                                 const char *table_name, uint table_name_length)
440 {
441   DBUG_ASSERT(schema_name_length <= NAME_LEN);
442   DBUG_ASSERT(table_name_length <= NAME_LEN);
443   char *saved_schema_name;
444   char *saved_table_name;
445 
446   char *ptr= &key->m_hash_key[0];
447   ptr[0]= (temporary ? OBJECT_TYPE_TEMPORARY_TABLE : OBJECT_TYPE_TABLE);
448   ptr++;
449   saved_schema_name= ptr;
450   memcpy(ptr, schema_name, schema_name_length);
451   ptr+= schema_name_length;
452   ptr[0]= 0;
453   ptr++;
454   saved_table_name= ptr;
455   memcpy(ptr, table_name, table_name_length);
456   ptr+= table_name_length;
457   ptr[0]= 0;
458   ptr++;
459   key->m_key_length= ptr - &key->m_hash_key[0];
460 
461   if (lower_case_table_names)
462   {
463     my_casedn_str(files_charset_info, saved_schema_name);
464     my_casedn_str(files_charset_info, saved_table_name);
465   }
466 }
467 
refresh_setup_object_flags(PFS_thread * thread)468 void PFS_table_share::refresh_setup_object_flags(PFS_thread *thread)
469 {
470   lookup_setup_object(thread,
471                       OBJECT_TYPE_TABLE,
472                       m_schema_name, m_schema_name_length,
473                       m_table_name, m_table_name_length,
474                       &m_enabled, &m_timed);
475 }
476 
477 /**
478   Initialize the file class buffer.
479   @param file_class_sizing            max number of file class
480   @return 0 on success
481 */
init_file_class(uint file_class_sizing)482 int init_file_class(uint file_class_sizing)
483 {
484   int result= 0;
485   file_class_dirty_count= file_class_allocated_count= 0;
486   file_class_max= file_class_sizing;
487   file_class_lost= 0;
488 
489   if (file_class_max > 0)
490   {
491     file_class_array= PFS_MALLOC_ARRAY(file_class_max, sizeof(PFS_file_class),
492                                        PFS_file_class, MYF(MY_ZEROFILL));
493     if (unlikely(file_class_array == NULL))
494       return 1;
495   }
496   else
497     file_class_array= NULL;
498 
499   return result;
500 }
501 
502 /** Cleanup the file class buffers. */
cleanup_file_class(void)503 void cleanup_file_class(void)
504 {
505   pfs_free(file_class_array);
506   file_class_array= NULL;
507   file_class_dirty_count= file_class_allocated_count= 0;
508   file_class_max= 0;
509 }
510 
511 /**
512   Initialize the stage class buffer.
513   @param stage_class_sizing            max number of stage class
514   @return 0 on success
515 */
init_stage_class(uint stage_class_sizing)516 int init_stage_class(uint stage_class_sizing)
517 {
518   int result= 0;
519   stage_class_dirty_count= stage_class_allocated_count= 0;
520   stage_class_max= stage_class_sizing;
521   stage_class_lost= 0;
522 
523   if (stage_class_max > 0)
524   {
525     stage_class_array= PFS_MALLOC_ARRAY(stage_class_max, sizeof(PFS_stage_class),
526                                         PFS_stage_class, MYF(MY_ZEROFILL));
527     if (unlikely(stage_class_array == NULL))
528       return 1;
529   }
530   else
531     stage_class_array= NULL;
532 
533   return result;
534 }
535 
536 /** Cleanup the stage class buffers. */
cleanup_stage_class(void)537 void cleanup_stage_class(void)
538 {
539   pfs_free(stage_class_array);
540   stage_class_array= NULL;
541   stage_class_dirty_count= stage_class_allocated_count= 0;
542   stage_class_max= 0;
543 }
544 
545 /**
546   Initialize the statement class buffer.
547   @param statement_class_sizing            max number of statement class
548   @return 0 on success
549 */
init_statement_class(uint statement_class_sizing)550 int init_statement_class(uint statement_class_sizing)
551 {
552   int result= 0;
553   statement_class_dirty_count= statement_class_allocated_count= 0;
554   statement_class_max= statement_class_sizing;
555   statement_class_lost= 0;
556 
557   if (statement_class_max > 0)
558   {
559     statement_class_array= PFS_MALLOC_ARRAY(statement_class_max, sizeof(PFS_statement_class),
560                                             PFS_statement_class, MYF(MY_ZEROFILL));
561     if (unlikely(statement_class_array == NULL))
562       return 1;
563   }
564   else
565     statement_class_array= NULL;
566 
567   return result;
568 }
569 
570 /** Cleanup the statement class buffers. */
cleanup_statement_class(void)571 void cleanup_statement_class(void)
572 {
573   pfs_free(statement_class_array);
574   statement_class_array= NULL;
575   statement_class_dirty_count= statement_class_allocated_count= 0;
576   statement_class_max= 0;
577 }
578 
579 /**
580   Initialize the socket class buffer.
581   @param socket_class_sizing            max number of socket class
582   @return 0 on success
583 */
init_socket_class(uint socket_class_sizing)584 int init_socket_class(uint socket_class_sizing)
585 {
586   int result= 0;
587   socket_class_dirty_count= socket_class_allocated_count= 0;
588   socket_class_max= socket_class_sizing;
589   socket_class_lost= 0;
590 
591   if (socket_class_max > 0)
592   {
593     socket_class_array= PFS_MALLOC_ARRAY(socket_class_max, sizeof(PFS_socket_class),
594                                          PFS_socket_class, MYF(MY_ZEROFILL));
595     if (unlikely(socket_class_array == NULL))
596       return 1;
597   }
598   else
599     socket_class_array= NULL;
600 
601   return result;
602 }
603 
604 /** Cleanup the socket class buffers. */
cleanup_socket_class(void)605 void cleanup_socket_class(void)
606 {
607   pfs_free(socket_class_array);
608   socket_class_array= NULL;
609   socket_class_dirty_count= socket_class_allocated_count= 0;
610   socket_class_max= 0;
611 }
612 
init_instr_class(PFS_instr_class * klass,const char * name,uint name_length,int flags,PFS_class_type class_type)613 static void init_instr_class(PFS_instr_class *klass,
614                              const char *name,
615                              uint name_length,
616                              int flags,
617                              PFS_class_type class_type)
618 {
619   DBUG_ASSERT(name_length <= PFS_MAX_INFO_NAME_LENGTH);
620   memset(klass, 0, sizeof(PFS_instr_class));
621   strncpy(klass->m_name, name, name_length);
622   klass->m_name_length= name_length;
623   klass->m_flags= flags;
624   klass->m_enabled= true;
625   klass->m_timed= true;
626   klass->m_type= class_type;
627   klass->m_timer= class_timers[class_type];
628 }
629 
630 /**
631   Set user-defined configuration values for an instrument.
632 */
configure_instr_class(PFS_instr_class * entry)633 static void configure_instr_class(PFS_instr_class *entry)
634 {
635   uint match_length= 0; /* length of matching pattern */
636 
637   for (uint i= 0; i < pfs_instr_config_array.elements; i++)
638   {
639     PFS_instr_config* e;
640     get_dynamic(&pfs_instr_config_array, (uchar*)&e, i);
641 
642     /**
643       Compare class name to all configuration entries. In case of multiple
644       matches, the longer specification wins. For example, the pattern
645       'ABC/DEF/GHI=ON' has precedence over 'ABC/DEF/%=OFF' regardless of
646       position within the configuration file or command line.
647 
648       Consecutive wildcards affect the count.
649     */
650     if (!my_wildcmp(&my_charset_latin1,
651                     entry->m_name, entry->m_name+entry->m_name_length,
652                     e->m_name, e->m_name+e->m_name_length,
653                     '\\', '?','%'))
654     {
655         if (e->m_name_length >= match_length)
656         {
657            entry->m_enabled= e->m_enabled;
658            entry->m_timed= e->m_timed;
659            match_length= MY_MAX(e->m_name_length, match_length);
660         }
661     }
662   }
663 }
664 
665 #define REGISTER_CLASS_BODY_PART(INDEX, ARRAY, MAX, NAME, NAME_LENGTH) \
666   for (INDEX= 0; INDEX < MAX; INDEX++)                                 \
667   {                                                                    \
668     entry= &ARRAY[INDEX];                                              \
669     if ((entry->m_name_length == NAME_LENGTH) &&                       \
670         (strncmp(entry->m_name, NAME, NAME_LENGTH) == 0))              \
671     {                                                                  \
672       DBUG_ASSERT(entry->m_flags == flags);                            \
673       return (INDEX + 1);                                              \
674     }                                                                  \
675   }
676 
677 /**
678   Register a mutex instrumentation metadata.
679   @param name                         the instrumented name
680   @param name_length                  length in bytes of name
681   @param flags                        the instrumentation flags
682   @return a mutex instrumentation key
683 */
register_mutex_class(const char * name,uint name_length,int flags)684 PFS_sync_key register_mutex_class(const char *name, uint name_length,
685                                   int flags)
686 {
687   uint32 index;
688   PFS_mutex_class *entry;
689 
690   /*
691     This is a full array scan, which is not optimal.
692     This is acceptable since this code is only used at startup,
693     or when a plugin is loaded.
694   */
695   REGISTER_CLASS_BODY_PART(index, mutex_class_array, mutex_class_max,
696                            name, name_length)
697   /*
698     Note that:
699     mutex_class_dirty_count is incremented *before* an entry is added
700     mutex_class_allocated_count is incremented *after* an entry is added
701   */
702   index= PFS_atomic::add_u32(&mutex_class_dirty_count, 1);
703 
704   if (index < mutex_class_max)
705   {
706     /*
707       The instrument was not found (from a possible previous
708       load / unload of a plugin), allocate it.
709       This code is safe when 2 threads execute in parallel
710       for different mutex classes:
711       - thread 1 registering class A
712       - thread 2 registering class B
713       will not collide in the same mutex_class_array[index] entry.
714       This code does not protect against 2 threads registering
715       in parallel the same class:
716       - thread 1 registering class A
717       - thread 2 registering class A
718       could lead to a duplicate class A entry.
719       This is ok, since this case can not happen in the caller:
720       - classes names are derived from a plugin name
721         ('wait/synch/mutex/<plugin>/xxx')
722       - 2 threads can not register concurrently the same plugin
723         in INSTALL PLUGIN.
724     */
725     entry= &mutex_class_array[index];
726     init_instr_class(entry, name, name_length, flags, PFS_CLASS_MUTEX);
727     entry->m_mutex_stat.reset();
728     entry->m_event_name_index= mutex_class_start + index;
729     entry->m_singleton= NULL;
730     entry->m_enabled= false; /* disabled by default */
731     entry->m_timed= false;
732 
733     /* Set user-defined configuration options for this instrument */
734     configure_instr_class(entry);
735 
736     /*
737       Now that this entry is populated, advertise it
738 
739       Technically, there is a small race condition here:
740       T0:
741       mutex_class_dirty_count= 10
742       mutex_class_allocated_count= 10
743       T1: Thread A increment mutex_class_dirty_count to 11
744       T2: Thread B increment mutex_class_dirty_count to 12
745       T3: Thread A populate entry 11
746       T4: Thread B populate entry 12
747       T5: Thread B increment mutex_class_allocated_count to 11,
748           advertise thread A incomplete record 11,
749           but does not advertise thread B complete record 12
750       T6: Thread A increment mutex_class_allocated_count to 12
751       This has no impact, and is acceptable.
752       A reader will not see record 12 for a short time.
753       A reader will see an incomplete record 11 for a short time,
754       which is ok: the mutex name / statistics will be temporarily
755       empty/NULL/zero, but this won't cause a crash
756       (mutex_class_array is initialized with MY_ZEROFILL).
757     */
758     PFS_atomic::add_u32(&mutex_class_allocated_count, 1);
759     return (index + 1);
760   }
761 
762   /*
763     Out of space, report to SHOW STATUS that
764     the allocated memory was too small.
765   */
766   mutex_class_lost++;
767   return 0;
768 }
769 
770 /**
771   Register a rwlock instrumentation metadata.
772   @param name                         the instrumented name
773   @param name_length                  length in bytes of name
774   @param flags                        the instrumentation flags
775   @return a rwlock instrumentation key
776 */
register_rwlock_class(const char * name,uint name_length,int flags)777 PFS_sync_key register_rwlock_class(const char *name, uint name_length,
778                                    int flags)
779 {
780   /* See comments in register_mutex_class */
781   uint32 index;
782   PFS_rwlock_class *entry;
783 
784   REGISTER_CLASS_BODY_PART(index, rwlock_class_array, rwlock_class_max,
785                            name, name_length)
786 
787   index= PFS_atomic::add_u32(&rwlock_class_dirty_count, 1);
788 
789   if (index < rwlock_class_max)
790   {
791     entry= &rwlock_class_array[index];
792     init_instr_class(entry, name, name_length, flags, PFS_CLASS_RWLOCK);
793     entry->m_rwlock_stat.reset();
794     entry->m_event_name_index= rwlock_class_start + index;
795     entry->m_singleton= NULL;
796     entry->m_enabled= false; /* disabled by default */
797     entry->m_timed= false;
798     /* Set user-defined configuration options for this instrument */
799     configure_instr_class(entry);
800     PFS_atomic::add_u32(&rwlock_class_allocated_count, 1);
801     return (index + 1);
802   }
803 
804   rwlock_class_lost++;
805   return 0;
806 }
807 
808 /**
809   Register a condition instrumentation metadata.
810   @param name                         the instrumented name
811   @param name_length                  length in bytes of name
812   @param flags                        the instrumentation flags
813   @return a condition instrumentation key
814 */
register_cond_class(const char * name,uint name_length,int flags)815 PFS_sync_key register_cond_class(const char *name, uint name_length,
816                                  int flags)
817 {
818   /* See comments in register_mutex_class */
819   uint32 index;
820   PFS_cond_class *entry;
821 
822   REGISTER_CLASS_BODY_PART(index, cond_class_array, cond_class_max,
823                            name, name_length)
824 
825   index= PFS_atomic::add_u32(&cond_class_dirty_count, 1);
826 
827   if (index < cond_class_max)
828   {
829     entry= &cond_class_array[index];
830     init_instr_class(entry, name, name_length, flags, PFS_CLASS_COND);
831     entry->m_event_name_index= cond_class_start + index;
832     entry->m_singleton= NULL;
833     entry->m_enabled= false; /* disabled by default */
834     entry->m_timed= false;
835     /* Set user-defined configuration options for this instrument */
836     configure_instr_class(entry);
837     PFS_atomic::add_u32(&cond_class_allocated_count, 1);
838     return (index + 1);
839   }
840 
841   cond_class_lost++;
842   return 0;
843 }
844 
845 #define FIND_CLASS_BODY(KEY, COUNT, ARRAY) \
846   if ((KEY == 0) || (KEY > COUNT))         \
847     return NULL;                           \
848   return &ARRAY[KEY - 1]
849 
850 /**
851   Find a mutex instrumentation class by key.
852   @param key                          the instrument key
853   @return the instrument class, or NULL
854 */
find_mutex_class(PFS_sync_key key)855 PFS_mutex_class *find_mutex_class(PFS_sync_key key)
856 {
857   FIND_CLASS_BODY(key, mutex_class_allocated_count, mutex_class_array);
858 }
859 
sanitize_mutex_class(PFS_mutex_class * unsafe)860 PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe)
861 {
862   SANITIZE_ARRAY_BODY(PFS_mutex_class, mutex_class_array, mutex_class_max, unsafe);
863 }
864 
865 /**
866   Find a rwlock instrumentation class by key.
867   @param key                          the instrument key
868   @return the instrument class, or NULL
869 */
find_rwlock_class(PFS_sync_key key)870 PFS_rwlock_class *find_rwlock_class(PFS_sync_key key)
871 {
872   FIND_CLASS_BODY(key, rwlock_class_allocated_count, rwlock_class_array);
873 }
874 
sanitize_rwlock_class(PFS_rwlock_class * unsafe)875 PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe)
876 {
877   SANITIZE_ARRAY_BODY(PFS_rwlock_class, rwlock_class_array, rwlock_class_max, unsafe);
878 }
879 
880 /**
881   Find a condition instrumentation class by key.
882   @param key                          the instrument key
883   @return the instrument class, or NULL
884 */
find_cond_class(PFS_sync_key key)885 PFS_cond_class *find_cond_class(PFS_sync_key key)
886 {
887   FIND_CLASS_BODY(key, cond_class_allocated_count, cond_class_array);
888 }
889 
sanitize_cond_class(PFS_cond_class * unsafe)890 PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe)
891 {
892   SANITIZE_ARRAY_BODY(PFS_cond_class, cond_class_array, cond_class_max, unsafe);
893 }
894 
895 /**
896   Register a thread instrumentation metadata.
897   @param name                         the instrumented name
898   @param name_length                  length in bytes of name
899   @param flags                        the instrumentation flags
900   @return a thread instrumentation key
901 */
register_thread_class(const char * name,uint name_length,int flags)902 PFS_thread_key register_thread_class(const char *name, uint name_length,
903                                      int flags)
904 {
905   /* See comments in register_mutex_class */
906   uint32 index;
907   PFS_thread_class *entry;
908 
909   for (index= 0; index < thread_class_max; index++)
910   {
911     entry= &thread_class_array[index];
912 
913     if ((entry->m_name_length == name_length) &&
914         (strncmp(entry->m_name, name, name_length) == 0))
915       return (index + 1);
916   }
917 
918   index= PFS_atomic::add_u32(&thread_class_dirty_count, 1);
919 
920   if (index < thread_class_max)
921   {
922     entry= &thread_class_array[index];
923     DBUG_ASSERT(name_length <= PFS_MAX_INFO_NAME_LENGTH);
924     strncpy(entry->m_name, name, name_length);
925     entry->m_name_length= name_length;
926     entry->m_enabled= true;
927     PFS_atomic::add_u32(&thread_class_allocated_count, 1);
928     return (index + 1);
929   }
930 
931   thread_class_lost++;
932   return 0;
933 }
934 
935 /**
936   Find a thread instrumentation class by key.
937   @param key                          the instrument key
938   @return the instrument class, or NULL
939 */
find_thread_class(PFS_sync_key key)940 PFS_thread_class *find_thread_class(PFS_sync_key key)
941 {
942   FIND_CLASS_BODY(key, thread_class_allocated_count, thread_class_array);
943 }
944 
sanitize_thread_class(PFS_thread_class * unsafe)945 PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe)
946 {
947   SANITIZE_ARRAY_BODY(PFS_thread_class, thread_class_array, thread_class_max, unsafe);
948 }
949 
950 /**
951   Register a file instrumentation metadata.
952   @param name                         the instrumented name
953   @param name_length                  length in bytes of name
954   @param flags                        the instrumentation flags
955   @return a file instrumentation key
956 */
register_file_class(const char * name,uint name_length,int flags)957 PFS_file_key register_file_class(const char *name, uint name_length,
958                                  int flags)
959 {
960   /* See comments in register_mutex_class */
961   uint32 index;
962   PFS_file_class *entry;
963 
964   REGISTER_CLASS_BODY_PART(index, file_class_array, file_class_max,
965                            name, name_length)
966 
967   index= PFS_atomic::add_u32(&file_class_dirty_count, 1);
968 
969   if (index < file_class_max)
970   {
971     entry= &file_class_array[index];
972     init_instr_class(entry, name, name_length, flags, PFS_CLASS_FILE);
973     entry->m_event_name_index= file_class_start + index;
974     entry->m_singleton= NULL;
975     entry->m_enabled= true; /* enabled by default */
976     entry->m_timed= true;
977     /* Set user-defined configuration options for this instrument */
978     configure_instr_class(entry);
979     PFS_atomic::add_u32(&file_class_allocated_count, 1);
980     return (index + 1);
981   }
982 
983   file_class_lost++;
984   return 0;
985 }
986 
987 /**
988   Register a stage instrumentation metadata.
989   @param name                         the instrumented name
990   @param prefix_length                length in bytes of the name prefix
991   @param name_length                  length in bytes of name
992   @param flags                        the instrumentation flags
993   @return a stage instrumentation key
994 */
register_stage_class(const char * name,uint prefix_length,uint name_length,int flags)995 PFS_stage_key register_stage_class(const char *name,
996                                    uint prefix_length,
997                                    uint name_length,
998                                    int flags)
999 {
1000   /* See comments in register_mutex_class */
1001   uint32 index;
1002   PFS_stage_class *entry;
1003 
1004   REGISTER_CLASS_BODY_PART(index, stage_class_array, stage_class_max,
1005                            name, name_length)
1006 
1007   index= PFS_atomic::add_u32(&stage_class_dirty_count, 1);
1008 
1009   if (index < stage_class_max)
1010   {
1011     entry= &stage_class_array[index];
1012     init_instr_class(entry, name, name_length, flags, PFS_CLASS_STAGE);
1013     entry->m_prefix_length= prefix_length;
1014     entry->m_event_name_index= index;
1015     entry->m_enabled= false; /* disabled by default */
1016     entry->m_timed= false;
1017     /* Set user-defined configuration options for this instrument */
1018     configure_instr_class(entry);
1019     PFS_atomic::add_u32(&stage_class_allocated_count, 1);
1020 
1021     return (index + 1);
1022   }
1023 
1024   stage_class_lost++;
1025   return 0;
1026 }
1027 
1028 /**
1029   Register a statement instrumentation metadata.
1030   @param name                         the instrumented name
1031   @param name_length                  length in bytes of name
1032   @param flags                        the instrumentation flags
1033   @return a statement instrumentation key
1034 */
register_statement_class(const char * name,uint name_length,int flags)1035 PFS_statement_key register_statement_class(const char *name, uint name_length,
1036                                            int flags)
1037 {
1038   /* See comments in register_mutex_class */
1039   uint32 index;
1040   PFS_statement_class *entry;
1041 
1042   REGISTER_CLASS_BODY_PART(index, statement_class_array, statement_class_max,
1043                            name, name_length)
1044 
1045   index= PFS_atomic::add_u32(&statement_class_dirty_count, 1);
1046 
1047   if (index < statement_class_max)
1048   {
1049     entry= &statement_class_array[index];
1050     init_instr_class(entry, name, name_length, flags, PFS_CLASS_STATEMENT);
1051     entry->m_event_name_index= index;
1052     entry->m_enabled= true; /* enabled by default */
1053     entry->m_timed= true;
1054     /* Set user-defined configuration options for this instrument */
1055     configure_instr_class(entry);
1056     PFS_atomic::add_u32(&statement_class_allocated_count, 1);
1057 
1058     return (index + 1);
1059   }
1060 
1061   statement_class_lost++;
1062   return 0;
1063 }
1064 
1065 /**
1066   Find a file instrumentation class by key.
1067   @param key                          the instrument key
1068   @return the instrument class, or NULL
1069 */
find_file_class(PFS_file_key key)1070 PFS_file_class *find_file_class(PFS_file_key key)
1071 {
1072   FIND_CLASS_BODY(key, file_class_allocated_count, file_class_array);
1073 }
1074 
sanitize_file_class(PFS_file_class * unsafe)1075 PFS_file_class *sanitize_file_class(PFS_file_class *unsafe)
1076 {
1077   SANITIZE_ARRAY_BODY(PFS_file_class, file_class_array, file_class_max, unsafe);
1078 }
1079 
1080 /**
1081   Find a stage instrumentation class by key.
1082   @param key                          the instrument key
1083   @return the instrument class, or NULL
1084 */
find_stage_class(PFS_stage_key key)1085 PFS_stage_class *find_stage_class(PFS_stage_key key)
1086 {
1087   FIND_CLASS_BODY(key, stage_class_allocated_count, stage_class_array);
1088 }
1089 
sanitize_stage_class(PFS_stage_class * unsafe)1090 PFS_stage_class *sanitize_stage_class(PFS_stage_class *unsafe)
1091 {
1092   SANITIZE_ARRAY_BODY(PFS_stage_class, stage_class_array, stage_class_max, unsafe);
1093 }
1094 
1095 /**
1096   Find a statement instrumentation class by key.
1097   @param key                          the instrument key
1098   @return the instrument class, or NULL
1099 */
find_statement_class(PFS_stage_key key)1100 PFS_statement_class *find_statement_class(PFS_stage_key key)
1101 {
1102   FIND_CLASS_BODY(key, statement_class_allocated_count, statement_class_array);
1103 }
1104 
sanitize_statement_class(PFS_statement_class * unsafe)1105 PFS_statement_class *sanitize_statement_class(PFS_statement_class *unsafe)
1106 {
1107   SANITIZE_ARRAY_BODY(PFS_statement_class, statement_class_array, statement_class_max, unsafe);
1108 }
1109 
1110 /**
1111   Register a socket instrumentation metadata.
1112   @param name                         the instrumented name
1113   @param name_length                  length in bytes of name
1114   @param flags                        the instrumentation flags
1115   @return a socket instrumentation key
1116 */
register_socket_class(const char * name,uint name_length,int flags)1117 PFS_socket_key register_socket_class(const char *name, uint name_length,
1118                                      int flags)
1119 {
1120   /* See comments in register_mutex_class */
1121   uint32 index;
1122   PFS_socket_class *entry;
1123 
1124   REGISTER_CLASS_BODY_PART(index, socket_class_array, socket_class_max,
1125                            name, name_length)
1126 
1127   index= PFS_atomic::add_u32(&socket_class_dirty_count, 1);
1128 
1129   if (index < socket_class_max)
1130   {
1131     entry= &socket_class_array[index];
1132     init_instr_class(entry, name, name_length, flags, PFS_CLASS_SOCKET);
1133     entry->m_event_name_index= socket_class_start + index;
1134     entry->m_singleton= NULL;
1135     entry->m_enabled= false; /* disabled by default */
1136     entry->m_timed= false;
1137     /* Set user-defined configuration options for this instrument */
1138     configure_instr_class(entry);
1139     PFS_atomic::add_u32(&socket_class_allocated_count, 1);
1140     return (index + 1);
1141   }
1142 
1143   socket_class_lost++;
1144   return 0;
1145 }
1146 
1147 /**
1148   Find a socket instrumentation class by key.
1149   @param key                          the instrument key
1150   @return the instrument class, or NULL
1151 */
find_socket_class(PFS_socket_key key)1152 PFS_socket_class *find_socket_class(PFS_socket_key key)
1153 {
1154   FIND_CLASS_BODY(key, socket_class_allocated_count, socket_class_array);
1155 }
1156 
sanitize_socket_class(PFS_socket_class * unsafe)1157 PFS_socket_class *sanitize_socket_class(PFS_socket_class *unsafe)
1158 {
1159   SANITIZE_ARRAY_BODY(PFS_socket_class, socket_class_array, socket_class_max, unsafe);
1160 }
1161 
find_table_class(uint index)1162 PFS_instr_class *find_table_class(uint index)
1163 {
1164   if (index == 1)
1165     return & global_table_io_class;
1166   if (index == 2)
1167     return & global_table_lock_class;
1168   return NULL;
1169 }
1170 
sanitize_table_class(PFS_instr_class * unsafe)1171 PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe)
1172 {
1173   if (likely((& global_table_io_class == unsafe) ||
1174              (& global_table_lock_class == unsafe)))
1175     return unsafe;
1176   return NULL;
1177 }
1178 
find_idle_class(uint index)1179 PFS_instr_class *find_idle_class(uint index)
1180 {
1181   if (index == 1)
1182     return & global_idle_class;
1183   return NULL;
1184 }
1185 
sanitize_idle_class(PFS_instr_class * unsafe)1186 PFS_instr_class *sanitize_idle_class(PFS_instr_class *unsafe)
1187 {
1188   if (likely(& global_idle_class == unsafe))
1189     return unsafe;
1190   return NULL;
1191 }
1192 
set_keys(PFS_table_share * pfs,const TABLE_SHARE * share)1193 static void set_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
1194 {
1195   int len;
1196   KEY *key_info= share->key_info;
1197   PFS_table_key *pfs_key= pfs->m_keys;
1198   PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
1199   pfs->m_key_count= share->keys;
1200 
1201   for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
1202   {
1203     len= strlen(key_info->name);
1204     memcpy(pfs_key->m_name, key_info->name, len);
1205     pfs_key->m_name_length= len;
1206   }
1207 
1208   pfs_key_last= pfs->m_keys + MAX_INDEXES;
1209   for ( ; pfs_key < pfs_key_last; pfs_key++)
1210     pfs_key->m_name_length= 0;
1211 }
1212 
compare_keys(PFS_table_share * pfs,const TABLE_SHARE * share)1213 static int compare_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
1214 {
1215   uint len;
1216   KEY *key_info= share->key_info;
1217   PFS_table_key *pfs_key= pfs->m_keys;
1218   PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
1219 
1220   if (pfs->m_key_count != share->keys)
1221     return 1;
1222 
1223   for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
1224   {
1225     len= strlen(key_info->name);
1226     if (len != pfs_key->m_name_length)
1227       return 1;
1228 
1229     if (memcmp(pfs_key->m_name, key_info->name, len) != 0)
1230       return 1;
1231   }
1232 
1233   return 0;
1234 }
1235 
1236 /**
1237   Find or create a table share instrumentation.
1238   @param thread                       the executing instrumented thread
1239   @param temporary                    true for TEMPORARY TABLE
1240   @param share                        table share
1241   @return a table share, or NULL
1242 */
find_or_create_table_share(PFS_thread * thread,bool temporary,const TABLE_SHARE * share)1243 PFS_table_share* find_or_create_table_share(PFS_thread *thread,
1244                                             bool temporary,
1245                                             const TABLE_SHARE *share)
1246 {
1247   /* See comments in register_mutex_class */
1248   PFS_table_share_key key;
1249 
1250   LF_PINS *pins= get_table_share_hash_pins(thread);
1251   if (unlikely(pins == NULL))
1252   {
1253     table_share_lost++;
1254     return NULL;
1255   }
1256 
1257   const char *schema_name= share->db.str;
1258   uint schema_name_length= share->db.length;
1259   const char *table_name= share->table_name.str;
1260   uint table_name_length= share->table_name.length;
1261 
1262   set_table_share_key(&key, temporary,
1263                       schema_name, schema_name_length,
1264                       table_name, table_name_length);
1265 
1266   PFS_table_share **entry;
1267   uint retry_count= 0;
1268   const uint retry_max= 3;
1269   bool enabled= true;
1270   bool timed= true;
1271   static uint PFS_ALIGNED table_share_monotonic_index= 0;
1272   uint index;
1273   uint attempts= 0;
1274   PFS_table_share *pfs;
1275 
1276 search:
1277   entry= reinterpret_cast<PFS_table_share**>
1278     (lf_hash_search(&table_share_hash, pins,
1279                     key.m_hash_key, key.m_key_length));
1280   if (entry && (entry != MY_ERRPTR))
1281   {
1282     pfs= *entry;
1283     pfs->inc_refcount() ;
1284     if (compare_keys(pfs, share) != 0)
1285     {
1286       set_keys(pfs, share);
1287       /* FIXME: aggregate to table_share sink ? */
1288       pfs->m_table_stat.fast_reset();
1289     }
1290     lf_hash_search_unpin(pins);
1291     return pfs;
1292   }
1293 
1294   lf_hash_search_unpin(pins);
1295 
1296   if (retry_count == 0)
1297   {
1298     lookup_setup_object(thread,
1299                         OBJECT_TYPE_TABLE,
1300                         schema_name, schema_name_length,
1301                         table_name, table_name_length,
1302                         &enabled, &timed);
1303     /*
1304       Even when enabled is false, a record is added in the dictionary:
1305       - It makes enabling a table already in the table cache possible,
1306       - It improves performances for the next time a TABLE_SHARE is reloaded
1307         in the table cache.
1308     */
1309   }
1310 
1311   while (++attempts <= table_share_max)
1312   {
1313     /* See create_mutex() */
1314     index= PFS_atomic::add_u32(& table_share_monotonic_index, 1) % table_share_max;
1315     pfs= table_share_array + index;
1316 
1317     if (pfs->m_lock.is_free())
1318     {
1319       if (pfs->m_lock.free_to_dirty())
1320       {
1321         pfs->m_key= key;
1322         pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
1323         pfs->m_schema_name_length= schema_name_length;
1324         pfs->m_table_name= &pfs->m_key.m_hash_key[schema_name_length + 2];
1325         pfs->m_table_name_length= table_name_length;
1326         pfs->m_enabled= enabled;
1327         pfs->m_timed= timed;
1328         pfs->init_refcount();
1329         pfs->m_table_stat.fast_reset();
1330         set_keys(pfs, share);
1331 
1332         int res;
1333         res= lf_hash_insert(&table_share_hash, pins, &pfs);
1334         if (likely(res == 0))
1335         {
1336           pfs->m_lock.dirty_to_allocated();
1337           return pfs;
1338         }
1339 
1340         pfs->m_lock.dirty_to_free();
1341 
1342         if (res > 0)
1343         {
1344           /* Duplicate insert by another thread */
1345           if (++retry_count > retry_max)
1346           {
1347             /* Avoid infinite loops */
1348             table_share_lost++;
1349             return NULL;
1350           }
1351           goto search;
1352         }
1353 
1354         /* OOM in lf_hash_insert */
1355         table_share_lost++;
1356         return NULL;
1357       }
1358     }
1359   }
1360 
1361   table_share_lost++;
1362   return NULL;
1363 }
1364 
aggregate_io(void)1365 void PFS_table_share::aggregate_io(void)
1366 {
1367   uint safe_key_count= sanitize_index_count(m_key_count);
1368   PFS_table_io_stat *from_stat;
1369   PFS_table_io_stat *from_stat_last;
1370   PFS_table_io_stat sum_io;
1371 
1372   /* Aggregate stats for each index, if any */
1373   from_stat= & m_table_stat.m_index_stat[0];
1374   from_stat_last= from_stat + safe_key_count;
1375   for ( ; from_stat < from_stat_last ; from_stat++)
1376     sum_io.aggregate(from_stat);
1377 
1378   /* Aggregate stats for the table */
1379   sum_io.aggregate(& m_table_stat.m_index_stat[MAX_INDEXES]);
1380 
1381   /* Add this table stats to the global sink. */
1382   global_table_io_stat.aggregate(& sum_io);
1383   m_table_stat.fast_reset_io();
1384 }
1385 
aggregate_lock(void)1386 void PFS_table_share::aggregate_lock(void)
1387 {
1388   global_table_lock_stat.aggregate(& m_table_stat.m_lock_stat);
1389   m_table_stat.fast_reset_lock();
1390 }
1391 
release_table_share(PFS_table_share * pfs)1392 void release_table_share(PFS_table_share *pfs)
1393 {
1394   DBUG_ASSERT(pfs->get_refcount() > 0);
1395   pfs->dec_refcount();
1396 }
1397 
1398 /**
1399   Drop the instrumented table share associated with a table.
1400   @param thread The running thread
1401   @param temporary True for TEMPORARY TABLE
1402   @param schema_name The table schema name
1403   @param schema_name_length The table schema name length
1404   @param table_name The table name
1405   @param table_name_length The table name length
1406 */
drop_table_share(PFS_thread * thread,bool temporary,const char * schema_name,uint schema_name_length,const char * table_name,uint table_name_length)1407 void drop_table_share(PFS_thread *thread,
1408                       bool temporary,
1409                       const char *schema_name, uint schema_name_length,
1410                       const char *table_name, uint table_name_length)
1411 {
1412   PFS_table_share_key key;
1413   LF_PINS* pins= get_table_share_hash_pins(thread);
1414   if (unlikely(pins == NULL))
1415     return;
1416   set_table_share_key(&key, temporary, schema_name, schema_name_length,
1417                       table_name, table_name_length);
1418   PFS_table_share **entry;
1419   entry= reinterpret_cast<PFS_table_share**>
1420     (lf_hash_search(&table_share_hash, pins,
1421                     key.m_hash_key, key.m_key_length));
1422   if (entry && (entry != MY_ERRPTR))
1423   {
1424     PFS_table_share *pfs= *entry;
1425     lf_hash_delete(&table_share_hash, pins,
1426                    pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
1427     pfs->m_lock.allocated_to_free();
1428   }
1429 
1430   lf_hash_search_unpin(pins);
1431 }
1432 
1433 /**
1434   Sanitize an unsafe table_share pointer.
1435   @param unsafe The possibly corrupt pointer.
1436   @return A valid table_safe_pointer, or NULL.
1437 */
sanitize_table_share(PFS_table_share * unsafe)1438 PFS_table_share *sanitize_table_share(PFS_table_share *unsafe)
1439 {
1440   SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe);
1441 }
1442 
1443 /** Reset the wait statistics per instrument class. */
reset_events_waits_by_class()1444 void reset_events_waits_by_class()
1445 {
1446   reset_file_class_io();
1447   reset_socket_class_io();
1448   global_idle_stat.reset();
1449   global_table_io_stat.reset();
1450   global_table_lock_stat.reset();
1451 }
1452 
1453 /** Reset the io statistics per file class. */
reset_file_class_io(void)1454 void reset_file_class_io(void)
1455 {
1456   PFS_file_class *pfs= file_class_array;
1457   PFS_file_class *pfs_last= file_class_array + file_class_max;
1458 
1459   for ( ; pfs < pfs_last; pfs++)
1460     pfs->m_file_stat.m_io_stat.reset();
1461 }
1462 
1463 /** Reset the io statistics per socket class. */
reset_socket_class_io(void)1464 void reset_socket_class_io(void)
1465 {
1466   PFS_socket_class *pfs= socket_class_array;
1467   PFS_socket_class *pfs_last= socket_class_array + socket_class_max;
1468 
1469   for ( ; pfs < pfs_last; pfs++)
1470     pfs->m_socket_stat.m_io_stat.reset();
1471 }
1472 
update_table_share_derived_flags(PFS_thread * thread)1473 void update_table_share_derived_flags(PFS_thread *thread)
1474 {
1475   PFS_table_share *pfs= table_share_array;
1476   PFS_table_share *pfs_last= table_share_array + table_share_max;
1477 
1478   for ( ; pfs < pfs_last; pfs++)
1479   {
1480     if (pfs->m_lock.is_populated())
1481       pfs->refresh_setup_object_flags(thread);
1482   }
1483 }
1484 
1485 /** @} */
1486 
1487