mariadb/innobase/dict/dict0boot.c
unknown adb703943d Added xml patch to mysqldump.
Made innodb to compile more cleanly with debugging options
enabled. Fixed a few bugs and found a few possible bugs, which
I hope Heikki will check. Comments needs to be fixed too. Some
while() functions should be changed to do ... until for documenting
purposes, because some of them must and will be processed at least
once, or a variable would be used uninitialized.

Regards,
Jani


client/mysqldump.c:
  Added xml output. Patch originally from Gary Huntress, but needed
  a some clean up.
innobase/btr/btr0btr.c:
  cleaner compiling
innobase/btr/btr0cur.c:
  cleaner compiling
innobase/btr/btr0sea.c:
  cleaner compiling / found a bug ??
innobase/buf/buf0buf.c:
  Fixed a bug.
innobase/buf/buf0lru.c:
  Fixed a bug.
innobase/data/data0data.c:
  cleaner compiling
innobase/dict/dict0boot.c:
  cleaner compiling
innobase/dict/dict0crea.c:
  cleaner compiling
innobase/dict/dict0dict.c:
  cleaner compiling
innobase/dict/dict0load.c:
  cleaner compiling
innobase/eval/eval0eval.c:
  cleaner compiling / found a bug ??
innobase/fil/fil0fil.c:
  cleaner compiling
innobase/fsp/fsp0fsp.c:
  cleaner compiling
innobase/ibuf/ibuf0ibuf.c:
  cleaner compiling
innobase/include/btr0btr.ic:
  cleaner compiling
innobase/include/buf0buf.ic:
  cleaner compiling
innobase/include/dict0dict.ic:
  cleaner compiling
innobase/include/ha0ha.ic:
  cleaner compiling
innobase/include/row0mysql.ic:
  cleaner compiling
innobase/include/row0vers.ic:
  cleaner compiling
innobase/include/sync0rw.ic:
  cleaner compiling
innobase/lock/lock0lock.c:
  cleaner compiling
innobase/mem/mem0dbg.c:
  cleaner compiling
innobase/mtr/mtr0mtr.c:
  cleaner compiling
innobase/odbc/odbc0odbc.c:
  cleaner compiling
innobase/os/os0thread.c:
  cleaner compiling
innobase/page/page0cur.c:
  cleaner compiling. while() should be changed to do ... until
  for documenting purposes.
innobase/page/page0page.c:
  cleaner compiling
innobase/pars/pars0opt.c:
  cleaner compiling. while() should be changed to do ... until,
  because it will and must be processed at least once (for documenting
  purposes)
innobase/pars/pars0pars.c:
  cleaner compiling
innobase/que/que0que.c:
  cleaner compiling
innobase/rem/rem0cmp.c:
  cleaner compiling
innobase/rem/rem0rec.c:
  cleaner compiling
innobase/row/row0ins.c:
  cleaner compiling
innobase/row/row0mysql.c:
  cleaner compiling
innobase/row/row0purge.c:
  cleaner compiling
innobase/row/row0sel.c:
  cleaner compiling
innobase/row/row0uins.c:
  cleaner compiling
innobase/row/row0umod.c:
  cleaner compiling
innobase/row/row0upd.c:
  cleaner compiling
innobase/srv/srv0srv.c:
  cleaner compiling
innobase/srv/srv0start.c:
  cleaner compiling
innobase/sync/sync0arr.c:
  cleaner compiling
innobase/sync/sync0rw.c:
  cleaner compiling
innobase/sync/sync0sync.c:
  cleaner compiling
innobase/trx/trx0purge.c:
  cleaner compiling. in theory this could also be a bug, although
  probably not. But the logic needs to be checked, it could be that
  these variables may be used uninitialized.
innobase/trx/trx0rec.c:
  cleaner compiling
innobase/trx/trx0roll.c:
  cleaner compiling
innobase/trx/trx0trx.c:
  cleaner compiling
innobase/trx/trx0undo.c:
  cleaner compiling
2001-11-05 23:48:03 +02:00

424 lines
12 KiB
C

