Add haggis_linkmap_get_or_add

This commit is contained in:
Nathan Fisher 2023-08-17 23:26:53 -04:00
parent 69107b2c80
commit fcdcd40e95
2 changed files with 60 additions and 58 deletions

View file

@ -42,28 +42,21 @@
#define HAGGIS_BUCKETS_BASE 64 #define HAGGIS_BUCKETS_BASE 64
struct _haggis_link { typedef struct __bucket {
struct _haggis_link *next;
char *path;
};
typedef struct _haggis_link haggis_link;
typedef struct {
union { union {
ino_t val; ino_t val;
u8 bytes[sizeof(ino_t)]; u8 bytes[sizeof(ino_t)];
} *key; } key;
uint64_t hash; uint64_t hash;
char * target; char * path;
haggis_link *links; struct __bucket * next;
} haggis_linkmap_node; } haggis_bucket;
typedef struct { typedef struct {
pthread_mutex_t *mutex; pthread_mutex_t *mutex;
size_t len; size_t len;
size_t capacity; size_t capacity;
haggis_linkmap_node *buckets; haggis_bucket *buckets;
} haggis_linkmap; } haggis_linkmap;
#endif // !HAGGIS_LINKMAP #endif // !HAGGIS_LINKMAP

View file

@ -32,67 +32,50 @@
#include "linkmap.h" #include "linkmap.h"
#include "haggis_private.h" #include "haggis_private.h"
#include <limits.h>
#include <pthread.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
haggis_link* haggis_link_init(char* path) { haggis_bucket* haggis_bucket_init(ino_t inode, uint64_t hash, char * path) {
haggis_link *link; haggis_bucket *bucket;
link = calloc(1, sizeof(haggis_link)); bucket = calloc(1, sizeof(haggis_bucket));
if (link == NULL) return NULL; if (bucket == NULL) return NULL;
link->path = path; bucket->key.val = inode;
return link; bucket->hash = hash;
bucket->path = path;
return bucket;
} }
void haggis_link_deinit(haggis_link *link) { void haggis_bucket_deinit(haggis_bucket *nod) {
if (link == NULL) if (nod->path != NULL)
return; free(nod->path);
if (link->path != NULL)
free(link->path);
free(link);
}
int haggis_link_append(haggis_link *head, char *path) {
haggis_link *tail;
tail = haggis_link_init(path);
if (tail == NULL) return 2;
while (head->next != NULL) {
head++;
}
head->next = tail;
return 0;
}
void haggis_linkmap_node_deinit(haggis_linkmap_node *nod) {
haggis_link *current;
haggis_link *previous;
current = nod->links;
while (current != NULL) {
previous = current;
current = current->next;
free(previous);
}
if (nod->key != NULL)
free(nod->key);
if (nod->target != NULL)
free(nod->target);
free(nod); free(nod);
} }
void haggis_bucket_append(haggis_bucket *head, haggis_bucket *tail) {
while (head->next != NULL) {
head = head->next;
}
head->next = tail;
}
int haggis_linkmap_expand(haggis_linkmap *map) { int haggis_linkmap_expand(haggis_linkmap *map) {
haggis_linkmap_node *buckets_new; haggis_bucket *buckets_new;
haggis_linkmap_node *buckets_old; haggis_bucket *buckets_old;
size_t i, hash, idx; size_t i, hash, idx;
buckets_new = calloc(map->capacity + HAGGIS_BUCKETS_BASE, sizeof(haggis_linkmap_node)); 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; i++) { for (i = 0; i < map->capacity; i++) {
if (&map->buckets[i] != NULL) { if (map->buckets[i].key.val != 0) {
hash = hash_fnv1a_64(map->buckets[i].key->bytes, sizeof(ino_t)); hash = hash_fnv1a_64(&map->buckets[i].key.bytes[0], sizeof(ino_t));
map ->capacity += HAGGIS_BUCKETS_BASE; map ->capacity += HAGGIS_BUCKETS_BASE;
idx = map->capacity % hash; idx = map->capacity % hash;
buckets_new[idx] = map->buckets[i]; buckets_new[idx] = map->buckets[i];
@ -104,3 +87,29 @@ int haggis_linkmap_expand(haggis_linkmap *map) {
map->capacity += HAGGIS_BUCKETS_BASE; map->capacity += HAGGIS_BUCKETS_BASE;
return 0; return 0;
} }
char* haggis_linkmap_get_or_add(haggis_linkmap *map, ino_t inode, char * path) {
union {
ino_t val;
u8 bytes[sizeof(ino_t)];
} key;
char * target = NULL;
size_t idx, hash;
pthread_mutex_lock(map->mutex);
key.val = inode;
hash = hash_fnv1a_64(key.bytes, sizeof(ino_t));
idx = map->capacity % hash;
if (map->buckets[idx].key.val == 0) {
map->buckets[idx].key.val = inode;
map->buckets[idx].hash = hash;
map->buckets[idx].path = path;
pthread_mutex_unlock(map->mutex);
return NULL;
} else if (map->buckets[idx].key.val == inode) {
target = strndup(target, PATH_MAX - 1);
pthread_mutex_unlock(map->mutex);
return target;
}
return NULL;
}