~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merge of show work (updates, a bit faster)

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
 
/**************************************************//**
20
 
@file handler/i_s.cc
21
 
InnoDB INFORMATION SCHEMA tables interface to MySQL.
22
 
 
23
 
Created July 18, 2007 Vasil Dimov
24
 
*******************************************************/
25
 
 
26
 
#include "config.h"
27
 
#include <drizzled/error.h>
28
 
#include "drizzled/charset_info.h"
29
 
#include "drizzled/internal/my_sys.h"
30
 
#include <drizzled/my_hash.h>
31
 
#include <drizzled/plugin.h>
32
 
#include <drizzled/field.h>
33
 
#include <drizzled/table.h>
34
 
#include <drizzled/time_functions.h>
35
 
#include "drizzled/global_charset_info.h"
36
 
 
37
 
 
38
 
#include "i_s.h"
39
 
 
40
 
#if 0
41
 
 
42
 
extern "C" {
43
 
#include "trx0i_s.h"
44
 
#include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
45
 
#include "buf0buddy.h" /* for i_s_cmpmem */
46
 
#include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
47
 
#include "ha_prototypes.h" /* for innobase_convert_name() */
48
 
#include "srv0start.h" /* for srv_was_started */
49
 
}
50
 
#include "handler0vars.h"
51
 
 
52
 
using namespace drizzled;
53
 
 
54
 
static const char plugin_author[] = "Innobase Oy";
55
 
 
56
 
#define OK(expr)                \
57
 
        if ((expr) != 0) {      \
58
 
                return(1);      \
59
 
        }
60
 
 
61
 
#define RETURN_IF_INNODB_NOT_STARTED(plugin_name)                       \
62
 
do {                                                                    \
63
 
        if (!srv_was_started) {                                         \
64
 
                push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,    \
65
 
                                    ER_CANT_FIND_SYSTEM_REC,            \
66
 
                                    "InnoDB: SELECTing from "           \
67
 
                                    "INFORMATION_SCHEMA.%s but "        \
68
 
                                    "the InnoDB storage engine "        \
69
 
                                    "is not installed", plugin_name);   \
70
 
                return(0);                                              \
71
 
        }                                                               \
72
 
} while (0)
73
 
 
74
 
#define STRUCT_FLD(name, value) value
75
 
 
76
 
plugin::InfoSchemaTable *innodb_trx_schema_table= NULL;
77
 
plugin::InfoSchemaTable *innodb_locks_schema_table= NULL;
78
 
plugin::InfoSchemaTable *innodb_lock_waits_schema_table= NULL;
79
 
plugin::InfoSchemaTable *innodb_cmp_schema_table= NULL;
80
 
plugin::InfoSchemaTable *innodb_cmp_reset_schema_table= NULL;
81
 
plugin::InfoSchemaTable *innodb_cmpmem_schema_table= NULL;
82
 
plugin::InfoSchemaTable *innodb_cmpmem_reset_schema_table= NULL;
83
 
 
84
 
static TrxISMethods trx_methods;
85
 
static CmpISMethods cmp_methods;
86
 
static CmpResetISMethods cmp_reset_methods;
87
 
static CmpmemISMethods cmpmem_methods;
88
 
static CmpmemResetISMethods cmpmem_reset_methods;
89
 
 
90
 
/*
91
 
Use the following types mapping:
92
 
 
93
 
C type  ST_FIELD_INFO::field_type
94
 
---------------------------------
95
 
long                    DRIZZLE_TYPE_LONGLONG
96
 
(field_length=MY_INT64_NUM_DECIMAL_DIGITS)
97
 
 
98
 
long unsigned           DRIZZLE_TYPE_LONGLONG
99
 
(field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
100
 
 
101
 
char*                   DRIZZLE_TYPE_STRING
102
 
(field_length=n)
103
 
 
104
 
float                   DRIZZLE_TYPE_FLOAT
105
 
(field_length=0 is ignored)
106
 
 
107
 
void*                   DRIZZLE_TYPE_LONGLONG
108
 
(field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
109
 
 
110
 
boolean (if else)       DRIZZLE_TYPE_LONG
111
 
(field_length=1)
112
 
 
113
 
time_t                  DRIZZLE_TYPE_DATETIME
114
 
(field_length=0 ignored)
115
 
---------------------------------
116
 
*/
117
 
 
118
 
/*******************************************************************//**
119
 
Auxiliary function to store time_t value in MYSQL_TYPE_DATETIME
120
 
field.
121
 
@return 0 on success */
122
 
static
123
 
int
124
 
field_store_time_t(
125
 
/*===============*/
126
 
        Field*  field,  /*!< in/out: target field for storage */
127
 
        time_t  time)   /*!< in: value to store */
128
 
{
129
 
        DRIZZLE_TIME    my_time;
130
 
        struct tm       tm_time;
131
 
 
132
 
#if 0
133
 
        /* use this if you are sure that `variables' and `time_zone'
134
 
        are always initialized */
135
 
        session->variables.time_zone->gmt_sec_to_TIME(
136
 
                &my_time, (time_t) time);
137
 
#else
138
 
        localtime_r(&time, &tm_time);
139
 
        localtime_to_TIME(&my_time, &tm_time);
140
 
        my_time.time_type = DRIZZLE_TIMESTAMP_DATETIME;
141
 
#endif
142
 
 
143
 
        return(field->store_time(&my_time, DRIZZLE_TIMESTAMP_DATETIME));
144
 
}
145
 
 
146
 
/*******************************************************************//**
147
 
Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
148
 
@return 0 on success */
149
 
static
150
 
int
151
 
field_store_string(
152
 
/*===============*/
153
 
        Field*          field,  /*!< in/out: target field for storage */
154
 
        const char*     str)    /*!< in: NUL-terminated utf-8 string,
155
 
                                or NULL */
