[Groonga-commit] groonga/groonga at 8709020 [master] grn_pat: detect `truncate` by another process

Back to archive index

Susumu Yata null+****@clear*****
Tue Dec 15 17:12:34 JST 2015


Susumu Yata	2015-12-15 17:12:34 +0900 (Tue, 15 Dec 2015)

  New Revision: 87090204ec4aa0b165ca51055e2a73954af7aa60
  https://github.com/groonga/groonga/commit/87090204ec4aa0b165ca51055e2a73954af7aa60

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

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

  Modified files:
    lib/grn_pat.h
    lib/pat.c

  Modified: lib/grn_pat.h (+2 -1)
===================================================================
--- lib/grn_pat.h    2015-12-15 09:45:02 +0900 (25f9dd7)
+++ lib/grn_pat.h    2015-12-15 17:12:34 +0900 (b8c7a32)
@@ -65,7 +65,8 @@ struct grn_pat_header {
   int32_t curr_del3;
   uint32_t n_garbages;
   grn_id normalizer;
-  uint32_t reserved[1004];
+  uint32_t truncated;
+  uint32_t reserved[1003];
   grn_pat_delinfo delinfos[GRN_PAT_NDELINFOS];
   grn_id garbages[GRN_PAT_MAX_KEY_SIZE + 1];
 };

  Modified: lib/pat.c (+203 -3)
===================================================================
--- lib/pat.c    2015-12-15 09:45:02 +0900 (fbf9f5a)
+++ lib/pat.c    2015-12-15 17:12:34 +0900 (4633413)
@@ -509,6 +509,7 @@ _grn_pat_create(grn_ctx *ctx, grn_pat *pat,
     pat->normalizer = NULL;
     header->normalizer = GRN_ID_NIL;
   }
+  header->truncated = GRN_FALSE;
   GRN_PTR_INIT(&(pat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL);
   pat->io = io;
   pat->header = header;
@@ -624,6 +625,64 @@ grn_pat_open(grn_ctx *ctx, const char *path)
   return pat;
 }
 
+/* grn_pat_reopen() reopens a grn_io for a truncated grn_pat. */
+static grn_rc
+grn_pat_reopen(grn_ctx *ctx, grn_pat *pat)
+{
+  grn_io *new_io;
+  const char *path;
+  struct grn_pat_header *new_header;
+  if (!ctx) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if (!pat || !pat->io) {
+    ERR(GRN_INVALID_ARGUMENT, "invalid argument");
+    return ctx->rc;
+  }
+  path = grn_io_path(pat->io);
+  if (!path || !*path) {
+    ERR(GRN_INVALID_ARGUMENT, "path not available");
+    return ctx->rc;
+  }
+  new_io = grn_io_open(ctx, path, 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_PAT_KEY) {
+    grn_io_close(ctx, new_io);
+    ERR(GRN_INVALID_FORMAT, "file type unmatch");
+    return ctx->rc;
+  }
+  new_header = grn_io_header(new_io);
+
+  pat->io = new_io;
+  pat->header = new_header;
+  pat->key_size = new_header->key_size;
+  pat->value_size = new_header->value_size;
+  pat->encoding = new_header->encoding;
+  pat->tokenizer = grn_ctx_at(ctx, new_header->tokenizer);
+  /* FIXME: This check may not be required. */
+  if (new_header->flags & GRN_OBJ_KEY_NORMALIZE) {
+    new_header->flags &= ~GRN_OBJ_KEY_NORMALIZE;
+    pat->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1);
+    new_header->normalizer = grn_obj_id(ctx, pat->normalizer);
+  } else {
+    pat->normalizer = grn_ctx_at(ctx, new_header->normalizer);
+  }
+  GRN_OBJ_FIN(ctx, &(pat->token_filters));
+  GRN_PTR_INIT(&(pat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL);
+  pat->obj.header.flags = new_header->flags;
+  if (pat->cache) {
+    grn_pat_cache_disable(ctx, pat);
+    pat->cache = NULL;
+    pat->cache_size = 0;
+  }
+  return GRN_SUCCESS;
+}
+
 grn_rc
 grn_pat_close(grn_ctx *ctx, grn_pat *pat)
 {
@@ -656,6 +715,12 @@ grn_pat_truncate(grn_ctx *ctx, grn_pat *pat)
   char *path;
   uint32_t key_size, value_size, flags;
 
+  if (pat->header->truncated) {
+    rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   if ((io_path = grn_io_path(pat->io)) && *io_path != '\0') {
     if (!(path = GRN_STRDUP(io_path))) {
       ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path);
@@ -667,6 +732,9 @@ grn_pat_truncate(grn_ctx *ctx, grn_pat *pat)
   key_size = pat->key_size;
   value_size = pat->value_size;
   flags = pat->obj.header.flags;
+  if (path) {
+    pat->header->truncated = GRN_TRUE;
+  }
   if ((rc = grn_io_close(ctx, pat->io))) { goto exit; }
   pat->io = NULL;
   if (path && (rc = grn_io_remove(ctx, path))) { goto exit; }
@@ -915,6 +983,12 @@ grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size,
   uint32_t new, lkey = 0;
   grn_id r0;
   uint8_t keybuf[MAX_FIXED_KEY_SIZE];
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return GRN_ID_NIL;
+    }
+  }
   if (!key || !key_size) { return GRN_ID_NIL; }
   if (key_size > GRN_TABLE_MAX_KEY_SIZE) {
     ERR(GRN_INVALID_ARGUMENT, "too long key: (%u)", key_size);
@@ -1005,6 +1079,12 @@ grn_id
 grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, void **value)
 {
   uint8_t keybuf[MAX_FIXED_KEY_SIZE];
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return GRN_ID_NIL;
+    }
+  }
   KEY_ENCODE(pat, keybuf, key, key_size);
   return _grn_pat_get(ctx, pat, key, key_size, value);
 }
