Commit f5e28202cb8d73a444e5a5664420fbe5bec11119

Michael Schubert 2013-03-25T13:38:43

opts: allow configuration of odb cache size Currently, the odb cache has a fixed size of 128 slots as defined by GIT_DEFAULT_CACHE_SIZE. Allow users to set the size of the cache via git_libgit2_opts(). Fixes #1035.

diff --git a/include/git2/common.h b/include/git2/common.h
index b8c3e42..5318e66 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -131,6 +131,8 @@ enum {
 	GIT_OPT_SET_MWINDOW_MAPPED_LIMIT,
 	GIT_OPT_GET_SEARCH_PATH,
 	GIT_OPT_SET_SEARCH_PATH,
+	GIT_OPT_GET_ODB_CACHE_SIZE,
+	GIT_OPT_SET_ODB_CACHE_SIZE,
 };
 
 /**
@@ -167,6 +169,15 @@ enum {
  *		- `level` must be GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_GLOBAL,
  *		  or GIT_CONFIG_LEVEL_XDG.
  *
+ *	opts(GIT_OPT_GET_ODB_CACHE_SIZE):
+ *		Get the size of the libgit2 odb cache.
+ *
+ *	opts(GIT_OPT_SET_ODB_CACHE_SIZE):
+ *		Set the size of the of the libgit2 odb cache. This needs
+ *		to be done before git_repository_open is called, since
+ *		git_repository_open initializes the odb layer. Defaults
+ *		to 128.
+ *
  * @param option Option key
  * @param ... value to set the option
  * @return 0 on success, <0 on failure
diff --git a/src/odb.c b/src/odb.c
index 5a0d887..c98df24 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -32,6 +32,8 @@ typedef struct
 	int is_alternate;
 } backend_internal;
 
+size_t git_odb__cache_size = GIT_DEFAULT_CACHE_SIZE;
+
 static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
 
 int git_odb__format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type)
@@ -351,7 +353,7 @@ int git_odb_new(git_odb **out)
 	git_odb *db = git__calloc(1, sizeof(*db));
 	GITERR_CHECK_ALLOC(db);
 
-	if (git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object) < 0 ||
+	if (git_cache_init(&db->cache, git_odb__cache_size, &free_odb_object) < 0 ||
 		git_vector_init(&db->backends, 4, backend_sort_cmp) < 0)
 	{
 		git__free(db);
diff --git a/src/util.c b/src/util.c
index f5b4a1d..44ac1af 100644
--- a/src/util.c
+++ b/src/util.c
@@ -38,6 +38,7 @@ int git_libgit2_capabilities()
 /* Declarations for tuneable settings */
 extern size_t git_mwindow__window_size;
 extern size_t git_mwindow__mapped_limit;
+extern size_t git_odb__cache_size;
 
 static int config_level_to_futils_dir(int config_level)
 {
@@ -92,6 +93,14 @@ int git_libgit2_opts(int key, ...)
 		if ((error = config_level_to_futils_dir(va_arg(ap, int))) >= 0)
 			error = git_futils_dirs_set(error, va_arg(ap, const char *));
 		break;
+
+	case GIT_OPT_GET_ODB_CACHE_SIZE:
+		*(va_arg(ap, size_t *)) = git_odb__cache_size;
+		break;
+
+	case GIT_OPT_SET_ODB_CACHE_SIZE:
+		git_odb__cache_size = va_arg(ap, size_t);
+		break;
 	}
 
 	va_end(ap);
diff --git a/tests-clar/core/opts.c b/tests-clar/core/opts.c
index 6468b35..907339d 100644
--- a/tests-clar/core/opts.c
+++ b/tests-clar/core/opts.c
@@ -1,4 +1,5 @@
 #include "clar_libgit2.h"
+#include "cache.h"
 
 void test_core_opts__readwrite(void)
 {
@@ -15,4 +16,15 @@ void test_core_opts__readwrite(void)
 	git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &new_val);
 
 	cl_assert(new_val == old_val);
+
+	git_libgit2_opts(GIT_OPT_GET_ODB_CACHE_SIZE, &old_val);
+
+	cl_assert(old_val == GIT_DEFAULT_CACHE_SIZE);
+
+	git_libgit2_opts(GIT_OPT_SET_ODB_CACHE_SIZE, (size_t)GIT_DEFAULT_CACHE_SIZE*2);
+	git_libgit2_opts(GIT_OPT_GET_ODB_CACHE_SIZE, &new_val);
+
+	cl_assert(new_val == (GIT_DEFAULT_CACHE_SIZE*2));
+
+	git_libgit2_opts(GIT_OPT_GET_ODB_CACHE_SIZE, &old_val);
 }