Skip to content

Commit 9694ef2

Browse files
committed
oidmap: introduce high-level getter for values
The current way of looking up an entry from a map is tightly coupled with the map implementation, as one first has to look up the index of the key and then retrieve the associated value by using the index. As a caller, you usually do not care about any indices at all, though, so this is more complicated than really necessary. Furthermore, it invites for errors to happen if the correct error checking sequence is not being followed. Introduce a new high-level function `git_oidmap_get` that takes a map and a key and returns a pointer to the associated value if such a key exists. Otherwise, a `NULL` pointer is returned. Adjust all callers that can trivially be converted.
1 parent 0355583 commit 9694ef2

File tree

10 files changed

+123
-62
lines changed

10 files changed

+123
-62
lines changed

src/cache.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,12 @@ static bool cache_should_store(git_object_t object_type, size_t object_size)
151151

152152
static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
153153
{
154-
size_t pos;
155-
git_cached_obj *entry = NULL;
154+
git_cached_obj *entry;
156155

157156
if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0)
158157
return NULL;
159158

160-
pos = git_oidmap_lookup_index(cache->map, oid);
161-
if (git_oidmap_valid_index(cache->map, pos)) {
162-
entry = git_oidmap_value_at(cache->map, pos);
163-
159+
if ((entry = git_oidmap_get(cache->map, oid)) != NULL) {
164160
if (flags && entry->flags != flags) {
165161
entry = NULL;
166162
} else {
@@ -175,7 +171,7 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags)
175171

176172
static void *cache_store(git_cache *cache, git_cached_obj *entry)
177173
{
178-
size_t pos;
174+
git_cached_obj *stored_entry;
179175

180176
git_cached_obj_incref(entry);
181177

@@ -194,10 +190,8 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
194190
if (git_cache__current_storage.val > git_cache__max_storage)
195191
cache_evict_entries(cache);
196192

197-
pos = git_oidmap_lookup_index(cache->map, &entry->oid);
198-
199193
/* not found */
200-
if (!git_oidmap_valid_index(cache->map, pos)) {
194+
if ((stored_entry = git_oidmap_get(cache->map, &entry->oid)) == NULL) {
201195
int rval;
202196

203197
git_oidmap_insert(cache->map, &entry->oid, entry, &rval);
@@ -209,19 +203,18 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
209203
}
210204
/* found */
211205
else {
212-
git_cached_obj *stored_entry = git_oidmap_value_at(cache->map, pos);
213-
214206
if (stored_entry->flags == entry->flags) {
215207
git_cached_obj_decref(entry);
216208
git_cached_obj_incref(stored_entry);
217209
entry = stored_entry;
218210
} else if (stored_entry->flags == GIT_CACHE_STORE_RAW &&
219-
entry->flags == GIT_CACHE_STORE_PARSED) {
211+
entry->flags == GIT_CACHE_STORE_PARSED) {
212+
int rval;
213+
220214
git_cached_obj_decref(stored_entry);
221215
git_cached_obj_incref(entry);
222216

223-
git_oidmap_set_key_at(cache->map, pos, &entry->oid);
224-
git_oidmap_set_value_at(cache->map, pos, entry);
217+
git_oidmap_insert(cache->map, &entry->oid, entry, &rval);
225218
} else {
226219
/* NO OP */
227220
}

src/describe.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,7 @@ struct commit_name {
3636

3737
static void *oidmap_value_bykey(git_oidmap *map, const git_oid *key)
3838
{
39-
size_t pos = git_oidmap_lookup_index(map, key);
40-
41-
if (!git_oidmap_valid_index(map, pos))
42-
return NULL;
43-
44-
return git_oidmap_value_at(map, pos);
39+
return git_oidmap_get(map, key);
4540
}
4641

4742
static struct commit_name *find_commit_name(

src/merge.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,14 +1104,13 @@ static void deletes_by_oid_free(git_oidmap *map) {
11041104
git_oidmap_free(map);
11051105
}
11061106

1107-
static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx) {
1108-
size_t pos;
1107+
static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx)
1108+
{
11091109
deletes_by_oid_queue *queue;
11101110
size_t *array_entry;
11111111
int error;
11121112

1113-
pos = git_oidmap_lookup_index(map, id);
1114-
if (!git_oidmap_valid_index(map, pos)) {
1113+
if ((queue = git_oidmap_get(map, id)) == NULL) {
11151114
queue = git_pool_malloc(pool, sizeof(deletes_by_oid_queue));
11161115
GIT_ERROR_CHECK_ALLOC(queue);
11171116

@@ -1123,7 +1122,6 @@ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid
11231122
if (error < 0)
11241123
return -1;
11251124
} else {
1126-
queue = git_oidmap_value_at(map, pos);
11271125
array_entry = git_array_alloc(queue->arr);
11281126
GIT_ERROR_CHECK_ALLOC(array_entry);
11291127
*array_entry = idx;
@@ -1132,18 +1130,14 @@ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid
11321130
return 0;
11331131
}
11341132

1135-
static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id) {
1136-
size_t pos;
1133+
static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id)
1134+
{
11371135
deletes_by_oid_queue *queue;
11381136
size_t *array_entry;
11391137

1140-
pos = git_oidmap_lookup_index(map, id);
1141-
1142-
if (!git_oidmap_valid_index(map, pos))
1138+
if ((queue = git_oidmap_get(map, id)) == NULL)
11431139
return GIT_ENOTFOUND;
11441140

1145-
queue = git_oidmap_value_at(map, pos);
1146-
11471141
if (queue->next_pos == 0) {
11481142
*idx = queue->first_entry;
11491143
} else {

src/odb_mempack.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,11 @@ static int impl__exists(git_odb_backend *backend, const git_oid *oid)
7979
static int impl__read(void **buffer_p, size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
8080
{
8181
struct memory_packer_db *db = (struct memory_packer_db *)backend;
82-
struct memobject *obj = NULL;
83-
size_t pos;
82+
struct memobject *obj;
8483

85-
pos = git_oidmap_lookup_index(db->objects, oid);
86-
if (!git_oidmap_valid_index(db->objects, pos))
84+
if ((obj = git_oidmap_get(db->objects, oid)) == NULL)
8785
return GIT_ENOTFOUND;
8886

89-
obj = git_oidmap_value_at(db->objects, pos);
90-
9187
*len_p = obj->len;
9288
*type_p = obj->type;
9389
*buffer_p = git__malloc(obj->len);
@@ -100,15 +96,11 @@ static int impl__read(void **buffer_p, size_t *len_p, git_object_t *type_p, git_
10096
static int impl__read_header(size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
10197
{
10298
struct memory_packer_db *db = (struct memory_packer_db *)backend;
103-
struct memobject *obj = NULL;
104-
size_t pos;
99+
struct memobject *obj;
105100

106-
pos = git_oidmap_lookup_index(db->objects, oid);
107-
if (!git_oidmap_valid_index(db->objects, pos))
101+
if ((obj = git_oidmap_get(db->objects, oid)) == NULL)
108102
return GIT_ENOTFOUND;
109103

110-
obj = git_oidmap_value_at(db->objects, pos);
111-
112104
*len_p = obj->len;
113105
*type_p = obj->type;
114106
return 0;

src/oidmap.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ size_t git_oidmap_size(git_oidmap *map)
4848
return kh_size(map);
4949
}
5050

51+
void *git_oidmap_get(git_oidmap *map, const git_oid *key)
52+
{
53+
size_t idx = git_oidmap_lookup_index(map, key);
54+
if (!git_oidmap_valid_index(map, idx) ||
55+
!git_oidmap_has_data(map, idx))
56+
return NULL;
57+
return kh_val(map, idx);
58+
}
59+
5160
size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key)
5261
{
5362
return kh_get(oid, map, key);

src/oidmap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ void git_oidmap_clear(git_oidmap *map);
5252
*/
5353
size_t git_oidmap_size(git_oidmap *map);
5454

55+
/**
56+
* Return value associated with the given key.
57+
*
58+
* @param map map to search key in
59+
* @param key key to search for
60+
* @return value associated with the given key or NULL if the key was not found
61+
*/
62+
void *git_oidmap_get(git_oidmap *map, const git_oid *key);
63+
5564
size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key);
5665
int git_oidmap_valid_index(git_oidmap *map, size_t idx);
5766

src/pack-objects.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,12 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data)
512512
{
513513
git_packbuilder *pb = data;
514514
git_pobject *po;
515-
size_t pos;
516515

517516
GIT_UNUSED(name);
518517

519-
pos = git_oidmap_lookup_index(pb->object_ix, oid);
520-
if (!git_oidmap_valid_index(pb->object_ix, pos))
518+
if ((po = git_oidmap_get(pb->object_ix, oid)) == NULL)
521519
return 0;
522520

523-
po = git_oidmap_value_at(pb->object_ix, pos);
524521
po->tagged = 1;
525522

526523
/* TODO: peel objects */
@@ -1537,14 +1534,10 @@ static int lookup_walk_object(struct walk_object **out, git_packbuilder *pb, con
15371534

15381535
static int retrieve_object(struct walk_object **out, git_packbuilder *pb, const git_oid *id)
15391536
{
1540-
int error;
1541-
size_t pos;
15421537
struct walk_object *obj;
1538+
int error;
15431539

1544-
pos = git_oidmap_lookup_index(pb->walk_objects, id);
1545-
if (git_oidmap_valid_index(pb->walk_objects, pos)) {
1546-
obj = git_oidmap_value_at(pb->walk_objects, pos);
1547-
} else {
1540+
if ((obj = git_oidmap_get(pb->walk_objects, id)) == NULL) {
15481541
if ((error = lookup_walk_object(&obj, pb, id)) < 0)
15491542
return error;
15501543

src/pack.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -957,14 +957,13 @@ git_off_t get_delta_base(
957957
} else if (type == GIT_OBJECT_REF_DELTA) {
958958
/* If we have the cooperative cache, search in it first */
959959
if (p->has_cache) {
960+
struct git_pack_entry *entry;
960961
git_oid oid;
961-
size_t k;
962962

963963
git_oid_fromraw(&oid, base_info);
964-
k = git_oidmap_lookup_index(p->idx_cache, &oid);
965-
if (git_oidmap_valid_index(p->idx_cache, k)) {
964+
if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
966965
*curpos += 20;
967-
return ((struct git_pack_entry *)git_oidmap_value_at(p->idx_cache, k))->offset;
966+
return entry->offset;
968967
} else {
969968
/* If we're building an index, don't try to find the pack
970969
* entry; we just haven't seen it yet. We'll make

src/revwalk.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ git_commit_list_node *git_revwalk__commit_lookup(
2525
int ret;
2626

2727
/* lookup and reserve space if not already present */
28-
pos = git_oidmap_lookup_index(walk->commits, oid);
29-
if (git_oidmap_valid_index(walk->commits, pos))
30-
return git_oidmap_value_at(walk->commits, pos);
28+
if ((commit = git_oidmap_get(walk->commits, oid)) != NULL)
29+
return commit;
3130

3231
commit = git_commit_list_alloc_node(walk);
3332
if (commit == NULL)

tests/core/oidmap.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,81 @@ void test_core_oidmap__hash_collision(void)
104104

105105
git_oidmap_free(map);
106106
}
107+
108+
void test_core_oidmap__get_succeeds_with_existing_keys(void)
109+
{
110+
git_oidmap *map;
111+
oidmap_item items[NITEMS];
112+
uint32_t i, j;
113+
114+
for (i = 0; i < NITEMS; ++i) {
115+
uint32_t segment = i / 8;
116+
int modi = i - (segment * 8);
117+
118+
items[i].extra = i;
119+
120+
for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) {
121+
items[i].oid.id[j * 4 ] = (unsigned char)modi;
122+
items[i].oid.id[j * 4 + 1] = (unsigned char)(modi >> 8);
123+
items[i].oid.id[j * 4 + 2] = (unsigned char)(modi >> 16);
124+
items[i].oid.id[j * 4 + 3] = (unsigned char)(modi >> 24);
125+
}
126+
127+
items[i].oid.id[ 8] = (unsigned char)i;
128+
items[i].oid.id[ 9] = (unsigned char)(i >> 8);
129+
items[i].oid.id[10] = (unsigned char)(i >> 16);
130+
items[i].oid.id[11] = (unsigned char)(i >> 24);
131+
}
132+
133+
cl_git_pass(git_oidmap_new(&map));
134+
135+
for (i = 0; i < NITEMS; ++i) {
136+
int ret;
137+
git_oidmap_insert(map, &items[i].oid, &items[i], &ret);
138+
cl_assert(ret == 1);
139+
}
140+
141+
for (i = 0; i < NITEMS; ++i)
142+
cl_assert_equal_p(git_oidmap_get(map, &items[i].oid), &items[i]);
143+
144+
git_oidmap_free(map);
145+
}
146+
147+
void test_core_oidmap__get_fails_with_nonexisting_key(void)
148+
{
149+
git_oidmap *map;
150+
oidmap_item items[NITEMS];
151+
uint32_t i, j;
152+
153+
for (i = 0; i < NITEMS; ++i) {
154+
uint32_t segment = i / 8;
155+
int modi = i - (segment * 8);
156+
157+
items[i].extra = i;
158+
159+
for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) {
160+
items[i].oid.id[j * 4 ] = (unsigned char)modi;
161+
items[i].oid.id[j * 4 + 1] = (unsigned char)(modi >> 8);
162+
items[i].oid.id[j * 4 + 2] = (unsigned char)(modi >> 16);
163+
items[i].oid.id[j * 4 + 3] = (unsigned char)(modi >> 24);
164+
}
165+
166+
items[i].oid.id[ 8] = (unsigned char)i;
167+
items[i].oid.id[ 9] = (unsigned char)(i >> 8);
168+
items[i].oid.id[10] = (unsigned char)(i >> 16);
169+
items[i].oid.id[11] = (unsigned char)(i >> 24);
170+
}
171+
172+
cl_git_pass(git_oidmap_new(&map));
173+
174+
/* Do _not_ add last OID to verify that we cannot look it up */
175+
for (i = 0; i < NITEMS - 1; ++i) {
176+
int ret;
177+
git_oidmap_insert(map, &items[i].oid, &items[i], &ret);
178+
cl_assert(ret == 1);
179+
}
180+
181+
cl_assert_equal_p(git_oidmap_get(map, &items[NITEMS - 1].oid), NULL);
182+
183+
git_oidmap_free(map);
184+
}

0 commit comments

Comments
 (0)