1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#include <stdlib.h>
#include <assert.h>
#include "fio.h"
#include "flist.h"
#include "hash.h"
#include "filehash.h"
#include "smalloc.h"
#include "lib/bloom.h"
#define HASH_BUCKETS 512
#define HASH_MASK (HASH_BUCKETS - 1)
#define BLOOM_SIZE 16*1024*1024
static unsigned int file_hash_size = HASH_BUCKETS * sizeof(struct flist_head);
static struct flist_head *file_hash;
static struct fio_sem *hash_lock;
static struct bloom *file_bloom;
static unsigned short hash(const char *name)
{
return jhash(name, strlen(name), 0) & HASH_MASK;
}
void fio_file_hash_lock(void)
{
if (hash_lock)
fio_sem_down(hash_lock);
}
void fio_file_hash_unlock(void)
{
if (hash_lock)
fio_sem_up(hash_lock);
}
void remove_file_hash(struct fio_file *f)
{
fio_sem_down(hash_lock);
if (fio_file_hashed(f)) {
assert(!flist_empty(&f->hash_list));
flist_del_init(&f->hash_list);
fio_file_clear_hashed(f);
}
fio_sem_up(hash_lock);
}
static struct fio_file *__lookup_file_hash(const char *name)
{
struct flist_head *bucket = &file_hash[hash(name)];
struct flist_head *n;
flist_for_each(n, bucket) {
struct fio_file *f = flist_entry(n, struct fio_file, hash_list);
if (!f->file_name)
continue;
if (!strcmp(f->file_name, name))
return f;
}
return NULL;
}
struct fio_file *lookup_file_hash(const char *name)
{
struct fio_file *f;
fio_sem_down(hash_lock);
f = __lookup_file_hash(name);
fio_sem_up(hash_lock);
return f;
}
struct fio_file *add_file_hash(struct fio_file *f)
{
struct fio_file *alias;
if (fio_file_hashed(f))
return NULL;
INIT_FLIST_HEAD(&f->hash_list);
fio_sem_down(hash_lock);
alias = __lookup_file_hash(f->file_name);
if (!alias) {
fio_file_set_hashed(f);
flist_add_tail(&f->hash_list, &file_hash[hash(f->file_name)]);
}
fio_sem_up(hash_lock);
return alias;
}
bool file_bloom_exists(const char *fname, bool set)
{
return bloom_string(file_bloom, fname, strlen(fname), set);
}
void file_hash_exit(void)
{
unsigned int i, has_entries = 0;
fio_sem_down(hash_lock);
for (i = 0; i < HASH_BUCKETS; i++)
has_entries += !flist_empty(&file_hash[i]);
fio_sem_up(hash_lock);
if (has_entries)
log_err("fio: file hash not empty on exit\n");
sfree(file_hash);
file_hash = NULL;
fio_sem_remove(hash_lock);
hash_lock = NULL;
bloom_free(file_bloom);
file_bloom = NULL;
}
void file_hash_init(void)
{
unsigned int i;
file_hash = smalloc(file_hash_size);
for (i = 0; i < HASH_BUCKETS; i++)
INIT_FLIST_HEAD(&file_hash[i]);
hash_lock = fio_sem_init(FIO_SEM_UNLOCKED);
file_bloom = bloom_new(BLOOM_SIZE);
}
|