os/graphics/fbs/fontandbitmapserver/sfbs/FbsRalc.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // This file holds the class methods for the Rom Address Lookup Cache feature
    15 // of FBServ: CFbsRalCacheEl, CFbsRalCache.
    16 // 
    17 //
    18 
    19 #include "FbsRalc.h"
    20 #include <e32svr.h>
    21 
    22 
    23 // ============================================================================
    24 
    25 /**
    26 Destructor of CFbsRalCacheEl objects releasing memory used by attributes.
    27 @internalComponent 
    28 @post		Object state undefined.
    29 */
    30 CFbsRalCacheEl::~CFbsRalCacheEl()
    31 	{
    32 	User::Free(iFilename);
    33 	iFilename = 0;
    34 	}
    35 
    36 /**
    37 Default constructor for CFbsRalCacheEl objects.
    38 @internalComponent 
    39 @post		CFbsRalCacheEl initialised with a null mapping information.
    40 */
    41 CFbsRalCacheEl::CFbsRalCacheEl() 
    42 : CBase(), iFilename(0), iAddress(0)
    43 	{
    44 	}
    45 
    46 /**
    47 Constructor for constructing TFbsRalCacheEl objects with valid 
    48 mapping information.
    49 @internalComponent 
    50 @param		aFilename full name of the file to store
    51 @param		aMemAddr ROM memory address file starts at
    52 @post		TFbsRalCacheEl initialised with the filename and memory address 
    53 supplied.
    54 @panic		EEmptyFilename panic generated when no chars in name
    55 @panic		EInvalidRomAddress panic generated when address out of range
    56 */
    57 CFbsRalCacheEl* 
    58 CFbsRalCacheEl::New(
    59 	const TDesC& aFilename,
    60 	TAny* aMemAddr
    61 )
    62 	{
    63 	// Allocate memory for new cache element object and construct.
    64 	CFbsRalCacheEl* ptr = new CFbsRalCacheEl;
    65 	if (!ptr)
    66 		return 0;
    67 
    68 	// Initialise attributes of cache element.
    69 	ptr->iFilename = HBufC::New(aFilename.Length());
    70 	if (!ptr->iFilename)
    71 		{
    72 		User::Free(ptr);
    73 		return 0;
    74 		}
    75 	*(ptr->iFilename) = aFilename;
    76 	ptr->iAddress = aMemAddr;
    77 #ifdef _RALC_DEBUG
    78 	ptr->iHitCount = 1;
    79 #endif //_RALC_DEBUG
    80 
    81 	// Done, return address to caller.
    82 	return ptr;
    83 	}
    84 
    85 /**
    86 This routine is used by callers to release the memory directly used for the 
    87 CFbsRalCacheEl object specified WITHOUT destroying the object first. Users
    88 wishing to destroy the object can do so by calling the destructory directly. 
    89 This is necessary since new/delete are not used for objects of this class as
    90 out of memory panics must be avoided.
    91 Therefore this routine must be used with caution to avoid memory leaks! 
    92 @internalComponent 
    93 @param		aThisRef Ptr to object to free. Ptr set to 0 on exit
    94 */
    95 void
    96 CFbsRalCacheEl::FreeOnly(
    97 	CFbsRalCacheEl*& aThisRef
    98 )
    99 	{
   100 	User::Free (aThisRef);
   101 	aThisRef = 0;
   102 	}
   103 
   104 /**
   105 An optimised routine for checking the filename in the entry matches that
   106 supplied to the routine. It compares filenames in a right to left fashion
   107 since most differences in filenames are in the last 16 characters or so.
   108 ASCII characters are compared in a case insensitive fashion.
   109 @internalComponent 
   110 @param		aSearchKey filename to compare entry with
   111 @return		ETrue if entry matches search key, EFalse otherwise.
   112 */
   113 TBool
   114 CFbsRalCacheEl::MatchKey(
   115 	const TDesC& aSearchKey
   116 )
   117 	{
   118 	if (!iFilename)
   119 		return EFalse;
   120 
   121 	// Check both filename descriptors are the same length
   122 	TInt charIndex = iFilename->Length();	
   123 	if (charIndex != aSearchKey.Length())
   124 		return EFalse;
   125 	
   126 	// Then check every character is the same by comparing right to left.
   127 	while (charIndex)
   128 		{
   129 		charIndex--;
   130 		if (ToLower((*iFilename)[charIndex]) != ToLower(aSearchKey[charIndex]))
   131 			return EFalse;
   132 		}
   133 
   134 	// If we reach here we know the entry matches what we are looking for.
   135 	return ETrue;
   136 	}
   137 
   138 TInt CFbsRalCacheEl::ToLower(TInt aInt)
   139 	{
   140 	return (0x40 < aInt && 0x5B > aInt) ? (aInt + 0x20) : aInt;
   141 	}
   142 
   143 // ============================================================================
   144 
   145 /**
   146 Destructor of CFbsRalCache objects by resetting the circular buffer.
   147 @internalComponent 
   148 @post		Object state undefined.
   149 */
   150 CFbsRalCache::~CFbsRalCache()
   151 	{
   152 #ifdef _RALC_DEBUG
   153 	RDebug::Print(_L("FBS RALCache destructed for process:%x\n"),(TUint)iProcId);
   154 	PrintCache();
   155 #endif //_RALC_DEBUG
   156 
   157 	while (Count())
   158 		DropItem();
   159 
   160 	Reset();
   161 	}
   162 
   163 /**
   164 CFbsRalCache private constructor.
   165 @internalComponent 
   166 @param		aFs valid file serve session handle used in lookups.
   167 @post		TFbsRalCache initialised with empty cache buffer.
   168 @see		Public construction achieved using static New() class method.
   169 */
   170 CFbsRalCache::CFbsRalCache(
   171 	RFs& aFs
   172 ) 
   173 : CCirBuf<CFbsRalCacheEl>(), iFs(aFs)
   174 	{
   175 #ifdef _RALC_DEBUG
   176 	RProcess current;
   177 	iProcId = current.Id();
   178 	RDebug::Print(_L("FBS RALCache constructed for process:%x\n"), 
   179 		(TUint)iProcId);
   180 #endif
   181 	}
   182 
   183 /**
   184 CFbsRalCache public constructor. This method allocates memory for a new
   185 object on the default heap and initialises it with the supplied data.
   186 @internalComponent 
   187 @param		aCacheSize number (fixed) of entries in the cache. 
   188 @param		aFs valid file serve session handle used in lookups.
   189 @return		Pointer to new object, otherwise 0 when error detected.
   190 @post		TFbsRalCache initialised with empty cache buffer.
   191 */
   192 CFbsRalCache* 
   193 CFbsRalCache::New(
   194 	TInt aCacheSize,
   195 	RFs& aFs
   196 )
   197 	{
   198 	if (aCacheSize == 0)
   199 		return 0;
   200 
   201 	// Allocate memory for new cache object
   202 	// and call its constructor to initialise it.
   203 	CFbsRalCache* ptr = new CFbsRalCache(aFs);
   204 	if (!ptr) 
   205 		return 0;
   206 
   207 	// Reserve capacity in circular buffer for cache entries.
   208 	TRAPD(lc, ptr->SetLengthL(aCacheSize));
   209 	if (lc != KErrNone)
   210 		{
   211 		User::Free(ptr);
   212 		return 0;
   213 		}
   214 
   215 	// Successful, new cache created.
   216 	return ptr;
   217 	}
   218 
   219 /**
   220 This is the main cache lookup method for getting a file's start address
   221 should it be found in ROM. It first scans the cache for a match and on a hit
   222 it returns the stored address. On a miss it uses the file server to get
   223 the file's ROM address. This result if +ve is stored and the Most-recently-used
   224 cache, otherwise 0 is returned.
   225 @internalComponent 
   226 @param		aFileKey Full file name of file to get address for.
   227 @return		Start address in ROM for the file, 0 if not in ROM.
   228 @post		Cache updated with new entry if ROM file and not in cache.
   229 */
   230 TAny*
   231 CFbsRalCache::Lookup(
   232 	const TDesC& aFileKey
   233 )
   234 	{
   235 
   236 	// Search the cache from the head to the tail should it have any entries
   237 	// based on a MRU policy.
   238 	if (Count())
   239 		{
   240 		TUint8* ptr = iHead;
   241 		for (TInt num = Count(); num; num--)
   242 			{
   243 			// Calculate the address of the entry.
   244 			if (ptr <= iPtr)
   245 				ptr = iPtrE;
   246 			ptr-=iSize;
   247 			CFbsRalCacheEl* entry = (CFbsRalCacheEl*)ptr;
   248 
   249 			// Compare the entry key with that suppled for a match and return.
   250 			if (entry->MatchKey(aFileKey))
   251 				{
   252 #ifdef _RALC_DEBUG
   253 				RDebug::Print(_L("FBS RALCache lookup HIT: %S\n"), &aFileKey);
   254 				entry->iHitCount++;
   255 #endif //_RALC_DEBUG
   256 				return entry->iAddress;
   257 				}
   258 			}
   259 		}
   260 
   261 #ifdef _RALC_DEBUG
   262 	RDebug::Print(_L("FBS RALCache lookup MISS: %S\n"), &aFileKey);
   263 #endif //_RALC_DEBUG
   264 
   265 	// Filename not in cache, ask file server for it's ROM address.
   266 	TAny *romAddr = iFs.IsFileInRom (aFileKey);
   267 	if (romAddr)
   268 		{
   269 		// Store new filename/address mapping in cache and return.
   270 		(void)AddItem (aFileKey, romAddr);
   271 		return romAddr;
   272 		}
   273 
   274 	// It's not a file in ROM
   275 	return 0;
   276 	}
   277 
   278 /**
   279 This method will create a cache entry from the supplied data and add it to the
   280 head of the circular cache buffer. If the cache is full this will result in the
   281 entry at the tail being overwritten with the new entry inserted at the head.
   282 @internalComponent 
   283 @param		aFilename full name of the file to store
   284 @param		aMemAddr ROM memory address file starts at
   285 @return		ETrue when successfully added, EFalse otherwise.
   286 @post		Cache updated as described above.
   287 */
   288 TBool 
   289 CFbsRalCache::AddItem(
   290 	const TDesC& aFilename, 
   291 	TAny* aMemAddr
   292 )
   293 	{
   294 	// Construct the new cache entry from the supplied data.
   295 	CFbsRalCacheEl* entry = CFbsRalCacheEl::New(aFilename, aMemAddr);
   296 	if (!entry)
   297 		return EFalse;
   298 
   299 	// Make room in the cache if we need to based on MRU policy.
   300 	if (Count() == Length()) // Is it full?
   301 		DropItem();
   302 
   303 	// Add a copy of the cache entry to the circular buffer.
   304 	if (Add(entry) == 0)
   305 		{
   306 		// Failed, can't cache it!
   307 		entry->~CFbsRalCacheEl();
   308 		CFbsRalCacheEl::FreeOnly(entry);
   309 		return EFalse;
   310 		}
   311 
   312 	// Item now cached so clean up local entry memory only
   313 	CFbsRalCacheEl::FreeOnly(entry);
   314 	return ETrue;
   315 	}
   316 
   317 /**
   318 This method will create a cache entry from the supplied data and add it to the
   319 head of the circular cache buffer. If tha cache is full this will result in the
   320 entry at the tail being overwritten with the new entry inserted at the head.
   321 @internalComponent 
   322 @post		Cache updated as described above.
   323 */
   324 void
   325 CFbsRalCache::DropItem()
   326 	{
   327 	// No items to drop from cache!?
   328 	if (Count() == 0)
   329 		return;
   330 
   331 	// Remove cache entry at tail copying into temporary variable.
   332 	CFbsRalCacheEl entry;
   333 	Remove(&entry);
   334 
   335 #ifdef _RALC_DEBUG
   336 	RDebug::Print(_L("FBS RALCache droped element: %S, %x, %d\n"),
   337 				entry.iFilename, entry.iAddress, entry.iHitCount); 
   338 #endif //_RALC_DEBUG
   339 
   340 	// 'entry' destroyed on exit and cleaned up.
   341 	}
   342 
   343 
   344 #ifdef _RALC_DEBUG
   345 void 
   346 CFbsRalCache::PrintCache()
   347 	{
   348 	if (Count())
   349         {
   350         TUint8* ptr = iHead;
   351 		TInt num = Count();
   352 		RDebug::Print(_L("FBS RALCache contents (%d):\n"), num);
   353         for (; num; num--)
   354             {
   355             if (ptr <= iPtr)
   356                 ptr = iPtrE;
   357             ptr-=iSize;
   358             CFbsRalCacheEl* entry = (CFbsRalCacheEl*)ptr;
   359 			RDebug::Print(_L("FBS RALCache El %d: %S, %x, %d\n"), num, 
   360 				entry->iFilename, entry->iAddress, entry->iHitCount); 
   361             }
   362         }
   363 	else
   364 		{
   365 		RDebug::Print(_L("FBS RALCache emtpy.\n"));
   366 		}
   367 	}
   368 #endif
   369 
   370 // ==========================================================================