CHashFile Class Reference

#include <svdhash.h>

Collaboration diagram for CHashFile:

Collaboration graph
[legend]

Public Member Functions

 CHashFile (void)
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)

Private Member Functions

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)

Private Attributes

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_CACHEm_Cache
int m_nCache
HF_PFILEOFFSET m_pDir

Detailed Description

Definition at line 196 of file svdhash.h.


Constructor & Destructor Documentation

CHashFile::CHashFile ( void   ) 

Definition at line 1281 of file svdhash.cpp.

References Init(), m_Cache, m_nCache, and SeedRandomNumberGenerator().

01282 {
01283     SeedRandomNumberGenerator();
01284     m_Cache = NULL;
01285     m_nCache = 0;
01286     Init();
01287 }

CHashFile::~CHashFile ( void   ) 

Definition at line 1747 of file svdhash.cpp.

References CloseAll(), and FinalCache().

01748 {
01749     FinalCache();
01750     CloseAll();
01751 }


Member Function Documentation

int CHashFile::AllocateEmptyPage ( int  nSafe,
int  Safe[] 
) [private]

Definition at line 2058 of file svdhash.cpp.

References cnt, FlushCache(), CHashPage::GetRange(), HF_CACHE_EMPTY, m_Cache, tagHashFileCache::m_hp, m_hpCacheLookup, m_iOldest, tagHashFileCache::m_iState, m_nCache, m_nDirDepth, and ResetAge().

Referenced by CreateFileSet(), Insert(), ReadCache(), and RebuildDirectory().

02059 {
02060     int cnt = m_nCache;
02061     while (cnt--)
02062     {
02063         int i = m_iOldest;
02064 
02065         bool bExclude = false;
02066         for (int j = 0; j < nSafe; j++)
02067         {
02068             if (Safe[j] == i)
02069             {
02070                 bExclude = true;
02071                 break;
02072             }
02073         }
02074 
02075         ResetAge(i);
02076 
02077         if (  !bExclude
02078            && FlushCache(i))
02079         {
02080             if (HF_CACHE_EMPTY != m_Cache[i].m_iState)
02081             {
02082                 UINT32 nStart, nEnd;
02083                 m_Cache[i].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
02084                 for ( ; nStart <= nEnd; nStart++)
02085                 {
02086                     m_hpCacheLookup[nStart] = -1;
02087                 }
02088                 m_Cache[i].m_iState = HF_CACHE_EMPTY;
02089             }
02090             return i;
02091         }
02092     }
02093     return -1;
02094 }

void CHashFile::CloseAll ( void   ) 

Definition at line 1704 of file svdhash.cpp.

References Init(), INVALID_HANDLE_VALUE, m_hDirFile, m_hPageFile, m_hpCacheLookup, m_pDir, and Sync().

Referenced by cache_close(), CreateFileSet(), Open(), and ~CHashFile().

01705 {
01706     if (m_hPageFile != INVALID_HANDLE_VALUE)
01707     {
01708         Sync();
01709         if (m_pDir)
01710         {
01711             delete [] m_pDir;
01712             m_pDir = NULL;
01713         }
01714         if (m_hpCacheLookup)
01715         {
01716             delete [] m_hpCacheLookup;
01717             m_hpCacheLookup = NULL;
01718         }
01719 
01720 #ifdef WIN32
01721         CloseHandle(m_hPageFile);
01722 #else // WIN32
01723         close(m_hPageFile);
01724 #endif // WIN32
01725     }
01726     if (m_hDirFile != INVALID_HANDLE_VALUE)
01727     {
01728 #ifdef WIN32
01729         CloseHandle(m_hDirFile);
01730 #else // WIN32
01731         close(m_hDirFile);
01732 #endif // WIN32
01733     }
01734     Init();
01735 }

void CHashFile::Copy ( HP_DIRINDEX  iDir,
HP_PHEAPLENGTH  pnRecord,
void *  pRecord 
)

Definition at line 2024 of file svdhash.cpp.

References CHashPage::HeapCopy(), iCache, m_Cache, and tagHashFileCache::m_hp.

Referenced by cache_del(), cache_get(), and cache_put().

02025 {
02026     m_Cache[iCache].m_hp.HeapCopy(iDir, pnRecord, pRecord);
02027 }

bool CHashFile::CreateFileSet ( const char *  szDirFile,
const char *  szPageFile 
) [private]

Definition at line 1374 of file svdhash.cpp.

References AllocateEmptyPage(), CloseAll(), CHashPage::Empty(), FlushCache(), HF_CACHE_UNPROTECTED, HF_SIZEOF_PAGE, iCache, InitializeDirectory(), INVALID_HANDLE_VALUE, m_Cache, m_hDirFile, tagHashFileCache::m_hp, m_hPageFile, m_hpCacheLookup, tagHashFileCache::m_iState, tagHashFileCache::m_o, m_pDir, O_BINARY, oEndOfFile, and WriteDirectory().

Referenced by Open().

