#include <svdhash.h>
Collaboration diagram for CHashFile:
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_CACHE * | m_Cache |
int | m_nCache |
HF_PFILEOFFSET | m_pDir |
Definition at line 196 of file svdhash.h.
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 }
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().
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 }
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] |
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().