// 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