~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/handler/data_dictionary.cc

  • Committer: Brian Aker
  • Date: 2010-03-01 17:04:10 UTC
  • mfrom: (1309.1.23 build)
  • Revision ID: brian@gaz-20100301170410-ph8eb1hdf9rqks51
Merge up build to staging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
5
This program is free software; you can redistribute it and/or modify it under
 
6
the terms of the GNU General Public License as published by the Free Software
 
7
Foundation; version 2 of the License.
 
8
 
 
9
This program is distributed in the hope that it will be useful, but WITHOUT
 
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
12
 
 
13
You should have received a copy of the GNU General Public License along with
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include "data_dictionary.h"
 
22
 
 
23
#include "drizzled/current_session.h"
 
24
 
 
25
extern "C" {
 
26
#include "trx0i_s.h"
 
27
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
 
28
#include "buf0buddy.h" /* for i_s_cmpmem */
 
29
#include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
 
30
#include "ha_prototypes.h" /* for innobase_convert_name() */
 
31
#include "srv0start.h" /* for srv_was_started */
 
32
}
 
33
#include "handler0vars.h"
 
34
 
 
35
using namespace drizzled;
 
36
 
 
37
/*
 
38
 * Fill the dynamic table data_dictionary.INNODB_CMP and INNODB_CMP_RESET
 
39
 *
 
40
 */
 
41
CmpTool::CmpTool(bool in_reset) :
 
42
  plugin::TableFunction("DATA_DICTIONARY", in_reset ? "INNODB_CMP_RESET" : "INNODB_CMP"),
 
43
  outer_reset(in_reset)
 
44
{
 
45
  add_field("PAGE_SIZE", plugin::TableFunction::NUMBER);
 
46
  add_field("COMPRESS_OPS", plugin::TableFunction::NUMBER);
 
47
  add_field("COMPRESS_OPS_OK", plugin::TableFunction::NUMBER);
 
48
  add_field("COMPRESS_TIME", plugin::TableFunction::NUMBER);
 
49
  add_field("UNCOMPRESS_OPS", plugin::TableFunction::NUMBER);
 
50
  add_field("UNCOMPRESS_TIME", plugin::TableFunction::NUMBER);
 
51
}
 
52
 
 
53
CmpTool::Generator::Generator(Field **arg, bool in_reset) :
 
54
  plugin::TableFunction::Generator(arg),
 
55
  record_number(0),
 
56
  inner_reset(in_reset)
 
57
{
 
58
}
 
59
 
 
60
bool CmpTool::Generator::populate()
 
61
{
 
62
  if (record_number == (PAGE_ZIP_NUM_SSIZE - 1))
 
63
  {
 
64
    return false;
 
65
  }
 
66
 
 
67
  page_zip_stat_t*        zip_stat = &page_zip_stat[record_number];
 
68
 
 
69
  push(static_cast<uint64_t>(PAGE_ZIP_MIN_SIZE << record_number));
 
70
 
 
71
  /* The cumulated counts are not protected by any
 
72
     mutex.  Thus, some operation in page0zip.c could
 
73
     increment a counter between the time we read it and
 
74
     clear it.  We could introduce mutex protection, but it
 
75
     could cause a measureable performance hit in
 
76
     page0zip.c. */
 
77
  push(zip_stat->compressed);
 
78
  push(zip_stat->compressed_ok);
 
79
  push(zip_stat->compressed_usec / 1000000);
 
80
  push(zip_stat->decompressed);
 
81
  push(zip_stat->decompressed_usec / 1000000);
 
82
 
 
83
  if (inner_reset)
 
84
  {
 
85
    memset(zip_stat, 0, sizeof *zip_stat);
 
86
  }
 
87
 
 
88
  record_number++;
 
89
 
 
90
  return true;
 
91
}
 
92
 
 
93
/*
 
94
 * Fill the dynamic table data_dictionary.INNODB_CMPMEM and INNODB_CMPMEM_RESET
 
95
 *
 
96
 */
 
97
CmpmemTool::CmpmemTool(bool in_reset) :
 
98
  plugin::TableFunction("DATA_DICTIONARY", in_reset ? "INNODB_CMPMEM_RESET" : "INNODB_CMPMEM"),
 
99
  outer_reset(in_reset)
 
100
{
 
101
  add_field("PAGE_SIZE", plugin::TableFunction::NUMBER);
 
102
  add_field("PAGES_USED", plugin::TableFunction::NUMBER);
 
103
  add_field("PAGES_FREE", plugin::TableFunction::NUMBER);
 
104
  add_field("RELOCATION_OPS", plugin::TableFunction::NUMBER);
 
105
  add_field("RELOCATION_TIME", plugin::TableFunction::NUMBER);
 
106
}
 
107
 
 
108
CmpmemTool::Generator::Generator(Field **arg, bool in_reset) :
 
109
  plugin::TableFunction::Generator(arg),
 
110
  record_number(0),
 
111
  inner_reset(in_reset)
 
112
{
 
113
  buf_pool_mutex_enter();
 
114
}
 
115
 
 
116
CmpmemTool::Generator::~Generator()
 
