commit - 54f20211c589e3522ed62f05814143d5450a49a7
commit + f6be5c308af39aaf5dd86f08ed270f009ba12ed8
blob - 9268ff826f30da37420b9969e0b0283db36d0455
blob + 32c6146fa5cf6b5944f483716a79e0969bbc4e4b
--- include/got_object.h
+++ include/got_object.h
struct got_tree_object {
int nentries;
SIMPLEQ_HEAD(, got_tree_entry) entries;
+
+ int refcnt; /* for internal use only */
};
struct got_object_qid {
blob - db2876225fd8367257df47e56a7a1744ac8632b5
blob + 4eb219f9241f6980f82035f28f5128cab0f988c5
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
#define GOT_OBJECT_CACHE_SIZE 8192
+enum got_object_chache_type {
+ GOT_OBJECT_CACHE_TYPE_OBJ,
+ GOT_OBJECT_CACHE_TYPE_TREE
+};
+
struct got_object_cache_entry {
struct got_object_id id;
- struct got_object *obj;
+ union {
+ struct got_object *obj;
+ struct got_tree_object *tree;
+ } data;
};
struct got_object_cache {
+ enum got_object_chache_type type;
struct got_object_idset *set;
int ncached;
int cache_hit;
/* Open file handles for pack files. */
struct got_pack packs[GOT_PACK_CACHE_SIZE];
+ /* Caches for opened objects. */
struct got_object_cache objcache;
+ struct got_object_cache treecache;
};
-const struct got_error*
-got_repo_cache_object(struct got_repository *, struct got_object_id *,
- struct got_object *);
+const struct got_error*got_repo_cache_object(struct got_repository *,
+ struct got_object_id *, struct got_object *);
struct got_object *got_repo_get_cached_object(struct got_repository *,
struct got_object_id *);
+const struct got_error*got_repo_cache_tree(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 *);
blob - 7fb951947c95f4ddf2f4abdfc5f7cd461226ea3f
blob + 07109c33e693f77141506e564316ba71e746ba5e
--- lib/object.c
+++ lib/object.c
struct got_repository *repo, struct got_object *obj)
{
const struct got_error *err = NULL;
+
+ *tree = got_repo_get_cached_tree(repo, &obj->id);
+ if (*tree != NULL) {
+ (*tree)->refcnt++;
+ return NULL;
+ }
if (obj->type != GOT_OBJ_TYPE_TREE)
return got_error(GOT_ERR_OBJ_TYPE);
err = read_tree_object_privsep(tree, obj, fd);
close(fd);
}
+
+ if (err == NULL) {
+ (*tree)->refcnt++;
+ err = got_repo_cache_tree(repo, &obj->id, *tree);
+ }
+
return err;
}
got_object_tree_close(struct got_tree_object *tree)
{
struct got_tree_entry *te;
+
+ if (tree->refcnt > 0) {
+ tree->refcnt--;
+ return;
+ }
while (!SIMPLEQ_EMPTY(&tree->entries)) {
te = SIMPLEQ_FIRST(&tree->entries);
blob - 9a2fb62cf1d7a941a30ddef9c72e45717d09a5e6
blob + 5900746421a52c01d51c4bbf365e42cce22e01f2
--- lib/repository.c
+++ lib/repository.c
}
-const struct got_error *
-got_repo_cache_object(struct got_repository *repo, struct got_object_id *id,
- struct got_object *obj)
+static const struct got_error *
+cache_add(struct got_object_cache *cache, struct got_object_id *id, void *item)
{
const struct got_error *err = NULL;
struct got_object_cache_entry *ce;
- if (repo->objcache.ncached >= GOT_OBJECT_CACHE_SIZE) {
+ if (cache->ncached >= GOT_OBJECT_CACHE_SIZE) {
err = got_object_idset_remove_random((void **)&ce,
- repo->objcache.set);
+ cache->set);
if (err)
return err;
- got_object_close(ce->obj);
+ switch (cache->type) {
+ case GOT_OBJECT_CACHE_TYPE_OBJ:
+ got_object_close(ce->data.obj);
+ break;
+ case GOT_OBJECT_CACHE_TYPE_TREE:
+ got_object_tree_close(ce->data.tree);
+ break;
+ }
free(ce);
- repo->objcache.ncached--;
+ cache->ncached--;
}
ce = calloc(1, sizeof(*ce));
if (ce == NULL)
return got_error_from_errno();
memcpy(&ce->id, id, sizeof(ce->id));
- ce->obj = obj;
- err = got_object_idset_add(NULL, repo->objcache.set, id, ce);
+ switch (cache->type) {
+ case GOT_OBJECT_CACHE_TYPE_OBJ:
+ ce->data.obj = (struct got_object *)item;
+ break;
+ case GOT_OBJECT_CACHE_TYPE_TREE:
+ ce->data.tree = (struct got_tree_object *)item;
+ break;
+ }
+ err = got_object_idset_add(NULL, cache->set, id, ce);
if (err) {
if (err->code == GOT_ERR_OBJ_EXISTS) {
free(ce);
err = NULL;
}
- } else {
- obj->refcnt++;
- repo->objcache.ncached++;
- }
+ } else
+ cache->ncached++;
return err;
}
+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;
+
+ err = cache_add(&repo->objcache, id, obj);
+ if (err)
+ return err;
+
+ obj->refcnt++;
+ return NULL;
+}
+
struct got_object *
got_repo_get_cached_object(struct got_repository *repo,
struct got_object_id *id)
ce = got_object_idset_get(repo->objcache.set, id);
if (ce) {
repo->objcache.cache_hit++;
- return ce->obj;
+ return ce->data.obj;
}
+
repo->objcache.cache_miss++;
return NULL;
}
const struct got_error *
+got_repo_cache_tree(struct got_repository *repo, struct got_object_id *id,
+ struct got_tree_object *tree)
+{
+ const struct got_error *err = NULL;
+
+ err = cache_add(&repo->treecache, id, tree);
+ if (err)
+ return err;
+
+ tree->refcnt++;
+ return NULL;
+}
+
+struct got_tree_object *
+got_repo_get_cached_tree(struct got_repository *repo,
+ struct got_object_id *id)
+{
+ struct got_object_cache_entry *ce;
+
+ ce = got_object_idset_get(repo->treecache.set, id);
+ if (ce) {
+ repo->treecache.cache_hit++;
+ return ce->data.tree;
+ }
+
+ repo->treecache.cache_miss++;
+ return NULL;
+}
+
+
+const struct got_error *
got_repo_open(struct got_repository **ret, const char *path)
{
struct got_repository *repo = NULL;
err = got_error_from_errno();
goto done;
}
+ repo->objcache.type = GOT_OBJECT_CACHE_TYPE_OBJ;
+ repo->treecache.set = got_object_idset_alloc();
+ if (repo->treecache.set == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ repo->treecache.type = GOT_OBJECT_CACHE_TYPE_TREE;
+
repo->path = got_path_normalize(abspath);
if (repo->path == NULL) {
err = got_error(GOT_ERR_BAD_PATH);
free(repo->path_git_dir);
if (repo->objcache.set)
got_object_idset_free(repo->objcache.set);
+ if (repo->treecache.set)
+ got_object_idset_free(repo->treecache.set);
free(repo);
}