Change linkmap structure to handle collisions by placing into the
next free bucket rather than by using a linked list structure. Fix bug where the filename was being freed in linkmap buckets, even though the data was owned by the caller.
This commit is contained in:
parent
826df41c01
commit
ee7c9b1b5d
2 changed files with 21 additions and 55 deletions
|
@ -125,7 +125,6 @@ typedef struct __bucket {
|
|||
} key;
|
||||
uint64_t hash;
|
||||
char * path;
|
||||
struct __bucket * next;
|
||||
} haggis_bucket;
|
||||
|
||||
typedef struct {
|
||||
|
|
75
linkmap.c
75
linkmap.c
|
@ -30,10 +30,10 @@
|
|||
* other than his own.
|
||||
*/
|
||||
|
||||
#include "haggis.h"
|
||||
#include "haggis_private.h"
|
||||
|
||||
#include <limits.h> // PATH_MAX
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // calloc, free
|
||||
#include <string.h> // strndup
|
||||
|
||||
|
@ -63,38 +63,6 @@ uint64_t hash_str_fnv1a_64(char * s) {
|
|||
return hash;
|
||||
}
|
||||
|
||||
haggis_bucket* haggis_bucket_init(ino_t inode, uint64_t hash, char * path) {
|
||||
haggis_bucket *bucket;
|
||||
|
||||
bucket = calloc(1, sizeof(haggis_bucket));
|
||||
if (bucket == NULL) return NULL;
|
||||
bucket->key.val = inode;
|
||||
bucket->hash = hash;
|
||||
bucket->path = path;
|
||||
bucket->next = NULL;
|
||||
return bucket;
|
||||
}
|
||||
|
||||
void haggis_bucket_deinit(haggis_bucket *nod) {
|
||||
if (nod->path != NULL)
|
||||
free(nod->path);
|
||||
free(nod);
|
||||
}
|
||||
|
||||
char* haggis_bucket_search_append(haggis_bucket *head, haggis_bucket *tail) {
|
||||
char* target;
|
||||
|
||||
while (head->next != NULL) {
|
||||
if (head->key.val == tail->key.val) {
|
||||
target = strndup(head->path, PATH_MAX - 1);
|
||||
return target;
|
||||
}
|
||||
head = head->next;
|
||||
}
|
||||
head->next = tail;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
haggis_linkmap* haggis_linkmap_init() {
|
||||
haggis_linkmap *map;
|
||||
|
||||
|
@ -111,13 +79,6 @@ haggis_linkmap* haggis_linkmap_init() {
|
|||
}
|
||||
|
||||
void haggis_linkmap_deinit(haggis_linkmap *map) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->capacity; i++) {
|
||||
if (map->buckets[i].next != NULL) {
|
||||
haggis_bucket_deinit(map->buckets[i].next);
|
||||
}
|
||||
}
|
||||
free(map->buckets);
|
||||
free(map);
|
||||
}
|
||||
|
@ -130,6 +91,9 @@ int haggis_linkmap_expand(haggis_linkmap *map) {
|
|||
buckets_new = calloc(map->capacity + HAGGIS_BUCKETS_BASE, sizeof(haggis_bucket));
|
||||
if (buckets_new == NULL)
|
||||
return 2;
|
||||
for (i = 0; i < map->capacity + HAGGIS_BUCKETS_BASE; i++) {
|
||||
map->buckets[i].path = NULL;
|
||||
}
|
||||
for (i = 0; i < map->capacity; i++) {
|
||||
if (map->buckets[i].key.val != 0) {
|
||||
hash = hash_fnv1a_64(&map->buckets[i].key.bytes[0], sizeof(ino_t));
|
||||
|
@ -151,8 +115,7 @@ char* haggis_linkmap_get_or_add(haggis_linkmap *map, ino_t inode, char * path) {
|
|||
u8 bytes[sizeof(ino_t)];
|
||||
} key;
|
||||
char * target = NULL;
|
||||
size_t idx, hash;
|
||||
haggis_bucket *b;
|
||||
size_t idx, hash, i;
|
||||
|
||||
pthread_mutex_lock(&map->mutex);
|
||||
if (map->len >= map->capacity)
|
||||
|
@ -160,18 +123,22 @@ char* haggis_linkmap_get_or_add(haggis_linkmap *map, ino_t inode, char * path) {
|
|||
key.val = inode;
|
||||
hash = hash_fnv1a_64(key.bytes, sizeof(ino_t));
|
||||
idx = hash % map->capacity;
|
||||
if (map->buckets[idx].key.val == inode) {
|
||||
target = strndup(map->buckets[idx].path, PATH_MAX - 1);
|
||||
map->buckets[idx].path = path;
|
||||
} else if (map->buckets[idx].key.val == 0) {
|
||||
map->buckets[idx].key.val = inode;
|
||||
map->buckets[idx].hash = hash;
|
||||
map->buckets[idx].path = path;
|
||||
map->len++;
|
||||
} else {
|
||||
b = haggis_bucket_init(key.val, hash, path);
|
||||
if (b == NULL) return NULL;
|
||||
target = haggis_bucket_search_append(&map->buckets[idx], b);
|
||||
for (i = 0; i < map->capacity; i++) {
|
||||
if (map->buckets[idx].key.val == inode) {
|
||||
target = strndup(map->buckets[idx].path, PATH_MAX - 1);
|
||||
map->buckets[idx].path = path;
|
||||
break;
|
||||
} else if (map->buckets[idx].key.val == 0) {
|
||||
map->buckets[idx].key.val = inode;
|
||||
map->buckets[idx].hash = hash;
|
||||
map->buckets[idx].path = path;
|
||||
map->len++;
|
||||
break;
|
||||
} else {
|
||||
idx++;
|
||||
if (idx == map->capacity)
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&map->mutex);
|
||||
return target;
|
||||
|
|
Loading…
Add table
Reference in a new issue