01375 {
01376     CloseAll();
01377 #ifdef WIN32
01378     m_hPageFile = CreateFile(szPageFile, GENERIC_READ | GENERIC_WRITE,
01379         FILE_SHARE_READ, 0, CREATE_ALWAYS,
01380         FILE_ATTRIBUTE_NORMAL + FILE_FLAG_RANDOM_ACCESS, NULL);
01381 #else // WIN32
01382     m_hPageFile = open(szPageFile, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, 0600);
01383 #endif // WIN32
01384 
01385     if (m_hPageFile == INVALID_HANDLE_VALUE)
01386     {
01387         return false;
01388     }
01389 
01390 #ifdef WIN32
01391     m_hDirFile = CreateFile(szDirFile, GENERIC_READ | GENERIC_WRITE,
01392         FILE_SHARE_READ, 0, CREATE_ALWAYS,
01393         FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, NULL);
01394 #else // WIN32
01395     m_hDirFile = open(szDirFile, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, 0600);
01396 #endif // WIN32
01397 
01398     if (m_hPageFile == INVALID_HANDLE_VALUE)
01399     {
01400         return false;
01401     }
01402 
01403     // Create empty structures in memory and write them out.
01404     //
01405     if (!InitializeDirectory(2))
01406     {
01407         return false;
01408     }
01409 
01410     iCache = AllocateEmptyPage(0, 0);
01411     if (iCache < 0)
01412     {
01413         return false;
01414     }
01415     m_Cache[iCache].m_hp.Empty(0, 0UL, 100);
01416     m_Cache[iCache].m_o = 0UL;
01417 
01418     m_pDir[0] = m_pDir[1] = m_Cache[iCache].m_o;
01419     m_hpCacheLookup[0] = m_hpCacheLookup[1] = iCache;
01420 
01421     m_Cache[iCache].m_iState = HF_CACHE_UNPROTECTED;
01422 
01423     oEndOfFile = HF_SIZEOF_PAGE;
01424 
01425 #ifdef DO_COMMIT
01426     FlushCache(iCache);
01427 #endif // DO_COMMIT
01428     WriteDirectory();
01429     return true;
01430 }

bool CHashFile::DoubleDirectory ( void   )  [private]

Definition at line 1934 of file svdhash.cpp.

References ISOUTOFMEMORY, m_hpCacheLookup, m_nDir, m_nDirDepth, m_pDir, and WriteDirectory().

Referenced by Insert(), and RebuildDirectory().

01935 {
01936     unsigned int nNewDir     = 2 * m_nDir;
01937     HP_DIRINDEX nNewDirDepth = m_nDirDepth + 1;
01938 
01939     HF_PFILEOFFSET pNewDir = new HF_FILEOFFSET[nNewDir];
01940     ISOUTOFMEMORY(pNewDir);
01941 
01942     int *pNewCacheLookup = new int[nNewDir];
01943     ISOUTOFMEMORY(pNewCacheLookup);
01944 
01945     unsigned int iNewDir = 0;
01946     for (unsigned int iDir = 0; iDir < m_nDir; iDir++)
01947     {
01948         pNewDir[iNewDir]   = m_pDir[iDir];
01949         pNewDir[iNewDir+1] = m_pDir[iDir];
01950         pNewCacheLookup[iNewDir]   = m_hpCacheLookup[iDir];
01951         pNewCacheLookup[iNewDir+1] = m_hpCacheLookup[iDir];
01952         iNewDir += 2;
01953     }
01954 
01955     // Write out the new directory. It's always larger than
01956     // the previous one.
01957     //
01958     WriteDirectory();
01959 
01960     delete [] m_pDir;
01961     m_pDir = pNewDir;
01962 
01963     delete [] m_hpCacheLookup;
01964     m_hpCacheLookup = pNewCacheLookup;
01965 
01966     m_nDirDepth = nNewDirDepth;
01967     m_nDir = nNewDir;
01968     return true;
01969 }

void CHashFile::FinalCache ( void   )  [private]

Definition at line 1737 of file svdhash.cpp.

References m_Cache, and m_nCache.

Referenced by Open(), and ~CHashFile().

01738 {
01739     if (m_Cache)
01740     {
01741         delete [] m_Cache;
01742         m_Cache = NULL;
01743         m_nCache = 0;
01744     }
01745 }

HP_DIRINDEX CHashFile::FindFirstKey ( UINT32  nHash  ) 

Definition at line 1971 of file svdhash.cpp.

References cs_fails, cs_reads, cs_rhits, CHashPage::FindFirstKey(), CHashPage::GetRange(), HF_FIND_END, HP_DIR_EMPTY, iCache, Log, m_Cache, tagHashFileCache::m_hp, m_nDir, m_nDirDepth, ReadCache(), CLogFile::tinyprintf(), and CLogFile::WriteString().

Referenced by cache_del(), cache_get(), and cache_put().

01972 {
01973     cs_reads++;
01974 
01975     UINT32 iFileDir = nHash >> (32-m_nDirDepth);
01976     if (iFileDir >= m_nDir)
01977     {
01978         Log.WriteString("CHashFile::Insert - iFileDir out of range." ENDLINE);
01979         cs_fails++;
01980         return HF_FIND_END;
01981     }
01982     iCache = ReadCache(iFileDir, &cs_rhits);
01983     if (iCache < 0)
01984     {
01985         cs_fails++;
01986         return HF_FIND_END;
01987     }
01988     UINT32 nStart, nEnd;
01989     m_Cache[iCache].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
01990     if (iFileDir < nStart || nEnd < iFileDir)
01991     {
01992         Log.tinyprintf("CHashFile::Find - Directory entry (0x%08X) points to the wrong page (0x%08X-0x%08X)." ENDLINE,
01993             iFileDir, nStart, nEnd);
01994         return HF_FIND_END;
01995     }
01996 
01997     unsigned int numchecks;
01998     HP_DIRINDEX iDir = m_Cache[iCache].m_hp.FindFirstKey(nHash, &numchecks);
01999 
02000     if (iDir == HP_DIR_EMPTY)
02001     {
02002         cs_fails++;
02003         return HF_FIND_END;
02004     }
02005     return iDir;
02006 }

HP_DIRINDEX CHashFile::FindNextKey ( HP_DIRINDEX  iDir,
UINT32  nHash 
)

