⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filecache.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{
    MLOG_HTTP("CHXFileCacheObject::AddBlock()\n");

    if(pBlock == NULL)
    {
        return HXR_INVALID_PARAMETER;
    }

    if(m_pList == NULL)
        return HXR_UNEXPECTED;
            
    if(m_pPendingAddBlock != NULL)
    {
        return HXR_UNEXPECTED;
    }
    else
    {
        m_pPendingAddBlock = pBlock;
        m_pPendingAddBlock->AddRef();
    }

    if(!m_bInAddBlockDone)
    {
        while(m_pPendingAddBlock)
        {
            IHXBuffer* pTempBlock = m_pPendingAddBlock;
            m_pPendingAddBlock = NULL;

            UINT32 ulBlockSize = pTempBlock->GetSize();
            Info *pNewInfo = NULL;

            HX_RESULT res = HXR_OK;
            if(ulBlockSize != 0)
            {
                m_pMutex->Lock(); 
           
                // Can you accomodate this data?
                if(m_ulUsedCapacity + ulBlockSize > m_ulCapacity)
                {
                    pTempBlock->Release();
                    res = HXR_OUTOFMEMORY;
                }
                else
                {
                    pNewInfo = new Info;
                    if(pNewInfo == NULL)
                        res = HXR_OUTOFMEMORY;
                }

                if(HXR_OK == res)
                {
                    // 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 );
                }
            

                m_pMutex->Unlock();
            }
            else
            {
                pTempBlock->Release();
            }

            m_bInAddBlockDone = TRUE;
            m_pCacheObjectResponse->AddBlockDone(res);
            m_bInAddBlockDone = FALSE;

        } // while
    }

    return HXR_OK;

} // AddBlock()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::VerifyBlock
 *
 *	Purpose:
 *
 *	    Verify that a block of data is in the cache.
 */

STDMETHODIMP
CHXFileCacheObject::VerifyBlock(UINT32	/*IN*/	ulBlockOffset,
			 UINT32	/*IN*/	ulBlockLength)
{
    MLOG_HTTP("CHXFileCacheObject::VeifyBlock()\n");

    if(m_pList == NULL)
        return HXR_UNEXPECTED;

    m_pMutex->Lock();
    
    // Critical Section starts

    BOOL bExists = TRUE;

    if(m_ulUsedCapacity == 0)
    {
        bExists = FALSE;
    }
    else
    {
        UINT32 ulLeastOffset = m_ulCurrentWriteOffset - m_ulUsedCapacity;
        UINT32 ulHighestOffset = m_ulCurrentWriteOffset - 1;

        
        BOOL bStartExists = (ulBlockOffset >= ulLeastOffset) && 
                            (ulBlockOffset <= ulHighestOffset);
        BOOL bEndExists = (ulBlockOffset + ulBlockLength - 1 >= ulLeastOffset) &&
                          (ulBlockOffset + ulBlockLength - 1 <= ulHighestOffset);

        bExists = bStartExists && bEndExists;
    }

    // Critical section ends

    m_pMutex->Unlock();

    m_pCacheObjectResponse->VerifyBlockDone(bExists);

    return HXR_OK;


} // VerifyBlock()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::ReadBlock
 *
 *	Purpose:
 *
 *	    Read a block out of the cache.
 */

