MailTmpFile.cpp
上传用户:weimei12
上传日期:2022-08-11
资源大小:185k
文件大小:13k
- #include "StdAfx.h"
- #include "MailStruct.h"
- #include "MailTmpFile.h"
- CMailTmpFile::CMailTmpFile(void)
- {
- m_pTmpFile = NULL;
- m_bOpenToWrite = FALSE;
- m_pMailCluster = NULL;
- memset(&m_fileHeader, 0, sizeof(SMailFileHeader));
- }
- CMailTmpFile::~CMailTmpFile(void)
- {
- if(m_pTmpFile != NULL)
- {
- m_pTmpFile->Close();
- delete m_pTmpFile;
- m_pTmpFile = NULL;
- }
- if(m_pMailCluster != NULL)
- {
- delete m_pMailCluster;
- m_pMailCluster = NULL;
- }
- }
- ///<summary>
- /// Open a file to save mails
- ///</summary>
- BOOL CMailTmpFile::Open(LPCTSTR szFileName, BOOL bCanWrite)
- {
- ASSERT(szFileName != NULL);
- if (NULL == szFileName)
- {
- return FALSE;
- }
- if (IsOpened())
- {
- ASSERT(FALSE);
- return FALSE;
- }
- CFile* pFile = new CFile();
- UINT nOpenFlag = CFile::modeRead;
- if (bCanWrite)
- {
- nOpenFlag = CFile::modeReadWrite;
- }
- if (!pFile->Open(szFileName, nOpenFlag))
- {
- delete pFile;
- pFile = NULL;
- return FALSE;
- }
- m_bOpenToWrite = bCanWrite;
- m_pTmpFile = pFile;
- m_strFileName = szFileName;
- //read the content according to the format
- if (!LoadFromTmpFile())
- {
- delete pFile;
- m_pTmpFile = NULL;
- m_strFileName.Empty();
- m_bOpenToWrite = FALSE;
- return FALSE;
- }
- CloseFile(TRUE);
- return TRUE;
- }
- ///<summary>
- /// Create an empty temporary file at first
- ///</summary>
- BOOL CMailTmpFile::CreateEmptyFile(LPCTSTR szFileName)
- {
- ASSERT(szFileName != NULL);
- if (NULL == szFileName)
- {
- return FALSE;
- }
- if (IsOpened())
- {
- ASSERT(FALSE);
- return FALSE;
- }
- CFile* pFile = new CFile();
- if (!pFile->Open(szFileName, CFile::modeCreate | CFile::modeReadWrite))
- {
- delete pFile;
- pFile = NULL;
- return FALSE;
- }
- m_bOpenToWrite = TRUE;
- m_pTmpFile = pFile;
- m_strFileName= szFileName;
- //create the file header
- memset(&m_fileHeader, 0, sizeof(SMailFileHeader));
- m_fileHeader.m_nHeadSize = sizeof(SMailFileHeader);
- m_fileHeader.m_nVersion = CUR_MAILFILE_VERSION;
- memcpy(m_fileHeader.m_szIdentity, SZ_MAILFILE_IDENTITY, 8 * sizeof(TCHAR));
- m_fileHeader.m_mailClusterHeadPos = sizeof(SMailFileHeader);
- m_fileHeader.m_endFilePos = sizeof(SMailFileHeader);
- MAILFILEPOS dataPos = sizeof(SMailFileHeader);
- //create a data cluster
- CDataCluster* pNewDataCluster = new CDataCluster();
- memset(&pNewDataCluster->m_dataCluster, 0, sizeof(SMailCluster));
- m_pMailCluster = pNewDataCluster;
- pNewDataCluster->m_selfFilePos = dataPos;
- pNewDataCluster->m_dataCluster.m_nMailBlockSize = MAIL_BLOCK_SIZE;
- pNewDataCluster->m_dataCluster.m_nUseHeapCount = 1;
- dataPos += sizeof(SMailCluster);
- pNewDataCluster->m_dataCluster.m_HeapPos[0] = dataPos;
- ASSERT(pNewDataCluster->m_pDataHeaps == NULL);
- pNewDataCluster->m_pDataHeaps = new SDataHeap[1];
- memset(&pNewDataCluster->m_pDataHeaps[0], 0, sizeof(SDataHeap));
-
- //initial the first heap
- dataPos += sizeof(SDataHeap);
- pNewDataCluster->m_pDataHeaps[0].m_blockDataStartPos = dataPos;
- dataPos += MAIL_HEAP_CAPACITY * MAIL_BLOCK_SIZE;
- m_fileHeader.m_endFilePos = dataPos;
-
- //begin to write into the file
- TRY
- {
- ASSERT(m_pTmpFile != NULL);
- m_pTmpFile->SeekToBegin();
- m_pTmpFile->Write(&m_fileHeader, sizeof(SMailFileHeader));
- m_pTmpFile->Seek(m_fileHeader.m_mailClusterHeadPos, CFile::begin);
- m_pTmpFile->Write(&m_pMailCluster->m_dataCluster, sizeof(SMailCluster));
- UINT i = 0;
- for (; i < m_pMailCluster->m_dataCluster.m_nUseHeapCount; i++)
- {
- m_pTmpFile->Seek(m_pMailCluster->m_dataCluster.m_HeapPos[i], CFile::begin);
- m_pTmpFile->Write(&m_pMailCluster->m_pDataHeaps[i], sizeof(SDataHeap));
- }
- m_pTmpFile->SetLength(m_fileHeader.m_endFilePos);
- }
- CATCH_ALL(ex)
- {
- ex->Delete();
- delete m_pTmpFile;
- m_pTmpFile = NULL;
- m_strFileName.Empty();
- m_bOpenToWrite = FALSE;
- return FALSE;
- }
- END_CATCH_ALL;
- CloseFile(TRUE);
- return TRUE;
- }
- ///<summary>
- /// read the specified block
- ///</summary>
- BOOL CMailTmpFile::ReadMailBlock(const UINT nBlockIndex, const UINT nLen, void* pBuf)
- {
- ASSERT(pBuf != NULL);
- if (NULL == pBuf)
- {
- return FALSE;
- }
- if (nLen > m_pMailCluster->m_dataCluster.m_nMailBlockSize)
- {
- ASSERT(FALSE);
- return FALSE;
- }
- //calculate the position of the block
- //the block index is counted as a whole, despite different heaps
- int nHeapIndex = nBlockIndex / MAIL_HEAP_CAPACITY;
- int nRealBlockIndex = nBlockIndex % MAIL_HEAP_CAPACITY;
- ASSERT(nHeapIndex < MAIL_CLUSTER_CAPACITY);
-
- BOOL bNeedClose = ReOpenFile();
- ASSERT(m_pTmpFile != NULL);
- TRY
- {
- MAILFILEPOS filePos = m_pMailCluster->m_pDataHeaps[nHeapIndex].m_blockDataStartPos
- + nRealBlockIndex * m_pMailCluster->m_dataCluster.m_nMailBlockSize;
- m_pTmpFile->Seek(filePos, CFile::begin);
- m_pTmpFile->Read(pBuf, nLen);
- }
- CATCH_ALL(ex)
- {
- ex->Delete();
- CloseFile(bNeedClose);
- return FALSE;
- }
- END_CATCH_ALL;
- CloseFile(bNeedClose);
- return TRUE;
- }
- ///<summary>
- /// write the specified block
- ///</summary>
- BOOL CMailTmpFile::WriteMailBlock(const UINT nBlockIndex, void* pBuf, const UINT nLen)
- {
- ASSERT(pBuf != NULL);
- if (NULL == pBuf)
- {
- return FALSE;
- }
- if (nLen > m_pMailCluster->m_dataCluster.m_nMailBlockSize)
- {
- ASSERT(FALSE);
- return FALSE;
- }
- //calculate the position of the block
- //the block index is counted as a whole, despite different heaps
- int nHeapIndex = nBlockIndex / MAIL_HEAP_CAPACITY;
- int nRealBlockIndex = nBlockIndex % MAIL_HEAP_CAPACITY;
- ASSERT(nHeapIndex < MAIL_CLUSTER_CAPACITY);
- BOOL bNeedClose = ReOpenFile();
- ASSERT(m_pTmpFile != NULL);
- TRY
- {
- MAILFILEPOS filePos = m_pMailCluster->m_pDataHeaps[nHeapIndex].m_blockDataStartPos
- + nRealBlockIndex * m_pMailCluster->m_dataCluster.m_nMailBlockSize;
- m_pTmpFile->Seek(filePos, CFile::begin);
- m_pTmpFile->Write(pBuf, nLen);
- }
- CATCH_ALL(ex)
- {
- ex->Delete();
- CloseFile(bNeedClose);
- return FALSE;
- }
- END_CATCH_ALL;
- CloseFile(bNeedClose);
- return TRUE;
- }
- ///<summary>
- /// apply specified number of blocks to save the mails
- ///</summary>
- UINT CMailTmpFile::ApplyMailBlocks(const UINT nCount, const UINT nStartBlockIndex /* = 0 */)
- {
- ASSERT(nStartBlockIndex >= 0);
- ASSERT(nCount > 0);
- BOOL bNeedClose = ReOpenFile();
- //find the first continuous blocks to apply
- UINT nUseHeapCount = m_pMailCluster->m_dataCluster.m_nUseHeapCount;
- UINT nNoUseCount = 0;
- UINT nStartIndex = 0;
- BOOL bFound = FALSE;
- for (UINT i = 0; i < nUseHeapCount; i++)
- {
- for (UINT j = 0; j < MAIL_HEAP_CAPACITY; j++)
- {
- if (j + i * MAIL_HEAP_CAPACITY < nStartBlockIndex)
- {//seek to the nStartBlockIndex
- continue;
- }
- //find continuous blocks without use
- if (FLAG_NO_USE == m_pMailCluster->m_pDataHeaps[i].m_UseFlags[j])
- {
- if (0 == nNoUseCount)
- {
- nStartIndex = i * MAIL_HEAP_CAPACITY + j;
- }
- nNoUseCount++;
- if (nNoUseCount >= nCount)
- {
- bFound = TRUE;
- break;
- }
- }
- else
- {
- nNoUseCount = 0;
- }
- }
- if (bFound)
- {
- break;
- }
- }
- //change the flags to denote that those blocks will be used
- if (bFound)
- {
- ASSERT(nNoUseCount == nCount || nCount == 0);
- for (UINT i = 0; i < nCount; i++)
- {
- m_pMailCluster->m_pDataHeaps[(nStartIndex + i) / MAIL_HEAP_CAPACITY].m_UseFlags[(nStartIndex + i) % MAIL_HEAP_CAPACITY] = FLAG_IS_USE;
- }
- TRY
- {
- ASSERT(m_pTmpFile != NULL);
- UINT nDataHeap = nStartIndex / MAIL_HEAP_CAPACITY;
- while (TRUE)
- {
- ASSERT(m_pMailCluster->m_dataCluster.m_HeapPos[nDataHeap] != 0);
- m_pTmpFile->Seek(m_pMailCluster->m_dataCluster.m_HeapPos[nDataHeap], CFile::begin);
- m_pTmpFile->Write(&m_pMailCluster->m_pDataHeaps[nDataHeap], sizeof(SDataHeap));
- nDataHeap++;
- if ((nDataHeap * MAIL_HEAP_CAPACITY) > (nStartIndex + nCount) || nDataHeap >= nUseHeapCount)
- {
- break;
- }
- }
- }
- CATCH_ALL (ex)
- {
- ex->Delete();
- }
- END_CATCH_ALL;
- CloseFile(bNeedClose);
- return nStartIndex;
- }
- //create a new heap if needed
- int nCreateHeapCount = (nCount - nNoUseCount) / MAIL_HEAP_CAPACITY + 1;
- SDataHeap* pNewHeaps = new SDataHeap[nUseHeapCount + nCreateHeapCount];
- memcpy(pNewHeaps, m_pMailCluster->m_pDataHeaps, sizeof(SDataHeap) * nUseHeapCount);
- memset(pNewHeaps + nUseHeapCount, 0 , sizeof(SDataHeap) * nCreateHeapCount);
- delete []m_pMailCluster->m_pDataHeaps;
- m_pMailCluster->m_pDataHeaps = pNewHeaps;
- //save the relevant information
- ASSERT(m_pTmpFile != NULL);
- MAILFILEPOS curFilePos = m_fileHeader.m_endFilePos;
- for (int i = 0; i < nCreateHeapCount; i++)
- {
- m_pMailCluster->m_dataCluster.m_HeapPos[nUseHeapCount + i] = curFilePos;
- curFilePos += sizeof(SDataHeap);
- pNewHeaps[nUseHeapCount + i].m_blockDataStartPos = curFilePos;
- curFilePos += MAIL_HEAP_CAPACITY * m_pMailCluster->m_dataCluster.m_nMailBlockSize;
- m_pTmpFile->Seek(m_pMailCluster->m_dataCluster.m_HeapPos[nUseHeapCount + i], CFile::begin);
- m_pTmpFile->Write(&pNewHeaps[nUseHeapCount + i], sizeof(SDataHeap));
- }
- m_fileHeader.m_endFilePos = curFilePos;
- m_pMailCluster->m_dataCluster.m_nUseHeapCount = nUseHeapCount + nCreateHeapCount;
- m_pTmpFile->Seek(m_pMailCluster->m_selfFilePos, CFile::begin);
- m_pTmpFile->Write(&m_pMailCluster->m_dataCluster, sizeof(SMailCluster));
- m_pTmpFile->SeekToBegin();
- m_pTmpFile->Write(&m_fileHeader, sizeof(SMailFileHeader));
- m_pTmpFile->SetLength(m_fileHeader.m_endFilePos);
- //apply with the new heap added
- UINT nAppliedBlock = ApplyMailBlocks(nCount, nStartBlockIndex);
- CloseFile(bNeedClose);
- return nAppliedBlock;
- }
- ///<summary>
- /// release the specified blocks that will not be used
- ///</summary>
- BOOL CMailTmpFile::ReleaseMailBlocks(IN const UINT nStartIndex, IN const UINT nCount)
- {
- ASSERT(nStartIndex >= 0);
- ASSERT(nCount > 0);
- ASSERT(nStartIndex / MAIL_HEAP_CAPACITY < m_pMailCluster->m_dataCluster.m_nUseHeapCount);
- BOOL bNeedClose = ReOpenFile();
- //just change the flags
- for (UINT i = 0; i < nCount; i++)
- {
- m_pMailCluster->m_pDataHeaps[(nStartIndex + i) / MAIL_HEAP_CAPACITY].m_UseFlags[(nStartIndex + i) % MAIL_HEAP_CAPACITY] = FLAG_NO_USE;
- }
- TRY
- {
- ASSERT(m_pTmpFile != NULL);
- UINT nDataHeap = nStartIndex / MAIL_HEAP_CAPACITY;
- while (TRUE)
- {
- ASSERT(m_pMailCluster->m_dataCluster.m_HeapPos[nDataHeap] != 0);
- m_pTmpFile->Seek(m_pMailCluster->m_dataCluster.m_HeapPos[nDataHeap], CFile::begin);
- m_pTmpFile->Write(&m_pMailCluster->m_pDataHeaps[nDataHeap], sizeof(SDataHeap));
- nDataHeap++;
- if ((nDataHeap * MAIL_HEAP_CAPACITY) > (nStartIndex + nCount) ||
- nDataHeap >= m_pMailCluster->m_dataCluster.m_nUseHeapCount)
- {
- break;
- }
- }
- }
- CATCH_ALL (ex)
- {
- ex->Delete();
- CloseFile(bNeedClose);
- return FALSE;
- }
- END_CATCH_ALL;
- CloseFile(bNeedClose);
- return TRUE;
- }
- ///<summary>
- /// Test if the file to save mails has been opened
- ///</summary>
- BOOL CMailTmpFile::IsOpened()
- {
- return m_pTmpFile != NULL;
- }
- ///<summary>
- /// load the mails from the file
- ///</summary>
- BOOL CMailTmpFile::LoadFromTmpFile()
- {
- TRY
- {
- ASSERT(m_pTmpFile != NULL);
- //read the file header first
- m_pTmpFile->SeekToBegin();
- m_pTmpFile->Read(&m_fileHeader, sizeof(SMailFileHeader));
- //validate something, no use now, preserved for future use
- if (memcmp(m_fileHeader.m_szIdentity, SZ_MAILFILE_IDENTITY, 8) != 0)
- {
- return FALSE;
- }
- if (m_fileHeader.m_nVersion > CUR_MAILFILE_VERSION)
- {
- return FALSE;
- }
- //read the data cluster
- if(!LoadMailCluster(m_fileHeader.m_mailClusterHeadPos))
- {
- return FALSE;
- }
- }
- CATCH_ALL(ex)
- {
- ex->Delete();
- return FALSE;
- }
- END_CATCH_ALL;
- return TRUE;
- }
- ///<summary>
- /// close the file to save the mails
- ///</summary>
- void CMailTmpFile::CloseFile(BOOL bRealClose)
- {
- if (!bRealClose)
- {
- return;
- }
- if (m_pTmpFile != NULL)
- {
- m_pTmpFile->Close();
- CFile *pDbFile = m_pTmpFile;
- m_pTmpFile =NULL;
- delete pDbFile;
- }
- }
- ///<summary>
- /// load the mails from the specified cluster
- ///</summary>
- BOOL CMailTmpFile::LoadMailCluster(MAILFILEPOS filePos/*, CDataCluster *pParentMailCluster*/)
- {
- ASSERT(m_pTmpFile != NULL);
- CDataCluster* pNewDataCluster = new CDataCluster();
- pNewDataCluster->m_selfFilePos = filePos;
- m_pTmpFile->Seek(filePos, CFile::begin);
- m_pTmpFile->Read(&pNewDataCluster->m_dataCluster, sizeof(SMailCluster));
- ASSERT(pNewDataCluster->m_pDataHeaps == NULL);
- ASSERT(pNewDataCluster->m_dataCluster.m_nUseHeapCount > 0 &&
- pNewDataCluster->m_dataCluster.m_nUseHeapCount < MAIL_CLUSTER_CAPACITY);
- pNewDataCluster->m_pDataHeaps = new SDataHeap[pNewDataCluster->m_dataCluster.m_nUseHeapCount];
- int nHeapCount = pNewDataCluster->m_dataCluster.m_nUseHeapCount;
- int i = 0;
- for (; i < nHeapCount; i++)
- {
- m_pTmpFile->Seek(pNewDataCluster->m_dataCluster.m_HeapPos[i], CFile::begin);
- m_pTmpFile->Read(&pNewDataCluster->m_pDataHeaps[i], sizeof(SDataHeap));
- }
- m_pMailCluster = pNewDataCluster;
- return TRUE;
- }
- ///<summary>
- /// reopen the file if it is closed
- ///</summary>
- BOOL CMailTmpFile::ReOpenFile()
- {
- if (IsOpened())
- {
- return FALSE;
- }
- CFile* pTmpFile = new CFile();
- UINT nOpenFlag = CFile::modeRead;
- if (m_bOpenToWrite)
- {
- nOpenFlag = CFile::modeReadWrite;
- }
- ASSERT(!m_strFileName.IsEmpty());
- if (!pTmpFile->Open(m_strFileName, nOpenFlag))
- {
- delete pTmpFile;
- pTmpFile = NULL;
- return FALSE;
- }
- m_pTmpFile = pTmpFile;
- return TRUE;
- }