1 /* Copyright (c) 2010, 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
21   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /**
24   @file storage/perfschema/table_ets_by_thread_by_event_name.cc
25   Table EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "table_ets_by_thread_by_event_name.h"
34 #include "pfs_global.h"
35 #include "pfs_visitor.h"
36 #include "pfs_buffer_container.h"
37 #include "field.h"
38 
39 THR_LOCK table_ets_by_thread_by_event_name::m_table_lock;
40 
41 static const TABLE_FIELD_TYPE field_types[]=
42 {
43   {
44     { C_STRING_WITH_LEN("THREAD_ID") },
45     { C_STRING_WITH_LEN("bigint(20)") },
46     { NULL, 0}
47   },
48   {
49     { C_STRING_WITH_LEN("EVENT_NAME") },
50     { C_STRING_WITH_LEN("varchar(128)") },
51     { NULL, 0}
52   },
53   {
54     { C_STRING_WITH_LEN("COUNT_STAR") },
55     { C_STRING_WITH_LEN("bigint(20)") },
56     { NULL, 0}
57   },
58   {
59     { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
60     { C_STRING_WITH_LEN("bigint(20)") },
61     { NULL, 0}
62   },
63   {
64     { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
65     { C_STRING_WITH_LEN("bigint(20)") },
66     { NULL, 0}
67   },
68   {
69     { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
70     { C_STRING_WITH_LEN("bigint(20)") },
71     { NULL, 0}
72   },
73   {
74     { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
75     { C_STRING_WITH_LEN("bigint(20)") },
76     { NULL, 0}
77   },
78   {
79     { C_STRING_WITH_LEN("COUNT_READ_WRITE") },
80     { C_STRING_WITH_LEN("bigint(20)") },
81     { NULL, 0}
82   },
83   {
84     { C_STRING_WITH_LEN("SUM_TIMER_READ_WRITE") },
85     { C_STRING_WITH_LEN("bigint(20)") },
86     { NULL, 0}
87   },
88   {
89     { C_STRING_WITH_LEN("MIN_TIMER_READ_WRITE") },
90     { C_STRING_WITH_LEN("bigint(20)") },
91     { NULL, 0}
92   },
93   {
94     { C_STRING_WITH_LEN("AVG_TIMER_READ_WRITE") },
95     { C_STRING_WITH_LEN("bigint(20)") },
96     { NULL, 0}
97   },
98   {
99     { C_STRING_WITH_LEN("MAX_TIMER_READ_WRITE") },
100     { C_STRING_WITH_LEN("bigint(20)") },
101     { NULL, 0}
102   },
103   {
104     { C_STRING_WITH_LEN("COUNT_READ_ONLY") },
105     { C_STRING_WITH_LEN("bigint(20)") },
106     { NULL, 0}
107   },
108   {
109     { C_STRING_WITH_LEN("SUM_TIMER_READ_ONLY") },
110     { C_STRING_WITH_LEN("bigint(20)") },
111     { NULL, 0}
112   },
113   {
114     { C_STRING_WITH_LEN("MIN_TIMER_READ_ONLY") },
115     { C_STRING_WITH_LEN("bigint(20)") },
116     { NULL, 0}
117   },
118   {
119     { C_STRING_WITH_LEN("AVG_TIMER_READ_ONLY") },
120     { C_STRING_WITH_LEN("bigint(20)") },
121     { NULL, 0}
122   },
123   {
124     { C_STRING_WITH_LEN("MAX_TIMER_READ_ONLY") },
125     { C_STRING_WITH_LEN("bigint(20)") },
126     { NULL, 0}
127   }
128 };
129 
130 TABLE_FIELD_DEF
131 table_ets_by_thread_by_event_name::m_field_def=
132 { 17, field_types };
133 
134 PFS_engine_table_share
135 table_ets_by_thread_by_event_name::m_share=
136 {
137   { C_STRING_WITH_LEN("events_transactions_summary_by_thread_by_event_name") },
138   &pfs_truncatable_acl,
139   table_ets_by_thread_by_event_name::create,
140   NULL, /* write_row */
141   table_ets_by_thread_by_event_name::delete_all_rows,
142   table_ets_by_thread_by_event_name::get_row_count,
143   sizeof(pos_ets_by_thread_by_event_name),
144   &m_table_lock,
145   &m_field_def,
146   false, /* checked */
147   false  /* perpetual */
148 };
149 
150 PFS_engine_table*
create(void)151 table_ets_by_thread_by_event_name::create(void)
152 {
153   return new table_ets_by_thread_by_event_name();
154 }
155 
156 int
delete_all_rows(void)157 table_ets_by_thread_by_event_name::delete_all_rows(void)
158 {
159   reset_events_transactions_by_thread();
160   return 0;
161 }
162 
163 ha_rows
get_row_count(void)164 table_ets_by_thread_by_event_name::get_row_count(void)
165 {
166   return global_thread_container.get_row_count() * transaction_class_max;
167 }
168 
table_ets_by_thread_by_event_name()169 table_ets_by_thread_by_event_name::table_ets_by_thread_by_event_name()
170   : PFS_engine_table(&m_share, &m_pos),
171     m_row_exists(false), m_pos(), m_next_pos()
172 {}
173 
reset_position(void)174 void table_ets_by_thread_by_event_name::reset_position(void)
175 {
176   m_pos.reset();
177   m_next_pos.reset();
178 }
179 
rnd_init(bool scan)180 int table_ets_by_thread_by_event_name::rnd_init(bool scan)
181 {
182   m_normalizer= time_normalizer::get(transaction_timer);
183   return 0;
184 }
185 
rnd_next(void)186 int table_ets_by_thread_by_event_name::rnd_next(void)
187 {
188   PFS_thread *thread;
189   PFS_transaction_class *transaction_class;
190   bool has_more_thread= true;
191 
192   for (m_pos.set_at(&m_next_pos);
193        has_more_thread;
194        m_pos.next_thread())
195   {
196     thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
197     if (thread != NULL)
198     {
199       transaction_class= find_transaction_class(m_pos.m_index_2);
200       if (transaction_class)
201       {
202         make_row(thread, transaction_class);
203         m_next_pos.set_after(&m_pos);
204         return 0;
205       }
206     }
207   }
208 
209   return HA_ERR_END_OF_FILE;
210 }
211 
212 int
rnd_pos(const void * pos)213 table_ets_by_thread_by_event_name::rnd_pos(const void *pos)
214 {
215   PFS_thread *thread;
216   PFS_transaction_class *transaction_class;
217 
218   set_position(pos);
219 
220   thread= global_thread_container.get(m_pos.m_index_1);
221   if (thread != NULL)
222   {
223     transaction_class= find_transaction_class(m_pos.m_index_2);
224     if (transaction_class)
225     {
226       make_row(thread, transaction_class);
227       return 0;
228     }
229   }
230 
231   return HA_ERR_RECORD_DELETED;
232 }
233 
234 void table_ets_by_thread_by_event_name
make_row(PFS_thread * thread,PFS_transaction_class * klass)235 ::make_row(PFS_thread *thread, PFS_transaction_class *klass)
236 {
237   pfs_optimistic_state lock;
238   m_row_exists= false;
239 
240   /* Protect this reader against a thread termination */
241   thread->m_lock.begin_optimistic_lock(&lock);
242 
243   m_row.m_thread_internal_id= thread->m_thread_internal_id;
244 
245   m_row.m_event_name.make_row(klass);
246 
247   PFS_connection_transaction_visitor visitor(klass);
248   PFS_connection_iterator::visit_thread(thread, &visitor);
249 
250   if (! thread->m_lock.end_optimistic_lock(&lock))
251     return;
252 
253   m_row_exists= true;
254   m_row.m_stat.set(m_normalizer, &visitor.m_stat);
255 }
256 
257 int table_ets_by_thread_by_event_name
read_row_values(TABLE * table,unsigned char *,Field ** fields,bool read_all)258 ::read_row_values(TABLE *table, unsigned char *, Field **fields,
259                   bool read_all)
260 {
261   Field *f;
262 
263   if (unlikely(! m_row_exists))
264     return HA_ERR_RECORD_DELETED;
265 
266   /* Set the null bits */
267   assert(table->s->null_bytes == 0);
268 
269   for (; (f= *fields) ; fields++)
270   {
271     if (read_all || bitmap_is_set(table->read_set, f->field_index))
272     {
273       switch(f->field_index)
274       {
275       case 0: /* THREAD_ID */
276         set_field_ulonglong(f, m_row.m_thread_internal_id);
277         break;
278       case 1: /* EVENT_NAME */
279         m_row.m_event_name.set_field(f);
280         break;
281       default:
282         /**
283           COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT
284           COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE
285           COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
286         */
287         m_row.m_stat.set_field(f->field_index-2, f);
288         break;
289       }
290     }
291   }
292 
293   return 0;
294 }
295 
296