#include "StdAfx.h" #include "CustomConfigCacher.h" using namespace wylib::stream; using namespace FDOP; CCustomConfigCacher::CCustomConfigCacher() { } CCustomConfigCacher::~CCustomConfigCacher() { } bool CCustomConfigCacher::LoadFromCache(LPCTSTR sCacheFile, DWORD dwSourceCRC, CObjectAllocator &allocator, OUT void** pElements, INT_PTR &nElementCount) { if ( !FDOP::FileExists(sCacheFile) ) return false; PCONF_DATA_CACHE_HDR pHdr; //加载缓存文件到内存 if (m_CacheStream.loadFromFile(sCacheFile) <= 0) return false; //如果无法读取文件头则不是有效的缓存文件 if (m_CacheStream.getSize() < sizeof(*pHdr)) return false; pHdr = (PCONF_DATA_CACHE_HDR)m_CacheStream.getMemory(); //如果效验文件头失败则返回false if (!ValidateHeader(*pHdr)) return false; //如果验证数据CRC失败则表明缓存数据错误或原始数据已经修改了 if (!ValidateCacheDataCRC(dwSourceCRC)) return false; //读取缓存数据 return ReadCacheFile(allocator, pElements, nElementCount); } bool CCustomConfigCacher::SaveToCache(LPCTSTR sCacheFile, DWORD dwSourceCRC, const CObjectAllocator &allocator, const void *pElements, INT_PTR nElementCount) { CONF_DATA_CACHE_HDR hdr; MEM_BLOCK_REC memRec; TCHAR sSavePath[1024]; //获取保存文件的目录路径,如果目录路径字符长度超出缓存长度则报错 if ( ExtractFileDirectory(sCacheFile, sSavePath, ArrayCount(sSavePath)) >= ArrayCount(sSavePath) ) { OutputMsg(rmError, _T("unable to save Config Cache Data to %s, path to long"), sCacheFile); return false; } //逐层判断目录是否存在,如果不存在则创建 if ( !DeepCreateDirectory(sSavePath) ) { OutputError(GetLastError(), _T("unable to create cache directory %s "), sSavePath); return false; } //清空数据 m_CacheStream.setSize(0); //填充文件头 ZeroMemory(&hdr, sizeof(hdr)); hdr.dwMemBlockCount = (DWORD)allocator.blockCount(); hdr.dwElementCount = (DWORD)nElementCount; hdr.dwDataCRC32 = 0xFFFFFFFF; hdr.dwSourceCRC32 = dwSourceCRC; hdr.btPlatFormIdent = sizeof(void*); FillHeaderData(hdr); //保留文件头空间 m_CacheStream.setPosition(sizeof(hdr)); //写入对象指针列表 m_CacheStream.write(pElements, hdr.dwSizeElement * nElementCount); //写入内存块描述表 LPCVOID lpKey = NULL; CObjectAllocator::DataBlockDesc desc; while (lpKey = allocator.enumBlockDesc(lpKey, desc)) { memRec.lpMemoryBase = (char*)desc.lpBaseAddress; memRec.dwMemorySize = desc.dwBlockSize; //TRACE(_T("MEMBLOCK-DESC:%X,%u\n"), desc.lpBaseAddress, desc.dwBlockSize); m_CacheStream.write(&memRec, sizeof(memRec)); } //写入内存数据段 while (lpKey = allocator.enumBlockDesc(lpKey, desc)) { m_CacheStream.write(desc.lpBaseAddress, desc.dwBlockSize); } //计算数据段CRC32值 hdr.dwDataCRC32 = ~CRC32Update(hdr.dwDataCRC32, ((const char*)m_CacheStream.getMemory()) + sizeof(hdr), (int)m_CacheStream.getSize() - sizeof(hdr)); //最后写入文件头 m_CacheStream.setPosition(0); m_CacheStream.write(&hdr, sizeof(hdr)); //保存到文件 m_CacheStream.setPosition(0); return m_CacheStream.saveToFile(sCacheFile) >= m_CacheStream.getSize(); } bool CCustomConfigCacher::ReadCacheFile(CObjectAllocator &allocator, OUT void** pElements, INT_PTR &nElementCount) { /* /*+-----+--------+----------+-----------+--------------+ /*|文件头|对象数据段|内存块描述段|内存块1数据段|内存块N数据段... | /*+-----+--------+----------+-----------+--------------+ */ CacheReadEnvir ev; #ifdef WIN32 __try #endif { ev.pHdr = (PCONF_DATA_CACHE_HDR)m_CacheStream.getMemory(); ev.pElements = (void*)(ev.pHdr + 1); ev.pMemBlocks = (PMEM_BLOCK_REC)(((char*)ev.pElements) + ev.pHdr->dwSizeElement * ev.pHdr->dwElementCount); ev.pDataSegment = ((char*)ev.pMemBlocks) + sizeof(*ev.pMemBlocks) * ev.pHdr->dwMemBlockCount; m_pCacheReadEnvir = &ev; ev.pNewMemory = allocator.allocObjects(CalcDataSize()); CopyBlockMemorys(ev.pNewMemory); INT_PTR i; char *pElement = (char*)ev.pElements; size_t dwSizeElement = ev.pHdr->dwSizeElement; for (i=(INT_PTR)ev.pHdr->dwElementCount-1; i>-1; --i) { if ( !AdjustElementPointers(pElement) ) return false; pElement += dwSizeElement; } *pElements = ev.pElements; nElementCount = ev.pHdr->dwElementCount; } #ifdef WIN32 __finally #endif { m_pCacheReadEnvir = NULL; } return true; } inline bool CCustomConfigCacher::ValidateCacheDataCRC(DWORD dwSourceCRC) { PCONF_DATA_CACHE_HDR pHdr = (PCONF_DATA_CACHE_HDR)m_CacheStream.getMemory(); //判断缓存生成平台 if (sizeof(void*) != pHdr->btPlatFormIdent) return false; //-1表示强制读取缓存 if (dwSourceCRC == -1) return true; //判断原数据的CRC32值 if (dwSourceCRC != pHdr->dwSourceCRC32) return false; DWORD dwCRC = 0xFFFFFFFF; //计算并对比缓存文件整个数据段的CRC32值 dwCRC = ~CRC32Update(dwCRC, pHdr+1, (int)m_CacheStream.getSize() - sizeof(*pHdr)); if ( dwCRC != pHdr->dwDataCRC32 ) return false; return true; } void* CCustomConfigCacher::GetNewMemoryPtr(LPCVOID lpAddress) { INT_PTR i, nCount = (INT_PTR)m_pCacheReadEnvir->pHdr->dwMemBlockCount; PMEM_BLOCK_REC pMemBlock = m_pCacheReadEnvir->pMemBlocks; char* pNewMemPtr = m_pCacheReadEnvir->pNewMemory; for (i=0; ilpMemoryBase <= (char*)lpAddress) { if (pMemBlock->lpMemoryBase + pMemBlock->dwMemorySize > (char*)lpAddress) { return pNewMemPtr + (((char*)lpAddress) - pMemBlock->lpMemoryBase); } } pNewMemPtr += pMemBlock->dwMemorySize; pMemBlock++; } return NULL; } size_t CCustomConfigCacher::CalcDataSize() { INT_PTR i, nCount = (INT_PTR)m_pCacheReadEnvir->pHdr->dwMemBlockCount; PMEM_BLOCK_REC pMemBlock = m_pCacheReadEnvir->pMemBlocks; size_t result = 0; for (i=0; idwMemorySize; pMemBlock++; } return result; } void CCustomConfigCacher::CopyBlockMemorys(char* lpNewMemory) { INT_PTR i, nCount = (INT_PTR)m_pCacheReadEnvir->pHdr->dwMemBlockCount; PMEM_BLOCK_REC pMemBlock = m_pCacheReadEnvir->pMemBlocks; char *lpCacheMemory = m_pCacheReadEnvir->pDataSegment; for (i=0; idwMemorySize); lpNewMemory += pMemBlock->dwMemorySize; lpCacheMemory += pMemBlock->dwMemorySize; pMemBlock++; } }