Drizzled Public API Documentation

dict0boot.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 St, Fifth Floor, Boston, MA 02110-1301 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #include "dict0boot.h"
27 
28 #ifdef UNIV_NONINL
29 #include "dict0boot.ic"
30 #endif
31 
32 #include "dict0crea.h"
33 #include "btr0btr.h"
34 #include "dict0load.h"
35 #include "dict0load.h"
36 #include "trx0trx.h"
37 #include "srv0srv.h"
38 #include "ibuf0ibuf.h"
39 #include "buf0flu.h"
40 #include "log0recv.h"
41 #include "os0file.h"
42 
43 /**********************************************************************/
46 UNIV_INTERN
47 dict_hdr_t*
48 dict_hdr_get(
49 /*=========*/
50  mtr_t* mtr)
51 {
52  buf_block_t* block;
53  dict_hdr_t* header;
54 
55  block = buf_page_get(DICT_HDR_SPACE, 0, DICT_HDR_PAGE_NO,
56  RW_X_LATCH, mtr);
57  header = DICT_HDR + buf_block_get_frame(block);
58 
59  buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
60 
61  return(header);
62 }
63 
64 /**********************************************************************/
66 UNIV_INTERN
67 void
68 dict_hdr_get_new_id(
69 /*================*/
70  table_id_t* table_id,
72  index_id_t* index_id,
74  ulint* space_id)
76 {
77  dict_hdr_t* dict_hdr;
78  ib_id_t id;
79  mtr_t mtr;
80 
81  mtr_start(&mtr);
82 
83  dict_hdr = dict_hdr_get(&mtr);
84 
85  if (table_id) {
86  id = mach_read_from_8(dict_hdr + DICT_HDR_TABLE_ID);
87  id++;
88  mlog_write_ull(dict_hdr + DICT_HDR_TABLE_ID, id, &mtr);
89  *table_id = id;
90  }
91 
92  if (index_id) {
93  id = mach_read_from_8(dict_hdr + DICT_HDR_INDEX_ID);
94  id++;
95  mlog_write_ull(dict_hdr + DICT_HDR_INDEX_ID, id, &mtr);
96  *index_id = id;
97  }
98 
99  if (space_id) {
100  *space_id = mtr_read_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
101  MLOG_4BYTES, &mtr);
102  if (fil_assign_new_space_id(space_id)) {
103  mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
104  *space_id, MLOG_4BYTES, &mtr);
105  }
106  }
107 
108  mtr_commit(&mtr);
109 }
110 
111 /**********************************************************************/
114 UNIV_INTERN
115 void
116 dict_hdr_flush_row_id(void)
117 /*=======================*/
118 {
119  dict_hdr_t* dict_hdr;
120  row_id_t id;
121  mtr_t mtr;
122 
123  ut_ad(mutex_own(&(dict_sys->mutex)));
124 
125  id = dict_sys->row_id;
126 
127  mtr_start(&mtr);
128 
129  dict_hdr = dict_hdr_get(&mtr);
130 
131  mlog_write_ull(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
132 
133  mtr_commit(&mtr);
134 }
135 
136 /*****************************************************************/
140 static
141 ibool
142 dict_hdr_create(
143 /*============*/
144  mtr_t* mtr)
145 {
146  buf_block_t* block;
147  dict_hdr_t* dict_header;
148  ulint root_page_no;
149 
150  ut_ad(mtr);
151 
152  /* Create the dictionary header file block in a new, allocated file
153  segment in the system tablespace */
154  block = fseg_create(DICT_HDR_SPACE, 0,
155  DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
156 
157  ut_a(DICT_HDR_PAGE_NO == buf_block_get_page_no(block));
158 
159  dict_header = dict_hdr_get(mtr);
160 
161  /* Start counting row, table, index, and tree ids from
162  DICT_HDR_FIRST_ID */
163  mlog_write_ull(dict_header + DICT_HDR_ROW_ID,
164  DICT_HDR_FIRST_ID, mtr);
165 
166  mlog_write_ull(dict_header + DICT_HDR_TABLE_ID,
167  DICT_HDR_FIRST_ID, mtr);
168 
169  mlog_write_ull(dict_header + DICT_HDR_INDEX_ID,
170  DICT_HDR_FIRST_ID, mtr);
171 
172  mlog_write_ulint(dict_header + DICT_HDR_MAX_SPACE_ID,
173  0, MLOG_4BYTES, mtr);
174 
175  /* Obsolete, but we must initialize it anyway. */
176  mlog_write_ulint(dict_header + DICT_HDR_MIX_ID_LOW,
177  DICT_HDR_FIRST_ID, MLOG_4BYTES, mtr);
178 
179  /* Create the B-tree roots for the clustered indexes of the basic
180  system tables */
181 
182  /*--------------------------*/
183  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
184  DICT_HDR_SPACE, 0, DICT_TABLES_ID,
185  dict_ind_redundant, mtr);
186  if (root_page_no == FIL_NULL) {
187 
188  return(FALSE);
189  }
190 
191  mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
192  MLOG_4BYTES, mtr);
193  /*--------------------------*/
194  root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, 0,
195  DICT_TABLE_IDS_ID,
196  dict_ind_redundant, mtr);
197  if (root_page_no == FIL_NULL) {
198 
199  return(FALSE);
200  }
201 
202  mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
203  MLOG_4BYTES, mtr);
204  /*--------------------------*/
205  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
206  DICT_HDR_SPACE, 0, DICT_COLUMNS_ID,
207  dict_ind_redundant, mtr);
208  if (root_page_no == FIL_NULL) {
209 
210  return(FALSE);
211  }
212 
213  mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
214  MLOG_4BYTES, mtr);
215  /*--------------------------*/
216  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
217  DICT_HDR_SPACE, 0, DICT_INDEXES_ID,
218  dict_ind_redundant, mtr);
219  if (root_page_no == FIL_NULL) {
220 
221  return(FALSE);
222  }
223 
224  mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
225  MLOG_4BYTES, mtr);
226  /*--------------------------*/
227  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
228  DICT_HDR_SPACE, 0, DICT_FIELDS_ID,
229  dict_ind_redundant, mtr);
230  if (root_page_no == FIL_NULL) {
231 
232  return(FALSE);
233  }
234 
235  mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
236  MLOG_4BYTES, mtr);
237  /*--------------------------*/
238 
239  return(TRUE);
240 }
241 
242 /*****************************************************************/
245 UNIV_INTERN
246 void
247 dict_boot(void)
248 /*===========*/
249 {
250  dict_table_t* table;
251  dict_index_t* index;
252  dict_hdr_t* dict_hdr;
253  mem_heap_t* heap;
254  mtr_t mtr;
255  ulint error;
256 
257  mtr_start(&mtr);
258 
259  /* Create the hash tables etc. */
260  dict_init();
261 
262  heap = mem_heap_create(450);
263 
264  mutex_enter(&(dict_sys->mutex));
265 
266  /* Get the dictionary header */
267  dict_hdr = dict_hdr_get(&mtr);
268 
269  /* Because we only write new row ids to disk-based data structure
270  (dictionary header) when it is divisible by
271  DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
272  the latest value of the row id counter. Therefore we advance
273  the counter at the database startup to avoid overlapping values.
274  Note that when a user after database startup first time asks for
275  a new row id, then because the counter is now divisible by
276  ..._MARGIN, it will immediately be updated to the disk-based
277  header. */
278 
279  dict_sys->row_id = DICT_HDR_ROW_ID_WRITE_MARGIN
280  + ut_uint64_align_up(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID),
281  DICT_HDR_ROW_ID_WRITE_MARGIN);
282 
283  /* Insert into the dictionary cache the descriptions of the basic
284  system tables */
285  /*-------------------------*/
286  table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0);
287 
288  dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
289  dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
290  /* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
291  dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
292  /* TYPE is either DICT_TABLE_ORDINARY, or (TYPE & DICT_TF_COMPACT)
293  and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
294  dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
295  dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
296  /* MIX_LEN may contain additional table flags when
297  ROW_FORMAT!=REDUNDANT. Currently, these flags include
298  DICT_TF2_TEMPORARY. */
299  dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
300  dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
301  dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
302 
303  table->id = DICT_TABLES_ID;
304 
305  dict_table_add_to_cache(table, heap);
306  dict_sys->sys_tables = table;
307  mem_heap_empty(heap);
308 
309  index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
310  DICT_HDR_SPACE,
312 
313  dict_mem_index_add_field(index, "NAME", 0);
314 
315  index->id = DICT_TABLES_ID;
316 
317  error = dict_index_add_to_cache(table, index,
318  mtr_read_ulint(dict_hdr
319  + DICT_HDR_TABLES,
320  MLOG_4BYTES, &mtr),
321  FALSE);
322  ut_a(error == DB_SUCCESS);
323 
324  /*-------------------------*/
325  index = dict_mem_index_create("SYS_TABLES", "ID_IND",
326  DICT_HDR_SPACE, DICT_UNIQUE, 1);
327  dict_mem_index_add_field(index, "ID", 0);
328 
329  index->id = DICT_TABLE_IDS_ID;
330  error = dict_index_add_to_cache(table, index,
331  mtr_read_ulint(dict_hdr
332  + DICT_HDR_TABLE_IDS,
333  MLOG_4BYTES, &mtr),
334  FALSE);
335  ut_a(error == DB_SUCCESS);
336 
337  /*-------------------------*/
338  table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
339 
340  dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
341  dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
342  dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
343  dict_mem_table_add_col(table, heap, "MTYPE", DATA_INT, 0, 4);
344  dict_mem_table_add_col(table, heap, "PRTYPE", DATA_INT, 0, 4);
345  dict_mem_table_add_col(table, heap, "LEN", DATA_INT, 0, 4);
346  dict_mem_table_add_col(table, heap, "PREC", DATA_INT, 0, 4);
347 
348  table->id = DICT_COLUMNS_ID;
349 
350  dict_table_add_to_cache(table, heap);
351  dict_sys->sys_columns = table;
352  mem_heap_empty(heap);
353 
354  index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
355  DICT_HDR_SPACE,
357 
358  dict_mem_index_add_field(index, "TABLE_ID", 0);
359  dict_mem_index_add_field(index, "POS", 0);
360 
361  index->id = DICT_COLUMNS_ID;
362  error = dict_index_add_to_cache(table, index,
363  mtr_read_ulint(dict_hdr
364  + DICT_HDR_COLUMNS,
365  MLOG_4BYTES, &mtr),
366  FALSE);
367  ut_a(error == DB_SUCCESS);
368 
369  /*-------------------------*/
370  table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
371 
372  dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
373  dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
374  dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
375  dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
376  dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
377  dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
378  dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
379 
380  /* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
381 #if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
382 #error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
383 #endif
384 #if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
385 #error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
386 #endif
387 #if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
388 #error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
389 #endif
390 #if DICT_SYS_INDEXES_NAME_FIELD != 2 + 2
391 #error "DICT_SYS_INDEXES_NAME_FIELD != 2 + 2"
392 #endif
393 
394  table->id = DICT_INDEXES_ID;
395  dict_table_add_to_cache(table, heap);
396  dict_sys->sys_indexes = table;
397  mem_heap_empty(heap);
398 
399  index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
400  DICT_HDR_SPACE,
402 
403  dict_mem_index_add_field(index, "TABLE_ID", 0);
404  dict_mem_index_add_field(index, "ID", 0);
405 
406  index->id = DICT_INDEXES_ID;
407  error = dict_index_add_to_cache(table, index,
408  mtr_read_ulint(dict_hdr
409  + DICT_HDR_INDEXES,
410  MLOG_4BYTES, &mtr),
411  FALSE);
412  ut_a(error == DB_SUCCESS);
413 
414  /*-------------------------*/
415  table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
416 
417  dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
418  dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
419  dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
420 
421  table->id = DICT_FIELDS_ID;
422  dict_table_add_to_cache(table, heap);
423  dict_sys->sys_fields = table;
424  mem_heap_free(heap);
425 
426  index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
427  DICT_HDR_SPACE,
429 
430  dict_mem_index_add_field(index, "INDEX_ID", 0);
431  dict_mem_index_add_field(index, "POS", 0);
432 
433  index->id = DICT_FIELDS_ID;
434  error = dict_index_add_to_cache(table, index,
435  mtr_read_ulint(dict_hdr
436  + DICT_HDR_FIELDS,
437  MLOG_4BYTES, &mtr),
438  FALSE);
439  ut_a(error == DB_SUCCESS);
440 
441  mtr_commit(&mtr);
442  /*-------------------------*/
443 
444  /* Initialize the insert buffer table and index for each tablespace */
445 
446  ibuf_init_at_db_start();
447 
448  /* Load definitions of other indexes on system tables */
449 
450  dict_load_sys_table(dict_sys->sys_tables);
451  dict_load_sys_table(dict_sys->sys_columns);
452  dict_load_sys_table(dict_sys->sys_indexes);
453  dict_load_sys_table(dict_sys->sys_fields);
454 
455  mutex_exit(&(dict_sys->mutex));
456 }
457 
458 /*****************************************************************/
461 static
462 void
463 dict_insert_initial_data(void)
464 /*==========================*/
465 {
466  /* Does nothing yet */
467 }
468 
469 /*****************************************************************/
471 UNIV_INTERN
472 void
473 dict_create(void)
474 /*=============*/
475 {
476  mtr_t mtr;
477 
478  mtr_start(&mtr);
479 
480  dict_hdr_create(&mtr);
481 
482  mtr_commit(&mtr);
483 
484  dict_boot();
485 
486  dict_insert_initial_data();
487 }