dict0boot.c 11.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/******************************************************
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"

monty@donna.mysql.fi's avatar
Merge  
monty@donna.mysql.fi committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/**************************************************************************
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);
42
#ifdef UNIV_SYNC_DEBUG
monty@donna.mysql.fi's avatar
Merge  
monty@donna.mysql.fi committed
43
	buf_page_dbg_add_level(header, SYNC_DICT_HEADER);
44
#endif /* UNIV_SYNC_DEBUG */
monty@donna.mysql.fi's avatar
Merge  
monty@donna.mysql.fi committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
	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);

68
	id = mtr_read_dulint(dict_hdr + type, &mtr); 
monty@donna.mysql.fi's avatar
Merge  
monty@donna.mysql.fi committed
69 70 71 72 73

	/* Add some dummy code here because otherwise pgcc seems to
	compile wrong */

	if (0 == ut_dulint_cmp(id, ut_dulint_max)) {
74 75
		/* TO DO: remove this code, or make it conditional */
		ut_dbg_null_ptr = 0;
monty@donna.mysql.fi's avatar
Merge  
monty@donna.mysql.fi committed
76 77 78 79
	}

	id = ut_dulint_add(id, 1);
	
80
	mlog_write_dulint(dict_hdr + type, id, &mtr); 
monty@donna.mysql.fi's avatar
Merge  
monty@donna.mysql.fi committed
81 82 83 84 85 86

	mtr_commit(&mtr);

	return(id);
}				

87 88 89 90 91 92 93 94 95 96 97 98
/**************************************************************************
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;

99
#ifdef UNIV_SYNC_DEBUG
100
	ut_ad(mutex_own(&(dict_sys->mutex)));
101
#endif /* UNIV_SYNC_DEBUG */
102 103 104 105 106 107 108

	id = dict_sys->row_id;

	mtr_start(&mtr);

	dict_hdr = dict_hdr_get(&mtr);
	
109
	mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr); 
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

	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,
145
				ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
146 147

	mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
148
				ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
149 150

	mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
151
				ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
152 153

	mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
154
				ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
155 156 157 158 159 160

	/* Create the B-tree roots for the clustered indexes of the basic
	system tables */

	/*--------------------------*/	
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
161
				DICT_HDR_SPACE, DICT_TABLES_ID, FALSE, mtr);
162 163 164 165 166 167 168 169 170
	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,
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
171
						DICT_TABLE_IDS_ID, FALSE, mtr);
172 173 174 175 176 177 178 179 180
	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,
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
181
				DICT_HDR_SPACE, DICT_COLUMNS_ID, FALSE, mtr);
182 183 184 185 186 187 188 189 190
	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,
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
191
				DICT_HDR_SPACE, DICT_INDEXES_ID, FALSE, mtr);
192 193 194 195 196 197 198 199 200
	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,
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
201
				DICT_HDR_SPACE, DICT_FIELDS_ID, FALSE, mtr);
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
	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;
226
	ibool		success;
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

	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,
251
							&mtr),
252 253 254 255 256 257
				DICT_HDR_ROW_ID_WRITE_MARGIN),
			     DICT_HDR_ROW_ID_WRITE_MARGIN);

	/* Insert into the dictionary cache the descriptions of the basic
	system tables */
	/*-------------------------*/
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
258
	table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE);
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
259 260 261 262 263 264 265 266 267

	dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "N_COLS", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "MIX_ID", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "MIX_LEN", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "CLUSTER_NAME", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
268 269 270 271 272 273

	table->id = DICT_TABLES_ID;
	
	dict_table_add_to_cache(table);
	dict_sys->sys_tables = table;
	
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
274 275
	index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
			DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 1);
276

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
277
	dict_mem_index_add_field(index, "NAME", 0, 0);
278 279 280

	index->id = DICT_TABLES_ID;

281 282 283
	success = dict_index_add_to_cache(table, index, mtr_read_ulint(
			dict_hdr + DICT_HDR_TABLES, MLOG_4BYTES, &mtr));
	ut_a(success);