117
{
 
118
  buf_pool_mutex_exit();
 
119
}
 
120
 
 
121
bool CmpmemTool::Generator::populate()
 
122
{
 
123
  if (record_number > BUF_BUDDY_SIZES)
 
124
  {
 
125
    return false;
 
126
  }
 
127
 
 
128
  buf_buddy_stat_t* buddy_stat = &buf_buddy_stat[record_number];
 
129
 
 
130
  push(static_cast<uint64_t>(BUF_BUDDY_LOW << record_number));
 
131
  push(buddy_stat->used);
 
132
  push(UNIV_LIKELY(record_number < BUF_BUDDY_SIZES) 
 
133
                   ? UT_LIST_GET_LEN(buf_pool->zip_free[record_number]) : 0);
 
134
 
 
135
  push(buddy_stat->relocated);
 
136
  push(buddy_stat->relocated_usec / 1000000);
 
137
 
 
138
 
 
139
  if (inner_reset)
 
140
  {
 
141
    buddy_stat->relocated = 0;
 
142
    buddy_stat->relocated_usec = 0;
 
143
  }
 
144
 
 
145
  record_number++;
 
146
 
 
147
  return true;
 
148
}
 
149
 
 
150
/*
 
151
 * Fill the dynamic table data_dictionary.INNODB_TRX INNODB_LOCKS INNODB_LOCK_WAITS
 
152
 *
 
153
 */
 
154
InnodbTrxTool::InnodbTrxTool(const char* in_table_name) :
 
155
  plugin::TableFunction("DATA_DICTIONARY", in_table_name),
 
156
  table_name(in_table_name)
 
157
{
 
158
  if (innobase_strcasecmp(table_name, "INNODB_TRX") == 0)
 
159
  {
 
160
    add_field("TRX_ID");
 
161
    add_field("TRX_STATE");
 
162
    add_field("TRX_STARTED", plugin::TableFunction::NUMBER);
 
163
    add_field("TRX_REQUESTED_LOCK_ID");
 
164
    add_field("TRX_WAIT_STARTED", plugin::TableFunction::NUMBER);
 
165
    add_field("TRX_WEIGHT", plugin::TableFunction::NUMBER);
 
166
    add_field("TRX_DRIZZLE_THREAD_ID", plugin::TableFunction::NUMBER);
 
167
    add_field("TRX_QUERY");
 
168
  }
 
169
  else if (innobase_strcasecmp(table_name, "INNODB_LOCKS") == 0)
 
170
  {
 
171
    add_field("LOCK_ID");
 
172
    add_field("LOCK_TRX_ID");
 
173
    add_field("LOCK_MODE");
 
174
    add_field("LOCK_TYPE");
 
175
    add_field("LOCK_TABLE");
 
176
    add_field("LOCK_INDEX");
 
177
    add_field("LOCK_SPACE", plugin::TableFunction::NUMBER);
 
178
    add_field("LOCK_PAGE", plugin::TableFunction::NUMBER);
 
179
    add_field("LOCK_REC", plugin::TableFunction::NUMBER);
 
180
    add_field("LOCK_DATA");
 
181
  }
 
182
  else if (innobase_strcasecmp(table_name, "INNODB_LOCK_WAITS") == 0)
 
183
  {
 
184
    add_field("REQUESTING_TRX_ID");  
 
185
    add_field("REQUESTED_LOCK_ID");
 
186
    add_field("BLOCKING_TRX_ID");
 
187
    add_field("BLOCKING_LOCK_ID");
 
188
  } 
 
189
}
 
190
 
 
191
InnodbTrxTool::Generator::Generator(Field **arg, const char* in_table_name) :
 
192
  plugin::TableFunction::Generator(arg),
 
193
  table_name(in_table_name)
 
194
{
 
195
  /* update the cache */
 
196
  trx_i_s_cache_start_write(trx_i_s_cache);
 
197
  trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache);
 
198
  trx_i_s_cache_end_write(trx_i_s_cache);
 
199
 
 
200
  if (trx_i_s_cache_is_truncated(trx_i_s_cache))
 
201
  {
 
202
    errmsg_printf(ERRMSG_LVL_ERROR, _("Warning: data in %s truncated due to memory limit of %d bytes\n"), 
 
203
                  table_name, TRX_I_S_MEM_LIMIT);
 
204
  } 
 
205
 
 
206
  trx_i_s_cache_start_read(trx_i_s_cache);
 
207
 
 
208
  number_rows= trx_i_s_cache_get_rows_used(trx_i_s_cache, I_S_INNODB_TRX);
 
209
 
 
210
  record_number= 0;
 
211
}
 
212
 
 
213
InnodbTrxTool::Generator::~Generator()
 
214
{
 
215
  trx_i_s_cache_end_read(trx_i_s_cache);
 
216
}
 
217
 
 
218
bool InnodbTrxTool::Generator::populate()
 
