summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorRamil Kalimullin <ramil@mysql.com>2009-01-26 10:35:15 +0400
committerRamil Kalimullin <ramil@mysql.com>2009-01-26 10:35:15 +0400
commit01511453102aa18fb8933927d80eccdeef501c68 (patch)
tree5abc1ae29b07ce3e199f41e4dfcab29a2f6a4d70 /storage
parent75342ddd345457753da016a5387584e742a1eb74 (diff)
downloadmariadb-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.c77
-rw-r--r--storage/myisam/ftdefs.h1
-rw-r--r--storage/myisam/mi_check.c5
-rw-r--r--storage/myisam/mi_open.c7
-rw-r--r--storage/myisam/myisamdef.h2
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 */