hash.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright (c) 1993-2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 1988, 1991 by Carnegie Mellon University
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Carnegie Mellon University not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission.
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*/
/*
* Generalized hash table ADT
*
* Provides multiple, dynamically-allocated, variable-sized hash tables on
* various data and keys.
*
* This package attempts to follow some of the coding conventions suggested
* by Bob Sidebotham and the AFS Clean Code Committee of the
* Information Technology Center at Carnegie Mellon.
*
* Additions for per bucket locking, and configurable dynamic free of
* unused entries.
*/
#include <stdlib.h>
#include <string.h>
#include <sys/sysmacros.h>
#include <stdarg.h>
#include <stddef.h>
#include <assert.h>
#include <synch.h>
#include "dhcpd.h"
#include "hash.h"
/*
* Hash table size calculation routine.
*
* Estimate the size of a hash table based on the expected number of
* entries, up to a maximum of HASHTABLESIZE.
*/
static unsigned
hashi_Hsize(unsigned hint)
{
unsigned f;
if (hint == 0) /* Default size. */
hint = 16;
hint /= 4;
if (hint % f == 0) {
f = 1;
hint++;
}
}
}
/*
* Frees an entire linked list of bucket members (used in the
* open hashing scheme). Does nothing if the passed pointer is NULL.
*
* Returns B_FALSE and members which could not be freed in bucketptr, when
* force variable is set to B_FALSE, and free_data routine indicates
* free did not occur.
*/
static boolean_t
{
if (bucketptr) {
B_FALSE) {
} else {
}
} else
}
}
return (ret);
}
/*
* Dynamic free initialization.
*/
static void
{
}
/*
* Dynamic free reference count increment.
*/
static void
{
}
/*
* Dynamic free expired data. Return NULL if memberptr is successfully
* dynamically freed, otherwise return memberptr.
*/
static hash_member *
{
else
return (memberptr);
}
/*
* Hash table initialization routine.
*
* This routine creates and intializes a hash table of size "tablesize"
* entries. Successful calls return a pointer to the hash table (which must
* be passed to other hash routines to identify the hash table). Failed
* calls return NULL.
*/
hash_tbl *
{
unsigned totalsize;
unsigned i;
(tablesize - 1));
hashtblptr->bucketnum = 0;
for (i = 0; i < tablesize; i++) {
USYNC_THREAD, NULL);
}
}
return (hashtblptr); /* NULL if failure */
}
/*
* Generic hash function to calculate a hash code from the given string.
*
* For each byte of the string, this function left-shifts the value in an
* accumulator and then adds the byte into the accumulator. The contents of
* the accumulator is returned after the entire string has been processed.
* It is assumed that this result will be used as the "hashcode" parameter in
* calls to other functions in this package. These functions automatically
* adjust the hashcode for the size of each hashtable.
*
* This algorithm probably works best when the hash table size is a prime
* number.
*
* Hopefully, this function is better than the previous one which returned
* the sum of the squares of all the bytes. I'm still open to other
* suggestions for a default hash function. The programmer is more than
* features of this package.
*/
static unsigned
{
unsigned accum;
/*
* Special case: allow hash_Delete() to iterate over buckets.
*/
return (len);
accum <<= 1;
}
return (accum);
}
/*
* This routine re-initializes the hash table. It frees all the allocated
* memory and resets all bucket pointers to NULL. For the macro hash
* table, the table will be reused. Other tables (with bucket locks)
* will be destroyed.
*/
void
{
unsigned i;
/*
* Unequivocally free member, using the force parameter.
*/
}
bucketptr++;
}
}
/*
* Returns B_TRUE if at least one entry for the given key exists; B_FALSE
* otherwise. Dynamically free expired data as searched.
*/
static int
{
/*
* Dynamically free expired data.
*/
NULL) {
continue;
}
}
/*
* Entry exists, or we are randomly selecting any
* element (compare function is NULL).
*/
break;
} else
}
return (ret);
}
/*
* Returns number of Dynamically freed expired entries.
*/
static int
{
int rcount = 0;
while (memberptr) {
/*
* Dynamically free expired data.
*/
NULL) {
rcount++;
continue;
}
}
}
return (rcount);
}
/*
* Insert the data item "element" into the hash table using "hashcode"
* to determine the bucket number, and "compare" and "key" to determine
* its uniqueness.
*
* If the insertion is successful the element is returned. If a matching entry
* already exists in the given bucket of the hash table, then NULL is returned,
* signifying that the entry is already in the table. This happens when some
* other thread has already inserted the entry.
*/
void *
{
&prev)) {
/* Some other thread got there first, so just return */
return (NULL);
}
/*
* Dynamic free initialization.
*/
return ((void *)temp);
}
/*
* Release the reference count on an item. Performance: if item is to be
* deleted, mark for future dynamic free.
*/
void
{
}
/*
* Report the reference count on an item.
*/
int
hash_Refcount(void *hashp)
{
int ret;
return (ret);
}
/*
* Report the dynamic free time on an item.
*/
int
hash_Htime(void *hashp)
{
int ret;
return (ret);
}
/*
* Increase the dynamic free time on an item.
*/
void
{
}
/*
* Set the dynamic free time on an item.
*/
void
{
}
/*
* Delete a data item from the hash table using "hashcode"
* to determine the bucket number, and "compare" and "key" to determine
* its uniqueness.
*
* If the deletion is successful 0 is returned. If a matching entry
* does not exist in the given bucket of the hash table, or some other error
* occurs, -1 is returned and the insertion is not done.
*/
{
return (B_FALSE); /* Entry does not exist */
}
if (temp) {
} else
return (B_TRUE);
}
/*
* Locate and return the data entry associated with the given key.
*
* If the data entry is found, a pointer to it is returned. Otherwise,
* NULL is returned.
*/
{
/*
* Dynamic free increment reference.
*/
if (hold)
}
return (ret);
}
/*
* Reap expired data items, or a random data item from the hash table.
*/
void
{
int rcount;
unsigned i;
rcount = 0;
/*
* Walk the buckets, reaping expired clients.
*/
bucketptr++;
}
/*
* Nothing to be reaped, delete a random element. Note that
* the unhash_data routine will wait for current references
* before deletion.
*/
if (rcount == 0) {
break;
}
}
}
}