[Groonga-commit] groonga/groonga [master] Improve error handling of grn_array.

Back to archive index

null+****@clear***** null+****@clear*****
2012年 4月 2日 (月) 18:15:43 JST


Susumu Yata	2012-04-02 18:15:43 +0900 (Mon, 02 Apr 2012)

  New Revision: 895b990810a20b36e9f99f7e33711172d99a5d5d

  Log:
    Improve error handling of grn_array.

  Modified files:
    lib/hash.c

  Modified: lib/hash.c (+52 -27)
===================================================================
--- lib/hash.c    2012-04-03 13:47:53 +0900 (e7adfca)
+++ lib/hash.c    2012-04-02 18:15:43 +0900 (4809020)
@@ -290,13 +290,14 @@ grn_array_entry_at(grn_ctx *ctx, grn_array *array, grn_id id, int flags)
   }
 }
 
-inline static grn_bool
+/* grn_array_bitmap_at() returns 1/0 on success, -1 on failure. */
+inline static int
 grn_array_bitmap_at(grn_ctx *ctx, grn_array *array, grn_id id)
 {
   if (grn_array_is_io_array(array)) {
-    return grn_io_array_bit_at(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id) == 1;
+    return grn_io_array_bit_at(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id);
   } else {
-    return grn_tiny_array_bit_at(&array->bitmap, id) == 1;
+    return grn_tiny_array_bit_at(&array->bitmap, id);
   }
 }
 