284
	/*-------------------------*/
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
285 286 287
	index = dict_mem_index_create("SYS_TABLES", "ID_IND",
			DICT_HDR_SPACE, DICT_UNIQUE, 1);
	dict_mem_index_add_field(index, "ID", 0, 0);
288 289

	index->id = DICT_TABLE_IDS_ID;
290 291 292
	success = dict_index_add_to_cache(table, index, mtr_read_ulint(
			dict_hdr + DICT_HDR_TABLE_IDS, MLOG_4BYTES, &mtr));
	ut_a(success);
293
	/*-------------------------*/
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
294
	table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE);
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
295 296 297 298 299 300 301 302

	dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0);
	dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "MTYPE", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "PRTYPE", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "LEN", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "PREC", DATA_INT, 0, 4, 0);
303 304 305 306 307 308
	
	table->id = DICT_COLUMNS_ID;

	dict_table_add_to_cache(table);
	dict_sys->sys_columns = table;

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
309 310
	index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
			DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
311

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
312 313
	dict_mem_index_add_field(index, "TABLE_ID", 0, 0);
	dict_mem_index_add_field(index, "POS", 0, 0);
314 315

	index->id = DICT_COLUMNS_ID;
316 317 318
	success = dict_index_add_to_cache(table, index, mtr_read_ulint(
			dict_hdr + DICT_HDR_COLUMNS, MLOG_4BYTES, &mtr));
	ut_a(success);
319
	/*-------------------------*/
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
320
	table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE);
321

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
322 323 324 325 326 327 328
	dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0);
	dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
	dict_mem_table_add_col(table, "N_FIELDS", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "TYPE", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "SPACE", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "PAGE_NO", DATA_INT, 0, 4, 0);
329 330

	/* The '+ 2' below comes from the 2 system fields */
heikki@hundin.mysql.fi's avatar
heikki@hundin.mysql.fi committed
331 332 333 334 335
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
#endif
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
336 337 338
#endif
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
heikki@hundin.mysql.fi's avatar
heikki@hundin.mysql.fi committed
339
#endif
340 341 342 343 344

	table->id = DICT_INDEXES_ID;
	dict_table_add_to_cache(table);
	dict_sys->sys_indexes = table;

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
345 346
	index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
			DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
347

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
348 349
	dict_mem_index_add_field(index, "TABLE_ID", 0, 0);
	dict_mem_index_add_field(index, "ID", 0, 0);
350 351

	index->id = DICT_INDEXES_ID;
352 353 354
	success = dict_index_add_to_cache(table, index, mtr_read_ulint(
			dict_hdr + DICT_HDR_INDEXES, MLOG_4BYTES, &mtr));
	ut_a(success);
355
	/*-------------------------*/
marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
356
	table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE);
357

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
358 359 360
	dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0);
	dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
	dict_mem_table_add_col(table, "COL_NAME", DATA_BINARY, 0,0,0);
361 362 363 364 365

	table->id = DICT_FIELDS_ID;
	dict_table_add_to_cache(table);
	dict_sys->sys_fields = table;

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
366 367
	index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
			DICT_HDR_SPACE, DICT_UNIQUE | DICT_CLUSTERED, 2);
368

marko@hundin.mysql.fi's avatar
marko@hundin.mysql.fi committed
369 370
	dict_mem_index_add_field(index, "INDEX_ID", 0, 0);
	dict_mem_index_add_field(index, "POS", 0, 0);
371 372

	index->id = DICT_FIELDS_ID;
373 374 375
	success = dict_index_add_to_cache(table, index, mtr_read_ulint(
			dict_hdr + DICT_HDR_FIELDS, MLOG_4BYTES, &mtr));
	ut_a(success);
376 377 378

	mtr_commit(&mtr);
	/*-------------------------*/
379 380 381 382 383

	/* Initialize the insert buffer table and index for each tablespace */

	ibuf_init_at_db_start();

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
	/* 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();
}