null+****@clear*****
null+****@clear*****
2012年 4月 26日 (木) 23:39:57 JST
Kouhei Sutou 2012-04-26 23:39:57 +0900 (Thu, 26 Apr 2012) New Revision: c753bda2f43827815b8af0dcdef41560232cc3a3 Log: Fix a crash bug when there is a syntax error query in many queries A new grn_ctx is used for fulltext search because an allocated object for fulltext search is destroyed after query is handled. It means that handling a query and destroying an allocated object for fulltext search may be occured in the same time on different threads. But grn_ctx isn't thread safe. It may causes crash. Reported by susumu takaoka. Thanks!!! Modified files: ha_mroonga.cpp ha_mroonga.hpp Modified: ha_mroonga.cpp (+63 -39) =================================================================== --- ha_mroonga.cpp 2012-04-26 00:20:33 +0900 (4d82115) +++ ha_mroonga.cpp 2012-04-26 23:39:57 +0900 (5cf97d4) @@ -1440,10 +1440,10 @@ static void mrn_generic_ft_close_search(FT_INFO *handler) MRN_DBUG_ENTER_FUNCTION(); st_mrn_ft_info *info = (st_mrn_ft_info *)handler; grn_obj_unlink(info->ctx, info->result); - grn_obj_unlink(info->ctx, info->sorted_result); grn_obj_unlink(info->ctx, info->score_column); grn_obj_unlink(info->ctx, &(info->key)); grn_obj_unlink(info->ctx, &(info->score)); + grn_ctx_fin(info->ctx); delete info; DBUG_VOID_RETURN; } @@ -6603,27 +6603,25 @@ void ha_mroonga::generic_ft_init_ext_add_conditions_fast_order_limit( DBUG_VOID_RETURN; } -FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key) +struct st_mrn_ft_info *ha_mroonga::generic_ft_init_ext_select(uint flags, + uint key_nr, + String *key) { MRN_DBUG_ENTER_METHOD(); - check_count_skip(0, 0, true); - - clear_cursor(); - - mrn_change_encoding(ctx, system_charset_info); struct st_mrn_ft_info *info = new st_mrn_ft_info(); info->mroonga = this; - info->ctx = ctx; + info->ctx = grn_ctx_open(0); + grn_ctx_use(info->ctx, grn_ctx_db(ctx)); info->table = grn_table; - info->result = grn_table_create(ctx, NULL, 0, NULL, + info->result = grn_table_create(info->ctx, NULL, 0, NULL, GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC, grn_table, 0); info->score_column = grn_obj_column(info->ctx, info->result, MRN_COLUMN_NAME_SCORE, strlen(MRN_COLUMN_NAME_SCORE)); GRN_TEXT_INIT(&(info->key), 0); - grn_bulk_space(ctx, &(info->key), table->key_info->key_length); + grn_bulk_space(info->ctx, &(info->key), table->key_info->key_length); GRN_INT32_INIT(&(info->score), 0); info->active_index = key_nr; info->key_info = &(table->key_info[key_nr]); @@ -6639,14 +6637,9 @@ FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key) GRN_EXPR_CREATE_FOR_QUERY(info->ctx, info->table, expression, expression_variable); - grn_table_sort_key *sort_keys = NULL; - int n_sort_keys = 0; - longlong limit = -1; - check_fast_order_limit(&sort_keys, &n_sort_keys, &limit, - info->result, info->score_column); - grn_rc rc = GRN_SUCCESS; - mrn_change_encoding(ctx, table->key_info[key_nr].key_part->field->charset()); + mrn_change_encoding(info->ctx, + table->key_info[key_nr].key_part->field->charset()); if (flags & FT_BOOL) { const char *keyword, *keyword_original; uint keyword_length, keyword_length_original; @@ -6721,22 +6714,56 @@ FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key) grn_obj_unlink(info->ctx, expression); grn_obj_unlink(info->ctx, match_columns); + DBUG_RETURN(info); +} + +FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key) +{ + MRN_DBUG_ENTER_METHOD(); + + check_count_skip(0, 0, true); + + clear_cursor(); + + mrn_change_encoding(ctx, system_charset_info); + grn_operator operation = GRN_OP_AND; + if (!matched_record_keys) { + matched_record_keys = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC, + grn_table, 0); + operation = GRN_OP_OR; + } + + grn_table_sort_key *sort_keys = NULL; + int n_sort_keys = 0; + longlong limit = -1; + check_fast_order_limit(&sort_keys, &n_sort_keys, &limit); + + struct st_mrn_ft_info *info = + generic_ft_init_ext_select(flags, key_nr, key); + + grn_rc rc; + rc = grn_table_setoperation(ctx, matched_record_keys, info->result, + matched_record_keys, operation); + if (rc) { + char error_message[MRN_MESSAGE_BUFFER_SIZE]; + snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, + "failed to merge matched record keys: <%s>", + ctx->errbuf); + my_message(ER_ERROR_ON_READ, error_message, MYF(0)); + GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message); + } if (fast_order_limit) { - info->sorted_result = grn_table_create(ctx, NULL, - 0, NULL, - GRN_OBJ_TABLE_NO_KEY, NULL, - info->result); - grn_table_sort(ctx, info->result, 0, limit, info->sorted_result, + sorted_result = grn_table_create(ctx, NULL, + 0, NULL, + GRN_OBJ_TABLE_NO_KEY, NULL, + matched_record_keys); + grn_table_sort(ctx, matched_record_keys, 0, limit, sorted_result, sort_keys, n_sort_keys); - sorted_result = info->sorted_result; - } else { - merge_matched_record_keys(info->result); } if (sort_keys) { for (int i = 0; i < n_sort_keys; i++) { - if (sort_keys[i].key != info->score_column) { - grn_obj_unlink(ctx, sort_keys[i].key); - } + grn_obj_unlink(info->ctx, sort_keys[i].key); } free(sort_keys); } @@ -7005,6 +7032,7 @@ void ha_mroonga::clear_search_result() MRN_DBUG_ENTER_METHOD(); clear_cursor(); if (sorted_result) { + grn_obj_unlink(ctx, sorted_result); sorted_result = NULL; } if (matched_record_keys) { @@ -7614,9 +7642,7 @@ bool ha_mroonga::is_grn_zero_column_value(grn_obj *column, grn_obj *value) void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, int *n_sort_keys, - longlong *limit, - grn_obj *target_table, - grn_obj *score_column) + longlong *limit) { MRN_DBUG_ENTER_METHOD(); @@ -7703,6 +7729,7 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, *n_sort_keys); ORDER *order; int i; + mrn_change_encoding(ctx, system_charset_info); for (order = (ORDER *) select_lex->order_list.first, i = 0; order; order = order->next, i++) { Item *item = *order->item; @@ -7723,15 +7750,12 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, DBUG_VOID_RETURN; } - if (strncmp(MRN_COLUMN_NAME_SCORE, column_name, column_name_size) == 0) { - (*sort_keys)[i].key = score_column; - } else { - mrn_change_encoding(ctx, system_charset_info); - (*sort_keys)[i].key = grn_obj_column(ctx, target_table, - column_name, column_name_size); - } + (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, + column_name, column_name_size); } else if (match_against->eq(item, true)) { - (*sort_keys)[i].key = score_column; + (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, + MRN_COLUMN_NAME_SCORE, + strlen(MRN_COLUMN_NAME_SCORE)); } else { DBUG_PRINT("info", ("mroonga: fast_order_limit = false: " "sort by computed value isn't supported.")); Modified: ha_mroonga.hpp (+4 -3) =================================================================== --- ha_mroonga.hpp 2012-04-26 00:20:33 +0900 (ca03baa) +++ ha_mroonga.hpp 2012-04-26 23:39:57 +0900 (5507215) @@ -142,7 +142,6 @@ struct st_mrn_ft_info grn_ctx *ctx; grn_obj *table; grn_obj *result; - grn_obj *sorted_result; grn_obj *score_column; grn_obj key; grn_obj score; @@ -466,8 +465,7 @@ private: bool is_fulltext_search_item(const Item *item); bool is_grn_zero_column_value(grn_obj *column, grn_obj *value); void check_fast_order_limit(grn_table_sort_key **sort_keys, int *n_sort_keys, - longlong *limit, - grn_obj *target_table, grn_obj *score_column); + longlong *limit); long long int get_grn_time_from_timestamp_field(Field_timestamp *field); @@ -729,6 +727,9 @@ private: FT_INFO *storage_ft_init_ext(uint flags, uint key_nr, String *key); void generic_ft_init_ext_add_conditions_fast_order_limit( struct st_mrn_ft_info *info, grn_obj *expression); + struct st_mrn_ft_info *generic_ft_init_ext_select(uint flags, + uint key_nr, + String *key); FT_INFO *generic_ft_init_ext(uint flags, uint key_nr, String *key); int wrapper_ft_read(uchar *buf); int storage_ft_read(uchar *buf);