fbs/fontandbitmapserver/sfbs/FbsRalc.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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 // ==========================================================================