MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pfs_instr_class.cc
Go to the documentation of this file.
1 /* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
21 #include "my_global.h"
22 #include "my_sys.h"
23 #include "structs.h"
24 #include "table.h"
25 #include "pfs_instr_class.h"
26 #include "pfs_instr.h"
27 #include "pfs_global.h"
28 #include "pfs_timer.h"
29 #include "pfs_events_waits.h"
30 #include "pfs_setup_object.h"
31 #include "pfs_atomic.h"
32 #include "mysql/psi/mysql_thread.h"
33 #include "lf.h"
34 
35 #include <string.h>
36 
48 my_bool pfs_enabled= TRUE;
49 
55 int pfs_instr_config_state= PFS_INSTR_CONFIG_NOT_INITIALIZED;
56 
57 static void configure_instr_class(PFS_instr_class *entry);
58 
59 static void init_instr_class(PFS_instr_class *klass,
60  const char *name,
61  uint name_length,
62  int flags,
63  PFS_class_type class_type);
64 
71 static volatile uint32 mutex_class_dirty_count= 0;
72 static volatile uint32 mutex_class_allocated_count= 0;
73 static volatile uint32 rwlock_class_dirty_count= 0;
74 static volatile uint32 rwlock_class_allocated_count= 0;
75 static volatile uint32 cond_class_dirty_count= 0;
76 static volatile uint32 cond_class_allocated_count= 0;
77 
79 ulong mutex_class_max= 0;
87 ulong cond_class_max= 0;
89 ulong cond_class_lost= 0;
95 ulong file_class_max= 0;
97 ulong file_class_lost= 0;
99 ulong stage_class_max= 0;
114 
115 PFS_mutex_class *mutex_class_array= NULL;
116 PFS_rwlock_class *rwlock_class_array= NULL;
117 PFS_cond_class *cond_class_array= NULL;
118 
125 static volatile uint32 thread_class_dirty_count= 0;
126 static volatile uint32 thread_class_allocated_count= 0;
127 
128 static PFS_thread_class *thread_class_array= NULL;
129 
137 
144 
147 {&wait_timer, /* PFS_CLASS_NONE */
148  &wait_timer, /* PFS_CLASS_MUTEX */
149  &wait_timer, /* PFS_CLASS_RWLOCK */
150  &wait_timer, /* PFS_CLASS_COND */
151  &wait_timer, /* PFS_CLASS_FILE */
152  &wait_timer, /* PFS_CLASS_TABLE */
153  &stage_timer, /* PFS_CLASS_STAGE */
154  &statement_timer, /* PFS_CLASS_STATEMENT */
155  &wait_timer, /* PFS_CLASS_SOCKET */
156  &wait_timer, /* PFS_CLASS_TABLE_IO */
157  &wait_timer, /* PFS_CLASS_TABLE_LOCK */
158  &idle_timer /* PFS_CLASS_IDLE */
159 };
160 
173 static bool table_share_hash_inited= false;
174 
175 static volatile uint32 file_class_dirty_count= 0;
176 static volatile uint32 file_class_allocated_count= 0;
177 
178 PFS_file_class *file_class_array= NULL;
179 
180 static volatile uint32 stage_class_dirty_count= 0;
181 static volatile uint32 stage_class_allocated_count= 0;
182 
183 static PFS_stage_class *stage_class_array= NULL;
184 
185 static volatile uint32 statement_class_dirty_count= 0;
186 static volatile uint32 statement_class_allocated_count= 0;
187 
188 static PFS_statement_class *statement_class_array= NULL;
189 
190 static volatile uint32 socket_class_dirty_count= 0;
191 static volatile uint32 socket_class_allocated_count= 0;
192 
193 static PFS_socket_class *socket_class_array= NULL;
194 
195 uint mutex_class_start= 0;
196 uint rwlock_class_start= 0;
197 uint cond_class_start= 0;
198 uint file_class_start= 0;
199 uint wait_class_max= 0;
200 uint socket_class_start= 0;
201 
202 void init_event_name_sizing(const PFS_global_param *param)
203 {
204  mutex_class_start= 3; /* global table io, table lock, idle */
205  rwlock_class_start= mutex_class_start + param->m_mutex_class_sizing;
206  cond_class_start= rwlock_class_start + param->m_rwlock_class_sizing;
207  file_class_start= cond_class_start + param->m_cond_class_sizing;
208  socket_class_start= file_class_start + param->m_file_class_sizing;
209  wait_class_max= socket_class_start + param->m_socket_class_sizing;
210 }
211 
212 void register_global_classes()
213 {
214  /* Table IO class */
215  init_instr_class(&global_table_io_class, "wait/io/table/sql/handler", 25,
216  0, PFS_CLASS_TABLE_IO);
217  global_table_io_class.m_event_name_index= GLOBAL_TABLE_IO_EVENT_INDEX;
218  configure_instr_class(&global_table_io_class);
219 
220  /* Table lock class */
221  init_instr_class(&global_table_lock_class, "wait/lock/table/sql/handler", 27,
222  0, PFS_CLASS_TABLE_LOCK);
223  global_table_lock_class.m_event_name_index= GLOBAL_TABLE_LOCK_EVENT_INDEX;
224  configure_instr_class(&global_table_lock_class);
225 
226  /* Idle class */
227  init_instr_class(&global_idle_class, "idle", 4,
228  0, PFS_CLASS_IDLE);
229  global_idle_class.m_event_name_index= GLOBAL_IDLE_EVENT_INDEX;
230  configure_instr_class(&global_idle_class);
231 }
232 
240 int init_sync_class(uint mutex_class_sizing,
241  uint rwlock_class_sizing,
242  uint cond_class_sizing)
243 {
244  mutex_class_dirty_count= mutex_class_allocated_count= 0;
245  rwlock_class_dirty_count= rwlock_class_allocated_count= 0;
246  cond_class_dirty_count= cond_class_allocated_count= 0;
247  mutex_class_max= mutex_class_sizing;
248  rwlock_class_max= rwlock_class_sizing;
249  cond_class_max= cond_class_sizing;
251 
252  mutex_class_array= NULL;
253  rwlock_class_array= NULL;
254  cond_class_array= NULL;
255 
256  if (mutex_class_max > 0)
257  {
259  MYF(MY_ZEROFILL));
260  if (unlikely(mutex_class_array == NULL))
261  return 1;
262  }
263 
264  if (rwlock_class_max > 0)
265  {
267  MYF(MY_ZEROFILL));
268  if (unlikely(rwlock_class_array == NULL))
269  return 1;
270  }
271 
272  if (cond_class_max > 0)
273  {
275  MYF(MY_ZEROFILL));
276  if (unlikely(cond_class_array == NULL))
277  return 1;
278  }
279 
280  return 0;
281 }
282 
285 {
286  pfs_free(mutex_class_array);
287  mutex_class_array= NULL;
288  mutex_class_dirty_count= mutex_class_allocated_count= mutex_class_max= 0;
289  pfs_free(rwlock_class_array);
290  rwlock_class_array= NULL;
291  rwlock_class_dirty_count= rwlock_class_allocated_count= rwlock_class_max= 0;
292  pfs_free(cond_class_array);
293  cond_class_array= NULL;
294  cond_class_dirty_count= cond_class_allocated_count= cond_class_max= 0;
295 }
296 
302 int init_thread_class(uint thread_class_sizing)
303 {
304  int result= 0;
305  thread_class_dirty_count= thread_class_allocated_count= 0;
306  thread_class_max= thread_class_sizing;
308 
309  if (thread_class_max > 0)
310  {
312  MYF(MY_ZEROFILL));
313  if (unlikely(thread_class_array == NULL))
314  result= 1;
315  }
316  else
317  thread_class_array= NULL;
318 
319  return result;
320 }
321 
324 {
325  pfs_free(thread_class_array);
326  thread_class_array= NULL;
327  thread_class_dirty_count= thread_class_allocated_count= 0;
328  thread_class_max= 0;
329 }
330 
336 int init_table_share(uint table_share_sizing)
337 {
338  int result= 0;
339  table_share_max= table_share_sizing;
340  table_share_lost= 0;
341 
342  if (table_share_max > 0)
343  {
345  MYF(MY_ZEROFILL));
346  if (unlikely(table_share_array == NULL))
347  result= 1;
348  }
349  else
350  table_share_array= NULL;
351 
352  return result;
353 }
354 
357 {
358  pfs_free(table_share_array);
359  table_share_array= NULL;
360  table_share_max= 0;
361 }
362 
363 C_MODE_START
365 static uchar *table_share_hash_get_key(const uchar *entry, size_t *length,
366  my_bool)
367 {
368  const PFS_table_share * const *typed_entry;
369  const PFS_table_share *share;
370  const void *result;
371  typed_entry= reinterpret_cast<const PFS_table_share* const *> (entry);
372  DBUG_ASSERT(typed_entry != NULL);
373  share= *typed_entry;
374  DBUG_ASSERT(share != NULL);
375  *length= share->m_key.m_key_length;
376  result= &share->m_key.m_hash_key[0];
377  return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
378 }
379 C_MODE_END
380 
383 {
384  if ((! table_share_hash_inited) && (table_share_max > 0))
385  {
386  lf_hash_init(&table_share_hash, sizeof(PFS_table_share*), LF_HASH_UNIQUE,
387  0, 0, table_share_hash_get_key, &my_charset_bin);
388  table_share_hash.size= table_share_max;
389  table_share_hash_inited= true;
390  }
391  return 0;
392 }
393 
396 {
397  if (table_share_hash_inited)
398  {
399  lf_hash_destroy(&table_share_hash);
400  table_share_hash_inited= false;
401  }
402 }
403 
410 {
411  if (unlikely(thread->m_table_share_hash_pins == NULL))
412  {
413  if (! table_share_hash_inited)
414  return NULL;
415  thread->m_table_share_hash_pins= lf_hash_get_pins(&table_share_hash);
416  }
417  return thread->m_table_share_hash_pins;
418 }
419 
429 static void set_table_share_key(PFS_table_share_key *key,
430  bool temporary,
431  const char *schema_name, uint schema_name_length,
432  const char *table_name, uint table_name_length)
433 {
434  DBUG_ASSERT(schema_name_length <= NAME_LEN);
435  DBUG_ASSERT(table_name_length <= NAME_LEN);
436  char *saved_schema_name;
437  char *saved_table_name;
438 
439  char *ptr= &key->m_hash_key[0];
440  ptr[0]= (temporary ? OBJECT_TYPE_TEMPORARY_TABLE : OBJECT_TYPE_TABLE);
441  ptr++;
442  saved_schema_name= ptr;
443  memcpy(ptr, schema_name, schema_name_length);
444  ptr+= schema_name_length;
445  ptr[0]= 0;
446  ptr++;
447  saved_table_name= ptr;
448  memcpy(ptr, table_name, table_name_length);
449  ptr+= table_name_length;
450  ptr[0]= 0;
451  ptr++;
452  key->m_key_length= ptr - &key->m_hash_key[0];
453 
454  if (lower_case_table_names)
455  {
456  my_casedn_str(files_charset_info, saved_schema_name);
457  my_casedn_str(files_charset_info, saved_table_name);
458  }
459 }
460 
461 void PFS_table_share::refresh_setup_object_flags(PFS_thread *thread)
462 {
463  lookup_setup_object(thread,
464  OBJECT_TYPE_TABLE,
467  &m_enabled, &m_timed);
468 }
469 
475 int init_file_class(uint file_class_sizing)
476 {
477  int result= 0;
478  file_class_dirty_count= file_class_allocated_count= 0;
479  file_class_max= file_class_sizing;
480  file_class_lost= 0;
481 
482  if (file_class_max > 0)
483  {
485  MYF(MY_ZEROFILL));
486  if (unlikely(file_class_array == NULL))
487  return 1;
488  }
489  else
490  file_class_array= NULL;
491 
492  return result;
493 }
494 
497 {
498  pfs_free(file_class_array);
499  file_class_array= NULL;
500  file_class_dirty_count= file_class_allocated_count= 0;
501  file_class_max= 0;
502 }
503 
509 int init_stage_class(uint stage_class_sizing)
510 {
511  int result= 0;
512  stage_class_dirty_count= stage_class_allocated_count= 0;
513  stage_class_max= stage_class_sizing;
514  stage_class_lost= 0;
515 
516  if (stage_class_max > 0)
517  {
519  MYF(MY_ZEROFILL));
520  if (unlikely(stage_class_array == NULL))
521  return 1;
522  }
523  else
524  stage_class_array= NULL;
525 
526  return result;
527 }
528 
531 {
532  pfs_free(stage_class_array);
533  stage_class_array= NULL;
534  stage_class_dirty_count= stage_class_allocated_count= 0;
535  stage_class_max= 0;
536 }
537 
543 int init_statement_class(uint statement_class_sizing)
544 {
545  int result= 0;
546  statement_class_dirty_count= statement_class_allocated_count= 0;
547  statement_class_max= statement_class_sizing;
549 
550  if (statement_class_max > 0)
551  {
553  MYF(MY_ZEROFILL));
554  if (unlikely(statement_class_array == NULL))
555  return 1;
556  }
557  else
558  statement_class_array= NULL;
559 
560  return result;
561 }
562 
565 {
566  pfs_free(statement_class_array);
567  statement_class_array= NULL;
568  statement_class_dirty_count= statement_class_allocated_count= 0;
570 }
571 
577 int init_socket_class(uint socket_class_sizing)
578 {
579  int result= 0;
580  socket_class_dirty_count= socket_class_allocated_count= 0;
581  socket_class_max= socket_class_sizing;
583 
584  if (socket_class_max > 0)
585  {
587  MYF(MY_ZEROFILL));
588  if (unlikely(socket_class_array == NULL))
589  return 1;
590  }
591  else
592  socket_class_array= NULL;
593 
594  return result;
595 }
596 
599 {
600  pfs_free(socket_class_array);
601  socket_class_array= NULL;
602  socket_class_dirty_count= socket_class_allocated_count= 0;
603  socket_class_max= 0;
604 }
605 
606 static void init_instr_class(PFS_instr_class *klass,
607  const char *name,
608  uint name_length,
609  int flags,
610  PFS_class_type class_type)
611 {
612  DBUG_ASSERT(name_length <= PFS_MAX_INFO_NAME_LENGTH);
613  memset(klass, 0, sizeof(PFS_instr_class));
614  strncpy(klass->m_name, name, name_length);
615  klass->m_name_length= name_length;
616  klass->m_flags= flags;
617  klass->m_enabled= true;
618  klass->m_timed= true;
619  klass->m_type= class_type;
620  klass->m_timer= class_timers[class_type];
621 }
622 
626 static void configure_instr_class(PFS_instr_class *entry)
627 {
628  uint match_length= 0; /* length of matching pattern */
629 
630  for (uint i= 0; i < pfs_instr_config_array.elements; i++)
631  {
632  PFS_instr_config* e;
633  get_dynamic(&pfs_instr_config_array, (uchar*)&e, i);
634 
643  if (!my_wildcmp(&my_charset_latin1,
644  entry->m_name, entry->m_name+entry->m_name_length,
645  e->m_name, e->m_name+e->m_name_length,
646  '\\', '?','%'))
647  {
648  if (e->m_name_length >= match_length)
649  {
650  entry->m_enabled= e->m_enabled;
651  entry->m_timed= e->m_timed;
652  match_length= MY_MAX(e->m_name_length, match_length);
653  }
654  }
655  }
656 }
657 
658 #define REGISTER_CLASS_BODY_PART(INDEX, ARRAY, MAX, NAME, NAME_LENGTH) \
659  for (INDEX= 0; INDEX < MAX; INDEX++) \
660  { \
661  entry= &ARRAY[INDEX]; \
662  if ((entry->m_name_length == NAME_LENGTH) && \
663  (strncmp(entry->m_name, NAME, NAME_LENGTH) == 0)) \
664  { \
665  DBUG_ASSERT(entry->m_flags == flags); \
666  return (INDEX + 1); \
667  } \
668  }
669 
677 PFS_sync_key register_mutex_class(const char *name, uint name_length,
678  int flags)
679 {
680  uint32 index;
682 
683  /*
684  This is a full array scan, which is not optimal.
685  This is acceptable since this code is only used at startup,
686  or when a plugin is loaded.
687  */
688  REGISTER_CLASS_BODY_PART(index, mutex_class_array, mutex_class_max,
689  name, name_length)
690  /*
691  Note that:
692  mutex_class_dirty_count is incremented *before* an entry is added
693  mutex_class_allocated_count is incremented *after* an entry is added
694  */
695  index= PFS_atomic::add_u32(&mutex_class_dirty_count, 1);
696 
697  if (index < mutex_class_max)
698  {
699  /*
700  The instrument was not found (from a possible previous
701  load / unload of a plugin), allocate it.
702  This code is safe when 2 threads execute in parallel
703  for different mutex classes:
704  - thread 1 registering class A
705  - thread 2 registering class B
706  will not collide in the same mutex_class_array[index] entry.
707  This code does not protect against 2 threads registering
708  in parallel the same class:
709  - thread 1 registering class A
710  - thread 2 registering class A
711  could lead to a duplicate class A entry.
712  This is ok, since this case can not happen in the caller:
713  - classes names are derived from a plugin name
714  ('wait/synch/mutex/<plugin>/xxx')
715  - 2 threads can not register concurrently the same plugin
716  in INSTALL PLUGIN.
717  */
718  entry= &mutex_class_array[index];
719  init_instr_class(entry, name, name_length, flags, PFS_CLASS_MUTEX);
720  entry->m_mutex_stat.reset();
721  entry->m_event_name_index= mutex_class_start + index;
722  entry->m_singleton= NULL;
723  entry->m_enabled= false; /* disabled by default */
724  entry->m_timed= false;
725 
726  /* Set user-defined configuration options for this instrument */
727  configure_instr_class(entry);
728 
729  /*
730  Now that this entry is populated, advertise it
731 
732  Technically, there is a small race condition here:
733  T0:
734  mutex_class_dirty_count= 10
735  mutex_class_allocated_count= 10
736  T1: Thread A increment mutex_class_dirty_count to 11
737  T2: Thread B increment mutex_class_dirty_count to 12
738  T3: Thread A populate entry 11
739  T4: Thread B populate entry 12
740  T5: Thread B increment mutex_class_allocated_count to 11,
741  advertise thread A incomplete record 11,
742  but does not advertise thread B complete record 12
743  T6: Thread A increment mutex_class_allocated_count to 12
744  This has no impact, and is acceptable.
745  A reader will not see record 12 for a short time.
746  A reader will see an incomplete record 11 for a short time,
747  which is ok: the mutex name / statistics will be temporarily
748  empty/NULL/zero, but this won't cause a crash
749  (mutex_class_array is initialized with MY_ZEROFILL).
750  */
751  PFS_atomic::add_u32(&mutex_class_allocated_count, 1);
752  return (index + 1);
753  }
754 
755  /*
756  Out of space, report to SHOW STATUS that
757  the allocated memory was too small.
758  */
760  return 0;
761 }
762 
770 PFS_sync_key register_rwlock_class(const char *name, uint name_length,
771  int flags)
772 {
773  /* See comments in register_mutex_class */
774  uint32 index;
776 
777  REGISTER_CLASS_BODY_PART(index, rwlock_class_array, rwlock_class_max,
778  name, name_length)
779 
780  index= PFS_atomic::add_u32(&rwlock_class_dirty_count, 1);
781 
782  if (index < rwlock_class_max)
783  {
784  entry= &rwlock_class_array[index];
785  init_instr_class(entry, name, name_length, flags, PFS_CLASS_RWLOCK);
786  entry->m_rwlock_stat.reset();
787  entry->m_event_name_index= rwlock_class_start + index;
788  entry->m_singleton= NULL;
789  entry->m_enabled= false; /* disabled by default */
790  entry->m_timed= false;
791  /* Set user-defined configuration options for this instrument */
792  configure_instr_class(entry);
793  PFS_atomic::add_u32(&rwlock_class_allocated_count, 1);
794  return (index + 1);
795  }
796 
798  return 0;
799 }
800 
808 PFS_sync_key register_cond_class(const char *name, uint name_length,
809  int flags)
810 {
811  /* See comments in register_mutex_class */
812  uint32 index;
814 
815  REGISTER_CLASS_BODY_PART(index, cond_class_array, cond_class_max,
816  name, name_length)
817 
818  index= PFS_atomic::add_u32(&cond_class_dirty_count, 1);
819 
820  if (index < cond_class_max)
821  {
822  entry= &cond_class_array[index];
823  init_instr_class(entry, name, name_length, flags, PFS_CLASS_COND);
824  entry->m_event_name_index= cond_class_start + index;
825  entry->m_singleton= NULL;
826  entry->m_enabled= false; /* disabled by default */
827  entry->m_timed= false;
828  /* Set user-defined configuration options for this instrument */
829  configure_instr_class(entry);
830  PFS_atomic::add_u32(&cond_class_allocated_count, 1);
831  return (index + 1);
832  }
833 
834  cond_class_lost++;
835  return 0;
836 }
837 
838 #define FIND_CLASS_BODY(KEY, COUNT, ARRAY) \
839  if ((KEY == 0) || (KEY > COUNT)) \
840  return NULL; \
841  return &ARRAY[KEY - 1]
842 
849 {
850  FIND_CLASS_BODY(key, mutex_class_allocated_count, mutex_class_array);
851 }
852 
853 PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe)
854 {
855  SANITIZE_ARRAY_BODY(PFS_mutex_class, mutex_class_array, mutex_class_max, unsafe);
856 }
857 
864 {
865  FIND_CLASS_BODY(key, rwlock_class_allocated_count, rwlock_class_array);
866 }
867 
868 PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe)
869 {
870  SANITIZE_ARRAY_BODY(PFS_rwlock_class, rwlock_class_array, rwlock_class_max, unsafe);
871 }
872 
879 {
880  FIND_CLASS_BODY(key, cond_class_allocated_count, cond_class_array);
881 }
882 
883 PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe)
884 {
885  SANITIZE_ARRAY_BODY(PFS_cond_class, cond_class_array, cond_class_max, unsafe);
886 }
887 
895 PFS_thread_key register_thread_class(const char *name, uint name_length,
896  int flags)
897 {
898  /* See comments in register_mutex_class */
899  uint32 index;
901 
902  for (index= 0; index < thread_class_max; index++)
903  {
904  entry= &thread_class_array[index];
905 
906  if ((entry->m_name_length == name_length) &&
907  (strncmp(entry->m_name, name, name_length) == 0))
908  return (index + 1);
909  }
910 
911  index= PFS_atomic::add_u32(&thread_class_dirty_count, 1);
912 
913  if (index < thread_class_max)
914  {
915  entry= &thread_class_array[index];
916  DBUG_ASSERT(name_length <= PFS_MAX_INFO_NAME_LENGTH);
917  strncpy(entry->m_name, name, name_length);
918  entry->m_name_length= name_length;
919  entry->m_enabled= true;
920  PFS_atomic::add_u32(&thread_class_allocated_count, 1);
921  return (index + 1);
922  }
923 
925  return 0;
926 }
927 
934 {
935  FIND_CLASS_BODY(key, thread_class_allocated_count, thread_class_array);
936 }
937 
938 PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe)
939 {
940  SANITIZE_ARRAY_BODY(PFS_thread_class, thread_class_array, thread_class_max, unsafe);
941 }
942 
950 PFS_file_key register_file_class(const char *name, uint name_length,
951  int flags)
952 {
953  /* See comments in register_mutex_class */
954  uint32 index;
956 
957  REGISTER_CLASS_BODY_PART(index, file_class_array, file_class_max,
958  name, name_length)
959 
960  index= PFS_atomic::add_u32(&file_class_dirty_count, 1);
961 
962  if (index < file_class_max)
963  {
964  entry= &file_class_array[index];
965  init_instr_class(entry, name, name_length, flags, PFS_CLASS_FILE);
966  entry->m_event_name_index= file_class_start + index;
967  entry->m_singleton= NULL;
968  entry->m_enabled= true; /* enabled by default */
969  entry->m_timed= true;
970  /* Set user-defined configuration options for this instrument */
971  configure_instr_class(entry);
972  PFS_atomic::add_u32(&file_class_allocated_count, 1);
973  return (index + 1);
974  }
975 
976  file_class_lost++;
977  return 0;
978 }
979 
989  uint prefix_length,
990  uint name_length,
991  int flags)
992 {
993  /* See comments in register_mutex_class */
994  uint32 index;
996 
997  REGISTER_CLASS_BODY_PART(index, stage_class_array, stage_class_max,
998  name, name_length)
999 
1000  index= PFS_atomic::add_u32(&stage_class_dirty_count, 1);
1001 
1002  if (index < stage_class_max)
1003  {
1004  entry= &stage_class_array[index];
1005  init_instr_class(entry, name, name_length, flags, PFS_CLASS_STAGE);
1006  entry->m_prefix_length= prefix_length;
1007  entry->m_event_name_index= index;
1008  entry->m_enabled= false; /* disabled by default */
1009  entry->m_timed= false;
1010  /* Set user-defined configuration options for this instrument */
1011  configure_instr_class(entry);
1012  PFS_atomic::add_u32(&stage_class_allocated_count, 1);
1013 
1014  return (index + 1);
1015  }
1016 
1017  stage_class_lost++;
1018  return 0;
1019 }
1020 
1028 PFS_statement_key register_statement_class(const char *name, uint name_length,
1029  int flags)
1030 {
1031  /* See comments in register_mutex_class */
1032  uint32 index;
1034 
1035  REGISTER_CLASS_BODY_PART(index, statement_class_array, statement_class_max,
1036  name, name_length)
1037 
1038  index= PFS_atomic::add_u32(&statement_class_dirty_count, 1);
1039 
1040  if (index < statement_class_max)
1041  {
1042  entry= &statement_class_array[index];
1043  init_instr_class(entry, name, name_length, flags, PFS_CLASS_STATEMENT);
1044  entry->m_event_name_index= index;
1045  entry->m_enabled= true; /* enabled by default */
1046  entry->m_timed= true;
1047  /* Set user-defined configuration options for this instrument */
1048  configure_instr_class(entry);
1049  PFS_atomic::add_u32(&statement_class_allocated_count, 1);
1050 
1051  return (index + 1);
1052  }
1053 
1055  return 0;
1056 }
1057 
1064 {
1065  FIND_CLASS_BODY(key, file_class_allocated_count, file_class_array);
1066 }
1067 
1068 PFS_file_class *sanitize_file_class(PFS_file_class *unsafe)
1069 {
1070  SANITIZE_ARRAY_BODY(PFS_file_class, file_class_array, file_class_max, unsafe);
1071 }
1072 
1079 {
1080  FIND_CLASS_BODY(key, stage_class_allocated_count, stage_class_array);
1081 }
1082 
1083 PFS_stage_class *sanitize_stage_class(PFS_stage_class *unsafe)
1084 {
1085  SANITIZE_ARRAY_BODY(PFS_stage_class, stage_class_array, stage_class_max, unsafe);
1086 }
1087 
1094 {
1095  FIND_CLASS_BODY(key, statement_class_allocated_count, statement_class_array);
1096 }
1097 
1098 PFS_statement_class *sanitize_statement_class(PFS_statement_class *unsafe)
1099 {
1100  SANITIZE_ARRAY_BODY(PFS_statement_class, statement_class_array, statement_class_max, unsafe);
1101 }
1102 
1110 PFS_socket_key register_socket_class(const char *name, uint name_length,
1111  int flags)
1112 {
1113  /* See comments in register_mutex_class */
1114  uint32 index;
1116 
1117  REGISTER_CLASS_BODY_PART(index, socket_class_array, socket_class_max,
1118  name, name_length)
1119 
1120  index= PFS_atomic::add_u32(&socket_class_dirty_count, 1);
1121 
1122  if (index < socket_class_max)
1123  {
1124  entry= &socket_class_array[index];
1125  init_instr_class(entry, name, name_length, flags, PFS_CLASS_SOCKET);
1126  entry->m_event_name_index= socket_class_start + index;
1127  entry->m_singleton= NULL;
1128  entry->m_enabled= false; /* disabled by default */
1129  entry->m_timed= false;
1130  /* Set user-defined configuration options for this instrument */
1131  configure_instr_class(entry);
1132  PFS_atomic::add_u32(&socket_class_allocated_count, 1);
1133  return (index + 1);
1134  }
1135 
1137  return 0;
1138 }
1139 
1146 {
1147  FIND_CLASS_BODY(key, socket_class_allocated_count, socket_class_array);
1148 }
1149 
1150 PFS_socket_class *sanitize_socket_class(PFS_socket_class *unsafe)
1151 {
1152  SANITIZE_ARRAY_BODY(PFS_socket_class, socket_class_array, socket_class_max, unsafe);
1153 }
1154 
1155 PFS_instr_class *find_table_class(uint index)
1156 {
1157  if (index == 1)
1158  return & global_table_io_class;
1159  if (index == 2)
1160  return & global_table_lock_class;
1161  return NULL;
1162 }
1163 
1164 PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe)
1165 {
1166  if (likely((& global_table_io_class == unsafe) ||
1167  (& global_table_lock_class == unsafe)))
1168  return unsafe;
1169  return NULL;
1170 }
1171 
1172 PFS_instr_class *find_idle_class(uint index)
1173 {
1174  if (index == 1)
1175  return & global_idle_class;
1176  return NULL;
1177 }
1178 
1179 PFS_instr_class *sanitize_idle_class(PFS_instr_class *unsafe)
1180 {
1181  if (likely(& global_idle_class == unsafe))
1182  return unsafe;
1183  return NULL;
1184 }
1185 
1186 static void set_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
1187 {
1188  int len;
1189  KEY *key_info= share->key_info;
1190  PFS_table_key *pfs_key= pfs->m_keys;
1191  PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
1192  pfs->m_key_count= share->keys;
1193 
1194  for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
1195  {
1196  len= strlen(key_info->name);
1197  memcpy(pfs_key->m_name, key_info->name, len);
1198  pfs_key->m_name_length= len;
1199  }
1200 
1201  pfs_key_last= pfs->m_keys + MAX_INDEXES;
1202  for ( ; pfs_key < pfs_key_last; pfs_key++)
1203  pfs_key->m_name_length= 0;
1204 }
1205 
1206 static int compare_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
1207 {
1208  uint len;
1209  KEY *key_info= share->key_info;
1210  PFS_table_key *pfs_key= pfs->m_keys;
1211  PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
1212 
1213  if (pfs->m_key_count != share->keys)
1214  return 1;
1215 
1216  for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
1217  {
1218  len= strlen(key_info->name);
1219  if (len != pfs_key->m_name_length)
1220  return 1;
1221 
1222  if (memcmp(pfs_key->m_name, key_info->name, len) != 0)
1223  return 1;
1224  }
1225 
1226  return 0;
1227 }
1228 
1237  bool temporary,
1238  const TABLE_SHARE *share)
1239 {
1240  /* See comments in register_mutex_class */
1241  PFS_table_share_key key;
1242 
1243  LF_PINS *pins= get_table_share_hash_pins(thread);
1244  if (unlikely(pins == NULL))
1245  {
1246  table_share_lost++;
1247  return NULL;
1248  }
1249 
1250  const char *schema_name= share->db.str;
1251  uint schema_name_length= share->db.length;
1252  const char *table_name= share->table_name.str;
1253  uint table_name_length= share->table_name.length;
1254 
1255  set_table_share_key(&key, temporary,
1256  schema_name, schema_name_length,
1257  table_name, table_name_length);
1258 
1260  uint retry_count= 0;
1261  const uint retry_max= 3;
1262  bool enabled= true;
1263  bool timed= true;
1264  static uint PFS_ALIGNED table_share_monotonic_index= 0;
1265  uint index;
1266  uint attempts= 0;
1267  PFS_table_share *pfs;
1268 
1269 search:
1270  entry= reinterpret_cast<PFS_table_share**>
1271  (lf_hash_search(&table_share_hash, pins,
1272  key.m_hash_key, key.m_key_length));
1273  if (entry && (entry != MY_ERRPTR))
1274  {
1275  pfs= *entry;
1276  pfs->inc_refcount() ;
1277  if (compare_keys(pfs, share) != 0)
1278  {
1279  set_keys(pfs, share);
1280  /* FIXME: aggregate to table_share sink ? */
1281  pfs->m_table_stat.fast_reset();
1282  }
1283  lf_hash_search_unpin(pins);
1284  return pfs;
1285  }
1286 
1287  lf_hash_search_unpin(pins);
1288 
1289  if (retry_count == 0)
1290  {
1291  lookup_setup_object(thread,
1292  OBJECT_TYPE_TABLE,
1293  schema_name, schema_name_length,
1294  table_name, table_name_length,
1295  &enabled, &timed);
1296  /*
1297  Even when enabled is false, a record is added in the dictionary:
1298  - It makes enabling a table already in the table cache possible,
1299  - It improves performances for the next time a TABLE_SHARE is reloaded
1300  in the table cache.
1301  */
1302  }
1303 
1304  while (++attempts <= table_share_max)
1305  {
1306  /* See create_mutex() */
1307  index= PFS_atomic::add_u32(& table_share_monotonic_index, 1) % table_share_max;
1308  pfs= table_share_array + index;
1309 
1310  if (pfs->m_lock.is_free())
1311  {
1312  if (pfs->m_lock.free_to_dirty())
1313  {
1314  pfs->m_key= key;
1315  pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
1316  pfs->m_schema_name_length= schema_name_length;
1317  pfs->m_table_name= &pfs->m_key.m_hash_key[schema_name_length + 2];
1318  pfs->m_table_name_length= table_name_length;
1319  pfs->m_enabled= enabled;
1320  pfs->m_timed= timed;
1321  pfs->init_refcount();
1322  pfs->m_table_stat.fast_reset();
1323  set_keys(pfs, share);
1324 
1325  int res;
1326  res= lf_hash_insert(&table_share_hash, pins, &pfs);
1327  if (likely(res == 0))
1328  {
1329  pfs->m_lock.dirty_to_allocated();
1330  return pfs;
1331  }
1332 
1333  pfs->m_lock.dirty_to_free();
1334 
1335  if (res > 0)
1336  {
1337  /* Duplicate insert by another thread */
1338  if (++retry_count > retry_max)
1339  {
1340  /* Avoid infinite loops */
1341  table_share_lost++;
1342  return NULL;
1343  }
1344  goto search;
1345  }
1346 
1347  /* OOM in lf_hash_insert */
1348  table_share_lost++;
1349  return NULL;
1350  }
1351  }
1352  }
1353 
1354  table_share_lost++;
1355  return NULL;
1356 }
1357 
1358 void PFS_table_share::aggregate_io(void)
1359 {
1360  uint safe_key_count= sanitize_index_count(m_key_count);
1361  PFS_table_io_stat *from_stat;
1362  PFS_table_io_stat *from_stat_last;
1363  PFS_table_io_stat sum_io;
1364 
1365  /* Aggregate stats for each index, if any */
1366  from_stat= & m_table_stat.m_index_stat[0];
1367  from_stat_last= from_stat + safe_key_count;
1368  for ( ; from_stat < from_stat_last ; from_stat++)
1369  sum_io.aggregate(from_stat);
1370 
1371  /* Aggregate stats for the table */
1372  sum_io.aggregate(& m_table_stat.m_index_stat[MAX_INDEXES]);
1373 
1374  /* Add this table stats to the global sink. */
1375  global_table_io_stat.aggregate(& sum_io);
1376  m_table_stat.fast_reset_io();
1377 }
1378 
1379 void PFS_table_share::aggregate_lock(void)
1380 {
1382  m_table_stat.fast_reset_lock();
1383 }
1384 
1386 {
1387  DBUG_ASSERT(pfs->get_refcount() > 0);
1388  pfs->dec_refcount();
1389 }
1390 
1401  bool temporary,
1402  const char *schema_name, uint schema_name_length,
1403  const char *table_name, uint table_name_length)
1404 {
1405  PFS_table_share_key key;
1406  LF_PINS* pins= get_table_share_hash_pins(thread);
1407  if (unlikely(pins == NULL))
1408  return;
1409  set_table_share_key(&key, temporary, schema_name, schema_name_length,
1410  table_name, table_name_length);
1412  entry= reinterpret_cast<PFS_table_share**>
1413  (lf_hash_search(&table_share_hash, pins,
1414  key.m_hash_key, key.m_key_length));
1415  if (entry && (entry != MY_ERRPTR))
1416  {
1417  PFS_table_share *pfs= *entry;
1418  lf_hash_delete(&table_share_hash, pins,
1419  pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
1420  pfs->m_lock.allocated_to_free();
1421  }
1422 
1423  lf_hash_search_unpin(pins);
1424 }
1425 
1432 {
1433  SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe);
1434 }
1435 
1438 {
1441  global_idle_stat.reset();
1442  global_table_io_stat.reset();
1443  global_table_lock_stat.reset();
1444 }
1445 
1448 {
1449  PFS_file_class *pfs= file_class_array;
1450  PFS_file_class *pfs_last= file_class_array + file_class_max;
1451 
1452  for ( ; pfs < pfs_last; pfs++)
1453  pfs->m_file_stat.m_io_stat.reset();
1454 }
1455 
1458 {
1459  PFS_socket_class *pfs= socket_class_array;
1460  PFS_socket_class *pfs_last= socket_class_array + socket_class_max;
1461 
1462  for ( ; pfs < pfs_last; pfs++)
1463  pfs->m_socket_stat.m_io_stat.reset();
1464 }
1465 
1467 {
1469  PFS_table_share *pfs_last= table_share_array + table_share_max;
1470 
1471  for ( ; pfs < pfs_last; pfs++)
1472  {
1473  if (pfs->m_lock.is_populated())
1474  pfs->refresh_setup_object_flags(thread);
1475  }
1476 }
1477