1 /* Copyright (c) 2011, 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_mems_by_thread_by_event_name.cc
25   Table MEMORY_SUMMARY_BY_THREAD_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_mems_by_thread_by_event_name.h"
34 #include "pfs_global.h"
35 #include "pfs_visitor.h"
36 #include "pfs_memory.h"
37 #include "pfs_buffer_container.h"
38 #include "field.h"
39 
40 THR_LOCK table_mems_by_thread_by_event_name::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_NAME") },
51     { C_STRING_WITH_LEN("varchar(128)") },
52     { NULL, 0}
53   },
54   {
55     { C_STRING_WITH_LEN("COUNT_ALLOC") },
56     { C_STRING_WITH_LEN("bigint(20)") },
57     { NULL, 0}
58   },
59   {
60     { C_STRING_WITH_LEN("COUNT_FREE") },
61     { C_STRING_WITH_LEN("bigint(20)") },
62     { NULL, 0}
63   },
64   {
65     { C_STRING_WITH_LEN("SUM_NUMBER_OF_BYTES_ALLOC") },
66     { C_STRING_WITH_LEN("bigint(20)") },
67     { NULL, 0}
68   },
69   {
70     { C_STRING_WITH_LEN("SUM_NUMBER_OF_BYTES_FREE") },
71     { C_STRING_WITH_LEN("bigint(20)") },
72     { NULL, 0}
73   },
74   {
75     { C_STRING_WITH_LEN("LOW_COUNT_USED") },
76     { C_STRING_WITH_LEN("bigint(20)") },
77     { NULL, 0}
78   },
79   {
80     { C_STRING_WITH_LEN("CURRENT_COUNT_USED") },
81     { C_STRING_WITH_LEN("bigint(20)") },
82     { NULL, 0}
83   },
84   {
85     { C_STRING_WITH_LEN("HIGH_COUNT_USED") },
86     { C_STRING_WITH_LEN("bigint(20)") },
87     { NULL, 0}
88   },
89   {
90     { C_STRING_WITH_LEN("LOW_NUMBER_OF_BYTES_USED") },
91     { C_STRING_WITH_LEN("bigint(20)") },
92     { NULL, 0}
93   },
94   {
95     { C_STRING_WITH_LEN("CURRENT_NUMBER_OF_BYTES_USED") },
96     { C_STRING_WITH_LEN("bigint(20)") },
97     { NULL, 0}
98   },
99   {
100     { C_STRING_WITH_LEN("HIGH_NUMBER_OF_BYTES_USED") },
101     { C_STRING_WITH_LEN("bigint(20)") },
102     { NULL, 0}
103   }
104 };
105 
106 TABLE_FIELD_DEF
107 table_mems_by_thread_by_event_name::m_field_def=
108 { 12, field_types };
109 
110 PFS_engine_table_share
111 table_mems_by_thread_by_event_name::m_share=
112 {
113   { C_STRING_WITH_LEN("memory_summary_by_thread_by_event_name") },
114   &pfs_readonly_acl,
115   table_mems_by_thread_by_event_name::create,
116   NULL, /* write_row */
117   table_mems_by_thread_by_event_name::delete_all_rows,
118   table_mems_by_thread_by_event_name::get_row_count,
119   sizeof(PFS_simple_index),
120   &m_table_lock,
121   &m_field_def,
122   false, /* checked */
123   false  /* perpetual */
124 };
125 
create(void)126 PFS_engine_table* table_mems_by_thread_by_event_name::create(void)
127 {
128   return new table_mems_by_thread_by_event_name();
129 }
130 
131 int
delete_all_rows(void)132 table_mems_by_thread_by_event_name::delete_all_rows(void)
133 {
134   reset_memory_by_thread();
135   return 0;
136 }
137 
138 ha_rows
get_row_count(void)139 table_mems_by_thread_by_event_name::get_row_count(void)
140 {
141   return global_thread_container.get_row_count() * memory_class_max;
142 }
143 
table_mems_by_thread_by_event_name()144 table_mems_by_thread_by_event_name::table_mems_by_thread_by_event_name()
145   : PFS_engine_table(&m_share, &m_pos),
146   m_row_exists(false), m_pos(), m_next_pos()
147 {}
148 
reset_position(void)149 void table_mems_by_thread_by_event_name::reset_position(void)
150 {
151   m_pos.reset();
152   m_next_pos.reset();
153 }
154 
rnd_next(void)155 int table_mems_by_thread_by_event_name::rnd_next(void)
156 {
157   PFS_thread *thread;
158   PFS_memory_class *memory_class;
159   bool has_more_thread= true;
160 
161   for (m_pos.set_at(&m_next_pos);
162        has_more_thread;
163        m_pos.next_thread())
164   {
165     thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
166     if (thread != NULL)
167     {
168       do
169       {
170         memory_class= find_memory_class(m_pos.m_index_2);
171         if (memory_class != NULL)
172         {
173           if (! memory_class->is_global())
174           {
175             make_row(thread, memory_class);
176             m_next_pos.set_after(&m_pos);
177             return 0;
178           }
179 
180           m_pos.next_class();
181         }
182       }
183       while (memory_class != NULL);
184     }
185   }
186 
187   return HA_ERR_END_OF_FILE;
188 }
189 
rnd_pos(const void * pos)190 int table_mems_by_thread_by_event_name::rnd_pos(const void *pos)
191 {
192   PFS_thread *thread;
193   PFS_memory_class *memory_class;
194 
195   set_position(pos);
196 
197   thread= global_thread_container.get(m_pos.m_index_1);
198   if (thread != NULL)
199   {
200     memory_class= find_memory_class(m_pos.m_index_2);
201     if (memory_class != NULL)
202     {
203       if (! memory_class->is_global())
204       {
205         make_row(thread, memory_class);
206         return 0;
207       }
208     }
209   }
210 
211   return HA_ERR_RECORD_DELETED;
212 }
213 
214 void table_mems_by_thread_by_event_name
make_row(PFS_thread * thread,PFS_memory_class * klass)215 ::make_row(PFS_thread *thread, PFS_memory_class *klass)
216 {
217   pfs_optimistic_state lock;
218   m_row_exists= false;
219 
220   /* Protect this reader against a thread termination */
221   thread->m_lock.begin_optimistic_lock(&lock);
222 
223   m_row.m_thread_internal_id= thread->m_thread_internal_id;
224 
225   m_row.m_event_name.make_row(klass);
226 
227   PFS_connection_memory_visitor visitor(klass);
228   PFS_connection_iterator::visit_thread(thread, & visitor);
229 
230   if (! thread->m_lock.end_optimistic_lock(&lock))
231     return;
232 
233   m_row_exists= true;
234   m_row.m_stat.set(& visitor.m_stat);
235 }
236 
read_row_values(TABLE * table,unsigned char *,Field ** fields,bool read_all)237 int table_mems_by_thread_by_event_name::read_row_values(TABLE *table,
238                                                     unsigned char *,
239                                                     Field **fields,
240                                                     bool read_all)
241 {
242   Field *f;
243 
244   if (unlikely(! m_row_exists))
245     return HA_ERR_RECORD_DELETED;
246 
247   /* Set the null bits */
248   assert(table->s->null_bytes == 0);
249 
250   for (; (f= *fields) ; fields++)
251   {
252     if (read_all || bitmap_is_set(table->read_set, f->field_index))
253     {
254       switch(f->field_index)
255       {
256       case 0: /* THREAD_ID */
257         set_field_ulonglong(f, m_row.m_thread_internal_id);
258         break;
259       case 1: /* EVENT_NAME */
260         m_row.m_event_name.set_field(f);
261         break;
262       default: /* 2, ... HIGH_NUMBER_OF_BYTES_USED */
263         m_row.m_stat.set_field(f->field_index - 2, f);
264         break;
265       }
266     }
267   }
268 
269   return 0;
270 }
271 
272