Drizzled Public API Documentation

data_dictionary.cc

00001 /*****************************************************************************
00002 
00003 Copyright (C) 2007, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
00016 
00017 *****************************************************************************/
00018 
00019 #include <config.h>
00020 
00021 #include "data_dictionary.h"
00022 
00023 #include <drizzled/current_session.h>
00024 
00025 #include "trx0i_s.h"
00026 #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
00027 #include "buf0buddy.h" /* for i_s_cmpmem */
00028 #include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
00029 #include "ha_prototypes.h" /* for innobase_convert_name() */
00030 #include "srv0start.h" /* for srv_was_started */
00031 #include "btr0pcur.h" /* for file sys_tables related info. */
00032 #include "btr0types.h"
00033 #include "dict0load.h"  /* for file sys_tables related info. */
00034 #include "dict0mem.h"
00035 #include "dict0types.h"
00036 #include "handler0vars.h"
00037 
00038 using namespace drizzled;
00039 
00040 InnodbSysTablesTool::InnodbSysTablesTool() :
00041   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_TABLES")
00042 {
00043   add_field("TABLE_ID", plugin::TableFunction::NUMBER, 0, false);
00044   add_field("NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00045   add_field("FLAG", plugin::TableFunction::NUMBER, 0, false);
00046   add_field("N_COLS", plugin::TableFunction::NUMBER, 0, false);
00047   add_field("SPACE", plugin::TableFunction::NUMBER, 0, false);
00048 }
00049 
00050 InnodbSysTablesTool::Generator::Generator(Field **arg) :
00051   plugin::TableFunction::Generator(arg)
00052 {
00053   heap= NULL;
00054 }
00055 
00056 bool InnodbSysTablesTool::Generator::populate()
00057 {
00058   if (heap == NULL)
00059   {
00060     heap = mem_heap_create(1000);
00061     mutex_enter(&(dict_sys->mutex));
00062     mtr_start(&mtr);
00063 
00064     rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
00065   }
00066   else
00067   {
00068     /* Get the next record */
00069     mutex_enter(&dict_sys->mutex);
00070     mtr_start(&mtr);
00071     rec = dict_getnext_system(&pcur, &mtr);
00072   }
00073 
00074   if (! rec)
00075   {
00076     mtr_commit(&mtr);
00077     mutex_exit(&dict_sys->mutex);
00078     mem_heap_free(heap);
00079     return false;
00080   }
00081 
00082   const char* err_msg;
00083   dict_table_t* table_rec;
00084 
00085   /* Create and populate a dict_table_t structure with
00086      information from SYS_TABLES row */
00087   err_msg = dict_process_sys_tables_rec(heap, rec, &table_rec,
00088                                         DICT_TABLE_LOAD_FROM_RECORD);
00089 
00090   mtr_commit(&mtr);
00091   mutex_exit(&dict_sys->mutex);
00092 
00093   if (!err_msg) {
00094     push(table_rec->id);
00095     push(table_rec->name);
00096     push(static_cast<uint64_t>(table_rec->flags));
00097     push(static_cast<uint64_t>(table_rec->n_cols));
00098     push(static_cast<uint64_t>(table_rec->space));
00099   } else {
00100 /*    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00101                         ER_CANT_FIND_SYSTEM_REC,
00102                         err_msg);
00103 */  }
00104 
00105   /* Since dict_process_sys_tables_rec() is called with
00106      DICT_TABLE_LOAD_FROM_RECORD, the table_rec is created in
00107      dict_process_sys_tables_rec(), we will need to free it */
00108   if (table_rec) {
00109     dict_mem_table_free(table_rec);
00110   }
00111 
00112   mem_heap_empty(heap);
00113 
00114   return true;
00115 }
00116 
00117 InnodbSysTableStatsTool::InnodbSysTableStatsTool() :
00118   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_TABLESTATS")
00119 {
00120   add_field("TABLE_ID", plugin::TableFunction::NUMBER, 0, false);
00121   add_field("NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00122   add_field("STATS_INITIALIZED", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00123   add_field("NUM_ROWS", plugin::TableFunction::NUMBER, 0, false);
00124   add_field("CLUST_INDEX_SIZE", plugin::TableFunction::NUMBER, 0, false);
00125   add_field("OTHER_INDEX_SIZE", plugin::TableFunction::NUMBER, 0, false);
00126   add_field("MODIFIED_COUNTER", plugin::TableFunction::NUMBER, 0, false);
00127   add_field("AUTOINC", plugin::TableFunction::NUMBER, 0, false);
00128   add_field("HANDLES_OPENED", plugin::TableFunction::NUMBER, 0, false);
00129 }
00130 
00131 InnodbSysTableStatsTool::Generator::Generator(Field **arg) :
00132   plugin::TableFunction::Generator(arg)
00133 {
00134   heap= NULL;
00135 }
00136 
00137 bool InnodbSysTableStatsTool::Generator::populate()
00138 {
00139   if (heap == NULL)
00140   {
00141     heap = mem_heap_create(1000);
00142     mutex_enter(&dict_sys->mutex);
00143     mtr_start(&mtr);
00144     rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
00145   }
00146   else
00147   {
00148     /* Get the next record */
00149     mutex_enter(&dict_sys->mutex);
00150     mtr_start(&mtr);
00151     rec = dict_getnext_system(&pcur, &mtr);
00152   }
00153 
00154   if (!rec)
00155   {
00156     mtr_commit(&mtr);
00157     mutex_exit(&dict_sys->mutex);
00158     mem_heap_free(heap);
00159     return false;
00160   }
00161 
00162   const char* err_msg;
00163   dict_table_t* table_rec;
00164 
00165   /* Fetch the dict_table_t structure corresponding to
00166      this SYS_TABLES record */
00167   err_msg = dict_process_sys_tables_rec(heap, rec, &table_rec,
00168                                         DICT_TABLE_LOAD_FROM_CACHE);
00169 
00170   mtr_commit(&mtr);
00171   mutex_exit(&dict_sys->mutex);
00172 
00173   if (!err_msg) {
00174     push(table_rec->id);
00175     push(table_rec->name);
00176     if (table_rec->stat_initialized)
00177       push("Initialized");
00178     else
00179       push("Uninitialized");
00180     push(table_rec->stat_n_rows);
00181     push(static_cast<uint64_t>(table_rec->stat_clustered_index_size));
00182     push(static_cast<uint64_t>(table_rec->stat_sum_of_other_index_sizes));
00183     push(static_cast<uint64_t>(table_rec->stat_modified_counter));
00184     push(table_rec->autoinc);
00185     push(static_cast<uint64_t>(table_rec->n_mysql_handles_opened));
00186   } else {
00187     /*    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
00188                         ER_CANT_FIND_SYSTEM_REC,
00189                         err_msg);*/
00190   }
00191 
00192   mem_heap_empty(heap);
00193 
00194   return true;
00195 }
00196 
00197 InnodbSysIndexesTool::InnodbSysIndexesTool() :
00198   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_INDEXES")
00199 {
00200   add_field("INDEX_ID", plugin::TableFunction::NUMBER, 0, false);
00201   add_field("NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00202   add_field("TABLE_ID", plugin::TableFunction::NUMBER, 0, false);
00203   add_field("TYPE", plugin::TableFunction::NUMBER, 0, false);
00204   add_field("N_FIELDS", plugin::TableFunction::NUMBER, 0, false);
00205   add_field("PAGE_NO", plugin::TableFunction::NUMBER, 0, false);
00206   add_field("SPACE", plugin::TableFunction::NUMBER, 0, false);
00207 }
00208 
00209 InnodbSysIndexesTool::Generator::Generator(Field **arg) :
00210   plugin::TableFunction::Generator(arg)
00211 {
00212   heap= NULL;
00213 }
00214 
00215 bool InnodbSysIndexesTool::Generator::populate()
00216 {
00217   if (heap == NULL)
00218   {
00219     heap = mem_heap_create(1000);
00220     mutex_enter(&dict_sys->mutex);
00221     mtr_start(&mtr);
00222 
00223     /* Start scan the SYS_INDEXES table */
00224     rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
00225   }
00226   else
00227   {
00228     /* Get the next record */
00229     mutex_enter(&dict_sys->mutex);
00230     mtr_start(&mtr);
00231     rec = dict_getnext_system(&pcur, &mtr);
00232   }
00233 
00234   if (! rec)
00235   {
00236     mtr_commit(&mtr);
00237     mutex_exit(&dict_sys->mutex);
00238     mem_heap_free(heap);
00239     return false;
00240   }
00241 
00242   const char* err_msg;;
00243   table_id_t  table_id;
00244   dict_index_t  index_rec;
00245 
00246   /* Populate a dict_index_t structure with information from
00247      a SYS_INDEXES row */
00248   err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
00249                                          &table_id);
00250 
00251   mtr_commit(&mtr);
00252   mutex_exit(&dict_sys->mutex);
00253   if (!err_msg) {
00254     push(index_rec.id);
00255     push(index_rec.name);
00256     push(static_cast<uint64_t>(table_id));
00257     push(static_cast<uint64_t>(index_rec.type));
00258     push(static_cast<uint64_t>(index_rec.n_fields));
00259     push(static_cast<uint64_t>(index_rec.page));
00260     push(static_cast<uint64_t>(index_rec.space));
00261   } else {
00262 /*    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
00263                         ER_CANT_FIND_SYSTEM_REC,
00264                         err_msg);*/
00265   }
00266 
00267   mem_heap_empty(heap);
00268 
00269   if (!rec)
00270   {
00271     mtr_commit(&mtr);
00272     mutex_exit(&dict_sys->mutex);
00273     mem_heap_free(heap);
00274     return false;
00275   }
00276 
00277   return true;
00278 }
00279 
00280 InnodbSysColumnsTool::InnodbSysColumnsTool() :
00281   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_COLUMNS")
00282 {
00283   add_field("TABLE_ID", plugin::TableFunction::NUMBER, 0, false);
00284   add_field("NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00285   add_field("POS", plugin::TableFunction::NUMBER, 0, false);
00286   add_field("MTYPE", plugin::TableFunction::NUMBER, 0, false);
00287   add_field("PRTYPE", plugin::TableFunction::NUMBER, 0, false);
00288   add_field("LEN", plugin::TableFunction::NUMBER, 0, false);
00289 }
00290 
00291 InnodbSysColumnsTool::Generator::Generator(Field **arg) :
00292   plugin::TableFunction::Generator(arg)
00293 {
00294   heap= NULL;
00295 }
00296 
00297 bool InnodbSysColumnsTool::Generator::populate()
00298 {
00299   if (heap == NULL)
00300   {
00301     heap = mem_heap_create(1000);
00302     mutex_enter(&dict_sys->mutex);
00303     mtr_start(&mtr);
00304     rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
00305   }
00306   else
00307   {
00308     /* Get the next record */
00309     mutex_enter(&dict_sys->mutex);
00310     mtr_start(&mtr);
00311     rec = dict_getnext_system(&pcur, &mtr);
00312   }
00313 
00314   if (! rec)
00315   {
00316     mtr_commit(&mtr);
00317     mutex_exit(&dict_sys->mutex);
00318     mem_heap_free(heap);
00319     return false;
00320   }
00321 
00322   const char* err_msg;
00323   dict_col_t  column_rec;
00324   table_id_t  table_id;
00325   const char* col_name;
00326 
00327   /* populate a dict_col_t structure with information from
00328      a SYS_COLUMNS row */
00329   err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
00330                    &table_id, &col_name);
00331 
00332   mtr_commit(&mtr);
00333   mutex_exit(&dict_sys->mutex);
00334 
00335   if (!err_msg) {
00336     push(table_id);
00337     push(col_name);
00338     push(static_cast<uint64_t>(column_rec.ind));
00339     push(static_cast<uint64_t>(column_rec.mtype));
00340     push(static_cast<uint64_t>(column_rec.prtype));
00341     push(static_cast<uint64_t>(column_rec.len));
00342   } else {
00343 /*    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
00344                         ER_CANT_FIND_SYSTEM_REC,
00345                         err_msg);*/
00346   }
00347 
00348   mem_heap_empty(heap);
00349 
00350   return true;
00351 }
00352 
00353 InnodbSysFieldsTool::InnodbSysFieldsTool() :
00354   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_FIELDS")
00355 {
00356   add_field("INDEX_ID", plugin::TableFunction::NUMBER, 0, false);
00357   add_field("NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00358   add_field("POS", plugin::TableFunction::NUMBER, 0, false);
00359 }
00360 
00361 InnodbSysFieldsTool::Generator::Generator(Field **arg) :
00362   plugin::TableFunction::Generator(arg)
00363 {
00364   heap= NULL;
00365 }
00366 
00367 bool InnodbSysFieldsTool::Generator::populate()
00368 {
00369   if (heap == NULL)
00370   {
00371     heap = mem_heap_create(1000);
00372     mutex_enter(&dict_sys->mutex);
00373     mtr_start(&mtr);
00374 
00375     /* will save last index id so that we know whether we move to
00376        the next index. This is used to calculate prefix length */
00377     last_id = 0;
00378 
00379     rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
00380   }
00381   else
00382   {
00383     /* Get the next record */
00384     mutex_enter(&dict_sys->mutex);
00385     mtr_start(&mtr);
00386     rec = dict_getnext_system(&pcur, &mtr);
00387   }
00388 
00389   if (! rec)
00390   {
00391     mtr_commit(&mtr);
00392     mutex_exit(&dict_sys->mutex);
00393     mem_heap_free(heap);
00394 
00395     return false;
00396   }
00397 
00398   ulint   pos;
00399   const char* err_msg;
00400   index_id_t  index_id;
00401   dict_field_t  field_rec;
00402 
00403   /* Populate a dict_field_t structure with information from
00404      a SYS_FIELDS row */
00405   err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
00406                                         &pos, &index_id, last_id);
00407 
00408   mtr_commit(&mtr);
00409   mutex_exit(&dict_sys->mutex);
00410 
00411   if (!err_msg) {
00412     push(index_id);
00413     push(field_rec.name);
00414     push(static_cast<uint64_t>(pos));
00415 
00416     last_id = index_id;
00417   } else {
00418 /*    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
00419                         ER_CANT_FIND_SYSTEM_REC,
00420                         err_msg);*/
00421   }
00422 
00423   mem_heap_empty(heap);
00424 
00425   return true;
00426 }
00427 
00428 InnodbSysForeignTool::InnodbSysForeignTool() :
00429   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_FOREIGN")
00430 {
00431   add_field("ID", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00432   add_field("FOR_NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00433   add_field("REF_NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00434   add_field("N_COLS", plugin::TableFunction::NUMBER, 0, false);
00435   add_field("TYPE", plugin::TableFunction::NUMBER, 0, false);
00436 }
00437 
00438 InnodbSysForeignTool::Generator::Generator(Field **arg) :
00439   plugin::TableFunction::Generator(arg)
00440 {
00441   heap= NULL;
00442 }
00443 
00444 bool InnodbSysForeignTool::Generator::populate()
00445 {
00446   if (heap == NULL)
00447   {
00448     heap = mem_heap_create(1000);
00449     mutex_enter(&dict_sys->mutex);
00450     mtr_start(&mtr);
00451 
00452     rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
00453   }
00454   else
00455   {
00456     /* Get the next record */
00457     mtr_start(&mtr);
00458     mutex_enter(&dict_sys->mutex);
00459     rec = dict_getnext_system(&pcur, &mtr);
00460   }
00461 
00462   if (! rec)
00463   {
00464     mtr_commit(&mtr);
00465     mutex_exit(&dict_sys->mutex);
00466     mem_heap_free(heap);
00467     return false;
00468   }
00469 
00470   const char* err_msg;
00471   dict_foreign_t  foreign_rec;
00472 
00473   /* Populate a dict_foreign_t structure with information from
00474      a SYS_FOREIGN row */
00475   err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
00476 
00477   mtr_commit(&mtr);
00478   mutex_exit(&dict_sys->mutex);
00479 
00480   if (!err_msg) {
00481     push(foreign_rec.id);
00482     push(foreign_rec.foreign_table_name);
00483     push(foreign_rec.referenced_table_name);
00484     push(static_cast<uint64_t>(foreign_rec.n_fields));
00485     push(static_cast<uint64_t>(foreign_rec.type));
00486   } else {
00487 /*    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
00488                         ER_CANT_FIND_SYSTEM_REC,
00489                         err_msg);
00490 */  }
00491 
00492   mem_heap_empty(heap);
00493 
00494   return true;
00495 }
00496 
00497 InnodbSysForeignColsTool::InnodbSysForeignColsTool() :
00498   plugin::TableFunction("DATA_DICTIONARY", "INNODB_SYS_FOREIGN_COLS")
00499 {
00500   add_field("ID", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00501   add_field("FOR_COL_NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00502   add_field("REF_COL_NAME", plugin::TableFunction::STRING, NAME_LEN + 1, false);
00503   add_field("POS", plugin::TableFunction::NUMBER, 0, false);
00504 }
00505 
00506 InnodbSysForeignColsTool::Generator::Generator(Field **arg) :
00507   plugin::TableFunction::Generator(arg)
00508 {
00509   heap= NULL;
00510 }
00511 
00512 bool InnodbSysForeignColsTool::Generator::populate()
00513 {
00514   if (heap == NULL)
00515   {
00516     heap = mem_heap_create(1000);
00517     mutex_enter(&dict_sys->mutex);
00518     mtr_start(&mtr);
00519 
00520     rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
00521   }
00522   else
00523   {
00524     /* Get the next record */
00525     mutex_enter(&dict_sys->mutex);
00526     mtr_start(&mtr);
00527     rec = dict_getnext_system(&pcur, &mtr);
00528   }
00529 
00530   if (! rec)
00531   {
00532     mtr_commit(&mtr);
00533     mutex_exit(&dict_sys->mutex);
00534     mem_heap_free(heap);
00535 
00536     return false;
00537   }
00538 
00539   const char* err_msg;
00540   const char* name;
00541   const char* for_col_name;
00542   const char* ref_col_name;
00543   ulint   pos;
00544 
00545   /* Extract necessary information from a SYS_FOREIGN_COLS row */
00546   err_msg = dict_process_sys_foreign_col_rec(heap, rec, &name, &for_col_name,
00547                                              &ref_col_name, &pos);
00548 
00549   mtr_commit(&mtr);
00550   mutex_exit(&dict_sys->mutex);
00551 
00552   if (!err_msg) {
00553     push(name);
00554     push(for_col_name);
00555     push(ref_col_name);
00556     push(static_cast<uint64_t>(pos));
00557   } else {
00558 /*    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
00559                         ER_CANT_FIND_SYSTEM_REC,
00560                         err_msg);
00561 */
00562   }
00563 
00564   mem_heap_empty(heap);
00565 
00566   return true;
00567 }
00568 
00569 /*
00570  * Fill the dynamic table data_dictionary.INNODB_CMP and INNODB_CMP_RESET
00571  *
00572  */
00573 CmpTool::CmpTool(bool in_reset) :
00574   plugin::TableFunction("DATA_DICTIONARY", in_reset ? "INNODB_CMP_RESET" : "INNODB_CMP"),
00575   outer_reset(in_reset)
00576 {
00577   add_field("PAGE_SIZE", plugin::TableFunction::NUMBER, 0, false);
00578   add_field("COMPRESS_OPS", plugin::TableFunction::NUMBER, 0, false);
00579   add_field("COMPRESS_OPS_OK", plugin::TableFunction::NUMBER, 0, false);
00580   add_field("COMPRESS_TIME", plugin::TableFunction::NUMBER, 0, false);
00581   add_field("UNCOMPRESS_OPS", plugin::TableFunction::NUMBER, 0, false);
00582   add_field("UNCOMPRESS_TIME", plugin::TableFunction::NUMBER, 0, false);
00583 }
00584 
00585 CmpTool::Generator::Generator(Field **arg, bool in_reset) :
00586   plugin::TableFunction::Generator(arg),
00587   record_number(0),
00588   inner_reset(in_reset)
00589 {
00590 }
00591 
00592 bool CmpTool::Generator::populate()
00593 {
00594   if (record_number == (PAGE_ZIP_NUM_SSIZE - 1))
00595   {
00596     return false;
00597   }
00598 
00599   page_zip_stat_t*        zip_stat = &page_zip_stat[record_number];
00600 
00601   push(static_cast<uint64_t>(PAGE_ZIP_MIN_SIZE << record_number));
00602 
00603   /* The cumulated counts are not protected by any
00604      mutex.  Thus, some operation in page0zip.c could
00605      increment a counter between the time we read it and
00606      clear it.  We could introduce mutex protection, but it
00607      could cause a measureable performance hit in
00608      page0zip.c. */
00609   push(static_cast<uint64_t>(zip_stat->compressed));
00610   push(static_cast<uint64_t>(zip_stat->compressed_ok));
00611   push(zip_stat->compressed_usec / 1000000);
00612   push(static_cast<uint64_t>(zip_stat->decompressed));
00613   push(zip_stat->decompressed_usec / 1000000);
00614 
00615   if (inner_reset)
00616   {
00617     memset(zip_stat, 0, sizeof *zip_stat);
00618   }
00619 
00620   record_number++;
00621 
00622   return true;
00623 }
00624 
00625 /*
00626  * Fill the dynamic table data_dictionary.INNODB_CMPMEM and INNODB_CMPMEM_RESET
00627  *
00628  */
00629 CmpmemTool::CmpmemTool(bool in_reset) :
00630   plugin::TableFunction("DATA_DICTIONARY", in_reset ? "INNODB_CMPMEM_RESET" : "INNODB_CMPMEM"),
00631   outer_reset(in_reset)
00632 {
00633   add_field("BUF_POOL", plugin::TableFunction::NUMBER, 0, false);
00634   add_field("PAGE_SIZE", plugin::TableFunction::NUMBER, 0, false);
00635   add_field("PAGES_USED", plugin::TableFunction::NUMBER, 0, false);
00636   add_field("PAGES_FREE", plugin::TableFunction::NUMBER, 0, false);
00637   add_field("RELOCATION_OPS", plugin::TableFunction::NUMBER, 0, false);
00638   add_field("RELOCATION_TIME", plugin::TableFunction::NUMBER, 0, false);
00639 }
00640 
00641 CmpmemTool::Generator::Generator(Field **arg, bool in_reset) :
00642   plugin::TableFunction::Generator(arg),
00643   record_number(0),
00644   inner_reset(in_reset)
00645 {
00646 }
00647 
00648 CmpmemTool::Generator::~Generator()
00649 {
00650 }
00651 
00652 bool CmpmemTool::Generator::populate()
00653 {
00654   if (record_number >= (BUF_BUDDY_SIZES+1)*srv_buf_pool_instances)
00655   {
00656     return false;
00657   }
00658 
00659   uint32_t buddy_nr= record_number % (BUF_BUDDY_SIZES+1);
00660   uint32_t buf_pool_nr= (record_number/(BUF_BUDDY_SIZES+1));
00661 
00662   buf_pool_t *buf_pool= buf_pool_from_array(buf_pool_nr);
00663 
00664   buf_pool_mutex_enter(buf_pool);
00665 
00666   buf_buddy_stat_t* buddy_stat = &buf_pool->buddy_stat[buddy_nr];
00667 
00668 
00669   push(static_cast<uint64_t>(buf_pool_nr));
00670   push(static_cast<uint64_t>(BUF_BUDDY_LOW << buddy_nr));
00671   push(static_cast<uint64_t>(buddy_stat->used));
00672 
00673 
00674   uint64_t pages_free= (UNIV_LIKELY(buddy_nr < BUF_BUDDY_SIZES) ? UT_LIST_GET_LEN(buf_pool->zip_free[buddy_nr]) : 0);
00675   push(pages_free);
00676 
00677   push(buddy_stat->relocated);
00678   push(buddy_stat->relocated_usec / 1000000);
00679 
00680 
00681   if (inner_reset)
00682   {
00683     buddy_stat->relocated = 0;
00684     buddy_stat->relocated_usec = 0;
00685   }
00686 
00687   buf_pool_mutex_exit(buf_pool);
00688   record_number++;
00689 
00690   return true;
00691 }
00692 
00693 /*
00694  * Fill the dynamic table data_dictionary.INNODB_TRX INNODB_LOCKS INNODB_LOCK_WAITS
00695  *
00696  */
00697 InnodbTrxTool::InnodbTrxTool(const char* in_table_name) :
00698   plugin::TableFunction("DATA_DICTIONARY", in_table_name),
00699   table_name(in_table_name)
00700 {
00701   if (innobase_strcasecmp(table_name, "INNODB_TRX") == 0)
00702   {
00703     add_field("TRX_ID");
00704     add_field("TRX_STATE");
00705     add_field("TRX_STARTED", plugin::TableFunction::NUMBER, 0, false);
00706     add_field("TRX_REQUESTED_LOCK_ID");
00707     add_field("TRX_WAIT_STARTED", plugin::TableFunction::NUMBER, 0, false);
00708     add_field("TRX_WEIGHT", plugin::TableFunction::NUMBER, 0, false);
00709     add_field("TRX_DRIZZLE_THREAD_ID", plugin::TableFunction::NUMBER, 0, false);
00710     add_field("TRX_QUERY", plugin::TableFunction::STRING, TRX_I_S_TRX_QUERY_MAX_LEN, true);
00711     add_field("TRX_OPERATION_STATE", plugin::TableFunction::STRING, TRX_I_S_TRX_OP_STATE_MAX_LEN, true);
00712 //    add_field("TRX_TABLES_IN_USE", plugin::TableFunction::NUMBER, 0, false);
00713     add_field("TRX_TABLES_LOCKED", plugin::TableFunction::NUMBER, 0, false);
00714     add_field("TRX_LOCK_STRUCTS", plugin::TableFunction::NUMBER, 0, false);
00715     add_field("TRX_LOCK_MEMORY_BYTES", plugin::TableFunction::NUMBER, 0, false);
00716     add_field("TRX_ROWS_LOCKED", plugin::TableFunction::NUMBER, 0, false);
00717     add_field("TRX_ROWS_MODIFIED", plugin::TableFunction::NUMBER, 0, false);
00718     add_field("TRX_CONCURRENCY_TICKETS", plugin::TableFunction::NUMBER, 0, false);
00719     add_field("TRX_ISOLATION_LEVEL", plugin::TableFunction::STRING, TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN, false);
00720     add_field("TRX_UNIQUE_CHECKS", plugin::TableFunction::NUMBER, 0, false);
00721     add_field("TRX_FOREIGN_KEY_CHECKS", plugin::TableFunction::NUMBER, 0, false);
00722     add_field("TRX_LAST_FOREIGN_KEY_ERROR", plugin::TableFunction::STRING,
00723               TRX_I_S_TRX_FK_ERROR_MAX_LEN, true);
00724     add_field("TRX_ADAPTIVE_HASH_LATCHED", plugin::TableFunction::NUMBER, 0, false);
00725     add_field("TRX_ADAPTIVE_HASH_TIMEOUT", plugin::TableFunction::NUMBER, 0, false);
00726   }
00727   else if (innobase_strcasecmp(table_name, "INNODB_LOCKS") == 0)
00728   {
00729     add_field("LOCK_ID");
00730     add_field("LOCK_TRX_ID");
00731     add_field("LOCK_MODE");
00732     add_field("LOCK_TYPE");
00733     add_field("LOCK_TABLE");
00734     add_field("LOCK_INDEX");
00735     add_field("LOCK_SPACE", plugin::TableFunction::NUMBER, 0, false);
00736     add_field("LOCK_PAGE", plugin::TableFunction::NUMBER, 0, false);
00737     add_field("LOCK_REC", plugin::TableFunction::NUMBER, 0, false);
00738     add_field("LOCK_DATA");
00739   }
00740   else if (innobase_strcasecmp(table_name, "INNODB_LOCK_WAITS") == 0)
00741   {
00742     add_field("REQUESTING_TRX_ID");  
00743     add_field("REQUESTED_LOCK_ID");
00744     add_field("BLOCKING_TRX_ID");
00745     add_field("BLOCKING_LOCK_ID");
00746   } 
00747 }
00748 
00749 InnodbTrxTool::Generator::Generator(Field **arg, const char* in_table_name) :
00750   plugin::TableFunction::Generator(arg),
00751   table_name(in_table_name)
00752 {
00753   /* update the cache */
00754   trx_i_s_cache_start_write(trx_i_s_cache);
00755   trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache);
00756   trx_i_s_cache_end_write(trx_i_s_cache);
00757 
00758   if (trx_i_s_cache_is_truncated(trx_i_s_cache))
00759   {
00760     errmsg_printf(error::ERROR, _("Warning: data in %s truncated due to memory limit of %d bytes\n"), 
00761                   table_name, TRX_I_S_MEM_LIMIT);
00762   } 
00763 
00764   trx_i_s_cache_start_read(trx_i_s_cache);
00765 
00766   if (innobase_strcasecmp(table_name, "INNODB_TRX") == 0)
00767     number_rows= trx_i_s_cache_get_rows_used(trx_i_s_cache, I_S_INNODB_TRX);
00768   else if (innobase_strcasecmp(table_name, "INNODB_LOCKS") == 0)
00769     number_rows= trx_i_s_cache_get_rows_used(trx_i_s_cache, I_S_INNODB_LOCKS);
00770   else if (innobase_strcasecmp(table_name, "INNODB_LOCK_WAITS") == 0)
00771     number_rows= trx_i_s_cache_get_rows_used(trx_i_s_cache, I_S_INNODB_LOCK_WAITS);
00772 
00773   record_number= 0;
00774 }
00775 
00776 InnodbTrxTool::Generator::~Generator()
00777 {
00778   trx_i_s_cache_end_read(trx_i_s_cache);
00779 }
00780 
00781 bool InnodbTrxTool::Generator::populate()
00782 {
00783   if (record_number == number_rows)
00784   {
00785     return false;
00786   }
00787 
00788   if (innobase_strcasecmp(table_name, "INNODB_TRX") == 0)
00789   {
00790     populate_innodb_trx();
00791   }
00792   else if (innobase_strcasecmp(table_name, "INNODB_LOCKS") == 0)
00793   {
00794     populate_innodb_locks();
00795   }
00796   else if (innobase_strcasecmp(table_name, "INNODB_LOCK_WAITS") == 0)
00797   {
00798     populate_innodb_lock_waits();
00799   }
00800   else 
00801   {
00802     return false;
00803   }
00804   record_number++;
00805 
00806   return true;
00807 }
00808 
00809 void InnodbTrxTool::Generator::populate_innodb_locks()
00810 {
00811 
00812   char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
00813   i_s_locks_row_t* row;
00814 
00815   /* note that the decoded database or table name is
00816      never expected to be longer than NAME_LEN;
00817      NAME_LEN for database name
00818      2 for surrounding quotes around database name
00819      NAME_LEN for table name
00820      2 for surrounding quotes around table name
00821      1 for the separating dot (.)
00822      9 for the #mysql50# prefix 
00823   */
00824 
00825    char buf[2 * NAME_LEN + 14];
00826    const char* bufend;
00827 
00828    char lock_trx_id[TRX_ID_MAX_LEN + 1];
00829 
00830    row = (i_s_locks_row_t*)
00831           trx_i_s_cache_get_nth_row(
00832           trx_i_s_cache, I_S_INNODB_LOCKS, record_number);
00833 
00834 
00835    trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
00836    push(lock_id);
00837 
00838    ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
00839                TRX_ID_FMT, row->lock_trx_id);
00840    push(lock_trx_id);
00841 
00842    push(row->lock_mode);
00843    push(row->lock_type);
00844 
00845    bufend = innobase_convert_name(buf, sizeof(buf),
00846                                   row->lock_table,
00847                                   strlen(row->lock_table),
00848                                   &getSession(), TRUE);
00849    push(bufend);
00850 
00851    if (row->lock_index != NULL)
00852    {
00853      bufend = innobase_convert_name(buf, sizeof(buf),
00854                                     row->lock_index,
00855                                     strlen(row->lock_index),
00856                                     &getSession(), FALSE);
00857      push(bufend);     
00858    }
00859    else 
00860    {
00861      push("");
00862    }   
00863  
00864    push(static_cast<uint64_t>(row->lock_space));
00865    push(static_cast<uint64_t>(row->lock_page)); 
00866    push(static_cast<uint64_t>(row->lock_rec));
00867    push(row->lock_data);
00868 }
00869 
00870 void InnodbTrxTool::Generator::populate_innodb_trx()
00871 {
00872     char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
00873     i_s_trx_row_t* row;
00874     char trx_id[TRX_ID_MAX_LEN + 1];
00875     row = (i_s_trx_row_t*) trx_i_s_cache_get_nth_row(trx_i_s_cache, I_S_INNODB_TRX, record_number);
00876 
00877     /* trx_id */
00878     ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
00879 
00880     push(trx_id);
00881     push(row->trx_state);
00882     push(static_cast<uint64_t>(row->trx_started));
00883 
00884     if (row->trx_wait_started != 0)
00885     {
00886       push(trx_i_s_create_lock_id(row->requested_lock_row, lock_id, sizeof(lock_id)));
00887       push(static_cast<uint64_t>(row->trx_wait_started));
00888     }
00889     else
00890     {
00891       push(static_cast<uint64_t>(0));
00892       push(static_cast<uint64_t>(0));
00893     }
00894 
00895     push(static_cast<int64_t>(row->trx_weight));
00896     push(static_cast<uint64_t>(row->trx_mysql_thread_id));
00897     if (row->trx_query)
00898       push(row->trx_query);
00899     else
00900       push();
00901 
00902     if (row->trx_operation_state)
00903       push(row->trx_operation_state);
00904     else
00905       push();
00906 
00907 //    push(row->trx_tables_in_use);
00908     push(static_cast<uint64_t>(row->trx_tables_locked));
00909     push(static_cast<uint64_t>(row->trx_lock_structs));
00910     push(static_cast<uint64_t>(row->trx_lock_memory_bytes));
00911     push(static_cast<uint64_t>(row->trx_rows_locked));
00912     push(static_cast<uint64_t>(row->trx_rows_modified));
00913     push(static_cast<uint64_t>(row->trx_concurrency_tickets));
00914     push(row->trx_isolation_level);
00915     push(static_cast<uint64_t>(row->trx_unique_checks));
00916     push(static_cast<uint64_t>(row->trx_foreign_key_checks));
00917     if (row->trx_foreign_key_error)
00918       push(row->trx_foreign_key_error);
00919     else
00920       push();
00921 
00922     push(static_cast<uint64_t>(row->trx_has_search_latch));
00923     push(static_cast<uint64_t>(row->trx_search_latch_timeout));
00924 }
00925 
00926 void InnodbTrxTool::Generator::populate_innodb_lock_waits()
00927 {
00928   char requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
00929   char blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
00930 
00931   i_s_lock_waits_row_t* row;
00932 
00933   char requesting_trx_id[TRX_ID_MAX_LEN + 1];
00934   char blocking_trx_id[TRX_ID_MAX_LEN + 1];
00935 
00936   row = (i_s_lock_waits_row_t*)
00937          trx_i_s_cache_get_nth_row(
00938          trx_i_s_cache, I_S_INNODB_LOCK_WAITS, record_number);
00939 
00940   ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
00941               TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
00942   push(requesting_trx_id);
00943 
00944   push(trx_i_s_create_lock_id(row->requested_lock_row, requested_lock_id, 
00945        sizeof(requested_lock_id)));
00946 
00947   ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
00948               TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
00949   push(blocking_trx_id);
00950 
00951   push(trx_i_s_create_lock_id(row->blocking_lock_row, blocking_lock_id, 
00952        sizeof(blocking_lock_id)));
00953 }