1 /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
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/table_events_waits.cc
25   Table EVENTS_WAITS_xxx (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "table_events_waits.h"
31 #include "pfs_global.h"
32 #include "pfs_instr_class.h"
33 #include "pfs_instr.h"
34 #include "pfs_events_waits.h"
35 #include "pfs_timer.h"
36 #include "m_string.h"
37 #include "pfs_buffer_container.h"
38 #include "field.h"
39 
40 THR_LOCK table_events_waits_current::m_table_lock;
41 
42 static const TABLE_FIELD_TYPE field_types[]=
43 {
44   {
45     { C_STRING_WITH_LEN("THREAD_ID") },
46     { C_STRING_WITH_LEN("bigint(20)") },
47     { NULL, 0}
48   },
49   {
50     { C_STRING_WITH_LEN("EVENT_ID") },
51     { C_STRING_WITH_LEN("bigint(20)") },
52     { NULL, 0}
53   },
54   {
55     { C_STRING_WITH_LEN("END_EVENT_ID") },
56     { C_STRING_WITH_LEN("bigint(20)") },
57     { NULL, 0}
58   },
59   {
60     { C_STRING_WITH_LEN("EVENT_NAME") },
61     { C_STRING_WITH_LEN("varchar(128)") },
62     { NULL, 0}
63   },
64   {
65     { C_STRING_WITH_LEN("SOURCE") },
66     { C_STRING_WITH_LEN("varchar(64)") },
67     { NULL, 0}
68   },
69   {
70     { C_STRING_WITH_LEN("TIMER_START") },
71     { C_STRING_WITH_LEN("bigint(20)") },
72     { NULL, 0}
73   },
74   {
75     { C_STRING_WITH_LEN("TIMER_END") },
76     { C_STRING_WITH_LEN("bigint(20)") },
77     { NULL, 0}
78   },
79   {
80     { C_STRING_WITH_LEN("TIMER_WAIT") },
81     { C_STRING_WITH_LEN("bigint(20)") },
82     { NULL, 0}
83   },
84   {
85     { C_STRING_WITH_LEN("SPINS") },
86     { C_STRING_WITH_LEN("int(10)") },
87     { NULL, 0}
88   },
89   {
90     { C_STRING_WITH_LEN("OBJECT_SCHEMA") },
91     { C_STRING_WITH_LEN("varchar(64)") },
92     { NULL, 0}
93   },
94   {
95     { C_STRING_WITH_LEN("OBJECT_NAME") },
96     { C_STRING_WITH_LEN("varchar(512)") },
97     { NULL, 0}
98   },
99   {
100     { C_STRING_WITH_LEN("INDEX_NAME") },
101     { C_STRING_WITH_LEN("varchar(64)") },
102     { NULL, 0}
103   },
104   {
105     { C_STRING_WITH_LEN("OBJECT_TYPE") },
106     { C_STRING_WITH_LEN("varchar(64)") },
107     { NULL, 0}
108   },
109   {
110     { C_STRING_WITH_LEN("OBJECT_INSTANCE_BEGIN") },
111     { C_STRING_WITH_LEN("bigint(20)") },
112     { NULL, 0}
113   },
114   {
115     { C_STRING_WITH_LEN("NESTING_EVENT_ID") },
116     { C_STRING_WITH_LEN("bigint(20)") },
117     { NULL, 0}
118   },
119   {
120     { C_STRING_WITH_LEN("NESTING_EVENT_TYPE") },
121     { C_STRING_WITH_LEN("enum(\'TRANSACTION\',\'STATEMENT\',\'STAGE\',\'WAIT\'") },
122     { NULL, 0}
123   },
124   {
125     { C_STRING_WITH_LEN("OPERATION") },
126     { C_STRING_WITH_LEN("varchar(32)") },
127     { NULL, 0}
128   },
129   {
130     { C_STRING_WITH_LEN("NUMBER_OF_BYTES") },
131     { C_STRING_WITH_LEN("bigint(20)") },
132     { NULL, 0}
133   },
134   {
135     { C_STRING_WITH_LEN("FLAGS") },
136     { C_STRING_WITH_LEN("int(10)") },
137     { NULL, 0}
138   }
139 };
140 
141 TABLE_FIELD_DEF
142 table_events_waits_current::m_field_def=
143 { 19, field_types };
144 
145 PFS_engine_table_share
146 table_events_waits_current::m_share=
147 {
148   { C_STRING_WITH_LEN("events_waits_current") },
149   &pfs_truncatable_acl,
150   table_events_waits_current::create,
151   NULL, /* write_row */
152   table_events_waits_current::delete_all_rows,
153   table_events_waits_current::get_row_count,
154   sizeof(pos_events_waits_current), /* ref length */
155   &m_table_lock,
156   &m_field_def,
157   false, /* checked */
158   false  /* perpetual */
159 };
160 
161 THR_LOCK table_events_waits_history::m_table_lock;
162 
163 PFS_engine_table_share
164 table_events_waits_history::m_share=
165 {
166   { C_STRING_WITH_LEN("events_waits_history") },
167   &pfs_truncatable_acl,
168   table_events_waits_history::create,
169   NULL, /* write_row */
170   table_events_waits_history::delete_all_rows,
171   table_events_waits_history::get_row_count,
172   sizeof(pos_events_waits_history), /* ref length */
173   &m_table_lock,
174   &table_events_waits_current::m_field_def,
175   false, /* checked */
176   false  /* perpetual */
177 };
178 
179 THR_LOCK table_events_waits_history_long::m_table_lock;
180 
181 PFS_engine_table_share
182 table_events_waits_history_long::m_share=
183 {
184   { C_STRING_WITH_LEN("events_waits_history_long") },
185   &pfs_truncatable_acl,
186   table_events_waits_history_long::create,
187   NULL, /* write_row */
188   table_events_waits_history_long::delete_all_rows,
189   table_events_waits_history_long::get_row_count,
190   sizeof(PFS_simple_index), /* ref length */
191   &m_table_lock,
192   &table_events_waits_current::m_field_def,
193   false, /* checked */
194   false  /* perpetual */
195 };
196 
table_events_waits_common(const PFS_engine_table_share * share,void * pos)197 table_events_waits_common::table_events_waits_common
198 (const PFS_engine_table_share *share, void *pos)
199   : PFS_engine_table(share, pos),
200   m_row_exists(false)
201 {}
202 
clear_object_columns()203 void table_events_waits_common::clear_object_columns()
204 {
205   m_row.m_object_type_length= 0;
206   m_row.m_object_schema_length= 0;
207   m_row.m_object_name_length= 0;
208   m_row.m_index_name_length= 0;
209 }
210 
make_table_object_columns(PFS_events_waits * wait)211 int table_events_waits_common::make_table_object_columns(PFS_events_waits *wait)
212 {
213   uint safe_index;
214   PFS_table_share *safe_table_share;
215 
216   safe_table_share= sanitize_table_share(wait->m_weak_table_share);
217   if (unlikely(safe_table_share == NULL))
218     return 1;
219 
220   if (wait->m_object_type == OBJECT_TYPE_TABLE)
221   {
222     m_row.m_object_type= "TABLE";
223     m_row.m_object_type_length= 5;
224   }
225   else
226   {
227     m_row.m_object_type= "TEMPORARY TABLE";
228     m_row.m_object_type_length= 15;
229   }
230 
231   if (safe_table_share->get_version() == wait->m_weak_version)
232   {
233     /* OBJECT SCHEMA */
234     m_row.m_object_schema_length= safe_table_share->m_schema_name_length;
235     if (unlikely((m_row.m_object_schema_length == 0) ||
236                  (m_row.m_object_schema_length > sizeof(m_row.m_object_schema))))
237       return 1;
238     memcpy(m_row.m_object_schema, safe_table_share->m_schema_name, m_row.m_object_schema_length);
239 
240     /* OBJECT NAME */
241     m_row.m_object_name_length= safe_table_share->m_table_name_length;
242     if (unlikely((m_row.m_object_name_length == 0) ||
243                  (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
244       return 1;
245     memcpy(m_row.m_object_name, safe_table_share->m_table_name, m_row.m_object_name_length);
246 
247     /* INDEX NAME */
248     safe_index= wait->m_index;
249     uint safe_key_count= sanitize_index_count(safe_table_share->m_key_count);
250     if (safe_index < safe_key_count)
251     {
252       PFS_table_share_index *index_stat;
253       index_stat= safe_table_share->find_index_stat(safe_index);
254 
255       if (index_stat != NULL)
256       {
257         m_row.m_index_name_length= index_stat->m_key.m_name_length;
258 
259         if (unlikely((m_row.m_index_name_length == 0) ||
260                      (m_row.m_index_name_length > sizeof(m_row.m_index_name))))
261           return 1;
262 
263         memcpy(m_row.m_index_name, index_stat->m_key.m_name, m_row.m_index_name_length);
264       }
265       else
266       {
267         m_row.m_index_name_length= 0;
268       }
269     }
270     else
271     {
272       m_row.m_index_name_length= 0;
273     }
274   }
275   else
276   {
277     m_row.m_object_schema_length= 0;
278     m_row.m_object_name_length= 0;
279     m_row.m_index_name_length= 0;
280   }
281 
282   m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
283   return 0;
284 }
285 
make_file_object_columns(PFS_events_waits * wait)286 int table_events_waits_common::make_file_object_columns(PFS_events_waits *wait)
287 {
288   PFS_file *safe_file;
289 
290   safe_file= sanitize_file(wait->m_weak_file);
291   if (unlikely(safe_file == NULL))
292     return 1;
293 
294   m_row.m_object_type= "FILE";
295   m_row.m_object_type_length= 4;
296   m_row.m_object_schema_length= 0;
297   m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
298 
299   if (safe_file->get_version() == wait->m_weak_version)
300   {
301     /* OBJECT NAME */
302     m_row.m_object_name_length= safe_file->m_filename_length;
303     if (unlikely((m_row.m_object_name_length == 0) ||
304                  (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
305       return 1;
306     memcpy(m_row.m_object_name, safe_file->m_filename, m_row.m_object_name_length);
307   }
308   else
309   {
310     m_row.m_object_name_length= 0;
311   }
312 
313   m_row.m_index_name_length= 0;
314 
315   return 0;
316 }
317 
make_socket_object_columns(PFS_events_waits * wait)318 int table_events_waits_common::make_socket_object_columns(PFS_events_waits *wait)
319 {
320   PFS_socket *safe_socket;
321 
322   safe_socket= sanitize_socket(wait->m_weak_socket);
323   if (unlikely(safe_socket == NULL))
324     return 1;
325 
326   m_row.m_object_type= "SOCKET";
327   m_row.m_object_type_length= 6;
328   m_row.m_object_schema_length= 0;
329   m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
330 
331   if (safe_socket->get_version() == wait->m_weak_version)
332   {
333     /* Convert port number to string, include delimiter in port name length */
334 
335     uint port;
336     char port_str[128];
337     char ip_str[INET6_ADDRSTRLEN+1];
338     uint ip_len= 0;
339     port_str[0]= ':';
340 
341     /* Get the IP address and port number */
342     ip_len= pfs_get_socket_address(ip_str, sizeof(ip_str), &port,
343                                    &safe_socket->m_sock_addr,
344                                    safe_socket->m_addr_len);
345 
346     /* Convert port number to a string (length includes ':') */
347     size_t port_len= int10_to_str(port, (port_str+1), 10) - port_str + 1;
348 
349     /* OBJECT NAME */
350     m_row.m_object_name_length= ip_len + port_len;
351 
352     if (unlikely((m_row.m_object_name_length == 0) ||
353                  (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
354       return 1;
355 
356     char *name= m_row.m_object_name;
357     memcpy(name, ip_str, ip_len);
358     memcpy(name + ip_len, port_str, port_len);
359   }
360   else
361   {
362     m_row.m_object_name_length= 0;
363   }
364 
365   m_row.m_index_name_length= 0;
366 
367   return 0;
368 }
369 
make_metadata_lock_object_columns(PFS_events_waits * wait)370 int table_events_waits_common::make_metadata_lock_object_columns(PFS_events_waits *wait)
371 {
372   PFS_metadata_lock *safe_metadata_lock;
373 
374   safe_metadata_lock= sanitize_metadata_lock(wait->m_weak_metadata_lock);
375   if (unlikely(safe_metadata_lock == NULL))
376     return 1;
377 
378   if (safe_metadata_lock->get_version() == wait->m_weak_version)
379   {
380     MDL_key *mdl= & safe_metadata_lock->m_mdl_key;
381 
382     switch(mdl->mdl_namespace())
383     {
384     case MDL_key::GLOBAL:
385       m_row.m_object_type= "GLOBAL";
386       m_row.m_object_type_length= 6;
387       m_row.m_object_schema_length= 0;
388       m_row.m_object_name_length= 0;
389       break;
390     case MDL_key::SCHEMA:
391       m_row.m_object_type= "SCHEMA";
392       m_row.m_object_type_length= 6;
393       m_row.m_object_schema_length= mdl->db_name_length();
394       m_row.m_object_name_length= 0;
395       break;
396     case MDL_key::TABLE:
397       m_row.m_object_type= "TABLE";
398       m_row.m_object_type_length= 5;
399       m_row.m_object_schema_length= mdl->db_name_length();
400       m_row.m_object_name_length= mdl->name_length();
401       break;
402     case MDL_key::FUNCTION:
403       m_row.m_object_type= "FUNCTION";
404       m_row.m_object_type_length= 8;
405       m_row.m_object_schema_length= mdl->db_name_length();
406       m_row.m_object_name_length= mdl->name_length();
407       break;
408     case MDL_key::PROCEDURE:
409       m_row.m_object_type= "PROCEDURE";
410       m_row.m_object_type_length= 9;
411       m_row.m_object_schema_length= mdl->db_name_length();
412       m_row.m_object_name_length= mdl->name_length();
413       break;
414     case MDL_key::TRIGGER:
415       m_row.m_object_type= "TRIGGER";
416       m_row.m_object_type_length= 7;
417       m_row.m_object_schema_length= mdl->db_name_length();
418       m_row.m_object_name_length= mdl->name_length();
419       break;
420     case MDL_key::EVENT:
421       m_row.m_object_type= "EVENT";
422       m_row.m_object_type_length= 5;
423       m_row.m_object_schema_length= mdl->db_name_length();
424       m_row.m_object_name_length= mdl->name_length();
425       break;
426     case MDL_key::COMMIT:
427       m_row.m_object_type= "COMMIT";
428       m_row.m_object_type_length= 6;
429       m_row.m_object_schema_length= 0;
430       m_row.m_object_name_length= 0;
431       break;
432     case MDL_key::USER_LEVEL_LOCK:
433       m_row.m_object_type= "USER LEVEL LOCK";
434       m_row.m_object_type_length= 15;
435       m_row.m_object_schema_length= 0;
436       m_row.m_object_name_length= mdl->name_length();
437       break;
438     case MDL_key::TABLESPACE:
439       m_row.m_object_type= "TABLESPACE";
440       m_row.m_object_type_length= 10;
441       m_row.m_object_schema_length= 0;
442       m_row.m_object_name_length= mdl->name_length();
443       break;
444     case MDL_key::LOCKING_SERVICE:
445       m_row.m_object_type= "LOCKING SERVICE";
446       m_row.m_object_type_length= 15;
447       m_row.m_object_schema_length= mdl->db_name_length();
448       m_row.m_object_name_length= mdl->name_length();
449       break;
450     case MDL_key::NAMESPACE_END:
451     default:
452       m_row.m_object_type_length= 0;
453       m_row.m_object_schema_length= 0;
454       m_row.m_object_name_length= 0;
455       break;
456     }
457 
458     if (m_row.m_object_schema_length > sizeof(m_row.m_object_schema))
459       return 1;
460     if (m_row.m_object_schema_length > 0)
461       memcpy(m_row.m_object_schema, mdl->db_name(), m_row.m_object_schema_length);
462 
463     if (m_row.m_object_name_length > sizeof(m_row.m_object_name))
464       return 1;
465     if (m_row.m_object_name_length > 0)
466       memcpy(m_row.m_object_name, mdl->name(), m_row.m_object_name_length);
467 
468     m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
469   }
470   else
471   {
472     m_row.m_object_type_length= 0;
473     m_row.m_object_schema_length= 0;
474     m_row.m_object_name_length= 0;
475     m_row.m_object_instance_addr= 0;
476   }
477 
478   /* INDEX NAME */
479   m_row.m_index_name_length= 0;
480 
481   return 0;
482 }
483 
484 /**
485   Build a row.
486   @param wait                       the wait the cursor is reading
487 */
make_row(PFS_events_waits * wait)488 void table_events_waits_common::make_row(PFS_events_waits *wait)
489 {
490   PFS_instr_class *safe_class;
491   enum_timer_name timer_name= wait_timer;
492   ulonglong timer_end;
493 
494   m_row_exists= false;
495 
496   /*
497     Design choice:
498     We could have used a pfs_lock in PFS_events_waits here,
499     to protect the reader from concurrent event generation,
500     but this leads to too many pfs_lock atomic operations
501     each time an event is recorded:
502     - 1 dirty() + 1 allocated() per event start, for EVENTS_WAITS_CURRENT
503     - 1 dirty() + 1 allocated() per event end, for EVENTS_WAITS_CURRENT
504     - 1 dirty() + 1 allocated() per copy to EVENTS_WAITS_HISTORY
505     - 1 dirty() + 1 allocated() per copy to EVENTS_WAITS_HISTORY_LONG
506     or 8 atomics per recorded event.
507     The problem is that we record a *lot* of events ...
508 
509     This code is prepared to accept *dirty* records,
510     and sanitizes all the data before returning a row.
511   */
512 
513   /*
514     PFS_events_waits::m_class needs to be sanitized,
515     for race conditions when this code:
516     - reads a new value in m_wait_class,
517     - reads an old value in m_class.
518   */
519   switch (wait->m_wait_class)
520   {
521   case WAIT_CLASS_METADATA:
522     if (make_metadata_lock_object_columns(wait))
523       return;
524     safe_class= sanitize_metadata_class(wait->m_class);
525     break;
526   case WAIT_CLASS_IDLE:
527     clear_object_columns();
528     m_row.m_object_instance_addr= 0;
529     safe_class= sanitize_idle_class(wait->m_class);
530     timer_name= idle_timer;
531     break;
532   case WAIT_CLASS_MUTEX:
533     clear_object_columns();
534     m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
535     safe_class= sanitize_mutex_class((PFS_mutex_class*) wait->m_class);
536     break;
537   case WAIT_CLASS_RWLOCK:
538     clear_object_columns();
539     m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
540     safe_class= sanitize_rwlock_class((PFS_rwlock_class*) wait->m_class);
541     break;
542   case WAIT_CLASS_COND:
543     clear_object_columns();
544     m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
545     safe_class= sanitize_cond_class((PFS_cond_class*) wait->m_class);
546     break;
547   case WAIT_CLASS_TABLE:
548     if (make_table_object_columns(wait))
549       return;
550     safe_class= sanitize_table_class(wait->m_class);
551     break;
552   case WAIT_CLASS_FILE:
553     if (make_file_object_columns(wait))
554       return;
555     safe_class= sanitize_file_class((PFS_file_class*) wait->m_class);
556     break;
557   case WAIT_CLASS_SOCKET:
558     if (make_socket_object_columns(wait))
559       return;
560     safe_class= sanitize_socket_class((PFS_socket_class*) wait->m_class);
561     break;
562   case NO_WAIT_CLASS:
563   default:
564     return;
565   }
566 
567   if (unlikely(safe_class == NULL))
568     return;
569 
570   m_row.m_thread_internal_id= wait->m_thread_internal_id;
571   m_row.m_event_id= wait->m_event_id;
572   m_row.m_end_event_id= wait->m_end_event_id;
573   m_row.m_nesting_event_id= wait->m_nesting_event_id;
574   m_row.m_nesting_event_type= wait->m_nesting_event_type;
575 
576   get_normalizer(safe_class);
577 
578   if (m_row.m_end_event_id == 0)
579   {
580     timer_end= get_timer_raw_value(timer_name);
581   }
582   else
583   {
584     timer_end= wait->m_timer_end;
585   }
586 
587   m_normalizer->to_pico(wait->m_timer_start, timer_end,
588                       & m_row.m_timer_start, & m_row.m_timer_end, & m_row.m_timer_wait);
589 
590   m_row.m_name= safe_class->m_name;
591   m_row.m_name_length= safe_class->m_name_length;
592 
593   /* Disable source file and line to avoid stale __FILE__ pointers. */
594   m_row.m_source_length= 0;
595 
596   m_row.m_operation= wait->m_operation;
597   m_row.m_number_of_bytes= wait->m_number_of_bytes;
598   m_row.m_flags= wait->m_flags;
599 
600   m_row_exists= true;
601 }
602 
603 /**
604   Operations names map, as displayed in the 'OPERATION' column.
605   Indexed by enum_operation_type - 1.
606   Note: enum_operation_type contains a more precise definition,
607   since more details are needed internally by the instrumentation.
608   Different similar operations (CLOSE vs STREAMCLOSE) are displayed
609   with the same name 'close'.
610 */
611 static const LEX_STRING operation_names_map[]=
612 {
613   /* Mutex operations */
614   { C_STRING_WITH_LEN("lock") },
615   { C_STRING_WITH_LEN("try_lock") },
616 
617   /* RWLock operations (RW-lock) */
618   { C_STRING_WITH_LEN("read_lock") },
619   { C_STRING_WITH_LEN("write_lock") },
620   { C_STRING_WITH_LEN("try_read_lock") },
621   { C_STRING_WITH_LEN("try_write_lock") },
622 
623   /* RWLock operations (SX-lock) */
624   { C_STRING_WITH_LEN("shared_lock") },
625   { C_STRING_WITH_LEN("shared_exclusive_lock") },
626   { C_STRING_WITH_LEN("exclusive_lock") },
627   { C_STRING_WITH_LEN("try_shared_lock") },
628   { C_STRING_WITH_LEN("try_shared_exclusive_lock") },
629   { C_STRING_WITH_LEN("try_exclusive_lock") },
630 
631   /* Condition operations */
632   { C_STRING_WITH_LEN("wait") },
633   { C_STRING_WITH_LEN("timed_wait") },
634 
635   /* File operations */
636   { C_STRING_WITH_LEN("create") },
637   { C_STRING_WITH_LEN("create") }, /* create tmp */
638   { C_STRING_WITH_LEN("open") },
639   { C_STRING_WITH_LEN("open") }, /* stream open */
640   { C_STRING_WITH_LEN("close") },
641   { C_STRING_WITH_LEN("close") }, /* stream close */
642   { C_STRING_WITH_LEN("read") },
643   { C_STRING_WITH_LEN("write") },
644   { C_STRING_WITH_LEN("seek") },
645   { C_STRING_WITH_LEN("tell") },
646   { C_STRING_WITH_LEN("flush") },
647   { C_STRING_WITH_LEN("stat") },
648   { C_STRING_WITH_LEN("stat") }, /* fstat */
649   { C_STRING_WITH_LEN("chsize") },
650   { C_STRING_WITH_LEN("delete") },
651   { C_STRING_WITH_LEN("rename") },
652   { C_STRING_WITH_LEN("sync") },
653 
654   /* Table io operations */
655   { C_STRING_WITH_LEN("fetch") },
656   { C_STRING_WITH_LEN("insert") }, /* write row */
657   { C_STRING_WITH_LEN("update") }, /* update row */
658   { C_STRING_WITH_LEN("delete") }, /* delete row */
659 
660   /* Table lock operations */
661   { C_STRING_WITH_LEN("read normal") },
662   { C_STRING_WITH_LEN("read with shared locks") },
663   { C_STRING_WITH_LEN("read high priority") },
664   { C_STRING_WITH_LEN("read no inserts") },
665   { C_STRING_WITH_LEN("write allow write") },
666   { C_STRING_WITH_LEN("write concurrent insert") },
667   { C_STRING_WITH_LEN("write low priority") },
668   { C_STRING_WITH_LEN("write normal") },
669   { C_STRING_WITH_LEN("read external") },
670   { C_STRING_WITH_LEN("write external") },
671 
672   /* Socket operations */
673   { C_STRING_WITH_LEN("create") },
674   { C_STRING_WITH_LEN("connect") },
675   { C_STRING_WITH_LEN("bind") },
676   { C_STRING_WITH_LEN("close") },
677   { C_STRING_WITH_LEN("send") },
678   { C_STRING_WITH_LEN("recv") },
679   { C_STRING_WITH_LEN("sendto") },
680   { C_STRING_WITH_LEN("recvfrom") },
681   { C_STRING_WITH_LEN("sendmsg") },
682   { C_STRING_WITH_LEN("recvmsg") },
683   { C_STRING_WITH_LEN("seek") },
684   { C_STRING_WITH_LEN("opt") },
685   { C_STRING_WITH_LEN("stat") },
686   { C_STRING_WITH_LEN("shutdown") },
687   { C_STRING_WITH_LEN("select") },
688 
689   /* Idle operations */
690   { C_STRING_WITH_LEN("idle") },
691 
692   /* Medatada lock operations */
693   { C_STRING_WITH_LEN("metadata lock") }
694 };
695 
696 
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)697 int table_events_waits_common::read_row_values(TABLE *table,
698                                                unsigned char *buf,
699                                                Field **fields,
700                                                bool read_all)
701 {
702   Field *f;
703   const LEX_STRING *operation;
704 
705   compile_time_assert(COUNT_OPERATION_TYPE ==
706                       array_elements(operation_names_map));
707 
708   if (unlikely(! m_row_exists))
709     return HA_ERR_RECORD_DELETED;
710 
711   /* Set the null bits */
712   assert(table->s->null_bytes == 2);
713   buf[0]= 0;
714   buf[1]= 0;
715 
716   /*
717     Some columns are unreliable, because they are joined with other buffers,
718     which could have changed and been reused for something else.
719     These columns are:
720     - THREAD_ID (m_thread joins with PFS_thread),
721     - SCHEMA_NAME (m_schema_name joins with PFS_table_share)
722     - OBJECT_NAME (m_object_name joins with PFS_table_share)
723   */
724   for (; (f= *fields) ; fields++)
725   {
726     if (read_all || bitmap_is_set(table->read_set, f->field_index))
727     {
728       switch(f->field_index)
729       {
730       case 0: /* THREAD_ID */
731         set_field_ulonglong(f, m_row.m_thread_internal_id);
732         break;
733       case 1: /* EVENT_ID */
734         set_field_ulonglong(f, m_row.m_event_id);
735         break;
736       case 2: /* END_EVENT_ID */
737         if (m_row.m_end_event_id > 0)
738           set_field_ulonglong(f, m_row.m_end_event_id - 1);
739         else
740           f->set_null();
741         break;
742       case 3: /* EVENT_NAME */
743         set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
744         break;
745       case 4: /* SOURCE */
746         set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length);
747         break;
748       case 5: /* TIMER_START */
749         if (m_row.m_timer_start != 0)
750           set_field_ulonglong(f, m_row.m_timer_start);
751         else
752           f->set_null();
753         break;
754       case 6: /* TIMER_END */
755         if (m_row.m_timer_end != 0)
756           set_field_ulonglong(f, m_row.m_timer_end);
757         else
758           f->set_null();
759         break;
760       case 7: /* TIMER_WAIT */
761         if (m_row.m_timer_wait != 0)
762           set_field_ulonglong(f, m_row.m_timer_wait);
763         else
764           f->set_null();
765         break;
766       case 8: /* SPINS */
767         f->set_null();
768         break;
769       case 9: /* OBJECT_SCHEMA */
770         if (m_row.m_object_schema_length > 0)
771         {
772           set_field_varchar_utf8(f, m_row.m_object_schema,
773                                  m_row.m_object_schema_length);
774         }
775         else
776           f->set_null();
777         break;
778       case 10: /* OBJECT_NAME */
779         if (m_row.m_object_name_length > 0)
780         {
781           set_field_varchar_utf8(f, m_row.m_object_name,
782                                  m_row.m_object_name_length);
783         }
784         else
785           f->set_null();
786         break;
787       case 11: /* INDEX_NAME */
788         if (m_row.m_index_name_length > 0)
789         {
790           set_field_varchar_utf8(f, m_row.m_index_name,
791                                  m_row.m_index_name_length);
792         }
793         else
794           f->set_null();
795         break;
796       case 12: /* OBJECT_TYPE */
797         if (m_row.m_object_type_length > 0)
798         {
799           set_field_varchar_utf8(f, m_row.m_object_type,
800                                  m_row.m_object_type_length);
801         }
802         else
803           f->set_null();
804         break;
805       case 13: /* OBJECT_INSTANCE */
806         set_field_ulonglong(f, m_row.m_object_instance_addr);
807         break;
808       case 14: /* NESTING_EVENT_ID */
809         if (m_row.m_nesting_event_id != 0)
810           set_field_ulonglong(f, m_row.m_nesting_event_id);
811         else
812           f->set_null();
813         break;
814       case 15: /* NESTING_EVENT_TYPE */
815         if (m_row.m_nesting_event_id != 0)
816           set_field_enum(f, m_row.m_nesting_event_type);
817         else
818           f->set_null();
819         break;
820       case 16: /* OPERATION */
821         operation= &operation_names_map[(int) m_row.m_operation - 1];
822         set_field_varchar_utf8(f, operation->str, operation->length);
823         break;
824       case 17: /* NUMBER_OF_BYTES (also used for ROWS) */
825         if ((m_row.m_operation == OPERATION_TYPE_FILEREAD) ||
826             (m_row.m_operation == OPERATION_TYPE_FILEWRITE) ||
827             (m_row.m_operation == OPERATION_TYPE_FILECHSIZE) ||
828             (m_row.m_operation == OPERATION_TYPE_SOCKETSEND) ||
829             (m_row.m_operation == OPERATION_TYPE_SOCKETRECV) ||
830             (m_row.m_operation == OPERATION_TYPE_SOCKETSENDTO) ||
831             (m_row.m_operation == OPERATION_TYPE_SOCKETRECVFROM) ||
832             (m_row.m_operation == OPERATION_TYPE_TABLE_FETCH) ||
833             (m_row.m_operation == OPERATION_TYPE_TABLE_WRITE_ROW) ||
834             (m_row.m_operation == OPERATION_TYPE_TABLE_UPDATE_ROW) ||
835             (m_row.m_operation == OPERATION_TYPE_TABLE_DELETE_ROW))
836           set_field_ulonglong(f, m_row.m_number_of_bytes);
837         else
838           f->set_null();
839         break;
840       case 18: /* FLAGS */
841         f->set_null();
842         break;
843       default:
844         assert(false);
845       }
846     }
847   }
848   return 0;
849 }
850 
create(void)851 PFS_engine_table* table_events_waits_current::create(void)
852 {
853   return new table_events_waits_current();
854 }
855 
table_events_waits_current()856 table_events_waits_current::table_events_waits_current()
857   : table_events_waits_common(&m_share, &m_pos),
858   m_pos(), m_next_pos()
859 {}
860 
reset_position(void)861 void table_events_waits_current::reset_position(void)
862 {
863   m_pos.reset();
864   m_next_pos.reset();
865 }
866 
rnd_next(void)867 int table_events_waits_current::rnd_next(void)
868 {
869   PFS_thread *pfs_thread;
870   PFS_events_waits *wait;
871   bool has_more_thread= true;
872 
873   for (m_pos.set_at(&m_next_pos);
874        has_more_thread;
875        m_pos.next_thread())
876   {
877     pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
878     if (pfs_thread != NULL)
879     {
880       /*
881         We do not show nested events for now,
882         this will be revised with TABLE io
883       */
884 // #define ONLY_SHOW_ONE_WAIT
885 
886 #ifdef ONLY_SHOW_ONE_WAIT
887       if (m_pos.m_index_2 >= 1)
888         continue;
889 #else
890       /* m_events_waits_stack[0] is a dummy record */
891       PFS_events_waits *top_wait = &pfs_thread->m_events_waits_stack[WAIT_STACK_BOTTOM];
892       wait= &pfs_thread->m_events_waits_stack[m_pos.m_index_2 + WAIT_STACK_BOTTOM];
893 
894       PFS_events_waits *safe_current = pfs_thread->m_events_waits_current;
895 
896       if (safe_current == top_wait)
897       {
898         /* Display the last top level wait, when completed */
899         if (m_pos.m_index_2 >= 1)
900           continue;
901       }
902       else
903       {
904         /* Display all pending waits, when in progress */
905         if (wait >= safe_current)
906           continue;
907       }
908 #endif
909 
910       if (wait->m_wait_class == NO_WAIT_CLASS)
911       {
912         /*
913           This locker does not exist.
914           There can not be more lockers in the stack, skip to the next thread
915         */
916         continue;
917       }
918 
919       make_row(pfs_thread, wait);
920       /* Next iteration, look for the next locker in this thread */
921       m_next_pos.set_after(&m_pos);
922       return 0;
923     }
924   }
925 
926   return HA_ERR_END_OF_FILE;
927 }
928 
rnd_pos(const void * pos)929 int table_events_waits_current::rnd_pos(const void *pos)
930 {
931   PFS_thread *pfs_thread;
932   PFS_events_waits *wait;
933 
934   set_position(pos);
935 
936   pfs_thread= global_thread_container.get(m_pos.m_index_1);
937   if (pfs_thread != NULL)
938   {
939 #ifdef ONLY_SHOW_ONE_WAIT
940     if (m_pos.m_index_2 >= 1)
941       return HA_ERR_RECORD_DELETED;
942 #else
943     /* m_events_waits_stack[0] is a dummy record */
944     PFS_events_waits *top_wait = &pfs_thread->m_events_waits_stack[WAIT_STACK_BOTTOM];
945     wait= &pfs_thread->m_events_waits_stack[m_pos.m_index_2 + WAIT_STACK_BOTTOM];
946 
947     PFS_events_waits *safe_current = pfs_thread->m_events_waits_current;
948 
949     if (safe_current == top_wait)
950     {
951       /* Display the last top level wait, when completed */
952       if (m_pos.m_index_2 >= 1)
953         return HA_ERR_RECORD_DELETED;
954     }
955     else
956     {
957       /* Display all pending waits, when in progress */
958       if (wait >= safe_current)
959         return HA_ERR_RECORD_DELETED;
960     }
961 #endif
962 
963     assert(m_pos.m_index_2 < WAIT_STACK_LOGICAL_SIZE);
964 
965     if (wait->m_wait_class != NO_WAIT_CLASS)
966     {
967       make_row(pfs_thread, wait);
968       return 0;
969     }
970   }
971 
972   return HA_ERR_RECORD_DELETED;
973 }
974 
make_row(PFS_thread * thread,PFS_events_waits * wait)975 void table_events_waits_current::make_row(PFS_thread *thread, PFS_events_waits *wait)
976 {
977   pfs_optimistic_state lock;
978 
979   /* Protect this reader against a thread termination */
980   thread->m_lock.begin_optimistic_lock(&lock);
981 
982   table_events_waits_common::make_row(wait);
983 
984   if (! thread->m_lock.end_optimistic_lock(&lock))
985     m_row_exists= false;
986 }
987 
delete_all_rows(void)988 int table_events_waits_current::delete_all_rows(void)
989 {
990   reset_events_waits_current();
991   return 0;
992 }
993 
994 ha_rows
get_row_count(void)995 table_events_waits_current::get_row_count(void)
996 {
997   return WAIT_STACK_SIZE * global_thread_container.get_row_count();
998 }
999 
create(void)1000 PFS_engine_table* table_events_waits_history::create(void)
1001 {
1002   return new table_events_waits_history();
1003 }
1004 
table_events_waits_history()1005 table_events_waits_history::table_events_waits_history()
1006   : table_events_waits_common(&m_share, &m_pos),
1007   m_pos(), m_next_pos()
1008 {}
1009 
reset_position(void)1010 void table_events_waits_history::reset_position(void)
1011 {
1012   m_pos.reset();
1013   m_next_pos.reset();
1014 }
1015 
rnd_next(void)1016 int table_events_waits_history::rnd_next(void)
1017 {
1018   PFS_thread *pfs_thread;
1019   PFS_events_waits *wait;
1020   bool has_more_thread= true;
1021 
1022   if (events_waits_history_per_thread == 0)
1023     return HA_ERR_END_OF_FILE;
1024 
1025   for (m_pos.set_at(&m_next_pos);
1026        has_more_thread;
1027        m_pos.next_thread())
1028   {
1029     pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
1030     if (pfs_thread != NULL)
1031     {
1032       if (m_pos.m_index_2 >= events_waits_history_per_thread)
1033       {
1034         /* This thread does not have more (full) history */
1035         continue;
1036       }
1037 
1038       if ( ! pfs_thread->m_waits_history_full &&
1039           (m_pos.m_index_2 >= pfs_thread->m_waits_history_index))
1040       {
1041         /* This thread does not have more (not full) history */
1042         continue;
1043       }
1044 
1045       wait= &pfs_thread->m_waits_history[m_pos.m_index_2];
1046       if (wait->m_wait_class != NO_WAIT_CLASS)
1047       {
1048         make_row(pfs_thread, wait);
1049         /* Next iteration, look for the next history in this thread */
1050         m_next_pos.set_after(&m_pos);
1051         return 0;
1052       }
1053     }
1054   }
1055 
1056   return HA_ERR_END_OF_FILE;
1057 }
1058 
rnd_pos(const void * pos)1059 int table_events_waits_history::rnd_pos(const void *pos)
1060 {
1061   PFS_thread *pfs_thread;
1062   PFS_events_waits *wait;
1063 
1064   assert(events_waits_history_per_thread != 0);
1065   set_position(pos);
1066 
1067   pfs_thread= global_thread_container.get(m_pos.m_index_1);
1068   if (pfs_thread != NULL)
1069   {
1070     assert(m_pos.m_index_2 < events_waits_history_per_thread);
1071 
1072     if ( ! pfs_thread->m_waits_history_full &&
1073         (m_pos.m_index_2 >= pfs_thread->m_waits_history_index))
1074       return HA_ERR_RECORD_DELETED;
1075 
1076     wait= &pfs_thread->m_waits_history[m_pos.m_index_2];
1077 
1078     if (wait->m_wait_class != NO_WAIT_CLASS)
1079     {
1080       make_row(pfs_thread, wait);
1081       return 0;
1082     }
1083   }
1084 
1085   return HA_ERR_RECORD_DELETED;
1086 }
1087 
make_row(PFS_thread * thread,PFS_events_waits * wait)1088 void table_events_waits_history::make_row(PFS_thread *thread, PFS_events_waits *wait)
1089 {
1090   pfs_optimistic_state lock;
1091 
1092   /* Protect this reader against a thread termination */
1093   thread->m_lock.begin_optimistic_lock(&lock);
1094 
1095   table_events_waits_common::make_row(wait);
1096 
1097   if (! thread->m_lock.end_optimistic_lock(&lock))
1098     m_row_exists= false;
1099 }
1100 
delete_all_rows(void)1101 int table_events_waits_history::delete_all_rows(void)
1102 {
1103   reset_events_waits_history();
1104   return 0;
1105 }
1106 
1107 ha_rows
get_row_count(void)1108 table_events_waits_history::get_row_count(void)
1109 {
1110   return events_waits_history_per_thread * global_thread_container.get_row_count();
1111 }
1112 
create(void)1113 PFS_engine_table* table_events_waits_history_long::create(void)
1114 {
1115   return new table_events_waits_history_long();
1116 }
1117 
table_events_waits_history_long()1118 table_events_waits_history_long::table_events_waits_history_long()
1119   : table_events_waits_common(&m_share, &m_pos),
1120   m_pos(0), m_next_pos(0)
1121 {}
1122 
reset_position(void)1123 void table_events_waits_history_long::reset_position(void)
1124 {
1125   m_pos.m_index= 0;
1126   m_next_pos.m_index= 0;
1127 }
1128 
rnd_next(void)1129 int table_events_waits_history_long::rnd_next(void)
1130 {
1131   PFS_events_waits *wait;
1132   uint limit;
1133 
1134   if (events_waits_history_long_size == 0)
1135     return HA_ERR_END_OF_FILE;
1136 
1137   if (events_waits_history_long_full)
1138     limit= events_waits_history_long_size;
1139   else
1140     limit= events_waits_history_long_index.m_u32 % events_waits_history_long_size;
1141 
1142   for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next())
1143   {
1144     wait= &events_waits_history_long_array[m_pos.m_index];
1145 
1146     if (wait->m_wait_class != NO_WAIT_CLASS)
1147     {
1148       make_row(wait);
1149       /* Next iteration, look for the next entry */
1150       m_next_pos.set_after(&m_pos);
1151       return 0;
1152     }
1153   }
1154 
1155   return HA_ERR_END_OF_FILE;
1156 }
1157 
rnd_pos(const void * pos)1158 int table_events_waits_history_long::rnd_pos(const void *pos)
1159 {
1160   PFS_events_waits *wait;
1161   uint limit;
1162 
1163   if (events_waits_history_long_size == 0)
1164     return HA_ERR_RECORD_DELETED;
1165 
1166   set_position(pos);
1167 
1168   if (events_waits_history_long_full)
1169     limit= events_waits_history_long_size;
1170   else
1171     limit= events_waits_history_long_index.m_u32 % events_waits_history_long_size;
1172 
1173   if (m_pos.m_index >= limit)
1174     return HA_ERR_RECORD_DELETED;
1175 
1176   wait= &events_waits_history_long_array[m_pos.m_index];
1177 
1178   if (wait->m_wait_class == NO_WAIT_CLASS)
1179     return HA_ERR_RECORD_DELETED;
1180 
1181   make_row(wait);
1182   return 0;
1183 }
1184 
delete_all_rows(void)1185 int table_events_waits_history_long::delete_all_rows(void)
1186 {
1187   reset_events_waits_history_long();
1188   return 0;
1189 }
1190 
1191 ha_rows
get_row_count(void)1192 table_events_waits_history_long::get_row_count(void)
1193 {
1194   return events_waits_history_long_size;
1195 }
1196 
1197