Convert Kernelhwsrv package from SFL to EPL
kernel\eka\compsupp is subject to the ARM EABI LICENSE
userlibandfileserver\fatfilenameconversionplugins\unicodeTables is subject to the Unicode license
kernel\eka\kernel\zlib is subject to the zlib license
// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32\sfile\sf_cache_client.cpp
//
//
/**
@file
@internalTechnology
*/
#include <e32std.h>
#include <e32std_private.h>
#include "sf_std.h"
#include <e32uid.h>
#include <e32wins.h>
#include <f32file.h>
#include "sf_cache_man.h"
#include "sf_cache_client.h"
#include "sf_file_cache_defs.h"
// This macro chnages the code so that new cachelines are stolen from the queue (if it is full)
// thus reducing the calls to RChunk::Commit
#define SYMBIAN_REUSE_STALE_CACHELINES
enum TCacheClientFault
{
ECacheClientSegmentNotFound0,
ECacheClientSegmentNotFound1,
ECacheClientSegmentNotFound2,
ECacheClientSegmentNotFound3,
ECacheClientSegmentNotFound4,
ECacheClientSegmentNotFound5,
ECacheClientSegmentNotFound6,
ECacheClientSegmentNotFound7,
ECacheClientLruInsertFailed,
ECacheClientInsertFailed,
ECacheClientRemovingBusySegment,
ECacheClientRemovingLockedSegment,
ECacheClientRemovingDirtySegment,
ECacheClientInvalidSegmentCount,
ECacheClientAlreadyLocked,
ECacheClientSegmentNotLocked,
ECacheClientSegmentNotDirty,
ECacheClientSegmentAlreadyUnlocked,
ECacheClientSegmentBadLockCount,
ECacheClientTotalByteCountInvalid,
ECacheClientUnexpectedHole,
ECacheClientSegmentAlreadyAllocated
};
LOCAL_C void Fault(TCacheClientFault aFault)
//
// Report a fault in the cache client
//
{
User::Panic(_L("FSCACHECLIENT"), aFault);
}
const TInt KSegmentArrayGranularity = 4;
//******************************
// CCacheClient
//******************************
CCacheClient* CCacheClient::NewL(CCacheManager& aManager)
{
CCacheClient* client = new(ELeave) CCacheClient(aManager);
CleanupStack::PushL(client);
client->ConstructL();
CleanupStack::Pop(1, client);
return client;
}
void CCacheClient::ConstructL()
{
iCacheLines = new(ELeave) RPointerArray<CCacheManager::TCacheLine>(KSegmentArrayGranularity);
iLastCacheLineIndex = -1;
}
CCacheClient::CCacheClient(CCacheManager& aManager) : iManager(aManager)
{
__CACHE_PRINT(_L("CACHECLIENT: CCacheClient()"));
iMaxBytesCached = 0;
}
/**
Purge() - free all cachelines
if aPurgeDirty == ETrue then discard all dirty data
E.g. if called from the destructor or following media removal
*/
void CCacheClient::Purge(TBool aPurgeDirty)
{
TInt cacheLineCount = iCacheLines->Count();
TInt n;
for (n=0; n<cacheLineCount; n++)
{
CCacheManager::TCacheLine& cacheLine = *(*iCacheLines)[n];
// Purge any locked and/or dirty cachlines if we still own them
// Freeing any locked or dirty pages implies that flushing the file
// has failed for some reason (media removal for example).
//
// NB if we own a cacheline and it is "in use" it's an error
// NB we need to check if it's locked first and then if we own it
// to guard against it being stolen by another thread.
if (aPurgeDirty && iManager.DirtyCount(this, cacheLine) != 0 && cacheLine.iClient == this)
{
#ifdef _DEBUG
if (iManager.LockCount(this, cacheLine) != 0)
__CACHE_PRINT(_L("CACHECLIENT: purging with locked segments"));
if (iManager.DirtyCount(this, cacheLine) != 0)
__CACHE_PRINT(_L("CACHECLIENT: purging dirty segments"));
__ASSERT_DEBUG(!iManager.InUse(cacheLine), Fault(ECacheClientRemovingBusySegment));
#endif
if (iManager.DirtyCount(this, cacheLine) != 0)
iManager.ClearDirty(this, cacheLine);
while (iManager.LockCount(this, cacheLine) != 0)
iManager.UnlockCacheLine(this, cacheLine);
} // if aPurgeDirty
TBool success = iManager.FreeCacheLine(this, cacheLine);
// if (aPurgeDirty == ETrue), then it is an error
// if a cacheline could not be freed (because it was locked).
if (aPurgeDirty)
{
__ASSERT_ALWAYS(success, Fault(ECacheClientRemovingLockedSegment));
}
}
}
CCacheClient::~CCacheClient()
{
__CACHE_PRINT1(_L("CACHECLIENT: ~CCacheClient() this %08X"), this);
if (iCacheLines)
{
Purge(ETrue);
iCacheLines->Close();
}
delete iCacheLines;
}
void CCacheClient::SetMaxSegments(TInt aMaxSegments)
{
iMaxBytesCached = aMaxSegments << iManager.SegmentSizeLog2();
}
TInt CCacheClient::SegmentSize()
{
return iManager.SegmentSize();
}
TInt CCacheClient::SegmentSizeLog2()
{
return iManager.SegmentSizeLog2();
}
TInt64 CCacheClient::SegmentSizeMask()
{
return iManager.SegmentSizeMask();
}
TInt CCacheClient::CacheLineSize()
{
return iManager.CacheLineSize();
}
TInt CCacheClient::CacheLineSizeInSegments()
{
return iManager.CacheLineSizeInSegments();
}
TUint8* CCacheClient::FindAndLockSegments(TInt64 aPos, TInt& aSegmentCount, TInt& aFilledSegmentCount, TInt& aLockError, TBool aMakeDirty)
{
TInt maxSegments = Min(aSegmentCount, CacheLineSizeInSegments());
aSegmentCount = 0;
aFilledSegmentCount = 0;
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
aLockError = KErrNone;
if (!cacheLine)
return NULL;
TInt offset = (TInt) (aPos - cacheLine->iPos);
TInt len = CacheLineLen(cacheLine) - offset;
TInt segmentSizeLog2 = iManager.SegmentSizeLog2();
TInt startSegmentNumber = offset >> segmentSizeLog2;
TInt filledCount = iManager.FillCount(this, *cacheLine);
// round up to a whole number of segments
aSegmentCount = ((len + iManager.SegmentSize() - 1) >> segmentSizeLog2);
aSegmentCount = Min(aSegmentCount, maxSegments);
// get filled count
aFilledSegmentCount = (filledCount > startSegmentNumber)?filledCount - startSegmentNumber:0;
__CACHE_PRINT4(_L("CACHECLIENT: FindAndLockSegments(), Client %08X pos %d addr %08X len %d"),
this, I64LOW(cacheLine->iPos), cacheLine->iAddr, CacheLineLen(cacheLine));
aLockError = LockSegments(aPos, aSegmentCount, aMakeDirty);
if (aLockError != KErrNone)
return NULL;
return cacheLine->iAddr + offset;
}
TUint8* CCacheClient::FindSegment(TInt64 aPos)
{
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
if (!cacheLine)
return NULL;
TInt offset = (TInt) (aPos - cacheLine->iPos);
return cacheLine->iAddr + offset;
}
TUint8* CCacheClient::AllocateAndLockSegments(TInt64 aPos, TInt& aSegmentCount, TBool aMakeDirty, TBool aExtendExisting)
{
__ASSERT_DEBUG(aSegmentCount >= 0, Fault(ECacheClientInvalidSegmentCount));
TInt segmentSizeLog2 = iManager.SegmentSizeLog2();
TInt segmentSize = iManager.SegmentSize();
TInt cacheLineSize = iManager.CacheLineSize();
aPos = (aPos >> segmentSizeLog2) << segmentSizeLog2;
// count number of uncached segments
TInt maxSegments = Min(aSegmentCount, CacheLineSizeInSegments());
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
// This is test code and changes the behaviour so that we always allocate
// as large a cacheline as possible, so as to increase the likelihood of "holes"
if (iManager.AllocateMaxSegments())
{
maxSegments = cacheLineSize >> segmentSizeLog2;
}
#endif
// make sure requested range doesn't overlap with an existing cacheline -
// if it does, shrink requested length down
TInt64 endPos = aPos + (maxSegments << segmentSizeLog2);
TInt cacheLineCount = iCacheLines->Count();
for (TInt index=0; index < cacheLineCount; index++)
{
const CCacheManager::TCacheLine* cacheLine = (*iCacheLines)[index];
TInt64 startPos = cacheLine->iPos;
if (cacheLine->iClient == this && startPos >= aPos && startPos < endPos)
{
endPos = cacheLine->iPos;
}
}
TInt segmentCount = (TInt) ((endPos - aPos) >> segmentSizeLog2);
__ASSERT_DEBUG(segmentCount > 0, Fault(ECacheClientSegmentAlreadyAllocated));
aSegmentCount = Min(segmentCount, aSegmentCount);
iLastCacheLineIndex = -1;
TUint8* segmentAddr = NULL;
__CACHE_PRINT2(_L("CACHECLIENT: AllocateAndLockSegments(%ld, %d)"), aPos, segmentCount);
// can we extend an existing cacheline ? (this saves wasting virtual memory)
// NB if we're about the make the new segment(s) dirty, only extend if last segment in existing
// cacheline is dirty, otherwise we'll end up unnecessarily marking lots of clean segments as dirty
if (aExtendExisting)
{
TInt64 posLastSegment = aPos - segmentSize;
const CCacheManager::TCacheLine* cacheLineOld;
TInt r;
if ((posLastSegment >= 0) && ((cacheLineOld = FindCacheLine(posLastSegment)) != NULL))
{
TInt prevSegmentNumber = StartSegment(cacheLineOld, posLastSegment);
TInt fillCountOld = iManager.FillCount(this, *cacheLineOld);
TInt fillCountNew = segmentCount + prevSegmentNumber+1; // fillCountOld;
if (prevSegmentNumber+1 == fillCountOld &&
fillCountNew <= (cacheLineSize >> segmentSizeLog2) &&
(!aMakeDirty || (prevSegmentNumber+1 == cacheLineOld->iDirtySegments))
)
{
__CACHE_PRINT(_L("CACHE: extending cacheline"));
segmentAddr = cacheLineOld->iAddr + (TInt) (aPos - cacheLineOld->iPos);
// Lock the cacheline and then try to extend it
r = LockSegments(cacheLineOld->iPos, cacheLineOld->iAllocatedSegments, ETrue);
if (r == KErrNone)
{
r = iManager.ExtendCacheLine(this, *cacheLineOld, fillCountNew);
//RDebug::Print(_L("GROW addr %08X, prevSegmentNumber %d, fillCount %d, fillCountNew %d, r %d\n"),
// cacheLineOld->iAddr, prevSegmentNumber, fillCountOld, fillCountNew, r);
if (r == KErrNone)
{
// If we've exceeded max, use LRU queue to discard old cachelines
RemoveLru(cacheLineOld);
return segmentAddr;
}
__CACHE_PRINT(_L("LockSegments FAIL"));
UnlockSegments(posLastSegment);
}
}
}
}
// reserve space in the segment array & LRU queue so we don't have to
// worry about failing to append
if (iCacheLines->Reserve(1) != KErrNone)
return NULL;
const CCacheManager::TCacheLine* cacheLineNew = NULL;
TBool reUsedCacheLineGrown = EFalse;
#ifdef SYMBIAN_REUSE_STALE_CACHELINES
// try to re-use an old cacheline if possible to avoid having to commit a new one
// as this involves calling RChunk::Commit() which takes some time....
TInt lenNewCacheLine = segmentCount << segmentSizeLog2;
TInt totalBytesCached = CachedBytes() + lenNewCacheLine;
cacheLineCount = iCacheLines->Count();
if (cacheLineCount > 0)
{
const CCacheManager::TCacheLine* cacheLineOld = (*iCacheLines)[cacheLineCount - 1];
TInt lenOldCacheLine = cacheLineOld->iFilledSegments << segmentSizeLog2;
reUsedCacheLineGrown = segmentCount > cacheLineOld->iAllocatedSegments;
if (totalBytesCached + lenNewCacheLine - lenOldCacheLine > iMaxBytesCached &&
cacheLineOld->iClient == this &&
cacheLineOld->iLockCount == 0)
{
if (iManager.ReAllocateAndLockCacheLine(this, aPos, *cacheLineOld, segmentCount) == KErrNone)
{
cacheLineNew = cacheLineOld;
}
}
}
#endif // SYMBIAN_REUSE_STALE_CACHELINES
TBool reUsingCacheline = cacheLineNew ? (TBool)ETrue:(TBool)EFalse;
// Request a free segment from cache manager
if (reUsingCacheline)
{
iCacheLines->Remove(cacheLineCount-1);
}
else
{
TInt r = iManager.AllocateAndLockCacheLine(this, aPos, cacheLineNew, segmentCount);
if (r != KErrNone)
{
__CACHE_PRINT1(_L("CACHECLIENT: AllocateSegment() failed r %d"), r);
return NULL;
}
// check the address isn't already in the iCacheLines -
// this can happen if it was stolen from us and we then steal it back
TInt indexDup = iCacheLines->Find(cacheLineNew);
if (indexDup != KErrNotFound)
iCacheLines->Remove(indexDup);
}
segmentAddr = cacheLineNew->iAddr;
// Add to top of LRU queue
TInt r = iCacheLines->Insert(cacheLineNew, 0);
__ASSERT_ALWAYS(r == KErrNone, Fault(ECacheClientInsertFailed));
__CACHE_PRINT4(_L("CACHECLIENT: AllocateAndLockSegments(), Client %08X pos %d addr %08X len %d"),
this, I64LOW(cacheLineNew->iPos), cacheLineNew->iAddr, CacheLineLen(cacheLineNew));
// assume LRU in use ...
iLastCacheLineIndex = 0;
if (!reUsingCacheline || reUsedCacheLineGrown)
RemoveLru(cacheLineNew);
return segmentAddr;
}
TInt CCacheClient::StartSegment(const CCacheManager::TCacheLine* aCacheLine, TInt64 aPos)
{
TInt offset = (TInt) (aPos - aCacheLine->iPos);
return offset >> iManager.SegmentSizeLog2();
}
TInt CCacheClient::CacheLineLen(const CCacheManager::TCacheLine* aCacheLine)
{
return aCacheLine->iAllocatedSegments << iManager.SegmentSizeLog2();
}
void CCacheClient::MarkSegmentsAsFilled(TInt64 aPos, TInt aSegmentCount)
{
__CACHE_PRINT2(_L("CACHECLIENT: Mark Filled Segments(%ld, %d)"), aPos, aSegmentCount);
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound0));
iManager.SetFilled(this, *cacheLine, StartSegment(cacheLine, aPos) + aSegmentCount);
}
void CCacheClient::MarkSegmentsAsDirty(TInt64 aPos, TInt aSegmentCount)
{
__CACHE_PRINT2(_L("CACHECLIENT: Mark Dirty Segments(%ld, %d)"), aPos, aSegmentCount);
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound1));
iManager.SetDirty(this, *cacheLine, StartSegment(cacheLine, aPos) + aSegmentCount);
}
TInt CCacheClient::FindFirstDirtySegment(TInt64& aPos, TUint8*& aAddr)
{
TInt cacheLineCount = iCacheLines->Count();
aPos = KMaxTInt64;
TInt segmentCount = 0;
for (TInt index = 0; index< cacheLineCount; index++)
{
CCacheManager::TCacheLine& cacheLine = *(*iCacheLines)[index];
TInt dirtyCount = iManager.DirtyCount(this, cacheLine);
if ((dirtyCount > 0 && cacheLine.iPos < aPos))
{
aPos = cacheLine.iPos;
aAddr = cacheLine.iAddr;
segmentCount = dirtyCount;
}
}
return segmentCount;
}
void CCacheClient::MarkSegmentsAsClean(TInt64 aPos)
{
__CACHE_PRINT1(_L("CACHECLIENT: MarkSegmentsAsClean(%d)"), I64LOW(aPos));
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound2));
// this sets the dirty count to zero, unlocks the cacheline and
// marks all the dirty pages as filled
iManager.ClearDirty(this, *cacheLine);
RemoveLru(cacheLine);
}
void CCacheClient::RemoveEmptySegments(const CCacheManager::TCacheLine* aCacheLine)
{
iManager.RemoveEmptySegments(this, *aCacheLine);
}
TInt CCacheClient::LockSegments(TInt64 aPos, TInt aSegmentCount, TBool aMakeDirty)
{
__CACHE_PRINT1(_L("CACHECLIENT: LockCacheLine(%d, %d)"), I64LOW(aPos));
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound3));
TInt startSegmentNumber = StartSegment(cacheLine, aPos);
TInt lockError;
if (aMakeDirty)
lockError = iManager.LockCacheLine(this, *cacheLine, 0, cacheLine->iAllocatedSegments);
else
lockError = iManager.LockCacheLine(this, *cacheLine, startSegmentNumber, aSegmentCount);
if (lockError == KErrInUse)
{
return lockError;
}
else if (lockError != KErrNone)
{
RemoveCacheLine(cacheLine);
return lockError;
}
// Check for "holes".i.e. empty segments before this one.
// If found, discard the empty segments and return KErrNotFound
TInt filledCount = iManager.FillCount(this, *cacheLine);
if (startSegmentNumber > filledCount)
{
__CACHE_PRINT(_L("CACHE: found hole"));
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
iManager.Stats().iHoleCount++;
#endif
RemoveEmptySegments(cacheLine);
iManager.UnlockCacheLine(this, *cacheLine);
if (CacheLineLen(cacheLine) == 0)
FreeCacheLine(cacheLine);
return KErrNotFound;
}
// Move this entry to top of LRU queue
iCacheLines->Remove(iLastCacheLineIndex);
#ifdef _DEBUG
TInt r =
#endif
iCacheLines->Insert(cacheLine, 0);
__ASSERT_DEBUG(r == KErrNone, Fault(ECacheClientLruInsertFailed));
iLastCacheLineIndex = 0;
return KErrNone;
}
/**
UnlockSegments()
*/
void CCacheClient::UnlockSegments(TInt64 aPos)
{
__CACHE_PRINT1(_L("CACHECLIENT: UnlockSegments(%d, %d)"), I64LOW(aPos));
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound4));
iManager.UnlockCacheLine(this, *cacheLine);
}
TInt CCacheClient::FindCacheLineIndex(TInt64 aPos)
{
TInt cacheLineCount = iCacheLines->Count();
if (iLastCacheLineIndex != -1 && iLastCacheLineIndex < cacheLineCount)
{
const CCacheManager::TCacheLine* cacheLine = (*iCacheLines)[iLastCacheLineIndex];
if (cacheLine->iClient == this &&
aPos >= cacheLine->iPos &&
aPos < cacheLine->iPos+CacheLineLen(cacheLine))
return iLastCacheLineIndex;
}
for (TInt index=0; index < cacheLineCount; index++)
{
const CCacheManager::TCacheLine* cacheLine = (*iCacheLines)[index];
if (cacheLine->iClient == this &&
aPos >= cacheLine->iPos &&
(aPos < cacheLine->iPos+CacheLineLen(cacheLine)))
{
iLastCacheLineIndex = index;
return index;
}
}
return KErrNotFound;
}
const CCacheManager::TCacheLine* CCacheClient::FindCacheLine(TInt64 aPos)
{
TInt index = FindCacheLineIndex(aPos);
return (index == KErrNotFound) ? NULL : (*iCacheLines)[index];
}
TBool CCacheClient::SegmentEmpty(TInt64 aPos)
{
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound5));
TInt startSegment = StartSegment(cacheLine, aPos);
TInt fillCount = iManager.FillCount(this, *cacheLine);
return startSegment >= fillCount ? (TBool)ETrue : (TBool)EFalse;
}
TBool CCacheClient::SegmentDirty(TInt64 aPos)
{
const CCacheManager::TCacheLine* cacheLine = FindCacheLine(aPos);
__ASSERT_ALWAYS(cacheLine != NULL, Fault(ECacheClientSegmentNotFound6));
TInt startSegment = StartSegment(cacheLine, aPos);
TInt dirtyCount = iManager.DirtyCount(this, *cacheLine);
return startSegment >= dirtyCount ? (TBool)ETrue : (TBool)EFalse;
}
// return whether there are too many locked pages globally (for all files)
// or too many for this file
TBool CCacheClient::TooManyLockedSegments()
{
if (iManager.TooManyLockedSegments())
return ETrue;
if (LockedBytes() > iMaxBytesCached)
return ETrue;
return EFalse;
}
TInt CCacheClient::CachedBytes()
{
TInt cacheLineCount = iCacheLines->Count();
TInt totalBytesCached = 0;
for (TInt n=0; n < cacheLineCount; n++)
totalBytesCached+= ((*iCacheLines)[n]->iFilledSegments << iManager.SegmentSizeLog2());
return totalBytesCached;
}
TInt CCacheClient::LockedBytes()
{
TInt cacheLineCount = iCacheLines->Count();
TInt segmentSizeLog2 = iManager.SegmentSizeLog2();
TInt totalBytesLocked = 0;
for (TInt n=0; n < cacheLineCount; n++)
{
CCacheManager::TCacheLine& cacheLine = *(*iCacheLines)[n];
if (cacheLine.iLockCount > 0)
totalBytesLocked+= cacheLine.iAllocatedSegments << segmentSizeLog2;
}
return totalBytesLocked;
}
void CCacheClient::RemoveLru(const CCacheManager::TCacheLine* aCacheLineToExclude)
{
if (iMaxBytesCached == 0) // LRU queue ?
return;
// If we've exceeded max, use LRU queue to remove stuff
TInt cacheLineCount = iCacheLines->Count();
TInt segmentSizeLog2 = iManager.SegmentSizeLog2();
// calculate the total bytes cached in all cachelines we own
// NB it's difficult to keep a track of this in this class because cachelines can be stolen (!)
TInt totalBytesCached = CachedBytes();
for (TInt lastIndex = cacheLineCount - 1;
lastIndex >= 0 && totalBytesCached > iMaxBytesCached;
lastIndex--)
{
const CCacheManager::TCacheLine* cacheLine = (*iCacheLines)[lastIndex];
// __CACHE_PRINT3(_L("Test cacheline index %d pos %ld len %d"), lastIndex, cacheLine.iPos, cacheLine.iLen);
if (cacheLine != aCacheLineToExclude)
{
// if removing a cacheline will bring the total to UNDER the "maximum"
// then don't remove it and abort - to do otherwise could remove
// data that has just been read-ahead ....
TInt lenCacheLine = cacheLine->iFilledSegments << segmentSizeLog2;
if (totalBytesCached - lenCacheLine <= iMaxBytesCached)
{
__CACHE_PRINT(_L("CACHECLIENT: cacheline too big to remove, aborting.."));
break;
}
__CACHE_PRINT3(_L("CACHECLIENT: Removing LRU index %d pos %ld len %d"), lastIndex, cacheLine->iPos, CacheLineLen(cacheLine));
TInt bytesFreed = cacheLine->iFilledSegments << iManager.SegmentSizeLog2();
if (FreeCacheLine(cacheLine))
{
totalBytesCached-= bytesFreed;
__ASSERT_ALWAYS(totalBytesCached >= 0, Fault(ECacheClientTotalByteCountInvalid));
}
}
}
}
TBool CCacheClient::FreeCacheLine(const CCacheManager::TCacheLine* aCacheLine)
{
__CACHE_PRINT1(_L("CACHECLIENT: FreeCacheLine(%d) )"), I64LOW(aCacheLine->iPos));
TBool success = iManager.FreeCacheLine(this, *aCacheLine);
if (success)
RemoveCacheLine(aCacheLine);
return success;
}
void CCacheClient::RemoveCacheLine(const CCacheManager::TCacheLine* aCacheLine)
{
__CACHE_PRINT1(_L("CACHECLIENT: RemoveCacheLine(%d) )"), I64LOW(aCacheLine->iPos));
TInt index = iCacheLines->Find(aCacheLine);
__ASSERT_ALWAYS(index != KErrNotFound, Fault(ECacheClientSegmentNotFound7));
iCacheLines->Remove(index);
}
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
void CCacheClient::DumpCache()
{
RDebug::Print(_L("**** CACHECLIENT: CacheLines ****\n"));
TInt cacheLineCount = iCacheLines->Count();
for (TInt index = 0; index< cacheLineCount; index++)
{
CCacheManager::TCacheLine& cacheLine = *(*iCacheLines)[index];
iManager.DumpCacheLine(cacheLine);
}
}
#endif