Kouhei Sutou
null+****@clear*****
Wed Apr 12 11:43:18 JST 2017
Kouhei Sutou 2017-04-12 11:43:18 +0900 (Wed, 12 Apr 2017) New Revision: c5a9975fe2e4f4461a5089cbc2ba7bb7c09ac385 https://github.com/groonga/groonga/commit/c5a9975fe2e4f4461a5089cbc2ba7bb7c09ac385 Message: cache persistent: support statistics in multi processes Modified files: lib/cache.c Modified: lib/cache.c (+329 -139) =================================================================== --- lib/cache.c 2017-04-12 09:14:08 +0900 (3348a21) +++ lib/cache.c 2017-04-12 11:43:18 +0900 (2f9d5c5) @@ -36,10 +36,25 @@ struct _grn_cache_entry_memory { grn_id id; }; -typedef struct _grn_cache_entry_persistent { +typedef struct _grn_cache_entry_persistent_data { grn_id next; grn_id prev; grn_timeval modified_time; +} grn_cache_entry_persistent_data; + +/* + sizeof(grn_cache_entry_persistent_metadata) should be equal or smaller + than sizeof(grn_cache_entry_persistent_data). + */ +typedef struct _grn_cache_entry_persistent_metadata { + uint32_t max_nentries; + uint32_t nfetches; + uint32_t nhits; +} grn_cache_entry_persistent_metadata; + +typedef union _grn_cache_entry_persistent { + grn_cache_entry_persistent_data data; + grn_cache_entry_persistent_metadata metadata; } grn_cache_entry_persistent; struct _grn_cache { @@ -49,6 +64,9 @@ struct _grn_cache { grn_cache_entry_memory *prev; grn_hash *hash; grn_mutex mutex; + uint32_t max_nentries; + uint32_t nfetches; + uint32_t nhits; } memory; struct { grn_hash *keys; @@ -58,15 +76,16 @@ struct _grn_cache { } impl; grn_bool is_memory; grn_ctx *ctx; - uint32_t max_nentries; - uint32_t nfetches; - uint32_t nhits; }; #define GRN_CACHE_PERSISTENT_ROOT_ID 1 #define GRN_CACHE_PERSISTENT_ROOT_KEY "\0" #define GRN_CACHE_PERSISTENT_ROOT_KEY_LEN \ (sizeof(GRN_CACHE_PERSISTENT_ROOT_KEY) - 1) +#define GRN_CACHE_PERSISTENT_METADATA_ID 2 +#define GRN_CACHE_PERSISTENT_METADATA_KEY "\1" +#define GRN_CACHE_PERSISTENT_METADATA_KEY_LEN \ + (sizeof(GRN_CACHE_PERSISTENT_METADATA_KEY) - 1) static grn_ctx grn_cache_ctx; static grn_cache *grn_cache_current = NULL; @@ -95,7 +114,7 @@ grn_get_default_cache_base_path(void) } } -inline static void +static void grn_cache_open_memory(grn_ctx *ctx, grn_cache *cache) { cache->impl.memory.next = (grn_cache_entry_memory *)cache; @@ -110,9 +129,13 @@ grn_cache_open_memory(grn_ctx *ctx, grn_cache *cache) return; } MUTEX_INIT(cache->impl.memory.mutex); + + cache->impl.memory.max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES; + cache->impl.memory.nfetches = 0; + cache->impl.memory.nhits = 0; } -inline static void +static void grn_cache_open_persistent(grn_ctx *ctx, grn_cache *cache, const char *base_path) @@ -168,7 +191,7 @@ grn_cache_open_persistent(grn_ctx *ctx, sizeof(grn_cache_entry_persistent), GRN_OBJ_KEY_VAR_SIZE); if (!cache->impl.persistent.keys) { - ERR(ctx->rc, + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, "[cache][persistent] failed to create cache keys storage: <%s>", keys_path ? keys_path : "(memory)"); return; @@ -180,7 +203,7 @@ grn_cache_open_persistent(grn_ctx *ctx, 0); if (!cache->impl.persistent.values) { grn_hash_close(ctx, cache->impl.persistent.keys); - ERR(ctx->rc, + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, "[cache][persistent] failed to create cache values storage: <%s>", values_path ? values_path : "(memory)"); return; @@ -207,17 +230,50 @@ grn_cache_open_persistent(grn_ctx *ctx, if (keys_path) { grn_hash_remove(ctx, keys_path); } - ERR(ctx->rc, - "[cache][persistent] broken cache keys storage: <%s>", + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, + "[cache][persistent] broken cache keys storage: broken root: <%s>", + keys_path ? keys_path : "(memory)"); + return; + } + + if (added) { + entry->data.next = root_id; + entry->data.prev = root_id; + entry->data.modified_time.tv_sec = 0; + entry->data.modified_time.tv_nsec = 0; + } + } + + { + grn_cache_entry_persistent *entry; + grn_id metadata_id; + int added; + + metadata_id = grn_hash_add(ctx, + cache->impl.persistent.keys, + GRN_CACHE_PERSISTENT_METADATA_KEY, + GRN_CACHE_PERSISTENT_METADATA_KEY_LEN, + (void **)&entry, + &added); + if (metadata_id != GRN_CACHE_PERSISTENT_METADATA_ID) { + grn_ja_close(ctx, cache->impl.persistent.values); + grn_hash_close(ctx, cache->impl.persistent.keys); + if (values_path) { + grn_ja_remove(ctx, values_path); + } + if (keys_path) { + grn_hash_remove(ctx, keys_path); + } + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, + "[cache][persistent] broken cache keys storage: broken metadata: <%s>", keys_path ? keys_path : "(memory)"); return; } if (added) { - entry->next = root_id; - entry->prev = root_id; - entry->modified_time.tv_sec = 0; - entry->modified_time.tv_nsec = 0; + entry->metadata.max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES; + entry->metadata.nfetches = 0; + entry->metadata.nhits = 0; } } @@ -251,10 +307,6 @@ grn_cache_open_raw(grn_ctx *ctx, goto exit; } - cache->max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES; - cache->nfetches = 0; - cache->nhits = 0; - exit : GRN_API_RETURN(cache); } @@ -292,7 +344,7 @@ grn_persistent_cache_open(grn_ctx *ctx, const char *base_path) } -inline static void +static void grn_cache_close_memory(grn_ctx *ctx, grn_cache *cache) { grn_cache_entry_memory *vp; @@ -304,7 +356,7 @@ grn_cache_close_memory(grn_ctx *ctx, grn_cache *cache) MUTEX_FIN(cache->impl.memory.mutex); } -inline static void +static void grn_cache_close_persistent(grn_ctx *ctx, grn_cache *cache) { grn_hash_close(ctx, cache->impl.persistent.keys); @@ -352,76 +404,6 @@ grn_cache_init(void) grn_cache_current_set(ctx, grn_cache_default); } -grn_rc -grn_cache_set_max_n_entries(grn_ctx *ctx, grn_cache *cache, unsigned int n) -{ - uint32_t current_max_n_entries; - - if (!cache) { - return GRN_INVALID_ARGUMENT; - } - - current_max_n_entries = cache->max_nentries; - cache->max_nentries = n; - if (n < current_max_n_entries) { - grn_cache_expire(cache, current_max_n_entries - n); - } - - return GRN_SUCCESS; -} - -uint32_t -grn_cache_get_max_n_entries(grn_ctx *ctx, grn_cache *cache) -{ - if (!cache) { - return 0; - } - return cache->max_nentries; -} - -static void -grn_cache_get_statistics_memory(grn_ctx *ctx, grn_cache *cache, - grn_cache_statistics *statistics) -{ - MUTEX_LOCK(cache->impl.memory.mutex); - statistics->nentries = GRN_HASH_SIZE(cache->impl.memory.hash); - statistics->max_nentries = cache->max_nentries; - statistics->nfetches = cache->nfetches; - statistics->nhits = cache->nhits; - MUTEX_UNLOCK(cache->impl.memory.mutex); -} - -static void -grn_cache_get_statistics_persistent(grn_ctx *ctx, grn_cache *cache, - grn_cache_statistics *statistics) -{ - grn_rc rc = GRN_INVALID_ARGUMENT; - grn_hash *keys = cache->impl.persistent.keys; - - rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); - if (rc != GRN_SUCCESS) { - return; - } - - statistics->nentries = GRN_HASH_SIZE(keys); - statistics->max_nentries = cache->max_nentries; - statistics->nfetches = cache->nfetches; - statistics->nhits = cache->nhits; - - grn_io_unlock(keys->io); -} - -void -grn_cache_get_statistics(grn_ctx *ctx, grn_cache *cache, - grn_cache_statistics *statistics) -{ - if (cache->is_memory) { - return grn_cache_get_statistics_memory(ctx, cache, statistics); - } else { - return grn_cache_get_statistics_persistent(ctx, cache, statistics); - } -} - static void grn_cache_expire_entry_memory(grn_cache *cache, grn_cache_entry_memory *ce) { @@ -443,15 +425,15 @@ grn_cache_entry_persistent_delete_link(grn_cache *cache, prev_entry = (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, keys, - entry->prev, + entry->data.prev, NULL); next_entry = (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, keys, - entry->next, + entry->data.next, NULL); - prev_entry->next = entry->next; - next_entry->prev = entry->prev; + prev_entry->data.next = entry->data.next; + next_entry->data.prev = entry->data.prev; } static void @@ -465,15 +447,15 @@ grn_cache_entry_persistent_prepend_link(grn_cache *cache, grn_hash *keys = cache->impl.persistent.keys; grn_cache_entry_persistent *head_next_entry; - entry->next = head_entry->next; - entry->prev = head_entry_id; + entry->data.next = head_entry->data.next; + entry->data.prev = head_entry_id; head_next_entry = (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, keys, - head_entry->next, + head_entry->data.next, NULL); - head_next_entry->prev = entry_id; - head_entry->next = entry_id; + head_next_entry->data.prev = entry_id; + head_entry->data.next = entry_id; } static void @@ -489,7 +471,199 @@ grn_cache_expire_entry_persistent(grn_cache *cache, grn_hash_delete_by_id(cache->ctx, keys, cache_id, NULL); } -inline static grn_rc +static void +grn_cache_expire_memory_without_lock(grn_cache *cache, int32_t size) +{ + grn_cache_entry_memory *ce0 = + (grn_cache_entry_memory *)(&(cache->impl.memory)); + while (ce0 != ce0->prev && size--) { + grn_cache_expire_entry_memory(cache, ce0->prev); + } +} + +static void +grn_cache_expire_persistent_without_lock(grn_cache *cache, int32_t size) +{ + grn_ctx *ctx = cache->ctx; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *head_entry; + + head_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_ROOT_ID, + NULL); + while (head_entry->data.prev != GRN_CACHE_PERSISTENT_ROOT_ID && + size > 0) { + grn_cache_entry_persistent *tail_entry; + tail_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + head_entry->data.prev, + NULL); + grn_cache_expire_entry_persistent(cache, tail_entry, head_entry->data.prev); + size--; + } +} + +static grn_rc +grn_cache_set_max_n_entries_memory(grn_ctx *ctx, + grn_cache *cache, + unsigned int n) +{ + uint32_t current_max_n_entries; + + MUTEX_LOCK(cache->impl.memory.mutex); + current_max_n_entries = cache->impl.memory.max_nentries; + cache->impl.memory.max_nentries = n; + if (n < current_max_n_entries) { + grn_cache_expire_memory_without_lock(cache, current_max_n_entries - n); + } + MUTEX_UNLOCK(cache->impl.memory.mutex); + + return GRN_SUCCESS; +} + +static grn_rc +grn_cache_set_max_n_entries_persistent(grn_ctx *ctx, + grn_cache *cache, + unsigned int n) +{ + grn_rc rc; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *metadata_entry; + uint32_t current_max_n_entries; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return rc; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + + current_max_n_entries = metadata_entry->metadata.max_nentries; + metadata_entry->metadata.max_nentries = n; + if (n < current_max_n_entries) { + grn_cache_expire_persistent_without_lock(cache, current_max_n_entries - n); + } + grn_io_unlock(keys->io); + + return GRN_SUCCESS; +} + +grn_rc +grn_cache_set_max_n_entries(grn_ctx *ctx, grn_cache *cache, unsigned int n) +{ + if (!cache) { + return GRN_INVALID_ARGUMENT; + } + + if (cache->is_memory) { + return grn_cache_set_max_n_entries_memory(cache->ctx, cache, n); + } else { + return grn_cache_set_max_n_entries_persistent(cache->ctx, cache, n); + } +} + +static uint32_t +grn_cache_get_max_n_entries_memory(grn_ctx *ctx, grn_cache *cache) +{ + return cache->impl.memory.max_nentries; +} + +static uint32_t +grn_cache_get_max_n_entries_persistent(grn_ctx *ctx, grn_cache *cache) +{ + grn_rc rc; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *metadata_entry; + uint32_t current_max_n_entries; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return 0; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + current_max_n_entries = metadata_entry->metadata.max_nentries; + grn_io_unlock(keys->io); + + return current_max_n_entries; +} + +uint32_t +grn_cache_get_max_n_entries(grn_ctx *ctx, grn_cache *cache) +{ + if (!cache) { + return 0; + } + + if (cache->is_memory) { + return grn_cache_get_max_n_entries_memory(cache->ctx, cache); + } else { + return grn_cache_get_max_n_entries_persistent(cache->ctx, cache); + } +} + +static void +grn_cache_get_statistics_memory(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics) +{ + MUTEX_LOCK(cache->impl.memory.mutex); + statistics->nentries = GRN_HASH_SIZE(cache->impl.memory.hash); + statistics->max_nentries = cache->impl.memory.max_nentries; + statistics->nfetches = cache->impl.memory.nfetches; + statistics->nhits = cache->impl.memory.nhits; + MUTEX_UNLOCK(cache->impl.memory.mutex); +} + +static void +grn_cache_get_statistics_persistent(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *metadata_entry; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + + statistics->nentries = GRN_HASH_SIZE(keys); + statistics->max_nentries = metadata_entry->metadata.max_nentries; + statistics->nfetches = metadata_entry->metadata.nfetches; + statistics->nhits = metadata_entry->metadata.nhits; + + grn_io_unlock(keys->io); +} + +void +grn_cache_get_statistics(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics) +{ + if (cache->is_memory) { + return grn_cache_get_statistics_memory(ctx, cache, statistics); + } else { + return grn_cache_get_statistics_persistent(ctx, cache, statistics); + } +} + +static grn_rc grn_cache_fetch_memory(grn_ctx *ctx, grn_cache *cache, const char *key, uint32_t key_len, grn_obj *output) @@ -499,7 +673,7 @@ grn_cache_fetch_memory(grn_ctx *ctx, grn_cache *cache, grn_cache_entry_memory *ce; MUTEX_LOCK(cache->impl.memory.mutex); - cache->nfetches++; + cache->impl.memory.nfetches++; if (grn_hash_get(cache->ctx, cache->impl.memory.hash, key, key_len, (void **)&ce)) { if (ce->tv.tv_sec <= grn_db_get_last_modified(ctx, ctx->impl->db)) { @@ -521,14 +695,14 @@ grn_cache_fetch_memory(grn_ctx *ctx, grn_cache *cache, ce0->next->prev = ce; ce0->next = ce; } - cache->nhits++; + cache->impl.memory.nhits++; } exit : MUTEX_UNLOCK(cache->impl.memory.mutex); return rc; } -inline static grn_rc +static grn_rc grn_cache_fetch_persistent(grn_ctx *ctx, grn_cache *cache, const char *key, uint32_t key_len, grn_obj *output) @@ -539,6 +713,7 @@ grn_cache_fetch_persistent(grn_ctx *ctx, grn_cache *cache, grn_ja *values = cache->impl.persistent.values; grn_id cache_id; grn_cache_entry_persistent *entry; + grn_cache_entry_persistent *metadata_entry; if (key_len == GRN_CACHE_PERSISTENT_ROOT_KEY_LEN && memcmp(key, @@ -555,14 +730,20 @@ grn_cache_fetch_persistent(grn_ctx *ctx, grn_cache *cache, /* TODO: How about GRN_NOT_FOUND? */ rc = GRN_INVALID_ARGUMENT; - cache->nfetches++; + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + metadata_entry->metadata.nfetches++; + cache_id = grn_hash_get(cache->ctx, keys, key, key_len, (void **)&entry); if (cache_id == GRN_ID_NIL) { goto exit; } if (cache_id != GRN_ID_NIL) { - if (entry->modified_time.tv_sec <= + if (entry->data.modified_time.tv_sec <= grn_db_get_last_modified(ctx, ctx->impl->db)) { grn_cache_expire_entry_persistent(cache, entry, cache_id); goto exit; @@ -584,7 +765,7 @@ grn_cache_fetch_persistent(grn_ctx *ctx, grn_cache *cache, head_entry, GRN_CACHE_PERSISTENT_ROOT_ID); } - cache->nhits++; + metadata_entry->metadata.nhits++; } exit : @@ -607,7 +788,7 @@ grn_cache_fetch(grn_ctx *ctx, grn_cache *cache, } } -inline static void +static void grn_cache_update_memory(grn_ctx *ctx, grn_cache *cache, const char *key, uint32_t key_len, grn_obj *value) @@ -619,6 +800,10 @@ grn_cache_update_memory(grn_ctx *ctx, grn_cache *cache, grn_obj *old = NULL; grn_obj *obj = NULL; + if (cache->impl.memory.max_nentries == 0) { + return; + } + MUTEX_LOCK(cache->impl.memory.mutex); obj = grn_obj_open(cache->ctx, GRN_BULK, 0, GRN_DB_TEXT); if (!obj) { @@ -644,7 +829,8 @@ grn_cache_update_memory(grn_ctx *ctx, grn_cache *cache, ce0->next->prev = ce; ce0->next = ce; } - if (GRN_HASH_SIZE(cache->impl.memory.hash) > cache->max_nentries) { + if (GRN_HASH_SIZE(cache->impl.memory.hash) > + cache->impl.memory.max_nentries) { grn_cache_expire_entry_memory(cache, cache->impl.memory.prev); } } else { @@ -656,7 +842,7 @@ exit : MUTEX_UNLOCK(cache->impl.memory.mutex); } -inline static void +static void grn_cache_update_persistent(grn_ctx *ctx, grn_cache *cache, const char *key, uint32_t key_len, grn_obj *value) @@ -664,6 +850,7 @@ grn_cache_update_persistent(grn_ctx *ctx, grn_cache *cache, grn_rc rc; grn_hash *keys = cache->impl.persistent.keys; grn_ja *values = cache->impl.persistent.values; + grn_cache_entry_persistent *metadata_entry; grn_id cache_id; grn_cache_entry_persistent *entry; int added; @@ -675,11 +862,27 @@ grn_cache_update_persistent(grn_ctx *ctx, grn_cache *cache, return; } + if (key_len == GRN_CACHE_PERSISTENT_METADATA_KEY_LEN && + memcmp(key, + GRN_CACHE_PERSISTENT_METADATA_KEY, + GRN_CACHE_PERSISTENT_METADATA_KEY_LEN) == 0) { + return; + } + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); if (rc != GRN_SUCCESS) { return; } + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + if (metadata_entry->metadata.max_nentries == 0) { + goto exit; + } + cache_id = grn_hash_add(cache->ctx, keys, key, key_len, (void **)&entry, &added); if (cache_id) { @@ -688,7 +891,7 @@ grn_cache_update_persistent(grn_ctx *ctx, grn_cache *cache, if (!added) { grn_cache_entry_persistent_delete_link(cache, entry); } - entry->modified_time = ctx->impl->tv; + entry->data.modified_time = ctx->impl->tv; grn_ja_put(cache->ctx, values, cache_id, GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value), @@ -704,17 +907,20 @@ grn_cache_update_persistent(grn_ctx *ctx, grn_cache *cache, cache_id, head_entry, GRN_CACHE_PERSISTENT_ROOT_ID); - if (GRN_HASH_SIZE(keys) > cache->max_nentries) { + if (GRN_HASH_SIZE(keys) > metadata_entry->metadata.max_nentries) { grn_cache_entry_persistent *tail_entry; tail_entry = (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, keys, - head_entry->prev, + head_entry->data.prev, NULL); - grn_cache_expire_entry_persistent(cache, tail_entry, head_entry->prev); + grn_cache_expire_entry_persistent(cache, + tail_entry, + head_entry->data.prev); } } +exit : grn_io_unlock(keys->io); } @@ -722,7 +928,7 @@ void grn_cache_update(grn_ctx *ctx, grn_cache *cache, const char *key, uint32_t key_len, grn_obj *value) { - if (!ctx->impl || !cache->max_nentries) { return; } + if (!ctx->impl) { return; } if (cache->is_memory) { grn_cache_update_memory(ctx, cache, key, key_len, value); @@ -731,46 +937,28 @@ grn_cache_update(grn_ctx *ctx, grn_cache *cache, } } -inline static void +static void grn_cache_expire_memory(grn_cache *cache, int32_t size) { - grn_cache_entry_memory *ce0 = - (grn_cache_entry_memory *)(&(cache->impl.memory)); MUTEX_LOCK(cache->impl.memory.mutex); - while (ce0 != ce0->prev && size--) { - grn_cache_expire_entry_memory(cache, ce0->prev); - } + grn_cache_expire_memory_without_lock(cache, size); MUTEX_UNLOCK(cache->impl.memory.mutex); } -inline static void +static void grn_cache_expire_persistent(grn_cache *cache, int32_t size) { grn_rc rc; grn_ctx *ctx = cache->ctx; grn_hash *keys = cache->impl.persistent.keys; - grn_cache_entry_persistent *head_entry; rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); if (rc != GRN_SUCCESS) { return; } - head_entry = - (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, - keys, - GRN_CACHE_PERSISTENT_ROOT_ID, - NULL); - while (head_entry->prev != GRN_CACHE_PERSISTENT_ROOT_ID && size > 0) { - grn_cache_entry_persistent *tail_entry; - tail_entry = - (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, - keys, - head_entry->prev, - NULL); - grn_cache_expire_entry_persistent(cache, tail_entry, head_entry->prev); - size--; - } + grn_cache_expire_persistent_without_lock(cache, size); + grn_io_unlock(keys->io); } @@ -791,8 +979,10 @@ grn_cache_fin(void) grn_cache_current_set(ctx, NULL); - grn_cache_close(ctx, grn_cache_default); - grn_cache_default = NULL; + if (grn_cache_default) { + grn_cache_close(ctx, grn_cache_default); + grn_cache_default = NULL; + } grn_ctx_fin(ctx); } -------------- next part -------------- HTML����������������������������...Descargar