156
 
{
157
 
        int     ret;
158
 
 
159
 
        if (str != NULL) {
160
 
 
161
 
                ret = field->store(str, strlen(str),
162
 
                                   system_charset_info);
163
 
                field->set_notnull();
164
 
        } else {
165
 
 
166
 
                ret = 0; /* success */
167
 
                field->set_null();
168
 
        }
169
 
 
170
 
        return(ret);
171
 
}
172
 
 
173
 
/*******************************************************************//**
174
 
Auxiliary function to store ulint value in DRIZZLE_TYPE_LONGLONG field.
175
 
If the value is ULINT_UNDEFINED then the field it set to NULL.
176
 
@return 0 on success */
177
 
static
178
 
int
179
 
field_store_ulint(
180
 
/*==============*/
181
 
        Field*  field,  /*!< in/out: target field for storage */
182
 
        ulint   n)      /*!< in: value to store */
183
 
{
184
 
        int     ret;
185
 
 
186
 
        if (n != ULINT_UNDEFINED) {
187
 
 
188
 
                ret = field->store(n);
189
 
                field->set_notnull();
190
 
        } else {
191
 
 
192
 
                ret = 0; /* success */
193
 
                field->set_null();
194
 
        }
195
 
 
196
 
        return(ret);
197
 
}
198
 
 
199
 
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
200
 
static plugin::ColumnInfo       innodb_trx_fields_info[] =
201
 
{
202
 
#define IDX_TRX_ID              0
203
 
        plugin::ColumnInfo("trx_id",
204
 
                  TRX_ID_MAX_LEN + 1,
205
 
                  DRIZZLE_TYPE_VARCHAR,
206
 
                  0,
207
 
                  0,
208
 
                  ""),
209
 
 
210
 
#define IDX_TRX_STATE           1
211
 
        plugin::ColumnInfo("trx_state",
212
 
                  TRX_QUE_STATE_STR_MAX_LEN + 1,
213
 
                  DRIZZLE_TYPE_VARCHAR,
214
 
                  0,
215
 
                  0,
216
 
                  ""),
217
 
 
218
 
#define IDX_TRX_STARTED         2
219
 
        plugin::ColumnInfo("trx_started",
220
 
                  0,
221
 
                  DRIZZLE_TYPE_DATETIME,
222
 
                  0,
223
 
                  0,
224
 
                  ""),
225
 
 
226
 
#define IDX_TRX_REQUESTED_LOCK_ID       3
227
 
        plugin::ColumnInfo("trx_requested_lock_id",
228
 
                  TRX_I_S_LOCK_ID_MAX_LEN + 1,
229
 
                  DRIZZLE_TYPE_VARCHAR,
230
 
                  0,
231
 
                  MY_I_S_MAYBE_NULL,
232
 
                  ""),
233
 
 
234
 
#define IDX_TRX_WAIT_STARTED    4
235
 
        plugin::ColumnInfo("trx_wait_started",
236
 
                  0,
237
 
                  DRIZZLE_TYPE_DATETIME,
238
 
                  0,
239
 
                  MY_I_S_MAYBE_NULL,
240
 
                  ""),
241
 
 
242
 
#define IDX_TRX_WEIGHT          5
243
 
        plugin::ColumnInfo("trx_weight",
244
 
                  MY_INT64_NUM_DECIMAL_DIGITS,
245
 
                  DRIZZLE_TYPE_LONGLONG,
246
 
                  0,
247
 
                  MY_I_S_UNSIGNED,
248
 
                  ""),
249
 
 
250
 
#define IDX_TRX_DRIZZLE_THREAD_ID       6
251
 
        plugin::ColumnInfo("trx_mysql_thread_id",
252
 
                  MY_INT64_NUM_DECIMAL_DIGITS,
253
 
                  DRIZZLE_TYPE_LONGLONG,
254
 
                  0,
255
 
                  MY_I_S_UNSIGNED,
256
 
                  ""),
257
 
 
258
 
#define IDX_TRX_QUERY           7
259
 
        plugin::ColumnInfo("trx_query",
260
 
                  TRX_I_S_TRX_QUERY_MAX_LEN,
261
 
                  DRIZZLE_TYPE_VARCHAR,
262
 
                  0,
263
 
                  MY_I_S_MAYBE_NULL,
264
 
                  ""),
265
 
 
266
 
        plugin::ColumnInfo()
267
 
};
268
 
 
269
 
/*******************************************************************//**
270
 
Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_trx
271
 
table with it.
272
 
@return 0 on success */
273
 
static
274
 
int
275
 
fill_innodb_trx_from_cache(
276
 
/*=======================*/
277
 
        trx_i_s_cache_t*        cache,  /*!< in: cache to read from */
278
 
        Table*                  table,  /*!< in/out: fill this table */
279
 
        plugin::InfoSchemaTable *schema_table)
280
 
{
281
 
        Field** fields;
282
 
        ulint   rows_num;
283
 
        char    lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
284
 
        ulint   i;
285
 
 
286
 
        fields = table->field;
287
 
 
288
 
        rows_num = trx_i_s_cache_get_rows_used(cache,
289
 
                                               I_S_INNODB_TRX);
290
 
 
291
 
        for (i = 0; i < rows_num; i++) {
292
 
 
293
 
                i_s_trx_row_t*  row;
294
 
                char            trx_id[TRX_ID_MAX_LEN + 1];
295
 
 
296
 
                row = (i_s_trx_row_t*)
297
 
                        trx_i_s_cache_get_nth_row(
298
 
                                cache, I_S_INNODB_TRX, i);
299
 
 
300
 
                /* trx_id */
301
 
                ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
302
 
                OK(field_store_string(fields[IDX_TRX_ID], trx_id));
303
 
 
304
 
                /* trx_state */
305
 
                OK(field_store_string(fields[IDX_TRX_STATE],
306
 
                                      row->trx_state));
307
 
 
308
 
                /* trx_started */
309
 
                OK(field_store_time_t(fields[IDX_TRX_STARTED],
310
 
                                      (time_t) row->trx_started));
311
 
 
312
 
                /* trx_requested_lock_id */
313
 
                /* trx_wait_started */
314
 
                if (row->trx_wait_started != 0) {
315
 
 
316
 
                        OK(field_store_string(
317
 
                                   fields[IDX_TRX_REQUESTED_LOCK_ID],
318
 
                                   trx_i_s_create_lock_id(
319
 
                                           row->requested_lock_row,
320
 
                                           lock_id, sizeof(lock_id))));
321
 
                        /* field_store_string() sets it no notnull */
322
 
 
323
 
                        OK(field_store_time_t(
324
 
                                   fields[IDX_TRX_WAIT_STARTED],
325
 
                                   (time_t) row->trx_wait_started));
326
 
                        fields[IDX_TRX_WAIT_STARTED]->set_notnull();
327
 
                } else {
328
 
 
329
 
                        fields[IDX_TRX_REQUESTED_LOCK_ID]->set_null();
330
 
                        fields[IDX_TRX_WAIT_STARTED]->set_null();
331
 
                }
332
 
 
333
 
                /* trx_weight */
334
 
                OK(fields[IDX_TRX_WEIGHT]->store((int64_t) row->trx_weight,
335
 
                                                 true));
336
 
 
337
 
                /* trx_mysql_thread_id */
338
 
                OK(fields[IDX_TRX_DRIZZLE_THREAD_ID]->store(
339
 
                           row->trx_mysql_thread_id));
340
 
 
341
 
                /* trx_query */
342
 
                OK(field_store_string(fields[IDX_TRX_QUERY],
343
 
                                      row->trx_query));
344
 
 
345
 
                schema_table->addRow(table->record[0],
346
 
                                     table->s->reclength);
347
 
        }
348
 
 
349
 
        return(0);
350
 
}
351
 
 
352
 
/*******************************************************************//**
353
 
Bind the dynamic table INFORMATION_SCHEMA.innodb_trx
354
 
@return 0 on success */
355
 
int
356
 
innodb_trx_init()
357
 
/*============*/
358
 
{
359
 
        if ((innodb_trx_schema_table= new plugin::InfoSchemaTable("INNODB_TRX")) == NULL)
360
 
                return(1);
361
 
 
362
 
        innodb_trx_schema_table->setColumnInfo(innodb_trx_fields_info);
363
 
        innodb_trx_schema_table->setInfoSchemaMethods(&trx_methods);
364
 
 
365
 
        return(0);
366
 
}
367
 
 
368
 
 
369
 
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
370
 
static plugin::ColumnInfo innodb_locks_fields_info[] =
371
 
{
372
 
#define IDX_LOCK_ID             0
373
 
        plugin::ColumnInfo("lock_id",
374
 
                  TRX_I_S_LOCK_ID_MAX_LEN + 1,
375
 
                  DRIZZLE_TYPE_VARCHAR,
376
 
                  0,
377
 
                  0,
378
 
                  ""),
379
 
 
380
 
#define IDX_LOCK_TRX_ID         1
381
 
        plugin::ColumnInfo("lock_trx_id",
382
 
                  TRX_ID_MAX_LEN + 1,
383
 
                  DRIZZLE_TYPE_VARCHAR,
384
 
                  0,
385
 
                  0,
386
 
                  ""),
387
 
 
388
 
#define IDX_LOCK_MODE           2
389
 
        plugin::ColumnInfo("lock_mode",
390
 
         /* S[,GAP] X[,GAP] IS[,GAP] IX[,GAP] AUTO_INC UNKNOWN */
391
 
                  32,
392
 
                  DRIZZLE_TYPE_VARCHAR,
393
 
                  0,
394
 
                  0,
395
 
                  ""),
396
 
 
397
 
#define IDX_LOCK_TYPE           3
398
 
        plugin::ColumnInfo("lock_type",
399
 
                  32, /* RECORD|TABLE|UNKNOWN */
400
 
                  DRIZZLE_TYPE_VARCHAR,
401
 
                  0,
402
 
                  0,
403
 
                  ""),
404
 
 
405
 
#define IDX_LOCK_TABLE          4
406
 
        plugin::ColumnInfo("lock_table",
407
 
                  1024,
408
 
                  DRIZZLE_TYPE_VARCHAR,
409
 
                  0,
410
 
                  0,
411
 
                  ""),
412
 
 
413
 
#define IDX_LOCK_INDEX          5
414
 
        plugin::ColumnInfo("lock_index",
415
 
                  1024,
416
 
                  DRIZZLE_TYPE_VARCHAR,
417
 
                  0,
418
 
                  MY_I_S_MAYBE_NULL,
419
 
                  ""),
420
 
 
421
 
#define IDX_LOCK_SPACE          6
422
 
        plugin::ColumnInfo("lock_space",
423
 
                  MY_INT64_NUM_DECIMAL_DIGITS,
424
 
                  DRIZZLE_TYPE_LONGLONG,
425
 
                  0,
426
 
                  MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL,
427
 
                  ""),
428
 
 
429
 
#define IDX_LOCK_PAGE           7
430
 
        plugin::ColumnInfo("lock_page",
431
 
                  MY_INT64_NUM_DECIMAL_DIGITS,
432
 
                  DRIZZLE_TYPE_LONGLONG,
433
 
                  0,
434
 
                  MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL,
435
 
                  ""),
436
 
 
437
 
#define IDX_LOCK_REC            8
438
 
        plugin::ColumnInfo("lock_rec",
439
 
                  MY_INT64_NUM_DECIMAL_DIGITS,
440
 
                  DRIZZLE_TYPE_LONGLONG,
441
 
                  0,
442
 
                  MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL,
443
 
                  ""),
444
 
 
445
 
#define IDX_LOCK_DATA           9
446
 
        plugin::ColumnInfo("lock_data",
447
 
                  TRX_I_S_LOCK_DATA_MAX_LEN,
448
 
                  DRIZZLE_TYPE_VARCHAR,
449
 
                  0,
450
 
                  MY_I_S_MAYBE_NULL,
451
 
                  ""),
452
 
 
453
 
        plugin::ColumnInfo()
454
 
};
455
 
 
456
 
