userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp
changeset 176 af6ec97d9189
parent 90 947f0dc9f7a8
equal deleted inserted replaced
175:5af6c74cd793 176:af6ec97d9189
    25 
    25 
    26 /**
    26 /**
    27 The static cache page creation function.
    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.
    28 Cache page objects are not supposed to be created on the stack, so this factory function is required.
    29 */
    29 */
    30 TDynamicDirCachePage* TDynamicDirCachePage::NewL(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr)
    30 TDynamicDirCachePage* TDynamicDirCachePage::CreateCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr)
    31 	{
    31 	{
    32 	return new(ELeave) TDynamicDirCachePage(aOwnerCache, aStartMedPos, aStartRamAddr);
    32 	return new TDynamicDirCachePage(aOwnerCache, aStartMedPos, aStartRamAddr);
    33 	}
    33 	}
    34 
    34 
    35 /**
    35 /**
    36 Cache page constructor.
    36 Cache page constructor.
    37 @param	aOwnerCache	pointer of the cache that owns this page
    37 @param	aOwnerCache	pointer of the cache that owns this page
   111                  :iPageSizeLog2(aPageSizeInBytesLog2),
   111                  :iPageSizeLog2(aPageSizeInBytesLog2),
   112                   iWrGranularityLog2(aWrGranularityLog2),
   112                   iWrGranularityLog2(aWrGranularityLog2),
   113                   iMinSizeInPages(aMinPageNum),
   113                   iMinSizeInPages(aMinPageNum),
   114                   iMaxSizeInPages(aMaxPageNum),
   114                   iMaxSizeInPages(aMaxPageNum),
   115                   iDrive(aDrive),
   115                   iDrive(aDrive),
       
   116 				  iLastVisitedPage(NULL),
   116                   iLockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   117                   iLockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   117                   iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   118                   iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   118                   iLockedQCount(0),
   119                   iLockedQCount(0),
   119                   iUnlockedQCount(0),
   120                   iUnlockedQCount(0),
   120                   iHashFunction(HashFunction),
   121                   iHashFunction(HashFunction),
   157 
   158 
   158 
   159 
   159 	// allocate as many permanently locked pages as there are threads - plus one
   160 	// allocate as many permanently locked pages as there are threads - plus one
   160 	// otherwise DoMakePageMRU() won't work properly with only one thread
   161 	// otherwise DoMakePageMRU() won't work properly with only one thread
   161     //-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool)
   162     //-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool)
   162 	const TUint KThreadCount = 1;
   163     const TUint KThreadCount = 1;
   163 	iPermanentlyAllocatedPageCount = KThreadCount + 1; 
   164     iPermanentlyAllocatedPageCount = KThreadCount; 
   164 
   165 
   165 	if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
   166 	if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
   166 		iMinSizeInPages = iPermanentlyAllocatedPageCount;
   167 		iMinSizeInPages = iPermanentlyAllocatedPageCount;
   167 
   168 
   168 	for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
   169 	for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
   169 		{
   170 		{
   170 		TDynamicDirCachePage* pPage = AllocateAndLockNewPageL(0);
   171         TDynamicDirCachePage* pPage = AllocateAndLockNewPage();
       
   172         ASSERT(pPage);
       
   173         if (!pPage)
       
   174             User::Leave(KErrNoMemory);
   171 		AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   175 		AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   172 		LookupTblAdd(pPage);
   176 		LookupTblAdd(pPage);
   173 		}
   177 		}
   174 
   178 
   175 	}
   179 	}
   186     CleanupStack::Pop();
   190     CleanupStack::Pop();
   187     return pSelf;
   191     return pSelf;
   188     }
   192     }
   189 
   193 
   190 /**
   194 /**
   191 Insert an unlocked page into the last position of the locked queue, may squeeze the original last page into
       
   192 the unlocked queue.
       
   193 This function is used on last visited but 'unlocked' pages to avoid excessive lock/unlock calls to cache memory
       
   194 manager as contiguous entry reading/writing often happens on the same page.
       
   195 @param	aPage	the page to be inserted.
       
   196 @pre	the page type of aPage should only be TDynamicDirCachePage::EUnknown
       
   197 */
       
   198 void CDynamicDirCache::MakePageLastLocked(TDynamicDirCachePage* aPage)
       
   199 	{
       
   200 	// this function should not be called on active pages
       
   201 	ASSERT(aPage->iType == TDynamicDirCachePage::EUnknown);
       
   202 
       
   203 	if (iLockedQ.IsEmpty())
       
   204 		{
       
   205 		// if locked queue is empty, add it onto the locked queue directly
       
   206 		AddFirstOntoQueue(aPage, TDynamicDirCachePage::ELocked);
       
   207 		}
       
   208 	else
       
   209 		{
       
   210 		// otherwise, we squeeze for the last position on locked queue
       
   211 		while (iLockedQCount + 1 >= iMinSizeInPages)
       
   212 			{
       
   213 			TDynamicDirCachePage* last = iLockedQ.Last();
       
   214 			DeQueue(last);
       
   215 			UnlockPage(last);
       
   216 			AddFirstOntoQueue(last, TDynamicDirCachePage::EUnlocked);
       
   217 			}
       
   218 
       
   219 		// iLockedQCount + 1 < iMinSizeInPages
       
   220 		iLockedQ.AddLast(*aPage);
       
   221 		aPage->SetPageType(TDynamicDirCachePage::ELocked);
       
   222 		iLockedQCount++;
       
   223 		}
       
   224 	}
       
   225 
       
   226 /**
       
   227     Read data from a single page. If the page is not found or not valid anymore, read media onto iActive page first.
   195     Read data from a single page. If the page is not found or not valid anymore, read media onto iActive page first.
   228     The data will be _Appended_ the the descriptor aDes. The caller is responsible for maintaining this descriptor.
   196     The data will be _Appended_ the the descriptor aDes. The caller is responsible for maintaining this descriptor.
   229 
   197 
   230     @param	aPos	the starting position of the media address to be read.
   198     @param	aPos	the starting position of the media address to be read.
   231     @param	aLength	the length of the content to be read.
   199     @param	aLength	the length of the content to be read.
   243     		{
   211     		{
   244     		// read data and append them to the descriptor
   212     		// read data and append them to the descriptor
   245             aDes.Append(pPage->PtrInPage(aPos), aLength);
   213             aDes.Append(pPage->PtrInPage(aPos), aLength);
   246 
   214 
   247 
   215 
   248             // if page is from unlocked queue, insert it onto the last page of the locked
   216             // if page is from unlocked queue, try to keep it locked until we move to a 
   249             //  queue. this is to avoid excessive locking and unlocking operations that is
   217             //  different page from the unlocked queue 
   250             //  highly likely to happen for following reads.
   218             // this is to avoid excessive locking and unlocking operations that is
   251             if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   219             //  highly likely to happen when DoFindL() linearly scan through the directory
   252             	{
   220             if (pPage->PageType() == TDynamicDirCachePage::EUnlocked
   253             	DeQueue(pPage);
   221                 && iLastVisitedPage != pPage)
   254             	MakePageLastLocked(pPage);
   222                 {
       
   223                 // Note: iLastVisitedPage may have been moved from unlocked queue to locked queue
       
   224                 if(iLastVisitedPage && iLastVisitedPage->PageType() == TDynamicDirCachePage::EUnlocked)
       
   225                     {
       
   226                     User::LeaveIfError(UnlockPage(iLastVisitedPage));
       
   227                     }
       
   228                 iLastVisitedPage = pPage;
   255             	}
   229             	}
   256     		}
   230     		}
   257     	else	// page locking failed
   231     	else	// page locking failed
   258     		{
   232     		{
   259     		ASSERT(pPage->PageType() == TDynamicDirCachePage::EUnlocked);
   233     		ASSERT(pPage->PageType() == TDynamicDirCachePage::EUnlocked);
   619 
   593 
   620         // dump cache, for debug
   594         // dump cache, for debug
   621         case EDumpCache:
   595         case EDumpCache:
   622         	{
   596         	{
   623         	RFs fs;
   597         	RFs fs;
   624         	fs.Connect();
   598         	r = fs.Connect();
       
   599             if(r != KErrNone)
       
   600                 break;
       
   601 
   625         	const TUint32 debugRegister = DebugRegister();
   602         	const TUint32 debugRegister = DebugRegister();
   626         	fs.SetDebugRegister(debugRegister|KFSYS);
   603         	fs.SetDebugRegister(debugRegister|KFSYS);
   627         	Dump();
   604         	Dump();
   628         	fs.SetDebugRegister(debugRegister);
   605         	fs.SetDebugRegister(debugRegister);
   629         	fs.Close();
   606         	fs.Close();
       
   607         	r = KErrNone;
   630         	break;
   608         	break;
   631         	}
   609         	}
   632         case ECacheInfo:
   610         case ECacheInfo:
   633         	{
   611         	{
   634         	RFs fs;
   612         	RFs fs;
   635         	fs.Connect();
   613         	r = fs.Connect();
       
   614             if(r != KErrNone)
       
   615                 break;
       
   616         	
   636         	const TUint32 debugRegister = DebugRegister();
   617         	const TUint32 debugRegister = DebugRegister();
   637         	fs.SetDebugRegister(debugRegister|KFSYS);
   618         	fs.SetDebugRegister(debugRegister|KFSYS);
   638         	Info();
   619             TDirCacheInfo* aInfo = static_cast<TDirCacheInfo*>(aParam2);
       
   620             Info(aInfo);
   639         	fs.SetDebugRegister(debugRegister);
   621         	fs.SetDebugRegister(debugRegister);
   640         	fs.Close();
   622         	fs.Close();
       
   623         	r = KErrNone;
   641         	break;
   624         	break;
   642         	}
   625         	}
   643 
   626 
   644         default:
   627         default:
   645             __PRINT1(_L("CDynamicDirCache::Control() invalid function: %d"), aFunction);
   628             __PRINT1(_L("CDynamicDirCache::Control() invalid function: %d"), aFunction);
   678 
   661 
   679 void CDynamicDirCache::DoMakePageMRU(TInt64 aPos)
   662 void CDynamicDirCache::DoMakePageMRU(TInt64 aPos)
   680 	{
   663 	{
   681 //	__PRINT1(_L("MakePageMRU (%lx)"), aPos);
   664 //	__PRINT1(_L("MakePageMRU (%lx)"), aPos);
   682 //	__PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages);
   665 //	__PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages);
   683 	// check there are at least two locked pages
   666 	// check there are at least one locked pages
   684 	ASSERT(iLockedQCount > 1);
   667 	ASSERT(iLockedQCount > 0);
   685 	
   668 	
   686 	// check the MRU page first, if it is already the MRU page, we can return immediately
   669 	// check the MRU page first, if it is already the MRU page, we can return immediately
   687 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   670 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   688 	if (!iLockedQ.IsEmpty())
   671 	if (!iLockedQ.IsEmpty())
   689 		{
   672 		{
   690 		if (iLockedQ.First()->StartPos() == pageStartMedPos)
   673         if (iLockedQCount > 1 && iLockedQ.First()->StartPos() == pageStartMedPos)
   691 			{
   674 			{
   692 			return;
   675 			return;
   693 			}
   676 			}
   694 		}
   677 		}
   695 
   678 
   696 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   679 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   697     if (pPage)
   680 	if (pPage)
   698     	{
   681 		{
   699     	ASSERT(pPage->IsValid());
   682 		ASSERT(pPage->IsValid());
   700 		// lock page before make it MRU
   683 		// lock page before make it MRU
   701     	if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   684 		if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   702     		{
   685 			{
   703     		ASSERT(!pPage->IsLocked());
   686             ASSERT(!pPage->IsLocked() || (pPage->IsLocked() && pPage == iLastVisitedPage));
   704         	if (LockPage(pPage) == NULL)
   687 			if (LockPage(pPage) == NULL)
   705         		{
   688 				{
   706         		DeQueue(pPage);
   689 				DeQueue(pPage);
   707         		LookupTblRemove(pPage->StartPos());
   690 				LookupTblRemove(pPage->StartPos());
   708         		DecommitPage(pPage);
   691 				DecommitPage(pPage);
   709         		delete pPage;
   692 				delete pPage;
   710         		pPage = NULL;
   693 				pPage = NULL;
   711         		}
   694 				}
   712     		}
   695 			}
   713     	else
   696 		else
   714     		{
   697 			{
   715     		// error checking: page should either be locked or active
   698 			// error checking: page should either be locked or active
   716     		ASSERT(LockPage(pPage) != NULL);
   699 			ASSERT(LockPage(pPage) != NULL);
   717     		}
   700 			}
   718     	}
   701 		}
   719 
   702 
   720     // if page not found or page data not valid anymore, use active page to read data
   703 	// if page not found or page data not valid anymore, use active page to read data
   721     if (!pPage)
   704 	if (!pPage)
   722     	{
   705 		{
   723         TRAPD(err, pPage = UpdateActivePageL(aPos));
   706 		TRAPD(err, pPage = UpdateActivePageL(aPos));
   724         if (err != KErrNone)
   707 		if (err != KErrNone)
   725         	{
   708 			{
   726         	// problem occurred reading active page, return immediately.
   709 			// problem occurred reading active page, return immediately.
   727         	return;
   710 			return;
   728         	}
   711 			}
   729     	}
   712 		}
   730 
   713 
   731     // by now, the page is either locked or active page
   714 	// by now, the page is either locked or active page
   732 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   715 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   733 
   716 
   734 
   717 
   735 
   718 
   736 	TBool allocateNewPage = pPage == iLockedQ.Last() && !CacheIsFull();
   719     TBool makeNewPageMRU = pPage == iLockedQ.Last();
   737 
   720 
   738 
   721 
   739 	switch (pPage->PageType())
   722 	switch (pPage->PageType())
   740 		{
   723 		{
   741 		case TDynamicDirCachePage::EUnlocked:
   724 		case TDynamicDirCachePage::EUnlocked:
   760 			}
   743 			}
   761 		default:
   744 		default:
   762 			ASSERT(0);
   745 			ASSERT(0);
   763 		}
   746 		}
   764 
   747 
   765 	if (allocateNewPage)
   748     if (!makeNewPageMRU)
   766 		{
   749         return;
   767 		TDynamicDirCachePage* nPage = NULL;
   750     
   768 		TRAPD(err, nPage = AllocateAndLockNewPageL(0));
   751     // when cache is full and a new MRU page is about to be added, we will need to evict the LRU page
   769 		if (err == KErrNone)
   752     //  accordingly
   770 			{
   753     if (CacheIsFull())
   771 
   754         {
   772 			// about to add a page to end of locked queue, so lie about iLockedQCount
   755         TUint32& queueCnt = iMaxSizeInPages - iMinSizeInPages > 0 ? iUnlockedQCount : iLockedQCount;
   773 			iLockedQCount++;
   756         queueCnt++;
   774 			CheckThresholds();
   757         CheckThresholds();
   775 			iLockedQCount--;
   758         queueCnt--;
   776 
   759         }
   777 			iLockedQ.AddLast(*nPage);
   760 
   778 			nPage->SetPageType(TDynamicDirCachePage::ELocked);
   761     // attempt to grow the cache by appending a clean, new page at the end of the locked page queue.
   779 			++iLockedQCount;
   762     // This can fail when out of memory; the LRU mechanism then makes sure the oldest page will be re-used.
   780 			LookupTblAdd(nPage);
   763     TDynamicDirCachePage* nPage = AllocateAndLockNewPage();
   781 			}
   764     if (!nPage)
   782 		}
   765         return;
       
   766 
       
   767     // about to add the new active page, force the locked queue to evict the existing last page to make room 
       
   768     //  for the new active page 
       
   769 	iLockedQCount++;
       
   770 	CheckThresholds();
       
   771 	iLockedQCount--;
       
   772 
       
   773 	iLockedQ.AddLast(*nPage);
       
   774 	nPage->SetPageType(TDynamicDirCachePage::ELocked);
       
   775 	++iLockedQCount;
   783 	}
   776 	}
   784 
   777 
   785 /**
   778 /**
   786     Implementation of pure virtual function.
   779     Implementation of pure virtual function.
   787     @see	MDiskSpecialAccessor::MakePageMRU()
   780     @see	MDiskSpecialAccessor::MakePageMRU()
   853 Check if the number of (locked pages + iActive page) and unlocked pages have exceeded minimum allowed page
   846 Check if the number of (locked pages + iActive page) and unlocked pages have exceeded minimum allowed page
   854 number and maximum allowed page number respectively.
   847 number and maximum allowed page number respectively.
   855 */
   848 */
   856 void CDynamicDirCache::CheckThresholds()
   849 void CDynamicDirCache::CheckThresholds()
   857 	{
   850 	{
   858 	while (iLockedQCount + 1 > iMinSizeInPages)
   851     while (iLockedQCount > iMinSizeInPages)
   859 		{
   852 		{
   860 		TDynamicDirCachePage* movePage = iLockedQ.Last();
   853 		TDynamicDirCachePage* movePage = iLockedQ.Last();
   861 		UnlockPage(movePage);
   854 		UnlockPage(movePage);
   862 		DeQueue(movePage);
   855 		DeQueue(movePage);
   863 		TInt err = LookupTblRemove(movePage->StartPos());
   856 		TInt err = LookupTblRemove(movePage->StartPos());
   893 
   886 
   894 /**
   887 /**
   895 Try to create a new page and lock the page content when it is created. This function should only be called
   888 Try to create a new page and lock the page content when it is created. This function should only be called
   896 when creating iActive page or making a page MRU (which might result in page evictions).
   889 when creating iActive page or making a page MRU (which might result in page evictions).
   897 @return	the pointer of the newly created page, or NULL if allocation failed.
   890 @return	the pointer of the newly created page, or NULL if allocation failed.
   898 @param	aStartMedPos	the starting media address of the page to be created.
   891 */
   899 @pre	aStartMedPos should not already be existing in the cache.
   892 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPage(/*TInt64 aStartMedPos*/)
   900 */
   893     {
   901 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPageL(TInt64 aStartMedPos)
   894     __PRINT(_L("CDynamicDirCache::AllocateAndLockNewPage()"));
   902 	{
   895 
   903 	__PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPageL(aStartMedPos=%lx)"), aStartMedPos);
   896     TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   904 
   897 
   905 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   898     if (!startRamAddr)
   906 	if (startRamAddr)
   899         return NULL;
   907 		{
   900 
   908 		// create new page and return
   901     TDynamicDirCachePage* pPage = TDynamicDirCachePage::CreateCachePage(this, 0, startRamAddr);
   909 		TDynamicDirCachePage* pPage = TDynamicDirCachePage::NewL(this, aStartMedPos, startRamAddr);
   902 
   910 		pPage->SetLocked(ETrue);
   903     // Failure would mean the cache chunk was able to grow but we've run out of heap.
   911 		pPage->SetValid(EFalse);
   904     // This seems extremely unlikely, but decommit the now-unmanageable cache segment just in case.
   912 		return pPage;
   905     if (!pPage)
   913 		}
   906         {
   914 
   907         iCacheMemoryClient->DecommitSegments(startRamAddr, PageSizeInSegs());
   915 	return NULL;
   908         return NULL;
   916 	}
   909         }
   917 
   910 
   918 #ifdef _DEBUG
   911 	pPage->SetLocked(ETrue);
       
   912 	pPage->SetValid(EFalse);
       
   913 	return pPage;
       
   914 	}
       
   915 
       
   916 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
   919 /**
   917 /**
   920 Dump cache information, only enabled in debug mode.
   918 Dump cache information, only enabled in debug mode.
   921 @see CDynamicDirCache::Control()
   919 @see CDynamicDirCache::Control()
   922 */
   920 */
   923 void CDynamicDirCache::Info() const
   921 void CDynamicDirCache::Info(TDirCacheInfo* aInfo) const
   924 	{
   922     {
   925 	__PRINT(_L("======== CDynamicDirCache::Info ========="));
   923     __PRINT(_L("======== CDynamicDirCache::Info ========="));
   926 	const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
   924     const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
   927 	// page size
   925     const TUint32 pageMemSizeLog2 = iPageSizeLog2 > SegmentSizeInBytesLog2 ? iPageSizeLog2 : SegmentSizeInBytesLog2;
   928 	__PRINT1(_L("=== Pages size:               [%d Bytes]"), iPageSizeInBytes);
   926     // page size
   929 	__PRINT1(_L("=== Segment size:             [%d Bytes]"), 1 << SegmentSizeInBytesLog2);
   927     __PRINT1(_L("=== Segment size:             [%d Bytes]"), 1 << SegmentSizeInBytesLog2);
   930 
   928     __PRINT1(_L("=== Page data size:           [%d Bytes]"), iPageSizeInBytes);
   931 	// data size:
   929     __PRINT1(_L("=== Page mem size:            [%d Bytes]"), 1 << pageMemSizeLog2);
   932 	__PRINT1(_L("=== Min data size:            [%d Bytes]"), iMinSizeInPages << iPageSizeLog2);
   930 
   933 	__PRINT1(_L("=== Max data size:            [%d Bytes]"), iMaxSizeInPages << iPageSizeLog2);
   931     // cache size in pages
   934 
   932     __PRINT1(_L("=== Min cache size in pages:  [%d]"), iMinSizeInPages);
   935 	// memory size:
   933     __PRINT1(_L("=== Max cache size in pages:  [%d]"), iMaxSizeInPages);
   936 	const TUint32 pageMemSizeLog2 = iPageSizeLog2 > SegmentSizeInBytesLog2 ? iPageSizeLog2 : SegmentSizeInBytesLog2;
   934 
   937 	__PRINT1(_L("=== Min memory size:          [%d Bytes]"), iMinSizeInPages << pageMemSizeLog2);
   935     // locked page num
   938 	__PRINT1(_L("=== Max memory size:          [%d Bytes]"), iMaxSizeInPages << pageMemSizeLog2);
   936     __PRINT1(_L("=== Number of pages locked:   [%d]"), iLockedQCount);
   939 
   937     // unlocked page num
   940 	// reserved pages
   938     __PRINT1(_L("=== Number of pages unlocked: [%d]"), iUnlockedQCount);
   941 	__PRINT1(_L("=== Number of pages reserved: [%d]"), iMinSizeInPages);
   939     __PRINT(_L("=========================================\n"));
   942 	__PRINT1(_L("=== Reserved memory:          [%d Bytes]"), (iMinSizeInPages * PageSizeInSegs()) << SegmentSizeInBytesLog2);
   940     
   943 	// locked page num
   941     ASSERT(aInfo);
   944 	__PRINT1(_L("=== Number of pages locked:   [%d]"), iLockedQCount);
   942     aInfo->iMemorySegmentSize       = 1 << SegmentSizeInBytesLog2;
   945 	__PRINT1(_L("=== Locked memory:            [%d Bytes]"), (iLockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
   943     aInfo->iPageSizeInMemory        = PageSizeInSegs() << SegmentSizeInBytesLog2;
   946 	// unlocked page num
   944     aInfo->iPageSizeInData          = iPageSizeInBytes;
   947 	__PRINT1(_L("=== Number of pages unlocked: [%d]"), iUnlockedQCount);
   945     aInfo->iMinCacheSizeInPages     = iMinSizeInPages;
   948 	__PRINT1(_L("=== Unlocked memory:          [%d Bytes]"), (iUnlockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
   946     aInfo->iMaxCacheSizeInPages     = iMaxSizeInPages;
   949 	}
   947     aInfo->iMinCacheSizeInMemory    = iMinSizeInPages * aInfo->iPageSizeInMemory;
       
   948     aInfo->iMaxCacheSizeInMemory    = iMaxSizeInPages * aInfo->iPageSizeInMemory;
       
   949     aInfo->iLockedPageNumber        = iLockedQCount;
       
   950     aInfo->iUnlockedPageNumber      = iUnlockedQCount;
       
   951     }
   950 
   952 
   951 /**
   953 /**
   952 Dump cache content, only enabled in debug mode.
   954 Dump cache content, only enabled in debug mode.
   953 @see CDynamicDirCache::Control()
   955 @see CDynamicDirCache::Control()
   954 */
   956 */
   994             pEntry = (TLookupEntry*) iter.Next();
   996             pEntry = (TLookupEntry*) iter.Next();
   995             };
   997             };
   996         }
   998         }
   997     __PRINT(_L("===========================================\n"));
   999     __PRINT(_L("===========================================\n"));
   998     }
  1000     }
   999 #endif //_DEBUG
  1001 #endif //#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  1000 
  1002 
  1001 /**
  1003 /**
  1002 Lock an unlocked page, or do nothing if the page is already locked.
  1004 Lock an unlocked page, or do nothing if the page is already locked.
  1003 @return	TUint8*	pointer of the page to be locked, if locking is successful, otherwise return NULL.
  1005 @return	TUint8*	pointer of the page to be locked, if locking is successful, otherwise return NULL.
  1004 @param	aPage	the pointer of the page to be locked.
  1006 @param	aPage	the pointer of the page to be locked.
  1026 */
  1028 */
  1027 TInt CDynamicDirCache::UnlockPage(TDynamicDirCachePage* aPage)
  1029 TInt CDynamicDirCache::UnlockPage(TDynamicDirCachePage* aPage)
  1028 	{
  1030 	{
  1029 	ASSERT(aPage != NULL);
  1031 	ASSERT(aPage != NULL);
  1030 	__PRINT1(_L("CDynamicDirCache::UnlockPage(%lx)"), aPage->StartPos());
  1032 	__PRINT1(_L("CDynamicDirCache::UnlockPage(%lx)"), aPage->StartPos());
  1031 	TInt r = iCacheMemoryClient->UnlockSegments(aPage->StartPtr(), PageSizeInSegs());
  1033     if (aPage)
  1032 	if (r == KErrNone)
  1034         {
  1033 		{
  1035 		TInt r = iCacheMemoryClient->UnlockSegments(aPage->StartPtr(), PageSizeInSegs());
  1034 		aPage->SetLocked(EFalse);
  1036 		if (r == KErrNone)
  1035 		}
  1037 			{
  1036 	return r;
  1038 			aPage->SetLocked(EFalse);
  1037 	}
  1039 			}
  1038 
  1040 		return r;
       
  1041 		}
       
  1042     return KErrArgument;
       
  1043     }
  1039 /**
  1044 /**
  1040 Decommit a locked or unlocked page.
  1045 Decommit a locked or unlocked page.
  1041 @return	TInt	KErrNone if decommition was successful, otherwise system-wide error code.
  1046 @return	TInt	KErrNone if decommition was successful, otherwise system-wide error code.
  1042 @param	aPage	the pointer of the page to be decommitted.
  1047 @param	aPage	the pointer of the page to be decommitted.
  1043 */
  1048 */