summaryrefslogtreecommitdiff
path: root/src/sortedcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sortedcache.c')
-rw-r--r--src/sortedcache.c380
1 files changed, 0 insertions, 380 deletions
diff --git a/src/sortedcache.c b/src/sortedcache.c
deleted file mode 100644
index ee6363f6d..000000000
--- a/src/sortedcache.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "sortedcache.h"
-
-int git_sortedcache_new(
- git_sortedcache **out,
- size_t item_path_offset,
- git_sortedcache_free_item_fn free_item,
- void *free_item_payload,
- git_vector_cmp item_cmp,
- const char *path)
-{
- git_sortedcache *sc;
- size_t pathlen, alloclen;
-
- pathlen = path ? strlen(path) : 0;
-
- GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_sortedcache), pathlen);
- GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
- sc = git__calloc(1, alloclen);
- GIT_ERROR_CHECK_ALLOC(sc);
-
- if (git_pool_init(&sc->pool, 1) < 0 ||
- git_vector_init(&sc->items, 4, item_cmp) < 0 ||
- git_strmap_new(&sc->map) < 0)
- goto fail;
-
- if (git_rwlock_init(&sc->lock)) {
- git_error_set(GIT_ERROR_OS, "failed to initialize lock");
- goto fail;
- }
-
- sc->item_path_offset = item_path_offset;
- sc->free_item = free_item;
- sc->free_item_payload = free_item_payload;
- GIT_REFCOUNT_INC(sc);
- if (pathlen)
- memcpy(sc->path, path, pathlen);
-
- *out = sc;
- return 0;
-
-fail:
- git_strmap_free(sc->map);
- git_vector_free(&sc->items);
- git_pool_clear(&sc->pool);
- git__free(sc);
- return -1;
-}
-
-void git_sortedcache_incref(git_sortedcache *sc)
-{
- GIT_REFCOUNT_INC(sc);
-}
-
-const char *git_sortedcache_path(git_sortedcache *sc)
-{
- return sc->path;
-}
-
-static void sortedcache_clear(git_sortedcache *sc)
-{
- git_strmap_clear(sc->map);
-
- if (sc->free_item) {
- size_t i;
- void *item;
-
- git_vector_foreach(&sc->items, i, item) {
- sc->free_item(sc->free_item_payload, item);
- }
- }
-
- git_vector_clear(&sc->items);
-
- git_pool_clear(&sc->pool);
-}
-
-static void sortedcache_free(git_sortedcache *sc)
-{
- /* acquire write lock to make sure everyone else is done */
- if (git_sortedcache_wlock(sc) < 0)
- return;
-
- sortedcache_clear(sc);
- git_vector_free(&sc->items);
- git_strmap_free(sc->map);
-
- git_sortedcache_wunlock(sc);
-
- git_rwlock_free(&sc->lock);
- git__free(sc);
-}
-
-void git_sortedcache_free(git_sortedcache *sc)
-{
- if (!sc)
- return;
- GIT_REFCOUNT_DEC(sc, sortedcache_free);
-}
-
-static int sortedcache_copy_item(void *payload, void *tgt_item, void *src_item)
-{
- git_sortedcache *sc = payload;
- /* path will already have been copied by upsert */
- memcpy(tgt_item, src_item, sc->item_path_offset);
- return 0;
-}
-
-/* copy a sorted cache */
-int git_sortedcache_copy(
- git_sortedcache **out,
- git_sortedcache *src,
- bool lock,
- int (*copy_item)(void *payload, void *tgt_item, void *src_item),
- void *payload)
-{
- int error = 0;
- git_sortedcache *tgt;
- size_t i;
- void *src_item, *tgt_item;
-
- /* just use memcpy if no special copy fn is passed in */
- if (!copy_item) {
- copy_item = sortedcache_copy_item;
- payload = src;
- }
-
- if ((error = git_sortedcache_new(
- &tgt, src->item_path_offset,
- src->free_item, src->free_item_payload,
- src->items._cmp, src->path)) < 0)
- return error;
-
- if (lock && git_sortedcache_rlock(src) < 0) {
- git_sortedcache_free(tgt);
- return -1;
- }
-
- git_vector_foreach(&src->items, i, src_item) {
- char *path = ((char *)src_item) + src->item_path_offset;
-
- if ((error = git_sortedcache_upsert(&tgt_item, tgt, path)) < 0 ||
- (error = copy_item(payload, tgt_item, src_item)) < 0)
- break;
- }
-
- if (lock)
- git_sortedcache_runlock(src);
- if (error)
- git_sortedcache_free(tgt);
-
- *out = !error ? tgt : NULL;
-
- return error;
-}
-
-/* lock sortedcache while making modifications */
-int git_sortedcache_wlock(git_sortedcache *sc)
-{
- GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */
-
- if (git_rwlock_wrlock(&sc->lock) < 0) {
- git_error_set(GIT_ERROR_OS, "unable to acquire write lock on cache");
- return -1;
- }
- return 0;
-}
-
-/* unlock sorted cache when done with modifications */
-void git_sortedcache_wunlock(git_sortedcache *sc)
-{
- git_vector_sort(&sc->items);
- git_rwlock_wrunlock(&sc->lock);
-}
-
-/* lock sortedcache for read */
-int git_sortedcache_rlock(git_sortedcache *sc)
-{
- GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */
-
- if (git_rwlock_rdlock(&sc->lock) < 0) {
- git_error_set(GIT_ERROR_OS, "unable to acquire read lock on cache");
- return -1;
- }
- return 0;
-}
-
-/* unlock sorted cache when done reading */
-void git_sortedcache_runlock(git_sortedcache *sc)
-{
- GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */
- git_rwlock_rdunlock(&sc->lock);
-}
-
-/* if the file has changed, lock cache and load file contents into buf;
- * returns <0 on error, >0 if file has not changed
- */
-int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf)
-{
- int error, fd;
- struct stat st;
-
- if ((error = git_sortedcache_wlock(sc)) < 0)
- return error;
-
- if ((error = git_futils_filestamp_check(&sc->stamp, sc->path)) <= 0)
- goto unlock;
-
- if ((fd = git_futils_open_ro(sc->path)) < 0) {
- error = fd;
- goto unlock;
- }
-
- if (p_fstat(fd, &st) < 0) {
- git_error_set(GIT_ERROR_OS, "failed to stat file");
- error = -1;
- (void)p_close(fd);
- goto unlock;
- }
-
- if (!git__is_sizet(st.st_size)) {
- git_error_set(GIT_ERROR_INVALID, "unable to load file larger than size_t");
- error = -1;
- (void)p_close(fd);
- goto unlock;
- }
-
- if (buf)
- error = git_futils_readbuffer_fd(buf, fd, (size_t)st.st_size);
-
- (void)p_close(fd);
-
- if (error < 0)
- goto unlock;
-
- return 1; /* return 1 -> file needs reload and was successfully loaded */
-
-unlock:
- git_sortedcache_wunlock(sc);
- return error;
-}
-
-void git_sortedcache_updated(git_sortedcache *sc)
-{
- /* update filestamp to latest value */
- git_futils_filestamp_check(&sc->stamp, sc->path);
-}
-
-/* release all items in sorted cache */
-int git_sortedcache_clear(git_sortedcache *sc, bool wlock)
-{
- if (wlock && git_sortedcache_wlock(sc) < 0)
- return -1;
-
- sortedcache_clear(sc);
-
- if (wlock)
- git_sortedcache_wunlock(sc);
-
- return 0;
-}
-
-/* find and/or insert item, returning pointer to item data */
-int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key)
-{
- size_t keylen, itemlen;
- int error = 0;
- char *item_key;
- void *item;
-
- if ((item = git_strmap_get(sc->map, key)) != NULL)
- goto done;
-
- keylen = strlen(key);
- itemlen = sc->item_path_offset + keylen + 1;
- itemlen = (itemlen + 7) & ~7;
-
- if ((item = git_pool_mallocz(&sc->pool, itemlen)) == NULL) {
- /* don't use GIT_ERROR_CHECK_ALLOC b/c of lock */
- error = -1;
- goto done;
- }
-
- /* one strange thing is that even if the vector or hash table insert
- * fail, there is no way to free the pool item so we just abandon it
- */
-
- item_key = ((char *)item) + sc->item_path_offset;
- memcpy(item_key, key, keylen);
-
- if ((error = git_strmap_set(sc->map, item_key, item)) < 0)
- goto done;
-
- if ((error = git_vector_insert(&sc->items, item)) < 0)
- git_strmap_delete(sc->map, item_key);
-
-done:
- if (out)
- *out = !error ? item : NULL;
- return error;
-}
-
-/* lookup item by key */
-void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key)
-{
- return git_strmap_get(sc->map, key);
-}
-
-/* find out how many items are in the cache */
-size_t git_sortedcache_entrycount(const git_sortedcache *sc)
-{
- return git_vector_length(&sc->items);
-}
-
-/* lookup item by index */
-void *git_sortedcache_entry(git_sortedcache *sc, size_t pos)
-{
- /* make sure the items are sorted so this gets the correct item */
- if (!git_vector_is_sorted(&sc->items))
- git_vector_sort(&sc->items);
-
- return git_vector_get(&sc->items, pos);
-}
-
-/* helper struct so bsearch callback can know offset + key value for cmp */
-struct sortedcache_magic_key {
- size_t offset;
- const char *key;
-};
-
-static int sortedcache_magic_cmp(const void *key, const void *value)
-{
- const struct sortedcache_magic_key *magic = key;
- const char *value_key = ((const char *)value) + magic->offset;
- return strcmp(magic->key, value_key);
-}
-
-/* lookup index of item by key */
-int git_sortedcache_lookup_index(
- size_t *out, git_sortedcache *sc, const char *key)
-{
- struct sortedcache_magic_key magic;
-
- magic.offset = sc->item_path_offset;
- magic.key = key;
-
- return git_vector_bsearch2(out, &sc->items, sortedcache_magic_cmp, &magic);
-}
-
-/* remove entry from cache */
-int git_sortedcache_remove(git_sortedcache *sc, size_t pos)
-{
- char *item;
-
- /*
- * Because of pool allocation, this can't actually remove the item,
- * but we can remove it from the items vector and the hash table.
- */
-
- if ((item = git_vector_get(&sc->items, pos)) == NULL) {
- git_error_set(GIT_ERROR_INVALID, "removing item out of range");
- return GIT_ENOTFOUND;
- }
-
- (void)git_vector_remove(&sc->items, pos);
-
- git_strmap_delete(sc->map, item + sc->item_path_offset);
-
- if (sc->free_item)
- sc->free_item(sc->free_item_payload, item);
-
- return 0;
-}
-