@@ -508,7 +509,7 @@ int
 grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf)
 {
   if (ctx && array) {
-    if (grn_array_bitmap_at(ctx, array, id)) {
+    if (grn_array_bitmap_at(ctx, array, id) == 1) {
       void * const entry = grn_array_entry_at(ctx, array, id, 0);
       if (entry) {
         if (valuebuf) {
@@ -521,12 +522,19 @@ grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf)
   return 0;
 }
 
+inline static grn_id
+grn_array_get_max_id(grn_array *array)
+{
+  return grn_array_is_io_array(array) ? array->header->curr_rec : array->array.max;
+}
+
 void *
 _grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id)
 {
   if (ctx && array) {
-    if (!grn_array_bitmap_at(ctx, array, id)) { return NULL; }
-    return grn_array_entry_at(ctx, array, id, 0);
+    if (grn_array_bitmap_at(ctx, array, id) == 1) {
+      return grn_array_entry_at(ctx, array, id, 0);
+    }
   }
   return NULL;
 }
@@ -538,7 +546,7 @@ grn_array_set_value(grn_ctx *ctx, grn_array *array, grn_id id,
   if (!ctx || !array || !value) {
     return GRN_INVALID_ARGUMENT;
   }
-  if (!grn_array_bitmap_at(ctx, array, id)) {
+  if (grn_array_bitmap_at(ctx, array, id) != 1) {
     return GRN_INVALID_ARGUMENT;
   }
 
@@ -590,7 +598,7 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
   if (!ctx || !array) {
     return GRN_INVALID_ARGUMENT;
   }
-  if (!grn_array_bitmap_at(ctx, array, id)) {
+  if (grn_array_bitmap_at(ctx, array, id) != 1) {
     return GRN_INVALID_ARGUMENT;
   }
 
@@ -612,8 +620,9 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
         (*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.
+         * The following grn_io_array_bit_off() fails iff a problem has
+         * occurred after the above grn_array_bitmap_at(). That is to say,
+         * an unexpected case.
          */
         grn_io_array_bit_off(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id);
       }
@@ -631,8 +640,9 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
         (*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.
+         * The following grn_io_array_bit_off() fails iff a problem has
+         * occurred after the above grn_array_bitmap_at(). That is to say,
+         * an unexpected case.
          */
         grn_tiny_array_bit_off(&array->bitmap, id);
       }
@@ -645,7 +655,7 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
 grn_id
 grn_array_at(grn_ctx *ctx, grn_array *array, grn_id id)
 {
-  return grn_array_bitmap_at(ctx, array, id) ? id : GRN_ID_NIL;
+  return (grn_array_bitmap_at(ctx, array, id) == 1) ? id : GRN_ID_NIL;
 }
 
 grn_rc
@@ -668,12 +678,6 @@ grn_array_cursor_close(grn_ctx *ctx, grn_array_cursor *cursor)
   GRN_FREE(cursor);
 }
 
-inline static grn_id
-grn_array_get_max_id(grn_array *array)
-{
-  return grn_array_is_io_array(array) ? array->header->curr_rec : array->array.max;
-}
-
 grn_array_cursor *
 grn_array_cursor_open(grn_ctx *ctx, grn_array *array, grn_id min, grn_id max,
                       int offset, int limit, int flags)
@@ -725,7 +729,9 @@ grn_array_cursor_open(grn_ctx *ctx, grn_array *array, grn_id min, grn_id max,
   if (*array->n_garbages) {
     while (offset && cursor->curr_rec != cursor->tail) {
       cursor->curr_rec += cursor->dir;
-      if (grn_array_bitmap_at(ctx, cursor->array, cursor->curr_rec)) { offset--; }
+      if (grn_array_bitmap_at(ctx, cursor->array, cursor->curr_rec) == 1) {
+        offset--;
+      }
     }
   } else {
     cursor->curr_rec += cursor->dir * offset;
@@ -741,7 +747,9 @@ grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor)
     while (cursor->curr_rec != cursor->tail) {
       cursor->curr_rec += cursor->dir;
       if (*cursor->array->n_garbages) {
-        if (!grn_array_bitmap_at(ctx, cursor->array, cursor->curr_rec)) { continue; }
+        if (grn_array_bitmap_at(ctx, cursor->array, cursor->curr_rec) != 1) {
+          continue;
+        }
       }
       cursor->rest--;
       return cursor->curr_rec;
@@ -755,7 +763,7 @@ grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id)
 {
   grn_id max = grn_array_get_max_id(array);
   while (++id <= max) {
-    if (grn_array_bitmap_at(ctx, array, id)) { return id; }
+    if (grn_array_bitmap_at(ctx, array, id) == 1) { return id; }
   }
   return GRN_ID_NIL;
 }
@@ -793,11 +801,21 @@ grn_array_add_to_tiny_array(grn_ctx *ctx, grn_array *array, void **value)
   grn_id id = array->garbages;
   void *entry;
   if (id) {
+    /* These operations fail iff the array is broken. */
     entry = grn_tiny_array_at_inline(&array->array, id);
+    if (!entry) {
+      return GRN_ID_NIL;
+    }
     array->garbages = *(grn_id *)entry;
     memset(entry, 0, array->value_size);
     (*array->n_garbages)--;
-    grn_tiny_array_bit_on(&array->bitmap, id);
+    if (!grn_tiny_array_bit_on(&array->bitmap, id)) {
+      /* Actually, it is difficult to recover from this error. */
+      *(grn_id *)entry = array->garbages;
+      array->garbages = id;
+      (*array->n_garbages)++;
+      return GRN_ID_NIL;
+    }
   } else {
     id = array->array.max + 1;
     if (!grn_tiny_array_bit_on(&array->bitmap, id)) {
@@ -822,6 +840,7 @@ grn_array_add_to_io_array(grn_ctx *ctx, grn_array *array, void **value)
   grn_id id = header->garbages;
   void *entry;
   if (id) {
+    /* These operations fail iff the array is broken. */
     entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD);
     if (!entry) {
       return GRN_ID_NIL;
@@ -829,12 +848,18 @@ grn_array_add_to_io_array(grn_ctx *ctx, grn_array *array, void **value)
     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(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id);
+    if (!grn_io_array_bit_on(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id)) {
+      /* Actually, it is difficult to recover from this error. */
+      *(grn_id *)entry = array->garbages;
+      array->garbages = id;
+      (*array->n_garbages)++;
+      return GRN_ID_NIL;
+    }
   } else {
     id = header->curr_rec + 1;
-    /* FIXME: grn_io_array_bit_on() may fail and cause a critical problem. */
-    grn_io_array_bit_on(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id);
+    if (!grn_io_array_bit_on(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id)) {
+      return GRN_ID_NIL;
+    }
     entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD);
     if (!entry) {
       grn_io_array_bit_off(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id);




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