Blame src/sortedcache.h

Packit ae9e2a
/*
Packit ae9e2a
 * Copyright (C) the libgit2 contributors. All rights reserved.
Packit ae9e2a
 *
Packit ae9e2a
 * This file is part of libgit2, distributed under the GNU GPL v2 with
Packit ae9e2a
 * a Linking Exception. For full terms see the included COPYING file.
Packit ae9e2a
 */
Packit ae9e2a
#ifndef INCLUDE_sorted_cache_h__
Packit ae9e2a
#define INCLUDE_sorted_cache_h__
Packit ae9e2a
Packit ae9e2a
#include "util.h"
Packit ae9e2a
#include "fileops.h"
Packit ae9e2a
#include "vector.h"
Packit ae9e2a
#include "thread-utils.h"
Packit ae9e2a
#include "pool.h"
Packit ae9e2a
#include "strmap.h"
Packit ae9e2a
Packit ae9e2a
#include <stddef.h>
Packit ae9e2a
Packit ae9e2a
/*
Packit ae9e2a
 * The purpose of this data structure is to cache the parsed contents of a
Packit ae9e2a
 * file (a.k.a. the backing file) where each item in the file can be
Packit ae9e2a
 * identified by a key string and you want to both look them up by name
Packit ae9e2a
 * and traverse them in sorted order.  Each item is assumed to itself end
Packit ae9e2a
 * in a GIT_FLEX_ARRAY.
Packit ae9e2a
 */
Packit ae9e2a
Packit ae9e2a
typedef void (*git_sortedcache_free_item_fn)(void *payload, void *item);
Packit ae9e2a
Packit ae9e2a
typedef struct {
Packit ae9e2a
	git_refcount rc;
Packit ae9e2a
	git_rwlock   lock;
Packit ae9e2a
	size_t       item_path_offset;
Packit ae9e2a
	git_sortedcache_free_item_fn free_item;
Packit ae9e2a
	void         *free_item_payload;
Packit ae9e2a
	git_pool     pool;
Packit ae9e2a
	git_vector   items;
Packit ae9e2a
	git_strmap   *map;
Packit ae9e2a
	git_futils_filestamp stamp;
Packit ae9e2a
	char         path[GIT_FLEX_ARRAY];
Packit ae9e2a
} git_sortedcache;
Packit ae9e2a
Packit ae9e2a
/* Create a new sortedcache
Packit ae9e2a
 *
Packit ae9e2a
 * Even though every sortedcache stores items with a GIT_FLEX_ARRAY at
Packit ae9e2a
 * the end containing their key string, you have to provide the item_cmp
Packit ae9e2a
 * sorting function because the sorting function doesn't get a payload
Packit ae9e2a
 * and therefore can't know the offset to the item key string. :-(
Packit ae9e2a
 *
Packit ae9e2a
 * @param out The allocated git_sortedcache
Packit ae9e2a
 * @param item_path_offset Offset to the GIT_FLEX_ARRAY item key in the
Packit ae9e2a
 *        struct - use offsetof(struct mine, key-field) to get this
Packit ae9e2a
 * @param free_item Optional callback to free each item
Packit ae9e2a
 * @param free_item_payload Optional payload passed to free_item callback
Packit ae9e2a
 * @param item_cmp Compare the keys of two items
Packit ae9e2a
 * @param path The path to the backing store file for this cache; this
Packit ae9e2a
 *        may be NULL.  The cache makes it easy to load this and check
Packit ae9e2a
 *        if it has been modified since the last load and/or write.
Packit ae9e2a
 */
Packit ae9e2a
int git_sortedcache_new(
Packit ae9e2a
	git_sortedcache **out,
Packit ae9e2a
	size_t item_path_offset, /* use offsetof(struct, path-field) macro */
Packit ae9e2a
	git_sortedcache_free_item_fn free_item,
Packit ae9e2a
	void *free_item_payload,
Packit ae9e2a
	git_vector_cmp item_cmp,
Packit ae9e2a
	const char *path);
Packit ae9e2a
Packit ae9e2a
/* Copy a sorted cache
Packit ae9e2a
 *
Packit ae9e2a
 * - `copy_item` can be NULL to just use memcpy
Packit ae9e2a
 * - if `lock`, grabs read lock on `src` during copy and releases after
Packit ae9e2a
 */
Packit ae9e2a
int git_sortedcache_copy(
Packit ae9e2a
	git_sortedcache **out,
Packit ae9e2a
	git_sortedcache *src,
Packit ae9e2a
	bool lock,
Packit ae9e2a
	int (*copy_item)(void *payload, void *tgt_item, void *src_item),
Packit ae9e2a
	void *payload);
Packit ae9e2a
Packit ae9e2a
/* Free sorted cache (first calling `free_item` callbacks)
Packit ae9e2a
 *
Packit ae9e2a
 * Don't call on a locked collection - it may acquire a write lock
Packit ae9e2a
 */
