3 Routines for manipulating hash tables... */
6 * Copyright (c) 2009-2010,2014 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1995-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
32 #include <omapip/omapip_p.h>
37 find_length(const void *key
,
38 unsigned (*do_hash
)(const void *, unsigned, unsigned))
40 if (do_hash
== do_case_hash
|| do_hash
== do_string_hash
)
41 return strlen((const char *)key
);
42 if (do_hash
== do_number_hash
)
43 return sizeof(unsigned);
44 if (do_hash
== do_ip4_hash
)
47 log_debug("Unexpected hash function at %s:%d.", MDL
);
49 * If we get a hash function we don't specifically expect
50 * return a length of 0, this covers the case where a client
51 * id has a length of 0.
56 int new_hash_table (tp
, count
, file
, line
)
57 struct hash_table
**tp
;
62 struct hash_table
*rval
;
66 log_error ("%s(%d): new_hash_table called with null pointer.",
68 #if defined (POINTER_DEBUG)
74 log_error ("%s(%d): non-null target for new_hash_table.",
76 #if defined (POINTER_DEBUG)
81 /* There is one hash bucket in the structure. Allocate extra
82 * memory beyond the end of the structure to fulfill the requested
83 * count ("count - 1"). Do not let there be less than one.
90 rval
= dmalloc(sizeof(struct hash_table
) +
91 (extra
* sizeof(struct hash_bucket
*)), file
, line
);
94 rval
-> hash_count
= count
;
99 void free_hash_table (tp
, file
, line
)
100 struct hash_table
**tp
;
104 struct hash_table
*ptr
= *tp
;
106 #if defined (DEBUG_MEMORY_LEAKAGE) || \
107 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
109 struct hash_bucket
*hbc
, *hbn
= (struct hash_bucket
*)0;
111 for (i
= 0; i
< ptr
-> hash_count
; i
++) {
112 for (hbc
= ptr
-> buckets
[i
]; hbc
; hbc
= hbn
) {
114 if (ptr
-> dereferencer
&& hbc
-> value
)
115 (*ptr
-> dereferencer
) (&hbc
-> value
, MDL
);
117 for (hbc
= ptr
-> buckets
[i
]; hbc
; hbc
= hbn
) {
119 free_hash_bucket (hbc
, MDL
);
121 ptr
-> buckets
[i
] = (struct hash_bucket
*)0;
125 dfree((void *)ptr
, MDL
);
126 *tp
= (struct hash_table
*)0;
129 struct hash_bucket
*free_hash_buckets
;
131 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
132 struct hash_bucket
*hash_bucket_hunks
;
134 void relinquish_hash_bucket_hunks ()
136 struct hash_bucket
*c
, *n
, **p
;
138 /* Account for all the hash buckets on the free list. */
139 p
= &free_hash_buckets
;
140 for (c
= free_hash_buckets
; c
; c
= c
-> next
) {
141 for (n
= hash_bucket_hunks
; n
; n
= n
-> next
) {
142 if (c
> n
&& c
< n
+ 127) {
148 /* If we didn't delete the hash bucket from the free list,
149 advance the pointer. */
154 for (c
= hash_bucket_hunks
; c
; c
= n
) {
156 if (c
-> len
!= 126) {
157 log_info ("hashbucket %lx hash_buckets %d free %u",
158 (unsigned long)c
, 127, c
-> len
);
165 struct hash_bucket
*new_hash_bucket (file
, line
)
169 struct hash_bucket
*rval
;
171 if (!free_hash_buckets
) {
172 rval
= dmalloc (127 * sizeof (struct hash_bucket
),
176 # if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
177 rval
-> next
= hash_bucket_hunks
;
178 hash_bucket_hunks
= rval
;
179 hash_bucket_hunks
-> len
= 0;
183 for (; i
< 127; i
++) {
184 rval
-> next
= free_hash_buckets
;
185 free_hash_buckets
= rval
;
189 rval
= free_hash_buckets
;
190 free_hash_buckets
= rval
-> next
;
194 void free_hash_bucket (ptr
, file
, line
)
195 struct hash_bucket
*ptr
;
199 #if defined (DEBUG_MALLOC_POOL)
200 struct hash_bucket
*hp
;
202 for (hp
= free_hash_buckets
; hp
; hp
= hp
-> next
) {
204 log_error ("hash bucket freed twice!");
209 ptr
-> next
= free_hash_buckets
;
210 free_hash_buckets
= ptr
;
213 int new_hash(struct hash_table
**rp
,
214 hash_reference referencer
,
215 hash_dereference dereferencer
,
217 unsigned (*hasher
)(const void *, unsigned, unsigned),
218 const char *file
, int line
)
221 hsize
= DEFAULT_HASH_SIZE
;
223 if (!new_hash_table (rp
, hsize
, file
, line
))
226 memset ((*rp
)->buckets
, 0, hsize
* sizeof(struct hash_bucket
*));
228 (*rp
)->referencer
= referencer
;
229 (*rp
)->dereferencer
= dereferencer
;
230 (*rp
)->do_hash
= hasher
;
232 if (hasher
== do_case_hash
)
233 (*rp
)->cmp
= casecmp
;
241 do_case_hash(const void *name
, unsigned len
, unsigned size
)
243 register unsigned accum
= 0;
244 register const unsigned char *s
= name
;
249 /* Make the hash case-insensitive. */
254 /* Add the character in... */
255 accum
= (accum
<< 1) + c
;
257 /* Add carry back in... */
258 while (accum
> 65535) {
259 accum
= (accum
& 65535) + (accum
>> 16);
267 do_string_hash(const void *name
, unsigned len
, unsigned size
)
269 register unsigned accum
= 0;
270 register const unsigned char *s
= (const unsigned char *)name
;
274 /* Add the character in... */
275 accum
= (accum
<< 1) + *s
++;
277 /* Add carry back in... */
278 while (accum
> 65535) {
279 accum
= (accum
& 65535) + (accum
>> 16);
285 /* Client identifiers are generally 32-bits of ordinary
286 * non-randomness followed by 24-bits of unordinary randomness.
287 * So, end-align in 24-bit chunks, and xor any preceding data
288 * just to mix it up a little.
291 do_id_hash(const void *name
, unsigned len
, unsigned size
)
293 register unsigned accum
= 0;
294 register const unsigned char *s
= (const unsigned char *)name
;
295 const unsigned char *end
= s
+ len
;
301 * The switch handles our starting conditions, then we hash the
302 * remaining bytes in groups of 3
325 do_number_hash(const void *key
, unsigned len
, unsigned size
)
327 register unsigned number
= *((const unsigned *)key
);
329 return number
% size
;
333 do_ip4_hash(const void *key
, unsigned len
, unsigned size
)
337 memcpy(&number
, key
, 4);
339 number
= ntohl(number
);
341 return number
% size
;
345 hash_report(struct hash_table
*table
)
347 static unsigned char retbuf
[sizeof("Contents/Size (%): "
348 "2147483647/2147483647 "
350 "Min/max: 2147483647/2147483647")];
351 unsigned curlen
, pct
, contents
=0, minlen
=UINT_MAX
, maxlen
=0;
353 struct hash_bucket
*bp
;
356 return (unsigned char *) "No table.";
358 if (table
->hash_count
== 0)
359 return (unsigned char *) "Invalid hash table.";
361 for (i
= 0 ; i
< table
->hash_count
; i
++) {
364 bp
= table
->buckets
[i
];
378 if (contents
>= (UINT_MAX
/ 100))
379 pct
= contents
/ ((table
->hash_count
/ 100) + 1);
381 pct
= (contents
* 100) / table
->hash_count
;
383 if (contents
> 2147483647 ||
384 table
->hash_count
> 2147483647 ||
386 minlen
> 2147483647 ||
388 return (unsigned char *) "Report out of range for display.";
390 sprintf((char *)retbuf
,
391 "Contents/Size (%%): %u/%u (%u%%). Min/max: %u/%u",
392 contents
, table
->hash_count
, pct
, minlen
, maxlen
);
397 void add_hash (table
, key
, len
, pointer
, file
, line
)
398 struct hash_table
*table
;
401 hashed_object_t
*pointer
;
406 struct hash_bucket
*bp
;
413 len
= find_length(key
, table
->do_hash
);
415 hashno
= (*table
->do_hash
)(key
, len
, table
->hash_count
);
416 bp
= new_hash_bucket (file
, line
);
419 log_error ("Can't add entry to hash table: no memory.");
423 if (table
-> referencer
) {
425 (*(table
-> referencer
)) (foo
, pointer
, file
, line
);
427 bp
-> value
= pointer
;
428 bp
-> next
= table
-> buckets
[hashno
];
430 table
-> buckets
[hashno
] = bp
;
433 void delete_hash_entry (table
, key
, len
, file
, line
)
434 struct hash_table
*table
;
441 struct hash_bucket
*bp
, *pbp
= (struct hash_bucket
*)0;
448 len
= find_length(key
, table
->do_hash
);
450 hashno
= (*table
->do_hash
)(key
, len
, table
->hash_count
);
452 /* Go through the list looking for an entry that matches;
453 if we find it, delete it. */
454 for (bp
= table
-> buckets
[hashno
]; bp
; bp
= bp
-> next
) {
456 !strcmp ((const char *)bp
->name
, key
)) ||
458 !(table
-> cmp
)(bp
->name
, key
, len
))) {
460 pbp
-> next
= bp
-> next
;
462 table
-> buckets
[hashno
] = bp
-> next
;
464 if (bp
-> value
&& table
-> dereferencer
) {
466 (*(table
-> dereferencer
)) (foo
, file
, line
);
468 free_hash_bucket (bp
, file
, line
);
471 pbp
= bp
; /* jwg, 9/6/96 - nice catch! */
475 int hash_lookup (vp
, table
, key
, len
, file
, line
)
476 hashed_object_t
**vp
;
477 struct hash_table
*table
;
484 struct hash_bucket
*bp
;
489 len
= find_length(key
, table
->do_hash
);
492 log_fatal("Internal inconsistency: storage value has not been "
493 "initialized to zero (from %s:%d).", file
, line
);
496 hashno
= (*table
->do_hash
)(key
, len
, table
->hash_count
);
498 for (bp
= table
-> buckets
[hashno
]; bp
; bp
= bp
-> next
) {
500 && !(*table
->cmp
)(bp
->name
, key
, len
)) {
501 if (table
-> referencer
)
502 (*table
-> referencer
) (vp
, bp
-> value
,
512 int hash_foreach (struct hash_table
*table
, hash_foreach_func func
)
515 struct hash_bucket
*bp
, *next
;
521 for (i
= 0; i
< table
-> hash_count
; i
++) {
522 bp
= table
-> buckets
[i
];
525 if ((*func
)(bp
->name
, bp
->len
, bp
->value
)
535 int casecmp (const void *v1
, const void *v2
, size_t len
)
538 const unsigned char *s
= v1
;
539 const unsigned char *t
= v2
;
541 for (i
= 0; i
< len
; i
++)