~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to storage/perfschema/table_threads.cc

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
99
TABLE_FIELD_DEF
 
100
table_threads::m_field_def=
 
101
{ 14, field_types };
 
102
 
 
103
PFS_engine_table_share
 
104
table_threads::m_share=
 
105
{
 
106
  { C_STRING_WITH_LEN("threads") },
 
107
  &pfs_updatable_acl,
 
108
  &table_threads::create,
 
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
 
 
119
PFS_engine_table* table_threads::create()
 
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
 
 
146
  m_row.m_thread_internal_id= pfs->m_thread_internal_id;
 
147
  m_row.m_parent_thread_internal_id= pfs->m_parent_thread_internal_id;
 
148
  m_row.m_processlist_id= pfs->m_processlist_id;
 
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
 
 
155
  m_row.m_username_length= pfs->m_username_length;
 
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
 
 
161
  m_row.m_hostname_length= pfs->m_hostname_length;
 
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
 
 
191
  m_row.m_processlist_info_ptr= & pfs->m_processlist_info[0];
 
192
  m_row.m_processlist_info_length= pfs->m_processlist_info_length;
 
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
  {
 
224
    m_row.m_processlist_state_length= 0;
 
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
 
 
233
int table_threads::read_row_values(TABLE *table,
 
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 */
 
255
        set_field_ulonglong(f, m_row.m_thread_internal_id);
 
256
        break;
 
257
      case 1: /* NAME */
 
258
        set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
 
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)
 
268
          set_field_ulonglong(f, m_row.m_processlist_id);
 
269
        else
 
270
          f->set_null();
 
271
        break;
 
272
      case 4: /* PROCESSLIST_USER */
 
273
        if (m_row.m_username_length > 0)
 
274
          set_field_varchar_utf8(f, m_row.m_username,
 
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)
 
281
          set_field_varchar_utf8(f, m_row.m_hostname,
 
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)
 
288
          set_field_varchar_utf8(f, m_row.m_dbname,
 
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)
 
312
          set_field_varchar_utf8(f, m_row.m_processlist_state_ptr,
 
313
                                 m_row.m_processlist_state_length);
 
314
        else
 
315
          f->set_null();
 
316
        break;
 
317
      case 10: /* PROCESSLIST_INFO */
 
318
        if (m_row.m_processlist_info_length > 0)
 
319
          set_field_longtext_utf8(f, m_row.m_processlist_info_ptr,
 
320
                                  m_row.m_processlist_info_length);
 
321
        else
 
322
          f->set_null();
 
323
        break;
 
324
      case 11: /* PARENT_THREAD_ID */
 
325
        if (m_row.m_parent_thread_internal_id != 0)
 
326
          set_field_ulonglong(f, m_row.m_parent_thread_internal_id);
 
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
 
 
344
int table_threads::update_row_values(TABLE *table,
 
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