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

📄 filecache.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 



#include "hxtypes.h"

#include "hxcom.h"      // IUnknown
#include "hxiids.h"     // GUIDs
#include "hxslist.h"    // CHXSimpleList
#include "hxthread.h"   // HXMutex
#include "hxstring.h"   // memcpy()
#include "hxcomm.h"     // IHXCommonClassFactory
#include "ihxpckts.h"   // IHXBuffer
#include "hxcache2.h"   // IHXCache2, IHXCacheObject, IHXCacheObjectResponse
#include "filecache.h"
#include "multilog.h"   
#include "mlog_http.h"  // MLOG_HTTP()

/****************************************************************************
 *  CHXFileCacheObject::CHXFileCacheObject
 *
 *  Constructor
 */

CHXFileCacheObject::CHXFileCacheObject(IHXCommonClassFactory* /*IN*/ pClassFactory,
                                       UINT32   /*IN*/      ulFileLength,
                                       char*   /*IN*/       pFileName)
    : m_RefCount                (0),
      m_pCacheObjectResponse    (NULL),
      m_pClassFactory           (NULL),
      m_ulCapacity              (0),
      m_lThreshold              (50),
      m_ulUsedCapacity          (0),
      m_pList                   (NULL),
      m_ulCurrentWriteOffset    (0),
      m_pPendingAddBlock        (NULL),
      m_bInAddBlockDone         (FALSE),
      m_bInReadBlockDone        (FALSE),
      m_pMutex                  (NULL),
      m_ulCurrentReadOffset     (0),
      m_ulFileLength            (0),
      m_pFileName               (NULL),
      m_ulFileWriteOffset       (0),
      m_pCacheFileHandle        (NULL),
      m_ulHighestByteNotRead    (0)
{
    MLOG_HTTP("CHXFileCacheObject::CHXFileCacheObject(FileLen = %u, FileName = %s)\n", ulFileLength, pFileName);

    m_pPendingReadInfo.ulOffset = 0;
    m_pPendingReadInfo.ulLength = 0;
    m_pPendingReadInfo.pBlock = NULL;

    if(pClassFactory != NULL)
    {
        m_pClassFactory = pClassFactory;
        m_pClassFactory->AddRef();
    }

    m_ulFileLength = ulFileLength;
    m_pFileName = pFileName;

    m_pList = new CHXSimpleList;

    #if defined(THREADS_SUPPORTED) || defined(_UNIX_THREADS_SUPPORTED)
        HXMutex::MakeMutex(m_pMutex);
    #else
        HXMutex::MakeStubMutex(m_pMutex);
    #endif

}

/****************************************************************************
 *  CHXFileCacheObject::~CHXFileCacheObject
 *
 *  Destructor
 */

CHXFileCacheObject::~CHXFileCacheObject()
{
    MLOG_HTTP("CHXFileCacheObject::~CHXFileCacheObject()\n");

    m_pMutex->Lock();

    // Close the cache file and delete if necessary
    if(m_pCacheFileHandle != NULL)
    {
        // If full media clip not played, delete cache file
        if(m_ulHighestByteNotRead != m_ulFileLength)
        {
            fclose(m_pCacheFileHandle);
            remove(m_pFileName);
        }
        else
        {
            _CopyAllDataToFile();
            fclose(m_pCacheFileHandle);
        }
    }

    // Destroy the list
    if(m_pList)
    {
        LISTPOSITION currPos = m_pList->GetHeadPosition();
        Info* currInfo;
        while(currPos != NULL)
        {
            currInfo = (Info *)m_pList->GetNext(currPos);
            currInfo->pBlock->Release();
            delete currInfo;
        }

        delete m_pList;
    }

    m_pMutex->Unlock();

    HX_DELETE(m_pMutex);

} // ~CHXFileCacheObject()


// IUnknown COM Interface Methods

/****************************************************************************
 *  IUnknown::AddRef
 *
 *  This routine increases the object reference count in a thread safe
 *  manner. The reference count is used to manage the lifetime of an object.
 *  This method must be explicitly called by the user whenever a new
 *  reference to an object is used.
 */

STDMETHODIMP_(UINT32) CHXFileCacheObject::AddRef(void)
{
    MLOG_HTTP("CHXFileCacheObject::AddRef()\n");

    return InterlockedIncrement(&m_RefCount);
}

/****************************************************************************
 *  IUnknown::Release
 *
 *  This routine decreases the object reference count in a thread safe
 *  manner, and deletes the object if no more references to it exist. It must
 *  be called explicitly by the user whenever an object is no longer needed.
 */

STDMETHODIMP_(UINT32) CHXFileCacheObject::Release(void)
{
    MLOG_HTTP("CHXFileCacheObject::Release()\n");

    if (InterlockedDecrement(&m_RefCount) > 0)
    {
	return m_RefCount;
    }

    delete this;
    return 0;
}


/****************************************************************************
 *  IUnknown::QueryInterface
 *
 *  This routine indicates which interfaces this object supports. If a given
 *  interface is supported, the object's reference count is incremented, and
 *  a reference to that interface is returned. Otherwise a NULL object and
 *  error code are returned. This method is called by other objects to
 *  discover the functionality of this object.
 */

STDMETHODIMP CHXFileCacheObject::QueryInterface(REFIID interfaceID,
					       void** ppInterfaceObj)
{
    MLOG_HTTP("CHXFileCacheObject::QueryInterface()\n");

    // By definition all COM objects support the IUnknown interface
    if (IsEqualIID(interfaceID, IID_IUnknown))
    {
	AddRef();
	*ppInterfaceObj = (IUnknown*)(IHXCacheObject*)this;
	return HXR_OK;
    }
    // IHXCacheObject interface is supported
    else if (IsEqualIID(interfaceID, IID_IHXCacheObject))
    {
	AddRef();
	*ppInterfaceObj = (IHXCacheObject*)this;
	return HXR_OK;
    }

    // No other interfaces are supported
    *ppInterfaceObj = NULL;
    return HXR_NOINTERFACE;
}


//IHXCacheObject methods

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::Init
 *
 *	Purpose:
 *
 *	    Associates a cache object with the response object
 *	    it should notify of operation completeness.
 */

STDMETHODIMP
CHXFileCacheObject::Init(IHXCacheObjectResponse*   /*IN*/  pCacheObjectResponse,
                         UINT32   /*IN*/      ulCapacity,
                         UINT32   /*IN*/      lThreshold)
{
    MLOG_HTTP("CHXFileCacheObject::Init(Capacity = %u, Threshold = %d)\n", ulCapacity, lThreshold);

    HX_RESULT res = HXR_OK;

    if(pCacheObjectResponse != NULL)
    {
        // Release any previous response objects
        if(m_pCacheObjectResponse != NULL)
        {
            m_pCacheObjectResponse->Release();
        }

        m_pCacheObjectResponse = pCacheObjectResponse;
        pCacheObjectResponse->AddRef();
    
    }
    else
    {
        res = HXR_INVALID_PARAMETER;
    }

    m_ulCapacity = ulCapacity;

    if( (lThreshold < 0) || (lThreshold >= 100) ) 
    {
        res = HXR_INVALID_PARAMETER;
    }
    else
    {
        m_lThreshold = lThreshold;
    }

    // Open the cache file for writing.
    m_pCacheFileHandle = fopen(m_pFileName, "wb+");
    if( m_pCacheFileHandle == NULL )
        res = HXR_FAIL;

    m_pCacheObjectResponse->InitDone(res);

    // HXR_OK from this function indicates InitDone() will be called.
    // Since this statement is executed only after the above InitDone()
    // we return HXR_OK instead of res. 
    return HXR_OK;

} // Init()

/************************************************************************
     *	Method:
     *
     *	    IHXCacheObject::GetThreshold
     *
     *	Purpose:
     *
     *	    Obtain the threshold of the cache object.
     */

STDMETHODIMP_(UINT32)
CHXFileCacheObject::GetThreshold(void)
{
    MLOG_HTTP("CHXFileCacheObject::GetThreshold()\n"); 

    return m_lThreshold;

} // GetThreshold()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::ChangeThreshold
 *
 *	Purpose:
 *
 *	    The object keeps caching data until it is full (exhausts its 
 *      capacity). Once it is full, it will overwite existing cached data
 *      with new data ONLY if the percentage of cached data which has been
 *      read from the cache using the ReadBlock() method is *greater* than a
 *      given percentage of Capacity.. This percentage is set using the SetThreshold()
 *      method. In case the threshold is exceeded, the oldest added data
 *      (the data with the the least offset) will be discarded and the 
 *      amount of data discarded is so that the remaining cached data just
 *      satisfies the threshold condidtion (approximately).
 *
 *      This cache object is used in the HTTP/1.0 file system plugin for
 *      mobile devices and in this case, the threshold is set to 70%
 *      i.e., utilizedDataPercentage = 0.7
 *
 */