/*******************************************************************//**
457
 
Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_locks
458
 
table with it.
459
 
@return 0 on success */
460
 
static
461
 
int
462
 
fill_innodb_locks_from_cache(
463
 
/*=========================*/
464
 
        trx_i_s_cache_t*        cache,  /*!< in: cache to read from */
465
 
        Session*                session,/*!< in: MySQL client connection */
466
 
        Table*                  table,  /*!< in/out: fill this table */
467
 
        plugin::InfoSchemaTable *schema_table)
468
 
{
469
 
        Field** fields;
470
 
        ulint   rows_num;
471
 
        char    lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
472
 
        ulint   i;
473
 
 
474
 
        fields = table->field;
475
 
 
476
 
        rows_num = trx_i_s_cache_get_rows_used(cache,
477
 
                                               I_S_INNODB_LOCKS);
478
 
 
479
 
        for (i = 0; i < rows_num; i++) {
480
 
 
481
 
                i_s_locks_row_t*        row;
482
 
 
483
 
                /* note that the decoded database or table name is
484
 
                never expected to be longer than NAME_LEN;
485
 
                NAME_LEN for database name
486
 
                2 for surrounding quotes around database name
487
 
                NAME_LEN for table name
488
 
                2 for surrounding quotes around table name
489
 
                1 for the separating dot (.)
490
 
                9 for the #mysql50# prefix */
491
 
                char                    buf[2 * NAME_LEN + 14];
492
 
                const char*             bufend;
493
 
 
494
 
                char                    lock_trx_id[TRX_ID_MAX_LEN + 1];
495
 
 
496
 
                row = (i_s_locks_row_t*)
497
 
                        trx_i_s_cache_get_nth_row(
498
 
                                cache, I_S_INNODB_LOCKS, i);
499
 
 
500
 
                /* lock_id */
501
 
                trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
502
 
                OK(field_store_string(fields[IDX_LOCK_ID],
503
 
                                      lock_id));
504
 
 
505
 
                /* lock_trx_id */
506
 
                ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
507
 
                            TRX_ID_FMT, row->lock_trx_id);
508
 
                OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id));
509
 
 
510
 
                /* lock_mode */
511
 
                OK(field_store_string(fields[IDX_LOCK_MODE],
512
 
                                      row->lock_mode));
513
 
 
514
 
                /* lock_type */
515
 
                OK(field_store_string(fields[IDX_LOCK_TYPE],
516
 
                                      row->lock_type));
517
 
 
518
 
                /* lock_table */
519
 
                bufend = innobase_convert_name(buf, sizeof(buf),
520
 
                                               row->lock_table,
521
 
                                               strlen(row->lock_table),
522
 
                                               session, TRUE);
523
 
                OK(fields[IDX_LOCK_TABLE]->store(buf, bufend - buf,
524
 
                                                 system_charset_info));
525
 
 
526
 
                /* lock_index */
527
 
                if (row->lock_index != NULL) {
528
 
 
529
 
                        bufend = innobase_convert_name(buf, sizeof(buf),
530
 
                                                       row->lock_index,
531
 
                                                       strlen(row->lock_index),
532
 
                                                       session, FALSE);
533
 
                        OK(fields[IDX_LOCK_INDEX]->store(buf, bufend - buf,
534
 
                                                         system_charset_info));
535
 
                        fields[IDX_LOCK_INDEX]->set_notnull();
536
 
                } else {
537
 
 
538
 
                        fields[IDX_LOCK_INDEX]->set_null();
539
 
                }
540
 
 
541
 
                /* lock_space */
542
 
                OK(field_store_ulint(fields[IDX_LOCK_SPACE],
543
 
                                     row->lock_space));
544
 
 
545
 
                /* lock_page */
546
 
                OK(field_store_ulint(fields[IDX_LOCK_PAGE],
547
 
                                     row->lock_page));
548
 
 
549
 
                /* lock_rec */
550
 
                OK(field_store_ulint(fields[IDX_LOCK_REC],
551
 
                                     row->lock_rec));
552
 
 
553
 
                /* lock_data */
554
 
                OK(field_store_string(fields[IDX_LOCK_DATA],
555
 
                                      row->lock_data));
556
 
 
557
 
                schema_table->addRow(table->record[0],
558
 
                                     table->s->reclength);
559
 
        }
560
 
 
561
 
        return(0);
562
 
}
563
 
 
564
 
/*******************************************************************//**
565
 
Bind the dynamic table INFORMATION_SCHEMA.innodb_locks
566
 
@return 0 on success */
567
 
int
568
 
innodb_locks_init()
569
 
/*==============*/
570
 
{
571
 
 
572
 
        if ((innodb_locks_schema_table= new plugin::InfoSchemaTable("INNODB_LOCKS")) == NULL)
573
 
                return(1);
574
 
 
575
 
        innodb_locks_schema_table->setColumnInfo(innodb_locks_fields_info);
576
 
        innodb_locks_schema_table->setInfoSchemaMethods(&trx_methods);
577
 
        return(0);
578
 
}
579
 
 
580
 
 
581
 
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
582
 
static plugin::ColumnInfo innodb_lock_waits_fields_info[] =
583
 
