[Groonga-commit] groonga/groonga at 963ae77 [master] grn_array: detect `truncate` by another process

Back to archive index

Susumu Yata null+****@clear*****
Mon Dec 14 23:31:25 JST 2015


Susumu Yata	2015-12-14 23:31:25 +0900 (Mon, 14 Dec 2015)

  New Revision: 963ae77d989cc90a6df12be255143a45645edf22
  https://github.com/groonga/groonga/commit/963ae77d989cc90a6df12be255143a45645edf22

  Merged e1d688f: Merge pull request #449 from groonga/detect-truncate

  Message:
    grn_array: detect `truncate` by another process
    
    GitHub: #447

  Modified files:
    lib/hash.c

  Modified: lib/hash.c (+103 -5)
===================================================================
--- lib/hash.c    2015-12-11 19:04:13 +0900 (2c44f25)
+++ lib/hash.c    2015-12-14 23:31:25 +0900 (6a88450)
@@ -397,7 +397,8 @@ struct grn_array_header {
   uint32_t n_garbages;
   grn_id garbages;
   uint32_t lock;
-  uint32_t reserved[9];
+  uint32_t truncated;
+  uint32_t reserved[8];
   grn_table_queue queue;
 };
 
@@ -462,6 +463,7 @@ grn_array_init_tiny_array(grn_ctx *ctx, grn_array *array, const char *path,
   array->n_garbages_buf = 0;
   array->n_entries_buf = 0;
   array->io = NULL;
+  array->header = NULL;
   array->garbages = GRN_ID_NIL;
   grn_tiny_array_init(ctx, &array->array, value_size, GRN_TINY_ARRAY_CLEAR);
   grn_tiny_bitmap_init(ctx, &array->bitmap);
@@ -509,6 +511,7 @@ grn_array_init_io_array(grn_ctx *ctx, grn_array *array, const char *path,
   header->n_entries = 0;
   header->n_garbages = 0;
   header->garbages = GRN_ID_NIL;
+  header->truncated = GRN_FALSE;
   grn_table_queue_init(ctx, &header->queue);
   array->obj.header.flags = flags;
   array->ctx = ctx;
@@ -607,6 +610,57 @@ grn_array_open(grn_ctx *ctx, const char *path)
   return NULL;
 }
 
+/* grn_array_reopen() reopens a grn_io for a truncated grn_array. */
+static grn_rc
+grn_array_reopen(grn_ctx *ctx, grn_array *array)
+{
+  grn_io *new_io;
+  const char *path;
+  struct grn_array_header *new_header;
+  if (!ctx) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if (!array || !array->io) {
+    ERR(GRN_INVALID_ARGUMENT, "invalid argument");
+    return ctx->rc;
+  }
+  path = grn_io_path(array->io);
+  if (!path || !*path) {
+    ERR(GRN_INVALID_ARGUMENT, "path not available");
+    return ctx->rc;
+  }
+  new_io = grn_io_open(ctx, grn_io_path(array->io), grn_io_auto);
+  if (!new_io) {
+    if (ctx->rc == GRN_SUCCESS) {
+      ERR(GRN_UNKNOWN_ERROR, "grn_io_open failed");
+    }
+    return ctx->rc;
+  }
+  if (grn_io_get_type(new_io) != GRN_TABLE_NO_KEY) {
+    grn_io_close(ctx, new_io);
+    ERR(GRN_INVALID_FORMAT, "file type unmatch");
+    return ctx->rc;
+  }
+  new_header = grn_io_header(new_io);
+  if (new_header->flags & GRN_ARRAY_TINY) {
+    grn_io_close(ctx, new_io);
+    ERR(GRN_INVALID_FORMAT, "invalid array flags");
+    return ctx->rc;
+  }
+  array->obj.header.flags = new_header->flags;
+  array->ctx = ctx;
+  array->value_size = new_header->value_size;
+  array->n_keys = 0;
+  array->keys = NULL;
+  array->n_garbages = &new_header->n_garbages;
+  array->n_entries = &new_header->n_entries;
+  grn_io_close(ctx, array->io);
+  array->io = new_io;
+  array->header = new_header;
+  array->lock = &new_header->lock;
+  return GRN_SUCCESS;
+}
+
 grn_rc
 grn_array_close(grn_ctx *ctx, grn_array *array)
 {
@@ -653,6 +707,10 @@ grn_array_truncate(grn_ctx *ctx, grn_array *array)
   flags = array->obj.header.flags;
 
   if (grn_array_is_io_array(array)) {
+    if (path) {
+      /* Only an I/O array with a valid path uses the `truncated` flag. */
+      array->header->truncated = GRN_TRUE;
+    }
     rc = grn_io_close(ctx, array->io);
     if (!rc) {
       array->io = NULL;
@@ -680,6 +738,12 @@ grn_array_get_value_inline(grn_ctx *ctx, grn_array *array, grn_id id)
   if (!ctx || !array) {
     return NULL;
   }
+  if (array->header && array->header->truncated) {
+    grn_rc rc = grn_array_reopen(ctx, array);
+    if (rc != GRN_SUCCESS) {
+      return NULL;
+    }
+  }
   if (*array->n_garbages) {
     /*
      * grn_array_bitmap_at() is a time-consuming function, so it is called only
@@ -717,7 +781,14 @@ inline static grn_rc
 grn_array_set_value_inline(grn_ctx *ctx, grn_array *array, grn_id id,
                            const void *value, int flags)
 {
-  void * const entry = grn_array_entry_at(ctx, array, id, 0);
+  void *entry;
+  if (array->header && array->header->truncated) {
+    grn_rc rc = grn_array_reopen(ctx, array);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
+  entry = grn_array_entry_at(ctx, array, id, 0);
   if (!entry) {
     return GRN_NO_MEMORY_AVAILABLE;
   }
@@ -784,6 +855,12 @@ grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id,
   if (!ctx || !array) {
     return GRN_INVALID_ARGUMENT;
   }
+  if (array->header && array->header->truncated) {
+    grn_rc rc = grn_array_reopen(ctx, array);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   if (grn_array_bitmap_at(ctx, array, id) != 1) {
     return GRN_INVALID_ARGUMENT;
   }
@@ -881,6 +958,12 @@ grn_array_cursor_open(grn_ctx *ctx, grn_array *array, grn_id min, grn_id max,
 {
   grn_array_cursor *cursor;
   if (!array || !ctx) { return NULL; }
+  if (array->header && array->header->truncated) {
+    grn_rc rc = grn_array_reopen(ctx, array);
+    if (rc != GRN_SUCCESS) {
+      return NULL;
+    }
+  }
 
   cursor = (grn_array_cursor *)GRN_MALLOCN(grn_array_cursor, 1);
   if (!cursor) { return NULL; }
@@ -958,7 +1041,14 @@ grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor)
 grn_id
 grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id)
 {
-  const grn_id max_id = grn_array_get_max_id(array);
+  grn_id max_id;
+  if (array->header && array->header->truncated) {
+    grn_rc rc = grn_array_reopen(ctx, array);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
+  max_id = grn_array_get_max_id(array);
   while (++id <= max_id) {
     if (!*array->n_garbages ||
         grn_array_bitmap_at(ctx, array, id) == 1) {
@@ -1037,9 +1127,17 @@ grn_array_add_to_tiny_array(grn_ctx *ctx, grn_array *array, void **value)
 inline static grn_id
 grn_array_add_to_io_array(grn_ctx *ctx, grn_array *array, void **value)
 {
-  struct grn_array_header * const header = array->header;
-  grn_id id = header->garbages;
+  grn_id id;
   void *entry;
+  struct grn_array_header *header;
+  if (array->header->truncated) {
+    grn_rc rc = grn_array_reopen(ctx, array);
+    if (rc != GRN_SUCCESS) {
+      return GRN_ID_NIL;
+    }
+  }
+  header = array->header;
+  id = header->garbages;
   if (id) {
     /* These operations fail iff the array is broken. */
     entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD);
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index