commit - 835e0dbdc83dcd863487243b581bdb1055f50855
commit + 7bb0daa1028563181fe482524973f2a801da9261
blob - 37a0ffc06e205900a148c1e549b6fffdc28b580e
blob + ed4dac1b48bc84f3f2eae84ae0ab8cdfaeee3c59
--- lib/got_lib_object.h
+++ lib/got_lib_object.h
char *path_packfile; /* if packed */
off_t pack_offset; /* if packed */
struct got_delta_chain deltas; /* if deltified */
+ int refcnt; /* > 0 if open and/or cached */
};
struct got_blob_object {
blob - 3a9c223be1d3414bc6e7fb4f23b22fd12686d95d
blob + b6db6c4cf6bcf528729664f7257826ed6a72156c
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
#define GOT_PACKIDX_CACHE_SIZE 64
#define GOT_PACK_CACHE_SIZE GOT_PACKIDX_CACHE_SIZE
+#define GOT_OBJECT_CACHE_SIZE 8192
+
+struct got_objcache_entry {
+ SIMPLEQ_ENTRY(got_objcache_entry) entry;
+ struct got_object_id id;
+ struct got_object *obj;
+};
+
struct got_repository {
char *path;
char *path_git_dir;
/* Open file handles for pack files. */
struct got_pack packs[GOT_PACK_CACHE_SIZE];
+
+ SIMPLEQ_HEAD(, got_objcache_entry) objcache;
+ int ncached;
+ int cache_hit;
+ int cache_miss;
};
+
+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 *);
blob - 92f261b77ad672726166be16ae6a9c236961006e
blob + 7fb951947c95f4ddf2f4abdfc5f7cd461226ea3f
--- lib/object.c
+++ lib/object.c
#include "got_lib_zbuf.h"
#include "got_lib_object.h"
#include "got_lib_privsep.h"
+#include "got_lib_repository.h"
#ifndef MIN
#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
const struct got_error *err = NULL;
char *path;
int fd;
+
+ *obj = got_repo_get_cached_object(repo, id);
+ if (*obj != NULL) {
+ (*obj)->refcnt++;
+ return NULL;
+ }
err = object_path(&path, id, repo);
if (err)
goto done;
memcpy((*obj)->id.sha1, id->sha1, SHA1_DIGEST_LENGTH);
}
+
+ if (err == NULL) {
+ (*obj)->refcnt++;
+ err = got_repo_cache_object(repo, id, *obj);
+ }
done:
free(path);
if (fd != -1)
void
got_object_close(struct got_object *obj)
{
+ if (obj->refcnt > 0) {
+ obj->refcnt--;
+ return;
+ }
+
if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
struct got_delta *delta;
while (!SIMPLEQ_EMPTY(&obj->deltas.entries)) {
}
}
- if (te)
+ if (te) {
err = got_object_open(obj, repo, te->id);
- else
+ if (err)
+ goto done;
+ } else
err = got_error(GOT_ERR_NO_OBJ);
done:
free(s0);
blob - fa438dbb0d40c4058f0a9906b50419ccf3d738b8
blob + bc4db374f5b9d527fbfd2db70ef9d4a4adc82132
--- lib/repository.c
+++ lib/repository.c
#include "got_reference.h"
#include "got_repository.h"
#include "got_worktree.h"
+#include "got_object.h"
#include "got_lib_path.h"
#include "got_lib_delta.h"
}
+const struct got_error*
+got_repo_cache_object(struct got_repository *repo, struct got_object_id *id,
+ struct got_object *obj)
+{
+ struct got_objcache_entry *ce;
+
+ if (repo->ncached >= GOT_OBJECT_CACHE_SIZE) {
+ ce = SIMPLEQ_FIRST(&repo->objcache);
+ SIMPLEQ_REMOVE_HEAD(&repo->objcache, entry);
+ got_object_close(ce->obj);
+ free(ce);
+ repo->ncached--;
+ }
+
+ ce = calloc(1, sizeof(*ce));
+ if (ce == NULL)
+ 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;
+}
+
+struct got_object *
+got_repo_get_cached_object(struct got_repository *repo,
+ struct got_object_id *id)
+{
+ struct got_objcache_entry *ce;
+
+ SIMPLEQ_FOREACH(ce, &repo->objcache, entry) {
+ if (got_object_id_cmp(&ce->id, id) != 0)
+ continue;
+ repo->cache_hit++;
+ return ce->obj;
+ }
+ repo->cache_miss++;
+ return NULL;
+}
+
const struct got_error *
got_repo_open(struct got_repository **ret, const char *path)
{
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);
+ }
+ fprintf(stderr, "repo cache size: %d hit: %d miss: %d\n", repo->ncached, repo->cache_hit, repo->cache_miss);
+
free(repo->path);
free(repo->path_git_dir);
free(repo);