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 memcpy(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