~drizzle-trunk/drizzle/development

641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1
/******************************************************
2
Data dictionary creation and booting
3
4
(c) 1996 Innobase Oy
5
6
Created 4/18/1996 Heikki Tuuri
7
*******************************************************/
8
9
#include "dict0boot.h"
10
11
#ifdef UNIV_NONINL
12
#include "dict0boot.ic"
13
#endif
14
15
#include "dict0crea.h"
16
#include "btr0btr.h"
17
#include "dict0load.h"
18
#include "dict0load.h"
19
#include "trx0trx.h"
20
#include "srv0srv.h"
21
#include "ibuf0ibuf.h"
22
#include "buf0flu.h"
23
#include "log0recv.h"
24
#include "os0file.h"
25
26
/**************************************************************************
27
Gets a pointer to the dictionary header and x-latches its page. */
28
UNIV_INTERN
29
dict_hdr_t*
30
dict_hdr_get(
31
/*=========*/
32
			/* out: pointer to the dictionary header,
33
			page x-latched */
34
	mtr_t*	mtr)	/* in: mtr */
35
{
36
	buf_block_t*	block;
37
	dict_hdr_t*	header;
38
39
	block = buf_page_get(DICT_HDR_SPACE, 0, DICT_HDR_PAGE_NO,
40
			     RW_X_LATCH, mtr);
41
	header = DICT_HDR + buf_block_get_frame(block);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
42
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
43
	buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
44
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
45
	return(header);
46
}
47
48
/**************************************************************************
49
Returns a new table, index, or tree id. */
50
UNIV_INTERN
51
dulint
52
dict_hdr_get_new_id(
53
/*================*/
54
			/* out: the new id */
55
	ulint	type)	/* in: DICT_HDR_ROW_ID, ... */
56
{
57
	dict_hdr_t*	dict_hdr;
58
	dulint		id;
59
	mtr_t		mtr;
60
61
	ut_ad((type == DICT_HDR_TABLE_ID) || (type == DICT_HDR_INDEX_ID));
62
63
	mtr_start(&mtr);
64
65
	dict_hdr = dict_hdr_get(&mtr);
66
67
	id = mtr_read_dulint(dict_hdr + type, &mtr);
68
	id = ut_dulint_add(id, 1);
69
70
	mlog_write_dulint(dict_hdr + type, id, &mtr);
71
72
	mtr_commit(&mtr);
73
74
	return(id);
75
}
76
77
/**************************************************************************
78
Writes the current value of the row id counter to the dictionary header file
79
page. */
80
UNIV_INTERN
81
void
82
dict_hdr_flush_row_id(void)
83
/*=======================*/
84
{
85
	dict_hdr_t*	dict_hdr;
86
	dulint		id;
87
	mtr_t		mtr;
88
89
	ut_ad(mutex_own(&(dict_sys->mutex)));
90
91
	id = dict_sys->row_id;
92
93
	mtr_start(&mtr);
94
95
	dict_hdr = dict_hdr_get(&mtr);
96
97
	mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
98
99
	mtr_commit(&mtr);
100
}
101
102
/*********************************************************************
103
Creates the file page for the dictionary header. This function is
104
called only at the database creation. */
105
static
106
ibool
107
dict_hdr_create(
108
/*============*/
109
			/* out: TRUE if succeed */
110
	mtr_t*	mtr)	/* in: mtr */
111
{
112
	buf_block_t*	block;
113
	dict_hdr_t*	dict_header;
114
	ulint		root_page_no;
115
116
	ut_ad(mtr);
117
118
	/* Create the dictionary header file block in a new, allocated file
119
	segment in the system tablespace */
120
	block = fseg_create(DICT_HDR_SPACE, 0,
121
			    DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
122
123
	ut_a(DICT_HDR_PAGE_NO == buf_block_get_page_no(block));
124
125
	dict_header = dict_hdr_get(mtr);
126
127
	/* Start counting row, table, index, and tree ids from
128
	DICT_HDR_FIRST_ID */
129
	mlog_write_dulint(dict_header + DICT_HDR_ROW_ID,
130
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
131
132
	mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
133
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
134
135
	mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
136
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
137
138
	/* Obsolete, but we must initialize it to 0 anyway. */
139
	mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
140
			  ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
141
142
	/* Create the B-tree roots for the clustered indexes of the basic
143
	system tables */
144
145
	/*--------------------------*/
146
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
147
				  DICT_HDR_SPACE, 0, DICT_TABLES_ID,
148
				  srv_sys->dummy_ind1, mtr);
149
	if (root_page_no == FIL_NULL) {
150
151
		return(FALSE);
152
	}
153
154
	mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
155
			 MLOG_4BYTES, mtr);
156
	/*--------------------------*/
157
	root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, 0,
158
				  DICT_TABLE_IDS_ID,
159
				  srv_sys->dummy_ind1, mtr);
