os/graphics/fbs/fontandbitmapserver/sfbs/FbsRalc.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/fbs/fontandbitmapserver/sfbs/FbsRalc.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,370 @@
     1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// This file holds the class methods for the Rom Address Lookup Cache feature
    1.18 +// of FBServ: CFbsRalCacheEl, CFbsRalCache.
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +#include "FbsRalc.h"
    1.23 +#include <e32svr.h>
    1.24 +
    1.25 +
    1.26 +// ============================================================================
    1.27 +
    1.28 +/**
    1.29 +Destructor of CFbsRalCacheEl objects releasing memory used by attributes.
    1.30 +@internalComponent 
    1.31 +@post		Object state undefined.
    1.32 +*/
    1.33 +CFbsRalCacheEl::~CFbsRalCacheEl()
    1.34 +	{
    1.35 +	User::Free(iFilename);
    1.36 +	iFilename = 0;
    1.37 +	}
    1.38 +
    1.39 +/**
    1.40 +Default constructor for CFbsRalCacheEl objects.
    1.41 +@internalComponent 
    1.42 +@post		CFbsRalCacheEl initialised with a null mapping information.
    1.43 +*/
    1.44 +CFbsRalCacheEl::CFbsRalCacheEl() 
    1.45 +: CBase(), iFilename(0), iAddress(0)
    1.46 +	{
    1.47 +	}
    1.48 +
    1.49 +/**
    1.50 +Constructor for constructing TFbsRalCacheEl objects with valid 
    1.51 +mapping information.
    1.52 +@internalComponent 
    1.53 +@param		aFilename full name of the file to store
    1.54 +@param		aMemAddr ROM memory address file starts at
    1.55 +@post		TFbsRalCacheEl initialised with the filename and memory address 
    1.56 +supplied.
    1.57 +@panic		EEmptyFilename panic generated when no chars in name
    1.58 +@panic		EInvalidRomAddress panic generated when address out of range
    1.59 +*/
    1.60 +CFbsRalCacheEl* 
    1.61 +CFbsRalCacheEl::New(
    1.62 +	const TDesC& aFilename,
    1.63 +	TAny* aMemAddr
    1.64 +)
    1.65 +	{
    1.66 +	// Allocate memory for new cache element object and construct.
    1.67 +	CFbsRalCacheEl* ptr = new CFbsRalCacheEl;
    1.68 +	if (!ptr)
    1.69 +		return 0;
    1.70 +
    1.71 +	// Initialise attributes of cache element.
    1.72 +	ptr->iFilename = HBufC::New(aFilename.Length());
    1.73 +	if (!ptr->iFilename)
    1.74 +		{
    1.75 +		User::Free(ptr);
    1.76 +		return 0;
    1.77 +		}
    1.78 +	*(ptr->iFilename) = aFilename;
    1.79 +	ptr->iAddress = aMemAddr;
    1.80 +#ifdef _RALC_DEBUG
    1.81 +	ptr->iHitCount = 1;
    1.82 +#endif //_RALC_DEBUG
    1.83 +
    1.84 +	// Done, return address to caller.
    1.85 +	return ptr;
    1.86 +	}
    1.87 +
    1.88 +/**
    1.89 +This routine is used by callers to release the memory directly used for the 
    1.90 +CFbsRalCacheEl object specified WITHOUT destroying the object first. Users
    1.91 +wishing to destroy the object can do so by calling the destructory directly. 
    1.92 +This is necessary since new/delete are not used for objects of this class as
    1.93 +out of memory panics must be avoided.
    1.94 +Therefore this routine must be used with caution to avoid memory leaks! 
    1.95 +@internalComponent 
    1.96 +@param		aThisRef Ptr to object to free. Ptr set to 0 on exit
    1.97 +*/
    1.98 +void
    1.99 +CFbsRalCacheEl::FreeOnly(
   1.100 +	CFbsRalCacheEl*& aThisRef
   1.101 +)
   1.102 +	{
   1.103 +	User::Free (aThisRef);
   1.104 +	aThisRef = 0;
   1.105 +	}
   1.106 +
   1.107 +/**
   1.108 +An optimised routine for checking the filename in the entry matches that
   1.109 +supplied to the routine. It compares filenames in a right to left fashion
   1.110 +since most differences in filenames are in the last 16 characters or so.
   1.111 +ASCII characters are compared in a case insensitive fashion.
   1.112 +@internalComponent 
   1.113 +@param		aSearchKey filename to compare entry with
   1.114 +@return		ETrue if entry matches search key, EFalse otherwise.
   1.115 +*/
   1.116 +TBool
   1.117 +CFbsRalCacheEl::MatchKey(
   1.118 +	const TDesC& aSearchKey
   1.119 +)
   1.120 +	{
   1.121 +	if (!iFilename)
   1.122 +		return EFalse;
   1.123 +
   1.124 +	// Check both filename descriptors are the same length
   1.125 +	TInt charIndex = iFilename->Length();	
   1.126 +	if (charIndex != aSearchKey.Length())
   1.127 +		return EFalse;
   1.128 +	
   1.129 +	// Then check every character is the same by comparing right to left.
   1.130 +	while (charIndex)
   1.131 +		{
   1.132 +		charIndex--;
   1.133 +		if (ToLower((*iFilename)[charIndex]) != ToLower(aSearchKey[charIndex]))
   1.134 +			return EFalse;
   1.135 +		}
   1.136 +
   1.137 +	// If we reach here we know the entry matches what we are looking for.
   1.138 +	return ETrue;
   1.139 +	}
   1.140 +
   1.141 +TInt CFbsRalCacheEl::ToLower(TInt aInt)
   1.142 +	{
   1.143 +	return (0x40 < aInt && 0x5B > aInt) ? (aInt + 0x20) : aInt;
   1.144 +	}
   1.145 +
   1.146 +// ============================================================================
   1.147 +
   1.148 +/**
   1.149 +Destructor of CFbsRalCache objects by resetting the circular buffer.
   1.150 +@internalComponent 
   1.151 +@post		Object state undefined.
   1.152 +*/
   1.153 +CFbsRalCache::~CFbsRalCache()
   1.154 +	{
   1.155 +#ifdef _RALC_DEBUG
   1.156 +	RDebug::Print(_L("FBS RALCache destructed for process:%x\n"),(TUint)iProcId);
   1.157 +	PrintCache();
   1.158 +#endif //_RALC_DEBUG
   1.159 +
   1.160 +	while (Count())
   1.161 +		DropItem();
   1.162 +
   1.163 +	Reset();
   1.164 +	}
   1.165 +
   1.166 +/**
   1.167 +CFbsRalCache private constructor.
   1.168 +@internalComponent 
   1.169 +@param		aFs valid file serve session handle used in lookups.
   1.170 +@post		TFbsRalCache initialised with empty cache buffer.
   1.171 +@see		Public construction achieved using static New() class method.
   1.172 +*/
   1.173 +CFbsRalCache::CFbsRalCache(
   1.174 +	RFs& aFs
   1.175 +) 
   1.176 +: CCirBuf<CFbsRalCacheEl>(), iFs(aFs)
   1.177 +	{
   1.178 +#ifdef _RALC_DEBUG
   1.179 +	RProcess current;
   1.180 +	iProcId = current.Id();
   1.181 +	RDebug::Print(_L("FBS RALCache constructed for process:%x\n"), 
   1.182 +		(TUint)iProcId);
   1.183 +#endif
   1.184 +	}
   1.185 +
   1.186 +/**
   1.187 +CFbsRalCache public constructor. This method allocates memory for a new
   1.188 +object on the default heap and initialises it with the supplied data.
   1.189 +@internalComponent 
   1.190 +@param		aCacheSize number (fixed) of entries in the cache. 
   1.191 +@param		aFs valid file serve session handle used in lookups.
   1.192 +@return		Pointer to new object, otherwise 0 when error detected.
   1.193 +@post		TFbsRalCache initialised with empty cache buffer.
   1.194 +*/
   1.195 +CFbsRalCache* 
   1.196 +CFbsRalCache::New(
   1.197 +	TInt aCacheSize,
   1.198 +	RFs& aFs
   1.199 +)
   1.200 +	{
   1.201 +	if (aCacheSize == 0)
   1.202 +		return 0;
   1.203 +
   1.204 +	// Allocate memory for new cache object
   1.205 +	// and call its constructor to initialise it.
   1.206 +	CFbsRalCache* ptr = new CFbsRalCache(aFs);
   1.207 +	if (!ptr) 
   1.208 +		return 0;
   1.209 +
   1.210 +	// Reserve capacity in circular buffer for cache entries.
   1.211 +	TRAPD(lc, ptr->SetLengthL(aCacheSize));
   1.212 +	if (lc != KErrNone)
   1.213 +		{
   1.214 +		User::Free(ptr);
   1.215 +		return 0;
   1.216 +		}
   1.217 +
   1.218 +	// Successful, new cache created.
   1.219 +	return ptr;
   1.220 +	}
   1.221 +
   1.222 +/**
   1.223 +This is the main cache lookup method for getting a file's start address
   1.224 +should it be found in ROM. It first scans the cache for a match and on a hit
   1.225 +it returns the stored address. On a miss it uses the file server to get
   1.226 +the file's ROM address. This result if +ve is stored and the Most-recently-used
   1.227 +cache, otherwise 0 is returned.
   1.228 +@internalComponent 
   1.229 +@param		aFileKey Full file name of file to get address for.
   1.230 +@return		Start address in ROM for the file, 0 if not in ROM.
   1.231 +@post		Cache updated with new entry if ROM file and not in cache.
   1.232 +*/
   1.233 +TAny*
   1.234 +CFbsRalCache::Lookup(
   1.235 +	const TDesC& aFileKey
   1.236 +)
   1.237 +	{
   1.238 +
   1.239 +	// Search the cache from the head to the tail should it have any entries
   1.240 +	// based on a MRU policy.
   1.241 +	if (Count())
   1.242 +		{
   1.243 +		TUint8* ptr = iHead;
   1.244 +		for (TInt num = Count(); num; num--)
   1.245 +			{
   1.246 +			// Calculate the address of the entry.
   1.247 +			if (ptr <= iPtr)
   1.248 +				ptr = iPtrE;
   1.249 +			ptr-=iSize;
   1.250 +			CFbsRalCacheEl* entry = (CFbsRalCacheEl*)ptr;
   1.251 +
   1.252 +			// Compare the entry key with that suppled for a match and return.
   1.253 +			if (entry->MatchKey(aFileKey))
   1.254 +				{
   1.255 +#ifdef _RALC_DEBUG
   1.256 +				RDebug::Print(_L("FBS RALCache lookup HIT: %S\n"), &aFileKey);
   1.257 +				entry->iHitCount++;
   1.258 +#endif //_RALC_DEBUG
   1.259 +				return entry->iAddress;
   1.260 +				}
   1.261 +			}
   1.262 +		}
   1.263 +
   1.264 +#ifdef _RALC_DEBUG
   1.265 +	RDebug::Print(_L("FBS RALCache lookup MISS: %S\n"), &aFileKey);
   1.266 +#endif //_RALC_DEBUG
   1.267 +
   1.268 +	// Filename not in cache, ask file server for it's ROM address.
   1.269 +	TAny *romAddr = iFs.IsFileInRom (aFileKey);
   1.270 +	if (romAddr)
   1.271 +		{
   1.272 +		// Store new filename/address mapping in cache and return.
   1.273 +		(void)AddItem (aFileKey, romAddr);
   1.274 +		return romAddr;
   1.275 +		}
   1.276 +
   1.277 +	// It's not a file in ROM
   1.278 +	return 0;
   1.279 +	}
   1.280 +
   1.281 +/**
   1.282 +This method will create a cache entry from the supplied data and add it to the
   1.283 +head of the circular cache buffer. If the cache is full this will result in the
   1.284 +entry at the tail being overwritten with the new entry inserted at the head.
   1.285 +@internalComponent 
   1.286 +@param		aFilename full name of the file to store
   1.287 +@param		aMemAddr ROM memory address file starts at
   1.288 +@return		ETrue when successfully added, EFalse otherwise.
   1.289 +@post		Cache updated as described above.
   1.290 +*/
   1.291 +TBool 
   1.292 +CFbsRalCache::AddItem(
   1.293 +	const TDesC& aFilename, 
   1.294 +	TAny* aMemAddr
   1.295 +)
   1.296 +	{
   1.297 +	// Construct the new cache entry from the supplied data.
   1.298 +	CFbsRalCacheEl* entry = CFbsRalCacheEl::New(aFilename, aMemAddr);
   1.299 +	if (!entry)
   1.300 +		return EFalse;
   1.301 +
   1.302 +	// Make room in the cache if we need to based on MRU policy.
   1.303 +	if (Count() == Length()) // Is it full?
   1.304 +		DropItem();
   1.305 +
   1.306 +	// Add a copy of the cache entry to the circular buffer.
   1.307 +	if (Add(entry) == 0)
   1.308 +		{
   1.309 +		// Failed, can't cache it!
   1.310 +		entry->~CFbsRalCacheEl();
   1.311 +		CFbsRalCacheEl::FreeOnly(entry);
   1.312 +		return EFalse;
   1.313 +		}
   1.314 +
   1.315 +	// Item now cached so clean up local entry memory only
   1.316 +	CFbsRalCacheEl::FreeOnly(entry);
   1.317 +	return ETrue;
   1.318 +	}
   1.319 +
   1.320 +/**
   1.321 +This method will create a cache entry from the supplied data and add it to the
   1.322 +head of the circular cache buffer. If tha cache is full this will result in the
   1.323 +entry at the tail being overwritten with the new entry inserted at the head.
   1.324 +@internalComponent 
   1.325 +@post		Cache updated as described above.
   1.326 +*/
   1.327 +void
   1.328 +CFbsRalCache::DropItem()
   1.329 +	{
   1.330 +	// No items to drop from cache!?
   1.331 +	if (Count() == 0)
   1.332 +		return;
   1.333 +
   1.334 +	// Remove cache entry at tail copying into temporary variable.
   1.335 +	CFbsRalCacheEl entry;
   1.336 +	Remove(&entry);
   1.337 +
   1.338 +#ifdef _RALC_DEBUG
   1.339 +	RDebug::Print(_L("FBS RALCache droped element: %S, %x, %d\n"),
   1.340 +				entry.iFilename, entry.iAddress, entry.iHitCount); 
   1.341 +#endif //_RALC_DEBUG
   1.342 +
   1.343 +	// 'entry' destroyed on exit and cleaned up.
   1.344 +	}
   1.345 +
   1.346 +
   1.347 +#ifdef _RALC_DEBUG
   1.348 +void 
   1.349 +CFbsRalCache::PrintCache()
   1.350 +	{
   1.351 +	if (Count())
   1.352 +        {
   1.353 +        TUint8* ptr = iHead;
   1.354 +		TInt num = Count();
   1.355 +		RDebug::Print(_L("FBS RALCache contents (%d):\n"), num);
   1.356 +        for (; num; num--)
   1.357 +            {
   1.358 +            if (ptr <= iPtr)
   1.359 +                ptr = iPtrE;
   1.360 +            ptr-=iSize;
   1.361 +            CFbsRalCacheEl* entry = (CFbsRalCacheEl*)ptr;
   1.362 +			RDebug::Print(_L("FBS RALCache El %d: %S, %x, %d\n"), num, 
   1.363 +				entry->iFilename, entry->iAddress, entry->iHitCount); 
   1.364 +            }
   1.365 +        }
   1.366 +	else
   1.367 +		{
   1.368 +		RDebug::Print(_L("FBS RALCache emtpy.\n"));
   1.369 +		}
   1.370 +	}
   1.371 +#endif
   1.372 +
   1.373 +// ==========================================================================