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