Definition at line 2008 of file svdhash.cpp.

References cs_fails, cs_reads, CHashPage::FindNextKey(), HF_FIND_END, HP_DIR_EMPTY, iCache, m_Cache, and tagHashFileCache::m_hp.

Referenced by cache_del(), cache_get(), and cache_put().

02009 {
02010     cs_reads++;
02011 
02012     unsigned int numchecks;
02013 
02014     iDir = m_Cache[iCache].m_hp.FindNextKey(iDir, nHash, &numchecks);
02015 
02016     if (iDir == HP_DIR_EMPTY)
02017     {
02018         cs_fails++;
02019         return HF_FIND_END;
02020     }
02021     return iDir;
02022 }

bool CHashFile::FlushCache ( int  iCache  )  [private]

Definition at line 2036 of file svdhash.cpp.

References HF_CACHE_CLEAN, HF_CACHE_UNPROTECTED, HF_CACHE_UNWRITTEN, m_Cache, tagHashFileCache::m_hp, m_hPageFile, and tagHashFileCache::m_o.

Referenced by AllocateEmptyPage(), CreateFileSet(), Insert(), Sync(), and Tick().

02037 {
02038     switch (m_Cache[iCache].m_iState)
02039     {
02040     case HF_CACHE_UNPROTECTED:
02041 #ifdef HP_PROTECTION
02042         m_Cache[iCache].m_hp.Protection();
02043 #endif // HP_PROTECTION
02044 
02045     case HF_CACHE_UNWRITTEN:
02046         if (m_Cache[iCache].m_hp.WritePage(m_hPageFile, m_Cache[iCache].m_o))
02047         {
02048             m_Cache[iCache].m_iState = HF_CACHE_CLEAN;
02049         }
02050         else
02051         {
02052             return false;
02053         }
02054     }
02055     return true;
02056 }

void CHashFile::Init ( void   )  [private]

Definition at line 1289 of file svdhash.cpp.

References iCache, INVALID_HANDLE_VALUE, m_hDirFile, m_hPageFile, m_hpCacheLookup, m_iLastFlushed, m_nDir, m_nDirDepth, and m_pDir.

Referenced by CHashFile(), and CloseAll().

01290 {
01291     m_hDirFile = INVALID_HANDLE_VALUE;
01292     m_hPageFile = INVALID_HANDLE_VALUE;
01293     m_nDir = 0;
01294     m_nDirDepth = 0;
01295     m_pDir = NULL;
01296     m_hpCacheLookup = NULL;
01297     iCache = 0;
01298     m_iLastFlushed = 0;
01299 }

void CHashFile::InitCache ( int  nCachePages  )  [private]

Definition at line 1528 of file svdhash.cpp.

References HF_CACHE_EMPTY, HF_SIZEOF_PAGE, ISOUTOFMEMORY, m_Cache, tagHashFileCache::m_iOlder, m_iOldest, tagHashFileCache::m_iState, tagHashFileCache::m_iYounger, m_nCache, and tagHashFileCache::m_o.

Referenced by Open().

01529 {
01530     if (m_Cache)
01531     {
01532         return;
01533     }
01534 
01535     // Allocate hash page cache.
01536     //
01537     m_nCache = nCachePages;
01538     m_Cache = new HF_CACHE[m_nCache];
01539     ISOUTOFMEMORY(m_Cache);
01540     for (int i = 0; i < m_nCache; i++)
01541     {
01542         m_Cache[i].m_hp.Allocate(HF_SIZEOF_PAGE);
01543         m_Cache[i].m_iState = HF_CACHE_EMPTY;
01544         m_Cache[i].m_o = 0UL;
01545         m_Cache[i].m_iYounger = i-1;
01546         m_Cache[i].m_iOlder   = i+1;
01547     }
01548     m_Cache[0].m_iYounger = m_nCache-1;
01549     m_Cache[m_nCache-1].m_iOlder = 0;
01550     m_iOldest = 0;
01551 }

bool CHashFile::InitializeDirectory ( unsigned int  nSize  )  [private]

Definition at line 1338 of file svdhash.cpp.

References ISOUTOFMEMORY, m_hpCacheLookup, m_nDir, m_nDirDepth, and m_pDir.

Referenced by CreateFileSet(), ReadDirectory(), and RebuildDirectory().

01339 {
01340     if (m_pDir)
01341     {
01342         delete [] m_pDir;
01343         m_pDir = NULL;
01344     }
01345     if (m_hpCacheLookup)
01346     {
01347         delete [] m_hpCacheLookup;
01348         m_hpCacheLookup = NULL;
01349     }
01350 
01351     m_nDir = n;
01352     m_nDirDepth = 0;
01353     n >>= 1;
01354     while (n)
01355     {
01356         m_nDirDepth++;
01357         n >>= 1;
01358     }
01359 
01360     m_pDir = new HF_FILEOFFSET[m_nDir];
01361     ISOUTOFMEMORY(m_pDir);
01362     m_hpCacheLookup = new int[m_nDir];
01363     ISOUTOFMEMORY(m_hpCacheLookup);
01364 
01365     for (unsigned int i = 0; i < m_nDir; i++)
01366     {
01367         m_pDir[i] = 0xFFFFFFFFUL;
01368         m_hpCacheLookup[i] = -1;
01369     }
01370 
01371     return true;
01372 }

bool CHashFile::Insert ( HP_HEAPLENGTH  nRecord,
UINT32  nHash,
void *  pRecord 
)

Definition at line 1753 of file svdhash.cpp.

