summaryrefslogtreecommitdiff
path: root/plugins/Db3x/src/dbcache3x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Db3x/src/dbcache3x.cpp')
-rw-r--r--plugins/Db3x/src/dbcache3x.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/plugins/Db3x/src/dbcache3x.cpp b/plugins/Db3x/src/dbcache3x.cpp
new file mode 100644
index 0000000000..5688ce0a53
--- /dev/null
+++ b/plugins/Db3x/src/dbcache3x.cpp
@@ -0,0 +1,198 @@
+/*
+
+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
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "commonheaders.h"
+
+int CDb3x::FindSectionForOffset(const DWORD ofs)
+{
+ for (int i = 0; i < CACHESECTIONCOUNT; i++)
+ if (ofs >= cacheSectionInfo[i].ofsBase && ofs<cacheSectionInfo[i].ofsBase + CACHESECTIONSIZE)
+ return i;
+ return -1;
+}
+
+int CDb3x::FindLRUSection(void)
+{
+ int lru = 0;
+ DWORD lowestLastUse = cacheSectionInfo[0].lastUsed;
+ for (int i = 1; i < CACHESECTIONCOUNT; i++)
+ if (cacheSectionInfo[i].lastUsed < lowestLastUse) {
+ lru = i;
+ lowestLastUse = cacheSectionInfo[i].lastUsed;
+ }
+ return lru;
+}
+
+void CDb3x::LoadSection(const int i,DWORD ofs)
+{
+ cacheSectionInfo[i].ofsBase = ofs - ofs%CACHESECTIONSIZE;
+ log1("readsect %08x",ofs);
+ SetFilePointer(m_hDbFile,cacheSectionInfo[i].ofsBase,NULL,FILE_BEGIN);
+ ReadFile(m_hDbFile,m_pDbCache+i*CACHESECTIONSIZE,CACHESECTIONSIZE,&ofs,NULL);
+}
+
+void CDb3x::MoveSection(int *sectId,int dest)
+{
+ CopyMemory(m_pDbCache+dest*CACHESECTIONSIZE,m_pDbCache+(*sectId)*CACHESECTIONSIZE,CACHESECTIONSIZE);
+ cacheSectionInfo[dest].ofsBase = cacheSectionInfo[*sectId].ofsBase;
+ *sectId = dest;
+}
+
+//we are assumed to be in a mutex here
+PBYTE CDb3x::DBRead(DWORD ofs,int bytesRequired,int *bytesAvail)
+{
+ int part1sect = FindSectionForOffset(ofs);
+ if (ofs%CACHESECTIONSIZE+bytesRequired<CACHESECTIONSIZE) {
+ //only one section required
+ if (part1sect == -1) {
+ part1sect = FindLRUSection();
+ LoadSection(part1sect,ofs);
+ }
+ cacheSectionInfo[part1sect].lastUsed = ++m_lastUseCounter;
+ if (bytesAvail!= NULL) *bytesAvail = cacheSectionInfo[part1sect].ofsBase+CACHESECTIONSIZE-ofs;
+ return m_pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
+ }
+ //two sections are required
+ int part2sect = FindSectionForOffset(ofs+CACHESECTIONSIZE);
+ if (part1sect != -1) {
+ if (part2sect == -1) { //first part in cache, but not second part
+ if (part1sect == CACHESECTIONCOUNT-1) MoveSection(&part1sect,0);
+ LoadSection(part1sect+1,ofs+CACHESECTIONSIZE);
+ }
+ else if (part2sect!= part1sect+1) { //both parts are in cache, but not already consecutive
+ if (part1sect == CACHESECTIONCOUNT-1) {
+ //first part is at end, move to before second part
+ if (part2sect == 0) //second part is at start: need to move both
+ MoveSection(&part2sect,1);
+ MoveSection(&part1sect,part2sect-1);
+ }
+ else //move second part to after first part
+ MoveSection(&part2sect,part1sect+1);
+ }
+ }
+ else {
+ if (part2sect == -1) { //neither section is in cache
+ part1sect = 0; part2sect = 1;
+ LoadSection(part1sect,ofs); LoadSection(part2sect,ofs+CACHESECTIONSIZE);
+ }
+ else { //part 2 is in cache, but not part 1
+ if (part2sect == 0) MoveSection(&part2sect,1);
+ part1sect = part2sect-1;
+ LoadSection(part1sect,ofs);
+ }
+ }
+
+ //both sections are now consecutive, starting at part1sect
+ cacheSectionInfo[part1sect].lastUsed = ++m_lastUseCounter;
+ cacheSectionInfo[part1sect+1].lastUsed = ++m_lastUseCounter;
+ if (bytesAvail!= NULL)
+ *bytesAvail = cacheSectionInfo[part1sect+1].ofsBase+CACHESECTIONSIZE-ofs;
+ return m_pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
+}
+
+//we are assumed to be in a mutex here
+void CDb3x::DBWrite(DWORD ofs,PVOID pData,int bytes)
+{
+ //write direct, and rely on Windows' write caching
+ log2("write %d@%08x", bytes, ofs);
+ SetFilePointer(m_hDbFile, ofs, NULL, FILE_BEGIN);
+
+ DWORD bytesWritten;
+ if ( WriteFile(m_hDbFile, pData, bytes, &bytesWritten, NULL) == 0)
+ DatabaseCorruption( _T("%s (Write error)"));
+
+ logg();
+
+ //check if any of the cache sections contain this bit
+ for(int i = 0; i < CACHESECTIONCOUNT; i++) {
+ if (ofs+bytes >= cacheSectionInfo[i].ofsBase && ofs<cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) {
+ if (ofs<cacheSectionInfo[i].ofsBase) { //don't start at beginning
+ if (ofs+bytes >= cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE) //don't finish at end
+ CopyMemory(m_pDbCache+i*CACHESECTIONSIZE,(PBYTE)pData+cacheSectionInfo[i].ofsBase-ofs,CACHESECTIONSIZE);
+ else CopyMemory(m_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(m_pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,cacheSectionInfo[i].ofsBase+CACHESECTIONSIZE-ofs);
+ else CopyMemory(m_pDbCache+i*CACHESECTIONSIZE+ofs-cacheSectionInfo[i].ofsBase,pData,bytes);
+ }
+ }
+ }
+}
+
+void CDb3x::DBMoveChunk(DWORD ofsDest,DWORD ofsSource,int bytes)
+{
+ DWORD bytesRead;
+ PBYTE buf;
+
+ log3("move %d %08x->%08x",bytes,ofsSource,ofsDest);
+ buf = (PBYTE)mir_alloc(bytes);
+ SetFilePointer(m_hDbFile,ofsSource,NULL,FILE_BEGIN);
+ ReadFile(m_hDbFile,buf,bytes,&bytesRead,NULL);
+ DBWrite(ofsDest,buf,bytes);
+ mir_free(buf);
+ logg();
+}
+
+static VOID CALLBACK DoBufferFlushTimerProc(HWND hwnd,UINT message,UINT_PTR idEvent,DWORD dwTime)
+{
+ for (int i=0; i < g_Dbs.getCount(); i++) {
+ CDb3x* db = g_Dbs[i];
+
+ KillTimer(NULL, db->m_flushBuffersTimerId);
+ log0("tflush1");
+ FlushFileBuffers(db->getFile());
+ log0("tflush2");
+ }
+}
+
+void CDb3x::DBFlush(int setting)
+{
+ if (!setting) {
+ log0("nflush1");
+ if (m_safetyMode) FlushFileBuffers(m_hDbFile);
+ log0("nflush2");
+ return;
+ }
+ KillTimer(NULL,m_flushBuffersTimerId);
+ m_flushBuffersTimerId = SetTimer(NULL,m_flushBuffersTimerId,50,DoBufferFlushTimerProc);
+}
+
+void CDb3x::DBFill(DWORD ofs,int bytes)
+{
+}
+
+int CDb3x::InitCache(void)
+{
+ m_pDbCache = (PBYTE)mir_alloc(CACHESECTIONSIZE*CACHESECTIONCOUNT);
+ m_lastUseCounter = CACHESECTIONCOUNT;
+ for(int i = 0; i < CACHESECTIONCOUNT; i++) {
+ cacheSectionInfo[i].ofsBase = 0;
+ cacheSectionInfo[i].lastUsed = i;
+ SetFilePointer(m_hDbFile,cacheSectionInfo[i].ofsBase,NULL,FILE_BEGIN);
+
+ DWORD bytesRead;
+ ReadFile(m_hDbFile,m_pDbCache+i*CACHESECTIONSIZE,CACHESECTIONSIZE,&bytesRead,NULL);
+ }
+ return 0;
+}