160
	if (root_page_no == FIL_NULL) {
161
162
		return(FALSE);
163
	}
164
165
	mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
166
			 MLOG_4BYTES, mtr);
167
	/*--------------------------*/
168
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
169
				  DICT_HDR_SPACE, 0, DICT_COLUMNS_ID,
170
				  srv_sys->dummy_ind1, mtr);
171
	if (root_page_no == FIL_NULL) {
172
173
		return(FALSE);
174
	}
175
176
	mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
177
			 MLOG_4BYTES, mtr);
178
	/*--------------------------*/
179
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
180
				  DICT_HDR_SPACE, 0, DICT_INDEXES_ID,
181
				  srv_sys->dummy_ind1, mtr);
182
	if (root_page_no == FIL_NULL) {
183
184
		return(FALSE);
185
	}
186
187
	mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
188
			 MLOG_4BYTES, mtr);
189
	/*--------------------------*/
190
	root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
191
				  DICT_HDR_SPACE, 0, DICT_FIELDS_ID,
192
				  srv_sys->dummy_ind1, mtr);
193
	if (root_page_no == FIL_NULL) {
194
195
		return(FALSE);
196
	}
197
198
	mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
199
			 MLOG_4BYTES, mtr);
200
	/*--------------------------*/
201
202
	return(TRUE);
203
}
204
205
/*********************************************************************
206
Initializes the data dictionary memory structures when the database is
207
started. This function is also called when the data dictionary is created. */
208
UNIV_INTERN
209
void
210
dict_boot(void)
211
/*===========*/
212
{
213
	dict_table_t*	table;
214
	dict_index_t*	index;
215
	dict_hdr_t*	dict_hdr;
216
	mem_heap_t*	heap;
217
	mtr_t		mtr;
218
	ulint		error;
219
220
	mtr_start(&mtr);
221
222
	/* Create the hash tables etc. */
223
	dict_init();
224
225
	heap = mem_heap_create(450);
226
227
	mutex_enter(&(dict_sys->mutex));
228
229
	/* Get the dictionary header */
230
	dict_hdr = dict_hdr_get(&mtr);
231
232
	/* Because we only write new row ids to disk-based data structure
233
	(dictionary header) when it is divisible by
234
	DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
235
	the latest value of the row id counter. Therefore we advance
236
	the counter at the database startup to avoid overlapping values.
237
	Note that when a user after database startup first time asks for
238
	a new row id, then because the counter is now divisible by
239
	..._MARGIN, it will immediately be updated to the disk-based
240
	header. */
241
242
	dict_sys->row_id = ut_dulint_add(
243
		ut_dulint_align_up(mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID,
244
						   &mtr),
245
				   DICT_HDR_ROW_ID_WRITE_MARGIN),
246
		DICT_HDR_ROW_ID_WRITE_MARGIN);
247
248
	/* Insert into the dictionary cache the descriptions of the basic
249
	system tables */
250
	/*-------------------------*/
251
	table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0);
252
253
	dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
254
	dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
255
	/* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
256
	dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
257
	/* TYPE is either DICT_TABLE_ORDINARY, or (TYPE & DICT_TF_COMPACT)
258
	and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
259
	dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
260
	dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
261
	dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
262
	dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
263
	dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
264
265
	table->id = DICT_TABLES_ID;
266
267
	dict_table_add_to_cache(table, heap);
268
	dict_sys->sys_tables = table;
269
	mem_heap_empty(heap);
270
271
	index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
272
				      DICT_HDR_SPACE,
273
				      DICT_UNIQUE | DICT_CLUSTERED, 1);
274
275
	dict_mem_index_add_field(index, "NAME", 0);
276
277
	index->id = DICT_TABLES_ID;
278
279
	error = dict_index_add_to_cache(table, index,
280
					mtr_read_ulint(dict_hdr
281
						       + DICT_HDR_TABLES,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
282
						       MLOG_4BYTES, &mtr),
283
					FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
284
	ut_a(error == DB_SUCCESS);
285
286
	/*-------------------------*/
287
	index = dict_mem_index_create("SYS_TABLES", "ID_IND",
288
				      DICT_HDR_SPACE, DICT_UNIQUE, 1);
289
	dict_mem_index_add_field(index, "ID", 0);
290
291
	index->id = DICT_TABLE_IDS_ID;