Packit ae9e2a
void git_sortedcache_free(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Increment reference count - balance with call to free */
Packit ae9e2a
void git_sortedcache_incref(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Get the pathname associated with this cache at creation time */
Packit ae9e2a
const char *git_sortedcache_path(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/*
Packit ae9e2a
 * CACHE WRITE FUNCTIONS
Packit ae9e2a
 *
Packit ae9e2a
 * The following functions require you to have a writer lock to make the
Packit ae9e2a
 * modification.  Some of the functions take a `wlock` parameter and
Packit ae9e2a
 * will optionally lock and unlock for you if that is passed as true.
Packit ae9e2a
 *
Packit ae9e2a
 */
Packit ae9e2a
Packit ae9e2a
/* Lock sortedcache for write */
Packit ae9e2a
int git_sortedcache_wlock(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Unlock sorted cache when done with write */
Packit ae9e2a
void git_sortedcache_wunlock(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Lock cache and load backing file into a buffer.
Packit ae9e2a
 *
Packit ae9e2a
 * This grabs a write lock on the cache then looks at the modification
Packit ae9e2a
 * time and size of the file on disk.
Packit ae9e2a
 *
Packit ae9e2a
 * If the file appears to have changed, this loads the file contents into
Packit ae9e2a
 * the buffer and returns a positive value leaving the cache locked - the
Packit ae9e2a
 * caller should parse the file content, update the cache as needed, then
Packit ae9e2a
 * release the lock.  NOTE: In this case, the caller MUST unlock the cache.
Packit ae9e2a
 *
Packit ae9e2a
 * If the file appears to be unchanged, then this automatically releases
Packit ae9e2a
 * the lock on the cache, clears the buffer, and returns 0.
Packit ae9e2a
 *
Packit ae9e2a
 * @return 0 if up-to-date, 1 if out-of-date, <0 on error
Packit ae9e2a
 */
Packit ae9e2a
int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf);
Packit ae9e2a
Packit ae9e2a
/* Refresh file timestamp after write completes
Packit ae9e2a
 * You should already be holding the write lock when you call this.
Packit ae9e2a
 */
Packit ae9e2a
void git_sortedcache_updated(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Release all items in sorted cache
Packit ae9e2a
 *
Packit ae9e2a
 * If `wlock` is true, grabs write lock and releases when done, otherwise
Packit ae9e2a
 * you should already be holding a write lock when you call this.
Packit ae9e2a
 */
Packit ae9e2a
int git_sortedcache_clear(git_sortedcache *sc, bool wlock);
Packit ae9e2a
Packit ae9e2a
/* Find and/or insert item, returning pointer to item data.
Packit ae9e2a
 * You should already be holding the write lock when you call this.
Packit ae9e2a
 */
Packit ae9e2a
int git_sortedcache_upsert(
Packit ae9e2a
	void **out, git_sortedcache *sc, const char *key);
Packit ae9e2a
Packit ae9e2a
/* Removes entry at pos from cache
Packit ae9e2a
 * You should already be holding the write lock when you call this.
Packit ae9e2a
 */
Packit ae9e2a
int git_sortedcache_remove(git_sortedcache *sc, size_t pos);
Packit ae9e2a
Packit ae9e2a
/*
Packit ae9e2a
 * CACHE READ FUNCTIONS
Packit ae9e2a
 *
Packit ae9e2a
 * The following functions access items in the cache.  To prevent the
Packit ae9e2a
 * results from being invalidated before they can be used, you should be
Packit ae9e2a
 * holding either a read lock or a write lock when using these functions.
Packit ae9e2a
 *
Packit ae9e2a
 */
Packit ae9e2a
Packit ae9e2a
/* Lock sortedcache for read */
Packit ae9e2a
int git_sortedcache_rlock(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Unlock sorted cache when done with read */
Packit ae9e2a
void git_sortedcache_runlock(git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Lookup item by key - returns NULL if not found */
Packit ae9e2a
void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key);
Packit ae9e2a
Packit ae9e2a
/* Get how many items are in the cache
Packit ae9e2a
 *
Packit ae9e2a
 * You can call this function without holding a lock, but be aware
Packit ae9e2a
 * that it may change before you use it.
Packit ae9e2a
 */
Packit ae9e2a
size_t git_sortedcache_entrycount(const git_sortedcache *sc);
Packit ae9e2a
Packit ae9e2a
/* Lookup item by index - returns NULL if out of range */
Packit ae9e2a
void *git_sortedcache_entry(git_sortedcache *sc, size_t pos);
Packit ae9e2a
Packit ae9e2a
/* Lookup index of item by key - returns GIT_ENOTFOUND if not found */
Packit ae9e2a
int git_sortedcache_lookup_index(
Packit ae9e2a
	size_t *out, git_sortedcache *sc, const char *key);
Packit ae9e2a
Packit ae9e2a
#endif