Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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