Commit 50bc349d7794337cf8810482840482511e013a0d

Stefan Sperling 2018-06-22T09:54:10

implement repository object cache via object_idset

diff --git a/lib/got_lib_repository.h b/lib/got_lib_repository.h
index b6db6c4..969dcdf 100644
--- a/lib/got_lib_repository.h
+++ b/lib/got_lib_repository.h
@@ -35,7 +35,7 @@ struct got_repository {
 	/* Open file handles for pack files. */
 	struct got_pack packs[GOT_PACK_CACHE_SIZE];
 
-	SIMPLEQ_HEAD(, got_objcache_entry) objcache;
+	struct got_object_idset *objcache;
 	int ncached;
 	int cache_hit;
 	int cache_miss;
diff --git a/lib/repository.c b/lib/repository.c
index 4b82bfc..28df53b 100644
--- a/lib/repository.c
+++ b/lib/repository.c
@@ -37,6 +37,7 @@
 #include "got_lib_pack.h"
 #include "got_lib_repository.h"
 #include "got_lib_worktree.h"
+#include "got_lib_object_idset.h"
 
 #ifndef nitems
 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
@@ -148,15 +149,18 @@ done:
 
 }
 
-const struct got_error*
+const struct got_error *
 got_repo_cache_object(struct got_repository *repo, struct got_object_id *id,
     struct got_object *obj)
 {
+	const struct got_error *err = NULL;
 	struct got_objcache_entry *ce;
 
 	if (repo->ncached >= GOT_OBJECT_CACHE_SIZE) {
-		ce = SIMPLEQ_FIRST(&repo->objcache);
-		SIMPLEQ_REMOVE_HEAD(&repo->objcache, entry);
+		err = got_object_idset_remove_random((void **)&ce,
+		    repo->objcache);
+		if (err)
+			return err;
 		got_object_close(ce->obj);
 		free(ce);
 		repo->ncached--;
@@ -167,10 +171,18 @@ got_repo_cache_object(struct got_repository *repo, struct got_object_id *id,
 		return got_error_from_errno();
 	memcpy(&ce->id, id, sizeof(ce->id));
 	ce->obj = obj;
-	obj->refcnt++;
-	SIMPLEQ_INSERT_HEAD(&repo->objcache, ce, entry);
-	repo->ncached++;
-	return NULL;
+	err = got_object_idset_add(NULL, repo->objcache, id, ce);
+	if (err) {
+		if (err->code == GOT_ERR_OBJ_EXISTS) {
+			free(ce);
+			err = NULL;
+		}
+	} else {
+		obj->refcnt++;
+		repo->ncached++;
+	}
+
+	return err;
 }
 
 struct got_object *
@@ -179,9 +191,8 @@ got_repo_get_cached_object(struct got_repository *repo,
 {
 	struct got_objcache_entry *ce;
 
-	SIMPLEQ_FOREACH(ce, &repo->objcache, entry) {
-		if (got_object_id_cmp(&ce->id, id) != 0)
-			continue;
+	ce = got_object_idset_get(repo->objcache, id);
+	if (ce) {
 		repo->cache_hit++;
 		return ce->obj;
 	}
@@ -209,6 +220,12 @@ got_repo_open(struct got_repository **ret, const char *path)
 		goto done;
 	}
 
+	repo->objcache = got_object_idset_alloc();
+	if (repo->objcache == NULL) {
+		err = got_error_from_errno();
+		goto done;
+	}
+
 	repo->path = got_path_normalize(abspath);
 	if (repo->path == NULL) {
 		err = got_error(GOT_ERR_BAD_PATH);
@@ -280,15 +297,9 @@ got_repo_close(struct got_repository *repo)
 		got_pack_close(&repo->packs[i]);
 	}
 
-	while (!SIMPLEQ_EMPTY(&repo->objcache)) {
-		struct got_objcache_entry *ce;
-		ce = SIMPLEQ_FIRST(&repo->objcache);
-		SIMPLEQ_REMOVE_HEAD(&repo->objcache, entry);
-		got_object_close(ce->obj);
-		free(ce);
-	}
-
 	free(repo->path);
 	free(repo->path_git_dir);
+	if (repo->objcache)
+		got_object_idset_free(repo->objcache);
 	free(repo);
 }
diff --git a/regress/idset/idset_test.c b/regress/idset/idset_test.c
index 35a2c48..cc88d70 100644
--- a/regress/idset/idset_test.c
+++ b/regress/idset/idset_test.c
@@ -167,7 +167,7 @@ idset_add_remove_iter(void)
 		goto done;
 	}
 
-	err = got_object_idset_remove(set, &id2);
+	err = got_object_idset_remove(NULL, set, &id2);
 	if (err)
 		goto done;
 	if (got_object_idset_num_elements(set) != 2) {
diff --git a/regress/repository/Makefile b/regress/repository/Makefile
index 18bd527..f8b2b59 100644
--- a/regress/repository/Makefile
+++ b/regress/repository/Makefile
@@ -1,9 +1,9 @@
 .PATH:${.CURDIR}/../../lib
 
 PROG = repository_test
-SRCS = path.c repository.c error.c reference.c object.c opentemp.c \
-	sha1.c diff.c diffreg.c pack.c privsep.c delta.c fileindex.c \
-	worktree.c zbuf.c repository_test.c
+SRCS = path.c repository.c error.c reference.c object.c object_idset.c \
+	opentemp.c sha1.c diff.c diffreg.c pack.c privsep.c delta.c \
+	fileindex.c worktree.c zbuf.c repository_test.c
 
 CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
 LDADD = -lutil -lz
diff --git a/regress/worktree/Makefile b/regress/worktree/Makefile
index bdce9e6..9048749 100644
--- a/regress/worktree/Makefile
+++ b/regress/worktree/Makefile
@@ -1,8 +1,8 @@
 .PATH:${.CURDIR}/../../lib
 
 PROG = worktree_test
-SRCS = worktree.c repository.c object.c opentemp.c path.c error.c \
-	reference.c sha1.c pack.c privsep.c delta.c zbuf.c \
+SRCS = worktree.c repository.c object.c object_idset.c opentemp.c path.c \
+	error.c reference.c sha1.c pack.c privsep.c delta.c zbuf.c \
 	fileindex.c worktree_test.c
 
 CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib