~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/fil/fil0fil.c

Merge initial InnoDB+ import.

This was applied by generating a patch between MySQL 5.1.50 InnoDB plugin and
the just-merged innodb+ from mysql-trunk revision-id: vasil.dimov@oracle.com-20100422110752-1zowoqxel5xx3z2e

Then, some manual merge resolving and it worked. This should make it much
easier to merge the rest of InnoDB 1.1 and 1.2 from the mysql tree using
my bzr-reapply script.

This takes us to InnoDB 1.1.1(ish).

Show diffs side-by-side

added added

removed removed

Lines of Context:
121
121
/** The null file address */
122
122
UNIV_INTERN fil_addr_t  fil_addr_null = {FIL_NULL, 0};
123
123
 
 
124
#ifdef UNIV_PFS_MUTEX
 
125
/* Key to register fil_system_mutex with performance schema */
 
126
UNIV_INTERN mysql_pfs_key_t     fil_system_mutex_key;
 
127
#endif /* UNIV_PFS_MUTEX */
 
128
 
 
129
#ifdef UNIV_PFS_RWLOCK
 
130
/* Key to register file space latch with performance schema */
 
131
UNIV_INTERN mysql_pfs_key_t     fil_space_latch_key;
 
132
#endif /* UNIV_PFS_RWLOCK */
 
133
 
124
134
/** File node of a tablespace or the log data space */
125
135
struct fil_node_struct {
126
136
        fil_space_t*    space;  /*!< backpointer to the space where this node
279
289
                                        request */
280
290
        UT_LIST_BASE_NODE_T(fil_space_t) space_list;
281
291
                                        /*!< list of all file spaces */
282
 
        ibool           space_id_reuse_warned;
283
 
                                        /* !< TRUE if fil_space_create()
284
 
                                        has issued a warning about
285
 
                                        potential space_id reuse */
286
292
};
287
293
 
288
294
/** The tablespace memory cache. This variable is NULL before the module is
653
659
                async I/O! */
654
660
 
655
661
                node->handle = os_file_create_simple_no_error_handling(
656
 
                        node->name, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
 
662
                        innodb_file_data_key, node->name, OS_FILE_OPEN,
 
663
                        OS_FILE_READ_ONLY, &success);
