/*++ 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_