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