657
664
                if (!success) {
658
665
                        /* The following call prints an error message */
659
666
                        os_file_get_last_error(TRUE);
771
778
        os_file_create() to fall back to the normal file I/O mode. */
772
779
 
773
780
        if (space->purpose == FIL_LOG) {
774
 
                node->handle = os_file_create(node->name, OS_FILE_OPEN,
775
 
                                              OS_FILE_AIO, OS_LOG_FILE, &ret);
 
781
                node->handle = os_file_create(innodb_file_log_key,
 
782
                                              node->name, OS_FILE_OPEN,
 
783
                                              OS_FILE_AIO, OS_LOG_FILE,
 
784
                                              &ret);
776
785
        } else if (node->is_raw_disk) {
777
 
                node->handle = os_file_create(node->name,
 
786
                node->handle = os_file_create(innodb_file_data_key,
 
787
                                              node->name,
778
788
                                              OS_FILE_OPEN_RAW,
779
 
                                              OS_FILE_AIO, OS_DATA_FILE, &ret);
 
789
                                              OS_FILE_AIO, OS_DATA_FILE,
 
790
                                                     &ret);
780
791
        } else {
781
 
                node->handle = os_file_create(node->name, OS_FILE_OPEN,
782
 
                                              OS_FILE_AIO, OS_DATA_FILE, &ret);
 
792
                node->handle = os_file_create(innodb_file_data_key,
 
793
                                              node->name, OS_FILE_OPEN,
 
794
                                              OS_FILE_AIO, OS_DATA_FILE,
 
795
                                              &ret);
783
796
        }
784
797
 
785
798
        ut_a(ret);
1197
1210
        space->tablespace_version = fil_system->tablespace_version;
1198
1211
        space->mark = FALSE;
1199
1212
 
1200
 
        if (UNIV_LIKELY(purpose == FIL_TABLESPACE && !recv_recovery_on)
1201
 
            && UNIV_UNLIKELY(id > fil_system->max_assigned_id)) {
1202
 
                if (!fil_system->space_id_reuse_warned) {
1203
 
                        fil_system->space_id_reuse_warned = TRUE;
1204
 
 
1205
 
                        ut_print_timestamp(stderr);
1206
 
                        fprintf(stderr,
1207
 
                                "  InnoDB: Warning: allocated tablespace %lu,"
1208
 
                                " old maximum was %lu\n",
1209
 
                                (ulong) id,
1210
 
                                (ulong) fil_system->max_assigned_id);
1211
 
                }
1212
 
 
 
1213
        if (purpose == FIL_TABLESPACE && id > fil_system->max_assigned_id) {
1213
1214
                fil_system->max_assigned_id = id;
1214
1215
        }
1215
1216
 
1228
1229
        UT_LIST_INIT(space->chain);
1229
1230
        space->magic_n = FIL_SPACE_MAGIC_N;
1230
1231
 
1231
 
        rw_lock_create(&space->latch, SYNC_FSP);
 
1232
        rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
1232
1233
 
1233
1234
        HASH_INSERT(fil_space_t, hash, fil_system->spaces, id, space);
1234
1235
 
1247
1248
Assigns a new space id for a new single-table tablespace. This works simply by
1248
1249
incrementing the global counter. If 4 billion id's is not enough, we may need
1249
1250
to recycle id's.
1250
 
@return TRUE if assigned, FALSE if not */
1251
 
UNIV_INTERN
1252
 
ibool
1253
 
fil_assign_new_space_id(
1254
 
/*====================*/
1255
 
        ulint*  space_id)       /*!< in/out: space id */
 
1251
@return new tablespace id; ULINT_UNDEFINED if could not assign an id */
 
1252
static
 
1253
ulint
 
1254
fil_assign_new_space_id(void)
 
1255
/*=========================*/
1256
1256
{
1257
 
        ulint   id;
1258
 
        ibool   success;
 
1257
        ulint           id;
1259
1258
 
1260
1259
        mutex_enter(&fil_system->mutex);
1261
1260
 
1262
 
        id = *space_id;
1263
 
 
1264
 
        if (id < fil_system->max_assigned_id) {
1265
 
                id = fil_system->max_assigned_id;
1266
 
        }
1267
 
 
1268
 
        id++;
 
1261
        fil_system->max_assigned_id++;
 
1262
 
 
1263
        id = fil_system->max_assigned_id;
1269
1264
 
1270
1265
        if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
1271
1266
                ut_print_timestamp(stderr);
1281
1276
                        (ulong) SRV_LOG_SPACE_FIRST_ID);
1282
1277
        }
1283
1278
 
1284
 
        success = (id < SRV_LOG_SPACE_FIRST_ID);
1285
 
 
1286
 
        if (success) {
1287
 
                *space_id = fil_system->max_assigned_id = id;
1288
 
        } else {
 
1279
        if (id >= SRV_LOG_SPACE_FIRST_ID) {
1289
1280
                ut_print_timestamp(stderr);
1290
1281
                fprintf(stderr,
1291
1282
                        "InnoDB: You have run out of single-table"
1295
1286
                        " have to dump all your tables and\n"
1296
1287
                        "InnoDB: recreate the whole InnoDB installation.\n",
1297
1288
                        (ulong) id);
1298
 
                *space_id = ULINT_UNDEFINED;
 
1289
                fil_system->max_assigned_id--;
 
1290
 
 
1291
                id = ULINT_UNDEFINED;
1299
1292
        }
1300
1293
 
1301
1294
        mutex_exit(&fil_system->mutex);
1302
1295
 
1303
 
        return(success);
 
1296
        return(id);
1304
1297
}
1305
1298
 
1306
1299
/*******************************************************************//**
1536
1529
        ut_a(hash_size > 0);
1537
1530
        ut_a(max_n_open > 0);
1538
1531
 
1539
 
        fil_system = mem_zalloc(sizeof(fil_system_t));
 
1532
        fil_system = mem_alloc(sizeof(fil_system_t));
1540
1533
 
1541
 
        mutex_create(&fil_system->mutex, SYNC_ANY_LATCH);
 
1534
        mutex_create(fil_system_mutex_key,
 
1535
                     &fil_system->mutex, SYNC_ANY_LATCH);
1542
1536
 
1543
1537
        fil_system->spaces = hash_create(hash_size);
1544
1538
        fil_system->name_hash = hash_create(hash_size);
1545
1539
 
1546
1540
        UT_LIST_INIT(fil_system->LRU);
1547
1541
 
 
1542
        fil_system->n_open = 0;
1548
1543
        fil_system->max_n_open = max_n_open;
 
1544
 
 
1545
        fil_system->modification_counter = 0;
 
1546
        fil_system->max_assigned_id = 0;
 
1547
 
 
1548
        fil_system->tablespace_version = 0;
 
1549
 
 
1550
        UT_LIST_INIT(fil_system->unflushed_spaces);
 
1551
        UT_LIST_INIT(fil_system->space_list);
1549
1552
}
1550
1553
 
1551
1554
/*******************************************************************//**
2130
2133
                        fil_create_directory_for_tablename(name);
2131
2134
 
2132
2135
                        if (fil_create_new_single_table_tablespace(
2133
 
                                    space_id, name, FALSE, flags,
 
2136
                                    &space_id, name, FALSE, flags,
2134
2137
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2135
2138
                                ut_error;
2136
2139
                        }
2534
2537
        success = fil_rename_tablespace_in_mem(space, node, path);
2535
2538
 
2536
2539
        if (success) {
2537
 
                success = os_file_rename(old_path, path);
 
2540
                success = os_file_rename(innodb_file_data_key, old_path, path);
2538
2541
 
2539
2542
                if (!success) {
2540
2543
                        /* We have to revert the changes we made
2577
2580
ulint
2578
2581
fil_create_new_single_table_tablespace(
2579
2582
/*===================================*/
2580
 
        ulint           space_id,       /*!< in: space id */
 
2583
        ulint*          space_id,       /*!< in/out: space id; if this is != 0,
 
2584
                                        then this is an input parameter,
 
2585
                                        otherwise output */
2581
2586
        const char*     tablename,      /*!< in: the table name in the usual
2582
2587
                                        databasename/tablename format
2583
2588
                                        of InnoDB, or a dir path to a temp
2597
2602
        ibool           success;
2598
2603
        char*           path;
2599
2604
 
2600
 
        ut_a(space_id > 0);
2601
 
        ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
2602
2605
        ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
2603
2606
        /* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
2604
2607
        ROW_FORMAT=COMPACT
2611
2614
 
2612
2615
        path = fil_make_ibd_name(tablename, is_temp);
2613
2616
 
2614
 
        file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL,
 
2617
        file = os_file_create(innodb_file_data_key, path,
 
2618
                              OS_FILE_CREATE, OS_FILE_NORMAL,
2615
2619
                              OS_DATA_FILE, &ret);
2616
2620
        if (ret == FALSE) {
2617
2621
                ut_print_timestamp(stderr);
2655
2659
                return(DB_ERROR);
2656
2660
        }
2657
2661
 
 
2662
        buf2 = ut_malloc(3 * UNIV_PAGE_SIZE);
 
2663
        /* Align the memory for file i/o if we might have O_DIRECT set */
 
2664
        page = ut_align(buf2, UNIV_PAGE_SIZE);
 
2665
 
2658
2666
        ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
2659
2667
 
2660
2668
        if (!ret) {
2661
 
                err = DB_OUT_OF_FILE_SPACE;
 
2669
                ut_free(buf2);
 
2670
                os_file_close(file);
 
2671
                os_file_delete(path);
 
2672
 
 
2673
                mem_free(path);
 
2674
                return(DB_OUT_OF_FILE_SPACE);
 
2675
        }
 
2676
 
 
2677
        if (*space_id == 0) {
 
2678
                *space_id = fil_assign_new_space_id();
 
2679
        }
 
2680
 
 
2681
        /* printf("Creating tablespace %s id %lu\n", path, *space_id); */
 
2682
 
 
2683
        if (*space_id == ULINT_UNDEFINED) {
 
2684
                ut_free(buf2);
2662
2685
error_exit:
2663
2686
                os_file_close(file);
2664
2687
error_exit2:
2665
2688
                os_file_delete(path);
2666
2689
 
2667
2690
                mem_free(path);
2668
 
                return(err);
 
2691
                return(DB_ERROR);
2669
2692
        }
2670
2693
 
2671
 
        /* printf("Creating tablespace %s id %lu\n", path, space_id); */
2672
 
 
2673
2694
        /* We have to write the space id to the file immediately and flush the
2674
2695
        file to disk. This is because in crash recovery we must be aware what
2675
2696
        tablespaces exist and what are their space id's, so that we can apply
2679
2700
        with zeros from the call of os_file_set_size(), until a buffer pool
2680
2701
        flush would write to it. */
2681
2702
 
2682
 
        buf2 = ut_malloc(3 * UNIV_PAGE_SIZE);
2683
 
        /* Align the memory for file i/o if we might have O_DIRECT set */
2684
 
        page = ut_align(buf2, UNIV_PAGE_SIZE);
2685
 
 
2686
2703
        memset(page, '\0', UNIV_PAGE_SIZE);
2687
2704
 
2688
 
        fsp_header_init_fields(page, space_id, flags);
2689
 
        mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
 
2705
        fsp_header_init_fields(page, *space_id, flags);
 
2706
        mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, *space_id);