References AllocateEmptyPage(), statedata::bStandAlone, cs_whits, cs_writes, DoubleDirectory(), statedata::dumping, ENDLOG, FlushCache(), CHashPage::GetRange(), HF_CACHE_EMPTY, HF_CACHE_UNPROTECTED, HF_SIZEOF_PAGE, HP_INSERT_ERROR_ILLEGAL, iCache, CHashPage::Insert(), IS_HP_SUCCESS, Log, LOG_DBSAVES, log_text(), m_Cache, m_hDirFile, tagHashFileCache::m_hp, m_hPageFile, m_hpCacheLookup, tagHashFileCache::m_iState, m_nDir, m_nDirDepth, tagHashFileCache::m_o, m_pDir, mudstate, MuxAlarm, oEndOfFile, ReadCache(), Safe, CMuxAlarm::Sleep(), STARTLOG, time_1s, CLogFile::tinyprintf(), and CLogFile::WriteString().

Referenced by cache_put().

01754 {
01755     cs_writes++;
01756     for (;;)
01757     {
01758         UINT32 iFileDir = nHash >> (32-m_nDirDepth);
01759         if (iFileDir >= m_nDir)
01760         {
01761             Log.WriteString("CHashFile::Insert - iFileDir out of range." ENDLINE);
01762             return false;
01763         }
01764         iCache = ReadCache(iFileDir, &cs_whits);
01765         if (iCache < 0)
01766         {
01767             Log.WriteString("CHashFile::Insert - Page wasn't valid." ENDLINE);
01768             return false;
01769         }
01770 
01771         UINT32 nStart, nEnd;
01772         m_Cache[iCache].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
01773         if (iFileDir < nStart || nEnd < iFileDir)
01774         {
01775             Log.tinyprintf("CHashFile::Insert - Directory entry (0x%08X) points to the wrong page (0x%08X-0x%08X)." ENDLINE,
01776                 iFileDir, nStart, nEnd);
01777             return false;
01778         }
01779         int errInserted = m_Cache[iCache].m_hp.Insert(nRecord, nHash, pRecord);
01780         if (IS_HP_SUCCESS(errInserted))
01781         {
01782             // The record was inserted successfully, so the page is dirty.
01783             //
01784             m_Cache[iCache].m_iState = HF_CACHE_UNPROTECTED;
01785             break;
01786         }
01787         else if (HP_INSERT_ERROR_ILLEGAL == errInserted)
01788         {
01789             return false;
01790         }
01791 
01792 #ifndef WIN32
01793         // First, if we are @dumping, then we have a @forked process
01794         // that is also reading from the file. We must pause and let
01795         // this reader process finish.
01796         //
01797         if (  !mudstate.bStandAlone
01798            && mudstate.dumping)
01799         {
01800             STARTLOG(LOG_DBSAVES, "DMP", "DUMP");
01801             log_text("Waiting on previously-forked child before page-splitting... ");
01802             ENDLOG;
01803             do
01804             {
01805                 // We have a forked dump in progress, so we will wait until the
01806                 // child exits.
01807                 //
01808                 MuxAlarm.Sleep(time_1s);
01809             } while (mudstate.dumping);
01810         }
01811 #endif // !WIN32
01812 
01813         // If the depth of this page is already as deep as the directory
01814         // depth,then we must increase depth of the directory, first.
01815         //
01816         if (m_nDirDepth == m_Cache[iCache].m_hp.GetDepth())
01817         {
01818             if (!DoubleDirectory())
01819             {
01820                 return false;
01821             }
01822         }
01823 
01824         // Split this page into two pages. We become a new one, and we
01825         // are given a pointer to the other one.
01826         //
01827         int Safe[2];
01828         int nSafe = 0;
01829         int iEmpty0, iEmpty1;
01830 
01831         Safe[nSafe++] = iCache;
01832         iEmpty0 = AllocateEmptyPage(nSafe, Safe);
01833         if (iEmpty0 < 0) return false;
01834 
01835         if (iCache == iEmpty0)
01836         {
01837             Log.WriteString("CHashFile::Split - iCache == iEmpty0" ENDLINE);
01838             return false;
01839         }
01840 
01841         Safe[nSafe++] = iEmpty0;
01842         iEmpty1 = AllocateEmptyPage(nSafe, Safe);
01843         if (iEmpty1 < 0) return false;
01844 
01845         if (iCache == iEmpty1)
01846         {
01847             Log.WriteString("CHashFile::Split - iCache == iEmpty1" ENDLINE);
01848             return false;
01849         }
01850 
01851         if (iEmpty0 == iEmpty1)
01852         {
01853             Log.WriteString("CHashFile::Split - iEmpty0 == iEmpty1" ENDLINE);
01854             return false;
01855         }
01856 
01857         if (!m_Cache[iCache].m_hp.Split(m_Cache[iEmpty0].m_hp, m_Cache[iEmpty1].m_hp))
01858         {
01859             return false;
01860         }
01861 
01862         // Tack another page onto the end of the .pag file.
01863         //
01864         long oNew = oEndOfFile;
01865         oEndOfFile += HF_SIZEOF_PAGE;
01866 
01867         // iEmpty0 => iCache. iEmpty1 => end of file
01868         //
01869         m_Cache[iCache].m_iState = HF_CACHE_EMPTY;
01870         m_Cache[iEmpty0].m_o = m_Cache[iCache].m_o;
01871         m_Cache[iEmpty1].m_o = oNew;
01872         m_Cache[iEmpty0].m_iState = HF_CACHE_UNPROTECTED;
01873         m_Cache[iEmpty1].m_iState = HF_CACHE_UNPROTECTED;
01874 
01875         // Update the directory.
01876         //
01877         m_Cache[iEmpty0].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
01878         for ( ; nStart <= nEnd; nStart++)
01879         {
01880             m_hpCacheLookup[nStart] = iEmpty0;
01881         }
01882         m_Cache[iEmpty1].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
01883         for ( ; nStart <= nEnd; nStart++)
01884         {
01885             m_pDir[nStart] = oNew;
01886             m_hpCacheLookup[nStart] = iEmpty1;
01887         }
01888 
01889         // Flush the pages out.
01890         //
01891         FlushCache(iEmpty1);
01892         FlushCache(iEmpty0);
01893 
01894 #ifdef DO_COMMIT
01895         if (!mudstate.bStandAlone)
01896         {
01897 #ifdef WIN32
01898             FlushFileBuffers(m_hPageFile);
01899 #else // WIN32
01900             fsync(m_hPageFile);
01901 #endif // WIN32
01902         }
01903 #endif // DO_COMMIT
01904 
01905         // Write Directory
01906         //
01907 #ifdef WIN32
01908         SetFilePointer(m_hDirFile, 0, 0, FILE_BEGIN);
01909         DWORD nWritten;
01910         WriteFile(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir, &nWritten, 0);
01911 #else // WIN32
01912 #ifdef HAVE_PWRITE
01913         pwrite(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir, 0);
01914 #else
01915         lseek(m_hDirFile, 0, SEEK_SET);
01916         write(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir);
01917 #endif // HAVE_PWRITE
01918 #endif // WIN32
01919 
01920 #ifdef DO_COMMIT
01921         if (!mudstate.bStandAlone)
01922         {
01923 #ifdef WIN32
01924             FlushFileBuffers(m_hDirFile);
01925 #else // WIN32
01926             fsync(m_hDirFile);
01927 #endif // WIN32
01928         }
01929 #endif // DO_COMMIT
01930     }
01931     return true;
01932 }