/******************************************************
Data dictionary creation and booting
(c) 1996 Innobase Oy
Created 4/18/1996 Heikki Tuuri
*******************************************************/
#include "dict0boot.h"
#ifdef UNIV_NONINL
#include "dict0boot.ic"
#endif
#include "dict0crea.h"
#include "btr0btr.h"
#include "dict0load.h"
#include "dict0load.h"
#include "trx0trx.h"
#include "srv0srv.h"
#include "ibuf0ibuf.h"
#include "buf0flu.h"
#include "log0recv.h"
#include "os0file.h"
/**************************************************************************
Gets a pointer to the dictionary header and x-latches its page. */
dict_hdr_t*
dict_hdr_get(
/*=========*/
/* out: pointer to the dictionary header,
page x-latched */
mtr_t* mtr) /* in: mtr */
{
dict_hdr_t* header;
ut_ad(mtr);
header = DICT_HDR + buf_page_get(DICT_HDR_SPACE, DICT_HDR_PAGE_NO,
RW_X_LATCH, mtr);
buf_page_dbg_add_level(header, SYNC_DICT_HEADER);
return(header);
}
/**************************************************************************
Returns a new table, index, or tree id. */
dulint
dict_hdr_get_new_id(
/*================*/
/* out: the new id */
ulint type) /* in: DICT_HDR_ROW_ID, ... */
{
dict_hdr_t* dict_hdr;
dulint id;
mtr_t mtr;
ut_ad((type == DICT_HDR_TABLE_ID) || (type == DICT_HDR_INDEX_ID)
|| (type == DICT_HDR_MIX_ID));
mtr_start(&mtr);
dict_hdr = dict_hdr_get(&mtr);
id = mtr_read_dulint(dict_hdr + type, MLOG_8BYTES, &mtr);
/* Add some dummy code here because otherwise pgcc seems to
compile wrong */
if (0 == ut_dulint_cmp(id, ut_dulint_max)) {
printf("Max id\n");
}
id = ut_dulint_add(id, 1);
mlog_write_dulint(dict_hdr + type, id, MLOG_8BYTES, &mtr);
mtr_commit(&mtr);
return(id);
}
/**************************************************************************
Writes the current value of the row id counter to the dictionary header file
page. */
void
dict_hdr_flush_row_id(void)
/*=======================*/
{
dict_hdr_t* dict_hdr;
dulint id;
mtr_t mtr;
ut_ad(mutex_own(&(dict_sys->mutex)));
id = dict_sys->row_id;
mtr_start(&mtr);
dict_hdr = dict_hdr_get(&mtr);
mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, MLOG_8BYTES, &mtr);
mtr_commit(&mtr);
}
/*********************************************************************
Creates the file page for the dictionary header. This function is
called only at the database creation. */
static
ibool
dict_hdr_create(
/*============*/
/* out: TRUE if succeed */
mtr_t* mtr) /* in: mtr */
{
dict_hdr_t* dict_header;
ulint hdr_page_no;
ulint root_page_no;
page_t* page;
ut_ad(mtr);
/* Create the dictionary header file block in a new, allocated file
segment in the system tablespace */
page = fseg_create(DICT_HDR_SPACE, 0,
DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
hdr_page_no = buf_frame_get_page_no(page);
ut_a(DICT_HDR_PAGE_NO == hdr_page_no);
dict_header = dict_hdr_get(mtr);
/* Start counting row, table, index, and tree ids from
DICT_HDR_FIRST_ID */
mlog_write_dulint(dict_header + DICT_HDR_ROW_ID,
ut_dulint_create(0, DICT_HDR_FIRST_ID),
MLOG_8BYTES, mtr);
mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
ut_dulint_create(0, DICT_HDR_FIRST_ID),
MLOG_8BYTES, mtr);
mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
ut_dulint_create(0, DICT_HDR_FIRST_ID),
MLOG_8BYTES, mtr);
mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
ut_dulint_create(0, DICT_HDR_FIRST_ID),
MLOG_8BYTES, mtr);
/* Create the B-tree roots for the clustered indexes of the basic
system tables */
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_TABLES_ID, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
}
mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE,
DICT_TABLE_IDS_ID, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
}
mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_COLUMNS_ID, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
}
mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_INDEXES_ID, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
}
mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
DICT_HDR_SPACE, DICT_FIELDS_ID, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
}
mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
MLOG_4BYTES, mtr);
/*--------------------------*/
return(TRUE);
}
/*********************************************************************
Initializes the data dictionary memory structures when the database is
started. This function is also called when the data dictionary is created. */
void
dict_boot(void)
/*===========*/
{
dict_table_t* table;
dict_index_t* index;
dict_hdr_t* dict_hdr;
mtr_t mtr;
mtr_start(&mtr);
/* Create the hash tables etc. */
dict_init();
mutex_enter(&(dict_sys->mutex));
/* Get the dictionary header */
dict_hdr = dict_hdr_get(&mtr);
/* Because we only write new row ids to disk-based data structure
(dictionary header) when it is divisible by
DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
the latest value of the row id counter. Therefore we advance
the counter at the database startup to avoid overlapping values.
Note that when a user after database startup first time asks for
a new row id, then because the counter is now divisible by
..._MARGIN, it will immediately be updated to the disk-based
header. */
dict_sys->row_id = ut_dulint_add(
ut_dulint_align_up(
mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID,
MLOG_8BYTES, &mtr),
DICT_HDR_ROW_ID_WRITE_MARGIN),
DICT_HDR_ROW_ID_WRITE_MARGIN);
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
table = dict_mem_table_create((char *) "SYS_TABLES", DICT_HDR_SPACE,8);
dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, (char *) "ID", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, (char *) "N_COLS", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "TYPE", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "MIX_ID", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, (char *) "MIX_LEN", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "CLUSTER_NAME", DATA_BINARY,
0, 0, 0);
dict_mem_table_add_col(table, (char *) "SPACE", DATA_INT, 0, 4, 0);
table->id = DICT_TABLES_ID;
dict_table_add_to_cache(table);
dict_sys->sys_tables = table;
index = dict_mem_index_create((char *) "SYS_TABLES", (char *)
"CLUST_IND",
DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 1);
dict_mem_index_add_field(index, (char *) "NAME", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLES,
MLOG_4BYTES, &mtr);
index->id = DICT_TABLES_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
index = dict_mem_index_create((char *) "SYS_TABLES",
(char *) "ID_IND", DICT_HDR_SPACE,
DICT_UNIQUE, 1);
dict_mem_index_add_field(index, (char *) "ID", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_TABLE_IDS,
MLOG_4BYTES, &mtr);
index->id = DICT_TABLE_IDS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
table = dict_mem_table_create((char *) "SYS_COLUMNS",DICT_HDR_SPACE,7);
dict_mem_table_add_col(table, (char *) "TABLE_ID", DATA_BINARY,0,0,0);
dict_mem_table_add_col(table, (char *) "POS", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, (char *) "MTYPE", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "PRTYPE", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "LEN", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "PREC", DATA_INT, 0, 4, 0);
table->id = DICT_COLUMNS_ID;
dict_table_add_to_cache(table);
dict_sys->sys_columns = table;
index = dict_mem_index_create((char *) "SYS_COLUMNS",
(char *) "CLUST_IND", DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, (char *) "TABLE_ID", 0);
dict_mem_index_add_field(index, (char *) "POS", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_COLUMNS,
MLOG_4BYTES, &mtr);
index->id = DICT_COLUMNS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
table = dict_mem_table_create((char *) "SYS_INDEXES",DICT_HDR_SPACE,7);
dict_mem_table_add_col(table, (char *) "TABLE_ID", DATA_BINARY, 0,0,0);
dict_mem_table_add_col(table, (char *) "ID", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, (char *) "NAME", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, (char *) "N_FIELDS", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "TYPE", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "SPACE", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "PAGE_NO", DATA_INT, 0, 4, 0);
/* The '+ 2' below comes from the 2 system fields */
ut_ad(DICT_SYS_INDEXES_PAGE_NO_FIELD == 6 + 2);
ut_ad(DICT_SYS_INDEXES_SPACE_NO_FIELD == 5 + 2);
table->id = DICT_INDEXES_ID;
dict_table_add_to_cache(table);
dict_sys->sys_indexes = table;
index = dict_mem_index_create((char *) "SYS_INDEXES",
(char *) "CLUST_IND", DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, (char *) "TABLE_ID", 0);
dict_mem_index_add_field(index, (char *) "ID", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_INDEXES,
MLOG_4BYTES, &mtr);
index->id = DICT_INDEXES_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
table = dict_mem_table_create((char *) "SYS_FIELDS", DICT_HDR_SPACE,3);
dict_mem_table_add_col(table, (char *) "INDEX_ID", DATA_BINARY, 0,0,0);
dict_mem_table_add_col(table, (char *) "POS", DATA_INT, 0, 4, 0);
dict_mem_table_add_col(table, (char *) "COL_NAME", DATA_BINARY, 0,0,0);
table->id = DICT_FIELDS_ID;
dict_table_add_to_cache(table);
dict_sys->sys_fields = table;
index = dict_mem_index_create((char *) "SYS_FIELDS",
(char *) "CLUST_IND", DICT_HDR_SPACE,
DICT_UNIQUE | DICT_CLUSTERED, 2);
dict_mem_index_add_field(index, (char *) "INDEX_ID", 0);
dict_mem_index_add_field(index, (char *) "POS", 0);
index->page_no = mtr_read_ulint(dict_hdr + DICT_HDR_FIELDS,
MLOG_4BYTES, &mtr);
index->id = DICT_FIELDS_ID;
ut_a(dict_index_add_to_cache(table, index));
mtr_commit(&mtr);
/*-------------------------*/
/* Initialize the insert buffer table and index for each tablespace */
ibuf_init_at_db_start();
/* Load definitions of other indexes on system tables */
dict_load_sys_table(dict_sys->sys_tables);
dict_load_sys_table(dict_sys->sys_columns);
dict_load_sys_table(dict_sys->sys_indexes);
dict_load_sys_table(dict_sys->sys_fields);
mutex_exit(&(dict_sys->mutex));
}
/*********************************************************************
Inserts the basic system table data into themselves in the database
creation. */
static
void
dict_insert_initial_data(void)
/*==========================*/
{
/* Does nothing yet */
}
/*********************************************************************
Creates and initializes the data dictionary at the database creation. */
void
dict_create(void)
/*=============*/
{
mtr_t mtr;
mtr_start(&mtr);
dict_hdr_create(&mtr);
mtr_commit(&mtr);
dict_boot();
dict_insert_initial_data();
sync_order_checks_on = TRUE;
}