{
584
 
#define IDX_REQUESTING_TRX_ID   0
585
 
        plugin::ColumnInfo("requesting_trx_id",
586
 
                  TRX_ID_MAX_LEN + 1,
587
 
                  DRIZZLE_TYPE_VARCHAR,
588
 
                  0,
589
 
                  0,
590
 
                  ""),
591
 
 
592
 
#define IDX_REQUESTED_LOCK_ID   1
593
 
        plugin::ColumnInfo("requested_lock_id",
594
 
                  TRX_I_S_LOCK_ID_MAX_LEN + 1,
595
 
                  DRIZZLE_TYPE_VARCHAR,
596
 
                  0,
597
 
                  0,
598
 
                  ""),
599
 
 
600
 
#define IDX_BLOCKING_TRX_ID     2
601
 
        plugin::ColumnInfo("blocking_trx_id",
602
 
                  TRX_ID_MAX_LEN + 1,
603
 
                  DRIZZLE_TYPE_VARCHAR,
604
 
                  0,
605
 
                  0,
606
 
                  ""),
607
 
 
608
 
#define IDX_BLOCKING_LOCK_ID    3
609
 
        plugin::ColumnInfo("blocking_lock_id",
610
 
                  TRX_I_S_LOCK_ID_MAX_LEN + 1,
611
 
                  DRIZZLE_TYPE_VARCHAR,
612
 
                  0,
613
 
                  0,
614
 
                  ""),
615
 
 
616
 
        plugin::ColumnInfo()
617
 
};
618
 
 
619
 
/*******************************************************************//**
620
 
Read data from cache buffer and fill the
621
 
INFORMATION_SCHEMA.innodb_lock_waits table with it.
622
 
@return 0 on success */
623
 
static
624
 
int
625
 
fill_innodb_lock_waits_from_cache(
626
 
/*==============================*/
627
 
        trx_i_s_cache_t*        cache,  /*!< in: cache to read from */
628
 
        Table*                  table,  /*!< in/out: fill this table */
629
 
        plugin::InfoSchemaTable *schema_table)
630
 
{
631
 
        Field** fields;
632
 
        ulint   rows_num;
633
 
        char    requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
634
 
        char    blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
635
 
        ulint   i;
636
 
 
637
 
        fields = table->field;
638
 
 
639
 
        rows_num = trx_i_s_cache_get_rows_used(cache,
640
 
                                               I_S_INNODB_LOCK_WAITS);
641
 
 
642
 
        for (i = 0; i < rows_num; i++) {
643
 
 
644
 
                i_s_lock_waits_row_t*   row;
645
 
 
646
 
                char    requesting_trx_id[TRX_ID_MAX_LEN + 1];
647
 
                char    blocking_trx_id[TRX_ID_MAX_LEN + 1];
648
 
 
649
 
                row = (i_s_lock_waits_row_t*)
650
 
                        trx_i_s_cache_get_nth_row(
651
 
                                cache, I_S_INNODB_LOCK_WAITS, i);
652
 
 
653
 
                /* requesting_trx_id */
654
 
                ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
655
 
                            TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
656
 
                OK(field_store_string(fields[IDX_REQUESTING_TRX_ID],
657
 
                                      requesting_trx_id));
658
 
 
659
 
                /* requested_lock_id */
660
 
                OK(field_store_string(
661
 
                           fields[IDX_REQUESTED_LOCK_ID],
662
 
                           trx_i_s_create_lock_id(
663
 
                                   row->requested_lock_row,
664
 
                                   requested_lock_id,
665
 
                                   sizeof(requested_lock_id))));
666
 
 
667
 
                /* blocking_trx_id */
668
 
                ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
669
 
                            TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
670
 
                OK(field_store_string(fields[IDX_BLOCKING_TRX_ID],
671
 
                                      blocking_trx_id));
672
 
 
673
 
                /* blocking_lock_id */
674
 
                OK(field_store_string(
675
 
                           fields[IDX_BLOCKING_LOCK_ID],
676
 
                           trx_i_s_create_lock_id(
677
 
                                   row->blocking_lock_row,
678
 
                                   blocking_lock_id,
679
 
                                   sizeof(blocking_lock_id))));
680
 
 
681
 
                schema_table->addRow(table->record[0],
682
 
                                     table->s->reclength);
683
 
        }
684
 
 
685
 
        return(0);
686
 
}
687
 
 
688
 
/*******************************************************************//**
689
 
Bind the dynamic table INFORMATION_SCHEMA.innodb_lock_waits
690
 
@return 0 on success */
691
 
int
692
 
innodb_lock_waits_init()
693
 
/*===================*/
694
 
{
695
 
 
696
 
        if ((innodb_lock_waits_schema_table= new plugin::InfoSchemaTable("INNODB_LOCK_WAITS")) == NULL)
697
 
                return(1);
698
 
 
699
 
        innodb_lock_waits_schema_table->setColumnInfo(innodb_lock_waits_fields_info);
700
 
        innodb_lock_waits_schema_table->setInfoSchemaMethods(&trx_methods);
701
 
 
702
 
 
703
 
        return(0);
704
 
}
705
 
 
706
 
 
707
 
/*******************************************************************//**
708
 
Common function to fill any of the dynamic tables:
709
 
INFORMATION_SCHEMA.innodb_trx
710
 
INFORMATION_SCHEMA.innodb_locks
711
 
INFORMATION_SCHEMA.innodb_lock_waits
712
 
@return 0 on success */
713
 
int
714
 
TrxISMethods::fillTable(
715
 
/*======================*/
716
 
        Session*        session,/*!< in: thread */
717
 
        Table*  table,  /*!< in/out: tables to fill */
718
 
        plugin::InfoSchemaTable *schema_table)
719
 
