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