2690
2707
 
2691
2708
        if (!(flags & DICT_TF_ZSSIZE_MASK)) {
2692
2709
                buf_flush_init_for_writing(page, NULL, 0);
2717
2734
                      " to tablespace ", stderr);
2718
2735
                ut_print_filename(stderr, path);
2719
2736
                putc('\n', stderr);
2720
 
                err = DB_ERROR;
2721
2737
                goto error_exit;
2722
2738
        }
2723
2739
 
2727
2743
                fputs("InnoDB: Error: file flush of tablespace ", stderr);
2728
2744
                ut_print_filename(stderr, path);
2729
2745
                fputs(" failed\n", stderr);
2730
 
                err = DB_ERROR;
2731
2746
                goto error_exit;
2732
2747
        }
2733
2748
 
2734
2749
        os_file_close(file);
2735
2750
 
2736
 
        success = fil_space_create(path, space_id, flags, FIL_TABLESPACE);
 
2751
        if (*space_id == ULINT_UNDEFINED) {
 
2752
                goto error_exit2;
 
2753
        }
 
2754
 
 
2755
        success = fil_space_create(path, *space_id, flags, FIL_TABLESPACE);
2737
2756
 
2738
2757
        if (!success) {
2739
 
                err = DB_ERROR;
2740
2758
                goto error_exit2;
2741
2759
        }
