userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp
branchRCL_3
changeset 87 2f92ad2dc5db
parent 80 597aaf25e343
child 256 c1f20ce4abcf
equal deleted inserted replaced
81:e7d2d738d3c2 87:2f92ad2dc5db
    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
   156 		}
   156 		}
   157 
   157 
   158 
   158 
   159 	// allocate as many permanently locked pages as there are threads - plus one
   159 	// allocate as many permanently locked pages as there are threads - plus one
   160 	// otherwise DoMakePageMRU() won't work properly with only one thread
   160 	// 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)
   161 	//-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool)
   162 	const TUint KThreadCount = 1;
   162 	const TUint KThreadCount = 1;
   163 	iPermanentlyAllocatedPageCount = KThreadCount + 1; 
   163 	iPermanentlyAllocatedPageCount = KThreadCount + 1; 
   164 
   164 
   165 	if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
   165 	if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
   166 		iMinSizeInPages = iPermanentlyAllocatedPageCount;
   166 		iMinSizeInPages = iPermanentlyAllocatedPageCount;
   167 
   167 
   168 	for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
   168 	for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
   169 		{
   169 		{
   170 		TDynamicDirCachePage* pPage = AllocateAndLockNewPageL(0);
   170 		TDynamicDirCachePage* pPage = AllocateAndLockNewPage(0);
       
   171 		ASSERT(pPage);
       
   172 		if (!pPage)
       
   173 			User::Leave(KErrNoMemory);
   171 		AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   174 		AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   172 		LookupTblAdd(pPage);
   175 		LookupTblAdd(pPage);
   173 		}
   176 		}
   174 
   177 
   175 	}
   178 	}
   692 			return;
   695 			return;
   693 			}
   696 			}
   694 		}
   697 		}
   695 
   698 
   696 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   699 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   697     if (pPage)
   700 	if (pPage)
   698     	{
   701 		{
   699     	ASSERT(pPage->IsValid());
   702 		ASSERT(pPage->IsValid());
   700 		// lock page before make it MRU
   703 		// lock page before make it MRU
   701     	if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   704 		if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   702     		{
   705 			{
   703     		ASSERT(!pPage->IsLocked());
   706 			ASSERT(!pPage->IsLocked());
   704         	if (LockPage(pPage) == NULL)
   707 			if (LockPage(pPage) == NULL)
   705         		{
   708 				{
   706         		DeQueue(pPage);
   709 				DeQueue(pPage);
   707         		LookupTblRemove(pPage->StartPos());
   710 				LookupTblRemove(pPage->StartPos());
   708         		DecommitPage(pPage);
   711 				DecommitPage(pPage);
   709         		delete pPage;
   712 				delete pPage;
   710         		pPage = NULL;
   713 				pPage = NULL;
   711         		}
   714 				}
   712     		}
   715 			}
   713     	else
   716 		else
   714     		{
   717 			{
   715     		// error checking: page should either be locked or active
   718 			// error checking: page should either be locked or active
   716     		ASSERT(LockPage(pPage) != NULL);
   719 			ASSERT(LockPage(pPage) != NULL);
   717     		}
   720 			}
   718     	}
   721 		}
   719 
   722 	// if page not found or page data not valid anymore, use active page to read data
   720     // if page not found or page data not valid anymore, use active page to read data
   723 	if (!pPage)
   721     if (!pPage)
   724 		{
   722     	{
   725 		TRAPD(err, pPage = UpdateActivePageL(aPos));
   723         TRAPD(err, pPage = UpdateActivePageL(aPos));
   726 		if (err != KErrNone)
   724         if (err != KErrNone)
   727 			{
   725         	{
   728 			// problem occurred reading active page, return immediately.
   726         	// problem occurred reading active page, return immediately.
   729 			return;
   727         	return;
   730 			}
   728         	}
   731 		}
   729     	}
   732 
   730 
   733 	// by now, the page is either locked or active page
   731     // by now, the page is either locked or active page
       
   732 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   734 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   733 
   735 
   734 
   736 
   735 
   737 	// if we used the active page (last on the queue), try to grow the cache.
   736 	TBool allocateNewPage = pPage == iLockedQ.Last() && !CacheIsFull();
   738 	TBool growCache = pPage == iLockedQ.Last();
   737 
       
   738 
   739 
   739 	switch (pPage->PageType())
   740 	switch (pPage->PageType())
   740 		{
   741 		{
   741 		case TDynamicDirCachePage::EUnlocked:
   742 		case TDynamicDirCachePage::EUnlocked:
   742 			{
   743 			{
   760 			}
   761 			}
   761 		default:
   762 		default:
   762 			ASSERT(0);
   763 			ASSERT(0);
   763 		}
   764 		}
   764 
   765 
   765 	if (allocateNewPage)
   766 	if (CacheIsFull() || !growCache)
   766 		{
   767 		return;
   767 		TDynamicDirCachePage* nPage = NULL;
   768 
   768 		TRAPD(err, nPage = AllocateAndLockNewPageL(0));
   769 	// attempt to grow the cache by appending a clean, new page at the end of the LRU list.
   769 		if (err == KErrNone)
   770 	// This can fail when out of memory; the LRU mechanism then makes sure the oldest page will be re-used.
   770 			{
   771 	TDynamicDirCachePage* nPage = AllocateAndLockNewPage(0);
   771 
   772 	if (!nPage)
   772 			// about to add a page to end of locked queue, so lie about iLockedQCount
   773 		return;
   773 			iLockedQCount++;
   774 
   774 			CheckThresholds();
   775 	// about to add a page to end of locked queue, so lie about iLockedQCount
   775 			iLockedQCount--;
   776 	iLockedQCount++;
   776 
   777 	CheckThresholds();
   777 			iLockedQ.AddLast(*nPage);
   778 	iLockedQCount--;
   778 			nPage->SetPageType(TDynamicDirCachePage::ELocked);
   779 
   779 			++iLockedQCount;
   780 	iLockedQ.AddLast(*nPage);
   780 			LookupTblAdd(nPage);
   781 	nPage->SetPageType(TDynamicDirCachePage::ELocked);
   781 			}
   782 	++iLockedQCount;
   782 		}
   783 	LookupTblAdd(nPage);
   783 	}
   784 	}
   784 
   785 
   785 /**
   786 /**
   786     Implementation of pure virtual function.
   787     Implementation of pure virtual function.
   787     @see	MDiskSpecialAccessor::MakePageMRU()
   788     @see	MDiskSpecialAccessor::MakePageMRU()
   819 	if (activePage->StartPos() == pageStartMedPos && activePage->IsValid())
   820 	if (activePage->StartPos() == pageStartMedPos && activePage->IsValid())
   820 		{
   821 		{
   821 		return activePage;
   822 		return activePage;
   822 		}
   823 		}
   823 
   824 
   824 	__PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos());
   825 	//__PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos());
   825 
   826 
   826 	activePage->Deque();
   827 	activePage->Deque();
   827 	LookupTblRemove(activePage->StartPos());
   828 	LookupTblRemove(activePage->StartPos());
   828 
   829 
   829 	// set start med pos value, no other effects, only available to active page
   830 	// set start med pos value, no other effects, only available to active page
   896 when creating iActive page or making a page MRU (which might result in page evictions).
   897 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.
   898 @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.
   899 @param	aStartMedPos	the starting media address of the page to be created.
   899 @pre	aStartMedPos should not already be existing in the cache.
   900 @pre	aStartMedPos should not already be existing in the cache.
   900 */
   901 */
   901 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPageL(TInt64 aStartMedPos)
   902 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPage(TInt64 aStartMedPos)
   902 	{
   903 	{
   903 	__PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPageL(aStartMedPos=%lx)"), aStartMedPos);
   904 	__PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPage(aStartMedPos=%lx)"), aStartMedPos);
   904 
   905 
   905 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   906 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   906 	if (startRamAddr)
   907 
   907 		{
   908 	if (!startRamAddr)
   908 		// create new page and return
   909 		return NULL;
   909 		TDynamicDirCachePage* pPage = TDynamicDirCachePage::NewL(this, aStartMedPos, startRamAddr);
   910 
   910 		pPage->SetLocked(ETrue);
   911 	TDynamicDirCachePage* pPage = TDynamicDirCachePage::CreateCachePage(this, aStartMedPos, startRamAddr);
   911 		pPage->SetValid(EFalse);
   912 
   912 		return pPage;
   913 	// Failure would mean the cache chunk was able to grow but we've run out of heap.
   913 		}
   914 	// This seems extremely unlikely, but decommit the now-unmanageable cache segment just in case.
   914 
   915 	if (!pPage)
   915 	return NULL;
   916 		{
   916 	}
   917 		iCacheMemoryClient->DecommitSegments(startRamAddr, PageSizeInSegs());
       
   918 		return NULL;
       
   919 		}
       
   920 
       
   921 	pPage->SetLocked(ETrue);
       
   922 	pPage->SetValid(EFalse);
       
   923 	return pPage;
       
   924 	}
       
   925 
   917 
   926 
   918 #ifdef _DEBUG
   927 #ifdef _DEBUG
   919 /**
   928 /**
   920 Dump cache information, only enabled in debug mode.
   929 Dump cache information, only enabled in debug mode.
   921 @see CDynamicDirCache::Control()
   930 @see CDynamicDirCache::Control()