mirror of
https://github.com/git/git.git
synced 2024-11-30 21:44:02 +08:00
fb79947487
Whenever the hash table becomes too small then its size is increased, the original part (and the added space) is zerod out using memset(), and the table is rebuilt from scratch. Simplify this proceess by returning the old memory using free() and allocating the new buffer using xcalloc(), which already clears the buffer for us. That way we avoid copying the old hash table contents needlessly inside xrealloc(). While at it, use the first array member with sizeof instead of a specific type. The old code used uint32_t and int, while index is actually an array of int32_t. Their sizes are the same basically everywhere, so it's not actually a problem, but the new code is cleaner and doesn't have to be touched should the type be changed. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
112 lines
2.2 KiB
C
112 lines
2.2 KiB
C
#include "cache.h"
|
|
#include "object.h"
|
|
#include "pack.h"
|
|
#include "pack-objects.h"
|
|
|
|
static uint32_t locate_object_entry_hash(struct packing_data *pdata,
|
|
const unsigned char *sha1,
|
|
int *found)
|
|
{
|
|
uint32_t i, hash, mask = (pdata->index_size - 1);
|
|
|
|
memcpy(&hash, sha1, sizeof(uint32_t));
|
|
i = hash & mask;
|
|
|
|
while (pdata->index[i] > 0) {
|
|
uint32_t pos = pdata->index[i] - 1;
|
|
|
|
if (!hashcmp(sha1, pdata->objects[pos].idx.sha1)) {
|
|
*found = 1;
|
|
return i;
|
|
}
|
|
|
|
i = (i + 1) & mask;
|
|
}
|
|
|
|
*found = 0;
|
|
return i;
|
|
}
|
|
|
|
static inline uint32_t closest_pow2(uint32_t v)
|
|
{
|
|
v = v - 1;
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
return v + 1;
|
|
}
|
|
|
|
static void rehash_objects(struct packing_data *pdata)
|
|
{
|
|
uint32_t i;
|
|
struct object_entry *entry;
|
|
|
|
pdata->index_size = closest_pow2(pdata->nr_objects * 3);
|
|
if (pdata->index_size < 1024)
|
|
pdata->index_size = 1024;
|
|
|
|
free(pdata->index);
|
|
pdata->index = xcalloc(pdata->index_size, sizeof(*pdata->index));
|
|
|
|
entry = pdata->objects;
|
|
|
|
for (i = 0; i < pdata->nr_objects; i++) {
|
|
int found;
|
|
uint32_t ix = locate_object_entry_hash(pdata, entry->idx.sha1, &found);
|
|
|
|
if (found)
|
|
die("BUG: Duplicate object in hash");
|
|
|
|
pdata->index[ix] = i + 1;
|
|
entry++;
|
|
}
|
|
}
|
|
|
|
struct object_entry *packlist_find(struct packing_data *pdata,
|
|
const unsigned char *sha1,
|
|
uint32_t *index_pos)
|
|
{
|
|
uint32_t i;
|
|
int found;
|
|
|
|
if (!pdata->index_size)
|
|
return NULL;
|
|
|
|
i = locate_object_entry_hash(pdata, sha1, &found);
|
|
|
|
if (index_pos)
|
|
*index_pos = i;
|
|
|
|
if (!found)
|
|
return NULL;
|
|
|
|
return &pdata->objects[pdata->index[i] - 1];
|
|
}
|
|
|
|
struct object_entry *packlist_alloc(struct packing_data *pdata,
|
|
const unsigned char *sha1,
|
|
uint32_t index_pos)
|
|
{
|
|
struct object_entry *new_entry;
|
|
|
|
if (pdata->nr_objects >= pdata->nr_alloc) {
|
|
pdata->nr_alloc = (pdata->nr_alloc + 1024) * 3 / 2;
|
|
pdata->objects = xrealloc(pdata->objects,
|
|
pdata->nr_alloc * sizeof(*new_entry));
|
|
}
|
|
|
|
new_entry = pdata->objects + pdata->nr_objects++;
|
|
|
|
memset(new_entry, 0, sizeof(*new_entry));
|
|
hashcpy(new_entry->idx.sha1, sha1);
|
|
|
|
if (pdata->index_size * 3 <= pdata->nr_objects * 4)
|
|
rehash_objects(pdata);
|
|
else
|
|
pdata->index[index_pos] = pdata->nr_objects;
|
|
|
|
return new_entry;
|
|
}
|