]> git.proxmox.com Git - libgit2.git/blob - src/cache.c
Cleanup legal data
[libgit2.git] / src / cache.c
1 /*
2 * Copyright (C) 2009-2011 the libgit2 contributors
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
8 #include "common.h"
9 #include "repository.h"
10 #include "commit.h"
11 #include "thread-utils.h"
12 #include "cache.h"
13
14 int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
15 {
16 size_t i;
17
18 if (size < 8)
19 size = 8;
20
21 /* round up size to closest power of 2 */
22 size--;
23 size |= size >> 1;
24 size |= size >> 2;
25 size |= size >> 4;
26 size |= size >> 8;
27 size |= size >> 16;
28
29 cache->size_mask = size;
30 cache->lru_count = 0;
31 cache->free_obj = free_ptr;
32
33 cache->nodes = git__malloc((size + 1) * sizeof(cache_node));
34 if (cache->nodes == NULL)
35 return GIT_ENOMEM;
36
37 for (i = 0; i < (size + 1); ++i) {
38 git_mutex_init(&cache->nodes[i].lock);
39 cache->nodes[i].ptr = NULL;
40 }
41
42 return GIT_SUCCESS;
43 }
44
45 void git_cache_free(git_cache *cache)
46 {
47 size_t i;
48
49 for (i = 0; i < (cache->size_mask + 1); ++i) {
50 if (cache->nodes[i].ptr)
51 git_cached_obj_decref(cache->nodes[i].ptr, cache->free_obj);
52
53 git_mutex_free(&cache->nodes[i].lock);
54 }
55
56 free(cache->nodes);
57 }
58
59 void *git_cache_get(git_cache *cache, const git_oid *oid)
60 {
61 const uint32_t *hash;
62 cache_node *node = NULL;
63 void *result = NULL;
64
65 hash = (const uint32_t *)oid->id;
66 node = &cache->nodes[hash[0] & cache->size_mask];
67
68 git_mutex_lock(&node->lock);
69 {
70 if (node->ptr && git_cached_obj_compare(node->ptr, oid) == 0) {
71 git_cached_obj_incref(node->ptr);
72 result = node->ptr;
73 }
74 }
75 git_mutex_unlock(&node->lock);
76
77 return result;
78 }
79
80 void *git_cache_try_store(git_cache *cache, void *entry)
81 {
82 const uint32_t *hash;
83 const git_oid *oid;
84 cache_node *node = NULL;
85
86 oid = &((git_cached_obj*)entry)->oid;
87 hash = (const uint32_t *)oid->id;
88 node = &cache->nodes[hash[0] & cache->size_mask];
89
90 /* increase the refcount on this object, because
91 * the cache now owns it */
92 git_cached_obj_incref(entry);
93 git_mutex_lock(&node->lock);
94
95 if (node->ptr == NULL) {
96 node->ptr = entry;
97 } else if (git_cached_obj_compare(node->ptr, oid) == 0) {
98 git_cached_obj_decref(entry, cache->free_obj);
99 entry = node->ptr;
100 } else {
101 git_cached_obj_decref(node->ptr, cache->free_obj);
102 node->ptr = entry;
103 }
104
105 /* increase the refcount again, because we are
106 * returning it to the user */
107 git_cached_obj_incref(entry);
108 git_mutex_unlock(&node->lock);
109
110 return entry;
111 }