2742
2760
 
2743
 
        fil_node_create(path, size, space_id, FALSE);
 
2761
        fil_node_create(path, size, *space_id, FALSE);
2744
2762
 
2745
2763
#ifndef UNIV_HOTBACKUP
2746
2764
        {
2751
2769
                fil_op_write_log(flags
2752
2770
                                 ? MLOG_FILE_CREATE2
2753
2771
                                 : MLOG_FILE_CREATE,
2754
 
                                 space_id,
 
2772
                                 *space_id,
2755
2773
                                 is_temp ? MLOG_FILE_FLAG_TEMP : 0,
2756
2774
                                 flags,
2757
2775
                                 tablename, NULL, &mtr);
2799
2817
        filepath = fil_make_ibd_name(name, FALSE);
2800
2818
 
2801
2819
        file = os_file_create_simple_no_error_handling(
2802
 
                filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
 
2820
                innodb_file_data_key, filepath, OS_FILE_OPEN,
 
2821
                OS_FILE_READ_WRITE, &success);
2803
2822
        if (!success) {
2804
2823
                /* The following call prints an error message */
2805
2824
                os_file_get_last_error(TRUE);
2983
3002
        ut_a(!(flags & (~0UL << DICT_TF_BITS)));
2984
3003
 
2985
3004
        file = os_file_create_simple_no_error_handling(
2986
 
                filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
 
3005
                innodb_file_data_key, filepath, OS_FILE_OPEN,
 
3006
                OS_FILE_READ_ONLY, &success);
2987
3007
        if (!success) {
2988
3008
                /* The following call prints an error message */
2989
3009
                os_file_get_last_error(TRUE);
3139
3159
# endif /* !UNIV_HOTBACKUP */
3140
3160
#endif
3141
3161
        file = os_file_create_simple_no_error_handling(
3142
 
                filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
 
3162
                innodb_file_data_key, filepath, OS_FILE_OPEN,
 
3163
                OS_FILE_READ_ONLY, &success);
3143
3164
        if (!success) {
3144
3165
                /* The following call prints an error message */
3145
3166
                os_file_get_last_error(TRUE);
3297
3318
                os_file_close(file);
3298
3319
 
3299
3320
                new_path = fil_make_ibbackup_old_name(filepath);
3300
 
                ut_a(os_file_rename(filepath, new_path));
 
3321
                ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
3301
3322
 
3302
3323
                ut_free(buf2);
3303
3324
                mem_free(filepath);
3335
3356
 
3336
3357
                mutex_exit(&fil_system->mutex);
3337
3358
 
3338
 
                ut_a(os_file_rename(filepath, new_path));
 
3359
                ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
3339
3360
 
3340
3361
                ut_free(buf2);
3341
3362
                mem_free(filepath);
3542
3563
        return(err);
3543
3564
}
3544
3565
 
 
3566
/********************************************************************//**
 
3567
If we need crash recovery, and we have called
 
3568
fil_load_single_table_tablespaces() and dict_load_single_table_tablespaces(),
 
3569
we can call this function to print an error message of orphaned .ibd files
 
3570
for which there is not a data dictionary entry with a matching table name
 
3571
and space id. */
 
3572
UNIV_INTERN
 
3573
void
 
3574
fil_print_orphaned_tablespaces(void)
 
3575
/*================================*/
 
3576
{
 
3577
        fil_space_t*    space;
 
3578
 
 
3579
        mutex_enter(&fil_system->mutex);
 
3580
 
 
3581
        space = UT_LIST_GET_FIRST(fil_system->space_list);
 
3582
 
 
3583
        while (space) {
 
3584
                if (space->purpose == FIL_TABLESPACE && space->id != 0
 
3585
                    && !space->mark) {
 
3586
                        fputs("InnoDB: Warning: tablespace ", stderr);
 
3587
                        ut_print_filename(stderr, space->name);
 
3588
                        fprintf(stderr, " of id %lu has no matching table in\n"
 
3589
                                "InnoDB: the InnoDB data dictionary.\n",
 
3590
                                (ulong) space->id);
 
3591
                }
 
3592
 
 
3593
                space = UT_LIST_GET_NEXT(space_list, space);
 
3594
        }
 
3595
 
 
3596
        mutex_exit(&fil_system->mutex);
 
3597
}
 
3598
 
3545
3599
/*******************************************************************//**
3546
3600
Returns TRUE if a single-table tablespace does not exist in the memory cache,
3547
3601
or is being deleted there.
4424
4478
 
4425
4479
        ut_ad(fil_validate());
4426
4480
 
4427
 
        if (os_aio_use_native_aio) {
 
4481
        if (srv_use_native_aio) {
4428
4482
                srv_set_io_thread_op_info(segment, "native aio handle");
4429
4483
#ifdef WIN_ASYNC_IO
4430
4484
                ret = os_aio_windows_handle(segment, 0, &fil_node,
4431
4485
                                            &message, &type);
 
4486
#elif defined(LINUX_NATIVE_AIO)
 
4487
                ret = os_aio_linux_handle(segment, &fil_node,
 
4488
                                          &message, &type);
4432
4489
#else
4433
4490
                ret = 0; /* Eliminate compiler warning */
4434
4491
                ut_error;