{
720
 
        const char*             table_name;
721
 
        int                     ret;
722
 
        trx_i_s_cache_t*        cache;
723
 
 
724
 
        /* minimize the number of places where global variables are
725
 
        referenced */
726
 
        cache = trx_i_s_cache;
727
 
 
728
 
        /* which table we have to fill? */
729
 
        table_name = schema_table->getName().c_str();
730
 
        /* or table_name = tables->schema_table->table_name; */
731
 
 
732
 
        RETURN_IF_INNODB_NOT_STARTED(table_name);
733
 
 
734
 
        /* update the cache */
735
 
        trx_i_s_cache_start_write(cache);
736
 
        trx_i_s_possibly_fetch_data_into_cache(cache);
737
 
        trx_i_s_cache_end_write(cache);
738
 
 
739
 
        if (trx_i_s_cache_is_truncated(cache)) {
740
 
 
741
 
                /* XXX show warning to user if possible */
742
 
                fprintf(stderr, "Warning: data in %s truncated due to "
743
 
                        "memory limit of %d bytes\n", table_name,
744
 
                        TRX_I_S_MEM_LIMIT);
745
 
        }
746
 
 
747
 
        ret = 0;
748
 
 
749
 
        trx_i_s_cache_start_read(cache);
750
 
 
751
 
        if (innobase_strcasecmp(table_name, "innodb_trx") == 0) {
752
 
 
753
 
                if (fill_innodb_trx_from_cache(
754
 
                        cache, table, schema_table) != 0) {
755
 
 
756
 
                        ret = 1;
757
 
                }
758
 
 
759
 
        } else if (innobase_strcasecmp(table_name, "innodb_locks") == 0) {
760
 
 
761
 
                if (fill_innodb_locks_from_cache(
762
 
                        cache, session, table, schema_table) != 0) {
763
 
 
764
 
                        ret = 1;
765
 
                }
766
 
 
767
 
        } else if (innobase_strcasecmp(table_name, "innodb_lock_waits") == 0) {
768
 
 
769
 
                if (fill_innodb_lock_waits_from_cache(
770
 
                        cache, table, schema_table) != 0) {
771
 
 
772
 
                        ret = 1;
773
 
                }
774
 
 
775
 
        } else {
776
 
 
777
 
                /* huh! what happened!? */
778
 
                fprintf(stderr,
779
 
                        "InnoDB: trx_i_s_common_fill_table() was "
780
 
                        "called to fill unknown table: %s.\n"
781
 
                        "This function only knows how to fill "
782
 
                        "innodb_trx, innodb_locks and "
783
 
                        "innodb_lock_waits tables.\n", table_name);
784
 
 
785
 
                ret = 1;
786
 
        }
787
 
 
788
 
        trx_i_s_cache_end_read(cache);
789
 
 
790
 
#if 0
791
 
        return(ret);
792
 
#else
793
 
        /* if this function returns something else than 0 then a
794
 
        deadlock occurs between the mysqld server and mysql client,
795
 
        see http://bugs.mysql.com/29900 ; when that bug is resolved
796
 
        we can enable the return(ret) above */
797
 
        return(0);
798
 
#endif
799
 
}
800
 
 
801
 
/* Fields of the dynamic table information_schema.innodb_cmp. */
802
 
static plugin::ColumnInfo       i_s_cmp_fields_info[] =
803
 
{
804
 
        plugin::ColumnInfo("page_size",
805
 
                  5,
806
 
                  DRIZZLE_TYPE_LONG,
807
 
                  0,
808
 
                  0,
809
 
                  "Compressed Page Size"),
810
 
 
811
 
        plugin::ColumnInfo("compress_ops",
812
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
813
 
                  DRIZZLE_TYPE_LONG,
814
 
                  0,
815
 
                  0,
816
 
                  "Total Number of Compressions"),
817
 
 
818
 
        plugin::ColumnInfo("compress_ops_ok",
819
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
820
 
                  DRIZZLE_TYPE_LONG,
821
 
                  0,
822
 
                  0,
823
 
                  "Total Number of Successful Compressions"),
824
 
 
825
 
        plugin::ColumnInfo("compress_time",
826
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
827
 
                  DRIZZLE_TYPE_LONG,
828
 
                  0,
829
 
                  0,
830
 
                  "Total Duration of Compressions in Seconds"),
831
 
 
832
 
        plugin::ColumnInfo("uncompress_ops",
833
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
834
 
                  DRIZZLE_TYPE_LONG,
835
 
                  0,
836
 
                  0,
837
 
                  "Total Number of Decompressions"),
838
 
 
839
 
        plugin::ColumnInfo("uncompress_time",
840
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
841
 
                  DRIZZLE_TYPE_LONG,
842
 
                  0,
843
 
                  0,
844
 
                  "Total Duration of Decompressions in Seconds"),
845
 
 
846
 
        plugin::ColumnInfo()
847
 
};
848
 
 
849
 
 
850
 
/*******************************************************************//**
851
 
Fill the dynamic table information_schema.innodb_cmp or
852
 
innodb_cmp_reset.
853
 
@return 0 on success, 1 on failure */
854
 
static
855
 
int
856
 
i_s_cmp_fill_low(
857
 
/*=============*/
858
 
        Session*        session,/*!< in: thread */
859
 
        Table*  table,  /*!< in/out: tables to fill */
860
 
        plugin::InfoSchemaTable *schema_table,
861
 
        ibool           reset)  /*!< in: TRUE=reset cumulated counts */
862
 
