fbs/fontandbitmapserver/sfbs/FBSMBMC.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/FBSMBMC.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,258 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// This file holds the class methods for the CFbTopMBMCache
+// 
+//
+
+#include "FBSMBMC.H"
+
+
+//
+//Constructor for CFbTopMBMCache objects with both forward and backward cache size
+//The forward(backward) cache size determines the number of stream ids after(before)
+//the current loaded bitmap ids to be stored in the cache
+//e.g Loading a bitmap with id=20 from a 40 bitmaps mbm file will load the cache(10,10)
+//with stream ids from 30-39(10 backward) and 40-49(10 forward)
+CFbTopStreamIdCache::CFbTopStreamIdCache(TInt aForwardSize, TInt aBackwardSize, TInt aMaxFilestores)
+	:CBase(),
+	iEntries(aMaxFilestores),
+	iForwardCacheSize(aForwardSize),
+	iBackwardCacheSize(aBackwardSize),
+	iMaxCacheFilestores(aMaxFilestores)
+	{
+	}
+
+//
+//Destructor of CFbTopMBMCache objects
+CFbTopStreamIdCache::~CFbTopStreamIdCache()
+	{
+	FlushCache();
+	}
+
+//Function to reset all the internal state of the class
+void CFbTopStreamIdCache::FlushCache()
+	{
+	CloseFileStores();
+	iEntries.Reset();
+	User::Free(iBuffer);
+	iBuffer = NULL;
+	}
+
+
+//Function to get the most recently used filestore stored in the cache
+CShiftedFileStore* CFbTopStreamIdCache::MruFileStore()
+	{
+	return iEntries[0]->FileStore();
+	}
+
+//Function to get the stream id for a bitmap id from a mbm file with certain offset.
+//It also fills up the cache with the stream ids for different bitmap from the same
+//mbm file and the number of stream ids stored depend on the initial setting of the
+//cache size. Also associates each resource with a client handle to improve the
+//performance of cleaning up.
+TStreamId CFbTopStreamIdCache::GetStreamIdL(RFile& aFile,const TDesC& aFilename,TInt32 aId,TUint aFileOffset, TInt aSessionHandle)
+	{
+	if (aId < 0)
+		{
+		User::Leave(KErrEof);
+		}
+	RCacheEntry *entry = FindCacheEntry(aFilename, aFileOffset);
+	if (entry == NULL)
+		{
+		entry = AddCacheEntryL(aFilename, aFileOffset);
+		}
+	entry->CreateFileStoreL(aFile, aSessionHandle);
+	return entry->GetStreamIdL(aId, iForwardCacheSize, iBackwardCacheSize);
+	}
+
+/**
+The overloaded version of GetStreamIdL which works with file session instead of file handle.
+*/
+TStreamId CFbTopStreamIdCache::GetStreamIdL(RFs& aFs, const TDesC& aFileName,TInt32 aId,TUint aFileOffset, TInt aSessionHandle)
+	{
+	if (aId < 0)
+		{
+		User::Leave(KErrEof);
+		}
+	RCacheEntry *entry = FindCacheEntry(aFileName, aFileOffset);
+	if (entry == NULL)
+		{
+		entry = AddCacheEntryL(aFileName, aFileOffset);
+		}
+	entry->CreateFileStoreL(aFs, aFileName, aSessionHandle);
+	return entry->GetStreamIdL(aId, iForwardCacheSize, iBackwardCacheSize);
+	}
+
+void CFbTopStreamIdCache::CloseFileStores(TInt aSessionHandle)
+	{
+	TInt n = iEntries.Count();
+	for (TInt i = 0; i < n; ++i)
+		{
+		if (!aSessionHandle || aSessionHandle == iEntries[i]->SessionHandle())
+			iEntries[i]->CloseFileStore();
+		}
+ 	}
+
+CFbTopStreamIdCache::RCacheEntry* CFbTopStreamIdCache::AddCacheEntryL(const TDesC& aFilename, TUint aFileOffset)
+	{
+	RCacheEntry *entry;
+	TInt n = iEntries.Count();
+	if (n < iMaxCacheFilestores)
+		{
+		TInt size = RCacheEntry::KBaseSize + (iForwardCacheSize + iBackwardCacheSize) * sizeof(TStreamId);
+		if (iBuffer == NULL)
+			iBuffer = static_cast<TUint8*>(User::AllocL(iMaxCacheFilestores * size));
+		entry = reinterpret_cast<RCacheEntry*>(iBuffer + n * size);
+		}
+	else
+		{
+		entry = iEntries[--n];
+		entry->CloseFileStore();
+		iEntries.Remove(n);
+		}
+	iEntries.InsertL(entry, 0);
+	return new(entry) RCacheEntry(aFilename, aFileOffset);
+	}
+
+CFbTopStreamIdCache::RCacheEntry* CFbTopStreamIdCache::FindCacheEntry(const TDesC& aFilename, TUint aFileOffset)
+	{
+	TInt n = iEntries.Count();
+	for (TInt i = 0; i < n; ++i)
+		{
+		RCacheEntry *entry = iEntries[i];
+		if (entry->SameFile(aFilename, aFileOffset))
+			{
+			if (i > 0)
+				{
+				iEntries.Remove(i); // Keep least-recently-used order
+				iEntries.Insert(entry, 0); // Cannot fail
+				}
+			return entry;
+			}
+		}
+	return NULL;
+	}
+
+
+const TInt CFbTopStreamIdCache::RCacheEntry::KBaseSize = _FOFF(CFbTopStreamIdCache::RCacheEntry, iStreamIdCache);
+
+
+CFbTopStreamIdCache::RCacheEntry::RCacheEntry(const TDesC& aFilename, TUint aFileOffset)
+:	iFilename(aFilename),
+	iFileOffset(aFileOffset),
+	iFilestore(NULL),
+	iLastId(KErrNotFound),
+	iStreamIdCount(0),
+	iSessionHandle(0)
+	{
+	}
+
+TBool CFbTopStreamIdCache::RCacheEntry::SameFile(const TDesC& aFilename, TUint aFileOffset)
+	{
+	return !aFilename.Compare(iFilename) && aFileOffset == iFileOffset;
+	}
+
+TStreamId CFbTopStreamIdCache::RCacheEntry::GetStreamIdL(TInt32 aId, TInt aForwardSize, TInt aBackwardSize)
+	{
+	if (iLastId >= 0 && aId >= iLastId - aBackwardSize && aId < iLastId + aForwardSize)
+		{
+		TInt startindex = iLastId < aBackwardSize ? 0 : iLastId - aBackwardSize;
+		// ensure aId exists in the MBM file
+		// cache size previously set using the number of bitmaps
+		if (aId - startindex >= iStreamIdCount)
+			User::Leave(KErrEof);
+		return iStreamIdCache[aId - startindex];
+		}
+	//Flush the cache array
+	iLastId = KErrNotFound;
+	iStreamIdCount = 0;
+
+	//Extracting the header stream parameters numbitmaps and the stream ids
+	TStreamId bmpstreamid(iFilestore->Root().Value() + iFileOffset);
+	RStoreReadStream readstream;
+	readstream.OpenLC(*iFilestore, bmpstreamid);
+	TInt numbitmaps = readstream.ReadInt32L();
+	if (aId >= numbitmaps)
+		User::Leave(KErrEof);
+	TInt endcount = aId + aForwardSize;
+	//if endcount is greater than the numbitmaps we need to truncate it so we
+	//never overread and cause panic.
+	if (endcount > numbitmaps)
+		endcount = numbitmaps;
+	for (TInt count = 0; count < endcount; ++count)
+		{
+		bmpstreamid.InternalizeL(readstream);
+		bmpstreamid=TStreamId(bmpstreamid.Value() + iFileOffset);
+		if (count >= aId - aBackwardSize)
+			iStreamIdCache[iStreamIdCount++] = bmpstreamid;
+		}
+	//get the stream id of the requested bitmap id
+	TInt startindex = aId < aBackwardSize ? 0 : aId - aBackwardSize;
+	bmpstreamid = iStreamIdCache[aId - startindex];
+	CleanupStack::PopAndDestroy();
+	// iLastId is updated just before returning to ensure that for error cases
+	// the cache is not used in subsequent calls to this method.
+	iLastId = aId;
+	return bmpstreamid;
+	}
+
+CShiftedFileStore* CFbTopStreamIdCache::RCacheEntry::FileStore()
+	{
+	return iFilestore;
+	}
+
+TInt CFbTopStreamIdCache::RCacheEntry::SessionHandle() const
+	{
+	return iSessionHandle;
+	}
+
+void CFbTopStreamIdCache::RCacheEntry::CloseFileStore()
+	{
+	delete iFilestore;
+	iFilestore = NULL;
+	iSessionHandle = 0;
+ 	}
+
+/**
+It creates a file store if is not there i.e. if iFileStore is NULL.
+
+@param  aFile the mbm or rsc file handle
+@param  aSessionHandle the associated client session handle
+*/
+void CFbTopStreamIdCache::RCacheEntry::CreateFileStoreL(RFile& aFile, TInt aSessionHandle)
+	{
+	if (iFilestore == NULL)
+		{
+		iFilestore = CShiftedFileStore::FromL(aFile, iFileOffset);
+		iSessionHandle = aSessionHandle;
+		}
+	}
+
+/**
+It creates a file store if is not there i.e. if iFileStore is NULL.
+
+@param  aFs the associated file session handle
+@param  aFileName the mbm or rsc file name
+@param  aSessionHandle the associated client session handle
+*/
+void CFbTopStreamIdCache::RCacheEntry::CreateFileStoreL(RFs& aFs, const TDesC& aFileName, TInt aSessionHandle)
+	{
+	if (iFilestore == NULL)
+		{
+		RFile file;
+		User::LeaveIfError(file.Open(aFs,aFileName,EFileShareReadersOnly));
+		iFilestore = CShiftedFileStore::FromL(file, iFileOffset);
+		iSessionHandle = aSessionHandle;
+		}
+	}