6 #include "mod_cuckoo.h"
15 unsigned int positions
;
16 struct cuckoo_array first
, second
;
19 static struct cuckoo_tbl cuckoo_tbl
;
21 #define HASH_TABLE_SIZE 3072 /* 3k */
22 #define LOTTERY_MAX 6 /* bytes */
23 #define NAME_LENGTH 17 /* bytes */
25 static inline unsigned int tdb_hash(char *name
)
27 unsigned value
; /* Used to compute the hash value. */
28 unsigned i
; /* Used to cycle through random values. */
30 /* Set the initial value from the key size. */
31 for (value
= 0x238F13AF * strlen(name
), i
=0; name
[i
]; i
++)
32 value
= (value
+ (((unsigned char *)name
)[i
] << (i
*5 % 24)));
34 return (1103515243 * value
+ 12345);
37 static inline unsigned int joaat_hash(char *name
)
40 unsigned int hash
= 0;
42 for (i
= 0; i
< (int) strlen(name
); i
++) {
55 static void cuckoo_print_stats(void)
57 struct cuckoo_tbl
*tbl
= &cuckoo_tbl
;
59 printf("\n-> Hash table statistics\n");
60 printf("First table size: %4d\n", tbl
->positions
);
61 printf(" o in use: %4d\n", tbl
->first
.size
);
62 printf(" o free: %4d\n", tbl
->positions
- tbl
->first
.size
);
63 printf("Second table size: %4d\n", tbl
->positions
);
64 printf(" o in use: %4d\n", tbl
->second
.size
);
65 printf(" o free: %4d\n", tbl
->positions
- tbl
->second
.size
);
69 static int cuckoo_lookup(char *name
, unsigned int *h
)
73 hash
= tdb_hash(name
) % cuckoo_tbl
.positions
;
74 if (cuckoo_tbl
.first
.array
[hash
] == NULL
)
77 if (!memcmp(cuckoo_tbl
.first
.array
[hash
], name
, NAME_LENGTH
))
80 hash
= joaat_hash(name
) % cuckoo_tbl
.positions
;
81 if (cuckoo_tbl
.second
.array
[hash
] == NULL
)
84 if (!memcmp(cuckoo_tbl
.second
.array
[hash
], name
, NAME_LENGTH
))
95 static int cuckoo_insert(char *name
)
101 ret
= cuckoo_lookup(name
, NULL
);
103 /* key already exists */
109 for (i
= 0; i
< cuckoo_tbl
.positions
; i
++) {
111 hash
= tdb_hash(el
) % cuckoo_tbl
.positions
;
112 if (cuckoo_tbl
.first
.array
[hash
] == NULL
) {
113 cuckoo_tbl
.first
.array
[hash
] = el
;
114 cuckoo_tbl
.first
.size
++;
118 tmp
= cuckoo_tbl
.first
.array
[hash
];
119 cuckoo_tbl
.first
.array
[hash
] = el
;
122 hash
= joaat_hash(el
) % cuckoo_tbl
.positions
;
123 if (cuckoo_tbl
.second
.array
[hash
] == NULL
) {
124 cuckoo_tbl
.second
.array
[hash
] = el
;
125 cuckoo_tbl
.second
.size
++;
129 tmp
= cuckoo_tbl
.second
.array
[hash
];
130 cuckoo_tbl
.second
.array
[hash
] = el
;
134 fprintf(stderr
, "Out of Max loop, aborting\n");
143 static struct cuckoo_tbl
*rehash(struct cuckoo_tbl
*tbl
)
147 struct cuckoo_tbl
*new_table
;
149 new_table
= malloc(sizeof(struct cuckoo_tbl
));
153 err
= cuckoo_init(new_table
, tbl
->positions
* 2);
157 for (i
= 0; i
< tbl
->positions
; i
++) {
158 if (tbl
->first
.array
[i
]) {
159 err
= cuckoo_insert(new_table
,
160 tbl
->first
.array
[i
]);
165 if (tbl
->second
.array
[i
]) {
166 err
= cuckoo_insert(new_table
,
167 tbl
->second
.array
[i
]);
184 static int cuckoo_init(void)
187 const int positions
= HASH_TABLE_SIZE
;
189 cuckoo_tbl
.first
.array
= malloc(sizeof(void *) * positions
);
190 if (!cuckoo_tbl
.first
.array
)
193 cuckoo_tbl
.second
.array
= malloc(sizeof(void *) * positions
);
194 if (!cuckoo_tbl
.second
.array
) {
195 free(cuckoo_tbl
.first
.array
);
199 for (i
= 0; i
< positions
; i
++)
200 cuckoo_tbl
.first
.array
[i
] = cuckoo_tbl
.second
.array
[i
] = NULL
;
202 cuckoo_tbl
.positions
= positions
;
203 cuckoo_tbl
.size
= cuckoo_tbl
.first
.size
= cuckoo_tbl
.second
.size
= 0;
208 static void cuckoo_destroy(void)
212 for (i
= 0; i
< cuckoo_tbl
.positions
; i
++) {
213 if (cuckoo_tbl
.first
.array
[i
])
214 free(cuckoo_tbl
.first
.array
[i
]);
216 if (cuckoo_tbl
.second
.array
[i
])
217 free(cuckoo_tbl
.second
.array
[i
]);
220 free(cuckoo_tbl
.first
.array
);
221 free(cuckoo_tbl
.second
.array
);
224 struct module cuckoo_module
= {
225 .mod_name
= "Cuckoo hashing",
226 .mod_init
= cuckoo_init
,
227 .mod_insert
= cuckoo_insert
,
228 .mod_lookup
= cuckoo_lookup
,
229 .mod_destroy
= cuckoo_destroy
,
230 .mod_stats
= cuckoo_print_stats
,