MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
table_threads.cc
1 /* Copyright (c) 2008, 2013, 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 
16 #include "my_global.h"
17 #include "my_pthread.h"
18 #include "table_threads.h"
19 #include "sql_parse.h"
20 #include "pfs_instr_class.h"
21 #include "pfs_instr.h"
22 
23 THR_LOCK table_threads::m_table_lock;
24 
25 static const TABLE_FIELD_TYPE field_types[]=
26 {
27  {
28  { C_STRING_WITH_LEN("THREAD_ID") },
29  { C_STRING_WITH_LEN("bigint(20)") },
30  { NULL, 0}
31  },
32  {
33  { C_STRING_WITH_LEN("NAME") },
34  { C_STRING_WITH_LEN("varchar(128)") },
35  { NULL, 0}
36  },
37  {
38  { C_STRING_WITH_LEN("TYPE") },
39  { C_STRING_WITH_LEN("varchar(10)") },
40  { NULL, 0}
41  },
42  {
43  { C_STRING_WITH_LEN("PROCESSLIST_ID") },
44  { C_STRING_WITH_LEN("bigint(20)") },
45  { NULL, 0}
46  },
47  {
48  { C_STRING_WITH_LEN("PROCESSLIST_USER") },
49  { C_STRING_WITH_LEN("varchar(16)") },
50  { NULL, 0}
51  },
52  {
53  { C_STRING_WITH_LEN("PROCESSLIST_HOST") },
54  { C_STRING_WITH_LEN("varchar(60)") },
55  { NULL, 0}
56  },
57  {
58  { C_STRING_WITH_LEN("PROCESSLIST_DB") },
59  { C_STRING_WITH_LEN("varchar(64)") },
60  { NULL, 0}
61  },
62  {
63  { C_STRING_WITH_LEN("PROCESSLIST_COMMAND") },
64  { C_STRING_WITH_LEN("varchar(16)") },
65  { NULL, 0}
66  },
67  {
68  { C_STRING_WITH_LEN("PROCESSLIST_TIME") },
69  { C_STRING_WITH_LEN("bigint(20)") },
70  { NULL, 0}
71  },
72  {
73  { C_STRING_WITH_LEN("PROCESSLIST_STATE") },
74  { C_STRING_WITH_LEN("varchar(64)") },
75  { NULL, 0}
76  },
77  {
78  { C_STRING_WITH_LEN("PROCESSLIST_INFO") },
79  { C_STRING_WITH_LEN("longtext") },
80  { NULL, 0}
81  },
82  {
83  { C_STRING_WITH_LEN("PARENT_THREAD_ID") },
84  { C_STRING_WITH_LEN("bigint(20)") },
85  { NULL, 0}
86  },
87  {
88  { C_STRING_WITH_LEN("ROLE") },
89  { C_STRING_WITH_LEN("varchar(64)") },
90  { NULL, 0}
91  },
92  {
93  { C_STRING_WITH_LEN("INSTRUMENTED") },
94  { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
95  { NULL, 0}
96  }
97 };
98 
100 table_threads::m_field_def=
101 { 14, field_types };
102 
105 {
106  { C_STRING_WITH_LEN("threads") },
109  NULL, /* write_row */
110  NULL, /* delete_all_rows */
111  NULL, /* get_row_count */
112  1000, /* records */
113  sizeof(PFS_simple_index), /* ref length */
114  &m_table_lock,
115  &m_field_def,
116  false /* checked */
117 };
118 
120 {
121  return new table_threads();
122 }
123 
124 table_threads::table_threads()
125  : cursor_by_thread(& m_share),
126  m_row_exists(false)
127 {}
128 
129 void table_threads::make_row(PFS_thread *pfs)
130 {
131  pfs_lock lock;
132  pfs_lock session_lock;
133  pfs_lock stmt_lock;
134  PFS_stage_class *stage_class;
135  PFS_thread_class *safe_class;
136 
137  m_row_exists= false;
138 
139  /* Protect this reader against thread termination */
140  pfs->m_lock.begin_optimistic_lock(&lock);
141 
142  safe_class= sanitize_thread_class(pfs->m_class);
143  if (unlikely(safe_class == NULL))
144  return;
145 
149  m_row.m_name= safe_class->m_name;
150  m_row.m_name_length= safe_class->m_name_length;
151 
152  /* Protect this reader against session attribute changes */
153  pfs->m_session_lock.begin_optimistic_lock(&session_lock);
154 
156  if (unlikely(m_row.m_username_length > sizeof(m_row.m_username)))
157  return;
158  if (m_row.m_username_length != 0)
159  memcpy(m_row.m_username, pfs->m_username, m_row.m_username_length);
160 
162  if (unlikely(m_row.m_hostname_length > sizeof(m_row.m_hostname)))
163  return;
164  if (m_row.m_hostname_length != 0)
165  memcpy(m_row.m_hostname, pfs->m_hostname, m_row.m_hostname_length);
166 
167  if (! pfs->m_session_lock.end_optimistic_lock(& session_lock))
168  {
169  /*
170  One of the columns:
171  - PROCESSLIST_USER
172  - PROCESSLIST_HOST
173  is being updated.
174  Do not discard the entire row.
175  Do not loop waiting for a stable value.
176  Just return NULL values.
177  */
178  m_row.m_username_length= 0;
179  m_row.m_hostname_length= 0;
180  }
181 
182  /* Protect this reader against statement attributes changes */
183  pfs->m_stmt_lock.begin_optimistic_lock(&stmt_lock);
184 
185  m_row.m_dbname_length= pfs->m_dbname_length;
186  if (unlikely(m_row.m_dbname_length > sizeof(m_row.m_dbname)))
187  return;
188  if (m_row.m_dbname_length != 0)
189  memcpy(m_row.m_dbname, pfs->m_dbname, m_row.m_dbname_length);
190 
193 
194  if (! pfs->m_stmt_lock.end_optimistic_lock(& stmt_lock))
195  {
196  /*
197  One of the columns:
198  - PROCESSLIST_DB
199  - PROCESSLIST_INFO
200  is being updated.
201  Do not discard the entire row.
202  Do not loop waiting for a stable value.
203  Just return NULL values.
204  */
205  m_row.m_dbname_length= 0;
206  m_row.m_processlist_info_length= 0;
207  }
208 
209  /* Dirty read, sanitize the command. */
210  m_row.m_command= pfs->m_command;
211  if ((m_row.m_command < 0) || (m_row.m_command > COM_END))
212  m_row.m_command= COM_END;
213 
214  m_row.m_start_time= pfs->m_start_time;
215 
216  stage_class= find_stage_class(pfs->m_stage);
217  if (stage_class != NULL)
218  {
219  m_row.m_processlist_state_ptr= stage_class->m_name + stage_class->m_prefix_length;
220  m_row.m_processlist_state_length= stage_class->m_name_length - stage_class->m_prefix_length;
221  }
222  else
223  {
225  }
226 
227  m_row.m_enabled_ptr= &pfs->m_enabled;
228 
229  if (pfs->m_lock.end_optimistic_lock(& lock))
230  m_row_exists= true;
231 }
232 
234  unsigned char *buf,
235  Field **fields,
236  bool read_all)
237 {
238  Field *f;
239 
240  if (unlikely(! m_row_exists))
241  return HA_ERR_RECORD_DELETED;
242 
243  /* Set the null bits */
244  DBUG_ASSERT(table->s->null_bytes == 2);
245  buf[0]= 0;
246  buf[1]= 0;
247 
248  for (; (f= *fields) ; fields++)
249  {
250  if (read_all || bitmap_is_set(table->read_set, f->field_index))
251  {
252  switch(f->field_index)
253  {
254  case 0: /* THREAD_ID */
256  break;
257  case 1: /* NAME */
259  break;
260  case 2: /* TYPE */
261  if (m_row.m_processlist_id != 0)
262  set_field_varchar_utf8(f, "FOREGROUND", 10);
263  else
264  set_field_varchar_utf8(f, "BACKGROUND", 10);
265  break;
266  case 3: /* PROCESSLIST_ID */
267  if (m_row.m_processlist_id != 0)
269  else
270  f->set_null();
271  break;
272  case 4: /* PROCESSLIST_USER */
273  if (m_row.m_username_length > 0)
275  m_row.m_username_length);
276  else
277  f->set_null();
278  break;
279  case 5: /* PROCESSLIST_HOST */
280  if (m_row.m_hostname_length > 0)
282  m_row.m_hostname_length);
283  else
284  f->set_null();
285  break;
286  case 6: /* PROCESSLIST_DB */
287  if (m_row.m_dbname_length > 0)
289  m_row.m_dbname_length);
290  else
291  f->set_null();
292  break;
293  case 7: /* PROCESSLIST_COMMAND */
294  if (m_row.m_processlist_id != 0)
295  set_field_varchar_utf8(f, command_name[m_row.m_command].str,
296  command_name[m_row.m_command].length);
297  else
298  f->set_null();
299  break;
300  case 8: /* PROCESSLIST_TIME */
301  if (m_row.m_start_time)
302  {
303  time_t now= my_time(0);
304  ulonglong elapsed= (now > m_row.m_start_time ? now - m_row.m_start_time : 0);
305  set_field_ulonglong(f, elapsed);
306  }
307  else
308  f->set_null();
309  break;
310  case 9: /* PROCESSLIST_STATE */
311  if (m_row.m_processlist_state_length > 0)
314  else
315  f->set_null();
316  break;
317  case 10: /* PROCESSLIST_INFO */
318  if (m_row.m_processlist_info_length > 0)
321  else
322  f->set_null();
323  break;
324  case 11: /* PARENT_THREAD_ID */
325  if (m_row.m_parent_thread_internal_id != 0)
327  else
328  f->set_null();
329  break;
330  case 12: /* ROLE */
331  f->set_null();
332  break;
333  case 13: /* INSTRUMENTED */
334  set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
335  break;
336  default:
337  DBUG_ASSERT(false);
338  }
339  }
340  }
341  return 0;
342 }
343 
345  const unsigned char *old_buf,
346  unsigned char *new_buf,
347  Field **fields)
348 {
349  Field *f;
350  enum_yes_no value;
351 
352  for (; (f= *fields) ; fields++)
353  {
354  if (bitmap_is_set(table->write_set, f->field_index))
355  {
356  switch(f->field_index)
357  {
358  case 0: /* THREAD_ID */
359  case 1: /* NAME */
360  case 2: /* TYPE */
361  case 3: /* PROCESSLIST_ID */
362  case 4: /* PROCESSLIST_USER */
363  case 5: /* PROCESSLIST_HOST */
364  case 6: /* PROCESSLIST_DB */
365  case 7: /* PROCESSLIST_COMMAND */
366  case 8: /* PROCESSLIST_TIME */
367  case 9: /* PROCESSLIST_STATE */
368  case 10: /* PROCESSLIST_INFO */
369  case 11: /* PARENT_THREAD_ID */
370  case 12: /* ROLE */
371  return HA_ERR_WRONG_COMMAND;
372  case 13: /* INSTRUMENTED */
373  value= (enum_yes_no) get_field_enum(f);
374  *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
375  break;
376  default:
377  DBUG_ASSERT(false);
378  }
379  }
380  }
381  return 0;
382 }
383