memcache.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:25k
- /* ***** 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 "memcache.h"
- #include "multilog.h"
- #include "mlog_http.h"
- /****************************************************************************
- * CHXMemCacheObject::CHXMemCacheObject
- *
- * Constructor
- */
- CHXMemCacheObject::CHXMemCacheObject(IHXCommonClassFactory* /*IN*/ pClassFactory)
- : m_RefCount (0),
- m_pMemResponse(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)
- {
- MLOG_HTTP("CHXMemCacheObject::CHXMemCacheObject()n");
- if(pClassFactory != NULL)
- {
- m_pClassFactory = pClassFactory;
- m_pClassFactory->AddRef();
- }
- m_pPendingReadInfo.ulOffset = 0;
- m_pPendingReadInfo.ulLength = 0;
- m_pPendingReadInfo.pBlock = NULL;
-
- m_pList = new CHXSimpleList;
- #if defined(THREADS_SUPPORTED) || defined(_UNIX_THREADS_SUPPORTED)
- HXMutex::MakeMutex(m_pMutex);
- #else
- HXMutex::MakeStubMutex(m_pMutex);
- #endif
- }
- /****************************************************************************
- * CHXMemCacheObject::~CHXMemCacheObject
- *
- * Destructor
- */
- CHXMemCacheObject::~CHXMemCacheObject()
- {
- MLOG_HTTP("CHXMemCacheObject::~CHXMemCacheObject()n");
- m_pMutex->Lock();
- // 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);
- } // ~CHXMemCacheObject()
- // 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) CHXMemCacheObject::AddRef(void)
- {
- MLOG_HTTP("CHXMemCacheObject::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) CHXMemCacheObject::Release(void)
- {
- MLOG_HTTP("CHXMemCacheObject::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 CHXMemCacheObject::QueryInterface(REFIID interfaceID,
- void** ppInterfaceObj)
- {
- MLOG_HTTP("CHXMemCacheObject::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
- CHXMemCacheObject::Init(IHXCacheObjectResponse* /*IN*/ pMemResponse,
- UINT32 /*IN*/ ulCapacity,
- UINT32 /*IN*/ lThreshold)
- {
- MLOG_HTTP("CHXMemCacheObject::Init(Capacity = %u, Threshold = %d)n", ulCapacity, lThreshold);
- HX_RESULT res = HXR_OK;
- if(pMemResponse != NULL)
- {
- // Release any previous response objects
- if(m_pMemResponse != NULL)
- {
- m_pMemResponse->Release();
- }
- m_pMemResponse = pMemResponse;
- pMemResponse->AddRef();
-
- }
- else
- {
- res = HXR_INVALID_PARAMETER;
- }
- m_ulCapacity = ulCapacity;
- if( (lThreshold < 0) || (lThreshold >= 100) )
- {
- res = HXR_INVALID_PARAMETER;
- }
- else
- {
- m_lThreshold = lThreshold;
- }
- m_pMemResponse->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)
- CHXMemCacheObject::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., fNewThreshold = 0.7
- *
- */
- STDMETHODIMP
- CHXMemCacheObject::ChangeThreshold(UINT32 /*IN*/ lNewThreshold)
- {
- MLOG_HTTP("CHXMemCacheObject::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)
- CHXMemCacheObject::GetCapacity(void)
- {
- MLOG_HTTP("CHXMemCacheObject::GetCapacity()n");
-
- return m_ulCapacity;
- } // GetCapacity()
- /************************************************************************
- * Method:
- *
- * IHXCacheObject::ChangeCapacity
- *
- * Purpose:
- *
- * Change the capacity of the cache object.
- */
- STDMETHODIMP
- CHXMemCacheObject::ChangeCapacity(UINT32 /*IN*/ newByteCount)
- {
- MLOG_HTTP("CHXMemCacheObject::ChangeCapacity(%u)n", newByteCount);
- HX_RESULT res = HXR_OK;
-
- m_pMutex->Lock();
- UINT32 ulOldCapacity = m_ulCapacity;
- m_ulCapacity = newByteCount;
- int ulExcessData = m_ulUsedCapacity - newByteCount;
-
- if(ulExcessData > 0)
- {
- // Discard the excess data.
- res = _DiscardData((UINT32)ulExcessData);
- 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_pMemResponse->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)
- CHXMemCacheObject::GetUnusedCapacity()
- {
- MLOG_HTTP("CHXMemCacheObject::GetUnusedCapacity()n");
- m_pMutex->Lock();
- UINT32 ulUnusedCapacity = m_ulCapacity - m_ulUsedCapacity;
- m_pMutex->Unlock();
- return ulUnusedCapacity;
- } // GetUnusedCapacity()
- /************************************************************************
- * Method:
- *
- * IHXCacheObject::AddBlock
- *
- * Purpose:
- *
- * Adds a block of data to the cache.
- */
- STDMETHODIMP
- CHXMemCacheObject::AddBlock(IHXBuffer* /*IN*/ pBlock)
- {
- MLOG_HTTP("CHXMemCacheObject::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)
- {
- 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_pMemResponse->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
- CHXMemCacheObject::VerifyBlock(UINT32 /*IN*/ ulBlockOffset,
- UINT32 /*IN*/ ulBlockLength)
- {
- MLOG_HTTP("CHXMemCacheObject::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_pMemResponse->VerifyBlockDone(bExists);
- return HXR_OK;
- } // VerifyBlock()
- /************************************************************************
- * Method:
- *
- * IHXCacheObject::ReadBlock
- *
- * Purpose:
- *
- * Read a block out of the cache.
- */
- STDMETHODIMP
- CHXMemCacheObject::ReadBlock(UINT32 /*IN*/ ulBlockOffset,
- UINT32 /*IN*/ ulBlockLength)
- {
- MLOG_HTTP("CHXMemCacheObject::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)
- {
- if(ulTempOffset >= m_ulCurrentWriteOffset)
- res2 = HXR_INCOMPLETE;
- else
- res2 = HXR_FAIL;
-
- HX_RELEASE(pTempBlock);
- pTempBlock = NULL;
- }
- else if(ulTempOffset < ulLeastOffset)
- {
- res2 = HXR_FAIL;
- HX_RELEASE(pTempBlock);
- pTempBlock = NULL;
- }
- 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 = ulHighestOffset + 1;
- 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();
- m_bInReadBlockDone = TRUE;
- m_pMemResponse->ReadBlockDone(res2, pTempBlock);
- m_bInReadBlockDone = FALSE;
-
- HX_RELEASE(pTempBlock);
- }
- }
- return HXR_OK;
- } // ReadBlock()
- /************************************************************************
- * Method:
- * IHXCacheObject::Flush
- *
- * Purpose:
- *
- * Releases all data buffers cached in the object. The object now
- * gets to a same state as when it was newly created. After flushine,
- * the object can be used for reading/writing as before.
- */
- STDMETHODIMP
- CHXMemCacheObject::Flush(void)
- {
- MLOG_HTTP("CHXMemCacheObject::Flush()n");
- if(!m_pList)
- return HXR_UNEXPECTED;;
-
- m_pMutex->Lock();
- LISTPOSITION currPos = m_pList->GetHeadPosition();
- Info* currInfo;
- while(currPos != NULL)
- {
- currInfo = (Info *)m_pList->GetNext(currPos);
- currInfo->pBlock->Release();
- delete currInfo;
- }
- m_pList->RemoveAll();
- m_ulUsedCapacity = 0;
- m_ulCurrentWriteOffset = 0;
- m_ulCurrentReadOffset = 0;
- m_pMutex->Unlock();
- m_pMemResponse->FlushDone(HXR_OK);
- return HXR_OK;
- } // Flush()
- /************************************************************************
- * Method:
- *
- * IHXCacheObject::IsFull
- *
- * Purpose:
- *
- * Can the cache object accept any more data for storage?
- */
- STDMETHODIMP_(BOOL)
- CHXMemCacheObject::IsFull()
- {
- MLOG_HTTP("CHXMemCacheObject::IsFull()n");
- m_pMutex->Lock();
- BOOL bIsFull = TRUE;
- if(m_ulUsedCapacity < m_ulCapacity)
- bIsFull = FALSE;
-
- m_pMutex->Unlock();
- return bIsFull;
- } // IsFull()
- /************************************************************************
- * Method:
- *
- * IHXCacheObject::IsEmpty
- *
- * Purpose:
- *
- * Does the cache object have any data stored?
- */
- STDMETHODIMP_(BOOL)
- CHXMemCacheObject::IsEmpty()
- {
- MLOG_HTTP("CHXMemCacheObject::IsEmpty()n");
- if(m_ulUsedCapacity == 0)
- return TRUE;
- else
- return FALSE;
- } // IsEmpty()
- // Discards exactly 'byteCount' amount of oldest 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 CHXMemCacheObject::_DiscardData(UINT32 byteCount)
- {
- MLOG_HTTP("CHXMemCacheObject::_DiscardData(%u)n", byteCount);
- HX_RESULT res = HXR_UNEXPECTED;
- UINT32 ulDiscardedData = 0;
- LISTPOSITION currHeadPos = NULL;
- Info *headInfo = NULL;
- while( (currHeadPos = m_pList->GetHeadPosition())!= NULL )
- {
- headInfo = (Info*)(m_pList->RemoveHead());
- UINT32 ulHeadBlockSize = headInfo->ulSize;
- if(ulDiscardedData + ulHeadBlockSize <= byteCount)
- {
- headInfo->pBlock->Release();
- delete headInfo;
-
- ulDiscardedData += ulHeadBlockSize;
- }
- else
- {
- if(ulDiscardedData + ulHeadBlockSize > byteCount)
- {
- UINT32 ulValidDataSize = (ulDiscardedData + ulHeadBlockSize - byteCount);
- UINT32 ulInvalidDataSize = ulHeadBlockSize - ulValidDataSize;
- 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*)(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;
- }
- }
- m_ulUsedCapacity -= ulDiscardedData;
- return res;
- }
- // 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 CHXMemCacheObject::_CheckForThresholdCondition()
- {
- MLOG_HTTP("CHXMemCacheObject::_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 ulExcess = (m_ulCurrentReadOffset - ulLeastOffset) -
- (INT32)(m_lThreshold * m_ulCapacity * 0.01);
- if(ulExcess > 0)
- {
- if(ulExcess > m_ulUsedCapacity)
- ulExcess = m_ulUsedCapacity;
- res = _DiscardData(ulExcess);
- }
- return res;
- } // _CheckForThresholdCondition()