|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
hash.h
Abstract:
contains prototypes for functions in hash.c
Author:
Paul McDaniel (paulmcd) 28-Apr-2000
Revision History:
--*/
#ifndef _HASH_H_
#define _HASH_H_
//
// The hash key is the file name, but we need to track both the file
// component of the name in addition to the stream component of the name (if
// there is one). The buffer in the FileName UNICODE_STRING contains the
// full name with stream information, but the length is set to just designate
// the file portion of the name.
//
// Note: The keys will be hashed based on the FileName only, not the stream
// portion of the name. This is done so that we can easily find all the
// entries related to a given file if that file has multiple data streams.
//
typedef struct _HASH_KEY {
UNICODE_STRING FileName;
USHORT StreamNameLength; USHORT Reserved;
} HASH_KEY, *PHASH_KEY;
//
// a hash list entry .
//
typedef struct _HASH_ENTRY { //
// the hash value
//
ULONG HashValue; //
// the key
//
HASH_KEY Key; //
// a context stored with this hash entry
//
PVOID pContext; } HASH_ENTRY, *PHASH_ENTRY;
//
// a hash bucket, which is basically an array of hash entries
// sorted by (HashValue, Key.Length, Key.Buffer) .
//
#define IS_VALID_HASH_BUCKET(pObject) \
(((pObject) != NULL) && ((pObject)->Signature == HASH_BUCKET_TAG))
typedef struct _HASH_BUCKET { //
// = HASH_BUCKET_TAG
//
ULONG Signature; ULONG AllocCount; ULONG UsedCount; HASH_ENTRY Entries[0];
} HASH_BUCKET, *PHASH_BUCKET;
#define HASH_ENTRY_DEFAULT_WIDTH 10
//
// a destructor for hash entries
//
typedef VOID (*PHASH_ENTRY_DESTRUCTOR) ( IN PHASH_KEY pKey, IN PVOID pContext );
typedef PVOID (*PHASH_ENTRY_CALLBACK) ( IN PHASH_KEY pKey, IN PVOID pEntryContext, IN PVOID pCallbackContext );
//
// and a hash header, an array of buckets which is hashed into.
//
#define IS_VALID_HASH_HEADER(pObject) \
(((pObject) != NULL) && ((pObject)->Signature == HASH_HEADER_TAG))
typedef struct _HASH_HEADER {
//
// NonPagedPool
//
//
// = HASH_HEADER_TAG
//
ULONG Signature;
//
// the count of buckets the hash table has
//
ULONG BucketCount;
//
// the memory this hash table is taking
//
ULONG UsedLength;
//
// the memory this hash table is allowed to use
//
ULONG AllowedLength;
//
// how many times we've trimmed due to memory
//
ULONG TrimCount; //
// the last time we trim'd
//
LARGE_INTEGER LastTrimTime;
//
// OPTIONAL the length in bytes of the duplicate prefix (if any)
// all keys share in this lists. This will be skipped for all manual
// comparisons as an optimization. this can be 0
//
ULONG PrefixLength;
//
// the lock for this list
//
ERESOURCE Lock; //
// OPTIONAL destructor
//
PHASH_ENTRY_DESTRUCTOR pDestructor;
//
// and the actual buckets
//
PHASH_BUCKET Buckets[0]; } HASH_HEADER, *PHASH_HEADER;
//
// Function Prototypes.
//
NTSTATUS HashCreateList ( IN ULONG BucketCount, IN ULONG AllowedLength, IN ULONG PrefixLength OPTIONAL, IN PHASH_ENTRY_DESTRUCTOR pDestructor OPTIONAL, OUT PHASH_HEADER * ppHashList );
VOID HashDestroyList ( IN PHASH_HEADER pHashList );
NTSTATUS HashAddEntry ( IN PHASH_HEADER pHashList, IN PHASH_KEY pKey, IN PVOID pContext );
NTSTATUS HashFindEntry ( IN PHASH_HEADER pHashList, IN PHASH_KEY pKey, OUT PVOID * ppContext );
VOID HashClearEntries ( IN PHASH_HEADER pHashList );
NTSTATUS HashClearAllFileEntries ( IN PHASH_HEADER pHeader, IN PUNICODE_STRING pFileName );
VOID HashProcessEntries ( IN PHASH_HEADER pHeader, IN PHASH_ENTRY_CALLBACK pfnCallback, IN PVOID pCallbackContext );
#if 0
#define HashCompute(Key) HashScramble(HashUnicodeString((Key)))
__inline ULONG HashUnicodeString( PUNICODE_STRING pKey ) { ULONG Hash = 0; ULONG Index; ULONG CharCount;
CharCount = pKey->Length/sizeof(WCHAR); for (Index = 0 ; Index < CharCount; ++Index) { Hash = 37 * Hash + (pKey->Buffer[Index] & 0xFFDF); } return Hash; }
// Produce a scrambled, randomish number in the range 0 to RANDOM_PRIME-1.
// Applying this to the results of the other hash functions is likely to
// produce a much better distribution, especially for the identity hash
// functions such as Hash(char c), where records will tend to cluster at
// the low end of the hashtable otherwise. LKHash applies this internally
// to all hash signatures for exactly this reason.
__inline ULONG HashScramble(ULONG dwHash) { // Here are 10 primes slightly greater than 10^9
// 1000000007, 1000000009, 1000000021, 1000000033, 1000000087,
// 1000000093, 1000000097, 1000000103, 1000000123, 1000000181.
// default value for "scrambling constant"
const ULONG RANDOM_CONSTANT = 314159269UL; // large prime number, also used for scrambling
const ULONG RANDOM_PRIME = 1000000007UL;
return (RANDOM_CONSTANT * dwHash) % RANDOM_PRIME ; }
#endif // 0
#endif // _HASH_H_
|