MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pfs_instr.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 <string.h>
23 
24 #include "my_sys.h"
25 #include "pfs.h"
26 #include "pfs_stat.h"
27 #include "pfs_instr.h"
28 #include "pfs_host.h"
29 #include "pfs_user.h"
30 #include "pfs_account.h"
31 #include "pfs_global.h"
32 #include "pfs_instr_class.h"
33 
40 ulong mutex_max;
44 ulong mutex_lost;
46 ulong rwlock_max;
52 ulong cond_max;
54 bool cond_full;
56 ulong cond_lost;
58 ulong thread_max;
64 ulong file_max;
66 bool file_full;
68 ulong file_lost;
79 ulong table_max;
83 ulong table_lost;
85 ulong socket_max;
98 ulong locker_lost= 0;
100 ulong statement_lost= 0;
105 
112 
119 
126 
133 
141 
148 
155 
162 
163 PFS_stage_stat *global_instr_class_stages_array= NULL;
164 PFS_statement_stat *global_instr_class_statements_array= NULL;
165 
166 static volatile uint64 thread_internal_id_counter= 0;
167 
168 static uint thread_instr_class_waits_sizing;
169 static uint thread_instr_class_stages_sizing;
170 static uint thread_instr_class_statements_sizing;
171 static PFS_single_stat *thread_instr_class_waits_array= NULL;
172 static PFS_stage_stat *thread_instr_class_stages_array= NULL;
173 static PFS_statement_stat *thread_instr_class_statements_array= NULL;
174 
175 static PFS_events_waits *thread_waits_history_array= NULL;
176 static PFS_events_stages *thread_stages_history_array= NULL;
177 static PFS_events_statements *thread_statements_history_array= NULL;
178 static PFS_events_statements *thread_statements_stack_array= NULL;
179 static char *thread_session_connect_attrs_array= NULL;
180 
184 static bool filename_hash_inited= false;
185 
192 {
193  uint thread_waits_history_sizing;
194  uint thread_stages_history_sizing;
195  uint thread_statements_history_sizing;
196  uint thread_statements_stack_sizing;
197  uint thread_session_connect_attrs_sizing;
198  uint index;
199 
200  /* Make sure init_event_name_sizing is called */
201  DBUG_ASSERT(wait_class_max != 0);
202 
203  mutex_max= param->m_mutex_sizing;
204  mutex_full= false;
205  mutex_lost= 0;
206  rwlock_max= param->m_rwlock_sizing;
207  rwlock_full= false;
208  rwlock_lost= 0;
209  cond_max= param->m_cond_sizing;
210  cond_full= false;
211  cond_lost= 0;
212  file_max= param->m_file_sizing;
213  file_full= false;
214  file_lost= 0;
216  file_handle_full= false;
217  file_handle_lost= 0;
218  table_max= param->m_table_sizing;
219  table_full= false;
220  table_lost= 0;
221  thread_max= param->m_thread_sizing;
222  thread_full= false;
223  thread_lost= 0;
224  socket_max= param->m_socket_sizing;
225  socket_full= false;
226  socket_lost= 0;
227 
229  thread_waits_history_sizing= param->m_thread_sizing
231 
232  thread_instr_class_waits_sizing= param->m_thread_sizing
233  * wait_class_max;
234 
236  thread_stages_history_sizing= param->m_thread_sizing
238 
240  thread_statements_history_sizing= param->m_thread_sizing
242 
244  thread_statements_stack_sizing= param->m_thread_sizing * statement_stack_max;
245 
246  thread_instr_class_stages_sizing= param->m_thread_sizing
247  * param->m_stage_class_sizing;
248 
249  thread_instr_class_statements_sizing= param->m_thread_sizing
250  * param->m_statement_class_sizing;
251 
253  thread_session_connect_attrs_sizing= param->m_thread_sizing
256 
257  mutex_array= NULL;
258  rwlock_array= NULL;
259  cond_array= NULL;
260  file_array= NULL;
261  file_handle_array= NULL;
262  table_array= NULL;
263  socket_array= NULL;
264  thread_array= NULL;
265  thread_waits_history_array= NULL;
266  thread_stages_history_array= NULL;
267  thread_statements_history_array= NULL;
268  thread_statements_stack_array= NULL;
269  thread_instr_class_waits_array= NULL;
270  thread_instr_class_stages_array= NULL;
271  thread_instr_class_statements_array= NULL;
272  thread_internal_id_counter= 0;
273 
274  if (mutex_max > 0)
275  {
276  mutex_array= PFS_MALLOC_ARRAY(mutex_max, PFS_mutex, MYF(MY_ZEROFILL));
277  if (unlikely(mutex_array == NULL))
278  return 1;
279  }
280 
281  if (rwlock_max > 0)
282  {
283  rwlock_array= PFS_MALLOC_ARRAY(rwlock_max, PFS_rwlock, MYF(MY_ZEROFILL));
284  if (unlikely(rwlock_array == NULL))
285  return 1;
286  }
287 
288  if (cond_max > 0)
289  {
290  cond_array= PFS_MALLOC_ARRAY(cond_max, PFS_cond, MYF(MY_ZEROFILL));
291  if (unlikely(cond_array == NULL))
292  return 1;
293  }
294 
295  if (file_max > 0)
296  {
297  file_array= PFS_MALLOC_ARRAY(file_max, PFS_file, MYF(MY_ZEROFILL));
298  if (unlikely(file_array == NULL))
299  return 1;
300  }
301 
302  if (file_handle_max > 0)
303  {
304  file_handle_array= PFS_MALLOC_ARRAY(file_handle_max, PFS_file*, MYF(MY_ZEROFILL));
305  if (unlikely(file_handle_array == NULL))
306  return 1;
307  }
308 
309  if (table_max > 0)
310  {
311  table_array= PFS_MALLOC_ARRAY(table_max, PFS_table, MYF(MY_ZEROFILL));
312  if (unlikely(table_array == NULL))
313  return 1;
314  }
315 
316  if (socket_max > 0)
317  {
318  socket_array= PFS_MALLOC_ARRAY(socket_max, PFS_socket, MYF(MY_ZEROFILL));
319  if (unlikely(socket_array == NULL))
320  return 1;
321  }
322 
323  if (thread_max > 0)
324  {
325  thread_array= PFS_MALLOC_ARRAY(thread_max, PFS_thread, MYF(MY_ZEROFILL));
326  if (unlikely(thread_array == NULL))
327  return 1;
328  }
329 
330  if (thread_waits_history_sizing > 0)
331  {
332  thread_waits_history_array=
333  PFS_MALLOC_ARRAY(thread_waits_history_sizing, PFS_events_waits,
334  MYF(MY_ZEROFILL));
335  if (unlikely(thread_waits_history_array == NULL))
336  return 1;
337  }
338 
339  if (thread_instr_class_waits_sizing > 0)
340  {
341  thread_instr_class_waits_array=
342  PFS_MALLOC_ARRAY(thread_instr_class_waits_sizing,
343  PFS_single_stat, MYF(MY_ZEROFILL));
344  if (unlikely(thread_instr_class_waits_array == NULL))
345  return 1;
346 
347  for (index= 0; index < thread_instr_class_waits_sizing; index++)
348  thread_instr_class_waits_array[index].reset();
349  }
350 
351  if (thread_stages_history_sizing > 0)
352  {
353  thread_stages_history_array=
354  PFS_MALLOC_ARRAY(thread_stages_history_sizing, PFS_events_stages,
355  MYF(MY_ZEROFILL));
356  if (unlikely(thread_stages_history_array == NULL))
357  return 1;
358  }
359 
360  if (thread_instr_class_stages_sizing > 0)
361  {
362  thread_instr_class_stages_array=
363  PFS_MALLOC_ARRAY(thread_instr_class_stages_sizing,
364  PFS_stage_stat, MYF(MY_ZEROFILL));
365  if (unlikely(thread_instr_class_stages_array == NULL))
366  return 1;
367 
368  for (index= 0; index < thread_instr_class_stages_sizing; index++)
369  thread_instr_class_stages_array[index].reset();
370  }
371 
372  if (thread_statements_history_sizing > 0)
373  {
374  thread_statements_history_array=
375  PFS_MALLOC_ARRAY(thread_statements_history_sizing, PFS_events_statements,
376  MYF(MY_ZEROFILL));
377  if (unlikely(thread_statements_history_array == NULL))
378  return 1;
379  }
380 
381  if (thread_statements_stack_sizing > 0)
382  {
383  thread_statements_stack_array=
384  PFS_MALLOC_ARRAY(thread_statements_stack_sizing, PFS_events_statements,
385  MYF(MY_ZEROFILL));
386  if (unlikely(thread_statements_stack_array == NULL))
387  return 1;
388  }
389 
390  if (thread_instr_class_statements_sizing > 0)
391  {
392  thread_instr_class_statements_array=
393  PFS_MALLOC_ARRAY(thread_instr_class_statements_sizing,
394  PFS_statement_stat, MYF(MY_ZEROFILL));
395  if (unlikely(thread_instr_class_statements_array == NULL))
396  return 1;
397 
398  for (index= 0; index < thread_instr_class_statements_sizing; index++)
399  thread_instr_class_statements_array[index].reset();
400  }
401 
402  if (thread_session_connect_attrs_sizing > 0)
403  {
404  thread_session_connect_attrs_array=
405  (char *)pfs_malloc(thread_session_connect_attrs_sizing, MYF(MY_ZEROFILL));
406  if (unlikely(thread_session_connect_attrs_array == NULL))
407  return 1;
408  }
409 
410  for (index= 0; index < thread_max; index++)
411  {
412  thread_array[index].m_waits_history=
413  &thread_waits_history_array[index * events_waits_history_per_thread];
414  thread_array[index].m_instr_class_waits_stats=
415  &thread_instr_class_waits_array[index * wait_class_max];
416  thread_array[index].m_stages_history=
417  &thread_stages_history_array[index * events_stages_history_per_thread];
418  thread_array[index].m_instr_class_stages_stats=
419  &thread_instr_class_stages_array[index * stage_class_max];
420  thread_array[index].m_statements_history=
421  &thread_statements_history_array[index * events_statements_history_per_thread];
422  thread_array[index].m_statement_stack=
423  &thread_statements_stack_array[index * statement_stack_max];
425  &thread_instr_class_statements_array[index * statement_class_max];
426  thread_array[index].m_session_connect_attrs=
427  &thread_session_connect_attrs_array[index * session_connect_attrs_size_per_thread];
428  }
429 
430  if (stage_class_max > 0)
431  {
432  global_instr_class_stages_array=
434  PFS_stage_stat, MYF(MY_ZEROFILL));
435  if (unlikely(global_instr_class_stages_array == NULL))
436  return 1;
437 
438  for (index= 0; index < stage_class_max; index++)
439  global_instr_class_stages_array[index].reset();
440  }
441 
442  if (statement_class_max > 0)
443  {
444  global_instr_class_statements_array=
446  PFS_statement_stat, MYF(MY_ZEROFILL));
447  if (unlikely(global_instr_class_statements_array == NULL))
448  return 1;
449 
450  for (index= 0; index < statement_class_max; index++)
451  global_instr_class_statements_array[index].reset();
452  }
453 
454  return 0;
455 }
456 
459 {
460  pfs_free(mutex_array);
461  mutex_array= NULL;
462  mutex_max= 0;
463  pfs_free(rwlock_array);
464  rwlock_array= NULL;
465  rwlock_max= 0;
466  pfs_free(cond_array);
467  cond_array= NULL;
468  cond_max= 0;
469  pfs_free(file_array);
470  file_array= NULL;
471  file_max= 0;
472  pfs_free(file_handle_array);
473  file_handle_array= NULL;
474  file_handle_max= 0;
475  pfs_free(table_array);
476  table_array= NULL;
477  table_max= 0;
478  pfs_free(socket_array);
479  socket_array= NULL;
480  socket_max= 0;
481  pfs_free(thread_array);
482  thread_array= NULL;
483  thread_max= 0;
484  pfs_free(thread_waits_history_array);
485  thread_waits_history_array= NULL;
486  pfs_free(thread_stages_history_array);
487  thread_stages_history_array= NULL;
488  pfs_free(thread_statements_history_array);
489  thread_statements_history_array= NULL;
490  pfs_free(thread_statements_stack_array);
491  thread_statements_stack_array= NULL;
492  pfs_free(thread_instr_class_waits_array);
493  thread_instr_class_waits_array= NULL;
494  pfs_free(global_instr_class_stages_array);
495  global_instr_class_stages_array= NULL;
496  pfs_free(global_instr_class_statements_array);
497  global_instr_class_statements_array= NULL;
498  pfs_free(thread_session_connect_attrs_array);
499  thread_session_connect_attrs_array=NULL;
500 }
501 
502 C_MODE_START
504 static uchar *filename_hash_get_key(const uchar *entry, size_t *length,
505  my_bool)
506 {
507  const PFS_file * const *typed_entry;
508  const PFS_file *file;
509  const void *result;
510  typed_entry= reinterpret_cast<const PFS_file* const *> (entry);
511  DBUG_ASSERT(typed_entry != NULL);
512  file= *typed_entry;
513  DBUG_ASSERT(file != NULL);
514  *length= file->m_filename_length;
515  result= file->m_filename;
516  return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
517 }
518 C_MODE_END
519 
524 int init_file_hash(void)
525 {
526  if ((! filename_hash_inited) && (file_max > 0))
527  {
528  lf_hash_init(&filename_hash, sizeof(PFS_file*), LF_HASH_UNIQUE,
529  0, 0, filename_hash_get_key, &my_charset_bin);
530  filename_hash.size= file_max;
531  filename_hash_inited= true;
532  }
533  return 0;
534 }
535 
538 {
539  if (filename_hash_inited)
540  {
541  lf_hash_destroy(&filename_hash);
542  filename_hash_inited= false;
543  }
544 }
545 
546 void PFS_scan::init(uint random, uint max_size)
547 {
548  m_pass= 0;
549 
550  if (max_size == 0)
551  {
552  /* Degenerated case, no buffer */
553  m_pass_max= 0;
554  return;
555  }
556 
557  DBUG_ASSERT(random < max_size);
558 
559  if (PFS_MAX_ALLOC_RETRY < max_size)
560  {
561  /*
562  The buffer is big compared to PFS_MAX_ALLOC_RETRY,
563  scan it only partially.
564  */
565  if (random + PFS_MAX_ALLOC_RETRY < max_size)
566  {
567  /*
568  Pass 1: [random, random + PFS_MAX_ALLOC_RETRY - 1]
569  Pass 2: not used.
570  */
571  m_pass_max= 1;
572  m_first[0]= random;
573  m_last[0]= random + PFS_MAX_ALLOC_RETRY;
574  m_first[1]= 0;
575  m_last[1]= 0;
576  }
577  else
578  {
579  /*
580  Pass 1: [random, max_size - 1]
581  Pass 2: [0, ...]
582  The combined length of pass 1 and 2 is PFS_MAX_ALLOC_RETRY.
583  */
584  m_pass_max= 2;
585  m_first[0]= random;
586  m_last[0]= max_size;
587  m_first[1]= 0;
588  m_last[1]= PFS_MAX_ALLOC_RETRY - (max_size - random);
589  }
590  }
591  else
592  {
593  /*
594  The buffer is small compared to PFS_MAX_ALLOC_RETRY,
595  scan it in full in two passes.
596  Pass 1: [random, max_size - 1]
597  Pass 2: [0, random - 1]
598  */
599  m_pass_max= 2;
600  m_first[0]= random;
601  m_last[0]= max_size;
602  m_first[1]= 0;
603  m_last[1]= random;
604  }
605 
606  DBUG_ASSERT(m_first[0] < max_size);
607  DBUG_ASSERT(m_first[1] < max_size);
608  DBUG_ASSERT(m_last[1] <= max_size);
609  DBUG_ASSERT(m_last[1] <= max_size);
610  /* The combined length of all passes should not exceed PFS_MAX_ALLOC_RETRY. */
611  DBUG_ASSERT((m_last[0] - m_first[0]) +
612  (m_last[1] - m_first[1]) <= PFS_MAX_ALLOC_RETRY);
613 }
614 
621 PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity)
622 {
623  static uint PFS_ALIGNED mutex_monotonic_index= 0;
624  uint index;
625  uint attempts= 0;
626  PFS_mutex *pfs;
627 
628  if (mutex_full)
629  {
630  /*
631  This is a safety plug.
632  When mutex_array is severely undersized,
633  do not spin to death for each call.
634  */
635  mutex_lost++;
636  return NULL;
637  }
638 
639  while (++attempts <= mutex_max)
640  {
641  /*
642  Problem:
643  Multiple threads running concurrently may need to create a new
644  instrumented mutex, and find an empty slot in mutex_array[].
645  With N1 threads running on a N2 core hardware:
646  - up to N2 hardware threads can run concurrently,
647  causing contention if looking at the same array[i] slot.
648  - up to N1 threads can run almost concurrently (with thread scheduling),
649  scanning maybe overlapping regions in the [0-mutex_max] array.
650 
651  Solution:
652  Instead of letting different threads compete on the same array[i] entry,
653  this code forces all threads to cooperate with the monotonic_index.
654  Only one thread will be allowed to test a given array[i] slot.
655  All threads do scan from the same region, starting at monotonic_index.
656  Serializing on monotonic_index ensures that when a slot is found occupied
657  in a given loop by a given thread, other threads will not attempt this
658  slot.
659  */
660  index= PFS_atomic::add_u32(& mutex_monotonic_index, 1) % mutex_max;
661  pfs= mutex_array + index;
662 
663  if (pfs->m_lock.is_free())
664  {
665  if (pfs->m_lock.free_to_dirty())
666  {
667  pfs->m_identity= identity;
668  pfs->m_class= klass;
670  pfs->m_timed= klass->m_timed;
671  pfs->m_mutex_stat.reset();
672  pfs->m_owner= NULL;
673  pfs->m_last_locked= 0;
674  pfs->m_lock.dirty_to_allocated();
675  if (klass->is_singleton())
676  klass->m_singleton= pfs;
677  return pfs;
678  }
679  }
680  }
681 
682  mutex_lost++;
683  /*
684  Race condition.
685  The mutex_array might not be full if a concurrent thread
686  called destroy_mutex() during the scan, leaving one
687  empty slot we did not find.
688  However, 99.999 percent full tables or 100 percent full tables
689  are treated the same here, we declare the array overloaded.
690  */
691  mutex_full= true;
692  return NULL;
693 }
694 
700 {
701  DBUG_ASSERT(pfs != NULL);
702  PFS_mutex_class *klass= pfs->m_class;
703  /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */
704  klass->m_mutex_stat.aggregate(& pfs->m_mutex_stat);
705  pfs->m_mutex_stat.reset();
706  if (klass->is_singleton())
707  klass->m_singleton= NULL;
708  pfs->m_lock.allocated_to_free();
709  mutex_full= false;
710 }
711 
718 PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity)
719 {
720  static uint PFS_ALIGNED rwlock_monotonic_index= 0;
721  uint index;
722  uint attempts= 0;
723  PFS_rwlock *pfs;
724 
725  if (rwlock_full)
726  {
727  rwlock_lost++;
728  return NULL;
729  }
730 
731  while (++attempts <= rwlock_max)
732  {
733  /* See create_mutex() */
734  index= PFS_atomic::add_u32(& rwlock_monotonic_index, 1) % rwlock_max;
735  pfs= rwlock_array + index;
736 
737  if (pfs->m_lock.is_free())
738  {
739  if (pfs->m_lock.free_to_dirty())
740  {
741  pfs->m_identity= identity;
742  pfs->m_class= klass;
744  pfs->m_timed= klass->m_timed;
745  pfs->m_rwlock_stat.reset();
746  pfs->m_lock.dirty_to_allocated();
747  pfs->m_writer= NULL;
748  pfs->m_readers= 0;
749  pfs->m_last_written= 0;
750  pfs->m_last_read= 0;
751  if (klass->is_singleton())
752  klass->m_singleton= pfs;
753  return pfs;
754  }
755  }
756  }
757 
758  rwlock_lost++;
759  rwlock_full= true;
760  return NULL;
761 }
762 
768 {
769  DBUG_ASSERT(pfs != NULL);
770  PFS_rwlock_class *klass= pfs->m_class;
771  /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */
772  klass->m_rwlock_stat.aggregate(& pfs->m_rwlock_stat);
773  pfs->m_rwlock_stat.reset();
774  if (klass->is_singleton())
775  klass->m_singleton= NULL;
776  pfs->m_lock.allocated_to_free();
777  rwlock_full= false;
778 }
779 
786 PFS_cond* create_cond(PFS_cond_class *klass, const void *identity)
787 {
788  static uint PFS_ALIGNED cond_monotonic_index= 0;
789  uint index;
790  uint attempts= 0;
791  PFS_cond *pfs;
792 
793  if (cond_full)
794  {
795  cond_lost++;
796  return NULL;
797  }
798 
799  while (++attempts <= cond_max)
800  {
801  /* See create_mutex() */
802  index= PFS_atomic::add_u32(& cond_monotonic_index, 1) % cond_max;
803  pfs= cond_array + index;
804 
805  if (pfs->m_lock.is_free())
806  {
807  if (pfs->m_lock.free_to_dirty())
808  {
809  pfs->m_identity= identity;
810  pfs->m_class= klass;
812  pfs->m_timed= klass->m_timed;
813  pfs->m_cond_stat.m_signal_count= 0;
815  pfs->m_wait_stat.reset();
816  pfs->m_lock.dirty_to_allocated();
817  if (klass->is_singleton())
818  klass->m_singleton= pfs;
819  return pfs;
820  }
821  }
822  }
823 
824  cond_lost++;
825  cond_full= true;
826  return NULL;
827 }
828 
834 {
835  DBUG_ASSERT(pfs != NULL);
836  PFS_cond_class *klass= pfs->m_class;
837  /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */
838  klass->m_cond_stat.aggregate(& pfs->m_cond_stat);
839  pfs->m_wait_stat.reset();
840  if (klass->is_singleton())
841  klass->m_singleton= NULL;
842  pfs->m_lock.allocated_to_free();
843  cond_full= false;
844 }
845 
846 PFS_thread* PFS_thread::get_current_thread()
847 {
848  PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
849  return pfs;
850 }
851 
853 {
856 
857  if ((m_session_connect_attrs != NULL) &&
859  {
860  /* Do not keep user data */
862  }
863 }
864 
874 PFS_thread* create_thread(PFS_thread_class *klass, const void *identity,
875  ulonglong processlist_id)
876 {
877  static uint PFS_ALIGNED thread_monotonic_index= 0;
878  uint index;
879  uint attempts= 0;
880  PFS_thread *pfs;
881 
882  if (thread_full)
883  {
884  thread_lost++;
885  return NULL;
886  }
887 
888  while (++attempts <= thread_max)
889  {
890  /* See create_mutex() */
891  index= PFS_atomic::add_u32(& thread_monotonic_index, 1) % thread_max;
892  pfs= thread_array + index;
893 
894  if (pfs->m_lock.is_free())
895  {
896  if (pfs->m_lock.free_to_dirty())
897  {
899  PFS_atomic::add_u64(&thread_internal_id_counter, 1);
901  pfs->m_processlist_id= processlist_id;
902  pfs->m_event_id= 1;
903  pfs->m_stmt_lock.set_allocated();
905  pfs->m_enabled= true;
906  pfs->m_class= klass;
908  pfs->m_waits_history_full= false;
909  pfs->m_waits_history_index= 0;
910  pfs->m_stages_history_full= false;
911  pfs->m_stages_history_index= 0;
912  pfs->m_statements_history_full= false;
914 
915  pfs->reset_stats();
917 
918  pfs->m_filename_hash_pins= NULL;
919  pfs->m_table_share_hash_pins= NULL;
920  pfs->m_setup_actor_hash_pins= NULL;
921  pfs->m_setup_object_hash_pins= NULL;
922  pfs->m_user_hash_pins= NULL;
923  pfs->m_account_hash_pins= NULL;
924  pfs->m_host_hash_pins= NULL;
925  pfs->m_digest_hash_pins= NULL;
926 
927  pfs->m_username_length= 0;
928  pfs->m_hostname_length= 0;
929  pfs->m_dbname_length= 0;
930  pfs->m_command= 0;
931  pfs->m_start_time= 0;
932  pfs->m_stage= 0;
933  pfs->m_processlist_info[0]= '\0';
935 
936  pfs->m_host= NULL;
937  pfs->m_user= NULL;
938  pfs->m_account= NULL;
939  set_thread_account(pfs);
940 
941  PFS_events_waits *child_wait;
942  for (index= 0; index < WAIT_STACK_SIZE; index++)
943  {
944  child_wait= & pfs->m_events_waits_stack[index];
945  child_wait->m_thread_internal_id= pfs->m_thread_internal_id;
946  child_wait->m_event_id= 0;
947  child_wait->m_end_event_id= 0;
948  child_wait->m_event_type= EVENT_TYPE_STATEMENT;
949  child_wait->m_wait_class= NO_WAIT_CLASS;
950  }
951 
952  PFS_events_stages *child_stage= & pfs->m_stage_current;
953  child_stage->m_thread_internal_id= pfs->m_thread_internal_id;
954  child_stage->m_event_id= 0;
955  child_stage->m_end_event_id= 0;
956  child_stage->m_event_type= EVENT_TYPE_STATEMENT;
957  child_stage->m_class= NULL;
958  child_stage->m_timer_start= 0;
959  child_stage->m_timer_end= 0;
960  child_stage->m_source_file= NULL;
961  child_stage->m_source_line= 0;
962 
963  PFS_events_statements *child_statement;
964  for (index= 0; index < statement_stack_max; index++)
965  {
966  child_statement= & pfs->m_statement_stack[index];
967  child_statement->m_thread_internal_id= pfs->m_thread_internal_id;
968  child_statement->m_event_id= 0;
969  child_statement->m_end_event_id= 0;
970  child_statement->m_event_type= EVENT_TYPE_STATEMENT;
971  child_statement->m_class= NULL;
972  child_statement->m_timer_start= 0;
973  child_statement->m_timer_end= 0;
974  child_statement->m_lock_time= 0;
975  child_statement->m_source_file= NULL;
976  child_statement->m_source_line= 0;
977  child_statement->m_current_schema_name_length= 0;
978  child_statement->m_sqltext_length= 0;
979 
980  child_statement->m_message_text[0]= '\0';
981  child_statement->m_sql_errno= 0;
982  child_statement->m_sqlstate[0]= '\0';
983  child_statement->m_error_count= 0;
984  child_statement->m_warning_count= 0;
985  child_statement->m_rows_affected= 0;
986 
987  child_statement->m_rows_sent= 0;
988  child_statement->m_rows_examined= 0;
989  child_statement->m_created_tmp_disk_tables= 0;
990  child_statement->m_created_tmp_tables= 0;
991  child_statement->m_select_full_join= 0;
992  child_statement->m_select_full_range_join= 0;
993  child_statement->m_select_range= 0;
994  child_statement->m_select_range_check= 0;
995  child_statement->m_select_scan= 0;
996  child_statement->m_sort_merge_passes= 0;
997  child_statement->m_sort_range= 0;
998  child_statement->m_sort_rows= 0;
999  child_statement->m_sort_scan= 0;
1000  child_statement->m_no_index_used= 0;
1001  child_statement->m_no_good_index_used= 0;
1002  }
1003  pfs->m_events_statements_count= 0;
1004 
1005  pfs->m_lock.dirty_to_allocated();
1006  return pfs;
1007  }
1008  }
1009  }
1010 
1011  thread_lost++;
1012  thread_full= true;
1013  return NULL;
1014 }
1015 
1016 PFS_mutex *sanitize_mutex(PFS_mutex *unsafe)
1017 {
1018  SANITIZE_ARRAY_BODY(PFS_mutex, mutex_array, mutex_max, unsafe);
1019 }
1020 
1021 PFS_rwlock *sanitize_rwlock(PFS_rwlock *unsafe)
1022 {
1023  SANITIZE_ARRAY_BODY(PFS_rwlock, rwlock_array, rwlock_max, unsafe);
1024 }
1025 
1026 PFS_cond *sanitize_cond(PFS_cond *unsafe)
1027 {
1028  SANITIZE_ARRAY_BODY(PFS_cond, cond_array, cond_max, unsafe);
1029 }
1030 
1041 {
1042  SANITIZE_ARRAY_BODY(PFS_thread, thread_array, thread_max, unsafe);
1043 }
1044 
1045 PFS_file *sanitize_file(PFS_file *unsafe)
1046 {
1047  SANITIZE_ARRAY_BODY(PFS_file, file_array, file_max, unsafe);
1048 }
1049 
1050 PFS_socket *sanitize_socket(PFS_socket *unsafe)
1051 {
1052  SANITIZE_ARRAY_BODY(PFS_socket, socket_array, socket_max, unsafe);
1053 }
1054 
1060 {
1061  DBUG_ASSERT(pfs != NULL);
1063  if (pfs->m_account != NULL)
1064  {
1065  pfs->m_account->release();
1066  pfs->m_account= NULL;
1067  DBUG_ASSERT(pfs->m_user == NULL);
1068  DBUG_ASSERT(pfs->m_host == NULL);
1069  }
1070  else
1071  {
1072  if (pfs->m_user != NULL)
1073  {
1074  pfs->m_user->release();
1075  pfs->m_user= NULL;
1076  }
1077  if (pfs->m_host != NULL)
1078  {
1079  pfs->m_host->release();
1080  pfs->m_host= NULL;
1081  }
1082  }
1083  if (pfs->m_filename_hash_pins)
1084  {
1085  lf_hash_put_pins(pfs->m_filename_hash_pins);
1086  pfs->m_filename_hash_pins= NULL;
1087  }
1088  if (pfs->m_table_share_hash_pins)
1089  {
1090  lf_hash_put_pins(pfs->m_table_share_hash_pins);
1091  pfs->m_table_share_hash_pins= NULL;
1092  }
1093  if (pfs->m_setup_actor_hash_pins)
1094  {
1095  lf_hash_put_pins(pfs->m_setup_actor_hash_pins);
1096  pfs->m_setup_actor_hash_pins= NULL;
1097  }
1098  if (pfs->m_setup_object_hash_pins)
1099  {
1100  lf_hash_put_pins(pfs->m_setup_object_hash_pins);
1101  pfs->m_setup_object_hash_pins= NULL;
1102  }
1103  if (pfs->m_user_hash_pins)
1104  {
1105  lf_hash_put_pins(pfs->m_user_hash_pins);
1106  pfs->m_user_hash_pins= NULL;
1107  }
1108  if (pfs->m_account_hash_pins)
1109  {
1110  lf_hash_put_pins(pfs->m_account_hash_pins);
1111  pfs->m_account_hash_pins= NULL;
1112  }
1113  if (pfs->m_host_hash_pins)
1114  {
1115  lf_hash_put_pins(pfs->m_host_hash_pins);
1116  pfs->m_host_hash_pins= NULL;
1117  }
1118  if (pfs->m_digest_hash_pins)
1119  {
1120  lf_hash_put_pins(pfs->m_digest_hash_pins);
1121  pfs->m_digest_hash_pins= NULL;
1122  }
1123  pfs->m_lock.allocated_to_free();
1124  thread_full= false;
1125 }
1126 
1133 {
1134  if (unlikely(thread->m_filename_hash_pins == NULL))
1135  {
1136  if (! filename_hash_inited)
1137  return NULL;
1138  thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash);
1139  }
1140  return thread->m_filename_hash_pins;
1141 }
1142 
1152 PFS_file*
1154  const char *filename, uint len, bool create)
1155 {
1156  PFS_file *pfs;
1157 
1158  DBUG_ASSERT(klass != NULL || ! create);
1159 
1160  LF_PINS *pins= get_filename_hash_pins(thread);
1161  if (unlikely(pins == NULL))
1162  {
1163  file_lost++;
1164  return NULL;
1165  }
1166 
1167  char safe_buffer[FN_REFLEN];
1168  const char *safe_filename;
1169 
1170  if (len >= FN_REFLEN)
1171  {
1172  /*
1173  The instrumented code uses file names that exceeds FN_REFLEN.
1174  This could be legal for instrumentation on non mysys APIs,
1175  so we support it.
1176  Truncate the file name so that:
1177  - it fits into pfs->m_filename
1178  - it is safe to use mysys apis to normalize the file name.
1179  */
1180  memcpy(safe_buffer, filename, FN_REFLEN - 1);
1181  safe_buffer[FN_REFLEN - 1]= 0;
1182  safe_filename= safe_buffer;
1183  }
1184  else
1185  safe_filename= filename;
1186 
1187  /*
1188  Normalize the file name to avoid duplicates when using aliases:
1189  - absolute or relative paths
1190  - symbolic links
1191  Names are resolved as follows:
1192  - /real/path/to/real_file ==> same
1193  - /path/with/link/to/real_file ==> /real/path/to/real_file
1194  - real_file ==> /real/path/to/real_file
1195  - ./real_file ==> /real/path/to/real_file
1196  - /real/path/to/sym_link ==> same
1197  - /path/with/link/to/sym_link ==> /real/path/to/sym_link
1198  - sym_link ==> /real/path/to/sym_link
1199  - ./sym_link ==> /real/path/to/sym_link
1200  When the last component of a file is a symbolic link,
1201  the last component is *not* resolved, so that all file io
1202  operations on a link (create, read, write, delete) are counted
1203  against the link itself, not the target file.
1204  Resolving the name would lead to create counted against the link,
1205  and read/write/delete counted against the target, leading to
1206  incoherent results and instrumentation leaks.
1207  Also note that, when creating files, this name resolution
1208  works properly for files that do not exist (yet) on the file system.
1209  */
1210  char buffer[FN_REFLEN];
1211  char dirbuffer[FN_REFLEN];
1212  size_t dirlen;
1213  const char *normalized_filename;
1214  int normalized_length;
1215 
1216  dirlen= dirname_length(safe_filename);
1217  if (dirlen == 0)
1218  {
1219  dirbuffer[0]= FN_CURLIB;
1220  dirbuffer[1]= FN_LIBCHAR;
1221  dirbuffer[2]= '\0';
1222  }
1223  else
1224  {
1225  memcpy(dirbuffer, safe_filename, dirlen);
1226  dirbuffer[dirlen]= '\0';
1227  }
1228 
1229  if (my_realpath(buffer, dirbuffer, MYF(0)) != 0)
1230  {
1231  file_lost++;
1232  return NULL;
1233  }
1234 
1235  /* Append the unresolved file name to the resolved path */
1236  char *ptr= buffer + strlen(buffer);
1237  char *buf_end= &buffer[sizeof(buffer)-1];
1238  if ((buf_end > ptr) && (*(ptr-1) != FN_LIBCHAR))
1239  *ptr++= FN_LIBCHAR;
1240  if (buf_end > ptr)
1241  strncpy(ptr, safe_filename + dirlen, buf_end - ptr);
1242  *buf_end= '\0';
1243 
1244  normalized_filename= buffer;
1245  normalized_length= strlen(normalized_filename);
1246 
1247  PFS_file **entry;
1248  uint retry_count= 0;
1249  const uint retry_max= 3;
1250  static uint PFS_ALIGNED file_monotonic_index= 0;
1251  uint index;
1252  uint attempts= 0;
1253 
1254 search:
1255 
1256  entry= reinterpret_cast<PFS_file**>
1257  (lf_hash_search(&filename_hash, pins,
1258  normalized_filename, normalized_length));
1259  if (entry && (entry != MY_ERRPTR))
1260  {
1261  pfs= *entry;
1262  pfs->m_file_stat.m_open_count++;
1263  lf_hash_search_unpin(pins);
1264  return pfs;
1265  }
1266 
1267  lf_hash_search_unpin(pins);
1268 
1269  if (! create)
1270  {
1271  /* No lost counter, just looking for the file existence. */
1272  return NULL;
1273  }
1274 
1275  if (file_full)
1276  {
1277  file_lost++;
1278  return NULL;
1279  }
1280 
1281  while (++attempts <= file_max)
1282  {
1283  /* See create_mutex() */
1284  index= PFS_atomic::add_u32(& file_monotonic_index, 1) % file_max;
1285  pfs= file_array + index;
1286 
1287  if (pfs->m_lock.is_free())
1288  {
1289  if (pfs->m_lock.free_to_dirty())
1290  {
1291  pfs->m_class= klass;
1293  pfs->m_timed= klass->m_timed;
1294  strncpy(pfs->m_filename, normalized_filename, normalized_length);
1295  pfs->m_filename[normalized_length]= '\0';
1296  pfs->m_filename_length= normalized_length;
1297  pfs->m_file_stat.m_open_count= 1;
1298  pfs->m_file_stat.m_io_stat.reset();
1299  pfs->m_identity= (const void *)pfs;
1300 
1301  int res;
1302  res= lf_hash_insert(&filename_hash, thread->m_filename_hash_pins,
1303  &pfs);
1304  if (likely(res == 0))
1305  {
1306  pfs->m_lock.dirty_to_allocated();
1307  if (klass->is_singleton())
1308  klass->m_singleton= pfs;
1309  return pfs;
1310  }
1311 
1312  pfs->m_lock.dirty_to_free();
1313 
1314  if (res > 0)
1315  {
1316  /* Duplicate insert by another thread */
1317  if (++retry_count > retry_max)
1318  {
1319  /* Avoid infinite loops */
1320  file_lost++;
1321  return NULL;
1322  }
1323  goto search;
1324  }
1325 
1326  /* OOM in lf_hash_insert */
1327  file_lost++;
1328  return NULL;
1329  }
1330  }
1331  }
1332 
1333  file_lost++;
1334  file_full= true;
1335  return NULL;
1336 }
1337 
1343 {
1344  DBUG_ASSERT(pfs != NULL);
1345  pfs->m_file_stat.m_open_count--;
1346 }
1347 
1353 void destroy_file(PFS_thread *thread, PFS_file *pfs)
1354 {
1355  DBUG_ASSERT(thread != NULL);
1356  DBUG_ASSERT(pfs != NULL);
1357  PFS_file_class *klass= pfs->m_class;
1358 
1359  /* Aggregate to FILE_SUMMARY_BY_EVENT_NAME */
1360  klass->m_file_stat.aggregate(& pfs->m_file_stat);
1361  pfs->m_file_stat.reset();
1362 
1363  if (klass->is_singleton())
1364  klass->m_singleton= NULL;
1365 
1366  LF_PINS *pins= get_filename_hash_pins(thread);
1367  DBUG_ASSERT(pins != NULL);
1368 
1369  lf_hash_delete(&filename_hash, pins,
1370  pfs->m_filename, pfs->m_filename_length);
1371  if (klass->is_singleton())
1372  klass->m_singleton= NULL;
1373  pfs->m_lock.allocated_to_free();
1374  file_full= false;
1375 }
1376 
1385  const void *identity)
1386 {
1387  static uint PFS_ALIGNED table_monotonic_index= 0;
1388  uint index;
1389  uint attempts= 0;
1390  PFS_table *pfs;
1391 
1392  if (table_full)
1393  {
1394  table_lost++;
1395  return NULL;
1396  }
1397 
1398  while (++attempts <= table_max)
1399  {
1400  /* See create_mutex() */
1401  index= PFS_atomic::add_u32(& table_monotonic_index, 1) % table_max;
1402  pfs= table_array + index;
1403 
1404  if (pfs->m_lock.is_free())
1405  {
1406  if (pfs->m_lock.free_to_dirty())
1407  {
1408  pfs->m_identity= identity;
1409  pfs->m_share= share;
1410  pfs->m_io_enabled= share->m_enabled &&
1413  pfs->m_lock_enabled= share->m_enabled &&
1416  pfs->m_has_io_stats= false;
1417  pfs->m_has_lock_stats= false;
1418  share->inc_refcount();
1419  pfs->m_table_stat.fast_reset();
1420  pfs->m_thread_owner= opening_thread;
1421  pfs->m_lock.dirty_to_allocated();
1422  return pfs;
1423  }
1424  }
1425  }
1426 
1427  table_lost++;
1428  table_full= true;
1429  return NULL;
1430 }
1431 
1433 {
1434  /*
1435  This thread could be a TRUNCATE on an aggregated summary table,
1436  and not own the table handle.
1437  */
1439  if (safe_share != NULL)
1440  {
1442  {
1443  safe_aggregate(& m_table_stat, safe_share);
1444  m_has_io_stats= false;
1445  m_has_lock_stats= false;
1446  }
1447  else if (m_has_io_stats)
1448  {
1449  safe_aggregate_io(& m_table_stat, safe_share);
1450  m_has_io_stats= false;
1451  }
1452  else if (m_has_lock_stats)
1453  {
1454  safe_aggregate_lock(& m_table_stat, safe_share);
1455  m_has_lock_stats= false;
1456  }
1457  }
1458 }
1459 
1461 {
1463  if (safe_share != NULL && m_has_io_stats)
1464  {
1465  safe_aggregate_io(& m_table_stat, safe_share);
1466  m_has_io_stats= false;
1467  }
1468 }
1469 
1471 {
1473  if (safe_share != NULL && m_has_lock_stats)
1474  {
1475  safe_aggregate_lock(& m_table_stat, safe_share);
1476  m_has_lock_stats= false;
1477  }
1478 }
1479 
1480 void PFS_table::safe_aggregate(PFS_table_stat *table_stat,
1481  PFS_table_share *table_share)
1482 {
1483  DBUG_ASSERT(table_stat != NULL);
1484  DBUG_ASSERT(table_share != NULL);
1485 
1486  uint key_count= sanitize_index_count(table_share->m_key_count);
1487 
1488  /* Aggregate to TABLE_IO_SUMMARY, TABLE_LOCK_SUMMARY */
1489  table_share->m_table_stat.aggregate(table_stat, key_count);
1490  table_stat->fast_reset();
1491 }
1492 
1493 void PFS_table::safe_aggregate_io(PFS_table_stat *table_stat,
1494  PFS_table_share *table_share)
1495 {
1496  DBUG_ASSERT(table_stat != NULL);
1497  DBUG_ASSERT(table_share != NULL);
1498 
1499  uint key_count= sanitize_index_count(table_share->m_key_count);
1500 
1501  /* Aggregate to TABLE_IO_SUMMARY */
1502  table_share->m_table_stat.aggregate_io(table_stat, key_count);
1503  table_stat->fast_reset_io();
1504 }
1505 
1506 void PFS_table::safe_aggregate_lock(PFS_table_stat *table_stat,
1507  PFS_table_share *table_share)
1508 {
1509  DBUG_ASSERT(table_stat != NULL);
1510  DBUG_ASSERT(table_share != NULL);
1511 
1512  /* Aggregate to TABLE_LOCK_SUMMARY */
1513  table_share->m_table_stat.aggregate_lock(table_stat);
1514  table_stat->fast_reset_lock();
1515 }
1516 
1522 {
1523  DBUG_ASSERT(pfs != NULL);
1524  pfs->m_share->dec_refcount();
1525  pfs->m_lock.allocated_to_free();
1526  table_full= false;
1527 }
1528 
1535 PFS_socket* create_socket(PFS_socket_class *klass, const my_socket *fd,
1536  const struct sockaddr *addr, socklen_t addr_len)
1537 {
1538  static uint PFS_ALIGNED socket_monotonic_index= 0;
1539  uint index;
1540  uint attempts= 0;
1541  PFS_socket *pfs;
1542 
1543  if (socket_full)
1544  {
1545  socket_lost++;
1546  return NULL;
1547  }
1548 
1549  uint fd_used= 0;
1550  uint addr_len_used= addr_len;
1551 
1552  if (fd != NULL)
1553  fd_used= *fd;
1554 
1555  if (addr_len_used > sizeof(sockaddr_storage))
1556  addr_len_used= sizeof(sockaddr_storage);
1557 
1558  while (++attempts <= socket_max)
1559  {
1560  index= PFS_atomic::add_u32(& socket_monotonic_index, 1) % socket_max;
1561  pfs= socket_array + index;
1562 
1563  if (pfs->m_lock.is_free())
1564  {
1565  if (pfs->m_lock.free_to_dirty())
1566  {
1567  pfs->m_fd= fd_used;
1568  /* There is no socket object, so we use the instrumentation. */
1569  pfs->m_identity= pfs;
1570  pfs->m_class= klass;
1572  pfs->m_timed= klass->m_timed;
1573  pfs->m_idle= false;
1574  pfs->m_socket_stat.reset();
1575  pfs->m_thread_owner= NULL;
1576 
1577  pfs->m_addr_len= addr_len_used;
1578  if ((addr != NULL) && (addr_len_used > 0))
1579  {
1580  pfs->m_addr_len= addr_len_used;
1581  memcpy(&pfs->m_sock_addr, addr, addr_len_used);
1582  }
1583  else
1584  {
1585  pfs->m_addr_len= 0;
1586  }
1587 
1588  pfs->m_lock.dirty_to_allocated();
1589 
1590  if (klass->is_singleton())
1591  klass->m_singleton= pfs;
1592  return pfs;
1593  }
1594  }
1595  }
1596 
1597  socket_lost++;
1598  socket_full= true;
1599  return NULL;
1600 }
1601 
1607 {
1608  DBUG_ASSERT(pfs != NULL);
1609  PFS_socket_class *klass= pfs->m_class;
1610 
1611  /* Aggregate to SOCKET_SUMMARY_BY_EVENT_NAME */
1612  klass->m_socket_stat.m_io_stat.aggregate(&pfs->m_socket_stat.m_io_stat);
1613 
1614  if (klass->is_singleton())
1615  klass->m_singleton= NULL;
1616 
1617  /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME */
1618  PFS_thread *thread= pfs->m_thread_owner;
1619  if (thread != NULL)
1620  {
1621  PFS_single_stat *event_name_array;
1622  event_name_array= thread->m_instr_class_waits_stats;
1623  uint index= pfs->m_class->m_event_name_index;
1624 
1625  /* Combine stats for all operations */
1626  PFS_single_stat stat;
1627  pfs->m_socket_stat.m_io_stat.sum_waits(&stat);
1628  event_name_array[index].aggregate(&stat);
1629  }
1630 
1631  pfs->m_socket_stat.reset();
1632  pfs->m_thread_owner= NULL;
1633  pfs->m_fd= 0;
1634  pfs->m_addr_len= 0;
1635  pfs->m_lock.allocated_to_free();
1636  socket_full= false;
1637 }
1638 
1639 static void reset_mutex_waits_by_instance(void)
1640 {
1641  PFS_mutex *pfs= mutex_array;
1642  PFS_mutex *pfs_last= mutex_array + mutex_max;
1643 
1644  for ( ; pfs < pfs_last; pfs++)
1645  pfs->m_mutex_stat.reset();
1646 }
1647 
1648 static void reset_rwlock_waits_by_instance(void)
1649 {
1650  PFS_rwlock *pfs= rwlock_array;
1651  PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
1652 
1653  for ( ; pfs < pfs_last; pfs++)
1654  pfs->m_rwlock_stat.reset();
1655 }
1656 
1657 static void reset_cond_waits_by_instance(void)
1658 {
1659  PFS_cond *pfs= cond_array;
1660  PFS_cond *pfs_last= cond_array + cond_max;
1661 
1662  for ( ; pfs < pfs_last; pfs++)
1663  pfs->m_cond_stat.reset();
1664 }
1665 
1666 static void reset_file_waits_by_instance(void)
1667 {
1668  PFS_file *pfs= file_array;
1669  PFS_file *pfs_last= file_array + file_max;
1670 
1671  for ( ; pfs < pfs_last; pfs++)
1672  pfs->m_file_stat.reset();
1673 }
1674 
1675 static void reset_socket_waits_by_instance(void)
1676 {
1677  PFS_socket *pfs= socket_array;
1678  PFS_socket *pfs_last= socket_array + socket_max;
1679 
1680  for ( ; pfs < pfs_last; pfs++)
1681  pfs->m_socket_stat.reset();
1682 }
1683 
1686 {
1687  reset_mutex_waits_by_instance();
1688  reset_rwlock_waits_by_instance();
1689  reset_cond_waits_by_instance();
1690  reset_file_waits_by_instance();
1691  reset_socket_waits_by_instance();
1692 }
1693 
1696 {
1697  PFS_file *pfs= file_array;
1698  PFS_file *pfs_last= file_array + file_max;
1699 
1700  for ( ; pfs < pfs_last; pfs++)
1701  pfs->m_file_stat.m_io_stat.reset();
1702 }
1703 
1706 {
1707  PFS_socket *pfs= socket_array;
1708  PFS_socket *pfs_last= socket_array + socket_max;
1709 
1710  for ( ; pfs < pfs_last; pfs++)
1711  pfs->m_socket_stat.m_io_stat.reset();
1712 }
1713 
1714 void aggregate_all_event_names(PFS_single_stat *from_array,
1715  PFS_single_stat *to_array)
1716 {
1717  PFS_single_stat *from;
1718  PFS_single_stat *from_last;
1720 
1721  from= from_array;
1722  from_last= from_array + wait_class_max;
1723  to= to_array;
1724 
1725  for ( ; from < from_last ; from++, to++)
1726  {
1727  if (from->m_count > 0)
1728  {
1729  to->aggregate(from);
1730  from->reset();
1731  }
1732  }
1733 }
1734 
1735 void aggregate_all_event_names(PFS_single_stat *from_array,
1736  PFS_single_stat *to_array_1,
1737  PFS_single_stat *to_array_2)
1738 {
1739  PFS_single_stat *from;
1740  PFS_single_stat *from_last;
1741  PFS_single_stat *to_1;
1742  PFS_single_stat *to_2;
1743 
1744  from= from_array;
1745  from_last= from_array + wait_class_max;
1746  to_1= to_array_1;
1747  to_2= to_array_2;
1748 
1749  for ( ; from < from_last ; from++, to_1++, to_2++)
1750  {
1751  if (from->m_count > 0)
1752  {
1753  to_1->aggregate(from);
1754  to_2->aggregate(from);
1755  from->reset();
1756  }
1757  }
1758 }
1759 
1760 void aggregate_all_stages(PFS_stage_stat *from_array,
1761  PFS_stage_stat *to_array)
1762 {
1763  PFS_stage_stat *from;
1764  PFS_stage_stat *from_last;
1765  PFS_stage_stat *to;
1766 
1767  from= from_array;
1768  from_last= from_array + stage_class_max;
1769  to= to_array;
1770 
1771  for ( ; from < from_last ; from++, to++)
1772  {
1773  if (from->m_timer1_stat.m_count > 0)
1774  {
1775  to->aggregate(from);
1776  from->reset();
1777  }
1778  }
1779 }
1780 
1781 void aggregate_all_stages(PFS_stage_stat *from_array,
1782  PFS_stage_stat *to_array_1,
1783  PFS_stage_stat *to_array_2)
1784 {
1785  PFS_stage_stat *from;
1786  PFS_stage_stat *from_last;
1787  PFS_stage_stat *to_1;
1788  PFS_stage_stat *to_2;
1789 
1790  from= from_array;
1791  from_last= from_array + stage_class_max;
1792  to_1= to_array_1;
1793  to_2= to_array_2;
1794 
1795  for ( ; from < from_last ; from++, to_1++, to_2++)
1796  {
1797  if (from->m_timer1_stat.m_count > 0)
1798  {
1799  to_1->aggregate(from);
1800  to_2->aggregate(from);
1801  from->reset();
1802  }
1803  }
1804 }
1805 
1806 void aggregate_all_statements(PFS_statement_stat *from_array,
1807  PFS_statement_stat *to_array)
1808 {
1809  PFS_statement_stat *from;
1810  PFS_statement_stat *from_last;
1812 
1813  from= from_array;
1814  from_last= from_array + statement_class_max;
1815  to= to_array;
1816 
1817  for ( ; from < from_last ; from++, to++)
1818  {
1819  if (from->m_timer1_stat.m_count > 0)
1820  {
1821  to->aggregate(from);
1822  from->reset();
1823  }
1824  }
1825 }
1826 
1827 void aggregate_all_statements(PFS_statement_stat *from_array,
1828  PFS_statement_stat *to_array_1,
1829  PFS_statement_stat *to_array_2)
1830 {
1831  PFS_statement_stat *from;
1832  PFS_statement_stat *from_last;
1833  PFS_statement_stat *to_1;
1834  PFS_statement_stat *to_2;
1835 
1836  from= from_array;
1837  from_last= from_array + statement_class_max;
1838  to_1= to_array_1;
1839  to_2= to_array_2;
1840 
1841  for ( ; from < from_last ; from++, to_1++, to_2++)
1842  {
1843  if (from->m_timer1_stat.m_count > 0)
1844  {
1845  to_1->aggregate(from);
1846  to_2->aggregate(from);
1847  from->reset();
1848  }
1849  }
1850 }
1851 
1852 void aggregate_thread_stats(PFS_thread *thread,
1853  PFS_account *safe_account,
1854  PFS_user *safe_user,
1855  PFS_host *safe_host)
1856 {
1857  if (likely(safe_account != NULL))
1858  {
1859  safe_account->m_disconnected_count++;
1860  return;
1861  }
1862 
1863  if (safe_user != NULL)
1864  safe_user->m_disconnected_count++;
1865 
1866  if (safe_host != NULL)
1867  safe_host->m_disconnected_count++;
1868 
1869  /* There is no global table for connections statistics. */
1870  return;
1871 }
1872 
1873 void aggregate_thread(PFS_thread *thread,
1874  PFS_account *safe_account,
1875  PFS_user *safe_user,
1876  PFS_host *safe_host)
1877 {
1878  aggregate_thread_waits(thread, safe_account, safe_user, safe_host);
1879  aggregate_thread_stages(thread, safe_account, safe_user, safe_host);
1880  aggregate_thread_statements(thread, safe_account, safe_user, safe_host);
1881  aggregate_thread_stats(thread, safe_account, safe_user, safe_host);
1882 }
1883 
1884 void aggregate_thread_waits(PFS_thread *thread,
1885  PFS_account *safe_account,
1886  PFS_user *safe_user,
1887  PFS_host *safe_host)
1888 {
1889  if (likely(safe_account != NULL))
1890  {
1891  /*
1892  Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
1893  to EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
1894  */
1895  aggregate_all_event_names(thread->m_instr_class_waits_stats,
1896  safe_account->m_instr_class_waits_stats);
1897 
1898  return;
1899  }
1900 
1901  if ((safe_user != NULL) && (safe_host != NULL))
1902  {
1903  /*
1904  Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
1905  - EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME
1906  - EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME
1907  in parallel.
1908  */
1909  aggregate_all_event_names(thread->m_instr_class_waits_stats,
1910  safe_user->m_instr_class_waits_stats,
1911  safe_host->m_instr_class_waits_stats);
1912  return;
1913  }
1914 
1915  if (safe_user != NULL)
1916  {
1917  /*
1918  Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
1919  to EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME, directly.
1920  */
1921  aggregate_all_event_names(thread->m_instr_class_waits_stats,
1922  safe_user->m_instr_class_waits_stats);
1923  return;
1924  }
1925 
1926  if (safe_host != NULL)
1927  {
1928  /*
1929  Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
1930  to EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
1931  */
1932  aggregate_all_event_names(thread->m_instr_class_waits_stats,
1933  safe_host->m_instr_class_waits_stats);
1934  return;
1935  }
1936 
1937  /* Orphan thread, clean the waits stats. */
1938  thread->reset_waits_stats();
1939 }
1940 
1941 void aggregate_thread_stages(PFS_thread *thread,
1942  PFS_account *safe_account,
1943  PFS_user *safe_user,
1944  PFS_host *safe_host)
1945 {
1946  if (likely(safe_account != NULL))
1947  {
1948  /*
1949  Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME
1950  to EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
1951  */
1952  aggregate_all_stages(thread->m_instr_class_stages_stats,
1953  safe_account->m_instr_class_stages_stats);
1954 
1955  return;
1956  }
1957 
1958  if ((safe_user != NULL) && (safe_host != NULL))
1959  {
1960  /*
1961  Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
1962  - EVENTS_STAGES_SUMMARY_BY_USER_BY_EVENT_NAME
1963  - EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME
1964  in parallel.
1965  */
1966  aggregate_all_stages(thread->m_instr_class_stages_stats,
1967  safe_user->m_instr_class_stages_stats,
1968  safe_host->m_instr_class_stages_stats);
1969  return;
1970  }
1971 
1972  if (safe_user != NULL)
1973  {
1974  /*
1975  Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
1976  - EVENTS_STAGES_SUMMARY_BY_USER_BY_EVENT_NAME
1977  - EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
1978  in parallel.
1979  */
1980  aggregate_all_stages(thread->m_instr_class_stages_stats,
1981  safe_user->m_instr_class_stages_stats,
1982  global_instr_class_stages_array);
1983  return;
1984  }
1985 
1986  if (safe_host != NULL)
1987  {
1988  /*
1989  Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME
1990  to EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
1991  */
1992  aggregate_all_stages(thread->m_instr_class_stages_stats,
1993  safe_host->m_instr_class_stages_stats);
1994  return;
1995  }
1996 
1997  /*
1998  Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME
1999  to EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME.
2000  */
2001  aggregate_all_stages(thread->m_instr_class_stages_stats,
2002  global_instr_class_stages_array);
2003 }
2004 
2005 void aggregate_thread_statements(PFS_thread *thread,
2006  PFS_account *safe_account,
2007  PFS_user *safe_user,
2008  PFS_host *safe_host)
2009 {
2010  if (likely(safe_account != NULL))
2011  {
2012  /*
2013  Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME
2014  to EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
2015  */
2016  aggregate_all_statements(thread->m_instr_class_statements_stats,
2017  safe_account->m_instr_class_statements_stats);
2018 
2019  return;
2020  }
2021 
2022  if ((safe_user != NULL) && (safe_host != NULL))
2023  {
2024  /*
2025  Aggregate EVENTS_STATEMENT_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
2026  - EVENTS_STATEMENT_SUMMARY_BY_USER_BY_EVENT_NAME
2027  - EVENTS_STATEMENT_SUMMARY_BY_HOST_BY_EVENT_NAME
2028  in parallel.
2029  */
2030  aggregate_all_statements(thread->m_instr_class_statements_stats,
2031  safe_user->m_instr_class_statements_stats,
2032  safe_host->m_instr_class_statements_stats);
2033  return;
2034  }
2035 
2036  if (safe_user != NULL)
2037  {
2038  /*
2039  Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
2040  - EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME
2041  - EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
2042  in parallel.
2043  */
2044  aggregate_all_statements(thread->m_instr_class_statements_stats,
2045  safe_user->m_instr_class_statements_stats,
2046  global_instr_class_statements_array);
2047  return;
2048  }
2049 
2050  if (safe_host != NULL)
2051  {
2052  /*
2053  Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME
2054  to EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
2055  */
2056  aggregate_all_statements(thread->m_instr_class_statements_stats,
2057  safe_host->m_instr_class_statements_stats);
2058  return;
2059  }
2060 
2061  /*
2062  Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME
2063  to EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME.
2064  */
2065  aggregate_all_statements(thread->m_instr_class_statements_stats,
2066  global_instr_class_statements_array);
2067 }
2068 
2069 void clear_thread_account(PFS_thread *thread)
2070 {
2071  if (thread->m_account != NULL)
2072  {
2073  thread->m_account->release();
2074  thread->m_account= NULL;
2075  }
2076 
2077  if (thread->m_user != NULL)
2078  {
2079  thread->m_user->release();
2080  thread->m_user= NULL;
2081  }
2082 
2083  if (thread->m_host != NULL)
2084  {
2085  thread->m_host->release();
2086  thread->m_host= NULL;
2087  }
2088 }
2089 
2090 void set_thread_account(PFS_thread *thread)
2091 {
2092  DBUG_ASSERT(thread->m_account == NULL);
2093  DBUG_ASSERT(thread->m_user == NULL);
2094  DBUG_ASSERT(thread->m_host == NULL);
2095 
2096  thread->m_account= find_or_create_account(thread,
2097  thread->m_username,
2098  thread->m_username_length,
2099  thread->m_hostname,
2100  thread->m_hostname_length);
2101 
2102  if ((thread->m_account == NULL) && (thread->m_username_length > 0))
2103  thread->m_user= find_or_create_user(thread,
2104  thread->m_username,
2105  thread->m_username_length);
2106 
2107  if ((thread->m_account == NULL) && (thread->m_hostname_length > 0))
2108  thread->m_host= find_or_create_host(thread,
2109  thread->m_hostname,
2110  thread->m_hostname_length);
2111 }
2112 
2114 {
2115  PFS_mutex *pfs= mutex_array;
2116  PFS_mutex *pfs_last= mutex_array + mutex_max;
2117  PFS_mutex_class *klass;
2118 
2119  for ( ; pfs < pfs_last; pfs++)
2120  {
2121  klass= sanitize_mutex_class(pfs->m_class);
2122  if (likely(klass != NULL))
2123  {
2125  pfs->m_timed= klass->m_timed;
2126  }
2127  else
2128  {
2129  pfs->m_enabled= false;
2130  pfs->m_timed= false;
2131  }
2132  }
2133 }
2134 
2136 {
2137  PFS_rwlock *pfs= rwlock_array;
2138  PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
2139  PFS_rwlock_class *klass;
2140 
2141  for ( ; pfs < pfs_last; pfs++)
2142  {
2143  klass= sanitize_rwlock_class(pfs->m_class);
2144  if (likely(klass != NULL))
2145  {
2147  pfs->m_timed= klass->m_timed;
2148  }
2149  else
2150  {
2151  pfs->m_enabled= false;
2152  pfs->m_timed= false;
2153  }
2154  }
2155 }
2156 
2158 {
2159  PFS_cond *pfs= cond_array;
2160  PFS_cond *pfs_last= cond_array + cond_max;
2161  PFS_cond_class *klass;
2162 
2163  for ( ; pfs < pfs_last; pfs++)
2164  {
2165  klass= sanitize_cond_class(pfs->m_class);
2166  if (likely(klass != NULL))
2167  {
2169  pfs->m_timed= klass->m_timed;
2170  }
2171  else
2172  {
2173  pfs->m_enabled= false;
2174  pfs->m_timed= false;
2175  }
2176  }
2177 }
2178 
2180 {
2181  PFS_file *pfs= file_array;
2182  PFS_file *pfs_last= file_array + file_max;
2183  PFS_file_class *klass;
2184 
2185  for ( ; pfs < pfs_last; pfs++)
2186  {
2187  klass= sanitize_file_class(pfs->m_class);
2188  if (likely(klass != NULL))
2189  {
2191  pfs->m_timed= klass->m_timed;
2192  }
2193  else
2194  {
2195  pfs->m_enabled= false;
2196  pfs->m_timed= false;
2197  }
2198  }
2199 }
2200 
2202 {
2203  PFS_table *pfs= table_array;
2204  PFS_table *pfs_last= table_array + table_max;
2205  PFS_table_share *share;
2206 
2207  for ( ; pfs < pfs_last; pfs++)
2208  {
2209  share= sanitize_table_share(pfs->m_share);
2210  if (likely(share != NULL))
2211  {
2212  pfs->m_io_enabled= share->m_enabled &&
2215  pfs->m_lock_enabled= share->m_enabled &&
2218  }
2219  else
2220  {
2221  pfs->m_io_enabled= false;
2222  pfs->m_io_timed= false;
2223  pfs->m_lock_enabled= false;
2224  pfs->m_lock_timed= false;
2225  }
2226  }
2227 }
2228 
2230 {
2231  PFS_socket *pfs= socket_array;
2232  PFS_socket *pfs_last= socket_array + socket_max;
2233  PFS_socket_class *klass;
2234 
2235  for ( ; pfs < pfs_last; pfs++)
2236  {
2237  klass= sanitize_socket_class(pfs->m_class);
2238  if (likely(klass != NULL))
2239  {
2241  pfs->m_timed= klass->m_timed;
2242  }
2243  else
2244  {
2245  pfs->m_enabled= false;
2246  pfs->m_timed= false;
2247  }
2248  }
2249 }
2250 
2252 {
2259  /* nothing for stages and statements (no instances) */
2260 }
2261