Kouhei Sutou
null+****@clear*****
Tue May 10 15:54:32 JST 2016
Kouhei Sutou 2016-05-10 15:54:32 +0900 (Tue, 10 May 2016) New Revision: 7d44c232ce421b00b4c51bbeea03356af48f10ee https://github.com/groonga/groonga/commit/7d44c232ce421b00b4c51bbeea03356af48f10ee Merged e8958bc: Merge pull request #543 from groonga/support-dirty-crash-detection Message: Support detecting changed database isn't closed It doesn't increase no overhead when the database isn't changed. For example, you have no overhead and no change when you only use select command. It doesn't flush many times. It flushes only at the first database change. Modified files: lib/dat.cpp lib/db.c lib/grn_dat.h lib/grn_pat.h lib/pat.c Modified: lib/dat.cpp (+27 -0) =================================================================== --- lib/dat.cpp 2016-05-10 15:40:40 +0900 (51a84da) +++ lib/dat.cpp 2016-05-10 15:54:32 +0900 (15001cf) @@ -115,6 +115,7 @@ grn_dat_init(grn_ctx *, grn_dat *dat) dat->normalizer = NULL; GRN_PTR_INIT(&(dat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); CRITICAL_SECTION_INIT(dat->lock); + dat->is_dirty = GRN_FALSE; } void @@ -126,6 +127,10 @@ grn_dat_fin(grn_ctx *ctx, grn_dat *dat) dat->old_trie = NULL; dat->trie = NULL; if (dat->io) { + if (dat->is_dirty) { + uint32_t n_dirty_opens; + GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), -1, n_dirty_opens); + } grn_io_close(ctx, dat->io); dat->io = NULL; } @@ -1142,4 +1147,26 @@ grn_dat_flush(grn_ctx *ctx, grn_dat *dat) return GRN_SUCCESS; } +grn_rc +grn_dat_dirty(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat->io) { + return GRN_SUCCESS; + } + + grn_rc rc = GRN_SUCCESS; + + { + CriticalSection critical_section(&dat->lock); + if (!dat->is_dirty) { + uint32_t n_dirty_opens; + dat->is_dirty = GRN_TRUE; + GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), 1, n_dirty_opens); + rc = grn_io_flush(ctx, dat->io); + } + } + + return rc; +} + } // extern "C" Modified: lib/db.c (+11 -0) =================================================================== --- lib/db.c 2016-05-10 15:40:40 +0900 (0558bb2) +++ lib/db.c 2016-05-10 15:54:32 +0900 (c849a22) @@ -664,7 +664,18 @@ grn_db_touch(grn_ctx *ctx, grn_obj *s) static inline void grn_obj_touch_db(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv) { + grn_db *db = (grn_db *)obj; + grn_obj_io(obj)->header->lastmod = tv->tv_sec; + + switch (db->keys->header.type) { + case GRN_TABLE_PAT_KEY : + grn_pat_dirty(ctx, (grn_pat *)(db->keys)); + break; + case GRN_TABLE_DAT_KEY : + grn_dat_dirty(ctx, (grn_dat *)(db->keys)); + break; + } } void Modified: lib/grn_dat.h (+5 -1) =================================================================== --- lib/grn_dat.h 2016-05-10 15:40:40 +0900 (2d4ac2a) +++ lib/grn_dat.h 2016-05-10 15:54:32 +0900 (f68d760) @@ -37,6 +37,7 @@ struct _grn_dat { grn_obj *normalizer; grn_obj token_filters; grn_critical_section lock; + grn_bool is_dirty; }; struct grn_dat_header { @@ -45,7 +46,8 @@ struct grn_dat_header { grn_id tokenizer; uint32_t file_id; grn_id normalizer; - uint32_t reserved[235]; + uint32_t n_dirty_opens; + uint32_t reserved[234]; }; struct _grn_dat_cursor { @@ -79,6 +81,8 @@ GRN_API grn_rc grn_dat_repair(grn_ctx *ctx, grn_dat *dat); GRN_API grn_rc grn_dat_flush(grn_ctx *ctx, grn_dat *dat); +grn_rc grn_dat_dirty(grn_ctx *ctx, grn_dat *dat); + #ifdef __cplusplus } #endif Modified: lib/grn_pat.h (+6 -1) =================================================================== --- lib/grn_pat.h 2016-05-10 15:40:40 +0900 (10aa0f1) +++ lib/grn_pat.h 2016-05-10 15:54:32 +0900 (aa66d52) @@ -41,6 +41,8 @@ struct _grn_pat { grn_obj token_filters; grn_id *cache; uint32_t cache_size; + grn_bool is_dirty; + grn_critical_section lock; }; #define GRN_PAT_NDELINFOS 0x100 @@ -68,7 +70,8 @@ struct grn_pat_header { uint32_t n_garbages; grn_id normalizer; uint32_t truncated; - uint32_t reserved[1003]; + uint32_t n_dirty_opens; + uint32_t reserved[1002]; grn_pat_delinfo delinfos[GRN_PAT_NDELINFOS]; grn_id garbages[GRN_PAT_MAX_KEY_SIZE + 1]; }; @@ -116,6 +119,8 @@ uint32_t grn_pat_total_key_size(grn_ctx *ctx, grn_pat *pat); grn_bool grn_pat_is_key_encoded(grn_ctx *ctx, grn_pat *pat); +grn_rc grn_pat_dirty(grn_ctx *ctx, grn_pat *pat); + #ifdef __cplusplus } #endif Modified: lib/pat.c (+30 -0) =================================================================== --- lib/pat.c 2016-05-10 15:40:40 +0900 (9fbdac8) +++ lib/pat.c 2016-05-10 15:54:32 +0900 (9db177c) @@ -541,6 +541,8 @@ grn_pat_create(grn_ctx *ctx, const char *path, uint32_t key_size, } pat->cache = NULL; pat->cache_size = 0; + pat->is_dirty = GRN_FALSE; + CRITICAL_SECTION_INIT(pat->lock); return pat; } @@ -623,6 +625,8 @@ grn_pat_open(grn_ctx *ctx, const char *path) } pat->cache = NULL; pat->cache_size = 0; + pat->is_dirty = GRN_FALSE; + CRITICAL_SECTION_INIT(pat->lock); return pat; } @@ -649,6 +653,14 @@ grn_rc grn_pat_close(grn_ctx *ctx, grn_pat *pat) { grn_rc rc; + + CRITICAL_SECTION_FIN(pat->lock); + + if (pat->is_dirty) { + uint32_t n_dirty_opens; + GRN_ATOMIC_ADD_EX(&(pat->header->n_dirty_opens), -1, n_dirty_opens); + } + if ((rc = grn_io_close(ctx, pat->io))) { ERR(rc, "grn_io_close failed"); } else { @@ -656,6 +668,7 @@ grn_pat_close(grn_ctx *ctx, grn_pat *pat) if (pat->cache) { grn_pat_cache_disable(ctx, pat); } GRN_FREE(pat); } + return rc; } @@ -3544,3 +3557,20 @@ grn_pat_is_key_encoded(grn_ctx *ctx, grn_pat *pat) return KEY_NEEDS_CONVERT(pat, key_size); } + +grn_rc +grn_pat_dirty(grn_ctx *ctx, grn_pat *pat) +{ + grn_rc rc = GRN_SUCCESS; + + CRITICAL_SECTION_ENTER(pat->lock); + if (!pat->is_dirty) { + uint32_t n_dirty_opens; + pat->is_dirty = GRN_TRUE; + GRN_ATOMIC_ADD_EX(&(pat->header->n_dirty_opens), 1, n_dirty_opens); + rc = grn_io_flush(ctx, pat->io); + } + CRITICAL_SECTION_LEAVE(pat->lock); + + return rc; +} -------------- next part -------------- HTML����������������������������... Télécharger