~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Tags: innodb-plugin-1.0.1
Imported 1.0.1 with clean - with no changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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);
 
42
#ifdef UNIV_SYNC_DEBUG
 
43
        buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
 
44
#endif /* UNIV_SYNC_DEBUG */
 
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,
 
282
                                                       MLOG_4BYTES, &mtr));
 
283
        ut_a(error == DB_SUCCESS);
 
284
 
 
285
        /*-------------------------*/
 
286
        index = dict_mem_index_create("SYS_TABLES", "ID_IND",
 
287
                                      DICT_HDR_SPACE, DICT_UNIQUE, 1);
 
288
        dict_mem_index_add_field(index, "ID", 0);
 
289
 
 
290
        index->id = DICT_TABLE_IDS_ID;
 
291
        error = dict_index_add_to_cache(table, index,
 
292
                                        mtr_read_ulint(dict_hdr
 
293
                                                       + DICT_HDR_TABLE_IDS,
 
294
                                                       MLOG_4BYTES, &mtr));
 
295
        ut_a(error == DB_SUCCESS);
 
296
 
 
297
        /*-------------------------*/
 
298
        table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
 
299
 
 
300
        dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
 
301
        dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
 
302
        dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
 
303
        dict_mem_table_add_col(table, heap, "MTYPE", DATA_INT, 0, 4);
 
304
        dict_mem_table_add_col(table, heap, "PRTYPE", DATA_INT, 0, 4);
 
305
        dict_mem_table_add_col(table, heap, "LEN", DATA_INT, 0, 4);
 
306
        dict_mem_table_add_col(table, heap, "PREC", DATA_INT, 0, 4);
 
307
 
 
308
        table->id = DICT_COLUMNS_ID;
 
309
 
 
310
        dict_table_add_to_cache(table, heap);
 
311
        dict_sys->sys_columns = table;
 
312
        mem_heap_empty(heap);
 
313
 
 
314
        index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
 
315
                                      DICT_HDR_SPACE,
 
316
                                      DICT_UNIQUE | DICT_CLUSTERED, 2);
 
317
 
 
318
        dict_mem_index_add_field(index, "TABLE_ID", 0);
 
319
        dict_mem_index_add_field(index, "POS", 0);
 
320
 
 
321
        index->id = DICT_COLUMNS_ID;
 
322
        error = dict_index_add_to_cache(table, index,
 
323
                                        mtr_read_ulint(dict_hdr
 
324
                                                       + DICT_HDR_COLUMNS,
 
325
                                                       MLOG_4BYTES, &mtr));
 
326
        ut_a(error == DB_SUCCESS);
 
327
 
 
328
        /*-------------------------*/
 
329
        table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
 
330
 
 
331
        dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
 
332
        dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
 
333
        dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
 
334
        dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
 
335
        dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
 
336
        dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
 
337
        dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
 
338
 
 
339
        /* The '+ 2' below comes from the 2 system fields */
 
340
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
 
341
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
 
342
#endif
 
343
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
 
344
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
 
345
#endif
 
346
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
 
347
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
 
348
#endif
 
349
 
 
350
        table->id = DICT_INDEXES_ID;
 
351
        dict_table_add_to_cache(table, heap);
 
352
        dict_sys->sys_indexes = table;
 
353
        mem_heap_empty(heap);
 
354
 
 
355
        index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
 
356
                                      DICT_HDR_SPACE,
 
357
                                      DICT_UNIQUE | DICT_CLUSTERED, 2);
 
358
 
 
359
        dict_mem_index_add_field(index, "TABLE_ID", 0);
 
360
        dict_mem_index_add_field(index, "ID", 0);
 
361
 
 
362
        index->id = DICT_INDEXES_ID;
 
363
        error = dict_index_add_to_cache(table, index,
 
364
                                        mtr_read_ulint(dict_hdr
 
365
                                                       + DICT_HDR_INDEXES,
 
366
                                                       MLOG_4BYTES, &mtr));
 
367
        ut_a(error == DB_SUCCESS);
 
368
 
 
369
        /*-------------------------*/
 
370
        table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
 
371
 
 
372
        dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
 
373
        dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
 
374
        dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
 
375
 
 
376
        table->id = DICT_FIELDS_ID;
 
377
        dict_table_add_to_cache(table, heap);
 
378
        dict_sys->sys_fields = table;
 
379
        mem_heap_free(heap);
 
380
 
 
381
        index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
 
382
                                      DICT_HDR_SPACE,
 
383
                                      DICT_UNIQUE | DICT_CLUSTERED, 2);
 
384
 
 
385
        dict_mem_index_add_field(index, "INDEX_ID", 0);
 
386
        dict_mem_index_add_field(index, "POS", 0);
 
387
 
 
388
        index->id = DICT_FIELDS_ID;
 
389
        error = dict_index_add_to_cache(table, index,
 
390
                                        mtr_read_ulint(dict_hdr
 
391
                                                       + DICT_HDR_FIELDS,
 
392
                                                       MLOG_4BYTES, &mtr));
 
393
        ut_a(error == DB_SUCCESS);
 
394
 
 
395
        mtr_commit(&mtr);
 
396
        /*-------------------------*/
 
397
 
 
398
        /* Initialize the insert buffer table and index for each tablespace */
 
399
 
 
400
        ibuf_init_at_db_start();
 
401
 
 
402
        /* Load definitions of other indexes on system tables */
 
403
 
 
404
        dict_load_sys_table(dict_sys->sys_tables);
 
405
        dict_load_sys_table(dict_sys->sys_columns);
 
406
        dict_load_sys_table(dict_sys->sys_indexes);
 
407
        dict_load_sys_table(dict_sys->sys_fields);
 
408
 
 
409
        mutex_exit(&(dict_sys->mutex));
 
410
}
 
411
 
 
412
/*********************************************************************
 
413
Inserts the basic system table data into themselves in the database
 
414
creation. */
 
415
static
 
416
void
 
417
dict_insert_initial_data(void)
 
418
/*==========================*/
 
419
{
 
420
        /* Does nothing yet */
 
421
}
 
422
 
 
423
/*********************************************************************
 
424
Creates and initializes the data dictionary at the database creation. */
 
425
UNIV_INTERN
 
426
void
 
427
dict_create(void)
 
428
/*=============*/
 
429
{
 
430
        mtr_t   mtr;
 
431
 
 
432
        mtr_start(&mtr);
 
433
 
 
434
        dict_hdr_create(&mtr);
 
435
 
 
436
        mtr_commit(&mtr);
 
437
 
 
438
        dict_boot();
 
439
 
 
440
        dict_insert_initial_data();
 
441
}