jhash.h, rpmhash.c: switch to Jenkins One-at-a-time hash

This commit is contained in:
Alexey Tourbin 2009-03-25 10:52:02 +03:00
parent 6a9eae99c7
commit 6d4fea769d
7 changed files with 99 additions and 29 deletions

View File

@ -1525,7 +1525,7 @@ int rpmRunTransactions( rpmTransactionSet ts,
int i, j;
int ourrc = 0;
struct availablePackage * alp;
int totalFileCount = 0;
unsigned int totalFileCount = 0;
hashTable ht;
TFI_t fi;
struct diskspaceInfo * dip;
@ -1773,7 +1773,7 @@ int rpmRunTransactions( rpmTransactionSet ts,
#endif
}
ht = htCreate(totalFileCount * 2, fpHashFunction, fpEqual);
ht = htCreate(totalFileCount, fpHashFunction, fpEqual);
fpc = fpCacheCreate(totalFileCount);
/* ===============================================

View File

@ -16,7 +16,7 @@ LIBPOPT = @LIBPOPT@
pkgincdir = $(pkgincludedir)
pkginc_HEADERS = hdrinline.h rpmdb.h
noinst_HEADERS = falloc.h fprint.h rpmhash.h
noinst_HEADERS = falloc.h fprint.h rpmhash.h jhash.h
mylibpaths = -L$(top_builddir)/lib/.libs
mylibs = -lrpm

View File

@ -10,12 +10,12 @@
#include "fprint.h"
#include "debug.h"
fingerPrintCache fpCacheCreate(int sizeHint)
fingerPrintCache fpCacheCreate(unsigned int size)
{
fingerPrintCache fpc;
fpc = xmalloc(sizeof(*fpc));
fpc->ht = htCreate(sizeHint * 2, hashFunctionString, hashEqualityString);
fpc->ht = htCreate(size, hashFunctionString, hashEqualityString);
return fpc;
}

View File

@ -87,10 +87,10 @@ int rpmdbFindFpList(/*@null@*/ rpmdb db, fingerPrint * fpList,
/**
* Create finger print cache.
* @param sizeHint number of elements expected
* @param size number of elements expected
* @return pointer to initialized fingerprint cache
*/
/*@only@*/ fingerPrintCache fpCacheCreate(int sizeHint)
/*@only@*/ fingerPrintCache fpCacheCreate(unsigned int size)
/*@*/;
/**

80
rpmdb/jhash.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef JHASH_H_
#define JHASH_H_
/*
* Jenkins One-at-a-time hash.
* http://burtleburtle.net/bob/hash/doobs.html
* Also used in perl, see PERL_HASH in hv.h.
*/
static inline
unsigned int jhashStringAppend(const char *str, unsigned int hash)
{
const char *p = str;
while (*p) {
hash += *p++;
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
static inline
unsigned int jhashDataAppend(const void *data, unsigned int len,
unsigned int hash)
{
const char *p = data;
while (len--) {
hash += *p++;
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
static inline
unsigned int jhashInit(void)
{
/* The golden ratio really is an arbitrary value.
* Its purpose is to avoid mapping all zeros to all zeros. */
return 0x9e3779b9;
}
static inline
unsigned int jhashString(const char *str)
{
return jhashStringAppend(str, jhashInit());
}
static inline
unsigned int jhashData(const void *data, unsigned int len)
{
return jhashDataAppend(data, len, jhashInit());
}
/*
* The best hash table sizes are powers of 2.
*/
static inline
unsigned int jhashSize(unsigned int size)
{
if (size < 16)
return 8;
/* 640K ought to be enough for anybody. */
if (size >= (1 << 20))
return (1 << 20);
/* Round down to proper power of 2.
* See Perl_hv_ksplit in hv.c. */
while ((size & (1 + ~size)) != size)
size &= ~(size & (1 + ~size));
return size;
}
#endif

View File

@ -8,6 +8,8 @@
#include "rpmhash.h"
#include "debug.h"
#include "jhash.h"
typedef struct hashBucket_s * hashBucket;
/**
@ -22,7 +24,7 @@ struct hashBucket_s {
/**
*/
struct hashTable_s {
int numBuckets; /*!< number of hash buckets */
unsigned int numBuckets; /*!< number of hash buckets */
hashBucket * buckets; /*!< hash bucket array */
hashFunctionType fn; /*!< generate hash value for key */
hashEqualityType eq; /*!< compare hash keys for equality */
@ -42,7 +44,7 @@ hashBucket findEntry(hashTable ht, const void * key)
hashBucket b;
/*@-modunconnomods@*/
hash = ht->fn(key) % ht->numBuckets;
hash = ht->fn(key) & (ht->numBuckets - 1);
b = ht->buckets[hash];
while (b && b->key && ht->eq(b->key, key))
@ -59,30 +61,18 @@ int hashEqualityString(const void * key1, const void * key2)
return strcmp(k1, k2);
}
unsigned int hashFunctionString(const void * string)
unsigned int hashFunctionString(const void *str)
{
char xorValue = 0;
char sum = 0;
short len;
int i;
const char * chp = string;
len = strlen(string);
for (i = 0; i < len; i++, chp++) {
xorValue ^= *chp;
sum += *chp;
}
return ((((unsigned)len) << 16) + (((unsigned)sum) << 8) + xorValue);
return jhashString(str);
}
hashTable htCreate(int numBuckets, hashFunctionType fn, hashEqualityType eq)
hashTable htCreate(unsigned int size, hashFunctionType fn, hashEqualityType eq)
{
hashTable ht;
ht = xmalloc(sizeof(*ht));
ht->numBuckets = numBuckets;
ht->buckets = xcalloc(numBuckets, sizeof(*ht->buckets));
ht->numBuckets = jhashSize(size);
ht->buckets = xcalloc(ht->numBuckets, sizeof(*ht->buckets));
/*@-assignexpose@*/
ht->fn = fn;
ht->eq = eq;
@ -93,7 +83,7 @@ hashTable htCreate(int numBuckets, hashFunctionType fn, hashEqualityType eq)
void htAddEntry(hashTable ht, const void * key, const void * data)
{
unsigned int hash = ht->fn(key) % ht->numBuckets;
unsigned int hash = ht->fn(key) & (ht->numBuckets - 1);
hashBucket b = ht->buckets[hash];
hashBucket *b_addr = ht->buckets + hash;

View File

@ -46,12 +46,12 @@ typedef void *(*hashFreeDataType) (const void *data);
/**
* Create hash table.
* @param numBuckets number of hash buckets
* @param size number of elements expected
* @param fn function to generate hash value for key
* @param eq function to compare hash keys for equality
* @return pointer to initialized hash table
*/
hashTable htCreate(int numBuckets, hashFunctionType fn, hashEqualityType eq)
hashTable htCreate(unsigned int size, hashFunctionType fn, hashEqualityType eq)
/*@*/;
/**