From 7aff1e4cb053394db57c2814d5fe1e6493e0cc75 Mon Sep 17 00:00:00 2001 From: watcherhd Date: Sat, 26 Nov 2011 14:19:43 +0000 Subject: Project folders rename part 2 git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@214 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- Dbx_tree/FileAccess.cpp | 299 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 Dbx_tree/FileAccess.cpp (limited to 'Dbx_tree/FileAccess.cpp') diff --git a/Dbx_tree/FileAccess.cpp b/Dbx_tree/FileAccess.cpp new file mode 100644 index 0000000..a0aa85a --- /dev/null +++ b/Dbx_tree/FileAccess.cpp @@ -0,0 +1,299 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +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 "FileAccess.h" +#include +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#define _time32 time +#endif +#include "Logger.h" + +const uint8_t CFileAccess::cJournalSignature[20] = "Miranda IM Journal!"; + +CFileAccess::CFileAccess(const TCHAR* FileName) +{ + m_FileName = new TCHAR[_tcslen(FileName) + 1]; + m_Journal.FileName = new TCHAR[_tcslen(FileName) + 5]; + _tcscpy_s(m_FileName, _tcslen(FileName) + 1, FileName); + _tcscpy_s(m_Journal.FileName, _tcslen(FileName) + 5, FileName); + _tcscat_s(m_Journal.FileName, _tcslen(FileName) + 5, _T(".jrn")); + + m_ReadOnly = false; + m_LastSize = 0; + m_Size = 0; + m_Journal.Use = false; + m_Journal.hFile = 0; + m_Journal.BufUse = 0; + + m_LastAllocTime = _time32(NULL); +} + +CFileAccess::~CFileAccess() +{ + CloseHandle(m_Journal.hFile); + DeleteFile(m_Journal.FileName); + + delete [] m_FileName; + delete [] m_Journal.FileName; +} + +uint32_t CFileAccess::Size(uint32_t NewSize) +{ + m_Size = NewSize; + if (!m_Journal.Use) + { + NewSize = (NewSize + m_AllocGranularity - 1) & ~(m_AllocGranularity - 1); + + if (NewSize == 0) + NewSize = m_AllocGranularity; + + if (NewSize != m_AllocSize) + { + m_AllocSize = _SetSize(NewSize); + + // adapt Alloc Granularity + uint32_t t = _time32(NULL); + uint32_t d = t - m_LastAllocTime; + m_LastAllocTime = t; + + if (d < 30) // increase alloc stepping + { + if (m_AllocGranularity < m_MaxAllocGranularity) + m_AllocGranularity = m_AllocGranularity << 1; + } else if (d > 120) // decrease alloc stepping + { + if (m_AllocGranularity > m_MinAllocGranularity) + m_AllocGranularity = m_AllocGranularity >> 1; + } + } + } + return NewSize; +} + + +void CFileAccess::CleanJournal() +{ + SetFilePointer(m_Journal.hFile, 0, NULL, FILE_BEGIN); + SetEndOfFile(m_Journal.hFile); + + DWORD written; + WriteFile(m_Journal.hFile, cJournalSignature, sizeof(cJournalSignature), &written, NULL); +} + +void CFileAccess::ProcessJournal() +{ + uint32_t filesize = GetFileSize(m_Journal.hFile, NULL) - sizeof(cJournalSignature); + SetFilePointer(m_Journal.hFile, sizeof(cJournalSignature), NULL, FILE_BEGIN); + + uint8_t* buf = (uint8_t*)malloc(filesize); + TJournalEntry* e = (TJournalEntry*)buf; + DWORD read = 0; + if (!ReadFile(m_Journal.hFile, buf, filesize, &read, NULL) || (read != filesize)) + { + free(buf); + LOGSYS(logCRITICAL, _T("Couldn't flush the journal because ReadFile failed!")); + return; + } + + m_Journal.Use = false; + std::vector currentops; + + while (filesize >= sizeof(TJournalEntry)) + { + switch (e->Signature) + { + case 'fini': + { + Size(e->Size); + + std::vector::iterator i = currentops.begin(); + while (i != currentops.end()) + { + switch ((*i)->Signature) + { + case 'writ': + { + if ((*i)->Address + (*i)->Size <= m_AllocSize) + { + _Write(*i + 1, (*i)->Address, (*i)->Size); + } else if ((*i)->Address < m_AllocSize) + { + _Write(*i + 1, (*i)->Address, m_AllocSize - (*i)->Address); + } + } break; + case 'inva': + { + if ((*i)->Address + (*i)->Size <= m_AllocSize) + { + _Invalidate((*i)->Address, (*i)->Size); + } else if ((*i)->Address < m_AllocSize) + { + _Invalidate((*i)->Address, m_AllocSize - (*i)->Address); + } + } break; + } + ++i; + } + currentops.clear(); + + e++; + filesize = filesize - sizeof(TJournalEntry); + } break; + case 'writ': + { + if (filesize < sizeof(e) + e->Size) + { + filesize = 0; + } else { + currentops.push_back(e); + filesize = filesize - sizeof(TJournalEntry) - e->Size; + e = (TJournalEntry*)((uint8_t*)e + sizeof(TJournalEntry) + e->Size); + } + } break; + case 'inva': + { + if (filesize < sizeof(e)) + { + filesize = 0; + } else { + currentops.push_back(e); + e++; + filesize = filesize - sizeof(TJournalEntry); + } + } break; + default: + { + filesize = 0; + if (currentops.size()) + LOG(logWARNING, _T("Your database journal wasn't completely written to disk.")); + } break; + } + } + + _Flush(); + + CleanJournal(); + + free(buf); + m_Journal.Use = true; +} + +void CFileAccess::InitJournal() +{ + m_Journal.hFile = CreateFile(m_Journal.FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (m_Journal.hFile == INVALID_HANDLE_VALUE) + { + LOGSYS(logCRITICAL, _T("CreateFile failed on Journal %s"), m_Journal.FileName); + return; + } + + uint8_t h[sizeof(cJournalSignature)]; + DWORD read; + if (ReadFile(m_Journal.hFile, &h, sizeof(h), &read, NULL) && (read == sizeof(h)) && (0 == memcmp(h, cJournalSignature, sizeof(h)))) + { + TCHAR * bckname = new TCHAR[_tcslen(m_FileName) + 12]; + _tcscpy_s(bckname, _tcslen(m_FileName) + 12, m_FileName); + _tcscat_s(bckname, _tcslen(m_FileName) + 12, _T(".autobackup")); + + TCHAR * bckjrnname = new TCHAR[_tcslen(m_Journal.FileName) + 12]; + _tcscpy_s(bckjrnname, _tcslen(m_Journal.FileName) + 12, m_Journal.FileName); + _tcscat_s(bckjrnname, _tcslen(m_Journal.FileName) + 12, _T(".autobackup")); + + char buf[4096]; + HANDLE hfilebackup = CreateFile(bckname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hfilebackup) + { + uint32_t i = 0; + while (i + sizeof(buf) <= m_AllocSize) + { + DWORD w; + _Read(buf, i, sizeof(buf)); + i += sizeof(buf); + WriteFile(hfilebackup, buf, sizeof(buf), &w, NULL); + } + if (i < m_AllocSize) + { + DWORD w; + _Read(buf, i, m_AllocSize - i); + WriteFile(hfilebackup, buf, m_AllocSize - i, &w, NULL); + } + + CloseHandle(hfilebackup); + } + + HANDLE hjrnfilebackup = CreateFile(bckjrnname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hjrnfilebackup) + { + uint32_t i = 0; + + uint32_t filesize = GetFileSize(m_Journal.hFile, NULL); + SetFilePointer(m_Journal.hFile, 0, NULL, FILE_BEGIN); + + while (i + sizeof(buf) <= filesize) + { + DWORD w, r; + ReadFile(m_Journal.hFile, buf, sizeof(buf), &r, NULL); + i += sizeof(buf); + WriteFile(hjrnfilebackup, buf, sizeof(buf), &w, NULL); + } + if (i < filesize) + { + DWORD w, r; + ReadFile(m_Journal.hFile, buf, filesize - i, &r, NULL); + WriteFile(hjrnfilebackup, buf, filesize - i, &w, NULL); + } + CloseHandle(hjrnfilebackup); + } + + TCHAR* path = bckname; + TCHAR* fn = _tcsrchr(m_Journal.FileName, _T('\\')); + TCHAR* bfn = _tcsrchr(bckname, _T('\\')); + TCHAR* jrn = _tcsrchr(bckjrnname, _T('\\')); + if (bfn) // truncate path var + *bfn = 0; + + if (hfilebackup || hjrnfilebackup) + { + LOG(logWARNING, + _T("Journal \"%s\" was found on start.\nBackup \"%s\"%s created and backup \"%s\"%s created.\nYou may delete these file(s) after successful start from \"%s\"."), + fn?fn+1:m_Journal.FileName, + bfn?bfn+1:bckname, (hfilebackup!=INVALID_HANDLE_VALUE)?_T(" was successfully"):_T(" could not be"), + jrn?jrn+1:bckjrnname, (hjrnfilebackup!=INVALID_HANDLE_VALUE)?_T(" was successfully"):_T(" could not be"), + path); + } else { + LOG(logWARNING, + _T("Journal \"%s\" was found on start.\nBackups \"%s\"and \"%s\" could not be created in \"%s\"."), + fn?fn+1:m_Journal.FileName, + bfn?bfn+1:bckname, + jrn?jrn+1:bckjrnname, + path); + } + + delete [] bckname; + delete [] bckjrnname; + + ProcessJournal(); + } + + CleanJournal(); +} -- cgit v1.2.3