// svdhash.h -- CHashPage, CHashFile, CHashTable modules // // $Id: svdhash.h,v 1.4 2000/09/07 08:22:38 sdennis Exp $ // // MUX 2.0 // Copyright (C) 1998 through 2000 Solid Vertical Domains, Ltd. All // rights not explicitly given are reserved. Permission is given to // use this code for building and hosting text-based game servers. // Permission is given to use this code for other non-commercial // purposes. To use this code for commercial purposes other than // building/hosting text-based game servers, contact the author at // Stephen Dennis <sdennis@svdltd.com> for another license. // #ifndef SVDHASH_H #define SVDHASH_H //#define HP_PROTECTION extern unsigned long CRC32_ProcessBuffer ( unsigned long ulCrc, const void *pBuffer, unsigned int nBuffer ); extern unsigned long CRC32_ProcessString(const void *szString); extern unsigned long CRC32_ProcessInteger(unsigned int nInteger); extern unsigned long CRC32_ProcessInteger2(unsigned int nInteger1, unsigned int nInteger2); #ifdef STANDALONE #define HF_PAGES 650 #else #define HF_PAGES 40 #endif #ifdef _SGI_SOURCE #define EXPAND_TO_BOUNDARY(x) (((x) + 3) & (~3)) typedef unsigned int HP_HEAPOFFSET, *HP_PHEAPOFFSET; typedef unsigned int HP_HEAPLENGTH, *HP_PHEAPLENGTH; typedef unsigned int HP_DIRINDEX, *HP_PDIRINDEX; #else #define EXPAND_TO_BOUNDARY(x) (((x) + 1) & (~1)) typedef unsigned short HP_HEAPOFFSET, *HP_PHEAPOFFSET; typedef unsigned short HP_HEAPLENGTH, *HP_PHEAPLENGTH; typedef unsigned short HP_DIRINDEX, *HP_PDIRINDEX; #endif // _SGI_SOURCE #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 { unsigned long m_nTotalInsert; unsigned long m_nDirEmptyLeft; unsigned long 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 0xFFFFU // Possible special values for m_pDirectory[i] // #define HP_DIR_EMPTY 0xFFFFU #define HP_DIR_DELETED 0xFFFEU typedef struct tagHPTrailer { unsigned long m_crc32; } HP_TRAILER, *HP_PTRAILER; typedef struct tagHPHeapNode { HP_HEAPLENGTH nBlockSize; union { HP_HEAPOFFSET oNext; struct { HP_HEAPLENGTH nRecordSize; unsigned long 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; unsigned long m_nDirEmptyTrigger; #ifdef HP_PROTECTION BOOL ValidateAllocatedBlock(unsigned long iDir); BOOL ValidateFreeBlock(HP_HEAPOFFSET oBlock); BOOL ValidateFreeList(void); #endif BOOL HeapAlloc(HP_DIRINDEX iDir, HP_HEAPLENGTH nRecord, unsigned long 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, unsigned long arg_nHashGroup, HP_DIRINDEX arg_nDirSize); #ifdef HP_PROTECTION void Protect(void); BOOL Validate(void); #endif #define HP_INSERT_SUCCESS 0 #define HP_INSERT_ERROR_FULL 1 #define HP_INSERT_ERROR_ILLEGAL 2 int Insert(HP_HEAPLENGTH nRecord, unsigned long nHash, void *pRecord); HP_DIRINDEX FindFirstKey(unsigned long nHash, unsigned int *numchecks); HP_DIRINDEX FindNextKey(HP_DIRINDEX i, unsigned long 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(unsigned long arg_nDirDepth, unsigned long &nStart, unsigned long &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_Age; } HF_CACHE; class CHashFile { private: HANDLE m_hDirFile; HANDLE m_hPageFile; int iCache; int m_iLastEmpty; int m_iLastFlushed; int m_hpCacheLookup[HF_PAGES*2]; int m_iAgeNext; HF_FILEOFFSET oEndOfFile; unsigned int m_nDir; unsigned int m_nDirDepth; HF_CACHE m_Cache[HF_PAGES]; HF_PFILEOFFSET m_pDir; BOOL DoubleDirectory(void); int AllocateEmptyPage(int nSafe, int Safe[]); int ReadCache(HF_FILEOFFSET oPage, int *pHits); BOOL FlushCache(int iCache); void WriteDirectory(void); BOOL EmptyDirectory(void); void Init(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); BOOL Insert(HP_HEAPLENGTH nRecord, unsigned long nHash, void *pRecord); HP_DIRINDEX FindFirstKey(unsigned long nHash); HP_DIRINDEX FindNextKey(HP_DIRINDEX iDir, unsigned long 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; unsigned int m_nDeletions; unsigned int m_nScans; unsigned int m_nHits; unsigned int 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, int *deletes, int *scans, int *hits, int *checks, int *max_scan); void Reset(void); BOOL Insert(HP_HEAPLENGTH nRecord, unsigned long nHash, void *pRecord); HP_DIRINDEX FindFirstKey(unsigned long nHash); HP_DIRINDEX FindNextKey(HP_DIRINDEX iDir, unsigned long 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: #if !defined(STANDALONE) && defined(WIN32) CLinearTimeAbsolute m_ltaStarted; CRITICAL_SECTION csLog; HANDLE m_hFile; int m_nSize; #endif int m_nBuffer; char m_aBuffer[SIZEOF_LOG_BUFFER]; #if !defined(STANDALONE) && defined(WIN32) char m_szPrefix[32]; char m_szFilename[SIZEOF_PATHNAME]; void CreateLogFile(void); void AppendLogFile(void); void CloseLogFile(void); #endif public: CLogFile(void); ~CLogFile(void); void WriteBuffer(int nString, const char *pString); void WriteString(const char *pString); void WriteInteger(int iNumber); void DCL_CDECL printf(char *pFormatSpec, ...); void Flush(void); void ChangePrefix(char *p); }; extern CLogFile Log; #endif