From 0d489da11220c272765fcc64d390be6bb50ff87f Mon Sep 17 00:00:00 2001 From: sje Date: Fri, 27 Jul 2007 15:27:25 +0000 Subject: based on mmap git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@302 4f64403b-2f21-0410-a795-97e2b3489a10 --- db3x_autobackups/dbcache.c | 248 ++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 138 deletions(-) (limited to 'db3x_autobackups/dbcache.c') diff --git a/db3x_autobackups/dbcache.c b/db3x_autobackups/dbcache.c index dd3bc5a..601670d 100644 --- a/db3x_autobackups/dbcache.c +++ b/db3x_autobackups/dbcache.c @@ -2,8 +2,8 @@ Miranda IM: the free IM client for Microsoft* Windows* -Copyright 2000-2003 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people +Copyright 2000-2003 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people listed in contributors.txt. This program is free software; you can redistribute it and/or @@ -22,165 +22,124 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "commonheaders.h" -#include "database.h" +BOOL safetyMode = TRUE; +static int flushBuffersTimerId; -#define CACHESECTIONSIZE 4096 -#define CACHESECTIONCOUNT 32 - -extern HANDLE hDbFile; -extern CRITICAL_SECTION csDbAccess; +static PBYTE pNull = 0; +static PBYTE pDbCache = NULL; +static HANDLE hMap = NULL; +static DWORD dwFileSize = 0; +static DWORD ChunkSize = 65536; -static BOOL safetyMode=TRUE; -static PBYTE pDbCache; -static DWORD lastUseCounter; -struct DBCacheSectionInfo { - DWORD ofsBase; - DWORD lastUsed; -} static cacheSectionInfo[CACHESECTIONCOUNT]; -static __inline int FindSectionForOffset(const DWORD ofs) +void Map() { - int i; - for(i=0;i=cacheSectionInfo[i].ofsBase && ofs ChunkSize) + { + if ((needed + dwFileSize) - dbHeader.ofsFileEnd > ChunkSize) + DatabaseCorruption("%s (Too large increment)"); + else + { + DWORD x = dbHeader.ofsFileEnd/ChunkSize; + dwFileSize = (x+1)*ChunkSize; + } + } + else + dwFileSize += ChunkSize; + +// FlushViewOfFile(pDbCache, 0); + UnmapViewOfFile(pDbCache); + pDbCache = NULL; + CloseHandle(hMap); + + Map(); } +void DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes) +{ + int x = 0; + log3("move %d %08x->%08x",bytes,ofsSource,ofsDest); + if (ofsDest+bytes>dwFileSize) ReMap(ofsDest+bytes-dwFileSize); + if (ofsSource+bytes>dwFileSize) { + x = ofsSource+bytes-dwFileSize; + log0("buggy move!"); + _ASSERT(0); + } + if (x > 0) + ZeroMemory(pDbCache+ofsDest+bytes-x, x); + if (ofsSource < dwFileSize) + MoveMemory(pDbCache+ofsDest,pDbCache+ofsSource, bytes-x); + logg(); +} //we are assumed to be in a mutex here PBYTE DBRead(DWORD ofs,int bytesRequired,int *bytesAvail) { - - int part1sect; - int part2sect; - - - part1sect = FindSectionForOffset(ofs); - if (ofs%CACHESECTIONSIZE+bytesRequired=dwFileSize) { + log2("read from outside %d@%08x",bytesRequired,ofs); + if (bytesAvail!=NULL) *bytesAvail = ChunkSize; + return pNull; } - //both sections are now consecutive, starting at part1sect - cacheSectionInfo[part1sect].lastUsed=++lastUseCounter; - cacheSectionInfo[part1sect+1].lastUsed=++lastUseCounter; - if(bytesAvail!=NULL) *bytesAvail=cacheSectionInfo[part1sect+1].ofsBase+CACHESECTIONSIZE-ofs; - return pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase); + log3((ofs+bytesRequired>dwFileSize)?"read %d@%08x, only %d avaliable":"read %d@%08x",bytesRequired,ofs,dwFileSize-ofs); + if (bytesAvail!=NULL) *bytesAvail = dwFileSize - ofs; + return pDbCache+ofs; } - - //we are assumed to be in a mutex here void DBWrite(DWORD ofs,PVOID pData,int bytes) { - //write direct, and rely on Windows' write caching - DWORD bytesWritten; - int i; - log2("write %d@%08x",bytes,ofs); - SetFilePointer(hDbFile,ofs,NULL,FILE_BEGIN); - if (WriteFile(hDbFile,pData,bytes,&bytesWritten,NULL)==0) - { - DatabaseCorruption(); - } + if (ofs+bytes>dwFileSize) ReMap(ofs+bytes-dwFileSize); + MoveMemory(pDbCache+ofs,pData,bytes); logg(); - //check if any of the cache sections contain this bit - for(i=0;i=cacheSectionInfo[i].ofsBase && ofs=cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) //don't finish at end - CopyMemory(pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,CACHESECTIONSIZE); - else CopyMemory(pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,bytes-(cacheSectionInfo[i].ofsBase-ofs)); - } - else { //start at beginning - if(ofs+bytes>=cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) //don't finish at end - CopyMemory(pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE-ofs); - else CopyMemory(pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,bytes); - } - } - } } -void DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes) +//we are assumed to be in a mutex here +void DBFill(DWORD ofs,int bytes) { - DWORD bytesRead; - PBYTE buf; - - log3("move %d %08x->%08x",bytes,ofsSource,ofsDest); - buf=(PBYTE)mir_alloc(bytes); - SetFilePointer(hDbFile,ofsSource,NULL,FILE_BEGIN); - ReadFile(hDbFile,buf,bytes,&bytesRead,NULL); - DBWrite(ofsDest,buf,bytes); - mir_free(buf); + log2("zerofill %d@%08x",bytes,ofs); + if (ofs+bytes<=dwFileSize) + ZeroMemory(pDbCache+ofs,bytes); logg(); } -static int flushBuffersTimerId; static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime) { + if (!pDbCache) return; + KillTimer(NULL,flushBuffersTimerId); log0("tflush1"); - FlushFileBuffers(hDbFile); + if (FlushViewOfFile(pDbCache, 0) == 0) + DatabaseCorruption(NULL); log0("tflush2"); } @@ -188,7 +147,10 @@ void DBFlush(int setting) { if(!setting) { log0("nflush1"); - if(safetyMode) FlushFileBuffers(hDbFile); + if(safetyMode && pDbCache) { + if (FlushViewOfFile(pDbCache, 0) == 0) + DatabaseCorruption(NULL); + } log0("nflush2"); return; } @@ -201,29 +163,39 @@ static int CacheSetSafetyMode(WPARAM wParam,LPARAM lParam) EnterCriticalSection(&csDbAccess); safetyMode=wParam; LeaveCriticalSection(&csDbAccess); - if(safetyMode) FlushFileBuffers(hDbFile); + DBFlush(1); return 0; } int InitCache(void) { - int i; - DWORD bytesRead; - + DWORD x; + SYSTEM_INFO sinf; + + GetSystemInfo(&sinf); + ChunkSize = sinf.dwAllocationGranularity; + + dwFileSize = GetFileSize(hDbFile, NULL); + + // Align to chunk + x = dwFileSize % ChunkSize; + if (x) dwFileSize += ChunkSize - x; + + Map(); + + // zero region for reads outside the file + pNull = calloc(ChunkSize,1); + CreateServiceFunction(MS_DB_SETSAFETYMODE,CacheSetSafetyMode); - pDbCache=(PBYTE)mir_alloc(CACHESECTIONSIZE*CACHESECTIONCOUNT); - lastUseCounter=CACHESECTIONCOUNT; - for(i=0;i