{
863
 
        int     status  = 0;
864
 
 
865
 
 
866
 
        RETURN_IF_INNODB_NOT_STARTED(schema_table->getName().c_str());
867
 
 
868
 
        for (uint i = 0; i < PAGE_ZIP_NUM_SSIZE - 1; i++) {
869
 
                page_zip_stat_t*        zip_stat = &page_zip_stat[i];
870
 
 
871
 
                table->field[0]->store(PAGE_ZIP_MIN_SIZE << i);
872
 
 
873
 
                /* The cumulated counts are not protected by any
874
 
                mutex.  Thus, some operation in page0zip.c could
875
 
                increment a counter between the time we read it and
876
 
                clear it.  We could introduce mutex protection, but it
877
 
                could cause a measureable performance hit in
878
 
                page0zip.c. */
879
 
                table->field[1]->store(zip_stat->compressed);
880
 
                table->field[2]->store(zip_stat->compressed_ok);
881
 
                table->field[3]->store(
882
 
                        (ulong) (zip_stat->compressed_usec / 1000000));
883
 
                table->field[4]->store(zip_stat->decompressed);
884
 
                table->field[5]->store(
885
 
                        (ulong) (zip_stat->decompressed_usec / 1000000));
886
 
 
887
 
                if (reset) {
888
 
                        memset(zip_stat, 0, sizeof *zip_stat);
889
 
                }
890
 
 
891
 
                schema_table->addRow(table->record[0],
892
 
                                     table->s->reclength);
893
 
        }
894
 
 
895
 
        return(status);
896
 
}
897
 
 
898
 
/*******************************************************************//**
899
 
Fill the dynamic table information_schema.innodb_cmp.
900
 
@return 0 on success, 1 on failure */
901
 
int
902
 
CmpISMethods::fillTable(
903
 
/*=========*/
904
 
        Session*        session,/*!< in: thread */
905
 
        Table*  table,  /*!< in/out: tables to fill */
906
 
        plugin::InfoSchemaTable *schema_table)
907
 
{
908
 
        return(i_s_cmp_fill_low(session, table, schema_table, FALSE));
909
 
}
910
 
 
911
 
/*******************************************************************//**
912
 
Fill the dynamic table information_schema.innodb_cmp_reset.
913
 
@return 0 on success, 1 on failure */
914
 
int
915
 
CmpResetISMethods::fillTable(
916
 
/*===============*/
917
 
        Session*        session,/*!< in: thread */
918
 
        Table*  table,  /*!< in/out: tables to fill */
919
 
        plugin::InfoSchemaTable *schema_table)
920
 
{
921
 
        return(i_s_cmp_fill_low(session, table, schema_table, TRUE));
922
 
}
923
 
 
924
 
/*******************************************************************//**
925
 
Bind the dynamic table information_schema.innodb_cmp.
926
 
@return 0 on success */
927
 
int
928
 
i_s_cmp_init()
929
 
/*=========*/
930
 
{
931
 
 
932
 
        if ((innodb_cmp_schema_table= new plugin::InfoSchemaTable("INNODB_CMP")) == NULL)
933
 
                return(1);
934
 
 
935
 
        innodb_cmp_schema_table->setColumnInfo(i_s_cmp_fields_info);
936
 
        innodb_cmp_schema_table->setInfoSchemaMethods(&cmp_methods);
937
 
 
938
 
        return(0);
939
 
}
940
 
 
941
 
/*******************************************************************//**
942
 
Bind the dynamic table information_schema.innodb_cmp_reset.
943
 
@return 0 on success */
944
 
int
945
 
i_s_cmp_reset_init()
946
 
/*===============*/
947
 
{
948
 
 
949
 
        if ((innodb_cmp_reset_schema_table= new plugin::InfoSchemaTable("INNODB_CMP_RESET")) == NULL)
950
 
                return(1);
951
 
 
952
 
        innodb_cmp_reset_schema_table->setColumnInfo(i_s_cmp_fields_info);
953
 
        innodb_cmp_reset_schema_table->setInfoSchemaMethods(&cmp_reset_methods);
954
 
 
955
 
        return(0);
956
 
}
957
 
 
958
 
 
959
 
 
960
 
/* Fields of the dynamic table information_schema.innodb_cmpmem. */
961
 
static plugin::ColumnInfo       i_s_cmpmem_fields_info[] =
962
 
{
963
 
        plugin::ColumnInfo("page_size",
964
 
                  5,
965
 
                  DRIZZLE_TYPE_LONG,
966
 
                  0,
967
 
                  0,
968
 
                  "Buddy Block Size"),
969
 
 
970
 
        plugin::ColumnInfo("pages_used",
971
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
972
 
                  DRIZZLE_TYPE_LONG,
973
 
                  0,
974
 
                  0,
975
 
                  "Currently in Use"),
976
 
 
977
 
        plugin::ColumnInfo("pages_free",
978
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
979
 
                  DRIZZLE_TYPE_LONG,
980
 
                  0,
981
 
                  0,
982
 
                  "Currently Available"),
983
 
 
984
 
        plugin::ColumnInfo("relocation_ops",
985
 
                  MY_INT64_NUM_DECIMAL_DIGITS,
986
 
                  DRIZZLE_TYPE_LONGLONG,
987
 
                  0,
988
 
                  0,
989
 
                  "Total Number of Relocations"),
990
 
 
991
 
        plugin::ColumnInfo("relocation_time",
992
 
                  MY_INT32_NUM_DECIMAL_DIGITS,
993
 
                  DRIZZLE_TYPE_LONG,
994
 
                  0,
995
 
                  0,
996
 
                  "Total Duration of Relocations, in Seconds"),
997
 
 
998
 
        plugin::ColumnInfo()
999
 
};
1000
 
 
1001
 
/*******************************************************************//**
1002
 
Fill the dynamic table information_schema.innodb_cmpmem or
1003
 
innodb_cmpmem_reset.
1004
 
@return 0 on success, 1 on failure */
1005
 
static
1006
 
int
1007
 
