diff options
Diffstat (limited to 'plugins/Dbx_tree/src/BlockManager.cpp')
-rw-r--r-- | plugins/Dbx_tree/src/BlockManager.cpp | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/plugins/Dbx_tree/src/BlockManager.cpp b/plugins/Dbx_tree/src/BlockManager.cpp deleted file mode 100644 index b6a7d22feb..0000000000 --- a/plugins/Dbx_tree/src/BlockManager.cpp +++ /dev/null @@ -1,963 +0,0 @@ -/*
-
-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 "Interface.h"
-#include "BlockManager.h"
-#include "Logger.h"
-
-CBlockManager::CBlockManager(
- CFileAccess & FileAccess,
- CEncryptionManager & EncryptionManager
- )
-: m_BlockSync(),
- m_FileAccess(FileAccess),
- m_EncryptionManager(EncryptionManager),
- m_BlockTable(1024),
- m_FreeBlocks()
-{
- m_Optimize.Thread = NULL;
- m_Optimize.Source = 0;
- m_Optimize.Dest = 0;
-
- m_CacheInfo.Growth = 0;
- m_CacheInfo.Size = 0;
- m_CacheInfo.LastPurge = time(NULL);
-
- m_PendingHead = NULL;
- m_PendingTail = NULL;
- m_PendingLast = NULL;
- m_LastFlush = time(NULL);
- m_BytesPending = 20;
- m_FirstFreeIndex = 0;
-
- m_SaveMode = true;
- m_ReadOnly = m_FileAccess.ReadOnly();
-
- memset(m_Cache, 0, sizeof(m_Cache));
-}
-
-CBlockManager::~CBlockManager()
-{
- m_BlockSync.BeginWrite();
- if (m_Optimize.Thread)
- {
- m_Optimize.Thread->FreeOnTerminate(false);
- m_Optimize.Thread->Terminate();
-
- m_BlockSync.EndWrite();
- m_Optimize.Thread->WaitFor();
-
- delete m_Optimize.Thread;
- } else {
- m_BlockSync.EndWrite();
- }
-
- _PendingFlush(true);
-
- for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++)
- {
- TCacheEntry * i = m_Cache[buddy];
- while (i)
- {
- free(i->Cache);
-
- TCacheEntry * tmp = i;
- i = i->Next;
- free(tmp);
- }
- }
-}
-
-// Optimize File Size
-void CBlockManager::ExecuteOptimize()
-{ /*
- TBlockHeadFree h = {0,0};
- uint8_t * buf = (uint8_t*)malloc(1 << 18); // 256kb
- uint32_t bufuse = 0;
- uint32_t bufsize = 1 << 18;
- uint32_t lastflush = 0;
-
- {
- int i = 0;
- while (!m_Optimize.Thread->Terminated() && (i < 600))
- {
- ++i;
- Sleep(100); // wait for Miranda to start
- }
- }
-
- TransactionBeginWrite();
-
- while (!m_Optimize.Thread->Terminated() && (m_Optimize.Source < m_FileAccess.Size()) && !m_ReadOnly)
- {
- m_FileAccess.Read(&h, m_Optimize.Source, sizeof(h));
- if (h.ID == cFreeBlockID)
- {
- _RemoveFreeBlock(m_Optimize.Source, h.Size);
-
- m_Optimize.Source += h.Size;
- } else {
-
- if (bufsize < bufuse + h.Size)
- {
- buf = (uint8_t*)realloc(buf, bufuse + h.Size);
- bufsize = bufuse + h.Size;
- }
- m_FileAccess.Read(buf + bufuse, m_Optimize.Source, h.Size);
-
- m_BlockTable[h.ID >> 2].Addr = (m_Optimize.Dest + bufuse) >> 2;
-
- m_Optimize.Source += h.Size;
- bufuse += h.Size;
- }
-
- if ((m_BlockSync.Waiting() > 0)
- || (bufuse + 1024 >= bufsize)
- || (m_Optimize.Source >= m_FileAccess.Size())) // buffer is nearly full or EOF
- {
- if (m_Optimize.Dest != m_Optimize.Source) // move blocks
- {
- TBlockHeadFree h = {cFreeBlockID, m_Optimize.Source - m_Optimize.Dest};
- TBlockTailFree t = {m_Optimize.Source - m_Optimize.Dest, cFreeBlockID};
-
- m_FileAccess.Write(buf, m_Optimize.Dest, bufuse);
-
- m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h));
- m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t));
- m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t));
-
- if (m_SaveMode)
- {
- m_FileAccess.CloseTransaction();
- m_FileAccess.Flush();
- m_FileAccess.UseJournal(false);
-
- m_FileAccess.Write(buf, m_Optimize.Dest, bufuse);
-
- m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h));
- m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t));
- m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t));
-
- m_FileAccess.Flush();
- m_FileAccess.CleanJournal();
- m_FileAccess.UseJournal(true);
- }
-
- m_Optimize.Dest += bufuse;
- bufuse = 0;
- }
-
- if (m_BlockSync.Waiting() > 0)
- {
- unsigned int w = m_BlockSync.Waiting();
- m_BlockSync.EndWrite();
- Sleep(w * 64 + 1);
- m_BlockSync.BeginWrite();
- m_FileAccess.UseJournal(m_SaveMode);
- }
- }
- }
-
- if (m_Optimize.Source >= m_FileAccess.Size())
- m_FileAccess.Size(m_Optimize.Dest);
-
- m_Optimize.Thread = NULL;
- m_Optimize.Source = 0;
- m_Optimize.Dest = 0;
- if (m_SaveMode)
- TransactionEndWrite();
- else
- m_BlockSync.EndWrite();
-
- free(buf); */
-
- m_Optimize.Thread = NULL;
-}
-
-inline void CBlockManager::_PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache)
-{
- TPendingOperation * p = NULL;
- if (BlockID == cFreeBlockID)
- {
- p = (TPendingOperation*)malloc(sizeof(TPendingOperation));
-
- p->BlockID = cFreeBlockID;
- p->Addr = Addr;
- p->Size = Size;
- p->CacheEntry = NULL;
- p->EncryptionBuffer = NULL;
-
- m_BytesPending += 24 + sizeof(TBlockHeadFree) + sizeof(TBlockTailFree);
- if (Addr & cPendingInvalidate)
- m_BytesPending += 12;
-
- } else {
- if (Cache->Pending)
- {
- p = Cache->Pending;
- _PendingRemove(Cache->Pending, false);
- } else {
- p = (TPendingOperation*)malloc(sizeof(TPendingOperation));
- }
-
- p->BlockID = BlockID;
- p->Addr = Addr;
- p->Size = Size;
- p->CacheEntry = Cache;
- p->EncryptionBuffer = NULL;
-
- m_BytesPending += 12 + Size;
-
- Cache->Pending = p;
- }
-
- p->Next = NULL;
- p->Prev = m_PendingTail;
- if (m_PendingTail)
- m_PendingTail->Next = p;
-
- m_PendingTail = p;
- if (!m_PendingHead)
- m_PendingHead = p;
-}
-
-inline void CBlockManager::_PendingRemove(TPendingOperation * Pending, bool Free)
-{
- if (Pending->Prev)
- Pending->Prev->Next = Pending->Next;
- else
- m_PendingHead = Pending->Next;
-
- if (Pending->Next)
- Pending->Next->Prev = Pending->Prev;
- else
- m_PendingTail = Pending->Prev;
-
- free(Pending->EncryptionBuffer);
-
- if (m_PendingLast == Pending)
- m_PendingLast = Pending->Prev;
-
- Pending->CacheEntry->Pending = NULL;
- if (Free)
- free(Pending);
-}
-
-inline void CBlockManager::_PendingFlush(bool FullFlush)
-{
- TPendingOperation * i = NULL;
-
- if (m_ReadOnly)
- return;
-
- if (FullFlush)
- {
- if (m_SaveMode)
- {
- _PendingFlush(false); // write to journal
- m_FileAccess.Flush();
- m_FileAccess.UseJournal(false);
- m_FileAccess.Size(m_FileAccess.Size()); // resize real file
- } else {
- m_FileAccess.UseJournal(false);
- }
-
- i = m_PendingHead;
- } else if (m_PendingLast)
- {
- i = m_PendingLast->Next;
- m_FileAccess.UseJournal(m_SaveMode);
- } else {
- i = m_PendingHead;
- m_FileAccess.UseJournal(m_SaveMode);
- }
-
- while (i)
- {
- if (i->BlockID == cFreeBlockID)
- {
- uint32_t addr = i->Addr & ~cPendingInvalidate;
- if (addr + i->Size <= m_FileAccess.Size())
- {
- TBlockHeadFree h = {cFreeBlockID, i->Size};
- TBlockTailFree t = {i->Size, cFreeBlockID};
-
- m_FileAccess.Write(&h, addr, sizeof(h));
- if (i->Addr & cPendingInvalidate)
- m_FileAccess.Invalidate(addr + sizeof(h), i->Size - sizeof(h) - sizeof(t));
- m_FileAccess.Write(&t, addr + i->Size - sizeof(t), sizeof(t));
- }
-
- } else {
-
- if (i->BlockID && !i->EncryptionBuffer && m_EncryptionManager.IsEncrypted(i->BlockID))
- {
- i->EncryptionBuffer = (TBlockHeadOcc*) malloc(i->Size);
- memcpy(i->EncryptionBuffer, i->CacheEntry->Cache, i->Size);
- m_EncryptionManager.Encrypt(i->EncryptionBuffer + 1, i->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), i->BlockID, 0);
- }
-
- if (i->EncryptionBuffer)
- {
- m_FileAccess.Write(i->EncryptionBuffer, i->Addr, i->Size);
- } else {
- m_FileAccess.Write(i->CacheEntry->Cache, i->Addr, i->Size);
- }
- }
-
- i = i->Next;
- } // while
-
- if (FullFlush)
- {
- m_FileAccess.Flush();
- if (m_SaveMode)
- m_FileAccess.CleanJournal();
-
- m_BytesPending = 20;
- m_LastFlush = time(NULL);
-
- i = m_PendingHead;
- while (i)
- {
- free(i->EncryptionBuffer);
-
- if (i->CacheEntry)
- i->CacheEntry->Pending = NULL;
-
- TPendingOperation * tmp = i;
- i = i->Next;
- free(tmp);
- }
- m_PendingHead = NULL;
- m_PendingTail = NULL;
- m_PendingLast = NULL;
- } else {
- m_PendingLast = m_PendingTail;
- m_FileAccess.CloseTransaction();
- }
-}
-
-inline CBlockManager::TCacheEntry * CBlockManager::_CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual)
-{
- TCacheEntry * res;
- uint32_t myidx = ROR_32(Idx, cCacheBuddyBits);
-
- res = (TCacheEntry *)malloc(sizeof(TCacheEntry));
- res->Cache = Cache;
- res->Pending = NULL;
- res->Idx = myidx;
- res->Forced = Virtual;
-
- TCacheEntry * volatile * last = &m_Cache[Idx % cCacheBuddyCount];
- TCacheEntry * i;
- do {
- i = *last;
-
- while (i && (i->Idx < myidx))
- {
- last = &i->Next;
- i = i->Next;
- }
-
- if (i && (i->Idx == myidx))
- {
- free(res);
- free(Cache);
-
- i->LastUse = time(NULL) >> 2;
- return i;
- }
-
- res->Next = i;
-
- } while (i != CMPXCHG_Ptr(*last, res, i));
-
- res->LastUse = time(NULL) >> 2;
-
- m_BlockTable[Idx].InCache = true;
- if (!Virtual)
- XADD_32(m_CacheInfo.Growth, res->Cache->Size);
-
- return res;
-}
-
-inline CBlockManager::TCacheEntry * CBlockManager::_CacheFind(uint32_t Idx)
-{
- TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount];
- uint32_t myidx = ROR_32(Idx, cCacheBuddyBits);
- while (i && (i->Idx < myidx))
- i = i->Next;
-
- if (i && (i->Idx == myidx))
- return i;
- else
- return NULL;
-}
-
-inline void CBlockManager::_CacheErase(uint32_t Idx)
-{
- TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount];
- TCacheEntry * volatile * l = &m_Cache[Idx % cCacheBuddyCount];
-
- uint32_t myidx = ROR_32(Idx, cCacheBuddyBits);
-
- while (i->Idx < myidx)
- {
- l = &i->Next;
- i = i->Next;
- }
- *l = i->Next;
-
- free(i->Cache);
- free(i);
-}
-
-inline void CBlockManager::_CachePurge()
-{
- _PendingFlush(true);
-
- uint32_t ts = time(NULL);
- if (m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) {
- ts = ts - (ts - m_CacheInfo.LastPurge) * cCachePurgeSize / (m_CacheInfo.Size + 2 * m_CacheInfo.Growth);
- } else if (m_CacheInfo.Growth > m_CacheInfo.Size)
- {
- ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Size / m_CacheInfo.Growth;
- } else if (m_CacheInfo.Size > m_CacheInfo.Growth)
- {
- ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Growth / m_CacheInfo.Size;
- } else {
- ts = m_CacheInfo.LastPurge;
- }
-
- m_CacheInfo.Size += m_CacheInfo.Growth;
- m_CacheInfo.Growth = 0;
- m_CacheInfo.LastPurge = time(NULL);
-
- for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++)
- {
- TCacheEntry * i = m_Cache[buddy];
- TCacheEntry * volatile * l = &m_Cache[buddy];
-
- while (i)
- {
- if (!i->Forced && !i->KeepInCache && i->Idx && ((i->LastUse << 2) < ts))
- {
- uint32_t idx = ROL_32(i->Idx, cCacheBuddyBits);
- m_CacheInfo.Size -= i->Cache->Size;
- m_BlockTable[idx].InCache = false;
- free(i->Cache);
-
- *l = i->Next;
- TCacheEntry * tmp = i;
- i = i->Next;
- free(tmp);
-
- } else {
- l = &i->Next;
- i = i->Next;
- }
- }
- }
-}
-
-inline uint32_t CBlockManager::_GetAvailableIndex()
-{
- uint32_t id;
- if (m_FirstFreeIndex)
- {
- id = m_FirstFreeIndex;
- m_FirstFreeIndex = m_BlockTable[id].Addr;
- TBlockTableEntry b = {false, false, 0};
- m_BlockTable[id] = b;
- } else {
- id = static_cast<uint32_t>(m_BlockTable.size());
- if (id > (1 << 12))
- m_BlockTable.resize(id + (1 << 12));
- else
- m_BlockTable.resize(id * 2);
-
- for (uint32_t i = static_cast<uint32_t>(m_BlockTable.size() - 1); i > id; --i)
- {
- TBlockTableEntry b = {true, true, m_FirstFreeIndex};
- m_BlockTable[i] = b;
- m_FirstFreeIndex = i;
- }
- }
- return id;
-}
-
-inline void CBlockManager::_InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse)
-{
- if (Addr + Size == m_FileAccess.Size())
- {
- if (Reuse) // in FindFreePosition we would want to use that block
- m_FileAccess.Size(Addr);
- } else {
-
- if (Reuse)
- m_FreeBlocks.insert(std::make_pair(Size, Addr));
-
- if (!m_ReadOnly)
- _PendingAdd(cFreeBlockID, InvalidateData ? Addr | cPendingInvalidate : Addr, Size, NULL);
-
- }
-}
-
-inline void CBlockManager::_RemoveFreeBlock(uint32_t Addr, uint32_t Size)
-{
- TFreeBlockMap::iterator i = m_FreeBlocks.find(Size);
- while ((i != m_FreeBlocks.end()) && (i->first == Size))
- {
- if (i->second == Addr)
- {
- m_FreeBlocks.erase(i);
- i = m_FreeBlocks.end();
- } else {
- ++i;
- }
- }
-}
-
-inline uint32_t CBlockManager::_FindFreePosition(uint32_t Size)
-{
- // try to find free block
- TFreeBlockMap::iterator f;
- TFreeBlockMap::iterator e = m_FreeBlocks.end();
-
- if (m_FreeBlocks.size())
- {
- f = m_FreeBlocks.find(Size);
- if (f == e)
- {
- if (m_FreeBlocks.rbegin()->first > Size * 2)
- {
- f = m_FreeBlocks.end();
- --f;
- }
- }
- } else {
- f = e;
- }
-
- uint32_t addr = 0;
-
- if (f == e) // no block found - expand file
- {
- addr = m_FileAccess.Size();
- m_FileAccess.Size(addr + Size);
-
- } else {
- addr = f->second;
-
- if (f->first != Size)
- {
- _InsertFreeBlock(addr + Size, f->first - Size, false, true);
- }
- _InsertFreeBlock(addr, Size, false, false);
-
- m_FreeBlocks.erase(f);
- }
-
- return addr;
-}
-
-inline bool CBlockManager::_InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache)
-{
- if (!BlockID || (BlockID & 3) || ((BlockID >> 2) >= m_BlockTable.size()))
- return false;
-
- uint32_t idx = BlockID >> 2;
- TBlockTableEntry dat = m_BlockTable[idx];
-
- if (dat.Deleted) // deleted or FreeIDList item
- return false;
-
- Addr = dat.Addr << 2;
- if (dat.InCache)
- {
- Cache = _CacheFind(idx);
- } else if (Addr)
- {
- TBlockHeadOcc h;
-
- m_FileAccess.Read(&h, Addr, sizeof(h));
-
- TBlockHeadOcc * block = (TBlockHeadOcc *) malloc(h.Size);
- m_FileAccess.Read(block, Addr, h.Size);
-
- m_EncryptionManager.Decrypt(block + 1, h.Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), BlockID, 0);
-
- Cache = _CacheInsert(idx, block, false);
- } else {
- return false;
- }
-
- return Cache != NULL;
-}
-
-inline void CBlockManager::_UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr)
-{
- CacheEntry->KeepInCache = m_ReadOnly;
-
- if (!CacheEntry->Forced)
- {
- if (!m_ReadOnly)
- _PendingAdd(BlockID, Addr, CacheEntry->Cache->Size, CacheEntry);
- }
-}
-
-
-uint32_t CBlockManager::ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize)
-{
- TBlockHeadOcc h, lasth = {0, 0, 0};
- uint32_t p;
- uint32_t res = 0;
- bool invalidateblock = false;
-
- p = FirstBlockStart;
- m_FirstBlockStart = FirstBlockStart;
- m_Optimize.Source = 0;
- m_Optimize.Dest = 0;
-
- { // insert header cache element
- void * header = malloc(FirstBlockStart);
- m_FileAccess.Read(header, 0, FirstBlockStart);
- _CacheInsert(0, (TBlockHeadOcc*)header, false);
- }
-
- TransactionBeginWrite();
-
- while (p < FileSize)
- {
- m_FileAccess.Read(&h, p, sizeof(h));
- if (CLogger::Instance().Level() >= CLogger::logERROR || !h.Size)
- {
- LOG(logCRITICAL, _T("Block-structure of file is corrupt!"));
- return 0;
- }
-
- if (h.ID == cFreeBlockID)
- {
- if (m_Optimize.Dest == 0)
- m_Optimize.Dest = p;
-
- if (lasth.ID == cFreeBlockID)
- {
- lasth.Size += h.Size;
- invalidateblock = true;
- } else {
- lasth = h;
- }
-
- } else {
-
- if (lasth.ID == cFreeBlockID)
- {
- if (m_Optimize.Source == 0)
- m_Optimize.Source = p;
-
- _InsertFreeBlock(p - lasth.Size, lasth.Size, invalidateblock, true);
- }
- lasth = h;
- invalidateblock = false;
-
- while ((h.ID >> 2) >= m_BlockTable.size())
- m_BlockTable.resize(m_BlockTable.size() << 1);
-
- m_BlockTable[h.ID >> 2].Addr = p >> 2;
-
- if (h.Signature == HeaderSignature)
- res = h.ID;
- }
-
- p = p + h.Size;
- }
-
- m_FirstFreeIndex = 0;
- for (uint32_t i = static_cast<uint32_t>(m_BlockTable.size() - 1); i > 0; --i)
- {
- if (m_BlockTable[i].Addr == 0)
- {
- TBlockTableEntry b = {true, true, m_FirstFreeIndex};
- m_BlockTable[i] = b;
- m_FirstFreeIndex = i;
- }
- }
-
- TransactionEndWrite();
-
- if (m_Optimize.Source && !m_FileAccess.ReadOnly())
- {
- m_Optimize.Thread = new COptimizeThread(*this);
- m_Optimize.Thread->Priority(CThread::tpLowest);
- m_Optimize.Thread->FreeOnTerminate(true);
- m_Optimize.Thread->Resume();
- }
-
- return res;
-}
-
-void * CBlockManager::_CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size)
-{
- uint32_t idx = _GetAvailableIndex();
- BlockID = idx << 2;
-
- Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes
-
- TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature};
- TBlockTailOcc t = {BlockID};
-
- TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t));
- *block = h;
- memset(block + 1, 0, Size);
- *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t;
-
- TCacheEntry * ce = _CacheInsert(idx, block, false);
-
- if (m_ReadOnly)
- {
- TBlockTableEntry b = {false, true, 0};
- m_BlockTable[idx] = b;
- } else {
- uint32_t addr = _FindFreePosition(Size + sizeof(h) + sizeof(t));
- TBlockTableEntry b = {false, true, addr >> 2 };
- m_BlockTable[idx] = b;
-
- _UpdateBlock(BlockID, ce, addr);
- }
-
- return ce->Cache + 1;
-}
-
-void * CBlockManager::_CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size)
-{
- uint32_t idx = _GetAvailableIndex();
- BlockID = idx << 2;
-
- Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes
-
- TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature};
- TBlockTailOcc t = {BlockID};
-
- TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t));
- *block = h;
- memset(block + 1, 0, Size);
- *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t;
-
- return _CacheInsert(idx, block, true)->Cache + 1;
-}
-
-bool CBlockManager::DeleteBlock(uint32_t BlockID)
-{
- uint32_t idx = BlockID >> 2;
- uint32_t addr;
- uint32_t size;
- TCacheEntry * ce;
- if (!_InitOperation(BlockID, addr, ce))
- return false;
-
- if (!ce->Forced)
- XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size);
-
- if (ce->Pending)
- _PendingRemove(ce->Pending, true);
-
- size = ce->Cache->Size;
- _CacheErase(idx);
-
- if (addr == 0) // Block in memory only
- {
- TBlockTableEntry b = {false, false, 0};
- m_BlockTable[idx] = b;
-
- } else if (m_ReadOnly)
- {
- m_BlockTable[idx].Deleted = true;
- m_BlockTable[idx].InCache = false;
- } else {
- _InsertFreeBlock(addr, size, true, true);
-
- TBlockTableEntry b = {false, false, 0};
- m_BlockTable[idx] = b;
- }
-
- return true;
-}
-
-uint32_t CBlockManager::_ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size)
-{
- uint32_t idx = BlockID >> 2;
- uint32_t addr;
- TCacheEntry * ce;
-
- if (Size == 0)
- return 0;
-
- if (!_InitOperation(BlockID, addr, ce))
- return 0;
-
- Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes
-
- uint32_t os = ce->Cache->Size;
- uint32_t ns = Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc);
- if (ns == ce->Cache->Size)
- {
- Buffer = ce->Cache + 1;
- return Size;
- }
-
- ce->Cache = (TBlockHeadOcc*) realloc(ce->Cache, ns);
- ce->Cache->Size = ns;
- TBlockTailOcc t = {BlockID};
- *(TBlockTailOcc*)(((uint8_t*)(ce->Cache + 1)) + Size) = t;
- XADD_32(m_CacheInfo.Size, ns - os);
-
- Buffer = ce->Cache + 1;
- ce->KeepInCache = m_ReadOnly;
-
- if (!m_ReadOnly && addr)
- {
- _InsertFreeBlock(addr, os, true, true);
- addr = _FindFreePosition(ns);
- m_BlockTable[idx].Addr = addr >> 2;
-
- _UpdateBlock(BlockID, ce, addr); // write down
- }
-
- return Size;
-}
-
-bool CBlockManager::IsForcedVirtual(uint32_t BlockID)
-{
- TCacheEntry * ce = _CacheFind(BlockID >> 2);
- return ce && ce->Forced;
-}
-
-bool CBlockManager::WriteBlockToDisk(uint32_t BlockID)
-{
- uint32_t addr;
- TCacheEntry * ce;
-
- if (!_InitOperation(BlockID, addr, ce))
- return false;
-
- if (!ce->Forced)
- return true;
-
- ce->Forced = false;
- XADD_32(m_CacheInfo.Size, ce->Cache->Size);
-
- if (!m_ReadOnly)
- {
- addr = _FindFreePosition(ce->Cache->Size);
- m_BlockTable[BlockID >> 2].Addr = addr >> 2;
- _UpdateBlock(BlockID, ce, addr);
- }
- return true;
-}
-
-bool CBlockManager::MakeBlockVirtual(uint32_t BlockID)
-{
- uint32_t addr;
- TCacheEntry * ce;
-
- if (!_InitOperation(BlockID, addr, ce))
- return false;
-
- if (ce->Forced)
- return true;
-
- if (ce->Pending) // don't write down, we kill it anyway
- _PendingRemove(ce->Pending, true);
-
- ce->Forced = true;
- XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size);
-
- if (!m_ReadOnly)
- {
- _InsertFreeBlock(addr, ce->Cache->Size, true, true);
- m_BlockTable[BlockID >> 2].Addr = 0;
- }
- return true;
-}
-
-void * CBlockManager::_ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature)
-{
- uint32_t addr;
- TCacheEntry * ce;
-
- if ((BlockID == 0) && (Signature == -1))
- {
- Size = m_FirstBlockStart;
- return m_Cache[0]->Cache;
- }
-
- if (!_InitOperation(BlockID, addr, ce))
- return NULL;
-
- if ((Signature != 0) && (Signature != ce->Cache->Signature))
- {
- Signature = ce->Cache->Signature;
- return NULL;
- }
- Signature = ce->Cache->Signature;
-
- if ((Size != 0) && (Size != ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc)))
- {
- Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc);
- return NULL;
- }
- Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc);
-
- return ce->Cache + 1;
-}
-
-bool CBlockManager::UpdateBlock(uint32_t BlockID, uint32_t Signature)
-{
- uint32_t addr;
- TCacheEntry * ce;
-
- if ((BlockID == 0) && (Signature == -1))
- {
- if (!m_ReadOnly)
- _PendingAdd(0, 0, m_FirstBlockStart, m_Cache[0]);
-
- return true;
- }
-
- if (!_InitOperation(BlockID, addr, ce))
- return false;
-
- if (Signature)
- ce->Cache->Signature = Signature;
-
- _UpdateBlock(BlockID, ce, addr);
-
- return true;
-}
-
-// make file writeable:
-// write all cached blocks to file and check for the old addresses
-// remove virtual only from file
-// update m_FreeBlocks along the way
-
|