os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-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 the License "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 // f32\sfat\sl_dir_cache.cpp
    15 //
    16 //
    17 
    18 #include "sl_std.h"
    19 #include "sl_dir_cache.h"
    20 
    21 //======================================================================
    22 TDynamicDirCachePage::~TDynamicDirCachePage()
    23 	{
    24 	}
    25 
    26 /**
    27 The static cache page creation function.
    28 Cache page objects are not supposed to be created on the stack, so this factory function is required.
    29 */
    30 TDynamicDirCachePage* TDynamicDirCachePage::NewL(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr)
    31 	{
    32 	return new(ELeave) TDynamicDirCachePage(aOwnerCache, aStartMedPos, aStartRamAddr);
    33 	}
    34 
    35 /**
    36 Cache page constructor.
    37 @param	aOwnerCache	pointer of the cache that owns this page
    38 @param	aStartMedPos	the start address on the media that this page caches
    39 @param	aStartRamAddr	the start address in the ram that this page content lives
    40 */
    41 TDynamicDirCachePage::TDynamicDirCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr)
    42 :iStartMedPos(aStartMedPos),
    43 iStartRamAddr(aStartRamAddr),
    44 iOwnerCache(aOwnerCache),
    45 iValid(EFalse),
    46 iLocked(EFalse)
    47 	{
    48 	//__PRINT3(_L("TDynamicDirCachePage::TDynamicDirCachePage(aStartMedPos=%lx, aStartRamAddr=0x%X, aPageSize=%u)"), aStartMedPos, aStartRamAddr, PageSizeInBytes());
    49 	iType = EUnknown;
    50 	}
    51 
    52 /////////////////////////////// class CDynamicDirCache::TLookupEntry ///////////////////////////
    53 /**
    54 Required by RHashSet<TLookupEntry> to identify individual hash set entries.
    55 @see	RHashSet
    56 */
    57 TBool IdentityFunction(const TLookupEntry& aEntry1, const TLookupEntry& aEntry2)
    58 	{
    59 	// only check starting med pos for hash searching
    60 	return aEntry1.iPos == aEntry2.iPos;
    61 	}
    62 /**
    63 Required by RHashSet<TLookupEntry> to generate hash value.
    64 @see	RHashSet
    65 */
    66 TUint32 HashFunction(const TLookupEntry& aEntry)
    67 	{
    68 	return (DefaultHash::Integer(I64HIGH(aEntry.iPos)) + DefaultHash::Integer(I64LOW(aEntry.iPos)));
    69 	}
    70 
    71 /////////////////////////////// class CDynamicDirCache ///////////////////////////
    72 CDynamicDirCache::~CDynamicDirCache()
    73 	{
    74 	__PRINT(_L("CDynamicDirCache::~CDynamicDirCache()"));
    75 
    76 	// we should never decommit locked pages
    77     while (!iLockedQ.IsEmpty())
    78 		{
    79 		TDynamicDirCachePage* page = iLockedQ.Last();
    80 		DeQueue(page);		// remove from queue
    81 		LookupTblRemove(page->StartPos());	// remove from lookuptable
    82 		delete page;
    83 		}
    84 	ASSERT(iLockedQCount == 0);
    85 
    86 	while (!iUnlockedQ.IsEmpty())
    87 		{
    88 		TDynamicDirCachePage* page = iUnlockedQ.Last();
    89 		DeQueue(page);		// remove from queue
    90 		LookupTblRemove(page->StartPos());	// remove from lookuptable
    91 		DecommitPage(page);	// inform cache client to decommit page memory
    92 		delete page;
    93 		}
    94 	ASSERT(iUnlockedQCount == 0);
    95 
    96 	ASSERT(iLookupTable.Count() == 0);
    97 	iLookupTable.Close();
    98     if (iCacheMemoryClient)
    99     	iCacheMemoryClient->Reset();
   100 	}
   101 
   102 /**
   103 Constructor of CDynamicDirCache.
   104 @param	aDrive	local drive interface to read/write media
   105 @param	aMinPageNum	the minimum page number for the cache, includes iActive page and locked pages.
   106 @param	aMaxPageNum	the maximum page number for the cache, includes iActive page, locked pages and unlocked pages.
   107 @param	aPageSizeInBytesLog2	the log2 value of page size in bytes, assumes page size is always a power of two
   108 */
   109 CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2)
   110 :iPageSizeLog2(aPageSizeInBytesLog2),
   111 iMinSizeInPages(aMinPageNum),
   112 iMaxSizeInPages(aMaxPageNum),
   113 iDrive(aDrive),
   114 iLockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   115 iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   116 iLockedQCount(0),
   117 iUnlockedQCount(0),
   118 iHashFunction(HashFunction),
   119 iIdentityFunction(IdentityFunction),
   120 iLookupTable(iHashFunction, iIdentityFunction)
   121 	{
   122 	iPageSizeInBytes = 1 << aPageSizeInBytesLog2;
   123 	iCacheDisabled = EFalse;
   124     iMinCacheSizeInBytes = aMinPageNum << aPageSizeInBytesLog2;
   125     iMaxCacheSizeInBytes = aMaxPageNum << aPageSizeInBytesLog2;
   126     ASSERT(iPageSizeInBytes && iPageSizeInBytes <= iMinCacheSizeInBytes && iMinCacheSizeInBytes <= iMaxCacheSizeInBytes);
   127 	// initial value, will be reset from outside
   128 	iCacheBasePos = 0;
   129 	}
   130 
   131 /**
   132 Second phase constructor of CDynamicDirCache.
   133 @param	aClientName the identification of cache memeory client this cache connects
   134 */
   135 void CDynamicDirCache::ConstructL(const TDesC& aClientName)
   136 	{
   137 //    __PRINT3(_L("CDynamicDirCache::ConstructL(Min=%u, Max=%u, page=%u)"), iMinCacheSizeInBytes, iMaxCacheSizeInBytes, iPageSizeInBytes);
   138 	CCacheMemoryManager* manager = CCacheMemoryManagerFactory::CacheMemoryManager();
   139 	if (manager)
   140 		{
   141 		// client will register itself onto cache memory manager when created
   142 		// note this operation may leave under OOM condition
   143 		iCacheMemoryClient = manager->ConnectClientL(aClientName, iMinSizeInPages * PageSizeInSegs(), iMaxSizeInPages * PageSizeInSegs());
   144 		}
   145 	else
   146 		{
   147 		User::Leave(KErrNotSupported);
   148 		}
   149 
   150 	ASSERT(iCacheMemoryClient);
   151 	if (!iCacheMemoryClient)
   152 		{
   153 		User::Leave(KErrNoMemory);
   154 		}
   155 
   156 
   157 	// allocate as many permanently locked pages as there are threads - plus one
   158 	// otherwise DoMakePageMRU() won't work properly with only one thread
   159     //-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool)
   160 	iPermanentlyAllocatedPageCount = 1; 
   161 
   162 	if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
   163 		iMinSizeInPages = iPermanentlyAllocatedPageCount;
   164 
   165 	for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
   166 		{
   167 		TDynamicDirCachePage* pPage = AllocateAndLockNewPageL(0);
   168 		AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   169 		LookupTblAdd(pPage);
   170 		}
   171 
   172 	}
   173 
   174 /**
   175 Static factory function of CDynamicDirCache
   176 */
   177 CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName)
   178     {
   179     __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<<aPageSizeLog2);
   180     CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2);
   181     CleanupStack::PushL(pSelf);
   182     pSelf->ConstructL(aClientName);
   183     CleanupStack::Pop();
   184     return pSelf;
   185     }
   186 
   187 /**
   188 Insert an unlocked page into the last position of the locked queue, may squeeze the original last page into
   189 the unlocked queue.
   190 This function is used on last visited but 'unlocked' pages to avoid excessive lock/unlock calls to cache memory
   191 manager as contiguous entry reading/writing often happens on the same page.
   192 @param	aPage	the page to be inserted.
   193 @pre	the page type of aPage should only be TDynamicDirCachePage::EUnknown
   194 */
   195 void CDynamicDirCache::MakePageLastLocked(TDynamicDirCachePage* aPage)
   196 	{
   197 	// this function should not be called on active pages
   198 	ASSERT(aPage->iType == TDynamicDirCachePage::EUnknown);
   199 
   200 	if (iLockedQ.IsEmpty())
   201 		{
   202 		// if locked queue is empty, add it onto the locked queue directly
   203 		AddFirstOntoQueue(aPage, TDynamicDirCachePage::ELocked);
   204 		}
   205 	else
   206 		{
   207 		// otherwise, we squeeze for the last position on locked queue
   208 		while (iLockedQCount + 1 >= iMinSizeInPages)
   209 			{
   210 			TDynamicDirCachePage* last = iLockedQ.Last();
   211 			DeQueue(last);
   212 			UnlockPage(last);
   213 			AddFirstOntoQueue(last, TDynamicDirCachePage::EUnlocked);
   214 			}
   215 
   216 		// iLockedQCount + 1 < iMinSizeInPages
   217 		iLockedQ.AddLast(*aPage);
   218 		aPage->SetPageType(TDynamicDirCachePage::ELocked);
   219 		iLockedQCount++;
   220 		}
   221 	}
   222 
   223 /**
   224     Read data from a single page. If the page is not found or not valid anymore, read media onto iActive page first.
   225     The data will be _Appended_ the the descriptor aDes. The caller is responsible for maintaining this descriptor.
   226 
   227     @param	aPos	the starting position of the media address to be read.
   228     @param	aLength	the length of the content to be read.
   229     @param	aDes	the descriptor to contain the content.
   230     @pre	aLength should be no more than page size.
   231 */
   232 void CDynamicDirCache::ReadDataFromSinglePageL(TInt64 aPos, TInt aLength, TDes8& aDes)
   233 	{
   234     //-- the data section is in the cache page entirely, take data directly from the cache
   235 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   236     if (pPage)
   237     	{
   238 		// lock page before reading,
   239     	if (LockPage(pPage) != NULL)
   240     		{
   241     		// read data and append them to the descriptor
   242             aDes.Append(pPage->PtrInPage(aPos), aLength);
   243 
   244 
   245             // if page is from unlocked queue, insert it onto the last page of the locked
   246             //  queue. this is to avoid excessive locking and unlocking operations that is
   247             //  highly likely to happen for following reads.
   248             if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   249             	{
   250             	DeQueue(pPage);
   251             	MakePageLastLocked(pPage);
   252             	}
   253     		}
   254     	else	// page locking failed
   255     		{
   256     		ASSERT(pPage->PageType() == TDynamicDirCachePage::EUnlocked);
   257     		DeQueue(pPage);
   258     		LookupTblRemove(pPage->StartPos());
   259     		DecommitPage(pPage);
   260     		delete pPage;
   261     		pPage = NULL;
   262     		}
   263     	}
   264 
   265 	if (!pPage)
   266 		{
   267         // if page not found or page data not valid anymore, use active page to read data in
   268         pPage = UpdateActivePageL(aPos);
   269         // read data and append them to the descriptor
   270         aDes.Append(pPage->PtrInPage(aPos), aLength);
   271     	}
   272 
   273 	}
   274 
   275 //====================================================================
   276 /**
   277 Implementation of pure virtual function.
   278 @see	MWTCacheInterface::ReadL()
   279 */
   280 void CDynamicDirCache::ReadL(TInt64 aPos, TInt aLength, TDes8& aDes)
   281 	{
   282 #ifdef _DEBUG
   283     if(iCacheDisabled)
   284         {
   285         // cache is disabled for debug purposes
   286         __PRINT(_L("CDynamicDirCache disabled"));
   287         User::LeaveIfError(iDrive.ReadNonCritical(aPos, aLength, aDes));
   288         return;
   289         }
   290 #endif //_DEBUG
   291 
   292     aDes.Zero();
   293     const TUint32 PageSz = iPageSizeInBytes;//-- cache page size
   294 
   295     TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   296     const TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos); //-- number of bytes from aPos to the end of the page
   297 
   298 //    __PRINT5(_L("CDynamicDirCache::ReadL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, aLength, pageStartMedPos, PageSz, bytesToPageEnd);
   299     // if all data needed is on a single page
   300     if((TUint32)aLength <= bytesToPageEnd)
   301         {
   302         ReadDataFromSinglePageL(aPos, aLength, aDes);
   303         }
   304     // or data to be read cross cache page boundary or probably we have more than 1 page to read
   305     else
   306         {
   307         __PRINT(_L("CDynamicDirCache::ReadL() CROSS PAGE!"));
   308         TUint32 dataLen(aLength);   //-- current data length
   309         TInt64  currMediaPos(aPos); //-- current media position
   310 
   311         //-- 1. read data that are already in the current page
   312         ReadDataFromSinglePageL(currMediaPos, bytesToPageEnd, aDes);
   313         dataLen -= bytesToPageEnd;
   314         currMediaPos += bytesToPageEnd;
   315 
   316         //-- 2. read whole pages of data
   317         while (dataLen >= PageSz)
   318         	{
   319         	//-- find out if currMediaPos is in cache. If not, find a spare page and read data there
   320             ReadDataFromSinglePageL(currMediaPos, PageSz, aDes);
   321             currMediaPos += PageSz;
   322             dataLen -= PageSz;
   323         	}
   324 
   325         //-- 3. read the rest of the data
   326         if(dataLen > 0)
   327             {
   328             ReadDataFromSinglePageL(currMediaPos, dataLen, aDes);
   329             }
   330         } //else((TUint32)aLength <= bytesToPageEnd)
   331 	}
   332 
   333 /**
   334 Write data through a single page. If the page is not found or not valid anymore, read media onto iActive page
   335 first, then write data through iActive page.
   336 @param	aPos	the starting position of the media address to be write.
   337 @param	aData	the starting address that the writing content lives in the ram.
   338 @param	aDataLen	the length of the content to be written.
   339 @pre	aDataLen	should be no more than page size.
   340 */
   341 void CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen)
   342 	{
   343 	ASSERT(aDataLen <= iPageSizeInBytes);
   344     //-- the data section is in the cache page entirely, take data directly from the cache
   345 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   346     if (pPage)
   347     	{
   348 		// lock page before writing,
   349     	if (LockPage(pPage) != NULL)
   350     		{
   351     		//-- update cache
   352             Mem::Copy(pPage->PtrInPage(aPos), aData, aDataLen);
   353     		}
   354     	else
   355     		{
   356     		ASSERT(pPage->PageType() == TDynamicDirCachePage::EUnlocked);
   357     		DeQueue(pPage);
   358     		LookupTblRemove(pPage->StartPos());
   359     		DecommitPage(pPage);
   360     		delete pPage;
   361     		pPage = NULL;
   362     		}
   363     	}
   364 
   365     // if page not found or page data not valid anymore, use active page to read data in
   366     if (!pPage)
   367     	{
   368         pPage = UpdateActivePageL(aPos);
   369         //-- update cache
   370         Mem::Copy(pPage->PtrInPage(aPos), aData, aDataLen);
   371     	}
   372 
   373 	// make sure the page is unlocked after use
   374 	if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   375 		{
   376 		UnlockPage(pPage);
   377 		}
   378 
   379 	// always make writting events MRU
   380 	DoMakePageMRU(aPos);
   381     return;
   382 	}
   383 
   384 /**
   385 Implementation of pure virtual function.
   386 @see	MWTCacheInterface::WriteL()
   387 */
   388 void CDynamicDirCache::WriteL(TInt64 aPos,const TDesC8& aDes)
   389 	{
   390 #ifdef _DEBUG
   391     if(iCacheDisabled)
   392         {
   393         // cache is disabled for debug purposes
   394         __PRINT(_L("CDynamicDirCache disabled"));
   395         User::LeaveIfError(iDrive.WriteCritical(aPos,aDes));
   396         return;
   397         }
   398 #endif //_DEBUG
   399 
   400     TUint32 dataLen = aDes.Size();
   401     const TUint8* pData   = aDes.Ptr();
   402     const TUint32 PageSz  = iPageSizeInBytes; //-- cache page size
   403 
   404     TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   405     TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos);
   406 
   407 //    __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd);
   408 
   409     if(dataLen <= bytesToPageEnd)
   410         {
   411         WriteDataOntoSinglePageL(aPos, pData, dataLen);
   412         }
   413     else
   414         {
   415         __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!"));
   416 
   417         //-- Data to be written cross cache page boundary or probably we have more than 1 page to write
   418         TInt64  currMediaPos(aPos);
   419 
   420         //-- 1. update the current page
   421         WriteDataOntoSinglePageL(currMediaPos, pData, bytesToPageEnd);
   422 
   423         pData += bytesToPageEnd;
   424         currMediaPos += bytesToPageEnd;
   425         dataLen -= bytesToPageEnd;
   426 
   427         //-- 2. write whole pages of data to the cache
   428         while (dataLen >= PageSz)
   429         	{
   430             WriteDataOntoSinglePageL(currMediaPos, pData, PageSz);
   431 
   432             pData += PageSz;
   433             currMediaPos += PageSz;
   434             dataLen -= PageSz;
   435         	}
   436 
   437         //-- 3. write the rest of the data
   438         if(dataLen > 0)
   439             {
   440             WriteDataOntoSinglePageL(currMediaPos, pData, dataLen);
   441             }
   442         }// else(dataLen <= bytesToPageEnd)
   443 
   444 
   445     //-- write data to the media
   446     const TInt nErr = iDrive.WriteCritical(aPos,aDes);
   447     if(nErr != KErrNone)
   448         {//-- some serious problem occured during writing, invalidate cache.
   449         InvalidateCache();
   450         User::Leave(nErr);
   451         }
   452 	}
   453 
   454 /**
   455     Invalidate the cache
   456     @see	MWTCacheInterface::InvalidateCache()
   457 */
   458 void CDynamicDirCache::DoInvalidateCache(void)
   459 	{
   460 	__PRINT2(_L("CDynamicDirCache::InvalidateCache(locked=%d, unlocked=%d)"), iLockedQCount, iUnlockedQCount);
   461 	// we should never decommit locked pages as they needs to be reserved anyway
   462 	// the overhead of unnecessary page committing operations
   463 
   464 	TInt pagesToRemoveFromLockedQueue = iLockedQCount - iPermanentlyAllocatedPageCount;
   465 	TInt n;
   466 	for (n=0; n<pagesToRemoveFromLockedQueue; n++)
   467 		{
   468 		TDynamicDirCachePage* page = iLockedQ.Last();
   469 		DeQueue(page);						// remove from queue
   470 		LookupTblRemove(page->StartPos());	// remove from lookuptable
   471 		DecommitPage(page);					// inform cache client to decommit page memory
   472 		delete page;
   473 		}
   474 	ASSERT(iLockedQCount == iPermanentlyAllocatedPageCount);
   475 
   476 	TDblQueIter<TDynamicDirCachePage> q(iLockedQ);
   477 	q.SetToFirst();
   478 	while((TDynamicDirCachePage*) q)
   479 		{
   480 		TDynamicDirCachePage* page = q++;
   481 		LookupTblRemove(page->StartPos());// remove from lookuptable
   482 		ResetPagePos(page);				// reset start media position (0), invalidate page content
   483 		}
   484 
   485 	// however we should decommit unlocked pages here
   486 	while (!iUnlockedQ.IsEmpty())
   487 		{
   488 		TDynamicDirCachePage* page = iUnlockedQ.Last();
   489 		DeQueue(page);						// remove from queue
   490 		LookupTblRemove(page->StartPos());	// remove from lookuptable
   491 		DecommitPage(page);					// inform cache client to decommit page memory
   492 		delete page;
   493 		}
   494 	ASSERT(iUnlockedQCount == 0);
   495 
   496 	ASSERT(iLockedQCount == iPermanentlyAllocatedPageCount);
   497 
   498 	ASSERT(iCacheMemoryClient);
   499 	}
   500 
   501 /**
   502 Implementation of pure virtual function.
   503 @see	MWTCacheInterface::InvalidateCache()
   504 */
   505 void CDynamicDirCache::InvalidateCache(void)
   506 	{
   507 	DoInvalidateCache();
   508 	}
   509 
   510 /** this method isn't implemented*/
   511 void CDynamicDirCache::InvalidateCachePage(TUint64 /*aPos*/)
   512     {
   513     ASSERT(0);
   514     }
   515 
   516 
   517 /**
   518 Implementation of pure virtual function.
   519 @see	MWTCacheInterface::PosCached()
   520 */
   521 TUint32 CDynamicDirCache::PosCached(const TInt64& aPos, TInt64& aCachedPosStart)
   522 	{
   523 	const TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   524 
   525 	// only search the page in lookup table
   526 	// NOTE: we don't count the active page into acount here,
   527 	// this is to avoid pulling next pages recursively
   528 	TDynamicDirCachePage* pPage = LookupTblFind(pageStartMedPos);
   529 
   530 	// then check if page is still valid if page is on Unlocked Page Queue
   531 	if (pPage && pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   532 		{
   533 		if (LockPage(pPage) != NULL)
   534 			{
   535 //			__PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos);
   536 			// have to unlock it before returning, otherwise there will be memory leak
   537 			UnlockPage(pPage);
   538     	    aCachedPosStart = pPage->StartPos();
   539 			return pPage->PageSizeInBytes();
   540 			}
   541 		else	// if the unlocked page is not valid anymore, remove it
   542 			{
   543     		DeQueue(pPage);
   544     		LookupTblRemove(pPage->StartPos());
   545     		DecommitPage(pPage);
   546     		delete pPage;
   547     		pPage = NULL;
   548 			}
   549 		}
   550 	// otherwise if page is already locked or valid active page
   551 	else if (pPage)
   552 		{
   553 		__PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) on Locked Queue!"), aPos);
   554 	    aCachedPosStart = pPage->StartPos();
   555 		return pPage->PageSizeInBytes();
   556 		}
   557 
   558 	// page is not found or not valid anymore
   559 	return 0;
   560 	}
   561 
   562 /**
   563 Implementation of pure virtual function.
   564 @see	MWTCacheInterface::CacheSizeInBytes()
   565 */
   566 TUint32 CDynamicDirCache::CacheSizeInBytes()  const
   567 	{
   568 	return iMaxCacheSizeInBytes;
   569 	}
   570 
   571 /**
   572 Implementation of pure virtual function.
   573 @see	MWTCacheInterface::Control()
   574 */
   575 TInt CDynamicDirCache::Control(TUint32 aFunction, TUint32 aParam1, TAny* aParam2)
   576 	{
   577     TInt r = KErrNotSupported;
   578 #ifdef _DEBUG
   579     (void)aParam2;
   580     switch(aFunction)
   581         {
   582         // disable / enable cache, for debug
   583         // if aParam1 != 0 cache will be disabled, enabled otherwise
   584         case EDisableCache:
   585             iCacheDisabled = aParam1 ? 1 : 0;
   586             r = KErrNone;
   587         break;
   588 
   589         // dump cache, for debug
   590         case EDumpCache:
   591         	{
   592         	RFs fs;
   593         	fs.Connect();
   594         	const TUint32 debugRegister = DebugRegister();
   595         	fs.SetDebugRegister(debugRegister|KFSYS);
   596         	Dump();
   597         	fs.SetDebugRegister(debugRegister);
   598         	fs.Close();
   599         	break;
   600         	}
   601         case ECacheInfo:
   602         	{
   603         	RFs fs;
   604         	fs.Connect();
   605         	const TUint32 debugRegister = DebugRegister();
   606         	fs.SetDebugRegister(debugRegister|KFSYS);
   607         	Info();
   608         	fs.SetDebugRegister(debugRegister);
   609         	fs.Close();
   610         	break;
   611         	}
   612 
   613         default:
   614             __PRINT1(_L("CDynamicDirCache::Control() invalid function: %d"), aFunction);
   615             ASSERT(0);
   616         break;
   617         }
   618 
   619 #else
   620     (void)aFunction; //-- supress warnings
   621     (void)aParam1;
   622     (void)aParam2;
   623     User::Invariant(); //-- don't call this method in release build
   624 #endif //_DEBUG
   625 
   626     return r;
   627 	}
   628 
   629 /**
   630 Implementation of pure virtual function.
   631 @see	MWTCacheInterface::SetCacheBasePos()
   632 */
   633 void CDynamicDirCache::SetCacheBasePos(TInt64 aBasePos)
   634 	{
   635 	iCacheBasePos = aBasePos;
   636 	}
   637 
   638 /**
   639 Implementation of pure virtual function.
   640 @see	MWTCacheInterface::SetCacheBasePos()
   641 */
   642 TUint32 CDynamicDirCache::PageSizeInBytesLog2() const
   643 	{
   644 	return iPageSizeLog2;
   645 	}
   646 
   647 
   648 void CDynamicDirCache::DoMakePageMRU(TInt64 aPos)
   649 	{
   650 //	__PRINT1(_L("MakePageMRU (%lx)"), aPos);
   651 //	__PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages);
   652 	// check the MRU page first, if it is already the MRU page, we can return immediately
   653 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   654 	if (!iLockedQ.IsEmpty())
   655 		{
   656 		if (iLockedQ.First()->StartPos() == pageStartMedPos)
   657 			{
   658 			return;
   659 			}
   660 		}
   661 
   662 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   663     if (pPage)
   664     	{
   665     	ASSERT(pPage->IsValid());
   666 		// lock page before make it MRU
   667     	if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   668     		{
   669     		ASSERT(!pPage->IsLocked());
   670         	if (LockPage(pPage) == NULL)
   671         		{
   672         		DeQueue(pPage);
   673         		LookupTblRemove(pPage->StartPos());
   674         		DecommitPage(pPage);
   675         		delete pPage;
   676         		pPage = NULL;
   677         		}
   678     		}
   679     	else
   680     		{
   681     		// error checking: page should either be locked or active
   682     		ASSERT(LockPage(pPage) != NULL);
   683     		}
   684     	}
   685 
   686     // if page not found or page data not valid anymore, use active page to read data
   687     if (!pPage)
   688     	{
   689         TRAPD(err, pPage = UpdateActivePageL(aPos));
   690         if (err != KErrNone)
   691         	{
   692         	// problem occurred reading active page, return immediately.
   693         	return;
   694         	}
   695     	}
   696 
   697     // by now, the page is either locked or active page
   698 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   699 
   700 
   701 
   702 	TBool allocateNewPage = pPage == iLockedQ.Last() && !CacheIsFull();
   703 
   704 
   705 	switch (pPage->PageType())
   706 		{
   707 		case TDynamicDirCachePage::EUnlocked:
   708 			{
   709 			// if page was originally on Unlocked Page Queque, remove it from Unlocked Page Queue, add it
   710 			// to the Locked Page Queue and make it MRU
   711 			DeQueue(pPage);
   712 			AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   713 			// check cache limit
   714 			CheckThresholds();
   715 			}
   716 		case TDynamicDirCachePage::ELocked:
   717 			{
   718 			// otherwise the page was on Locked Page Queue, make it MRU
   719 			// no need to check cache limit
   720 			if (pPage != iLockedQ.First())
   721 				{
   722 				DeQueue(pPage);
   723 				AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   724 				}
   725 			break;
   726 			}
   727 		default:
   728 			ASSERT(0);
   729 		}
   730 
   731 	if (allocateNewPage)
   732 		{
   733 		TDynamicDirCachePage* nPage = NULL;
   734 		TRAPD(err, nPage = AllocateAndLockNewPageL(0));
   735 		if (err == KErrNone)
   736 			{
   737 
   738 			// about to add a page to end of locked queue, so lie about iLockedQCount
   739 			iLockedQCount++;
   740 			CheckThresholds();
   741 			iLockedQCount--;
   742 
   743 			iLockedQ.AddLast(*nPage);
   744 			nPage->SetPageType(TDynamicDirCachePage::ELocked);
   745 			++iLockedQCount;
   746 			LookupTblAdd(nPage);
   747 			}
   748 		}
   749 	}
   750 
   751 /**
   752     Implementation of pure virtual function.
   753     @see	MDiskSpecialAccessor::MakePageMRU()
   754 */
   755 void CDynamicDirCache::MakePageMRU(TInt64 aPos)
   756 	{
   757 	DoMakePageMRU(aPos);
   758 	}
   759 
   760 //====================================================================
   761 /**
   762 Internal query function, to check if aPos is cached or not. iActive page is included in searching.
   763 */
   764 TDynamicDirCachePage* CDynamicDirCache::FindPageByPos(TInt64 aPos)
   765 	{
   766 //	__PRINT1(_L("CDynamicDirCache::FindPageByPos(aPos=%lx)"), aPos);
   767     // align the page position
   768 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   769 
   770 	// search in lookup table
   771 	return LookupTblFind(pageStartMedPos);
   772 	}
   773 
   774 /**
   775 read a page length data into iActive page and return iActive page if read is successful.
   776 */
   777 TDynamicDirCachePage* CDynamicDirCache::UpdateActivePageL(TInt64 aPos)
   778 	{
   779     // align the page position
   780 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   781 
   782 	ASSERT(!iLockedQ.IsEmpty());
   783 	TDynamicDirCachePage* activePage = iLockedQ.Last();
   784 
   785 	if (activePage->StartPos() == pageStartMedPos && activePage->IsValid())
   786 		{
   787 		return activePage;
   788 		}
   789 
   790 	__PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos());
   791 
   792 	activePage->Deque();
   793 	LookupTblRemove(activePage->StartPos());
   794 
   795 	// set start med pos value, no other effects, only available to active page
   796 	activePage->SetPos(pageStartMedPos);
   797 
   798 	// read data, make active page valid
   799 	TUint8* data = activePage->PtrInPage(activePage->iStartMedPos);
   800     TPtr8 dataPtr(data, iPageSizeInBytes);
   801 	
   802     const TInt nErr = iDrive.ReadNonCritical(activePage->iStartMedPos, iPageSizeInBytes, dataPtr);
   803 
   804 	iLockedQ.AddLast(*activePage);
   805 	LookupTblAdd(activePage);
   806 
   807     if(nErr !=KErrNone)
   808         {
   809         // some serious problem occured during reading, invalidate cache.
   810         DoInvalidateCache();
   811         User::Leave(nErr);
   812         }
   813     activePage->SetValid(ETrue);
   814 
   815     return activePage;
   816 	}
   817 
   818 /**
   819 Check if the number of (locked pages + iActive page) and unlocked pages have exceeded minimum allowed page
   820 number and maximum allowed page number respectively.
   821 */
   822 void CDynamicDirCache::CheckThresholds()
   823 	{
   824 	while (iLockedQCount + 1 > iMinSizeInPages)
   825 		{
   826 		TDynamicDirCachePage* movePage = iLockedQ.Last();
   827 		UnlockPage(movePage);
   828 		DeQueue(movePage);
   829 		TInt err = LookupTblRemove(movePage->StartPos());
   830 		ASSERT(err == KErrNone);
   831 
   832 		// if it is a valid page, add onto unlocked queue
   833 		if (movePage->StartPos() != 0)
   834 			{
   835 			ASSERT(movePage->IsValid());
   836 			AddFirstOntoQueue(movePage, TDynamicDirCachePage::EUnlocked);
   837 			err = LookupTblAdd(movePage);
   838 			ASSERT(err == KErrNone);
   839 			}
   840 		else // reserved page, delete
   841 			{
   842 			DecommitPage(movePage);
   843 			delete movePage;
   844 			}
   845 		}
   846 
   847 	// if unlocked queue exceeds limit, delete LRU page
   848 	// note: all pages on unlocked queue should be valid
   849 	while (iUnlockedQCount > iMaxSizeInPages - iMinSizeInPages)
   850 		{
   851 		TDynamicDirCachePage* removePage = iUnlockedQ.Last();
   852 		ASSERT(removePage->StartPos() != 0 && removePage->IsValid());
   853 		DeQueue(removePage);
   854 		LookupTblRemove(removePage->StartPos());
   855 		DecommitPage(removePage);
   856 		delete removePage;
   857 		}
   858 	}
   859 
   860 /**
   861 Try to create a new page and lock the page content when it is created. This function should only be called
   862 when creating iActive page or making a page MRU (which might result in page evictions).
   863 @return	the pointer of the newly created page, or NULL if allocation failed.
   864 @param	aStartMedPos	the starting media address of the page to be created.
   865 @pre	aStartMedPos should not already be existing in the cache.
   866 */
   867 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPageL(TInt64 aStartMedPos)
   868 	{
   869 	__PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPageL(aStartMedPos=%lx)"), aStartMedPos);
   870 
   871 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   872 	if (startRamAddr)
   873 		{
   874 		// create new page and return
   875 		TDynamicDirCachePage* pPage = TDynamicDirCachePage::NewL(this, aStartMedPos, startRamAddr);
   876 		pPage->SetLocked(ETrue);
   877 		pPage->SetValid(EFalse);
   878 		return pPage;
   879 		}
   880 
   881 	return NULL;
   882 	}
   883 
   884 #ifdef _DEBUG
   885 /**
   886 Dump cache information, only enabled in debug mode.
   887 @see CDynamicDirCache::Control()
   888 */
   889 void CDynamicDirCache::Info() const
   890 	{
   891 	__PRINT(_L("======== CDynamicDirCache::Info ========="));
   892 	const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
   893 	// page size
   894 	__PRINT1(_L("=== Pages size:               [%d Bytes]"), iPageSizeInBytes);
   895 	__PRINT1(_L("=== Segment size:             [%d Bytes]"), 1 << SegmentSizeInBytesLog2);
   896 
   897 	// data size:
   898 	__PRINT1(_L("=== Min data size:            [%d Bytes]"), iMinSizeInPages << iPageSizeLog2);
   899 	__PRINT1(_L("=== Max data size:            [%d Bytes]"), iMaxSizeInPages << iPageSizeLog2);
   900 
   901 	// memory size:
   902 	const TUint32 pageMemSizeLog2 = iPageSizeLog2 > SegmentSizeInBytesLog2 ? iPageSizeLog2 : SegmentSizeInBytesLog2;
   903 	__PRINT1(_L("=== Min memory size:          [%d Bytes]"), iMinSizeInPages << pageMemSizeLog2);
   904 	__PRINT1(_L("=== Max memory size:          [%d Bytes]"), iMaxSizeInPages << pageMemSizeLog2);
   905 
   906 	// reserved pages
   907 	__PRINT1(_L("=== Number of pages reserved: [%d]"), iMinSizeInPages);
   908 	__PRINT1(_L("=== Reserved memory:          [%d Bytes]"), (iMinSizeInPages * PageSizeInSegs()) << SegmentSizeInBytesLog2);
   909 	// locked page num
   910 	__PRINT1(_L("=== Number of pages locked:   [%d]"), iLockedQCount);
   911 	__PRINT1(_L("=== Locked memory:            [%d Bytes]"), (iLockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
   912 	// unlocked page num
   913 	__PRINT1(_L("=== Number of pages unlocked: [%d]"), iUnlockedQCount);
   914 	__PRINT1(_L("=== Unlocked memory:          [%d Bytes]"), (iUnlockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
   915 	}
   916 
   917 /**
   918 Dump cache content, only enabled in debug mode.
   919 @see CDynamicDirCache::Control()
   920 */
   921 void CDynamicDirCache::Dump()
   922 	{
   923 	__PRINT(_L("======== CDynamicDirCache::Dump ========="));
   924 	if (!iLockedQ.IsEmpty())
   925 		{
   926 		TDblQueIter<TDynamicDirCachePage> q(iLockedQ);
   927 		q.SetToFirst();
   928 		TInt i = 0;
   929 		while((TDynamicDirCachePage*)q)
   930 			{
   931 			TDynamicDirCachePage* pP = q++;
   932 			__PRINT5(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
   933 			}
   934 		}
   935 	if (!iUnlockedQ.IsEmpty())
   936 		{
   937 		TDblQueIter<TDynamicDirCachePage> q(iUnlockedQ);
   938 		q.SetToFirst();
   939 		TInt i = 0;
   940 		while((TDynamicDirCachePage*)q)
   941 			{
   942 			TDynamicDirCachePage* pP = q++;
   943 			__PRINT5(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
   944 			}
   945 		}
   946 
   947 	if (iLookupTable.Count())
   948 		{
   949 		TInt i = 0;
   950 		THashSetIter<TLookupEntry> iter(iLookupTable);
   951 		TLookupEntry* pEntry;
   952 		pEntry = (TLookupEntry*) iter.Next();
   953 		while(pEntry)
   954 			{
   955 			TDynamicDirCachePage* pP = pEntry->iPage;
   956 			__PRINT5(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
   957 			pEntry = (TLookupEntry*) iter.Next();
   958 			};
   959 		}
   960 	__PRINT(_L("===========================================\n"));
   961 	}
   962 #endif //_DEBUG
   963 
   964 /**
   965 Lock an unlocked page, or do nothing if the page is already locked.
   966 @return	TUint8*	pointer of the page to be locked, if locking is successful, otherwise return NULL.
   967 @param	aPage	the pointer of the page to be locked.
   968 */
   969 TUint8* CDynamicDirCache::LockPage(TDynamicDirCachePage* aPage)
   970 	{
   971 	ASSERT(aPage != NULL);
   972 	if (aPage->IsLocked())
   973 		return aPage->StartPtr();
   974 
   975 	TInt r = iCacheMemoryClient->LockSegments(aPage->StartPtr(), PageSizeInSegs());
   976 	if (r == KErrNone)
   977 		{
   978 		aPage->SetLocked(ETrue);
   979 		return aPage->StartPtr();
   980 		}
   981 
   982 	return NULL;
   983 	}
   984 
   985 /**
   986 Unlock a locked page.
   987 @return	TInt	KErrNone if unlocking was successful, otherwise system-wide error code.
   988 @param	aPage	the pointer of the page to be unlocked.
   989 */
   990 TInt CDynamicDirCache::UnlockPage(TDynamicDirCachePage* aPage)
   991 	{
   992 	ASSERT(aPage != NULL);
   993 	__PRINT1(_L("CDynamicDirCache::UnlockPage(%lx)"), aPage->StartPos());
   994 	TInt r = iCacheMemoryClient->UnlockSegments(aPage->StartPtr(), PageSizeInSegs());
   995 	if (r == KErrNone)
   996 		{
   997 		aPage->SetLocked(EFalse);
   998 		}
   999 	return r;
  1000 	}
  1001 
  1002 /**
  1003 Decommit a locked or unlocked page.
  1004 @return	TInt	KErrNone if decommition was successful, otherwise system-wide error code.
  1005 @param	aPage	the pointer of the page to be decommitted.
  1006 */
  1007 TInt CDynamicDirCache::DecommitPage(TDynamicDirCachePage* aPage)
  1008 	{
  1009 	ASSERT(aPage != NULL);
  1010 	__PRINT1(_L("CDynamicDirCache::DecommitPage(%lx)"), aPage->StartPos());
  1011 	if (aPage)
  1012 		{
  1013 		TInt r = iCacheMemoryClient->DecommitSegments(aPage->StartPtr(), PageSizeInSegs());
  1014 		if (r == KErrNone)
  1015 			{
  1016 			aPage->SetLocked(EFalse);
  1017 			aPage->SetValid(EFalse);
  1018 			}
  1019 		return r;
  1020 		}
  1021 	return KErrArgument;
  1022 	}
  1023 
  1024 /////////////////////////// aluxiliary functions //////////////////////////////////
  1025 /**
  1026 Calculate the page size in segments. Segment size is the size of the kernel memory unit that cache memory manager manages.
  1027 We are making assumption here about the page size: page size should always be either less than segment size
  1028 or multiple times of segment size
  1029 @return	TUint32	the page size in segments.
  1030 */
  1031 TUint32 CDynamicDirCache::PageSizeInSegs() const
  1032 	{
  1033 	// initialize cache memory manager as all file systems have mounted by now
  1034 	ASSERT(CCacheMemoryManagerFactory::CacheMemoryManager());
  1035 	const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
  1036 
  1037 	// Page size should be non-zero
  1038 	ASSERT(iPageSizeInBytes);
  1039 
  1040 	TUint32 segs = iPageSizeInBytes >> SegmentSizeInBytesLog2;
  1041 	return segs > 0 ? segs : 1;
  1042 	}
  1043 
  1044 /**
  1045 Deque the page from locked queue or unlocked queue. All pages are managed through these two queues, expect iActive
  1046 page.
  1047 @param	aPage	the pointer of the page to be dequeued
  1048 @return	TInt	KErrArgument if aPage is invalid, otherwise KErrNone.
  1049 */
  1050 TInt CDynamicDirCache::DeQueue(TDynamicDirCachePage* aPage)
  1051 	{
  1052 	ASSERT(aPage);
  1053 	if (!aPage)
  1054 		return KErrArgument;
  1055 
  1056 	if (aPage->iType == TDynamicDirCachePage::ELocked)
  1057 		{
  1058 		aPage->Deque();
  1059 		aPage->SetPageType(TDynamicDirCachePage::EUnknown);
  1060 		--iLockedQCount;
  1061 		}
  1062 	else if (aPage->iType == TDynamicDirCachePage::EUnlocked)
  1063 		{
  1064 		aPage->Deque();
  1065 		aPage->SetPageType(TDynamicDirCachePage::EUnknown);
  1066 		--iUnlockedQCount;
  1067 		}
  1068 	else
  1069 		{
  1070 		ASSERT(0);
  1071 		return KErrArgument;
  1072 		}
  1073 	return KErrNone;
  1074 	}
  1075 
  1076 /**
  1077 Insert a page to the first position of locked queue or unlocked queue.
  1078 @param	aPage	the pointer of the page to be inserted.
  1079 @param	aType	the type of the queue to be inserted.
  1080 @return	TInt	KErrArgument if aPage is invalid, otherwise KErrNone.
  1081 */
  1082 TInt CDynamicDirCache::AddFirstOntoQueue(TDynamicDirCachePage* aPage, TDynamicDirCachePage::TPageType aType)
  1083 	{
  1084 	ASSERT(aPage);
  1085 	if (!aPage)
  1086 		return KErrArgument;
  1087 
  1088 	if (aType == TDynamicDirCachePage::ELocked)
  1089 		{
  1090 		iLockedQ.AddFirst(*aPage);
  1091 		aPage->SetPageType(TDynamicDirCachePage::ELocked);
  1092 		++iLockedQCount;
  1093 		}
  1094 	else if (aType == TDynamicDirCachePage::EUnlocked)
  1095 		{
  1096 		iUnlockedQ.AddFirst(*aPage);
  1097 		aPage->SetPageType(TDynamicDirCachePage::EUnlocked);
  1098 		++iUnlockedQCount;
  1099 		}
  1100 	else
  1101 		{
  1102 		ASSERT(0);
  1103 		return KErrArgument;
  1104 		}
  1105 
  1106 	return KErrNone;
  1107 	}
  1108 
  1109 /**
  1110 Remove a page from the lookup table, indexed by the starting media address of the page content.
  1111 @param	aPagePos	the starting media position of the page to be removed.
  1112 */
  1113 TInt CDynamicDirCache::LookupTblRemove(TInt64 aPagePos)
  1114 	{
  1115 	if (aPagePos == 0)
  1116 		{
  1117 		return KErrNone;
  1118 		}
  1119 
  1120 	TInt r = iLookupTable.Remove(TLookupEntry(aPagePos, 0, NULL));
  1121 	return r;
  1122 	}
  1123 
  1124 /**
  1125 Insert a page to the lookup table, indexed by the starting media address of the page content.
  1126 @param	aPagePos	the starting media position of the page to be inserted.
  1127 */
  1128 TInt CDynamicDirCache::LookupTblAdd(TDynamicDirCachePage* aPage)
  1129 	{
  1130 	ASSERT(aPage);
  1131 	if (!aPage)
  1132 		return KErrArgument;
  1133 
  1134 	if (aPage->StartPos() == 0)
  1135 		{
  1136 		return KErrNone;
  1137 		}
  1138 
  1139 	TInt r = iLookupTable.Insert(TLookupEntry(aPage->StartPos(), iPageSizeInBytes, aPage));
  1140 	return r;
  1141 	}
  1142 
  1143 /**
  1144 Reset the media address of the page to 0, also invalidate the page.
  1145 @param	aPage	the pointer of the page to be reset.
  1146 */
  1147 TInt CDynamicDirCache::ResetPagePos(TDynamicDirCachePage* aPage)
  1148 	{
  1149 	ASSERT(aPage);
  1150 	if (!aPage)
  1151 		return KErrArgument;
  1152 
  1153 	aPage->ResetPos();
  1154 	return KErrNone;
  1155 	}
  1156 
  1157 /**
  1158 Search the lookup table to find the page start with a specific media address.
  1159 @param	aPos	the starting media address to be searched.
  1160 */
  1161 TDynamicDirCachePage* CDynamicDirCache::LookupTblFind(TInt64 aPos)
  1162 	{
  1163 	if (aPos == 0)
  1164 		{
  1165 		ASSERT(0);
  1166 		return NULL;
  1167 		}
  1168 
  1169 	TLookupEntry* entry = iLookupTable.Find(TLookupEntry(aPos, 0, NULL));
  1170 	if(entry)
  1171 		{
  1172 		// last entry on used queue is used as the 'active' page & may not be valid
  1173 		if (!entry->iPage->IsValid())
  1174 			return NULL;
  1175 
  1176 		return entry->iPage;
  1177 		}
  1178 
  1179 	return NULL;
  1180 	}