MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ha_perfschema.cc
Go to the documentation of this file.
1 /* Copyright (c) 2008, 2011, 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 as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
21 #include "my_global.h"
22 #include "my_pthread.h"
23 #include "my_atomic.h"
24 #include "sql_plugin.h"
25 #include "mysql/plugin.h"
26 #include "ha_perfschema.h"
27 #include "pfs_engine_table.h"
28 #include "pfs_column_values.h"
29 #include "pfs_instr_class.h"
30 #include "pfs_instr.h"
31 #include "pfs_account.h"
32 #include "pfs_host.h"
33 #include "pfs_user.h"
34 #include "pfs_account.h"
35 
36 #ifdef MY_ATOMIC_MODE_DUMMY
37 /*
38  The performance schema can can not function with MY_ATOMIC_MODE_DUMMY,
39  a fully functional implementation of MY_ATOMIC should be used instead.
40  If the build fails with this error message:
41  - either use a different ./configure --with-atomic-ops option
42  - or do not build with the performance schema.
43 */
44 #error "The performance schema needs a functional MY_ATOMIC implementation."
45 #endif
46 
47 handlerton *pfs_hton= NULL;
48 
49 static handler* pfs_create_handler(handlerton *hton,
51  MEM_ROOT *mem_root)
52 {
53  return new (mem_root) ha_perfschema(hton, table);
54 }
55 
56 static int compare_database_names(const char *name1, const char *name2)
57 {
58  if (lower_case_table_names)
59  return strcasecmp(name1, name2);
60  return strcmp(name1, name2);
61 }
62 
63 static const PFS_engine_table_share*
64 find_table_share(const char *db, const char *name)
65 {
66  DBUG_ENTER("find_table_share");
67 
68  if (compare_database_names(db, PERFORMANCE_SCHEMA_str.str) != 0)
69  DBUG_RETURN(NULL);
70 
71  const PFS_engine_table_share* result;
73  DBUG_RETURN(result);
74 }
75 
76 static int pfs_init_func(void *p)
77 {
78  DBUG_ENTER("pfs_init_func");
79 
80  pfs_hton= reinterpret_cast<handlerton *> (p);
81 
82  pfs_hton->state= SHOW_OPTION_YES;
83  pfs_hton->create= pfs_create_handler;
84  pfs_hton->show_status= pfs_show_status;
85  pfs_hton->flags= HTON_ALTER_NOT_SUPPORTED |
86  HTON_TEMPORARY_NOT_SUPPORTED |
87  HTON_NO_PARTITION |
88  HTON_NO_BINLOG_ROW_OPT;
89 
90  /*
91  As long as the server implementation keeps using legacy_db_type,
92  as for example in mysql_truncate(),
93  we can not rely on the fact that different mysqld process will assign
94  consistently the same legacy_db_type for a given storage engine name.
95  In particular, using different --loose-skip-xxx options between
96  ./mysqld --bootstrap
97  ./mysqld
98  creates bogus .frm forms when bootstrapping the performance schema,
99  if we rely on ha_initialize_handlerton to assign a really dynamic value.
100  To fix this, a dedicated DB_TYPE is officially assigned to
101  the performance schema. See Bug#43039.
102  */
103  pfs_hton->db_type= DB_TYPE_PERFORMANCE_SCHEMA;
104 
106 
107  DBUG_RETURN(0);
108 }
109 
110 static int pfs_done_func(void *p)
111 {
112  DBUG_ENTER("pfs_done_func");
113 
114  pfs_hton= NULL;
115 
117 
118  DBUG_RETURN(0);
119 }
120 
121 static struct st_mysql_show_var pfs_status_vars[]=
122 {
123  {"Performance_schema_mutex_classes_lost",
124  (char*) &mutex_class_lost, SHOW_LONG_NOFLUSH},
125  {"Performance_schema_rwlock_classes_lost",
126  (char*) &rwlock_class_lost, SHOW_LONG_NOFLUSH},
127  {"Performance_schema_cond_classes_lost",
128  (char*) &cond_class_lost, SHOW_LONG_NOFLUSH},
129  {"Performance_schema_thread_classes_lost",
130  (char*) &thread_class_lost, SHOW_LONG_NOFLUSH},
131  {"Performance_schema_file_classes_lost",
132  (char*) &file_class_lost, SHOW_LONG_NOFLUSH},
133  {"Performance_schema_socket_classes_lost",
134  (char*) &socket_class_lost, SHOW_LONG_NOFLUSH},
135  {"Performance_schema_mutex_instances_lost",
136  (char*) &mutex_lost, SHOW_LONG},
137  {"Performance_schema_rwlock_instances_lost",
138  (char*) &rwlock_lost, SHOW_LONG},
139  {"Performance_schema_cond_instances_lost",
140  (char*) &cond_lost, SHOW_LONG},
141  {"Performance_schema_thread_instances_lost",
142  (char*) &thread_lost, SHOW_LONG},
143  {"Performance_schema_file_instances_lost",
144  (char*) &file_lost, SHOW_LONG},
145  {"Performance_schema_file_handles_lost",
146  (char*) &file_handle_lost, SHOW_LONG},
147  {"Performance_schema_socket_instances_lost",
148  (char*) &socket_lost, SHOW_LONG},
149  {"Performance_schema_locker_lost",
150  (char*) &locker_lost, SHOW_LONG},
151  /* table shares, can be flushed */
152  {"Performance_schema_table_instances_lost",
153  (char*) &table_share_lost, SHOW_LONG},
154  /* table handles, can be flushed */
155  {"Performance_schema_table_handles_lost",
156  (char*) &table_lost, SHOW_LONG},
157  {"Performance_schema_hosts_lost",
158  (char*) &host_lost, SHOW_LONG},
159  {"Performance_schema_users_lost",
160  (char*) &user_lost, SHOW_LONG},
161  {"Performance_schema_accounts_lost",
162  (char*) &account_lost, SHOW_LONG},
163  {"Performance_schema_stage_classes_lost",
164  (char*) &stage_class_lost, SHOW_LONG},
165  {"Performance_schema_statement_classes_lost",
166  (char*) &statement_class_lost, SHOW_LONG},
167  {"Performance_schema_digest_lost",
168  (char*) &digest_lost, SHOW_LONG},
169  {"Performance_schema_session_connect_attrs_lost",
170  (char*) &session_connect_attrs_lost, SHOW_LONG},
171  {NullS, NullS, SHOW_LONG}
172 };
173 
174 struct st_mysql_storage_engine pfs_storage_engine=
175 { MYSQL_HANDLERTON_INTERFACE_VERSION };
176 
177 const char* pfs_engine_name= "PERFORMANCE_SCHEMA";
178 
179 mysql_declare_plugin(perfschema)
180 {
181  MYSQL_STORAGE_ENGINE_PLUGIN,
182  &pfs_storage_engine,
184  "Marc Alff, Oracle", /* Formerly Sun Microsystems, formerly MySQL */
185  "Performance Schema",
186  PLUGIN_LICENSE_GPL,
187  pfs_init_func, /* Plugin Init */
188  pfs_done_func, /* Plugin Deinit */
189  0x0001 /* 0.1 */,
190  pfs_status_vars, /* status variables */
191  NULL, /* system variables */
192  NULL, /* config options */
193  0, /* flags */
194 }
195 mysql_declare_plugin_end;
196 
198  : handler(hton, share), m_table_share(NULL), m_table(NULL)
199 {}
200 
201 ha_perfschema::~ha_perfschema()
202 {}
203 
204 static const char *ha_pfs_exts[]= {
205  NullS
206 };
207 
208 const char **ha_perfschema::bas_ext() const
209 {
210  return ha_pfs_exts;
211 }
212 
213 int ha_perfschema::open(const char *name, int mode, uint test_if_locked)
214 {
215  DBUG_ENTER("ha_perfschema::open");
216 
217  m_table_share= find_table_share(table_share->db.str,
218  table_share->table_name.str);
219  if (! m_table_share)
220  DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
221 
222  thr_lock_data_init(m_table_share->m_thr_lock_ptr, &m_thr_lock, NULL);
223  ref_length= m_table_share->m_ref_length;
224 
225  DBUG_RETURN(0);
226 }
227 
229 {
230  DBUG_ENTER("ha_perfschema::close");
231  m_table_share= NULL;
232  delete m_table;
233  m_table= NULL;
234 
235  DBUG_RETURN(0);
236 }
237 
239 {
240  int result;
241 
242  DBUG_ENTER("ha_perfschema::write_row");
243  if (!pfs_initialized)
244  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
245 
246  DBUG_ASSERT(m_table_share);
247  ha_statistic_increment(&SSV::ha_write_count);
248  result= m_table_share->write_row(table, buf, table->field);
249  DBUG_RETURN(result);
250 }
251 
253 {
254  /*
255  This is also called in case of row based replication,
256  see TABLE::mark_columns_needed_for_update().
257  Add all columns to the read set, but do not touch the write set,
258  as some columns in the SETUP_ tables are not writable.
259  */
260  table->column_bitmaps_set_no_signal(&table->s->all_set, table->write_set);
261 }
262 
263 int ha_perfschema::update_row(const uchar *old_data, uchar *new_data)
264 {
265  DBUG_ENTER("ha_perfschema::update_row");
266  if (!pfs_initialized)
267  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
268 
269  DBUG_ASSERT(m_table);
270  ha_statistic_increment(&SSV::ha_update_count);
271  int result= m_table->update_row(table, old_data, new_data, table->field);
272  DBUG_RETURN(result);
273 }
274 
276 {
277  DBUG_ENTER("ha_perfschema::delete_row");
278  if (!pfs_initialized)
279  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
280 
281  DBUG_ASSERT(m_table);
282  ha_statistic_increment(&SSV::ha_delete_count);
283  int result= m_table->delete_row(table, buf, table->field);
284  DBUG_RETURN(result);
285 }
286 
288 {
289  int result;
290  DBUG_ENTER("ha_perfschema::rnd_init");
291 
292  DBUG_ASSERT(m_table_share);
293  DBUG_ASSERT(m_table_share->m_open_table != NULL);
294 
295  stats.records= 0;
296  if (m_table == NULL)
297  m_table= m_table_share->m_open_table();
298  else
299  m_table->reset_position();
300 
301  if (m_table != NULL)
302  m_table->rnd_init(scan);
303 
304  result= m_table ? 0 : HA_ERR_OUT_OF_MEM;
305  DBUG_RETURN(result);
306 }
307 
309 {
310  DBUG_ENTER("ha_perfschema::rnd_end");
311  DBUG_ASSERT(m_table);
312  delete m_table;
313  m_table= NULL;
314  DBUG_RETURN(0);
315 }
316 
318 {
319  DBUG_ENTER("ha_perfschema::rnd_next");
320  if (!pfs_initialized)
321  DBUG_RETURN(HA_ERR_END_OF_FILE);
322 
323  DBUG_ASSERT(m_table);
324  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
325 
326  int result= m_table->rnd_next();
327  if (result == 0)
328  {
329  result= m_table->read_row(table, buf, table->field);
330  if (result == 0)
331  stats.records++;
332  }
333  DBUG_RETURN(result);
334 }
335 
336 void ha_perfschema::position(const uchar *record)
337 {
338  DBUG_ENTER("ha_perfschema::position");
339 
340  DBUG_ASSERT(m_table);
341  m_table->get_position(ref);
342  DBUG_VOID_RETURN;
343 }
344 
345 int ha_perfschema::rnd_pos(uchar *buf, uchar *pos)
346 {
347  DBUG_ENTER("ha_perfschema::rnd_pos");
348  if (!pfs_initialized)
349  DBUG_RETURN(HA_ERR_END_OF_FILE);
350 
351  DBUG_ASSERT(m_table);
352  ha_statistic_increment(&SSV::ha_read_rnd_count);
353  int result= m_table->rnd_pos(pos);
354  if (result == 0)
355  result= m_table->read_row(table, buf, table->field);
356  DBUG_RETURN(result);
357 }
358 
359 int ha_perfschema::info(uint flag)
360 {
361  DBUG_ENTER("ha_perfschema::info");
362  DBUG_ASSERT(m_table_share);
363  if (flag & HA_STATUS_VARIABLE)
364  stats.records= m_table_share->get_row_count();
365  if (flag & HA_STATUS_CONST)
366  ref_length= m_table_share->m_ref_length;
367  DBUG_RETURN(0);
368 }
369 
371 {
372  int result;
373 
374  DBUG_ENTER("ha_perfschema::delete_all_rows");
375  if (!pfs_initialized)
376  DBUG_RETURN(0);
377 
378  DBUG_ASSERT(m_table_share);
379  if (m_table_share->m_delete_all_rows)
380  result= m_table_share->m_delete_all_rows();
381  else
382  {
383  result= HA_ERR_WRONG_COMMAND;
384  }
385  DBUG_RETURN(result);
386 }
387 
389 {
390  return delete_all_rows();
391 }
392 
394  THR_LOCK_DATA **to,
395  enum thr_lock_type lock_type)
396 {
397  if (lock_type != TL_IGNORE && m_thr_lock.type == TL_UNLOCK)
398  m_thr_lock.type= lock_type;
399  *to++= &m_thr_lock;
400  m_thr_lock.m_psi= m_psi;
401  return to;
402 }
403 
404 int ha_perfschema::delete_table(const char *name)
405 {
406  DBUG_ENTER("ha_perfschema::delete_table");
407  DBUG_RETURN(0);
408 }
409 
410 int ha_perfschema::rename_table(const char * from, const char * to)
411 {
412  DBUG_ENTER("ha_perfschema::rename_table ");
413  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
414 }
415 
416 int ha_perfschema::create(const char *name, TABLE *table_arg,
417  HA_CREATE_INFO *create_info)
418 {
419  DBUG_ENTER("ha_perfschema::create");
420  DBUG_ASSERT(table_arg);
421  DBUG_ASSERT(table_arg->s);
422  if (find_table_share(table_arg->s->db.str,
423  table_arg->s->table_name.str))
424  {
425  /*
426  Attempting to create a known performance schema table.
427  Allowing the create, to create .FRM files,
428  for the initial database install, and mysql_upgrade.
429  This should fail once .FRM are removed.
430  */
431  DBUG_RETURN(0);
432  }
433  /*
434  This is not a general purpose engine.
435  Failure to CREATE TABLE is the expected result.
436  */
437  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
438 }
439 
440 void ha_perfschema::print_error(int error, myf errflag)
441 {
442  switch (error)
443  {
444  case HA_ERR_TABLE_NEEDS_UPGRADE:
445  /*
446  The error message for ER_TABLE_NEEDS_UPGRADE refers to REPAIR table,
447  which does not apply to performance schema tables.
448  */
449  my_error(ER_WRONG_NATIVE_TABLE_STRUCTURE, MYF(0),
450  table_share->db.str, table_share->table_name.str);
451  break;
452  case HA_ERR_WRONG_COMMAND:
453  /*
454  The performance schema is not a general purpose storage engine,
455  some operations are not supported, by design.
456  We do not want to print "Command not supported",
457  which gives the impression that a command implementation is missing,
458  and that the failure should be considered a bug.
459  We print "Invalid performance_schema usage." instead,
460  to emphasise that the operation attempted is not meant to be legal,
461  and that the failure returned is indeed the expected result.
462  */
463  my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
464  break;
465  default:
466  handler::print_error(error, errflag);
467  break;
468  }
469 }
470