292
	error = dict_index_add_to_cache(table, index,
293
					mtr_read_ulint(dict_hdr
294
						       + DICT_HDR_TABLE_IDS,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
295
						       MLOG_4BYTES, &mtr),
296
					FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
297
	ut_a(error == DB_SUCCESS);
298
299
	/*-------------------------*/
300
	table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
301
302
	dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
303
	dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
304
	dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
305
	dict_mem_table_add_col(table, heap, "MTYPE", DATA_INT, 0, 4);
306
	dict_mem_table_add_col(table, heap, "PRTYPE", DATA_INT, 0, 4);
307
	dict_mem_table_add_col(table, heap, "LEN", DATA_INT, 0, 4);
308
	dict_mem_table_add_col(table, heap, "PREC", DATA_INT, 0, 4);
309
310
	table->id = DICT_COLUMNS_ID;
311
312
	dict_table_add_to_cache(table, heap);
313
	dict_sys->sys_columns = table;
314
	mem_heap_empty(heap);
315
316
	index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
317
				      DICT_HDR_SPACE,
318
				      DICT_UNIQUE | DICT_CLUSTERED, 2);
319
320
	dict_mem_index_add_field(index, "TABLE_ID", 0);
321
	dict_mem_index_add_field(index, "POS", 0);
322
323
	index->id = DICT_COLUMNS_ID;
324
	error = dict_index_add_to_cache(table, index,
325
					mtr_read_ulint(dict_hdr
326
						       + DICT_HDR_COLUMNS,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
327
						       MLOG_4BYTES, &mtr),
328
					FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
329
	ut_a(error == DB_SUCCESS);
330
331
	/*-------------------------*/
332
	table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
333
334
	dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
335
	dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
336
	dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
337
	dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
338
	dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
339
	dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
340
	dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
341
342
	/* The '+ 2' below comes from the 2 system fields */
343
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
344
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
345
#endif
346
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
347
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
348
#endif
349
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
350
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
351
#endif
352
353
	table->id = DICT_INDEXES_ID;
354
	dict_table_add_to_cache(table, heap);
355
	dict_sys->sys_indexes = table;
356
	mem_heap_empty(heap);
357
358
	index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
359
				      DICT_HDR_SPACE,
360
				      DICT_UNIQUE | DICT_CLUSTERED, 2);
361
362
	dict_mem_index_add_field(index, "TABLE_ID", 0);
363
	dict_mem_index_add_field(index, "ID", 0);
364
365
	index->id = DICT_INDEXES_ID;
366
	error = dict_index_add_to_cache(table, index,
367
					mtr_read_ulint(dict_hdr
368
						       + DICT_HDR_INDEXES,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
369
						       MLOG_4BYTES, &mtr),
370
					FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
371
	ut_a(error == DB_SUCCESS);
372
373
	/*-------------------------*/
374
	table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
375
376
	dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
377
	dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
378
	dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
379
380
	table->id = DICT_FIELDS_ID;
381
	dict_table_add_to_cache(table, heap);
382
	dict_sys->sys_fields = table;
383
	mem_heap_free(heap);
384
385
	index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
386
				      DICT_HDR_SPACE,
387
				      DICT_UNIQUE | DICT_CLUSTERED, 2);
388
389
	dict_mem_index_add_field(index, "INDEX_ID", 0);
390
	dict_mem_index_add_field(index, "POS", 0);
391
392
	index->id = DICT_FIELDS_ID;
393
	error = dict_index_add_to_cache(table, index,
394
					mtr_read_ulint(dict_hdr
395
						       + DICT_HDR_FIELDS,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
396
						       MLOG_4BYTES, &mtr),
397
					FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
398
	ut_a(error == DB_SUCCESS);
399
400
	mtr_commit(&mtr);
401
	/*-------------------------*/
402
403
	/* Initialize the insert buffer table and index for each tablespace */
404
405
	ibuf_init_at_db_start();
406
407
	/* Load definitions of other indexes on system tables */
408
409
	dict_load_sys_table(dict_sys->sys_tables);
410
	dict_load_sys_table(dict_sys->sys_columns);
411
	dict_load_sys_table(dict_sys->sys_indexes);
412
	dict_load_sys_table(dict_sys->sys_fields);
413
414
	mutex_exit(&(dict_sys->mutex));
415
}
416
417
/*********************************************************************
418
Inserts the basic system table data into themselves in the database
419
creation. */
420
static
421
void
422
dict_insert_initial_data(void)
423
/*==========================*/
424
{
425
	/* Does nothing yet */
426
}
427
428
/*********************************************************************
429
Creates and initializes the data dictionary at the database creation. */
430
UNIV_INTERN
431
void
432
dict_create(void)
433
/*=============*/
434
{
435
	mtr_t	mtr;
436
437
	mtr_start(&mtr);
438
439
	dict_hdr_create(&mtr);
440
441
	mtr_commit(&mtr);
442
443
	dict_boot();
444
445
	dict_insert_initial_data();
446
}