219
{
 
220
  if (record_number == number_rows)
 
221
  {
 
222
    return false;
 
223
  }
 
224
 
 
225
  if (innobase_strcasecmp(table_name, "INNODB_TRX") == 0)
 
226
  {
 
227
    populate_innodb_trx();
 
228
  }
 
229
  else if (innobase_strcasecmp(table_name, "INNODB_LOCKS") == 0)
 
230
  {
 
231
    populate_innodb_locks();
 
232
  }
 
233
  else if (innobase_strcasecmp(table_name, "INNODB_LOCK_WAITS") == 0)
 
234
  {
 
235
    populate_innodb_lock_waits();
 
236
  }
 
237
  else 
 
238
  {
 
239
    return false;
 
240
  }
 
241
  record_number++;
 
242
 
 
243
  return true;
 
244
}
 
245
 
 
246
void InnodbTrxTool::Generator::populate_innodb_locks()
 
247
{
 
248
 
 
249
  char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
 
250
  i_s_locks_row_t* row;
 
251
 
 
252
  /* note that the decoded database or table name is
 
253
     never expected to be longer than NAME_LEN;
 
254
     NAME_LEN for database name
 
255
     2 for surrounding quotes around database name
 
256
     NAME_LEN for table name
 
257
     2 for surrounding quotes around table name
 
258
     1 for the separating dot (.)
 
259
     9 for the #mysql50# prefix 
 
260
  */
 
261
 
 
262
   char buf[2 * NAME_LEN + 14];
 
263
   const char* bufend;
 
264
 
 
265
   char lock_trx_id[TRX_ID_MAX_LEN + 1];
 
266
 
 
267
   row = (i_s_locks_row_t*)
 
268
          trx_i_s_cache_get_nth_row(
 
269
          trx_i_s_cache, I_S_INNODB_LOCKS, record_number);
 
270
 
 
271
 
 
272
   trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
 
273
   push(lock_id);
 
274
 
 
275
   ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
 
276
               TRX_ID_FMT, row->lock_trx_id);
 
277
   push(lock_trx_id);
 
278
 
 
279
   push(row->lock_mode);
 
280
   push(row->lock_type);
 
281
 
 
282
   bufend = innobase_convert_name(buf, sizeof(buf),
 
283
                                  row->lock_table,
 
284
                                  strlen(row->lock_table),
 
285
                                  current_session, TRUE);
 
286
   push(bufend);
 
287
 
 
288
   if (row->lock_index != NULL)
 
289
   {
 
290
     bufend = innobase_convert_name(buf, sizeof(buf),
 
291
                                    row->lock_index,
 
292
                                    strlen(row->lock_index),
 
293
                                    current_session, FALSE);
 
294
     push(bufend);     
 
295
   }
 
296
   else 
 
297
   {
 
298
     push("");
 
299
   }   
 
300
 
 
301
   push(row->lock_space);
 
302
   push(row->lock_page); 
 
303
   push(row->lock_rec);
 
304
   push(row->lock_data);
 
305
}
 
306
 
 
307
void InnodbTrxTool::Generator::populate_innodb_trx()
 
308
{
 
309
    char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
 
310
    i_s_trx_row_t* row;
 
311
    char trx_id[TRX_ID_MAX_LEN + 1];
 
312
    row = (i_s_trx_row_t*) trx_i_s_cache_get_nth_row(trx_i_s_cache, I_S_INNODB_TRX, record_number);
 
313
 
 
314
    /* trx_id */
 
315
    ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
 
316
 
 
317
    push(trx_id);
 
318
    push(row->trx_state);
 
319
    push(row->trx_started);
 
320
 
 
321
    if (row->trx_wait_started != 0)
 
322
    {
 
323
      push(trx_i_s_create_lock_id(row->requested_lock_row, lock_id, sizeof(lock_id)));
 
324
      push(row->trx_wait_started);
 
325
    }
 
326
    else
 
327
    {
 
328
      push(static_cast<uint64_t>(0));
 
329
      push(static_cast<uint64_t>(0));
 
330
    }
 
331
 
 
332
    push(static_cast<int64_t>(row->trx_weight));
 
333
    push(row->trx_mysql_thread_id);
 
334
    push(row->trx_query);
 
335
}
 
336
 
 
337
void InnodbTrxTool::Generator::populate_innodb_lock_waits()
 
338
{
 
339
  char requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
 
340
  char blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
 
341
 
 
342
  i_s_lock_waits_row_t* row;
 
343
 
 
344
  char requesting_trx_id[TRX_ID_MAX_LEN + 1];
 
345
  char blocking_trx_id[TRX_ID_MAX_LEN + 1];
 
346
 
 
347
  row = (i_s_lock_waits_row_t*)
 
348
         trx_i_s_cache_get_nth_row(
 
349
         trx_i_s_cache, I_S_INNODB_LOCK_WAITS, record_number);
 
350
 
 
351
  ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
 
352
              TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
 
353
  push(requesting_trx_id);
 
354
 
 
355
  push(trx_i_s_create_lock_id(row->requested_lock_row, requested_lock_id, 
 
356
       sizeof(requested_lock_id)));
 
357
 
 
358
  ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
 
359
              TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
 
360
  push(blocking_trx_id);
 
361
 
 
362
  push(trx_i_s_create_lock_id(row->blocking_lock_row, blocking_lock_id, 
 
363
       sizeof(blocking_lock_id)));
 
364
}