int CHashFile::Open ( const char *  szDirFile,
const char *  szPageFile,
int  nCachePages 
)

Definition at line 1553 of file svdhash.cpp.

References CloseAll(), CreateFileSet(), FinalCache(), HF_OPEN_STATUS_ERROR, HF_OPEN_STATUS_NEW, HF_OPEN_STATUS_OLD, HF_SIZEOF_PAGE, InitCache(), INVALID_HANDLE_VALUE, m_hDirFile, m_hPageFile, O_BINARY, oEndOfFile, ReadDirectory(), and RebuildDirectory().

Referenced by cache_init(), and main().

01554 {
01555     CloseAll();
01556     FinalCache();
01557     InitCache(nCachePages);
01558 
01559     // First let's try to open the page file. This is the more important file.
01560     //
01561 #ifdef WIN32
01562     m_hPageFile = CreateFile(szPageFile, GENERIC_READ | GENERIC_WRITE,
01563         FILE_SHARE_READ, 0, OPEN_EXISTING,
01564         FILE_ATTRIBUTE_NORMAL + FILE_FLAG_RANDOM_ACCESS, NULL);
01565 #else // WIN32
01566     m_hPageFile = open(szPageFile, O_RDWR|O_BINARY);
01567 #endif // WIN32
01568     if (m_hPageFile == INVALID_HANDLE_VALUE)
01569     {
01570         // The PageFile doesn't exist, so we have'ta create both of them.
01571         //
01572         if (!CreateFileSet(szDirFile, szPageFile))
01573         {
01574             CloseAll();
01575             return HF_OPEN_STATUS_ERROR;
01576         }
01577         return HF_OPEN_STATUS_NEW;
01578     }
01579 
01580     // We have a page file open. Let's check how big it is. If it's
01581     // zero-length, the page file is useless to use, and we need to go through
01582     // the standard creation process. If the size is not a multiple of
01583     // HF_SIZEOF_PAGE, we need to fail.
01584     //
01585 #ifdef WIN32
01586     oEndOfFile = SetFilePointer(m_hPageFile, 0, 0, FILE_END);
01587 #else // WIN32
01588     oEndOfFile = lseek(m_hPageFile, 0, SEEK_END);
01589 #endif // WIN32
01590     if (oEndOfFile == 0xFFFFFFFFUL)
01591     {
01592         CloseAll();
01593         return HF_OPEN_STATUS_ERROR;
01594     }
01595     else if (oEndOfFile == 0UL)
01596     {
01597         // The PageFile exists, but it's zero-length, so we have'ta create
01598         // both of them.
01599         //
01600         if (!CreateFileSet(szDirFile, szPageFile))
01601         {
01602             CloseAll();
01603             return HF_OPEN_STATUS_ERROR;
01604         }
01605         return HF_OPEN_STATUS_NEW;
01606     }
01607     else if ((oEndOfFile % HF_SIZEOF_PAGE) != 0)
01608     {
01609         // This is not a mulitple of HP_SIZEOF_PAGE. Weird unknown format.
01610         //
01611         CloseAll();
01612         return HF_OPEN_STATUS_ERROR;
01613     }
01614 
01615     // Now that the page file appears valid so far, let's see if the directory
01616     // file is there. This file is not strictly necessary, we can rebuild it.
01617     // However, having it helps us to open faster.
01618     //
01619 #ifdef WIN32
01620     m_hDirFile = CreateFile(szDirFile, GENERIC_READ | GENERIC_WRITE,
01621         FILE_SHARE_READ, 0, OPEN_EXISTING,
01622         FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, NULL);
01623 #else // WIN32
01624     m_hDirFile = open(szDirFile, O_RDWR|O_BINARY);
01625 #endif // WIN32
01626     if (m_hDirFile == INVALID_HANDLE_VALUE)
01627     {
01628         // The Directory doesn't exist, so we create it anew, and rebuild the
01629         // index.
01630 #ifdef WIN32
01631         m_hDirFile = CreateFile(szDirFile, GENERIC_READ | GENERIC_WRITE,
01632             FILE_SHARE_READ, 0, CREATE_ALWAYS,
01633             FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, NULL);
01634 #else // WIN32
01635         m_hDirFile = open(szDirFile, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, 0600);
01636 #endif // WIN32
01637 
01638         if (m_hPageFile == INVALID_HANDLE_VALUE)
01639         {
01640             CloseAll();
01641             return HF_OPEN_STATUS_ERROR;
01642         }
01643 
01644         if (!RebuildDirectory())
01645         {
01646             CloseAll();
01647             return HF_OPEN_STATUS_ERROR;
01648         }
01649         return HF_OPEN_STATUS_OLD;
01650     }
01651 
01652     // Read in the directory.
01653     //
01654     if (!ReadDirectory())
01655     {
01656         CloseAll();
01657         return HF_OPEN_STATUS_ERROR;
01658     }
01659     return HF_OPEN_STATUS_OLD;
01660 }

