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_session_status.cc
25 Table SESSION_STATUS (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "table_session_status.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_session_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_session_status::m_field_def=
54 { 2, field_types };
55
56 PFS_engine_table_share
57 table_session_status::m_share=
58 {
59 { C_STRING_WITH_LEN("session_status") },
60 &pfs_readonly_world_acl,
61 table_session_status::create,
62 NULL, /* write_row */
63 NULL, /* delete_all_rows */
64 table_session_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_session_status::create(void)
74 {
75 return new table_session_status();
76 }
77
get_row_count(void)78 ha_rows table_session_status::get_row_count(void)
79 {
80 mysql_mutex_lock(&LOCK_status);
81 ha_rows status_var_count= all_status_vars.size();
82 mysql_mutex_unlock(&LOCK_status);
83 return status_var_count;
84 }
85
table_session_status()86 table_session_status::table_session_status()
87 : PFS_engine_table(&m_share, &m_pos),
88 m_status_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
89 {}
90
reset_position(void)91 void table_session_status::reset_position(void)
92 {
93 m_pos.m_index = 0;
94 m_next_pos.m_index = 0;
95 }
96
rnd_init(bool scan)97 int table_session_status::rnd_init(bool scan)
98 {
99 /* Build a cache of all status variables for this thread. */
100 m_status_cache.materialize_all(current_thd);
101
102 /* Record the current number of status variables to detect subsequent changes. */
103 ulonglong status_version= m_status_cache.get_status_array_version();
104
105 /*
106 The table context holds the current version of the global status array.
107 If scan == true, then allocate a new context from mem_root and store in TLS.
108 If scan == false, then restore from TLS.
109 */
110 m_context= (table_session_status_context *)current_thd->alloc(sizeof(table_session_status_context));
111 new(m_context) table_session_status_context(status_version, !scan);
112 return 0;
113 }
114
rnd_next(void)115 int table_session_status::rnd_next(void)
116 {
117 for (m_pos.set_at(&m_next_pos);
118 m_pos.m_index < m_status_cache.size();
119 m_pos.next())
120 {
121 if (m_status_cache.is_materialized())
122 {
123 const Status_variable *stat_var= m_status_cache.get(m_pos.m_index);
124 if (stat_var != NULL)
125 {
126 make_row(stat_var);
127 m_next_pos.set_after(&m_pos);
128 return 0;
129 }
130 }
131 }
132 return HA_ERR_END_OF_FILE;
133 }
134
135 int
rnd_pos(const void * pos)136 table_session_status::rnd_pos(const void *pos)
137 {
138 /* If global status array has changed, do nothing. */ // TODO: warning
139 if (!m_context->versions_match())
140 return HA_ERR_RECORD_DELETED;
141
142 set_position(pos);
143 assert(m_pos.m_index < m_status_cache.size());
144
145 if (m_status_cache.is_materialized())
146 {
147 const Status_variable *stat_var= m_status_cache.get(m_pos.m_index);
148 if (stat_var != NULL)
149 {
150 make_row(stat_var);
151 return 0;
152 }
153 }
154
155 return HA_ERR_RECORD_DELETED;
156 }
157
158 void table_session_status
make_row(const Status_variable * status_var)159 ::make_row(const Status_variable *status_var)
160 {
161 m_row_exists= false;
162 m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
163 m_row.m_variable_value.make_row(status_var);
164 m_row_exists= true;
165 }
166
167 int table_session_status
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)168 ::read_row_values(TABLE *table,
169 unsigned char *buf,
170 Field **fields,
171 bool read_all)
172 {
173 Field *f;
174
175 if (unlikely(!m_row_exists))
176 return HA_ERR_RECORD_DELETED;
177
178 /* Set the null bits */
179 assert(table->s->null_bytes == 1);
180 buf[0]= 0;
181
182 for (; (f= *fields) ; fields++)
183 {
184 if (read_all || bitmap_is_set(table->read_set, f->field_index))
185 {
186 switch(f->field_index)
187 {
188 case 0: /* VARIABLE_NAME */
189 set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
190 break;
191 case 1: /* VARIABLE_VALUE */
192 m_row.m_variable_value.set_field(f);
193 break;
194 default:
195 assert(false);
196 }
197 }
198 }
199
200 return 0;
201 }
202
203