~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/dict/dict0dict.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:
69
69
on the mode in trx_struct::dict_operation_lock_mode */
70
70
UNIV_INTERN rw_lock_t   dict_operation_lock;
71
71
 
 
72
/* Keys to register rwlocks and mutexes with performance schema */
 
73
#ifdef UNIV_PFS_RWLOCK
 
74
UNIV_INTERN mysql_pfs_key_t     dict_operation_lock_key;
 
75
UNIV_INTERN mysql_pfs_key_t     index_tree_rw_lock_key;
 
76
#endif /* UNIV_PFS_RWLOCK */
 
77
 
 
78
#ifdef UNIV_PFS_MUTEX
 
79
UNIV_INTERN mysql_pfs_key_t     dict_sys_mutex_key;
 
80
UNIV_INTERN mysql_pfs_key_t     dict_foreign_err_mutex_key;
 
81
#endif /* UNIV_PFS_MUTEX */
 
82
 
72
83
#define DICT_HEAP_SIZE          100     /*!< initial memory heap size when
73
84
                                        creating a table or index object */
74
85
#define DICT_POOL_PER_TABLE_HASH 512    /*!< buffer pool max size per table
79
90
/** Identifies generated InnoDB foreign key names */
80
91
static char     dict_ibfk[] = "_ibfk_";
81
92
 
82
 
/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
83
 
#define DICT_INDEX_STAT_MUTEX_SIZE      32
84
 
static mutex_t  dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
85
 
 
86
93
/*******************************************************************//**
87
94
Tries to find column names for the index and sets the col field of the
88
95
index.
242
249
        mutex_exit(&(dict_sys->mutex));
243
250
}
244
251
 
245
 
/** Get the mutex that protects index->stat_n_diff_key_vals[] */
246
 
#define GET_INDEX_STAT_MUTEX(index) \
247
 
        (&dict_index_stat_mutex[ut_fold_dulint(index->id) \
248
 
                                % DICT_INDEX_STAT_MUTEX_SIZE])
249
 
 
250
 
/**********************************************************************//**
251
 
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
252
 
index->id is used to pick the right mutex and it should not change
253
 
before dict_index_stat_mutex_exit() is called on this index. */
254
 
UNIV_INTERN
255
 
void
256
 
dict_index_stat_mutex_enter(
257
 
/*========================*/
258
 
        const dict_index_t*     index)  /*!< in: index */
259
 
{
260
 
        ut_ad(index != NULL);
261
 
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
262
 
        ut_ad(index->cached);
263
 
        ut_ad(!index->to_be_dropped);
264
 
 
265
 
        mutex_enter(GET_INDEX_STAT_MUTEX(index));
266
 
}
267
 
 
268
 
/**********************************************************************//**
269
 
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
270
 
UNIV_INTERN
271
 
void
272
 
dict_index_stat_mutex_exit(
273
 
/*=======================*/
274
 
        const dict_index_t*     index)  /*!< in: index */
275
 
{
276
 
        ut_ad(index != NULL);
277
 
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
278
 
        ut_ad(index->cached);
279
 
        ut_ad(!index->to_be_dropped);
280
 
 
281
 
        mutex_exit(GET_INDEX_STAT_MUTEX(index));
282
 
}
283
 
 
284
252
/********************************************************************//**
285
253
Decrements the count of open MySQL handles to a table. */
286
254
UNIV_INTERN
569
537
 
570
538
        if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
571
539
            || trx->dict_operation_lock_mode == RW_X_LATCH) {
572
 
 
573
 
                /* Note: An X latch implies that the transaction
574
 
                already owns the dictionary mutex. */
575
 
 
576
 
                ut_ad(mutex_own(&dict_sys->mutex));
 
540
                /* It is a system table which will always exist in the table
 
541
                cache: we avoid acquiring the dictionary mutex, because
 
542
                if we are doing a rollback to handle an error in TABLE
 
543
                CREATE, for example, we already have the mutex! */
 
544
 
 
545
                ut_ad(mutex_own(&(dict_sys->mutex))
 
546
                      || trx->dict_operation_lock_mode == RW_X_LATCH);
577
547
 
578
548
                return(dict_table_get_on_id_low(table_id));
579
549
        }
645
615
dict_init(void)
646
616
/*===========*/
647
617
{
648
 
        int     i;
649
 
 
650
618
        dict_sys = mem_alloc(sizeof(dict_sys_t));
651
619
 
652
 
        mutex_create(&dict_sys->mutex, SYNC_DICT);
 
620
        mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
653
621
 
654
622
        dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
655
623
                                           / (DICT_POOL_PER_TABLE_HASH
661
629
 
662
630
        UT_LIST_INIT(dict_sys->table_LRU);
663
631
 
664
 
        rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
 
632
        rw_lock_create(dict_operation_lock_key,
 
633
                       &dict_operation_lock, SYNC_DICT_OPERATION);
665
634
 
666
635
        dict_foreign_err_file = os_file_create_tmpfile();
667
636
        ut_a(dict_foreign_err_file);
668
637
 
669
 
        mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
670
 
 
671
 
        for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
672
 
                mutex_create(&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
673
 
        }
 
638
        mutex_create(dict_foreign_err_mutex_key,
 
639
                     &dict_foreign_err_mutex, SYNC_ANY_LATCH);
674
640
}
675
641
 
676
642
/**********************************************************************//**
847
813
        /* Add table to LRU list of tables */
848
814
        UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
849
815
 
850
 
        dict_sys->size += mem_heap_get_size(table->heap)
851
 
                + strlen(table->name) + 1;
 
816
        dict_sys->size += mem_heap_get_size(table->heap);
852
817
}
853
818
 
854
819
/**********************************************************************//**
902
867
        dict_foreign_t* foreign;
903
868
        dict_index_t*   index;
904
869
        ulint           fold;
905
 
        char            old_name[MAX_TABLE_NAME_LEN + 1];
 
870
        ulint           old_size;
 
871
        const char*     old_name;
906
872
 
907
873
        ut_ad(table);
908
874
        ut_ad(mutex_own(&(dict_sys->mutex)));
909
875
 
910
 
        /* store the old/current name to an automatic variable */
911
 
        if (strlen(table->name) + 1 <= sizeof(old_name)) {
912
 
                memcpy(old_name, table->name, strlen(table->name) + 1);
913
 
        } else {
914
 
                ut_print_timestamp(stderr);
915
 
                fprintf(stderr, "InnoDB: too long table name: '%s', "
916
 
                        "max length is %d\n", table->name,
917
 
                        MAX_TABLE_NAME_LEN);
918
 
                ut_error;
919
 
        }
 
876
        old_size = mem_heap_get_size(table->heap);
 
877
        old_name = table->name;
920
878
 
921
879
        fold = ut_fold_string(new_name);
922
880
 
962
920
        /* Remove table from the hash tables of tables */
963
921
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
964
922
                    ut_fold_string(old_name), table);
965
 
 
966
 
        if (strlen(new_name) > strlen(table->name)) {
967
 
                /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
968
 
                memory fragmentation, we assume a repeated calls of
969
 
                ut_realloc() with the same size do not cause fragmentation */
970
 
                ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
971
 
                table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
972
 
        }
973
 
        memcpy(table->name, new_name, strlen(new_name) + 1);
 
923
        table->name = mem_heap_strdup(table->heap, new_name);
974
924
 
975
925
        /* Add table to hash table of tables */
976
926
        HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
977
927
                    table);
978
 
 
979
 
        dict_sys->size += strlen(new_name) - strlen(old_name);
980
 
        ut_a(dict_sys->size > 0);
 
928
        dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
981
929
 
982
930
        /* Update the table_name field in indexes */
983
931
        index = dict_table_get_first_index(table);
1202
1150
        /* Remove table from LRU list of tables */
1203
1151
        UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
1204
1152
 
1205
 
        size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
 
1153
        size = mem_heap_get_size(table->heap);
1206
1154
 
1207
1155
        ut_ad(dict_sys->size >= size);
1208
1156
 
1631
1579
        new_index->stat_n_leaf_pages = 1;
1632
1580
 
1633
1581
        new_index->page = page_no;
1634
 
        rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
 
1582
        rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
 
1583
                       SYNC_INDEX_TREE);
1635
1584
 
1636
1585
        if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1637
1586
 
3023
2972
char*
3024
2973
dict_strip_comments(
3025
2974
/*================*/
3026
 
        const char*     sql_string,     /*!< in: SQL string */
3027
 
        size_t          sql_length)     /*!< in: length of sql_string */
 
2975
        const char*     sql_string)     /*!< in: SQL string */