int CHashFile::ReadCache ( UINT32  iFileDir,
int *  pHits 
) [private]

Definition at line 2161 of file svdhash.cpp.

References AllocateEmptyPage(), CHashPage::GetRange(), HF_CACHE_CLEAN, HF_CACHE_EMPTY, iCache, Log, m_Cache, tagHashFileCache::m_hp, m_hPageFile, m_hpCacheLookup, tagHashFileCache::m_iState, m_nDirDepth, m_pDir, ResetAge(), and CLogFile::WriteString().

Referenced by FindFirstKey(), and Insert().

02162 {
02163     int iCache = m_hpCacheLookup[iFileDir];
02164     HF_FILEOFFSET oPage = m_pDir[iFileDir];
02165 
02166     if (  iCache != -1
02167        && m_Cache[iCache].m_iState != HF_CACHE_EMPTY
02168        && m_Cache[iCache].m_o == oPage)
02169     {
02170         ResetAge(iCache);
02171         (*phits)++;
02172         return iCache;
02173     }
02174 
02175     if ((iCache = AllocateEmptyPage(0, NULL)) >= 0)
02176     {
02177         if (m_Cache[iCache].m_hp.ReadPage(m_hPageFile, oPage))
02178         {
02179             //if (m_Cache[i].m_hp.Validate())
02180             //{
02181                 m_Cache[iCache].m_o = oPage;
02182                 m_Cache[iCache].m_iState = HF_CACHE_CLEAN;
02183                 ResetAge(iCache);
02184 
02185                 UINT32 nStart, nEnd;
02186                 m_Cache[iCache].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
02187                 for ( ; nStart <= nEnd; nStart++)
02188                 {
02189                     m_hpCacheLookup[nStart] = iCache;
02190                 }
02191 
02192                 return iCache;
02193             //}
02194         }
02195         else
02196         {
02197             Log.WriteString("CHashFile::ReadCache.  ReadPage failed to get the page. DB DAMAGE." ENDLINE);
02198         }
02199     }
02200     return -1;
02201 }

bool CHashFile::ReadDirectory ( void   )  [private]

Definition at line 1499 of file svdhash.cpp.

References HF_SIZEOF_FILEOFFSET, InitializeDirectory(), m_hDirFile, m_nDir, and m_pDir.

Referenced by Open().

01500 {
01501 #ifdef WIN32
01502     UINT32 cc = SetFilePointer(m_hDirFile, 0, 0, FILE_END);
01503 #else // WIN32
01504     UINT32 cc = lseek(m_hDirFile, 0, SEEK_END);
01505 #endif // WIN32
01506     if (cc == 0xFFFFFFFFUL)
01507     {
01508         return false;
01509     }
01510 
01511     InitializeDirectory(cc / HF_SIZEOF_FILEOFFSET);
01512 
01513 #ifdef WIN32
01514     cc = SetFilePointer(m_hDirFile, 0, 0, FILE_BEGIN);
01515     DWORD nRead;
01516     ReadFile(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir, &nRead, 0);
01517 #else // WIN32
01518 #ifdef HAVE_PREAD
01519     pread(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir, 0);
01520 #else
01521     lseek(m_hDirFile, 0, SEEK_SET);
01522     read(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir);
01523 #endif // HAVE_PREAD
01524 #endif // WIN32
01525     return true;
01526 }

bool CHashFile::RebuildDirectory ( void   )  [private]

Definition at line 1432 of file svdhash.cpp.

References AllocateEmptyPage(), DoubleDirectory(), CHashPage::GetDepth(), CHashPage::GetRange(), HF_CACHE_CLEAN, HF_SIZEOF_PAGE, iCache, InitializeDirectory(), Log, m_Cache, tagHashFileCache::m_hp, m_hPageFile, m_hpCacheLookup, tagHashFileCache::m_iState, m_nDir, m_nDirDepth, m_pDir, oEndOfFile, ResetAge(), WriteDirectory(), and CLogFile::WriteString().

Referenced by Open().

