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