STDMETHODIMP
CHXFileCacheObject::ReadBlock(UINT32    /*IN*/	ulBlockOffset,
			      UINT32    /*IN*/	ulBlockLength)
{
    MLOG_HTTP("CHXFileCacheObject::ReadBlock(Offset = %u, Length = %u)\n", ulBlockOffset, ulBlockLength);

    if(m_pList == NULL)
        return HXR_UNEXPECTED;

    if(m_pPendingReadInfo.pBlock != NULL)
        return HXR_UNEXPECTED;

    m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
                     (void **) &m_pPendingReadInfo.pBlock);

    if(m_pPendingReadInfo.pBlock == NULL)
        return HXR_OUTOFMEMORY;

    HX_RESULT res = m_pPendingReadInfo.pBlock->SetSize(ulBlockLength);

    if(res != HXR_OK)
    {
        m_pPendingReadInfo.pBlock->Release();
        m_pPendingReadInfo.pBlock = NULL;
        return res;
    }

    m_pPendingReadInfo.ulLength = ulBlockLength;
    m_pPendingReadInfo.ulOffset = ulBlockOffset;

    if(!m_bInReadBlockDone)
    {
        while(m_pPendingReadInfo.pBlock)
        {
            HX_RESULT res2 = HXR_OK;

            // To prepare for the possibilty of ReadBlock()
            // being called from ReadBlockDone()
            IHXBuffer* pTempBlock = m_pPendingReadInfo.pBlock;
            m_pPendingReadInfo.pBlock = NULL;
            UINT32 ulTempLength = m_pPendingReadInfo.ulLength;
            m_pPendingReadInfo.ulLength = 0;
            UINT32 ulTempOffset = m_pPendingReadInfo.ulOffset;
            m_pPendingReadInfo.ulOffset = 0;

            m_pMutex->Lock();

            UINT32 ulLeastOffset = m_ulCurrentWriteOffset - m_ulUsedCapacity; 
            UINT32 ulHighestOffset = m_ulCurrentWriteOffset - 1;

            if( (m_ulUsedCapacity == 0) && (m_ulCurrentWriteOffset == 0) )
            {
                res2 = HXR_INCOMPLETE;
                HX_RELEASE(pTempBlock);
                pTempBlock = NULL;

            }
            else if(ulTempOffset < ulLeastOffset)
            {
                res2 = HXR_INCOMPLETE;
                HX_RELEASE(pTempBlock);
                pTempBlock = NULL;

                // Flush data to file and then read the required (past)
                // data from the file.
                _CopyAllDataToFile();

                UINT32 ulGap = ulLeastOffset - ulTempOffset;
                UINT32 ulDiscardData = 0;

                if(ulGap >= m_ulCapacity)
                    ulDiscardData = m_ulUsedCapacity;
                else
                {
                    int nRemovableData = m_ulCurrentWriteOffset - 
                                         (ulTempOffset + m_ulCapacity);
                    ulDiscardData = (nRemovableData > 0)? (UINT32)nRemovableData: 0;
                }

                if(ulDiscardData >0)
                {
                    _DiscardDataFromTail(ulDiscardData, FALSE);
                }

                if(ulGap >= m_ulCapacity)
                {
                    _CopyFromFileToHead(ulTempOffset, m_ulCapacity);
                    m_ulCurrentWriteOffset = ulTempOffset + m_ulCapacity;
                    m_ulCurrentReadOffset = ulTempOffset;
                    m_ulUsedCapacity = m_ulCapacity;
                }
                else
                {
                    m_ulCurrentWriteOffset = ulTempOffset + ulGap + m_ulUsedCapacity;

                    //if(ulDiscardData != 0)
                    //{
                        _CopyFromFileToHead(ulTempOffset, ulGap);
                    //}
                    
                    m_ulCurrentReadOffset = ulTempOffset;
                }

            }
            else if(ulTempOffset > ulHighestOffset)
            {
                res2 = HXR_INCOMPLETE;
                HX_RELEASE(pTempBlock);
                pTempBlock = NULL;

                // If 'forward data' requested, mark all data as read so
                // that old data can be discarded to make space for new data.
                m_ulCurrentReadOffset = ulTempOffset;
                _CheckForThresholdCondition();
            }
            else
            {
                // Fill the pTempBlock with data from the list
            
                UCHAR* ucTempBlockData = pTempBlock->GetBuffer();
                UINT32 ulBytesReadFromList = 0;

                LISTPOSITION currPos = m_pList->GetHeadPosition();
                Info* currInfo;

                while(currPos != NULL)
                {   
                    currInfo = (Info *)m_pList->GetNext(currPos);
                    UINT32 ulCurrLowOffset = currInfo->ulOffset;
                    UINT32 ulCurrHighOffset = currInfo->ulOffset + currInfo->ulSize - 1;
                    UCHAR* ucCurrBlockData = currInfo->pBlock->GetBuffer();

                    if( (ulTempOffset >= ulCurrLowOffset) && (ulTempOffset <= ulCurrHighOffset) )
                    {
                        UINT32 ulMatchSize = ( (ulCurrHighOffset - ulTempOffset + 1) < ulTempLength ) ?
                                                ulCurrHighOffset - ulTempOffset + 1 : ulTempLength;

                        memcpy((void*)(ucTempBlockData + ulBytesReadFromList),
                                (void*)(ucCurrBlockData + ulTempOffset - ulCurrLowOffset), ulMatchSize);

                        ulBytesReadFromList += ulMatchSize;
                        ulTempOffset += ulMatchSize;

                        ulTempLength -= ulMatchSize;

                        if(0 == ulTempLength)
                            break;
                    }
                }

                if(ulTempLength > 0)
                {
                    res2 = HXR_INCOMPLETE;
                    pTempBlock->SetSize(ulBytesReadFromList);   
                }
                else
                {
                    res2 = HXR_OK;
                }

                m_ulCurrentReadOffset = ulTempOffset;
                _CheckForThresholdCondition();

            }

            m_pMutex->Unlock();

            if(m_ulHighestByteNotRead < m_ulCurrentReadOffset)
                m_ulHighestByteNotRead = m_ulCurrentReadOffset;

            m_bInReadBlockDone = TRUE;
            m_pCacheObjectResponse->ReadBlockDone(res2, pTempBlock);
            m_bInReadBlockDone = FALSE;
            
            HX_RELEASE(pTempBlock);
        }

    }

    return HXR_OK;

} // ReadBlock()

/************************************************************************
 *	Method:
 *	    IHXCacheObject::Flush
 *
 *	Purpose:
 *
 *	    Flushes all data to the cache file AND releases all data buffers 
 *          in the memory.After flushing, the object can be used for reading/writing
 *          as before.
 */

