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 |
}
|