commit - a9bf0c2c43fb5545d5929f63896d06d00281cdd7
commit + 1943de014775b966dbd5307f839f666123bb26f1
blob - 32c6146fa5cf6b5944f483716a79e0969bbc4e4b
blob + df0f4ad3be5ed31bf13f8da8ca88aef61e9c0a7c
--- include/got_object.h
+++ include/got_object.h
char *committer;
struct tm tm_committer; /* UTC */
char *logmsg;
+
+ int refcnt; /* for internal use only */
};
/* A generic object. Used as a handle which holds an ID and an object type. */
blob - fbcf7b53c0bdfe9bb34535846550f44b0c38fbb1
blob + f25073b2d2020fd56df8a7a70de65ce9d55f481c
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
enum got_object_chache_type {
GOT_OBJECT_CACHE_TYPE_OBJ,
- GOT_OBJECT_CACHE_TYPE_TREE
+ GOT_OBJECT_CACHE_TYPE_TREE,
+ GOT_OBJECT_CACHE_TYPE_COMMIT,
};
struct got_object_cache_entry {
union {
struct got_object *obj;
struct got_tree_object *tree;
+ struct got_commit_object *commit;
} data;
};
/* Caches for opened objects. */
struct got_object_cache objcache;
struct got_object_cache treecache;
+ struct got_object_cache commitcache;
};
const struct got_error*got_repo_cache_object(struct got_repository *,
struct got_object_id *, struct got_tree_object *);
struct got_tree_object *got_repo_get_cached_tree(struct got_repository *,
struct got_object_id *);
+const struct got_error*got_repo_cache_commit(struct got_repository *,
+ struct got_object_id *, struct got_commit_object *);
+struct got_commit_object *got_repo_get_cached_commit(struct got_repository *,
+ struct got_object_id *);
blob - 07109c33e693f77141506e564316ba71e746ba5e
blob + 499cfb5cf31ce4b89b028472a453d69fcbafcb54
--- lib/object.c
+++ lib/object.c
struct got_repository *repo, struct got_object *obj)
{
const struct got_error *err = NULL;
+
+ *commit = got_repo_get_cached_commit(repo, &obj->id);
+ if (*commit != NULL) {
+ (*commit)->refcnt++;
+ return NULL;
+ }
if (obj->type != GOT_OBJ_TYPE_COMMIT)
return got_error(GOT_ERR_OBJ_TYPE);
err = read_commit_object_privsep(commit, repo, obj, fd);
close(fd);
}
+
+ if (err == NULL) {
+ (*commit)->refcnt++;
+ err = got_repo_cache_commit(repo, &obj->id, *commit);
+ }
+
return err;
}
got_object_commit_close(struct got_commit_object *commit)
{
struct got_object_qid *qid;
+
+ if (commit->refcnt > 0) {
+ commit->refcnt--;
+ return;
+ }
while (!SIMPLEQ_EMPTY(&commit->parent_ids)) {
qid = SIMPLEQ_FIRST(&commit->parent_ids);
blob - a688bdaa5e2ba19b4cd1972d21e8d8d99c37f0e5
blob + 73293f2c64aea38647a40355fd9003ca7cae5f77
--- lib/repository.c
+++ lib/repository.c
case GOT_OBJECT_CACHE_TYPE_TREE:
got_object_tree_close(ce->data.tree);
break;
+ case GOT_OBJECT_CACHE_TYPE_COMMIT:
+ got_object_commit_close(ce->data.commit);
+ break;
}
free(ce);
}
case GOT_OBJECT_CACHE_TYPE_TREE:
ce->data.tree = (struct got_tree_object *)item;
break;
+ case GOT_OBJECT_CACHE_TYPE_COMMIT:
+ ce->data.commit = (struct got_commit_object *)item;
+ break;
}
err = got_object_idset_add(NULL, cache->set, id, ce);
if (err) {
}
repo->treecache.cache_miss++;
+ return NULL;
+}
+
+const struct got_error *
+got_repo_cache_commit(struct got_repository *repo, struct got_object_id *id,
+ struct got_commit_object *commit)
+{
+ const struct got_error *err = NULL;
+
+ err = cache_add(&repo->commitcache, id, commit);
+ if (err)
+ return err;
+
+ commit->refcnt++;
return NULL;
}
+struct got_commit_object *
+got_repo_get_cached_commit(struct got_repository *repo,
+ struct got_object_id *id)
+{
+ struct got_object_cache_entry *ce;
+ ce = got_object_idset_get(repo->commitcache.set, id);
+ if (ce) {
+ repo->commitcache.cache_hit++;
+ return ce->data.commit;
+ }
+
+ repo->commitcache.cache_miss++;
+ return NULL;
+}
+
const struct got_error *
got_repo_open(struct got_repository **ret, const char *path)
{
}
repo->treecache.type = GOT_OBJECT_CACHE_TYPE_TREE;
+ repo->commitcache.set = got_object_idset_alloc();
+ if (repo->commitcache.set == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ repo->commitcache.type = GOT_OBJECT_CACHE_TYPE_COMMIT;
+
repo->path = got_path_normalize(abspath);
if (repo->path == NULL) {
err = got_error(GOT_ERR_BAD_PATH);
return err;
}
+static void
+print_cache_stats(struct got_object_cache *cache, const char *name)
+{
+#if 0
+ fprintf(stderr, "%s cache: %d elements, %d hits, %d missed\n",
+ name, got_object_idset_num_elements(cache->set), cache->cache_hit,
+ cache->cache_miss);
+#endif
+}
+
void
got_repo_close(struct got_repository *repo)
{
free(repo->path);
free(repo->path_git_dir);
+ print_cache_stats(&repo->objcache, "object");
+ print_cache_stats(&repo->treecache, "tree");
+ print_cache_stats(&repo->commitcache, "commit");
if (repo->objcache.set)
got_object_idset_free(repo->objcache.set);
if (repo->treecache.set)
got_object_idset_free(repo->treecache.set);
+ if (repo->commitcache.set)
+ got_object_idset_free(repo->commitcache.set);
free(repo);
}