3028
2976
{
3029
2977
        char*           str;
3030
2978
        const char*     sptr;
3031
 
        const char*     eptr    = sql_string + sql_length;
3032
2979
        char*           ptr;
3033
2980
        /* unclosed quote character (0 if none) */
3034
2981
        char            quote   = 0;
3035
2982
 
3036
 
        str = mem_alloc(sql_length + 1);
 
2983
        str = mem_alloc(strlen(sql_string) + 1);
3037
2984
 
3038
2985
        sptr = sql_string;
3039
2986
        ptr = str;
3040
2987
 
3041
2988
        for (;;) {
3042
2989
scan_more:
3043
 
                if (sptr >= eptr || *sptr == '\0') {
3044
 
end_of_string:
 
2990
                if (*sptr == '\0') {
3045
2991
                        *ptr = '\0';
3046
2992
 
3047
 
                        ut_a(ptr <= str + sql_length);
 
2993
                        ut_a(ptr <= str + strlen(sql_string));
3048
2994
 
3049
2995
                        return(str);
3050
2996
                }
3063
3009
                           || (sptr[0] == '-' && sptr[1] == '-'
3064
3010
                               && sptr[2] == ' ')) {
3065
3011
                        for (;;) {
3066
 
                                if (++sptr >= eptr) {
3067
 
                                        goto end_of_string;
3068
 
                                }
3069
 
 
3070
3012
                                /* In Unix a newline is 0x0A while in Windows
3071
3013
                                it is 0x0D followed by 0x0A */
3072
3014
 
3073
 
                                switch (*sptr) {
3074
 
                                case (char) 0X0A:
3075
 
                                case (char) 0x0D:
3076
 
                                case '\0':
 
3015
                                if (*sptr == (char)0x0A
 
3016
                                    || *sptr == (char)0x0D
 
3017
                                    || *sptr == '\0') {
 
3018
 
3077
3019
                                        goto scan_more;
3078
3020
                                }
 
3021
 
 
3022
                                sptr++;
3079
3023
                        }
3080
3024
                } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
3081
 
                        sptr += 2;
3082
3025
                        for (;;) {
3083
 
                                if (sptr >= eptr) {
3084
 
                                        goto end_of_string;
 
3026
                                if (*sptr == '*' && *(sptr + 1) == '/') {
 
3027
 
 
3028
                                        sptr += 2;
 
3029
 
 
3030
                                        goto scan_more;
3085
3031
                                }
3086
3032
 
3087
 
                                switch (*sptr) {
3088
 
                                case '\0':
 
3033
                                if (*sptr == '\0') {
 
3034
 
3089
3035
                                        goto scan_more;
3090
 
                                case '*':
3091
 
                                        if (sptr[1] == '/') {
3092
 
                                                sptr += 2;
3093
 
                                                goto scan_more;
3094
 
                                        }
3095
3036
                                }
3096
3037
 
3097
3038
                                sptr++;
3772
3713
                                        name before it: test.table2; the
3773
3714
                                        default database id the database of
3774
3715
                                        parameter name */
3775
 
        size_t          sql_length,     /*!< in: length of sql_string */
3776
3716
        const char*     name,           /*!< in: table full name in the
3777
3717
                                        normalized form
3778
3718
                                        database_name/table_name */
3787
3727
        ut_a(trx);
3788
3728
        ut_a(trx->mysql_thd);
3789
3729
 
3790
 
        str = dict_strip_comments(sql_string, sql_length);
 
3730
        str = dict_strip_comments(sql_string);
3791
3731
        heap = mem_heap_create(10000);
3792
3732
 
3793
3733
        err = dict_create_foreign_constraints_low(
3820
3760
        dict_foreign_t*         foreign;
3821
3761
        ibool                   success;
3822
3762
        char*                   str;
3823
 
        size_t                  len;
 
3763
        size_t                  len;
3824
3764
        const char*             ptr;
3825
3765
        const char*             id;
3826
3766
        FILE*                   ef      = dict_foreign_err_file;
3835
3775
 
3836
3776
        *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3837
3777
 
3838
 
        ptr = innobase_get_stmt(trx->mysql_thd, &len);
 
3778
        ptr = innobase_get_stmt(trx->mysql_thd, &len);
3839
3779
 
3840
 
        str = dict_strip_comments(ptr, len);
 
3780
        str = dict_strip_comments(ptr);
3841
3781
 
3842
3782
        ptr = str;
3843
3783
 
4248
4188
 
4249
4189
        index = dict_table_get_first_index(table);
4250
4190
 
4251
 
        dict_index_stat_mutex_enter(index);
4252
 
 
4253
4191
        table->stat_n_rows = index->stat_n_diff_key_vals[
4254
4192
                dict_index_get_n_unique(index)];
4255
4193
 
4256
 
        dict_index_stat_mutex_exit(index);
4257
 
 
4258
4194
        table->stat_clustered_index_size = index->stat_index_size;
4259
4195
 
4260
4196
        table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4432
4368
 
4433
4369
        ut_ad(mutex_own(&(dict_sys->mutex)));
4434
4370
 
4435
 
        dict_index_stat_mutex_enter(index);
4436
 
 
4437
4371
        if (index->n_user_defined_cols > 0) {
4438
4372
                n_vals = index->stat_n_diff_key_vals[
4439
4373
                        index->n_user_defined_cols];
4441
4375
                n_vals = index->stat_n_diff_key_vals[1];
4442
4376
        }
4443
4377
 
4444
 
        dict_index_stat_mutex_exit(index);
4445
 
 
4446
4378
        if (dict_index_is_clust(index)) {
4447
4379
                type_string = "clustered index";
4448
4380
        } else if (dict_index_is_unique(index)) {
4938
4870
 
4939
4871
        mem_free(dict_sys);
4940
4872
        dict_sys = NULL;
4941
 
 
4942
 
        for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
4943
 
                mutex_free(&dict_index_stat_mutex[i]);
4944
 
        }
4945
4873
}
4946
4874
#endif /* !UNIV_HOTBACKUP */