Drizzled Public API Documentation

dict0boot.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1996, 2010, 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 /**************************************************/
00026 #include "dict0boot.h"
00027 
00028 #ifdef UNIV_NONINL
00029 #include "dict0boot.ic"
00030 #endif
00031 
00032 #include "dict0crea.h"
00033 #include "btr0btr.h"
00034 #include "dict0load.h"
00035 #include "dict0load.h"
00036 #include "trx0trx.h"
00037 #include "srv0srv.h"
00038 #include "ibuf0ibuf.h"
00039 #include "buf0flu.h"
00040 #include "log0recv.h"
00041 #include "os0file.h"
00042 
00043 /**********************************************************************/
00046 UNIV_INTERN
00047 dict_hdr_t*
00048 dict_hdr_get(
00049 /*=========*/
00050   mtr_t*  mtr)  
00051 {
00052   buf_block_t*  block;
00053   dict_hdr_t* header;
00054 
00055   block = buf_page_get(DICT_HDR_SPACE, 0, DICT_HDR_PAGE_NO,
00056            RW_X_LATCH, mtr);
00057   header = DICT_HDR + buf_block_get_frame(block);
00058 
00059   buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
00060 
00061   return(header);
00062 }
00063 
00064 /**********************************************************************/
00066 UNIV_INTERN
00067 void
00068 dict_hdr_get_new_id(
00069 /*================*/
00070   table_id_t* table_id, 
00072   index_id_t* index_id, 
00074   ulint*    space_id) 
00076 {
00077   dict_hdr_t* dict_hdr;
00078   ib_id_t   id;
00079   mtr_t   mtr;
00080 
00081   mtr_start(&mtr);
00082 
00083   dict_hdr = dict_hdr_get(&mtr);
00084 
00085   if (table_id) {
00086     id = mach_read_from_8(dict_hdr + DICT_HDR_TABLE_ID);
00087     id++;
00088     mlog_write_ull(dict_hdr + DICT_HDR_TABLE_ID, id, &mtr);
00089     *table_id = id;
00090   }
00091 
00092   if (index_id) {
00093     id = mach_read_from_8(dict_hdr + DICT_HDR_INDEX_ID);
00094     id++;
00095     mlog_write_ull(dict_hdr + DICT_HDR_INDEX_ID, id, &mtr);
00096     *index_id = id;
00097   }
00098 
00099   if (space_id) {
00100     *space_id = mtr_read_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
00101              MLOG_4BYTES, &mtr);
00102     if (fil_assign_new_space_id(space_id)) {
00103       mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
00104            *space_id, MLOG_4BYTES, &mtr);
00105     }
00106   }
00107 
00108   mtr_commit(&mtr);
00109 }
00110 
00111 /**********************************************************************/
00114 UNIV_INTERN
00115 void
00116 dict_hdr_flush_row_id(void)
00117 /*=======================*/
00118 {
00119   dict_hdr_t* dict_hdr;
00120   row_id_t  id;
00121   mtr_t   mtr;
00122 
00123   ut_ad(mutex_own(&(dict_sys->mutex)));
00124 
00125   id = dict_sys->row_id;
00126 
00127   mtr_start(&mtr);
00128 
00129   dict_hdr = dict_hdr_get(&mtr);
00130 
00131   mlog_write_ull(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
00132 
00133   mtr_commit(&mtr);
00134 }
00135 
00136 /*****************************************************************/
00140 static
00141 ibool
00142 dict_hdr_create(
00143 /*============*/
00144   mtr_t*  mtr)  
00145 {
00146   buf_block_t*  block;
00147   dict_hdr_t* dict_header;
00148   ulint   root_page_no;
00149 
00150   ut_ad(mtr);
00151 
00152   /* Create the dictionary header file block in a new, allocated file
00153   segment in the system tablespace */
00154   block = fseg_create(DICT_HDR_SPACE, 0,
00155           DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
00156 
00157   ut_a(DICT_HDR_PAGE_NO == buf_block_get_page_no(block));
00158 
00159   dict_header = dict_hdr_get(mtr);
00160 
00161   /* Start counting row, table, index, and tree ids from
00162   DICT_HDR_FIRST_ID */
00163   mlog_write_ull(dict_header + DICT_HDR_ROW_ID,
00164            DICT_HDR_FIRST_ID, mtr);
00165 
00166   mlog_write_ull(dict_header + DICT_HDR_TABLE_ID,
00167            DICT_HDR_FIRST_ID, mtr);
00168 
00169   mlog_write_ull(dict_header + DICT_HDR_INDEX_ID,
00170            DICT_HDR_FIRST_ID, mtr);
00171 
00172   mlog_write_ulint(dict_header + DICT_HDR_MAX_SPACE_ID,
00173        0, MLOG_4BYTES, mtr);
00174 
00175   /* Obsolete, but we must initialize it anyway. */
00176   mlog_write_ulint(dict_header + DICT_HDR_MIX_ID_LOW,
00177        DICT_HDR_FIRST_ID, MLOG_4BYTES, mtr);
00178 
00179   /* Create the B-tree roots for the clustered indexes of the basic
00180   system tables */
00181 
00182   /*--------------------------*/
00183   root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
00184           DICT_HDR_SPACE, 0, DICT_TABLES_ID,
00185           dict_ind_redundant, mtr);
00186   if (root_page_no == FIL_NULL) {
00187 
00188     return(FALSE);
00189   }
00190 
00191   mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
00192        MLOG_4BYTES, mtr);
00193   /*--------------------------*/
00194   root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, 0,
00195           DICT_TABLE_IDS_ID,
00196           dict_ind_redundant, mtr);
00197   if (root_page_no == FIL_NULL) {
00198 
00199     return(FALSE);
00200   }
00201 
00202   mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
00203        MLOG_4BYTES, mtr);
00204   /*--------------------------*/
00205   root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
00206           DICT_HDR_SPACE, 0, DICT_COLUMNS_ID,
00207           dict_ind_redundant, mtr);
00208   if (root_page_no == FIL_NULL) {
00209 
00210     return(FALSE);
00211   }
00212 
00213   mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
00214        MLOG_4BYTES, mtr);
00215   /*--------------------------*/
00216   root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
00217           DICT_HDR_SPACE, 0, DICT_INDEXES_ID,
00218           dict_ind_redundant, mtr);
00219   if (root_page_no == FIL_NULL) {
00220 
00221     return(FALSE);
00222   }
00223 
00224   mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
00225        MLOG_4BYTES, mtr);
00226   /*--------------------------*/
00227   root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
00228           DICT_HDR_SPACE, 0, DICT_FIELDS_ID,
00229           dict_ind_redundant, mtr);
00230   if (root_page_no == FIL_NULL) {
00231 
00232     return(FALSE);
00233   }
00234 
00235   mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
00236        MLOG_4BYTES, mtr);
00237   /*--------------------------*/
00238 
00239   return(TRUE);
00240 }
00241 
00242 /*****************************************************************/
00245 UNIV_INTERN
00246 void
00247 dict_boot(void)
00248 /*===========*/
00249 {
00250   dict_table_t* table;
00251   dict_index_t* index;
00252   dict_hdr_t* dict_hdr;
00253   mem_heap_t* heap;
00254   mtr_t   mtr;
00255   ulint   error;
00256 
00257   mtr_start(&mtr);
00258 
00259   /* Create the hash tables etc. */
00260   dict_init();
00261 
00262   heap = mem_heap_create(450);
00263 
00264   mutex_enter(&(dict_sys->mutex));
00265 
00266   /* Get the dictionary header */
00267   dict_hdr = dict_hdr_get(&mtr);
00268 
00269   /* Because we only write new row ids to disk-based data structure
00270   (dictionary header) when it is divisible by
00271   DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
00272   the latest value of the row id counter. Therefore we advance
00273   the counter at the database startup to avoid overlapping values.
00274   Note that when a user after database startup first time asks for
00275   a new row id, then because the counter is now divisible by
00276   ..._MARGIN, it will immediately be updated to the disk-based
00277   header. */
00278 
00279   dict_sys->row_id = DICT_HDR_ROW_ID_WRITE_MARGIN
00280     + ut_uint64_align_up(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID),
00281              DICT_HDR_ROW_ID_WRITE_MARGIN);
00282 
00283   /* Insert into the dictionary cache the descriptions of the basic
00284   system tables */
00285   /*-------------------------*/
00286   table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0);
00287 
00288   dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
00289   dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
00290   /* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
00291   dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
00292   /* TYPE is either DICT_TABLE_ORDINARY, or (TYPE & DICT_TF_COMPACT)
00293   and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
00294   dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
00295   dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
00296   /* MIX_LEN may contain additional table flags when
00297   ROW_FORMAT!=REDUNDANT.  Currently, these flags include
00298   DICT_TF2_TEMPORARY. */
00299   dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
00300   dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
00301   dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
00302 
00303   table->id = DICT_TABLES_ID;
00304 
00305   dict_table_add_to_cache(table, heap);
00306   dict_sys->sys_tables = table;
00307   mem_heap_empty(heap);
00308 
00309   index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
00310               DICT_HDR_SPACE,
00311               DICT_UNIQUE | DICT_CLUSTERED, 1);
00312 
00313   dict_mem_index_add_field(index, "NAME", 0);
00314 
00315   index->id = DICT_TABLES_ID;
00316 
00317   error = dict_index_add_to_cache(table, index,
00318           mtr_read_ulint(dict_hdr
00319                    + DICT_HDR_TABLES,
00320                    MLOG_4BYTES, &mtr),
00321           FALSE);
00322   ut_a(error == DB_SUCCESS);
00323 
00324   /*-------------------------*/
00325   index = dict_mem_index_create("SYS_TABLES", "ID_IND",
00326               DICT_HDR_SPACE, DICT_UNIQUE, 1);
00327   dict_mem_index_add_field(index, "ID", 0);
00328 
00329   index->id = DICT_TABLE_IDS_ID;
00330   error = dict_index_add_to_cache(table, index,
00331           mtr_read_ulint(dict_hdr
00332                    + DICT_HDR_TABLE_IDS,
00333                    MLOG_4BYTES, &mtr),
00334           FALSE);
00335   ut_a(error == DB_SUCCESS);
00336 
00337   /*-------------------------*/
00338   table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
00339 
00340   dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
00341   dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
00342   dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
00343   dict_mem_table_add_col(table, heap, "MTYPE", DATA_INT, 0, 4);
00344   dict_mem_table_add_col(table, heap, "PRTYPE", DATA_INT, 0, 4);
00345   dict_mem_table_add_col(table, heap, "LEN", DATA_INT, 0, 4);
00346   dict_mem_table_add_col(table, heap, "PREC", DATA_INT, 0, 4);
00347 
00348   table->id = DICT_COLUMNS_ID;
00349 
00350   dict_table_add_to_cache(table, heap);
00351   dict_sys->sys_columns = table;
00352   mem_heap_empty(heap);
00353 
00354   index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
00355               DICT_HDR_SPACE,
00356               DICT_UNIQUE | DICT_CLUSTERED, 2);
00357 
00358   dict_mem_index_add_field(index, "TABLE_ID", 0);
00359   dict_mem_index_add_field(index, "POS", 0);
00360 
00361   index->id = DICT_COLUMNS_ID;
00362   error = dict_index_add_to_cache(table, index,
00363           mtr_read_ulint(dict_hdr
00364                    + DICT_HDR_COLUMNS,
00365                    MLOG_4BYTES, &mtr),
00366           FALSE);
00367   ut_a(error == DB_SUCCESS);
00368 
00369   /*-------------------------*/
00370   table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
00371 
00372   dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
00373   dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
00374   dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
00375   dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
00376   dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
00377   dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
00378   dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
00379 
00380   /* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
00381 #if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
00382 #error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
00383 #endif
00384 #if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
00385 #error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
00386 #endif
00387 #if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
00388 #error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
00389 #endif
00390 #if DICT_SYS_INDEXES_NAME_FIELD != 2 + 2
00391 #error "DICT_SYS_INDEXES_NAME_FIELD != 2 + 2"
00392 #endif
00393 
00394   table->id = DICT_INDEXES_ID;
00395   dict_table_add_to_cache(table, heap);
00396   dict_sys->sys_indexes = table;
00397   mem_heap_empty(heap);
00398 
00399   index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
00400               DICT_HDR_SPACE,
00401               DICT_UNIQUE | DICT_CLUSTERED, 2);
00402 
00403   dict_mem_index_add_field(index, "TABLE_ID", 0);
00404   dict_mem_index_add_field(index, "ID", 0);
00405 
00406   index->id = DICT_INDEXES_ID;
00407   error = dict_index_add_to_cache(table, index,
00408           mtr_read_ulint(dict_hdr
00409                    + DICT_HDR_INDEXES,
00410                    MLOG_4BYTES, &mtr),
00411           FALSE);
00412   ut_a(error == DB_SUCCESS);
00413 
00414   /*-------------------------*/
00415   table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
00416 
00417   dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
00418   dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
00419   dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
00420 
00421   table->id = DICT_FIELDS_ID;
00422   dict_table_add_to_cache(table, heap);
00423   dict_sys->sys_fields = table;
00424   mem_heap_free(heap);
00425 
00426   index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
00427               DICT_HDR_SPACE,
00428               DICT_UNIQUE | DICT_CLUSTERED, 2);
00429 
00430   dict_mem_index_add_field(index, "INDEX_ID", 0);
00431   dict_mem_index_add_field(index, "POS", 0);
00432 
00433   index->id = DICT_FIELDS_ID;
00434   error = dict_index_add_to_cache(table, index,
00435           mtr_read_ulint(dict_hdr
00436                    + DICT_HDR_FIELDS,
00437                    MLOG_4BYTES, &mtr),
00438           FALSE);
00439   ut_a(error == DB_SUCCESS);
00440 
00441   mtr_commit(&mtr);
00442   /*-------------------------*/
00443 
00444   /* Initialize the insert buffer table and index for each tablespace */
00445 
00446   ibuf_init_at_db_start();
00447 
00448   /* Load definitions of other indexes on system tables */
00449 
00450   dict_load_sys_table(dict_sys->sys_tables);
00451   dict_load_sys_table(dict_sys->sys_columns);
00452   dict_load_sys_table(dict_sys->sys_indexes);
00453   dict_load_sys_table(dict_sys->sys_fields);
00454 
00455   mutex_exit(&(dict_sys->mutex));
00456 }
00457 
00458 /*****************************************************************/
00461 static
00462 void
00463 dict_insert_initial_data(void)
00464 /*==========================*/
00465 {
00466   /* Does nothing yet */
00467 }
00468 
00469 /*****************************************************************/
00471 UNIV_INTERN
00472 void
00473 dict_create(void)
00474 /*=============*/
00475 {
00476   mtr_t mtr;
00477 
00478   mtr_start(&mtr);
00479 
00480   dict_hdr_create(&mtr);
00481 
00482   mtr_commit(&mtr);
00483 
00484   dict_boot();
00485 
00486   dict_insert_initial_data();
00487 }