]> git.proxmox.com Git - libgit2.git/blob - src/sortedcache.h
Merge pull request #1805 from libgit2/threading-packed-load
[libgit2.git] / src / sortedcache.h
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7 #ifndef INCLUDE_sorted_cache_h__
8 #define INCLUDE_sorted_cache_h__
9
10 #include "util.h"
11 #include "fileops.h"
12 #include "vector.h"
13 #include "thread-utils.h"
14 #include "pool.h"
15 #include "strmap.h"
16
17 /*
18 * The purpose of this data structure is to cache the parsed contents of a
19 * file (a.k.a. the backing file) where each item in the file can be
20 * identified by a key string and you want to both look them up by name
21 * and traverse them in sorted order. Each item is assumed to itself end
22 * in a GIT_FLEX_ARRAY.
23 */
24
25 typedef void (*git_sortedcache_free_item_fn)(void *payload, void *item);
26
27 typedef struct {
28 git_refcount rc;
29 git_rwlock lock;
30 size_t item_path_offset;
31 git_sortedcache_free_item_fn free_item;
32 void *free_item_payload;
33 git_pool pool;
34 git_vector items;
35 git_strmap *map;
36 git_futils_filestamp stamp;
37 char path[GIT_FLEX_ARRAY];
38 } git_sortedcache;
39
40 /* Create a new sortedcache
41 *
42 * Even though every sortedcache stores items with a GIT_FLEX_ARRAY at
43 * the end containing their key string, you have to provide the item_cmp
44 * sorting function because the sorting function doesn't get a payload
45 * and therefore can't know the offset to the item key string. :-(
46 *
47 * @param out The allocated git_sortedcache
48 * @param item_path_offset Offset to the GIT_FLEX_ARRAY item key in the
49 * struct - use offsetof(struct mine, key-field) to get this
50 * @param free_item Optional callback to free each item
51 * @param free_item_payload Optional payload passed to free_item callback
52 * @param item_cmp Compare the keys of two items
53 * @param path The path to the backing store file for this cache; this
54 * may be NULL. The cache makes it easy to load this and check
55 * if it has been modified since the last load and/or write.
56 */
57 int git_sortedcache_new(
58 git_sortedcache **out,
59 size_t item_path_offset, /* use offsetof(struct, path-field) macro */
60 git_sortedcache_free_item_fn free_item,
61 void *free_item_payload,
62 git_vector_cmp item_cmp,
63 const char *path);
64
65 /* Copy a sorted cache
66 *
67 * - `copy_item` can be NULL to just use memcpy
68 * - if `lock`, grabs read lock on `src` during copy and releases after
69 */
70 int git_sortedcache_copy(
71 git_sortedcache **out,
72 git_sortedcache *src,
73 bool lock,
74 int (*copy_item)(void *payload, void *tgt_item, void *src_item),
75 void *payload);
76
77 /* Free sorted cache (first calling `free_item` callbacks)
78 *
79 * Don't call on a locked collection - it may acquire a write lock
80 */
81 void git_sortedcache_free(git_sortedcache *sc);
82
83 /* Increment reference count - balance with call to free */
84 void git_sortedcache_incref(git_sortedcache *sc);
85
86 /* Get the pathname associated with this cache at creation time */
87 const char *git_sortedcache_path(git_sortedcache *sc);
88
89 /*
90 * CACHE WRITE FUNCTIONS
91 *
92 * The following functions require you to have a writer lock to make the
93 * modification. Some of the functions take a `wlock` parameter and
94 * will optionally lock and unlock for you if that is passed as true.
95 *
96 */
97
98 /* Lock sortedcache for write */
99 int git_sortedcache_wlock(git_sortedcache *sc);
100
101 /* Unlock sorted cache when done with write */
102 void git_sortedcache_wunlock(git_sortedcache *sc);
103
104 /* Lock cache and load backing file into a buffer.
105 *
106 * This grabs a write lock on the cache then looks at the modification
107 * time and size of the file on disk.
108 *
109 * If the file appears to have changed, this loads the file contents into
110 * the buffer and returns a positive value leaving the cache locked - the
111 * caller should parse the file content, update the cache as needed, then
112 * release the lock. NOTE: In this case, the caller MUST unlock the cache.
113 *
114 * If the file appears to be unchanged, then this automatically releases
115 * the lock on the cache, clears the buffer, and returns 0.
116 *
117 * @return 0 if up-to-date, 1 if out-of-date, <0 on error
118 */
119 int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf);
120
121 /* Refresh file timestamp after write completes
122 * You should already be holding the write lock when you call this.
123 */
124 void git_sortedcache_updated(git_sortedcache *sc);
125
126 /* Release all items in sorted cache
127 *
128 * If `wlock` is true, grabs write lock and releases when done, otherwise
129 * you should already be holding a write lock when you call this.
130 */
131 int git_sortedcache_clear(git_sortedcache *sc, bool wlock);
132
133 /* Find and/or insert item, returning pointer to item data.
134 * You should already be holding the write lock when you call this.
135 */
136 int git_sortedcache_upsert(
137 void **out, git_sortedcache *sc, const char *key);
138
139 /* Removes entry at pos from cache
140 * You should already be holding the write lock when you call this.
141 */
142 int git_sortedcache_remove(git_sortedcache *sc, size_t pos);
143
144 /*
145 * CACHE READ FUNCTIONS
146 *
147 * The following functions access items in the cache. To prevent the
148 * results from being invalidated before they can be used, you should be
149 * holding either a read lock or a write lock when using these functions.
150 *
151 */
152
153 /* Lock sortedcache for read */
154 int git_sortedcache_rlock(git_sortedcache *sc);
155
156 /* Unlock sorted cache when done with read */
157 void git_sortedcache_runlock(git_sortedcache *sc);
158
159 /* Lookup item by key - returns NULL if not found */
160 void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key);
161
162 /* Get how many items are in the cache
163 *
164 * You can call this function without holding a lock, but be aware
165 * that it may change before you use it.
166 */
167 size_t git_sortedcache_entrycount(const git_sortedcache *sc);
168
169 /* Lookup item by index - returns NULL if out of range */
170 void *git_sortedcache_entry(git_sortedcache *sc, size_t pos);
171
172 /* Lookup index of item by key - returns GIT_ENOTFOUND if not found */
173 int git_sortedcache_lookup_index(
174 size_t *out, git_sortedcache *sc, const char *key);
175
176 #endif