@@ -1014,6 +1094,12 @@ grn_pat_nextid(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size)
 {
   grn_id r = GRN_ID_NIL;
   if (pat && key) {
+    if (pat->header->truncated) {
+      grn_rc rc = grn_pat_reopen(ctx, pat);
+      if (rc != GRN_SUCCESS) {
+        return GRN_ID_NIL;
+      }
+    }
     if (!(r = pat->header->garbages[key_size > sizeof(uint32_t) ? key_size : 0])) {
       r = pat->header->curr_rec + 1;
     }
@@ -1060,6 +1146,12 @@ grn_pat_prefix_search(grn_ctx *ctx, grn_pat *pat,
   grn_id r;
   pat_node *rn;
   uint8_t keybuf[MAX_FIXED_KEY_SIZE];
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   KEY_ENCODE(pat, keybuf, key, key_size);
   PAT_AT(pat, 0, rn);
   r = rn->lr[1];
@@ -1142,7 +1234,16 @@ grn_pat_lcp_search(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_siz
   grn_id r, r2 = GRN_ID_NIL;
   uint32_t len = key_size * 16;
   int c0 = -1, c;
-  if (!pat || !key || !(pat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE)) { return GRN_ID_NIL; }
+  if (!pat || !key) {
+    return GRN_ID_NIL;
+  }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return GRN_ID_NIL;
+    }
+  }
+  if (!(pat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE)) { return GRN_ID_NIL; }
   PAT_AT(pat, 0, rn);
   for (r = rn->lr[1]; r;) {
     PAT_AT(pat, r, rn);
@@ -1397,6 +1498,12 @@ grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size,
 {
   uint8_t keybuf[MAX_FIXED_KEY_SIZE];
   if (!pat || !key || !key_size) { return GRN_INVALID_ARGUMENT; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   KEY_ENCODE(pat, keybuf, key, key_size);
   return _grn_pat_delete(ctx, pat, key, key_size, optarg);
 }
@@ -1405,6 +1512,12 @@ uint32_t
 grn_pat_size(grn_ctx *ctx, grn_pat *pat)
 {
   if (!pat) { return GRN_INVALID_ARGUMENT; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   return pat->header->n_entries;
 }
 
@@ -1413,6 +1526,12 @@ _grn_pat_key(grn_ctx *ctx, grn_pat *pat, grn_id id, uint32_t *key_size)
 {
   pat_node *node;
   uint8_t *key;
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return NULL;
+    }
+  }
   PAT_AT(pat, id, node);
   if (!node) {
     *key_size = 0;
@@ -1432,6 +1551,12 @@ grn_pat_delete_by_id(grn_ctx *ctx, grn_pat *pat, grn_id id,
                      grn_table_delete_optarg *optarg)
 {
   if (!pat || !id) { return GRN_INVALID_ARGUMENT; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   {
     uint32_t key_size;
     const char *key = _grn_pat_key(ctx, pat, id, &key_size);
@@ -1446,6 +1571,12 @@ grn_pat_get_key(grn_ctx *ctx, grn_pat *pat, grn_id id, void *keybuf, int bufsize
   uint8_t *key;
   pat_node *node;
   if (!pat) { return GRN_INVALID_ARGUMENT; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return 0;
+    }
+  }
   if (!id) { return 0; }
   PAT_AT(pat, id, node);
   if (!node) { return 0; }
@@ -1468,6 +1599,12 @@ grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk)
   uint8_t *key;
   pat_node *node;
   if (!pat) { return GRN_INVALID_ARGUMENT; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return 0;
+    }
+  }
   if (!id) { return 0; }
   PAT_AT(pat, id, node);
   if (!node) { return 0; }
@@ -1496,7 +1633,14 @@ grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk)
 int
 grn_pat_get_value(grn_ctx *ctx, grn_pat *pat, grn_id id, void *valuebuf)
 {
-  int value_size = (int)pat->value_size;
+  int value_size;
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return 0;
+    }
+  }
+  value_size = (int)pat->value_size;
   if (value_size) {
     byte *v = (byte *)sis_at(ctx, pat, id);
     if (v) {
@@ -1517,6 +1661,12 @@ const char *
 grn_pat_get_value_(grn_ctx *ctx, grn_pat *pat, grn_id id, uint32_t *size)
 {
   const char *value = NULL;
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return NULL;
+    }
+  }
   if ((*size = pat->value_size)) {
     if ((value = (const char *)sis_at(ctx, pat, id))
         && (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS)) {
@@ -1530,6 +1680,12 @@ grn_rc
 grn_pat_set_value(grn_ctx *ctx, grn_pat *pat, grn_id id,
                   const void *value, int flags)
 {
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   if (value) {
     uint32_t value_size = pat->value_size;
     if (value_size) {
@@ -1582,6 +1738,12 @@ grn_pat_info(grn_ctx *ctx, grn_pat *pat, int *key_size, unsigned int *flags,
 {
   ERRCLR(NULL);
   if (!pat) { return GRN_INVALID_ARGUMENT; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
   if (key_size) { *key_size = pat->key_size; }
   if (flags) { *flags = pat->obj.header.flags; }
   if (encoding) { *encoding = pat->encoding; }
@@ -1603,7 +1765,14 @@ grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id,
 {
   int level = 0, shared;
   const char *key = NULL, *_key;
-  sis_node *sp, *ss = NULL, *si = sis_at(ctx, pat, id);
+  sis_node *sp, *ss = NULL, *si;
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return 0;
+    }
+  }
+  si = sis_at(ctx, pat, id);
   while (id) {
     pat_node *rn;
     uint32_t key_size;
@@ -1677,6 +1846,12 @@ grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id,
 grn_id
 grn_pat_next(grn_ctx *ctx, grn_pat *pat, grn_id id)
 {
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return GRN_ID_NIL;
+    }
+  }
   while (++id <= pat->header->curr_rec) {
     uint32_t key_size;
     const char *key = _grn_pat_key(ctx, pat, id, &key_size);
@@ -1699,6 +1874,12 @@ grn_pat_at(grn_ctx *ctx, grn_pat *pat, grn_id id)
 grn_id
 grn_pat_curr_id(grn_ctx *ctx, grn_pat *pat)
 {
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return GRN_ID_NIL;
+    }
+  }
   return pat->header->curr_rec;
 }
 
@@ -1708,6 +1889,12 @@ grn_pat_scan(grn_ctx *ctx, grn_pat *pat, const char *str, unsigned int str_len,
 {
   int n = 0;
   grn_id tid;
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return 0;
+    }
+  }
   if (pat->normalizer) {
     grn_obj *nstr = grn_string_open(ctx, str, str_len,
                                     pat->normalizer, GRN_STRING_WITH_CHECKS);
@@ -2294,6 +2481,12 @@ grn_pat_cursor_open(grn_ctx *ctx, grn_pat *pat,
   pat_node *node;
   grn_pat_cursor *c;
   if (!pat || !ctx) { return NULL; }
+  if (pat->header->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return NULL;
+    }
+  }
   if ((flags & GRN_CURSOR_BY_ID)) {
     return grn_pat_cursor_open_by_id(ctx, pat, min, min_size, max, max_size,
                                      offset, limit, flags);
@@ -2457,6 +2650,13 @@ grn_pat_check(grn_ctx *ctx, grn_pat *pat)
 {
   char buf[8];
   struct grn_pat_header *h = pat->header;
+  if (h->truncated) {
+    grn_rc rc = grn_pat_reopen(ctx, pat);
+    if (rc != GRN_SUCCESS) {
+      return;
+    }
+    h = pat->header;
+  }
   GRN_OUTPUT_ARRAY_OPEN("RESULT", 1);
   GRN_OUTPUT_MAP_OPEN("SUMMARY", 23);
   GRN_OUTPUT_CSTR("flags");
-------------- next part --------------
HTML����������������������������...
다운로드 



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