📄 filecache.cpp
字号:
if(pNewInfo->pBlock == NULL)
break;
res = pNewInfo->pBlock->SetSize(ulValidDataSize);
if(res != HXR_OK)
break;
memcpy( (void*)(pNewInfo->pBlock->GetBuffer()),
(void*)(headInfo->pBlock->GetBuffer()+ ulInvalidDataSize),
ulValidDataSize );
pNewInfo->ulOffset = headInfo->ulOffset + ulInvalidDataSize;
pNewInfo->ulSize = ulValidDataSize;
m_pList->AddHead( (void *)pNewInfo );
headInfo->pBlock->Release();
delete headInfo;
}
ulDiscardedData = byteCount;
headInfo = NULL;
res = HXR_OK;
break;
}
currHead = m_pList->GetHeadPosition();
}
m_ulUsedCapacity -= ulDiscardedData;
return res;
} // _DiscardDataFromHead()
// Check if utilizedData has exceeded THRESHOLD. If yes, discard
// appropriate amount of data. Note that this
// method is not thread safe. The caller has to take care of
// locking common data structures before calling this method.
HX_RESULT CHXFileCacheObject::_CheckForThresholdCondition()
{
MLOG_HTTP("CHXFileCacheObject::_CheckForThresholdCondition()\n");
if(m_ulUsedCapacity == 0)
{
return HXR_OK;
}
UINT32 ulLeastOffset = m_ulCurrentWriteOffset - m_ulUsedCapacity;
UINT32 ulHighestOffset = m_ulCurrentWriteOffset - 1;
HX_RESULT res = HXR_OK;
INT32 nExcess = (m_ulCurrentReadOffset - ulLeastOffset) -
(INT32)(m_lThreshold * m_ulCapacity * 0.01);
if(nExcess > 0)
{
if(nExcess > m_ulUsedCapacity)
nExcess = m_ulUsedCapacity;
res = _DiscardDataFromHead(nExcess, TRUE);
INT32 nExtraFileData = m_ulFileWriteOffset - m_ulCurrentWriteOffset;
if(nExtraFileData > 0)
{
UINT32 ulUnusedCapacity = m_ulCapacity - m_ulUsedCapacity;
UINT32 ulFileReadData = ((UINT32)nExtraFileData > ulUnusedCapacity) ?
ulUnusedCapacity: nExtraFileData;
res = _CopyFromFileToTail(m_ulCurrentWriteOffset, ulFileReadData);
}
}
return res;
} // _CheckForThresholdCondition()
// Discards exactly 'byteCount' amount of data from the tail.
// Note that this method is not thread safe. The caller has to take
// care of locking common data structures before calling this method.
HX_RESULT CHXFileCacheObject::_DiscardDataFromTail(UINT32 byteCount, BOOL bWriteToFile)
{
MLOG_HTTP("CHXFileCacheObject::_DiscardDataFromTail(%u, %d)\n", byteCount, bWriteToFile);
HX_RESULT res = HXR_OK;
if( (bWriteToFile) && (m_ulFileWriteOffset < m_ulCurrentWriteOffset) )
{
LISTPOSITION currPos = m_pList->GetTailPosition();
while(currPos != NULL)
{
Info* pCurrInfo = (Info*)(m_pList->GetPrev(currPos));
if( (m_ulFileWriteOffset >= pCurrInfo->ulOffset) &&
(m_ulFileWriteOffset >= pCurrInfo->ulOffset + pCurrInfo->ulSize - 1) )
{
break;
}
}
if(currPos != NULL)
{
Info* pCurrInfo = (Info*)(m_pList->GetAtNext(currPos));
UINT32 ulValidData = m_ulFileWriteOffset - (pCurrInfo->ulOffset);
UINT32 ulInvalidData = pCurrInfo->ulSize - ulValidData;
fseek(m_pCacheFileHandle, m_ulFileWriteOffset, SEEK_SET);
int nBytesWritten = fwrite( (void*)(pCurrInfo->pBlock->GetBuffer() + ulValidData),
sizeof(UCHAR), ulInvalidData, m_pCacheFileHandle);
fflush(m_pCacheFileHandle);
m_ulFileWriteOffset += ulInvalidData;
pCurrInfo = (Info*)(m_pList->GetNext(currPos));
while(pCurrInfo != NULL)
{
int nBytesWritten = fwrite( (void*)(pCurrInfo->pBlock->GetBuffer()),
sizeof(UCHAR), pCurrInfo->ulSize, m_pCacheFileHandle);
fflush(m_pCacheFileHandle);
m_ulFileWriteOffset += pCurrInfo->ulSize;
pCurrInfo = (Info*)(m_pList->GetNext(currPos));
}
}
else
{
res = HXR_UNEXPECTED;
}
}
if(res != HXR_OK)
return res;
UINT32 ulDiscardedData = 0;
Info *tailInfo = NULL;
res = HXR_UNEXPECTED;
LISTPOSITION currTail = m_pList->GetTailPosition();
while(currTail != NULL)
{
tailInfo = (Info*)(m_pList->RemoveTail());
UINT32 ulTailBlockSize = tailInfo->ulSize;
if(ulDiscardedData + ulTailBlockSize <= byteCount)
{
tailInfo->pBlock->Release();
delete tailInfo;
ulDiscardedData += ulTailBlockSize;
}
else
{
if(ulDiscardedData + ulTailBlockSize > byteCount)
{
UINT32 ulValidDataSize = (ulDiscardedData + ulTailBlockSize - byteCount);
Info *pNewInfo = new Info;
if(pNewInfo == NULL)
{
res = HXR_OUTOFMEMORY;
break;
}
m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void **) &(pNewInfo->pBlock));
if(pNewInfo->pBlock == NULL)
break;
res = pNewInfo->pBlock->SetSize(ulValidDataSize);
if(res != HXR_OK)
break;
memcpy( (void*)(pNewInfo->pBlock->GetBuffer()),
(void*)(tailInfo->pBlock->GetBuffer()),
ulValidDataSize );
pNewInfo->ulOffset = tailInfo->ulOffset;
pNewInfo->ulSize = ulValidDataSize;
m_pList->AddTail( (void *)pNewInfo );
tailInfo->pBlock->Release();
delete tailInfo;
}
ulDiscardedData = byteCount;
tailInfo = NULL;
res = HXR_OK;
break;
}
currTail = m_pList->GetTailPosition();
}
m_ulUsedCapacity -= ulDiscardedData;
m_ulCurrentWriteOffset -= ulDiscardedData;
return res;
} // _DiscardDataFromTail()
// Copies 'ulSize' amount of data from offset 'ulOffset' from
// the cache file. The blocks are added to the Tail of the list.
// The data is copied in blocks of size determined
// by CAPACITY_BLOCKSIZE_RATIO. Requires that the data is present
// in the file.
HX_RESULT CHXFileCacheObject::_CopyFromFileToTail(UINT32 ulOffset, UINT32 ulSize)
{
MLOG_HTTP("CHXFileCacheObject::_CopyFromFileToTail(Offset = %u, Size = %u)\n", ulOffset, ulSize);
if(ulSize == 0)
return HXR_OK;
m_ulCurrentWriteOffset = ulOffset;
UINT32 ulBlockSize = m_ulCapacity/CAPACITY_BLOCKSIZE_RATIO;
UINT32 ulRemainderBlockSize = 0;
UINT32 ulNumFullBlocks = ulSize/ulBlockSize;
if((ulSize%ulBlockSize) > 0)
{
ulRemainderBlockSize = ulSize - ulNumFullBlocks * ulBlockSize;
}
HX_RESULT res = HXR_OK;
fseek(m_pCacheFileHandle, ulOffset, SEEK_SET);
if(ulRemainderBlockSize > 0)
{
IHXBuffer* pRemainderBlock = NULL;
m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void **) &pRemainderBlock);
if(pRemainderBlock != NULL)
{
res = pRemainderBlock->SetSize(ulRemainderBlockSize);
}
else
{
res = HXR_OUTOFMEMORY;
}
if(res == HXR_OK)
{
fread( (void*)(pRemainderBlock->GetBuffer()),
sizeof(UCHAR), ulRemainderBlockSize, m_pCacheFileHandle );
Info* pNewInfo = new Info;
if(pNewInfo == NULL)
{
res = HXR_OUTOFMEMORY;
}
else
{
// The new block should be contiguous
pNewInfo->ulOffset = m_ulCurrentWriteOffset;
pNewInfo->ulSize = ulRemainderBlockSize;
pNewInfo->pBlock = pRemainderBlock;
m_pList->AddTail( (void *)pNewInfo );
m_ulUsedCapacity += ulRemainderBlockSize;
m_ulCurrentWriteOffset += ulRemainderBlockSize;
}
}
}
if(res != HXR_OK)
return res;
for(int i = 0; i < ulNumFullBlocks; i++)
{
IHXBuffer* pTempBlock = NULL;
m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void **) &pTempBlock);
if(pTempBlock != NULL)
{
res = pTempBlock->SetSize(ulBlockSize);
}
else
{
res = HXR_OUTOFMEMORY;
}
if(res == HXR_OK)
{
fread( (void*)(pTempBlock->GetBuffer()),
sizeof(UCHAR), ulBlockSize, m_pCacheFileHandle );
Info* pNewInfo = new Info;
if(pNewInfo == NULL)
{
res = HXR_OUTOFMEMORY;
}
else
{
// The new block should be contiguous
pNewInfo->ulOffset = m_ulCurrentWriteOffset;
pNewInfo->ulSize = ulBlockSize;
pNewInfo->pBlock = pTempBlock;
m_ulUsedCapacity += ulBlockSize;
m_ulCurrentWriteOffset += ulBlockSize;
m_pList->AddTail( (void *)pNewInfo );
}
}
}
return res;
} // _CopyFromFileToTail()
// Copies 'ulSize' amount of data from offset 'ulOffset' from
// the cache file. The blocks are added to the Head of the list.
// The data is copied in blocks of size determined
// by CAPACITY_BLOCKSIZE_RATIO. Requires that the data is present
// in the file.
HX_RESULT CHXFileCacheObject::_CopyFromFileToHead(UINT32 ulOffset, UINT32 ulSize)
{
MLOG_HTTP("CHXFileCacheObject::_CopyFromFileToHead(Offset = %u, Size = %u)\n", ulOffset, ulSize);
if(ulSize == 0)
return HXR_OK;
UINT32 ulBlockSize = m_ulCapacity/CAPACITY_BLOCKSIZE_RATIO;
UINT32 ulRemainderBlockSize = 0;
UINT32 ulNumFullBlocks = ulSize/ulBlockSize;
if((ulSize%ulBlockSize) > 0)
{
ulRemainderBlockSize = ulSize - ulNumFullBlocks * ulBlockSize;
}
HX_RESULT res = HXR_OK;
fseek(m_pCacheFileHandle, ulOffset + ulSize, SEEK_SET);
UINT32 ulCurrBlockOffset = ulOffset + ulSize;
if(ulRemainderBlockSize > 0)
{
IHXBuffer* pRemainderBlock = NULL;
m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void **) &pRemainderBlock);
if(pRemainderBlock != NULL)
{
res = pRemainderBlock->SetSize(ulRemainderBlockSize);
}
else
{
res = HXR_OUTOFMEMORY;
}
if(res == HXR_OK)
{
ulCurrBlockOffset -= ulRemainderBlockSize;
fseek(m_pCacheFileHandle, ulCurrBlockOffset , SEEK_SET);
fread( (void*)(pRemainderBlock->GetBuffer()),
sizeof(UCHAR), ulRemainderBlockSize, m_pCacheFileHandle );
fseek(m_pCacheFileHandle, ulCurrBlockOffset , SEEK_SET);
Info* pNewInfo = new Info;
if(pNewInfo == NULL)
{
res = HXR_OUTOFMEMORY;
}
else
{
// The new block should be contiguous
pNewInfo->ulOffset = ulCurrBlockOffset;
pNewInfo->ulSize = ulRemainderBlockSize;
pNewInfo->pBlock = pRemainderBlock;
m_pList->AddHead( (void *)pNewInfo );
m_ulUsedCapacity += ulRemainderBlockSize;
}
}
}
if(res != HXR_OK)
return res;
for(int i = 0; i < ulNumFullBlocks; i++)
{
IHXBuffer* pTempBlock = NULL;
m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void **) &pTempBlock);
if(pTempBlock != NULL)
{
res = pTempBlock->SetSize(ulBlockSize);
}
else
{
res = HXR_OUTOFMEMORY;
}
if(res == HXR_OK)
{
ulCurrBlockOffset -= ulBlockSize;
fseek(m_pCacheFileHandle, ulCurrBlockOffset, SEEK_SET);
fread( (void*)(pTempBlock->GetBuffer()),
sizeof(UCHAR), ulBlockSize, m_pCacheFileHandle );
fseek(m_pCacheFileHandle, ulCurrBlockOffset, SEEK_SET);
Info* pNewInfo = new Info;
if(pNewInfo == NULL)
{
res = HXR_OUTOFMEMORY;
}
else
{
// The new block should be contiguous
pNewInfo->ulOffset = ulCurrBlockOffset;
pNewInfo->ulSize = ulBlockSize;
pNewInfo->pBlock = pTempBlock;
m_pList->AddHead( (void *)pNewInfo );
m_ulUsedCapacity += ulBlockSize;
}
}
}
return res;
} // _CopyFromFileToHead()
// Copy all the data present in the list to the local file
HX_RESULT CHXFileCacheObject::_CopyAllDataToFile()
{
MLOG_HTTP("CHXFileCacheObject::_CopyAllDataToFile()\n");
if(m_pList == NULL)
return HXR_UNEXPECTED;
LISTPOSITION currPos = m_pList->GetHeadPosition();
Info* pCurrInfo;
while(currPos != NULL)
{
pCurrInfo = (Info *)m_pList->GetNext(currPos);
UINT32 ulCurrBlockOffset = pCurrInfo->ulOffset;
UINT32 ulCurrBlockSize = pCurrInfo->ulSize;
// If data already written to file, no need to write again.
if( (m_ulFileWriteOffset >= ulCurrBlockOffset) &&
(m_ulFileWriteOffset <= ulCurrBlockOffset + ulCurrBlockSize - 1) )
{
UINT32 ulDataAlreadyWritten = m_ulFileWriteOffset - ulCurrBlockOffset;
UINT32 ulDataToWrite = ulCurrBlockSize - ulDataAlreadyWritten;
fseek(m_pCacheFileHandle, m_ulFileWriteOffset, SEEK_SET);
int nBytesWritten = fwrite( (void*)(pCurrInfo->pBlock->GetBuffer() +
ulDataAlreadyWritten), sizeof(UCHAR),
ulDataToWrite, m_pCacheFileHandle);
fflush(m_pCacheFileHandle);
m_ulFileWriteOffset += ulDataToWrite;
}
}
return HXR_OK;
} // _CopyAllDataToFile()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -