userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp
changeset 149 d9f1e5bfe28c
parent 90 947f0dc9f7a8
child 201 43365a9b78a3
equal deleted inserted replaced
135:5e441a173c63 149:d9f1e5bfe28c
    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 
   720     // if page not found or page data not valid anymore, use active page to read data
   723 	// if page not found or page data not valid anymore, use active page to read data
   721     if (!pPage)
   724 	if (!pPage)
   722     	{
   725 		{
   723         TRAPD(err, pPage = UpdateActivePageL(aPos));
   726 		TRAPD(err, pPage = UpdateActivePageL(aPos));
   724         if (err != KErrNone)
   727 		if (err != KErrNone)
   725         	{
   728 			{
   726         	// problem occurred reading active page, return immediately.
   729 			// problem occurred reading active page, return immediately.
   727         	return;
   730 			return;
   728         	}
   731 			}
   729     	}
   732 		}
   730 
   733 
   731     // by now, the page is either locked or active page
   734 	// by now, the page is either locked or active page
   732 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   735 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   733 
   736 
   734 
   737 
   735 
   738 	// if we used the active page (last on the queue), try to grow the cache.
   736 	TBool allocateNewPage = pPage == iLockedQ.Last() && !CacheIsFull();
   739 	TBool growCache = pPage == iLockedQ.Last();
   737 
       
   738 
   740 
   739 	switch (pPage->PageType())
   741 	switch (pPage->PageType())
   740 		{
   742 		{
   741 		case TDynamicDirCachePage::EUnlocked:
   743 		case TDynamicDirCachePage::EUnlocked:
   742 			{
   744 			{
   760 			}
   762 			}
   761 		default:
   763 		default:
   762 			ASSERT(0);
   764 			ASSERT(0);
   763 		}
   765 		}
   764 
   766 
   765 	if (allocateNewPage)
   767 	if (CacheIsFull() || !growCache)
   766 		{
   768 		return;
   767 		TDynamicDirCachePage* nPage = NULL;
   769 
   768 		TRAPD(err, nPage = AllocateAndLockNewPageL(0));
   770 	// attempt to grow the cache by appending a clean, new page at the end of the LRU list.
   769 		if (err == KErrNone)
   771 	// This can fail when out of memory; the LRU mechanism then makes sure the oldest page will be re-used.
   770 			{
   772 	TDynamicDirCachePage* nPage = AllocateAndLockNewPage(0);
   771 
   773 	if (!nPage)
   772 			// about to add a page to end of locked queue, so lie about iLockedQCount
   774 		return;
   773 			iLockedQCount++;
   775 
   774 			CheckThresholds();
   776 	// about to add a page to end of locked queue, so lie about iLockedQCount
   775 			iLockedQCount--;
   777 	iLockedQCount++;
   776 
   778 	CheckThresholds();
   777 			iLockedQ.AddLast(*nPage);
   779 	iLockedQCount--;
   778 			nPage->SetPageType(TDynamicDirCachePage::ELocked);
   780 
   779 			++iLockedQCount;
   781 	iLockedQ.AddLast(*nPage);
   780 			LookupTblAdd(nPage);
   782 	nPage->SetPageType(TDynamicDirCachePage::ELocked);
   781 			}
   783 	++iLockedQCount;
   782 		}
   784 	LookupTblAdd(nPage);
   783 	}
   785 	}
   784 
   786 
   785 /**
   787 /**
   786     Implementation of pure virtual function.
   788     Implementation of pure virtual function.
   787     @see	MDiskSpecialAccessor::MakePageMRU()
   789     @see	MDiskSpecialAccessor::MakePageMRU()
   896 when creating iActive page or making a page MRU (which might result in page evictions).
   898 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.
   899 @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.
   900 @param	aStartMedPos	the starting media address of the page to be created.
   899 @pre	aStartMedPos should not already be existing in the cache.
   901 @pre	aStartMedPos should not already be existing in the cache.
   900 */
   902 */
   901 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPageL(TInt64 aStartMedPos)
   903 TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPage(TInt64 aStartMedPos)
   902 	{
   904 	{
   903 	__PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPageL(aStartMedPos=%lx)"), aStartMedPos);
   905 	__PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPage(aStartMedPos=%lx)"), aStartMedPos);
   904 
   906 
   905 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   907 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
   906 	if (startRamAddr)
   908 
   907 		{
   909 	if (!startRamAddr)
   908 		// create new page and return
   910 		return NULL;
   909 		TDynamicDirCachePage* pPage = TDynamicDirCachePage::NewL(this, aStartMedPos, startRamAddr);
   911 
   910 		pPage->SetLocked(ETrue);
   912 	TDynamicDirCachePage* pPage = TDynamicDirCachePage::CreateCachePage(this, aStartMedPos, startRamAddr);
   911 		pPage->SetValid(EFalse);
   913 
   912 		return pPage;
   914 	// Failure would mean the cache chunk was able to grow but we've run out of heap.
   913 		}
   915 	// This seems extremely unlikely, but decommit the now-unmanageable cache segment just in case.
   914 
   916 	if (!pPage)
   915 	return NULL;
   917 		{
       
   918 		iCacheMemoryClient->DecommitSegments(startRamAddr, PageSizeInSegs());
       
   919 		return NULL;
       
   920 		}
       
   921 
       
   922 	pPage->SetLocked(ETrue);
       
   923 	pPage->SetValid(EFalse);
       
   924 	return pPage;
   916 	}
   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.