01433 {
01434     // Initialize in-memory page directory
01435     //
01436     if (!InitializeDirectory(2))
01437     {
01438         return false;
01439     }
01440 
01441     // Re-build the directory from CHashPages.
01442     //
01443     for (UINT32 oPage = 0; oPage < oEndOfFile; oPage += HF_SIZEOF_PAGE)
01444     {
01445         int iCache;
01446         if ((iCache = AllocateEmptyPage(0, NULL)) < 0)
01447         {
01448             Log.WriteString("CHashFile::RebuildDirectory.  AllocateEmptyPage failed. DB DAMAGE." ENDLINE);
01449             return false;
01450         }
01451 
01452         if (m_Cache[iCache].m_hp.ReadPage(m_hPageFile, oPage))
01453         {
01454             m_Cache[iCache].m_o = oPage;
01455             m_Cache[iCache].m_iState = HF_CACHE_CLEAN;
01456             ResetAge(iCache);
01457         }
01458         else
01459         {
01460             Log.WriteString("CHashFile::RebuildDirectory.  ReadPage failed to get the page. DB DAMAGE." ENDLINE);
01461         }
01462 
01463         UINT32 nPageDepth = m_Cache[iCache].m_hp.GetDepth();
01464         while (m_nDirDepth < nPageDepth)
01465         {
01466             if (!DoubleDirectory())
01467             {
01468                 return false;
01469             }
01470         }
01471         UINT32 nStart, nEnd;
01472         m_Cache[iCache].m_hp.GetRange(m_nDirDepth, nStart, nEnd);
01473         for ( ; nStart <= nEnd; nStart++)
01474         {
01475             if (m_pDir[nStart] != 0xFFFFFFFFUL)
01476             {
01477                 Log.WriteString("CHashFile::Open - The keyspace of pages in Page File overlap." ENDLINE);
01478                 return false;
01479             }
01480             m_pDir[nStart] = oPage;
01481             m_hpCacheLookup[nStart] = iCache;
01482         }
01483     }
01484 
01485     // Validate that the directory does not have holes.
01486     //
01487     for (UINT32 iFileDir = 0; iFileDir < m_nDir; iFileDir++)
01488     {
01489         if (m_pDir[iFileDir] == 0xFFFFFFFFUL)
01490         {
01491             Log.WriteString("CHashFile::Open - Page File is incomplete." ENDLINE);
01492             return false;
01493         }
01494     }
01495     WriteDirectory();
01496     return true;
01497 }

void CHashFile::Remove ( HP_DIRINDEX  iDir  ) 

Definition at line 2029 of file svdhash.cpp.

References cs_dels, CHashPage::HeapFree(), HF_CACHE_UNPROTECTED, iCache, m_Cache, tagHashFileCache::m_hp, and tagHashFileCache::m_iState.

Referenced by cache_del(), and cache_put().

02030 {
02031     cs_dels++;
02032     m_Cache[iCache].m_hp.HeapFree(iDir);
02033     m_Cache[iCache].m_iState = HF_CACHE_UNPROTECTED;
02034 }

void CHashFile::ResetAge ( int  iEntry  )  [private]

Definition at line 2096 of file svdhash.cpp.

References m_Cache, tagHashFileCache::m_iOlder, m_iOldest, and tagHashFileCache::m_iYounger.

Referenced by AllocateEmptyPage(), ReadCache(), and RebuildDirectory().

02097 {
02098     if (iEntry == m_iOldest)
02099     {
02100         // Rotate the doubly-linked list to make the oldest entry the
02101         // youngest.
02102         //
02103         m_iOldest = m_Cache[m_iOldest].m_iYounger;
02104     }
02105     else if (iEntry == m_Cache[m_iOldest].m_iOlder)
02106     {
02107         // This is already the youngest entry.
02108         //
02109     }
02110     else
02111     {
02112         // Unlink this entry.
02113         //
02114         int iYounger = m_Cache[iEntry].m_iYounger;
02115         int iOlder   = m_Cache[iEntry].m_iOlder;
02116         m_Cache[iYounger].m_iOlder = iOlder;
02117         m_Cache[iOlder].m_iYounger = iYounger;
02118 
02119         // Re-link at the young end of the queue.
02120         //
02121         iYounger = m_iOldest;
02122         iOlder   = m_Cache[iYounger].m_iOlder;
02123         m_Cache[iEntry].m_iOlder   = iOlder;
02124         m_Cache[iEntry].m_iYounger = iYounger;
02125         m_Cache[iYounger].m_iOlder = iEntry;
02126         m_Cache[iOlder].m_iYounger = iEntry;
02127     }
02128 }

void CHashFile::Sync ( void   ) 

Definition at line 1662 of file svdhash.cpp.

References statedata::bStandAlone, cs_syncs, FlushCache(), INVALID_HANDLE_VALUE, Log, m_hDirFile, m_hPageFile, m_nCache, mudstate, and CLogFile::WriteString().

Referenced by cache_sync(), and CloseAll().

01663 {
01664     if (m_hPageFile != INVALID_HANDLE_VALUE)
01665     {
01666         cs_syncs++;
01667         bool bAllFlushed = true;
01668         for (int i = 0; i < m_nCache; i++)
01669         {
01670             if (!FlushCache(i))
01671             {
01672                 bAllFlushed = false;
01673             }
01674         }
01675         if (!bAllFlushed)
01676         {
01677             Log.WriteString("CHashFile::Sync. Could not flush all the pages. DB DAMAGE." ENDLINE);
01678         }
01679 
01680 #ifdef DO_COMMIT
01681         if (!mudstate.bStandAlone)
01682         {
01683 #ifdef WIN32
01684             FlushFileBuffers(m_hPageFile);
01685 #else // WIN32
01686             fsync(m_hPageFile);
01687 #endif // WIN32
01688         }
01689 #endif // DO_COMMIT
01690     }
01691 #ifdef DO_COMMIT
01692     if (  m_hDirFile != INVALID_HANDLE_VALUE
01693        && !mudstate.bStandAlone)
01694     {
01695 #ifdef WIN32
01696         FlushFileBuffers(m_hDirFile);
01697 #else // WIN32
01698         fsync(m_hDirFile);
01699 #endif // WIN32
01700     }
01701 #endif // DO_COMMIT
01702 }

