|
|
#include "stdafx.h"
//#include <stdio.h>
#define StreamName L"ResetTable"
ULONG CXResetData::BinarySearch( LPRESETREC pTbl, ULONG ulStart, ULONG ulEnd, ULARGE_INTEGER uliKey ) { #ifdef _DEBUG
static int cLoop; // BugBug! This will fail in multithreaded situations!
cLoop++; RonM_ASSERT(cLoop < 20); #endif
if (ulStart == ulEnd) { DEBUGCODE(cLoop = 0;) return ulStart; } else if (ulStart == (ulEnd -1)) { #ifdef _DEBUG
cLoop = 0; #endif
if (CULINT(uliKey) >= CULINT(ulEnd * m_ulBlockSize)) return ulEnd; else return ulStart; } ULONG ulMid = (ulEnd + ulStart) / 2;
if (CULINT(uliKey) <= CULINT(ulMid * m_ulBlockSize)) { return BinarySearch(pTbl, ulStart, ulMid, uliKey); } else { return BinarySearch(pTbl, ulMid, ulEnd, uliKey); } }
ULONG CXResetData::FindRecord( ULARGE_INTEGER uliOffset, ULARGE_INTEGER *puliXOffset, BOOL *pfLastRecord ) { ULONG ulRecNum; if (m_cFillRecs) { ulRecNum = BinarySearch(m_pSyncTbl, 0, m_cFillRecs - 1, uliOffset); *puliXOffset = (m_pSyncTbl + ulRecNum)->uliXOffset; *pfLastRecord = (ulRecNum == (m_cFillRecs - 1)); } return ulRecNum; }
BOOL CXResetData::FGetRecord( ULONG ulRecNum, ULARGE_INTEGER *puliOffset, ULARGE_INTEGER *puliXOffset, BOOL *pfLastRecord ) { if (ulRecNum >= m_cFillRecs) return FALSE;
*puliOffset = CULINT(ulRecNum * m_ulBlockSize).Uli(); *puliXOffset = (m_pSyncTbl + ulRecNum)->uliXOffset; *pfLastRecord = (ulRecNum == (m_cFillRecs - 1)); return TRUE; }
HRESULT CXResetData::DeleteRecord(ULONG ulRecNum) { HRESULT hr = NO_ERROR;
//Verify we are deleting valid record
if (ulRecNum < m_cFillRecs) { m_cFillRecs--; m_cEmptyRecs++; } else { hr = E_FAIL; }
return hr; }
HRESULT CXResetData::AddRecord(ULARGE_INTEGER uliOffset, ULARGE_INTEGER uliXOffset) { if (m_cEmptyRecs <= 0) { //double the size of reset table for future use
LPRESETREC prec = m_pSyncTbl;
ULONG nTotalRecs = (m_cFillRecs ? m_cFillRecs : 64) * 2; if (m_pSyncTbl = New sResetRec[nTotalRecs]) { //copy old table to newly created table with bigger size
if (prec) { memCpy((LPBYTE)m_pSyncTbl, (LPBYTE)prec, m_cFillRecs * sizeof(sResetRec)); delete prec; } m_cEmptyRecs = nTotalRecs - m_cFillRecs; } else { m_pSyncTbl = prec; return STG_E_INSUFFICIENTMEMORY; } } LPRESETREC prec = m_pSyncTbl + m_cFillRecs; prec->uliXOffset = uliXOffset;
m_cFillRecs++; m_cEmptyRecs--;
m_fDirty = TRUE;
return NO_ERROR; }
CXResetData::CXResetData( /*IStorage *pstg*/ ) { m_fDirty = FALSE; m_pStm = NULL; m_pStg = NULL; m_cFillRecs = 0; m_cEmptyRecs =0; m_pSyncTbl = NULL;
}
CXResetData::~CXResetData() { if (m_pSyncTbl) { delete m_pSyncTbl; m_pSyncTbl = NULL; } if (m_pStm) m_pStm->Release(); if (m_pStg) m_pStg->Release(); }
HRESULT CXResetData::InitResetTable(IStorage *pStg, ULARGE_INTEGER *puliVSpaceSize, ULARGE_INTEGER *puliTxSpaceSize, ULONG ulBlockSize) { m_pStg = pStg; m_pStg->AddRef(); HRESULT hr = NO_ERROR;
*puliVSpaceSize = CULINT(0).Uli(); *puliTxSpaceSize = CULINT(0).Uli(); m_ulBlockSize = ulBlockSize;
if (SUCCEEDED(hr = GetResetTblStream(pStg, &m_pStm))) { sHeader header; ULONG cbBytesRead = 0;
int hr = m_pStm->Read((LPVOID)&header, sizeof(sHeader), &cbBytesRead); if (SUCCEEDED(hr) && (cbBytesRead == sizeof(sHeader))) { *puliVSpaceSize = header.uliVSpaceSize; *puliTxSpaceSize = header.uliTxSpaceSize; m_cFillRecs = header.cRecs; if (m_cFillRecs > 0) { //allocate reset table with record
//count which is double of m_cFillRecs.
ULONG nTotalRecs = m_cFillRecs * 2; if (m_pSyncTbl = New sResetRec[nTotalRecs]) { m_cEmptyRecs = nTotalRecs - m_cFillRecs; LARGE_INTEGER dliB; ULARGE_INTEGER dliBFinal;
dliB.HighPart = 0; dliB. LowPart = header.cbSize;
dliBFinal.HighPart = 0; dliBFinal. LowPart = 0; if (SUCCEEDED(hr = m_pStm->Seek(dliB, STREAM_SEEK_SET, &dliBFinal))) { if (header.dwVerInfo == 1) { sResetRecV1 sRecV1; ULONG cb; for (int iRec = 0; SUCCEEDED(hr) && (iRec < m_cFillRecs); iRec++) { hr = m_pStm->Read((LPVOID)&sRecV1, sizeof(sResetRecV1), &cb); cbBytesRead += cb; (m_pSyncTbl + iRec)->uliXOffset = sRecV1.uliXOffset; } } else if (header.dwVerInfo == LZX_Current_Version) { hr = m_pStm->Read((LPVOID)(m_pSyncTbl), m_cFillRecs * sizeof(sResetRec), &cbBytesRead); }//read
}//seek
}// new
else { hr = STG_E_INSUFFICIENTMEMORY; } }//no. of entries in table > 0
}//read header
}//open reset table stream
return hr; }
HRESULT CXResetData::DumpStream(IStream *pTempStrm, LPSTR pFileName) { HRESULT hr = NO_ERROR; #if 0 //test code
FILE *file = fopen(pFileName, "w" );
if (file != NULL) { RonM_ASSERT(pTempStrm != NULL); HRESULT hr = NO_ERROR; BYTE lpBuf[2048];
if (SUCCEEDED(hr = pTempStrm->Seek(CLINT(0).Li(), STREAM_SEEK_SET, 0))) { ULONG cbToRead = sizeof(lpBuf); ULONG cbWritten; ULONG cbRead = cbToRead; while (SUCCEEDED(hr) && (cbRead == cbToRead)) { if (SUCCEEDED(hr = pTempStrm->Read(lpBuf, cbToRead, &cbRead))) { cbWritten = fwrite(lpBuf, sizeof(BYTE), cbRead, file); RonM_ASSERT(cbRead == cbWritten); if (cbRead != cbWritten) hr = E_FAIL; }//ReadAt
}//while
}//seek
fclose(file); } else hr = E_FAIL;
#endif //end test code
return hr; }
HRESULT CXResetData::CommitResetTable(ULARGE_INTEGER uliVSpaceSize, ULARGE_INTEGER uliTxSpaceSize) { RonM_ASSERT(m_pStm); HRESULT hr = NO_ERROR;
if (m_fDirty) { sHeader header; //latest version
header.dwVerInfo = LZX_Current_Version; header.cRecs = m_cFillRecs; header.cbSize = sizeof(sHeader); header.cbRecSize = sizeof(sResetRec); header.uliVSpaceSize = uliVSpaceSize; header.uliTxSpaceSize = uliTxSpaceSize; header.ulBlockSize = m_ulBlockSize; header.unused = 0; ULONG cbWritten; LARGE_INTEGER dliB; ULARGE_INTEGER dliBFinal; dliB.HighPart = 0; dliB. LowPart = 0;
dliBFinal.HighPart = 0; dliBFinal. LowPart = 0;
if (SUCCEEDED(hr = m_pStm->Seek(dliB, STREAM_SEEK_SET, &dliBFinal))) { hr = m_pStm->Write((LPVOID)&header, sizeof(header), &cbWritten); if (SUCCEEDED(hr) && (cbWritten == sizeof(header))) { if (SUCCEEDED(hr = m_pStm->Write((LPVOID)m_pSyncTbl, sizeof(sResetRec) * m_cFillRecs, &cbWritten))) { if (cbWritten != sizeof(sResetRec) * m_cFillRecs) hr = E_FAIL; else m_fDirty = FALSE;
}//write table
}//write header
}//seek
}//if table dirty
//test code
#ifdef _DEBUG
DumpStream(m_pStm, "c:\\dbg.tbl"); #else
DumpStream(m_pStm, "c:\\rel.tbl"); #endif
return hr; }
HRESULT CXResetData::GetResetTblStream(IStorage *pStg, IStream **ppStm) { HRESULT hr; if (STG_E_FILENOTFOUND == (hr = pStg->OpenStream(StreamName, 0, STGM_READWRITE | STGM_SHARE_EXCLUSIVE| STGM_DIRECT, 0, ppStm))) { hr = pStg->CreateStream(StreamName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_CREATE, 0, 0, ppStm); }//open stream
return hr; }
|