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, Fifth Floor, Boston, MA 02110-1335 USA */
22
23 /**
24 @file storage/perfschema/table_setup_objects.cc
25 Table SETUP_OBJECTS (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_pthread.h"
30 #include "pfs_instr.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "pfs_setup_object.h"
34 #include "table_setup_objects.h"
35 #include "table_helper.h"
36 #include "pfs_global.h"
37
38 THR_LOCK table_setup_objects::m_table_lock;
39
40 PFS_engine_table_share
41 table_setup_objects::m_share=
42 {
43 { C_STRING_WITH_LEN("setup_objects") },
44 &pfs_editable_acl,
45 table_setup_objects::create,
46 table_setup_objects::write_row,
47 table_setup_objects::delete_all_rows,
48 table_setup_objects::get_row_count,
49 1000, /* records */
50 sizeof(PFS_simple_index),
51 &m_table_lock,
52 { C_STRING_WITH_LEN("CREATE TABLE setup_objects("
53 "OBJECT_TYPE ENUM ('TABLE') not null default 'TABLE' comment 'Type of object to instrument. Currently, only TABLE, for base table.',"
54 "OBJECT_SCHEMA VARCHAR(64) default '%' comment 'Schema containing the object, either the literal or % for any schema.',"
55 "OBJECT_NAME VARCHAR(64) not null default '%' comment 'Name of the instrumented object, either the literal or % for any object.',"
56 "ENABLED ENUM ('YES', 'NO') not null default 'YES' comment 'Whether the object''s events are instrumented or not. Can be disabled, in which case monitoring is not enabled for those objects.',"
57 "TIMED ENUM ('YES', 'NO') not null default 'YES' comment 'Whether the object''s events are timed or not. Can be modified.')") }
58 };
59
update_derived_flags()60 int update_derived_flags()
61 {
62 PFS_thread *thread= PFS_thread::get_current_thread();
63 if (unlikely(thread == NULL))
64 return HA_ERR_OUT_OF_MEM;
65
66 update_table_share_derived_flags(thread);
67 update_table_derived_flags();
68 return 0;
69 }
70
create(void)71 PFS_engine_table* table_setup_objects::create(void)
72 {
73 return new table_setup_objects();
74 }
75
write_row(TABLE * table,const unsigned char * buf,Field ** fields)76 int table_setup_objects::write_row(TABLE *table, const unsigned char *buf,
77 Field **fields)
78 {
79 int result;
80 Field *f;
81 enum_object_type object_type= OBJECT_TYPE_TABLE;
82 String object_schema_data("%", 1, &my_charset_utf8_bin);
83 String object_name_data("%", 1, &my_charset_utf8_bin);
84 String *object_schema= &object_schema_data;
85 String *object_name= &object_name_data;
86 enum_yes_no enabled_value= ENUM_YES;
87 enum_yes_no timed_value= ENUM_YES;
88 bool enabled= true;
89 bool timed= true;
90
91 for (; (f= *fields) ; fields++)
92 {
93 if (bitmap_is_set(table->write_set, f->field_index))
94 {
95 switch(f->field_index)
96 {
97 case 0: /* OBJECT_TYPE */
98 object_type= (enum_object_type) get_field_enum(f);
99 break;
100 case 1: /* OBJECT_SCHEMA */
101 object_schema= get_field_varchar_utf8(f, &object_schema_data);
102 break;
103 case 2: /* OBJECT_NAME */
104 object_name= get_field_varchar_utf8(f, &object_name_data);
105 break;
106 case 3: /* ENABLED */
107 enabled_value= (enum_yes_no) get_field_enum(f);
108 break;
109 case 4: /* TIMED */
110 timed_value= (enum_yes_no) get_field_enum(f);
111 break;
112 default:
113 DBUG_ASSERT(false);
114 }
115 }
116 }
117
118 /* Reject illegal enum values in OBJECT_TYPE */
119 if (object_type != OBJECT_TYPE_TABLE)
120 return HA_ERR_NO_REFERENCED_ROW;
121
122 /* Reject illegal enum values in ENABLED */
123 if ((enabled_value != ENUM_YES) && (enabled_value != ENUM_NO))
124 return HA_ERR_NO_REFERENCED_ROW;
125
126 /* Reject illegal enum values in TIMED */
127 if ((timed_value != ENUM_YES) && (timed_value != ENUM_NO))
128 return HA_ERR_NO_REFERENCED_ROW;
129
130 enabled= (enabled_value == ENUM_YES) ? true : false;
131 timed= (timed_value == ENUM_YES) ? true : false;
132
133 result= insert_setup_object(object_type, object_schema, object_name,
134 enabled, timed);
135 if (result == 0)
136 result= update_derived_flags();
137 return result;
138 }
139
delete_all_rows(void)140 int table_setup_objects::delete_all_rows(void)
141 {
142 int result= reset_setup_object();
143 if (result == 0)
144 result= update_derived_flags();
145 return result;
146 }
147
get_row_count(void)148 ha_rows table_setup_objects::get_row_count(void)
149 {
150 return setup_object_count();
151 }
152
table_setup_objects()153 table_setup_objects::table_setup_objects()
154 : PFS_engine_table(&m_share, &m_pos),
155 m_row_exists(false), m_pos(0), m_next_pos(0)
156 {}
157
reset_position(void)158 void table_setup_objects::reset_position(void)
159 {
160 m_pos.m_index= 0;
161 m_next_pos.m_index= 0;
162 }
163
rnd_next(void)164 int table_setup_objects::rnd_next(void)
165 {
166 PFS_setup_object *pfs;
167
168 for (m_pos.set_at(&m_next_pos);
169 m_pos.m_index < setup_object_max;
170 m_pos.next())
171 {
172 pfs= &setup_object_array[m_pos.m_index];
173 if (pfs->m_lock.is_populated())
174 {
175 make_row(pfs);
176 m_next_pos.set_after(&m_pos);
177 return 0;
178 }
179 }
180
181 return HA_ERR_END_OF_FILE;
182 }
183
rnd_pos(const void * pos)184 int table_setup_objects::rnd_pos(const void *pos)
185 {
186 PFS_setup_object *pfs;
187
188 set_position(pos);
189
190 DBUG_ASSERT(m_pos.m_index < setup_object_max);
191 pfs= &setup_object_array[m_pos.m_index];
192 if (pfs->m_lock.is_populated())
193 {
194 make_row(pfs);
195 return 0;
196 }
197
198 return HA_ERR_RECORD_DELETED;
199 }
200
make_row(PFS_setup_object * pfs)201 void table_setup_objects::make_row(PFS_setup_object *pfs)
202 {
203 pfs_lock lock;
204
205 m_row_exists= false;
206
207 pfs->m_lock.begin_optimistic_lock(&lock);
208
209 m_row.m_object_type= pfs->get_object_type();
210 memcpy(m_row.m_schema_name, pfs->m_schema_name, pfs->m_schema_name_length);
211 m_row.m_schema_name_length= pfs->m_schema_name_length;
212 memcpy(m_row.m_object_name, pfs->m_object_name, pfs->m_object_name_length);
213 m_row.m_object_name_length= pfs->m_object_name_length;
214 m_row.m_enabled_ptr= &pfs->m_enabled;
215 m_row.m_timed_ptr= &pfs->m_timed;
216
217 if (pfs->m_lock.end_optimistic_lock(&lock))
218 m_row_exists= true;
219 }
220
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)221 int table_setup_objects::read_row_values(TABLE *table,
222 unsigned char *buf,
223 Field **fields,
224 bool read_all)
225 {
226 Field *f;
227
228 if (unlikely(! m_row_exists))
229 return HA_ERR_RECORD_DELETED;
230
231 /* Set the null bits */
232 DBUG_ASSERT(table->s->null_bytes == 1);
233 buf[0]= 0;
234
235 for (; (f= *fields) ; fields++)
236 {
237 if (read_all || bitmap_is_set(table->read_set, f->field_index))
238 {
239 switch(f->field_index)
240 {
241 case 0: /* OBJECT_TYPE */
242 set_field_enum(f, m_row.m_object_type);
243 break;
244 case 1: /* OBJECT_SCHEMA */
245 if (m_row.m_schema_name_length)
246 set_field_varchar_utf8(f, m_row.m_schema_name,
247 m_row.m_schema_name_length);
248 else
249 f->set_null();
250 break;
251 case 2: /* OBJECT_NAME */
252 if (m_row.m_object_name_length)
253 set_field_varchar_utf8(f, m_row.m_object_name,
254 m_row.m_object_name_length);
255 else
256 f->set_null();
257 break;
258 case 3: /* ENABLED */
259 set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
260 break;
261 case 4: /* TIMED */
262 set_field_enum(f, (*m_row.m_timed_ptr) ? ENUM_YES : ENUM_NO);
263 break;
264 default:
265 DBUG_ASSERT(false);
266 }
267 }
268 }
269
270 return 0;
271 }
272
update_row_values(TABLE * table,const unsigned char *,const unsigned char *,Field ** fields)273 int table_setup_objects::update_row_values(TABLE *table,
274 const unsigned char *,
275 const unsigned char *,
276 Field **fields)
277 {
278 int result;
279 Field *f;
280 enum_yes_no value;
281
282 for (; (f= *fields) ; fields++)
283 {
284 if (bitmap_is_set(table->write_set, f->field_index))
285 {
286 switch(f->field_index)
287 {
288 case 0: /* OBJECT_TYPE */
289 case 1: /* OBJECT_SCHEMA */
290 case 2: /* OBJECT_NAME */
291 return HA_ERR_WRONG_COMMAND;
292 case 3: /* ENABLED */
293 value= (enum_yes_no) get_field_enum(f);
294 /* Reject illegal enum values in ENABLED */
295 if ((value != ENUM_YES) && (value != ENUM_NO))
296 return HA_ERR_NO_REFERENCED_ROW;
297 *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
298 break;
299 case 4: /* TIMED */
300 value= (enum_yes_no) get_field_enum(f);
301 /* Reject illegal enum values in TIMED */
302 if ((value != ENUM_YES) && (value != ENUM_NO))
303 return HA_ERR_NO_REFERENCED_ROW;
304 *m_row.m_timed_ptr= (value == ENUM_YES) ? true : false;
305 break;
306 default:
307 DBUG_ASSERT(false);
308 }
309 }
310 }
311
312 result= update_derived_flags();
313 return result;
314 }
315
delete_row_values(TABLE * table,const unsigned char * buf,Field ** fields)316 int table_setup_objects::delete_row_values(TABLE *table,
317 const unsigned char *buf,
318 Field **fields)
319 {
320 DBUG_ASSERT(m_row_exists);
321
322 CHARSET_INFO *cs= &my_charset_utf8_bin;
323 enum_object_type object_type= OBJECT_TYPE_TABLE;
324 String object_schema(m_row.m_schema_name, m_row.m_schema_name_length, cs);
325 String object_name(m_row.m_object_name, m_row.m_object_name_length, cs);
326
327 int result= delete_setup_object(object_type, &object_schema, &object_name);
328
329 if (result == 0)
330 result= update_derived_flags();
331 return result;
332 }
333
334