// svdhash.h -- CHashPage, CHashFile, CHashTable modules. // // $Id: svdhash.h,v 1.16 2005/10/13 07:38:37 sdennis Exp $ // // MUX 2.4 // Copyright (C) 1998 through 2004 Solid Vertical Domains, Ltd. All // rights not explicitly given are reserved. // #ifndef SVDHASH_H #define SVDHASH_H //#define HP_PROTECTION #define SECTOR_SIZE 512 #define LBUF_BLOCKED (SECTOR_SIZE*((LBUF_SIZE+SECTOR_SIZE-1)/SECTOR_SIZE)) #define HT_SIZEOF_PAGE (1*LBUF_BLOCKED) #define HF_SIZEOF_PAGE (3*LBUF_BLOCKED) extern UINT32 CRC32_ProcessBuffer ( UINT32 ulCrc, const void *pBuffer, unsigned int nBuffer ); extern UINT32 CRC32_ProcessInteger(UINT32 nInteger); extern UINT32 CRC32_ProcessInteger2 ( UINT32 nInteger1, UINT32 nInteger2 ); extern UINT32 HASH_ProcessBuffer ( UINT32 ulHash, const void *arg_pBuffer, size_t nBuffer ); #if _SGI_SOURCE || ((UINT16_MAX_VALUE-2) <= HF_SIZEOF_PAGE) typedef UINT32 UINT_OFFSET; #define UINT_OFFSET_MAX_VALUE UINT32_MAX_VALUE #define EXPAND_TO_BOUNDARY(x) (((x) + 3) & (~3)) #else typedef UINT16 UINT_OFFSET; #define UINT_OFFSET_MAX_VALUE UINT16_MAX_VALUE #define EXPAND_TO_BOUNDARY(x) (((x) + 1) & (~1)) #endif typedef UINT_OFFSET HP_HEAPOFFSET, *HP_PHEAPOFFSET; typedef UINT_OFFSET HP_HEAPLENGTH, *HP_PHEAPLENGTH; typedef UINT_OFFSET HP_DIRINDEX, *HP_PDIRINDEX; #define HP_SIZEOF_HEAPOFFSET sizeof(HP_HEAPOFFSET) #define HP_SIZEOF_HEAPLENGTH sizeof(HP_HEAPLENGTH) #define HP_SIZEOF_DIRINDEX sizeof(HP_DIRINDEX); #pragma pack(1) typedef struct tagHPHeader { UINT32 m_nTotalInsert; UINT32 m_nDirEmptyLeft; UINT32 m_nHashGroup; HP_DIRINDEX m_nDirSize; HP_DIRINDEX m_Primes[16]; HP_HEAPOFFSET m_oFreeList; HP_DIRINDEX m_nDepth; } HP_HEADER, *HP_PHEADER; #define HP_NIL_OFFSET UINT_OFFSET_MAX_VALUE // Possible special values for m_pDirectory[i] // #define HP_DIR_EMPTY UINT_OFFSET_MAX_VALUE #define HP_DIR_DELETED (UINT_OFFSET_MAX_VALUE-1) typedef struct tagHPTrailer { UINT32 m_checksum; } HP_TRAILER, *HP_PTRAILER; typedef struct tagHPHeapNode { HP_HEAPLENGTH nBlockSize; union { HP_HEAPOFFSET oNext; struct { HP_HEAPLENGTH nRecordSize; UINT32 nHash; } s; } u; } HP_HEAPNODE, *HP_PHEAPNODE; #define HP_SIZEOF_HEAPNODE sizeof(HP_HEAPNODE) #pragma pack() #define HP_MIN_HEAP_ALLOC HP_SIZEOF_HEAPNODE typedef unsigned long HF_FILEOFFSET, *HF_PFILEOFFSET; #define HF_SIZEOF_FILEOFFSET sizeof(HF_FILEOFFSET) class CHashPage { private: unsigned char *m_pPage; unsigned int m_nPageSize; HP_PHEADER m_pHeader; HP_PHEAPOFFSET m_pDirectory; unsigned char *m_pHeapStart; unsigned char *m_pHeapEnd; HP_PTRAILER m_pTrailer; int m_iDir; int m_nProbesLeft; UINT32 m_nDirEmptyTrigger; #ifdef HP_PROTECTION bool ValidateAllocatedBlock(UINT32 iDir); bool ValidateFreeBlock(HP_HEAPOFFSET oBlock); bool ValidateFreeList(void); #endif // HP_PROTECTION bool HeapAlloc(HP_DIRINDEX iDir, HP_HEAPLENGTH nRecord, UINT32 nHash, void *pRecord); void SetVariablePointers(void); void SetFixedPointers(void); void GetStats(HP_HEAPLENGTH nExtra, int *pnRecords, HP_HEAPLENGTH *pnAllocatedSize, int *pnGoodDirSize); public: CHashPage(void); bool Allocate(unsigned int nPageSize); ~CHashPage(void); void Empty(HP_DIRINDEX arg_nDepth, UINT32 arg_nHashGroup, HP_DIRINDEX arg_nDirSize); #ifdef HP_PROTECTION void Protection(void); bool Validate(void); #endif // HP_PROTECTION #define HP_INSERT_SUCCESS_DEFRAG 0 #define HP_INSERT_SUCCESS 1 #define HP_INSERT_ERROR_FULL 2 #define HP_INSERT_ERROR_ILLEGAL 3 #define IS_HP_SUCCESS(x) ((x) <= HP_INSERT_SUCCESS) int Insert(HP_HEAPLENGTH nRecord, UINT32 nHash, void *pRecord); HP_DIRINDEX FindFirstKey(UINT32 nHash, unsigned int *numchecks); HP_DIRINDEX FindNextKey(HP_DIRINDEX i, UINT32 nHash, unsigned int *numchecks); HP_DIRINDEX FindFirst(HP_PHEAPLENGTH pnRecord, void *pRecord); HP_DIRINDEX FindNext(HP_PHEAPLENGTH pnRecord, void *pRecord); void HeapCopy(HP_DIRINDEX iDir, HP_PHEAPLENGTH pnRecord, void *pRecord); void HeapFree(HP_DIRINDEX iDir); void HeapUpdate(HP_DIRINDEX iDir, HP_HEAPLENGTH nRecord, void *pRecord); bool WritePage(HANDLE hFile, HF_FILEOFFSET oWhere); bool ReadPage(HANDLE hFile, HF_FILEOFFSET oWhere); HP_DIRINDEX GetDepth(void); bool Split(CHashPage &hp0, CHashPage &hp1); bool Defrag(HP_HEAPLENGTH nExtra); void GetRange(UINT32 arg_nDirDepth, UINT32 &nStart, UINT32 &nEnd); }; #define HF_FIND_FIRST HP_DIR_EMPTY #define HF_FIND_END HP_DIR_EMPTY #define HF_CACHE_EMPTY 0 #define HF_CACHE_CLEAN 1 #define HF_CACHE_UNPROTECTED 2 #define HF_CACHE_UNWRITTEN 3 #define HF_CACHE_NUM_STATES 4 typedef struct tagHashFileCache { CHashPage m_hp; HF_FILEOFFSET m_o; int m_iState; int m_iYounger; int m_iOlder; } HF_CACHE; class CHashFile { private: HANDLE m_hDirFile; HANDLE m_hPageFile; int iCache; int m_iOldest; int m_iLastFlushed; int *m_hpCacheLookup; HF_FILEOFFSET oEndOfFile; unsigned int m_nDir; unsigned int m_nDirDepth; HF_CACHE *m_Cache; int m_nCache; HF_PFILEOFFSET m_pDir; bool DoubleDirectory(void); int AllocateEmptyPage(int nSafe, int Safe[]); int ReadCache(UINT32 iFileDir, int *pHits); bool FlushCache(int iCache); void WriteDirectory(void); bool InitializeDirectory(unsigned int nSize); void ResetAge(int iEntry); void Init(void); void InitCache(int nCachePages); void FinalCache(void); bool CreateFileSet(const char *szDirFile, const char *szPageFile); bool RebuildDirectory(void); bool ReadDirectory(void); public: CHashFile(void); #define HF_OPEN_STATUS_ERROR -1 #define HF_OPEN_STATUS_NEW 0 #define HF_OPEN_STATUS_OLD 1 int Open(const char *szDirFile, const char *szPageFile, int nCachePages); bool Insert(HP_HEAPLENGTH nRecord, UINT32 nHash, void *pRecord); HP_DIRINDEX FindFirstKey(UINT32 nHash); HP_DIRINDEX FindNextKey(HP_DIRINDEX iDir, UINT32 nHash); void Copy(HP_DIRINDEX iDir, HP_PHEAPLENGTH pnRecord, void *pRecord); void Remove(HP_DIRINDEX iDir); void CloseAll(void); void Sync(void); void Tick(void); ~CHashFile(void); }; typedef CHashPage *pCHashPage; class CHashTable { private: unsigned int m_nDir; unsigned int m_nDirDepth; pCHashPage *m_pDir; CHashPage *m_hpLast; unsigned int m_iPage; unsigned int m_nPages; unsigned int m_nEntries; INT64 m_nDeletions; INT64 m_nScans; INT64 m_nHits; INT64 m_nChecks; unsigned int m_nMaxScan; bool DoubleDirectory(void); void Init(void); void Final(void); public: CHashTable(void); void ResetStats(void); void GetStats( unsigned int *hashsize, int *entries, INT64 *deletes, INT64 *scans, INT64 *hits, INT64 *checks, int *max_scan); INT64 GetEntryCount(); void Reset(void); bool Insert(HP_HEAPLENGTH nRecord, UINT32 nHash, void *pRecord); HP_DIRINDEX FindFirstKey(UINT32 nHash); HP_DIRINDEX FindNextKey(HP_DIRINDEX iDir, UINT32 nHash); HP_DIRINDEX FindFirst(HP_PHEAPLENGTH pnRecord, void *pRecord); HP_DIRINDEX FindNext(HP_PHEAPLENGTH pnRecord, void *pRecord); void Copy(HP_DIRINDEX iDir, HP_PHEAPLENGTH pnRecord, void *pRecord); void Remove(HP_DIRINDEX iDir); void Update(HP_DIRINDEX iDir, HP_HEAPLENGTH nRecord, void *pRecord); ~CHashTable(void); }; #define SIZEOF_LOG_BUFFER 1024 class CLogFile { private: CLinearTimeAbsolute m_ltaStarted; #ifdef WIN32 CRITICAL_SECTION csLog; #endif // WIN32 HANDLE m_hFile; size_t m_nSize; size_t m_nBuffer; char m_aBuffer[SIZEOF_LOG_BUFFER]; bool bEnabled; bool bUseStderr; char *m_pBasename; char m_szPrefix[32]; char m_szFilename[SIZEOF_PATHNAME]; void CreateLogFile(void); void AppendLogFile(void); void CloseLogFile(void); public: CLogFile(void); ~CLogFile(void); void WriteBuffer(size_t nString, const char *pString); void WriteString(const char *pString); void WriteInteger(int iNumber); void DCL_CDECL tinyprintf(char *pFormatSpec, ...); void Flush(void); void SetPrefix(const char *pPrefix); void SetBasename(const char *pBasename); void StartLogging(void); void StopLogging(void); }; extern CLogFile Log; #endif //!SVDHASH_H