diff options
Diffstat (limited to 'omapip/hash.c')
-rw-r--r-- | omapip/hash.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/omapip/hash.c b/omapip/hash.c index 29a67eb6..ace7ef22 100644 --- a/omapip/hash.c +++ b/omapip/hash.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: hash.c,v 1.11 2006/07/25 09:59:39 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: hash.c,v 1.12 2006/10/27 22:54:12 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include <omapip/omapip_p.h> @@ -282,6 +282,41 @@ do_string_hash(const void *name, unsigned len, unsigned size) return accum % size; } +/* Client identifiers are generally 32-bits of ordinary + * non-randomness followed by 24-bits of unordinary randomness. + * So, end-align in 24-bit chunks, and xor any preceding data + * just to mix it up a little. + */ +unsigned +do_id_hash(const void *name, unsigned len, unsigned size) +{ + register unsigned accum = 0; + register const unsigned char *s = (const unsigned char *)name; + const unsigned char *end = s + len; + + if (len == 0) + return 0; + + /* The switch indexes our starting position into the do/while loop, + * taking up the remainder after hashing in all the other bytes in + * threes. + */ + switch (len % 3) { + do { + case 0: + accum ^= *s++ << 16; + case 2: + accum ^= *s++ << 8; + case 1: + accum ^= *s++; + } while (s < end); + + break; + } + + return accum % size; +} + unsigned do_number_hash(const void *key, unsigned len, unsigned size) { @@ -302,6 +337,55 @@ do_ip4_hash(const void *key, unsigned len, unsigned size) return number % size; } +unsigned char * +hash_report(struct hash_table *table) +{ + static unsigned char retbuf[sizeof("Contents/Size (%): " + "2147483647/2147483647 " + "(2147483647%). " + "Min/max: 2147483647/2147483647")]; + unsigned curlen, pct, contents=0, minlen=UINT_MAX, maxlen=0; + unsigned i; + struct hash_bucket *bp; + + if (table->hash_count == 0) + return "Invalid hash table."; + + for (i = 0 ; i < table->hash_count ; i++) { + curlen = 0; + + bp = table->buckets[i]; + while (bp != NULL) { + curlen++; + bp = bp->next; + } + + if (curlen < minlen) + minlen = curlen; + if (curlen > maxlen) + maxlen = curlen; + + contents += curlen; + } + + if (contents >= (UINT_MAX / 100)) + pct = contents / ((table->hash_count / 100) + 1); + else + pct = (contents * 100) / table->hash_count; + + if (contents > 2147483647 || + table->hash_count > 2147483647 || + pct > 2147483647 || + minlen > 2147483647 || + maxlen > 2147483647) + return "Report out of range for display."; + + sprintf(retbuf, "Contents/Size (%%): %u/%u (%u%%). Min/max: %u/%u", + contents, table->hash_count, pct, minlen, maxlen); + + return retbuf; +} + void add_hash (table, key, len, pointer, file, line) struct hash_table *table; unsigned len; |