diff options
author | Ramil Kalimullin <ramil@mysql.com> | 2009-01-26 10:35:15 +0400 |
---|---|---|
committer | Ramil Kalimullin <ramil@mysql.com> | 2009-01-26 10:35:15 +0400 |
commit | 01511453102aa18fb8933927d80eccdeef501c68 (patch) | |
tree | 5abc1ae29b07ce3e199f41e4dfcab29a2f6a4d70 /storage | |
parent | 75342ddd345457753da016a5387584e742a1eb74 (diff) | |
download | mariadb-git-01511453102aa18fb8933927d80eccdeef501c68.tar.gz |
Fix for bug #37756: enabling fulltext indexes with
myisam_repair_threads > 1 causes crash
Problem: parallel repair (myisam_repair_threads > 1) of a myisam
table with two or more fulltext keys that use the same parser may
lead to a server crash. ALTER TABLE ENABLE KEYS is affected as well.
Fix: properly initialize fulltext structures for parallel repair.
Note: 1. there's no deterministic test case.
2. now we call parser->init() for each fulltext key
(not for each fulltext parser used).
Diffstat (limited to 'storage')
-rw-r--r-- | storage/myisam/ft_parser.c | 77 | ||||
-rw-r--r-- | storage/myisam/ftdefs.h | 1 | ||||
-rw-r--r-- | storage/myisam/mi_check.c | 5 | ||||
-rw-r--r-- | storage/myisam/mi_open.c | 7 | ||||
-rw-r--r-- | storage/myisam/myisamdef.h | 2 |
5 files changed, 40 insertions, 52 deletions
diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index 042a999fffa..4cde3834ed7 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -323,60 +323,41 @@ int ft_parse(TREE *wtree, uchar *doc, int doclen, DBUG_RETURN(parser->parse(param)); } + #define MAX_PARAM_NR 2 -MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, - uint keynr, uint paramnr) + +MYSQL_FTPARSER_PARAM* ftparser_alloc_param(MI_INFO *info) { - uint32 ftparser_nr; - struct st_mysql_ftparser *parser; - if (! info->ftparser_param) + if (!info->ftparser_param) { - /* info->ftparser_param can not be zero after the initialization, - because it always includes built-in fulltext parser. And built-in - parser can be called even if the table has no fulltext indexes and - no varchar/text fields. */ - if (! info->s->ftparsers) - { - /* It's ok that modification to shared structure is done w/o mutex - locks, because all threads would set the same variables to the - same values. */ - uint i, j, keys= info->s->state.header.keys, ftparsers= 1; - for (i= 0; i < keys; i++) - { - MI_KEYDEF *keyinfo= &info->s->keyinfo[i]; - if (keyinfo->flag & HA_FULLTEXT) - { - for (j= 0;; j++) - { - if (j == i) - { - keyinfo->ftparser_nr= ftparsers++; - break; - } - if (info->s->keyinfo[j].flag & HA_FULLTEXT && - keyinfo->parser == info->s->keyinfo[j].parser) - { - keyinfo->ftparser_nr= info->s->keyinfo[j].ftparser_nr; - break; - } - } - } - } - info->s->ftparsers= ftparsers; - } - /* - We have to allocate two MYSQL_FTPARSER_PARAM structures per plugin - because in a boolean search a parser is called recursively - ftb_find_relevance* calls ftb_check_phrase* - (MAX_PARAM_NR=2) + /* +. info->ftparser_param can not be zero after the initialization, + because it always includes built-in fulltext parser. And built-in + parser can be called even if the table has no fulltext indexes and + no varchar/text fields. + + ftb_find_relevance... parser (ftb_find_relevance_parse, + ftb_find_relevance_add_word) calls ftb_check_phrase... parser + (ftb_check_phrase_internal, ftb_phrase_add_word). Thus MAX_PARAM_NR=2. */ info->ftparser_param= (MYSQL_FTPARSER_PARAM *) my_malloc(MAX_PARAM_NR * sizeof(MYSQL_FTPARSER_PARAM) * - info->s->ftparsers, MYF(MY_WME|MY_ZEROFILL)); + info->s->ftkeys, MYF(MY_WME | MY_ZEROFILL)); init_alloc_root(&info->ft_memroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); - if (! info->ftparser_param) - return 0; } + return info->ftparser_param; +} + + +MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, + uint keynr, uint paramnr) +{ + uint32 ftparser_nr; + struct st_mysql_ftparser *parser; + + if (!ftparser_alloc_param(info)) + return 0; + if (keynr == NO_SUCH_KEY) { ftparser_nr= 0; @@ -384,7 +365,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, } else { - ftparser_nr= info->s->keyinfo[keynr].ftparser_nr; + ftparser_nr= info->s->keyinfo[keynr].ftkey_nr; parser= info->s->keyinfo[keynr].parser; } DBUG_ASSERT(paramnr < MAX_PARAM_NR); @@ -416,7 +397,7 @@ void ftparser_call_deinitializer(MI_INFO *info) for (j=0; j < MAX_PARAM_NR; j++) { MYSQL_FTPARSER_PARAM *ftparser_param= - &info->ftparser_param[keyinfo->ftparser_nr*MAX_PARAM_NR + j]; + &info->ftparser_param[keyinfo->ftkey_nr * MAX_PARAM_NR + j]; if (keyinfo->flag & HA_FULLTEXT && ftparser_param->mysql_add_word) { if (keyinfo->parser->deinit) diff --git a/storage/myisam/ftdefs.h b/storage/myisam/ftdefs.h index 22443807b87..ddcf1a8dc26 100644 --- a/storage/myisam/ftdefs.h +++ b/storage/myisam/ftdefs.h @@ -146,6 +146,7 @@ void ft_boolean_close_search(FT_INFO *); float ft_boolean_get_relevance(FT_INFO *); my_off_t ft_boolean_get_docid(FT_INFO *); void ft_boolean_reinit_search(FT_INFO *); +MYSQL_FTPARSER_PARAM* ftparser_alloc_param(MI_INFO *info); extern MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, uint keynr, uint paramnr); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index b132000b356..bdca1a1f0b8 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2397,7 +2397,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, Note, built-in parser is always nr. 0 - see ftparser_call_initializer() */ - if (sort_param.keyinfo->ftparser_nr == 0) + if (sort_param.keyinfo->ftkey_nr == 0) { /* for built-in parser the number of generated index entries @@ -2895,6 +2895,9 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, sort_param[0].fix_datafile= (my_bool)(! rep_quick); sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM); + if (!ftparser_alloc_param(info)) + goto err; + sort_info.got_error=0; pthread_mutex_lock(&sort_info.mutex); diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 605dea6594e..78749d50fe5 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -331,6 +331,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->blocksize=min(IO_SIZE,myisam_block_size); { HA_KEYSEG *pos=share->keyparts; + uint32 ftkey_nr= 1; for (i=0 ; i < keys ; i++) { share->keyinfo[i].share= share; @@ -412,6 +413,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->ft2_keyinfo.end=pos; setup_key_functions(& share->ft2_keyinfo); } + share->keyinfo[i].ftkey_nr= ftkey_nr++; } setup_key_functions(share->keyinfo+i); share->keyinfo[i].end=pos; @@ -421,6 +423,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) pos->flag=0; /* For purify */ pos++; } + for (i=0 ; i < uniques ; i++) { disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]); @@ -449,7 +452,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) pos->flag=0; pos++; } - share->ftparsers= 0; + share->ftkeys= ftkey_nr; } disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos); @@ -1112,7 +1115,7 @@ uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef) keydef->underflow_block_length=keydef->block_length/3; keydef->version = 0; /* Not saved */ keydef->parser = &ft_default_parser; - keydef->ftparser_nr = 0; + keydef->ftkey_nr = 0; return ptr; } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 2ca79608408..9af3f652c5f 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -193,7 +193,7 @@ typedef struct st_mi_isam_share { /* Shared between opens */ ulong state_diff_length; uint rec_reflength; /* rec_reflength in use now */ uint unique_name_length; - uint32 ftparsers; /* Number of distinct ftparsers + 1 */ + uint32 ftkeys; /* Number of full-text keys + 1 */ File kfile; /* Shared keyfile */ File data_file; /* Shared data file */ int mode; /* mode of file on open */ |