1 /* Copyright (c) 2015, 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_global_status.cc
25 Table global_status (implementation).
26 */
27
28 #include "my_global.h"
29 #include "table_global_status.h"
30 #include "my_thread.h"
31 #include "pfs_instr_class.h"
32 #include "pfs_column_types.h"
33 #include "pfs_column_values.h"
34 #include "pfs_global.h"
35
36 THR_LOCK table_global_status::m_table_lock;
37
38 static const TABLE_FIELD_TYPE field_types[]=
39 {
40 {
41 { C_STRING_WITH_LEN("VARIABLE_NAME") },
42 { C_STRING_WITH_LEN("varchar(64)") },
43 { NULL, 0}
44 },
45 {
46 { C_STRING_WITH_LEN("VARIABLE_VALUE") },
47 { C_STRING_WITH_LEN("varchar(1024)") },
48 { NULL, 0}
49 }
50 };
51
52 TABLE_FIELD_DEF
53 table_global_status::m_field_def=
54 { 2, field_types };
55
56 PFS_engine_table_share
57 table_global_status::m_share=
58 {
59 { C_STRING_WITH_LEN("global_status") },
60 &pfs_truncatable_world_acl,
61 table_global_status::create,
62 NULL, /* write_row */
63 table_global_status::delete_all_rows,
64 table_global_status::get_row_count,
65 sizeof(pos_t),
66 &m_table_lock,
67 &m_field_def,
68 false, /* checked */
69 true /* perpetual */
70 };
71
72 PFS_engine_table*
create(void)73 table_global_status::create(void)
74 {
75 return new table_global_status();
76 }
77
delete_all_rows(void)78 int table_global_status::delete_all_rows(void)
79 {
80 mysql_mutex_lock(&LOCK_status);
81 reset_status_by_thread();
82 reset_status_by_account();
83 reset_status_by_user();
84 reset_status_by_host();
85 reset_global_status();
86 mysql_mutex_unlock(&LOCK_status);
87 return 0;
88 }
89
get_row_count(void)90 ha_rows table_global_status::get_row_count(void)
91 {
92 mysql_mutex_lock(&LOCK_status);
93 ha_rows status_var_count= all_status_vars.size();
94 mysql_mutex_unlock(&LOCK_status);
95 return status_var_count;
96 }
97
table_global_status()98 table_global_status::table_global_status()
99 : PFS_engine_table(&m_share, &m_pos),
100 m_status_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
101 {}
102
reset_position(void)103 void table_global_status::reset_position(void)
104 {
105 m_pos.m_index= 0;
106 m_next_pos.m_index= 0;
107 }
108
rnd_init(bool scan)109 int table_global_status::rnd_init(bool scan)
110 {
111 /* Build a cache of all global status variables. Sum across threads. */
112 m_status_cache.materialize_global();
113
114 /* Record the current number of status variables to detect subsequent changes. */
115 ulonglong status_version= m_status_cache.get_status_array_version();
116
117 /*
118 The table context holds the current version of the global status array.
119 If scan == true, then allocate a new context from mem_root and store in TLS.
120 If scan == false, then restore from TLS.
121 */
122 m_context= (table_global_status_context *)current_thd->alloc(sizeof(table_global_status_context));
123 new(m_context) table_global_status_context(status_version, !scan);
124 return 0;
125 }
126
rnd_next(void)127 int table_global_status::rnd_next(void)
128 {
129 for (m_pos.set_at(&m_next_pos);
130 m_pos.m_index < m_status_cache.size();
131 m_pos.next())
132 {
133 const Status_variable *status_var= m_status_cache.get(m_pos.m_index);
134 if (status_var != NULL)
135 {
136 make_row(status_var);
137 m_next_pos.set_after(&m_pos);
138 return 0;
139 }
140 }
141 return HA_ERR_END_OF_FILE;
142 }
143
rnd_pos(const void * pos)144 int table_global_status::rnd_pos(const void *pos)
145 {
146 /* If global status array has changed, do nothing. */ // TODO: Issue warning
147 if (!m_context->versions_match())
148 return HA_ERR_RECORD_DELETED;
149
150 set_position(pos);
151 const Status_variable *status_var= m_status_cache.get(m_pos.m_index);
152 if (status_var != NULL)
153 {
154 make_row(status_var);
155 return 0;
156 }
157
158 return HA_ERR_RECORD_DELETED;
159 }
160
161 void table_global_status
make_row(const Status_variable * status_var)162 ::make_row(const Status_variable *status_var)
163 {
164 m_row_exists= false;
165 if (status_var->is_null())
166 return;
167 m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
168 m_row.m_variable_value.make_row(status_var);
169 m_row_exists= true;
170 }
171
172 int table_global_status
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)173 ::read_row_values(TABLE *table,
174 unsigned char *buf,
175 Field **fields,
176 bool read_all)
177 {
178 Field *f;
179
180 if (unlikely(! m_row_exists))
181 return HA_ERR_RECORD_DELETED;
182
183 /* Set the null bits */
184 assert(table->s->null_bytes == 1);
185 buf[0]= 0;
186
187 for (; (f= *fields) ; fields++)
188 {
189 if (read_all || bitmap_is_set(table->read_set, f->field_index))
190 {
191 switch(f->field_index)
192 {
193 case 0: /* VARIABLE_NAME */
194 set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
195 break;
196 case 1: /* VARIABLE_VALUE */
197 m_row.m_variable_value.set_field(f);
198 break;
199 default:
200 assert(false);
201 }
202 }
203 }
204
205 return 0;
206 }
207
208