void CHashFile::Tick ( void   ) 

Definition at line 2130 of file svdhash.cpp.

References confdata::cache_tick_period, confdata::check_interval, confdata::dump_interval, FlushCache(), m_iLastFlushed, m_nCache, mudconf, and CLinearTimeDelta::SetSeconds().

Referenced by cache_tick().

02131 {
02132     int nCycle = mudconf.check_interval;
02133     if (mudconf.dump_interval < nCycle)
02134     {
02135         nCycle = mudconf.dump_interval;
02136     }
02137 
02138     CLinearTimeDelta ltdCycle;
02139     ltdCycle.SetSeconds(nCycle);
02140 
02141     int n = (mudconf.cache_tick_period*m_nCache)/ltdCycle;
02142     if (n < 1)
02143     {
02144         n = 1;
02145     }
02146 
02147     for (int i = 0; i < n; i++)
02148     {
02149         // Go ahead and flush a cache entry...just to keep the sync load
02150         // down a bit. This gives the cache time to age, and yet, pushes
02151         // the pages off to the disk eventually and gradually.
02152         //
02153         FlushCache(m_iLastFlushed++);
02154         if (m_iLastFlushed >= m_nCache)
02155         {
02156             m_iLastFlushed = 0;
02157         }
02158     }
02159 }

void CHashFile::WriteDirectory ( void   )  [private]

Definition at line 1318 of file svdhash.cpp.

References statedata::bStandAlone, INVALID_HANDLE_VALUE, m_hDirFile, m_nDir, m_pDir, and mudstate.

Referenced by CreateFileSet(), DoubleDirectory(), and RebuildDirectory().

01319 {
01320     if (m_hDirFile == INVALID_HANDLE_VALUE) return;
01321 
01322 #ifdef HAVE_PWRITE
01323     pwrite(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir, 0);
01324 #else
01325     lseek(m_hDirFile, 0, SEEK_SET);
01326     write(m_hDirFile, m_pDir, sizeof(HF_FILEOFFSET)*m_nDir);
01327 #endif // HAVE_PWRITE
01328     //SetEndOfFile(m_hDirFile);
01329 #ifdef DO_COMMIT
01330     if (!mudstate.bStandAlone)
01331     {
01332         fsync(m_hDirFile);
01333     }
01334 #endif // DO_COMMIT
01335 }


Field Documentation

int CHashFile::iCache [private]

Definition at line 201 of file svdhash.h.

Referenced by Copy(), CreateFileSet(), FindFirstKey(), FindNextKey(), Init(), Insert(), ReadCache(), RebuildDirectory(), and Remove().

HF_CACHE* CHashFile::m_Cache [private]

Definition at line 208 of file svdhash.h.

Referenced by AllocateEmptyPage(), CHashFile(), Copy(), CreateFileSet(), FinalCache(), FindFirstKey(), FindNextKey(), FlushCache(), InitCache(), Insert(), ReadCache(), RebuildDirectory(), Remove(), and ResetAge().

HANDLE CHashFile::m_hDirFile [private]

Definition at line 199 of file svdhash.h.

Referenced by CloseAll(), CreateFileSet(), Init(), Insert(), Open(), ReadDirectory(), Sync(), and WriteDirectory().

HANDLE CHashFile::m_hPageFile [private]

Definition at line 200 of file svdhash.h.

Referenced by CloseAll(), CreateFileSet(), FlushCache(), Init(), Insert(), Open(), ReadCache(), RebuildDirectory(), and Sync().

int* CHashFile::m_hpCacheLookup [private]

Definition at line 204 of file svdhash.h.

Referenced by AllocateEmptyPage(), CloseAll(), CreateFileSet(), DoubleDirectory(), Init(), InitializeDirectory(), Insert(), ReadCache(), and RebuildDirectory().

int CHashFile::m_iLastFlushed [private]

Definition at line 203 of file svdhash.h.

Referenced by Init(), and Tick().

int CHashFile::m_iOldest [private]

Definition at line 202 of file svdhash.h.

Referenced by AllocateEmptyPage(), InitCache(), and ResetAge().

int CHashFile::m_nCache [private]

Definition at line 209 of file svdhash.h.

Referenced by AllocateEmptyPage(), CHashFile(), FinalCache(), InitCache(), Sync(), and Tick().

unsigned int CHashFile::m_nDir [private]

Definition at line 206 of file svdhash.h.

Referenced by DoubleDirectory(), FindFirstKey(), Init(), InitializeDirectory(), Insert(), ReadDirectory(), RebuildDirectory(), and WriteDirectory().

unsigned int CHashFile::m_nDirDepth [private]

Definition at line 207 of file svdhash.h.

Referenced by AllocateEmptyPage(), DoubleDirectory(), FindFirstKey(), Init(), InitializeDirectory(), Insert(), ReadCache(), and RebuildDirectory().

HF_PFILEOFFSET CHashFile::m_pDir [private]

Definition at line 210 of file svdhash.h.

Referenced by CloseAll(), CreateFileSet(), DoubleDirectory(), Init(), InitializeDirectory(), Insert(), ReadCache(), ReadDirectory(), RebuildDirectory(), and WriteDirectory().

HF_FILEOFFSET CHashFile::oEndOfFile [private]

Definition at line 205 of file svdhash.h.

Referenced by CreateFileSet(), Insert(), Open(), and RebuildDirectory().


The documentation for this class was generated from the following files:
Generated on Mon May 28 04:40:24 2007 for MUX by  doxygen 1.4.7