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 +// ==========================================================================