[Groonga-mysql-commit] mroonga/mroonga [master] Fix a crash bug when there is a syntax error query in many queries

アーカイブの一覧に戻る

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);




Groonga-mysql-commit メーリングリストの案内
アーカイブの一覧に戻る