diff options
-rw-r--r-- | include/git2/common.h | 3 | ||||
-rw-r--r-- | src/cache.c | 25 | ||||
-rw-r--r-- | src/cache.h | 1 | ||||
-rw-r--r-- | src/util.c | 6 | ||||
-rw-r--r-- | tests-clar/object/cache.c | 6 |
5 files changed, 29 insertions, 12 deletions
diff --git a/include/git2/common.h b/include/git2/common.h index 80d83d345..ccd252fda 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -131,7 +131,8 @@ enum { GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, GIT_OPT_GET_SEARCH_PATH, GIT_OPT_SET_SEARCH_PATH, - GIT_OPT_SET_CACHE_LIMIT, + GIT_OPT_SET_CACHE_OBJECT_LIMIT, + GIT_OPT_SET_CACHE_MAX_SIZE, GIT_OPT_ENABLE_CACHING }; diff --git a/src/cache.c b/src/cache.c index c51be895e..ca122fb77 100644 --- a/src/cache.c +++ b/src/cache.c @@ -18,6 +18,7 @@ GIT__USE_OIDMAP bool git_cache__enabled = true; +size_t git_cache__max_storage = (4 * 1024 * 1024); static size_t git_cache__max_object_size[8] = { 0, /* GIT_OBJ__EXT1 */ @@ -70,19 +71,25 @@ int git_cache_init(git_cache *cache) return 0; } -void git_cache_clear(git_cache *cache) +/* called with lock */ +static void clear_cache(git_cache *cache) { git_cached_obj *evict = NULL; - if (git_mutex_lock(&cache->lock) < 0) - return; - kh_foreach_value(cache->map, evict, { git_cached_obj_decref(evict); }); kh_clear(oid, cache->map); cache->used_memory = 0; +} + +void git_cache_clear(git_cache *cache) +{ + if (git_mutex_lock(&cache->lock) < 0) + return; + + clear_cache(cache); git_mutex_unlock(&cache->lock); } @@ -95,14 +102,15 @@ void git_cache_free(git_cache *cache) git_mutex_free(&cache->lock); } -/* Call with lock, yo */ -static void cache_evict_entries(git_cache *cache, size_t evict_count) +/* Called with lock */ +static void cache_evict_entries(git_cache *cache) { uint32_t seed = rand(); + size_t evict_count = 8; /* do not infinite loop if there's not enough entries to evict */ if (evict_count > kh_size(cache->map)) { - git_cache_clear(cache); + clear_cache(cache); return; } @@ -163,6 +171,9 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) if (git_mutex_lock(&cache->lock) < 0) return entry; + if (cache->used_memory > git_cache__max_storage) + cache_evict_entries(cache); + pos = kh_get(oid, cache->map, &entry->oid); /* not found */ diff --git a/src/cache.h b/src/cache.h index e95d521fe..1715c7220 100644 --- a/src/cache.h +++ b/src/cache.h @@ -35,6 +35,7 @@ typedef struct { } git_cache; extern bool git_cache__enabled; +extern size_t git_cache__max_storage; int git_cache_set_max_object_size(git_otype type, size_t size); diff --git a/src/util.c b/src/util.c index 1ed5d5d16..c3fc69756 100644 --- a/src/util.c +++ b/src/util.c @@ -95,7 +95,7 @@ int git_libgit2_opts(int key, ...) error = git_futils_dirs_set(error, va_arg(ap, const char *)); break; - case GIT_OPT_SET_CACHE_LIMIT: + case GIT_OPT_SET_CACHE_OBJECT_LIMIT: { git_otype type = (git_otype)va_arg(ap, int); size_t size = va_arg(ap, size_t); @@ -103,6 +103,10 @@ int git_libgit2_opts(int key, ...) break; } + case GIT_OPT_SET_CACHE_MAX_SIZE: + git_cache__max_storage = va_arg(ap, size_t); + break; + case GIT_OPT_ENABLE_CACHING: git_cache__enabled = (va_arg(ap, int) != 0); break; diff --git a/tests-clar/object/cache.c b/tests-clar/object/cache.c index b36bf2726..a3eba8737 100644 --- a/tests-clar/object/cache.c +++ b/tests-clar/object/cache.c @@ -13,7 +13,7 @@ void test_object_cache__cleanup(void) git_repository_free(g_repo); g_repo = NULL; - git_libgit2_opts(GIT_OPT_SET_CACHE_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); } static struct { @@ -54,7 +54,7 @@ void test_object_cache__cache_everything(void) git_odb *odb; git_libgit2_opts( - GIT_OPT_SET_CACHE_LIMIT, (int)GIT_OBJ_BLOB, (size_t)32767); + GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)32767); cl_git_pass(git_repository_odb(&odb, g_repo)); @@ -103,7 +103,7 @@ void test_object_cache__cache_no_blobs(void) git_object *obj; git_odb *odb; - git_libgit2_opts(GIT_OPT_SET_CACHE_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); cl_git_pass(git_repository_odb(&odb, g_repo)); |