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