]> git.proxmox.com Git - libgit2.git/blame - src/cache.c
Merge pull request #600 from nulltoken/fix/windows-network-paths
[libgit2.git] / src / cache.c
CommitLineData
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 14int 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
42void 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
54void *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 75void *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}