STDMETHODIMP
CHXFileCacheObject::Flush(void) 
{
    MLOG_HTTP("CHXFileCacheObject::Flush()\n");
    
    if(!m_pList)
        return HXR_UNEXPECTED;
    
    m_pMutex->Lock();

    _DiscardDataFromHead(m_ulUsedCapacity, TRUE);
    m_ulUsedCapacity = 0;

    m_pMutex->Unlock();

    m_pCacheObjectResponse->FlushDone(HXR_OK);

    return HXR_OK;

} // Flush()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::IsFull
 *
 *	Purpose:
 *
 *	    Can the cache object accept any more data for storage?
 */

STDMETHODIMP_(BOOL)
CHXFileCacheObject::IsFull()
{
    MLOG_HTTP("CHXFileCacheObject::IsFull()\n");

    if(GetUnusedCapacity() == 0)
        return TRUE;
    else
        return FALSE;

} // IsFull()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::IsEmpty
 *
 *	Purpose:
 *
 *	    Does the cache object have any data stored?
 */

STDMETHODIMP_(BOOL)
CHXFileCacheObject::IsEmpty()
{
    MLOG_HTTP("CHXFileCacheObject::IsEmpty()\n");

    if(m_ulUsedCapacity == 0)
        return TRUE;
    else
        return FALSE;

} // IsEmpty()


// Discards exactly 'byteCount' amount of data from the head.
// 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::_DiscardDataFromHead(UINT32 byteCount, BOOL bWriteToFile)
{
    MLOG_HTTP("CHXFileCacheObject::_DiscardDataFromHead(%u, %d)\n", byteCount, bWriteToFile);

    HX_RESULT res = HXR_UNEXPECTED;

    UINT32 ulDiscardedData = 0;

    Info *headInfo = NULL;

    LISTPOSITION currHead = m_pList->GetHeadPosition();

    while(currHead != NULL) 
    {
        headInfo = (Info*)m_pList->RemoveHead();

        UINT32 ulHeadBlockOffset = headInfo->ulOffset;
        UINT32 ulHeadBlockSize = headInfo->ulSize;

        // This whole block should be discarded
        if(ulDiscardedData + ulHeadBlockSize <= byteCount)
        {
            if(bWriteToFile == TRUE)
            {
                // If data already written to file, no need to write again.
                if( (m_ulFileWriteOffset >= ulHeadBlockOffset) &&
                    (m_ulFileWriteOffset <= ulHeadBlockOffset + ulHeadBlockSize - 1) )
                {
                    UINT32 ulDataAlreadyWritten = m_ulFileWriteOffset - ulHeadBlockOffset;
                    UINT32 ulDataToWrite = ulHeadBlockSize - ulDataAlreadyWritten;

                    fseek(m_pCacheFileHandle, m_ulFileWriteOffset, SEEK_SET);
                    int nBytesWritten = fwrite( (void*)(headInfo->pBlock->GetBuffer() + ulDataAlreadyWritten),
                                sizeof(UCHAR), ulDataToWrite, m_pCacheFileHandle);
                    fflush(m_pCacheFileHandle);

                    m_ulFileWriteOffset += ulDataToWrite;
                }
            }

            headInfo->pBlock->Release();
            delete headInfo;
            
            ulDiscardedData += ulHeadBlockSize;
        }
        else // Only part of the block needs to be discarded.
        {
            if(ulDiscardedData + ulHeadBlockSize > byteCount) // >>> Redundant condition
            {
                UINT32 ulValidDataSize = (ulDiscardedData + ulHeadBlockSize - byteCount);
                UINT32 ulInvalidDataSize = ulHeadBlockSize - ulValidDataSize;

                if(bWriteToFile == TRUE)
                {
                    // If data already written to file, no need to write again.
                    if( (m_ulFileWriteOffset >= ulHeadBlockOffset) && 
                        (m_ulFileWriteOffset <= ulHeadBlockOffset + ulInvalidDataSize - 1) )
                    {
                        UINT32 ulDataAlreadyWritten = m_ulFileWriteOffset - ulHeadBlockOffset;
                        UINT32 ulDataToWrite = ulInvalidDataSize - ulDataAlreadyWritten;

                        fseek(m_pCacheFileHandle, m_ulFileWriteOffset, SEEK_SET);
                        int nBytesWritten = fwrite( (void*)(headInfo->pBlock->GetBuffer() + ulDataAlreadyWritten),
                                    sizeof(UCHAR), ulDataToWrite, m_pCacheFileHandle);
                        fflush(m_pCacheFileHandle);

                        m_ulFileWriteOffset += ulDataToWrite;
                    }
                    
                }

                Info *pNewInfo = new Info;
                if(pNewInfo == NULL)
                {
                   res = HXR_OUTOFMEMORY;
                   break;
                }

                m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
                                               (void **) &(pNewInfo->pBlock));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -