1 /* Copyright (c) 2008, 2010, 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/table_events_waits_summary.cc
25   Table EVENTS_WAITS_SUMMARY_BY_xxx (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_pthread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "table_events_waits_summary.h"
34 #include "pfs_global.h"
35 
36 THR_LOCK table_events_waits_summary_by_instance::m_table_lock;
37 
38 static const TABLE_FIELD_TYPE ews_by_instance_field_types[]=
39 {
40   {
41     { C_STRING_WITH_LEN("EVENT_NAME") },
42     { C_STRING_WITH_LEN("varchar(128)") },
43     { NULL, 0}
44   },
45   {
46     { C_STRING_WITH_LEN("OBJECT_INSTANCE_BEGIN") },
47     { C_STRING_WITH_LEN("bigint(20)") },
48     { NULL, 0}
49   },
50   {
51     { C_STRING_WITH_LEN("COUNT_STAR") },
52     { C_STRING_WITH_LEN("bigint(20)") },
53     { NULL, 0}
54   },
55   {
56     { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
57     { C_STRING_WITH_LEN("bigint(20)") },
58     { NULL, 0}
59   },
60   {
61     { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
62     { C_STRING_WITH_LEN("bigint(20)") },
63     { NULL, 0}
64   },
65   {
66     { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
67     { C_STRING_WITH_LEN("bigint(20)") },
68     { NULL, 0}
69   },
70   {
71     { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
72     { C_STRING_WITH_LEN("bigint(20)") },
73     { NULL, 0}
74   }
75 };
76 
77 TABLE_FIELD_DEF
78 table_events_waits_summary_by_instance::m_field_def=
79 { 7, ews_by_instance_field_types };
80 
81 PFS_engine_table_share
82 table_events_waits_summary_by_instance::m_share=
83 {
84   { C_STRING_WITH_LEN("events_waits_summary_by_instance") },
85   &pfs_truncatable_acl,
86   &table_events_waits_summary_by_instance::create,
87   NULL, /* write_row */
88   &table_events_waits_summary_by_instance::delete_all_rows,
89   NULL, /* get_row_count */
90   1000, /* records */
91   sizeof(pos_all_instr),
92   &m_table_lock,
93   &m_field_def,
94   false /* checked */
95 };
96 
create(void)97 PFS_engine_table* table_events_waits_summary_by_instance::create(void)
98 {
99   return new table_events_waits_summary_by_instance();
100 }
101 
delete_all_rows(void)102 int table_events_waits_summary_by_instance::delete_all_rows(void)
103 {
104   reset_events_waits_by_instance();
105   return 0;
106 }
107 
108 table_events_waits_summary_by_instance
table_events_waits_summary_by_instance()109 ::table_events_waits_summary_by_instance()
110   : table_all_instr(&m_share), m_row_exists(false)
111 {}
112 
113 void table_events_waits_summary_by_instance
make_instr_row(PFS_instr * pfs,PFS_instr_class * klass,const void * object_instance_begin,PFS_single_stat * pfs_stat)114 ::make_instr_row(PFS_instr *pfs, PFS_instr_class *klass,
115                  const void *object_instance_begin,
116                  PFS_single_stat *pfs_stat)
117 {
118   pfs_lock lock;
119   m_row_exists= false;
120 
121   /*
122     Protect this reader against a mutex/rwlock/cond destroy,
123     file delete, table drop.
124   */
125   pfs->m_lock.begin_optimistic_lock(&lock);
126 
127   m_row.m_name= klass->m_name;
128   m_row.m_name_length= klass->m_name_length;
129   m_row.m_object_instance_addr= (intptr) object_instance_begin;
130 
131   get_normalizer(klass);
132   m_row.m_stat.set(m_normalizer, pfs_stat);
133 
134   if (pfs->m_lock.end_optimistic_lock(&lock))
135     m_row_exists= true;
136 }
137 
138 /**
139   Build a row, for mutex statistics in a thread.
140   @param pfs              the mutex this cursor is reading
141 */
make_mutex_row(PFS_mutex * pfs)142 void table_events_waits_summary_by_instance::make_mutex_row(PFS_mutex *pfs)
143 {
144   PFS_mutex_class *safe_class;
145   safe_class= sanitize_mutex_class(pfs->m_class);
146   if (unlikely(safe_class == NULL))
147     return;
148 
149   make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_mutex_stat.m_wait_stat);
150 }
151 
152 /**
153   Build a row, for rwlock statistics in a thread.
154   @param pfs              the rwlock this cursor is reading
155 */
make_rwlock_row(PFS_rwlock * pfs)156 void table_events_waits_summary_by_instance::make_rwlock_row(PFS_rwlock *pfs)
157 {
158   PFS_rwlock_class *safe_class;
159   safe_class= sanitize_rwlock_class(pfs->m_class);
160   if (unlikely(safe_class == NULL))
161     return;
162 
163   make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_rwlock_stat.m_wait_stat);
164 }
165 
166 /**
167   Build a row, for condition statistics in a thread.
168   @param pfs              the condition this cursor is reading
169 */
make_cond_row(PFS_cond * pfs)170 void table_events_waits_summary_by_instance::make_cond_row(PFS_cond *pfs)
171 {
172   PFS_cond_class *safe_class;
173   safe_class= sanitize_cond_class(pfs->m_class);
174   if (unlikely(safe_class == NULL))
175     return;
176 
177   make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_cond_stat.m_wait_stat);
178 }
179 
180 /**
181   Build a row, for file statistics in a thread.
182   @param pfs              the file this cursor is reading
183 */
make_file_row(PFS_file * pfs)184 void table_events_waits_summary_by_instance::make_file_row(PFS_file *pfs)
185 {
186   PFS_file_class *safe_class;
187   safe_class= sanitize_file_class(pfs->m_class);
188   if (unlikely(safe_class == NULL))
189     return;
190 
191   PFS_single_stat sum;
192   pfs->m_file_stat.m_io_stat.sum_waits(& sum);
193   /*
194     Files don't have a in memory structure associated to it,
195     so we use the address of the PFS_file buffer as object_instance_begin
196   */
197   make_instr_row(pfs, safe_class, pfs, & sum);
198 }
199 
200 /**
201   Build a row, for socket statistics in a thread.
202   @param pfs              the socket this cursor is reading
203 */
make_socket_row(PFS_socket * pfs)204 void table_events_waits_summary_by_instance::make_socket_row(PFS_socket *pfs)
205 {
206   PFS_socket_class *safe_class;
207   safe_class= sanitize_socket_class(pfs->m_class);
208   if (unlikely(safe_class == NULL))
209     return;
210 
211   /*
212      Consolidate wait times and byte counts for individual operations. This is
213      done by the consumer in order to reduce overhead on the socket instrument.
214   */
215   PFS_byte_stat pfs_stat;
216   pfs->m_socket_stat.m_io_stat.sum(&pfs_stat);
217 
218   /*
219     Sockets don't have an associated in-memory structure, so use the address of
220     the PFS_socket buffer as object_instance_begin.
221   */
222   make_instr_row(pfs, safe_class, pfs, &pfs_stat);
223 }
224 
225 int table_events_waits_summary_by_instance
read_row_values(TABLE * table,unsigned char *,Field ** fields,bool read_all)226 ::read_row_values(TABLE *table, unsigned char *, Field **fields,
227                   bool read_all)
228 {
229   Field *f;
230 
231   if (unlikely(! m_row_exists))
232     return HA_ERR_RECORD_DELETED;
233 
234   /* Set the null bits */
235   DBUG_ASSERT(table->s->null_bytes == 0);
236 
237   for (; (f= *fields) ; fields++)
238   {
239     if (read_all || bitmap_is_set(table->read_set, f->field_index))
240     {
241       switch(f->field_index)
242       {
243       case 0: /* NAME */
244         set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
245         break;
246       case 1: /* OBJECT_INSTANCE */
247         set_field_ulonglong(f, m_row.m_object_instance_addr);
248         break;
249       case 2: /* COUNT */
250         set_field_ulonglong(f, m_row.m_stat.m_count);
251         break;
252       case 3: /* SUM */
253         set_field_ulonglong(f, m_row.m_stat.m_sum);
254         break;
255       case 4: /* MIN */
256         set_field_ulonglong(f, m_row.m_stat.m_min);
257         break;
258       case 5: /* AVG */
259         set_field_ulonglong(f, m_row.m_stat.m_avg);
260         break;
261       case 6: /* MAX */
262         set_field_ulonglong(f, m_row.m_stat.m_max);
263         break;
264       default:
265         DBUG_ASSERT(false);
266       }
267     }
268   }
269 
270   return 0;
271 }
272 
273