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;
|
} key;
|
||||||
uint64_t hash;
|
uint64_t hash;
|
||||||
char * path;
|
char * path;
|
||||||
struct __bucket * next;
|
|
||||||
} haggis_bucket;
|
} haggis_bucket;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
75
linkmap.c
75
linkmap.c
|
@ -30,10 +30,10 @@
|
||||||
* other than his own.
|
* other than his own.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "haggis.h"
|
||||||
#include "haggis_private.h"
|
#include "haggis_private.h"
|
||||||
|
|
||||||
#include <limits.h> // PATH_MAX
|
#include <limits.h> // PATH_MAX
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h> // calloc, free
|
#include <stdlib.h> // calloc, free
|
||||||
#include <string.h> // strndup
|
#include <string.h> // strndup
|
||||||
|
|
||||||
|
@ -63,38 +63,6 @@ uint64_t hash_str_fnv1a_64(char * s) {
|
||||||
return hash;
|
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* haggis_linkmap_init() {
|
||||||
haggis_linkmap *map;
|
haggis_linkmap *map;
|
||||||
|
|
||||||
|
@ -111,13 +79,6 @@ haggis_linkmap* haggis_linkmap_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void haggis_linkmap_deinit(haggis_linkmap *map) {
|
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->buckets);
|
||||||
free(map);
|
free(map);
|
||||||
}
|
}
|
||||||
|
@ -130,6 +91,9 @@ int haggis_linkmap_expand(haggis_linkmap *map) {
|
||||||
buckets_new = calloc(map->capacity + HAGGIS_BUCKETS_BASE, sizeof(haggis_bucket));
|
buckets_new = calloc(map->capacity + HAGGIS_BUCKETS_BASE, sizeof(haggis_bucket));
|
||||||
if (buckets_new == NULL)
|
if (buckets_new == NULL)
|
||||||
return 2;
|
return 2;
|
||||||
|
for (i = 0; i < map->capacity + HAGGIS_BUCKETS_BASE; i++) {
|
||||||
|
map->buckets[i].path = NULL;
|
||||||
|
}
|
||||||
for (i = 0; i < map->capacity; i++) {
|
for (i = 0; i < map->capacity; i++) {
|
||||||
if (map->buckets[i].key.val != 0) {
|
if (map->buckets[i].key.val != 0) {
|
||||||
hash = hash_fnv1a_64(&map->buckets[i].key.bytes[0], sizeof(ino_t));
|
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)];
|
u8 bytes[sizeof(ino_t)];
|
||||||
} key;
|
} key;
|
||||||
char * target = NULL;
|
char * target = NULL;
|
||||||
size_t idx, hash;
|
size_t idx, hash, i;
|
||||||
haggis_bucket *b;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&map->mutex);
|
pthread_mutex_lock(&map->mutex);
|
||||||
if (map->len >= map->capacity)
|
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;
|
key.val = inode;
|
||||||
hash = hash_fnv1a_64(key.bytes, sizeof(ino_t));
|
hash = hash_fnv1a_64(key.bytes, sizeof(ino_t));
|
||||||
idx = hash % map->capacity;
|
idx = hash % map->capacity;
|
||||||
if (map->buckets[idx].key.val == inode) {
|
for (i = 0; i < map->capacity; i++) {
|
||||||
target = strndup(map->buckets[idx].path, PATH_MAX - 1);
|
if (map->buckets[idx].key.val == inode) {
|
||||||
map->buckets[idx].path = path;
|
target = strndup(map->buckets[idx].path, PATH_MAX - 1);
|
||||||
} else if (map->buckets[idx].key.val == 0) {
|
map->buckets[idx].path = path;
|
||||||
map->buckets[idx].key.val = inode;
|
break;
|
||||||
map->buckets[idx].hash = hash;
|
} else if (map->buckets[idx].key.val == 0) {
|
||||||
map->buckets[idx].path = path;
|
map->buckets[idx].key.val = inode;
|
||||||
map->len++;
|
map->buckets[idx].hash = hash;
|
||||||
} else {
|
map->buckets[idx].path = path;
|
||||||
b = haggis_bucket_init(key.val, hash, path);
|
map->len++;
|
||||||
if (b == NULL) return NULL;
|
break;
|
||||||
target = haggis_bucket_search_append(&map->buckets[idx], b);
|
} else {
|
||||||
|
idx++;
|
||||||
|
if (idx == map->capacity)
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&map->mutex);
|
pthread_mutex_unlock(&map->mutex);
|
||||||
return target;
|
return target;
|
||||||
|
|
Loading…
Add table
Reference in a new issue