~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/dict/dict0boot.c

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/**************************************************//**
 
20
@file dict/dict0boot.c
 
21
Data dictionary creation and booting
 
22
 
 
23
Created 4/18/1996 Heikki Tuuri
 
24
*******************************************************/
 
25
 
 
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
/**********************************************************************//**
 
44
Gets a pointer to the dictionary header and x-latches its page.
 
45
@return pointer to the dictionary header, page x-latched */
 
46
UNIV_INTERN
 
47
dict_hdr_t*
 
48
dict_hdr_get(
 
49
/*=========*/
 
50
        mtr_t*  mtr)    /*!< in: 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
/**********************************************************************//**
 
65
Returns a new table, index, or space id. */
 
66
UNIV_INTERN
 
67
void
 
68
dict_hdr_get_new_id(
 
69
/*================*/
 
70
        table_id_t*     table_id,       /*!< out: table id
 
71
                                        (not assigned if NULL) */
 
72
        index_id_t*     index_id,       /*!< out: index id
 
73
                                        (not assigned if NULL) */
 
74
        ulint*          space_id)       /*!< out: space id
 
75
                                        (not assigned if NULL) */
 
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
/**********************************************************************//**
 
112
Writes the current value of the row id counter to the dictionary header file
 
113
page. */
 
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
/*****************************************************************//**
 
137
Creates the file page for the dictionary header. This function is
 
138
called only at the database creation.
 
139
@return TRUE if succeed */
 
140
static
 
141
ibool
 
142
dict_hdr_create(
 
143
/*============*/
 
144
        mtr_t*  mtr)    /*!< in: 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
/*****************************************************************//**
 
243
Initializes the data dictionary memory structures when the database is
 
244
started. This function is also called when the data dictionary is created. */
 
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,
 
311
                                      DICT_UNIQUE | DICT_CLUSTERED, 1);
 
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,
 
356
                                      DICT_UNIQUE | DICT_CLUSTERED, 2);
 
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,
 
401
                                      DICT_UNIQUE | DICT_CLUSTERED, 2);
 
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,
 
428
                                      DICT_UNIQUE | DICT_CLUSTERED, 2);
 
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
/*****************************************************************//**
 
459
Inserts the basic system table data into themselves in the database
 
460
creation. */
 
461
static
 
462
void
 
463
dict_insert_initial_data(void)
 
464
/*==========================*/
 
465
{
 
466
        /* Does nothing yet */
 
467
}
 
468
 
 
469
/*****************************************************************//**
 
470
Creates and initializes the data dictionary at the database creation. */
 
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
}