[Groonga-commit] groonga/groonga [master] Fix some of problems in grn_array_add().

Back to archive index

null+****@clear***** null+****@clear*****
2012年 3月 29日 (木) 16:09:39 JST


Susumu Yata	2012-03-29 16:09:39 +0900 (Thu, 29 Mar 2012)

  New Revision: da287cd3c7e2467f422f2aef3c1141ee64760ffd

  Log:
    Fix some of problems in grn_array_add().

  Modified files:
    lib/hash.c

  Modified: lib/hash.c (+61 -36)
===================================================================
--- lib/hash.c    2012-03-29 15:32:03 +0900 (22df28b)
+++ lib/hash.c    2012-03-29 16:09:39 +0900 (d869457)
@@ -545,6 +545,10 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
       if (!rc) {
         (*array->n_entries)--;
         (*array->n_garbages)++;
+        /*
+         * The following GRN_IO_ARRAY_BIT_OFF() never fails because the above
+         * grn_array_bitmap_at() returned 1 for the same ID.
+         */
         GRN_IO_ARRAY_BIT_OFF(array->io, array_seg_bitmap, id);
       }
     } else {
@@ -560,6 +564,10 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
       if (!rc) {
         (*array->n_entries)--;
         (*array->n_garbages)++;
+        /*
+         * The following grn_tiny_array_bit_off() never fails because the above
+         * grn_array_bitmap_at() returned 1 for the same ID.
+         */
         grn_tiny_array_bit_off(&array->bitmap, id);
       }
     }
@@ -713,39 +721,63 @@ grn_array_cursor_delete(grn_ctx *ctx, grn_array_cursor *cursor,
   return grn_array_delete_by_id(ctx, cursor->array, cursor->curr_rec, optarg);
 }
 
-/*
- * FIXME: Error handling of grn_array_add() is insufficient.
- */
+inline static grn_id
+grn_array_add_to_tiny_array(grn_ctx *ctx, grn_array *array, void **value)
+{
+  grn_id id = array->garbages;
+  void *entry;
+  if (id) {
+    entry = grn_tiny_array_at_inline(&array->a, id);
+    array->garbages = *(grn_id *)entry;
+    memset(entry, 0, array->value_size);
+    (*array->n_garbages)--;
+    grn_tiny_array_bit_on(&array->bitmap, id);
+  } else {
+    id = array->a.max + 1;
+    if (!grn_tiny_array_bit_on(&array->bitmap, id)) {
+      return GRN_ID_NIL;
+    }
+    entry = grn_tiny_array_at_inline(&array->a, id);
+    if (!entry) {
+      grn_tiny_array_bit_off(&array->bitmap, id);
+      return GRN_ID_NIL;
+    }
+    array->a.max = id;
+  }
+  (*array->n_entries)++;
+  if (value) { *value = entry; }
+  return id;
+}
 
 inline static grn_id
-grn_array_entry_new(grn_ctx *ctx, grn_array *array)
+grn_array_add_to_io_array(grn_ctx *ctx, grn_array *array, void **value)
 {
-  grn_id id;
-  if (IO_ARRAYP(array)) {
-    struct grn_array_header * const header = array->header;
-    id = header->garbages;
-    if (id) {
-      void * const entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD);
-      if (!entry) { return GRN_ID_NIL; }
-      header->garbages = *(grn_id *)entry;
-      memset(entry, 0, header->value_size);
-      (*array->n_garbages)--;
-    } else {
-      id = ++header->curr_rec;
+  struct grn_array_header * const header = array->header;
+  grn_id id = header->garbages;
+  void *entry;
+  if (id) {
+    entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD);
+    if (!entry) {
+      return GRN_ID_NIL;
     }
+    header->garbages = *(grn_id *)entry;
+    memset(entry, 0, header->value_size);
+    (*array->n_garbages)--;
+    /* FIXME: GRN_IO_ARRAY_BIT_ON() may fail and cause a critical problem. */
     GRN_IO_ARRAY_BIT_ON(array->io, array_seg_bitmap, id);
   } else {
-    id = array->garbages;
-    if (id) {
-      void * const entry = grn_tiny_array_at_inline(&array->a, id);
-      array->garbages = *(grn_id *)entry;
-      memset(entry, 0, array->value_size);
-      (*array->n_garbages)--;
-    } else {
-      id = ++array->a.max;
+    id = header->curr_rec + 1;
+    /* FIXME: GRN_IO_ARRAY_BIT_ON() may fail and cause a critical problem. */
+    GRN_IO_ARRAY_BIT_ON(array->io, array_seg_bitmap, id);
+    entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD);
+    if (!entry) {
+      GRN_IO_ARRAY_BIT_OFF(array->io, array_seg_bitmap, id);
+      return GRN_ID_NIL;
     }
-    grn_tiny_array_bit_on(&array->bitmap, id);
+    header->curr_rec = id;
   }
+  (*array->n_entries)++;
+  if (value) { *value = entry; }
   return id;
 }
 
@@ -753,17 +785,10 @@ grn_id
 grn_array_add(grn_ctx *ctx, grn_array *array, void **value)
 {
   if (ctx && array) {
-    const grn_id id = grn_array_entry_new(ctx, array);
-    if (id) {
-      void *entry;
-      (*array->n_entries)++;
-      /*
-       * FIXME: The following causes segmentation fault when
-       * grn_array_entry_at() returns NULL.
-       */
-      entry = grn_array_entry_at(ctx, array, id, GRN_TABLE_ADD);
-      if (value) { *value = entry; }
-      return id;
+    if (IO_ARRAYP(array)) {
+      return grn_array_add_to_io_array(ctx, array, value);
+    } else {
+      return grn_array_add_to_tiny_array(ctx, array, value);
     }
   }
   return GRN_ID_NIL;




Groonga-commit メーリングリストの案内
Back to archive index