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����������������������������...다운로드