i_s_cmpmem_fill_low(
1008
 
/*================*/
1009
 
        Session*        session,/*!< in: thread */
1010
 
        Table*  table,  /*!< in/out: tables to fill */
1011
 
        plugin::InfoSchemaTable *schema_table,
1012
 
        ibool           reset)  /*!< in: TRUE=reset cumulated counts */
1013
 
{
1014
 
        int     status  = 0;
1015
 
 
1016
 
        RETURN_IF_INNODB_NOT_STARTED(schema_table->getName().c_str());
1017
 
 
1018
 
        buf_pool_mutex_enter();
1019
 
 
1020
 
        for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
1021
 
                buf_buddy_stat_t*       buddy_stat = &buf_buddy_stat[x];
1022
 
 
1023
 
                table->field[0]->store(BUF_BUDDY_LOW << x);
1024
 
                table->field[1]->store(buddy_stat->used);
1025
 
                table->field[2]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
1026
 
                                       ? UT_LIST_GET_LEN(buf_pool->zip_free[x])
1027
 
                                       : 0);
1028
 
                table->field[3]->store((int64_t) buddy_stat->relocated, true);
1029
 
                table->field[4]->store(
1030
 
                        (ulong) (buddy_stat->relocated_usec / 1000000));
1031
 
 
1032
 
                if (reset) {
1033
 
                        /* This is protected by buf_pool_mutex. */
1034
 
                        buddy_stat->relocated = 0;
1035
 
                        buddy_stat->relocated_usec = 0;
1036
 
                }
1037
 
 
1038
 
                schema_table->addRow(table->record[0],
1039
 
                                     table->s->reclength);
1040
 
        }
1041
 
 
1042
 
        buf_pool_mutex_exit();
1043
 
        return(status);
1044
 
}
1045
 
 
1046
 
/*******************************************************************//**
1047
 
Fill the dynamic table information_schema.innodb_cmpmem.
1048
 
@return 0 on success, 1 on failure */
1049
 
int
1050
 
CmpmemISMethods::fillTable(
1051
 
/*============*/
1052
 
        Session*        session,/*!< in: thread */
1053
 
        Table*  table, /*!< in/out: tables to fill */
1054
 
        plugin::InfoSchemaTable *schema_table)  
1055
 
{
1056
 
        return(i_s_cmpmem_fill_low(session, table, schema_table, FALSE));
1057
 
}
1058
 
 
1059
 
/*******************************************************************//**
1060
 
Fill the dynamic table information_schema.innodb_cmpmem_reset.
1061
 
@return 0 on success, 1 on failure */
1062
 
int
1063
 
CmpmemResetISMethods::fillTable(
1064
 
/*==================*/
1065
 
        Session*        session,/*!< in: thread */
1066
 
        Table*  table,  /*!< in/out: tables to fill */
1067
 
        plugin::InfoSchemaTable *schema_table)
1068
 
{
1069
 
        return(i_s_cmpmem_fill_low(session, table, schema_table, TRUE));
1070
 
}
1071
 
 
1072
 
/*******************************************************************//**
1073
 
Bind the dynamic table information_schema.innodb_cmpmem.
1074
 
@return 0 on success */
1075
 
int
1076
 
i_s_cmpmem_init()
1077
 
/*============*/
1078
 
{
1079
 
 
1080
 
        if ((innodb_cmpmem_schema_table= new plugin::InfoSchemaTable("INNODB_CMPMEM")) == NULL)
1081
 
                return(1);
1082
 
 
1083
 
        innodb_cmpmem_schema_table->setColumnInfo(i_s_cmpmem_fields_info);
1084
 
        innodb_cmpmem_schema_table->setInfoSchemaMethods(&cmpmem_methods);
1085
 
 
1086
 
        return(0);
1087
 
}
1088
 
 
1089
 
/*******************************************************************//**
1090
 
Bind the dynamic table information_schema.innodb_cmpmem_reset.
1091
 
@return 0 on success */
1092
 
int
1093
 
i_s_cmpmem_reset_init()
1094
 
/*==================*/
1095
 
{
1096
 
        if ((innodb_cmpmem_reset_schema_table= new plugin::InfoSchemaTable("INNODB_CMPMEM_RESET")) == NULL)
1097
 
                return(1);
1098
 
 
1099
 
        innodb_cmpmem_reset_schema_table->setColumnInfo(i_s_cmpmem_fields_info);
1100
 
        innodb_cmpmem_reset_schema_table->setInfoSchemaMethods(&cmpmem_reset_methods);
1101
 
        return(0);
1102
 
}
1103
 
 
1104
 
 
1105
 
/*******************************************************************//**
1106
 
Unbind a dynamic INFORMATION_SCHEMA table.
1107
 
@return 0 on success */
1108
 
int
1109
 
i_s_common_deinit(
1110
 
/*==============*/
1111
 
        plugin::Registry &registry)     /*!< in/out: table schema object */
1112
 
{
1113
 
        registry.remove(innodb_trx_schema_table);
1114
 
        registry.remove(innodb_locks_schema_table);
1115
 
        registry.remove(innodb_lock_waits_schema_table);
1116
 
        registry.remove(innodb_cmp_schema_table);
1117
 
        registry.remove(innodb_cmp_reset_schema_table);
1118
 
        registry.remove(innodb_cmpmem_schema_table);
1119
 
        registry.remove(innodb_cmpmem_reset_schema_table);
1120
 
 
1121
 
        delete innodb_trx_schema_table;
1122
 
        delete innodb_locks_schema_table;
1123
 
        delete innodb_lock_waits_schema_table;
1124
 
        delete innodb_cmp_schema_table;
1125
 
        delete innodb_cmp_reset_schema_table;
1126
 
        delete innodb_cmpmem_schema_table;
1127
 
        delete innodb_cmpmem_reset_schema_table;
1128
 
 
1129
 
        return(0);
1130
 
}
1131
 
 
1132
 
#endif