STDMETHODIMP
CHXFileCacheObject::ChangeThreshold(UINT32  /*IN*/	lNewThreshold)
{
    MLOG_HTTP("CHXFileCacheObject::ChangeThreshold(%d)\n", lNewThreshold);

    if( (lNewThreshold < 0) || (lNewThreshold >= 100) )
    {
        return HXR_INVALID_PARAMETER;
    }

    m_pMutex->Lock();

    UINT32 lOldThreshold = m_lThreshold;
    m_lThreshold = lNewThreshold;

    HX_RESULT res = _CheckForThresholdCondition();

    if(HXR_OK != res)
    {
        // Revert back as something got messed up.
        m_lThreshold = lOldThreshold;
    }

    m_pMutex->Unlock();

    return res;


} // ChangeThreshold()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::GetCapacity
 *
 *	Purpose:
 *
 *	    Obtain the capacity in bytes of the cache object.
 */

STDMETHODIMP_(UINT32)
CHXFileCacheObject::GetCapacity(void)
{
    MLOG_HTTP("CHXFileCacheObject::GetCapacity()\n"); 

    return m_ulCapacity;

} // GetCapacity()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::ChangeCapacity
 *
 *	Purpose:
 *
 *	    Change the capacity of the cache object.
 */
STDMETHODIMP
CHXFileCacheObject::ChangeCapacity(UINT32  /*IN*/	newByteCount) 
{
   MLOG_HTTP("CHXFileCacheObject::ChangeCapacity(%u)\n", newByteCount);

   HX_RESULT res = HXR_OK;
    
   m_pMutex->Lock();

   UINT32 ulOldCapacity = m_ulCapacity;

   m_ulCapacity = newByteCount;

   int nExcessData = m_ulUsedCapacity - newByteCount;
   
   if(nExcessData > 0)
   {
       // Discard the excess data writing to the cache file if necessary
       res = _DiscardDataFromHead((UINT32)nExcessData, TRUE);

       if(HXR_OK != res)
       {
           // Revert back to old capacity if you couldn't
           // discard data.
           m_ulCapacity = ulOldCapacity;    
       }
       else
       {
           // Capacity has changed, so threshold might have been exceeded.
           res = _CheckForThresholdCondition();
       }
   }

   m_pMutex->Unlock();

   m_pCacheObjectResponse->ChangeCapacityDone(res);
   
   // HXR_OK from this function indicates ChangeCapacityDone() will be called.
   // Since this statement is executed only after the above ChangeCapacityDone()
   // we return HXR_OK instead of res. 
   return HXR_OK;

} // ChangeCapacity()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::GetUnusedCapacity
 *
 *	Purpose:
 *
 *	    Obtain the unused capacity in bytes of the cache object.
 */

STDMETHODIMP_(UINT32)
CHXFileCacheObject::GetUnusedCapacity()
{
    MLOG_HTTP("CHXFileCacheObject::GetUnusedCapacity()\n");

    UINT32 ulUnusedCapacity = 0;

    m_pMutex->Lock();

    // There's data in the cache file which will be used to
    // populate the list. Will accept more data from outside
    // once I use up all data in the file.
    if(m_ulFileWriteOffset > m_ulCurrentWriteOffset)
    {
        ulUnusedCapacity = 0;
    }
    else
    {
        ulUnusedCapacity = m_ulCapacity - m_ulUsedCapacity;
    }
    
    m_pMutex->Unlock();

    return ulUnusedCapacity;


} // GetUnusedCapacity()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObject::AddBlock
 *
 *	Purpose:
 *
 *	    Adds a block of data to the cache.
 */

STDMETHODIMP
CHXFileCacheObject::AddBlock(IHXBuffer*	/*IN*/	pBlock) 

⌨️ 快捷键说明

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