userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp
changeset 33 0173bcd7697c
parent 15 4122176ea935
child 62 4a8fed1c0ef6
child 90 947f0dc9f7a8
equal deleted inserted replaced
31:56f325a607ea 33:0173bcd7697c
    43 iStartRamAddr(aStartRamAddr),
    43 iStartRamAddr(aStartRamAddr),
    44 iOwnerCache(aOwnerCache),
    44 iOwnerCache(aOwnerCache),
    45 iValid(EFalse),
    45 iValid(EFalse),
    46 iLocked(EFalse)
    46 iLocked(EFalse)
    47 	{
    47 	{
    48 //	__PRINT3(_L("TDynamicDirCachePage::TDynamicDirCachePage(aStartMedPos=%lx, aStartRamAddr=0x%X, aPageSize=%u)"), aStartMedPos, aStartRamAddr, PageSizeInBytes());
    48 	//__PRINT3(_L("TDynamicDirCachePage::TDynamicDirCachePage(aStartMedPos=%lx, aStartRamAddr=0x%X, aPageSize=%u)"), aStartMedPos, aStartRamAddr, PageSizeInBytes());
    49 	iType = EUnknown;
    49 	iType = EUnknown;
    50 	}
    50 	}
    51 
    51 
    52 /////////////////////////////// class CDynamicDirCache::TLookupEntry ///////////////////////////
    52 /////////////////////////////// class CDynamicDirCache::TLookupEntry ///////////////////////////
    53 /**
    53 /**
    69 	}
    69 	}
    70 
    70 
    71 /////////////////////////////// class CDynamicDirCache ///////////////////////////
    71 /////////////////////////////// class CDynamicDirCache ///////////////////////////
    72 CDynamicDirCache::~CDynamicDirCache()
    72 CDynamicDirCache::~CDynamicDirCache()
    73 	{
    73 	{
    74 //	__PRINT(_L("CDynamicDirCache::~CDynamicDirCache()"));
    74 	__PRINT(_L("CDynamicDirCache::~CDynamicDirCache()"));
    75 
    75 
    76 	// we should never decommit locked pages
    76 	// we should never decommit locked pages
    77     while (!iLockedQ.IsEmpty())
    77     while (!iLockedQ.IsEmpty())
    78 		{
    78 		{
    79 		TDynamicDirCachePage* page = iLockedQ.Last();
    79 		TDynamicDirCachePage* page = iLockedQ.Last();
    91 		DecommitPage(page);	// inform cache client to decommit page memory
    91 		DecommitPage(page);	// inform cache client to decommit page memory
    92 		delete page;
    92 		delete page;
    93 		}
    93 		}
    94 	ASSERT(iUnlockedQCount == 0);
    94 	ASSERT(iUnlockedQCount == 0);
    95 
    95 
    96 	delete iActivePage;
       
    97 
       
    98 	ASSERT(iLookupTable.Count() == 0);
    96 	ASSERT(iLookupTable.Count() == 0);
    99 	iLookupTable.Close();
    97 	iLookupTable.Close();
   100     if (iCacheMemoryClient)
    98     if (iCacheMemoryClient)
   101     	iCacheMemoryClient->Reset();
    99     	iCacheMemoryClient->Reset();
   102 	}
   100 	}
   106 @param	aDrive	local drive interface to read/write media
   104 @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.
   105 @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.
   106 @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
   107 @param	aPageSizeInBytesLog2	the log2 value of page size in bytes, assumes page size is always a power of two
   110 */
   108 */
   111 CDynamicDirCache::CDynamicDirCache(TFatDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2)
   109 CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2)
   112 :iPageSizeLog2(aPageSizeInBytesLog2),
   110 :iPageSizeLog2(aPageSizeInBytesLog2),
   113 iMinSizeInPages(aMinPageNum),
   111 iMinSizeInPages(aMinPageNum),
   114 iMaxSizeInPages(aMaxPageNum),
   112 iMaxSizeInPages(aMaxPageNum),
   115 iDrive(aDrive),
   113 iDrive(aDrive),
   116 iLockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   114 iLockedQ(_FOFF(TDynamicDirCachePage, iLink)),
   153 	if (!iCacheMemoryClient)
   151 	if (!iCacheMemoryClient)
   154 		{
   152 		{
   155 		User::Leave(KErrNoMemory);
   153 		User::Leave(KErrNoMemory);
   156 		}
   154 		}
   157 
   155 
   158 	// reserve active page
   156 
   159 	iActivePage = AllocateAndLockNewPageL(0);
   157 	// allocate as many permanently locked pages as there are threads - plus one
   160 	ASSERT(iActivePage);
   158 	// otherwise DoMakePageMRU() won't work properly with only one thread
   161 	if (!iActivePage)
   159     //-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool)
   162 		{
   160 	iPermanentlyAllocatedPageCount = 1; 
   163 		User::Leave(KErrNoMemory);
   161 
   164 		}
   162 	if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
   165 	iActivePage->SetPageType(TDynamicDirCachePage::EActivePage);
   163 		iMinSizeInPages = iPermanentlyAllocatedPageCount;
       
   164 
       
   165 	for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
       
   166 		{
       
   167 		TDynamicDirCachePage* pPage = AllocateAndLockNewPageL(0);
       
   168 		AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
       
   169 		LookupTblAdd(pPage);
       
   170 		}
       
   171 
   166 	}
   172 	}
   167 
   173 
   168 /**
   174 /**
   169 Static factory function of CDynamicDirCache
   175 Static factory function of CDynamicDirCache
   170 */
   176 */
   171 CDynamicDirCache* CDynamicDirCache::NewL(TFatDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName)
   177 CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName)
   172     {
   178     {
   173 //    __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<<aPageSizeLog2);
   179     __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<<aPageSizeLog2);
   174     CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2);
   180     CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2);
   175     CleanupStack::PushL(pSelf);
   181     CleanupStack::PushL(pSelf);
   176     pSelf->ConstructL(aClientName);
   182     pSelf->ConstructL(aClientName);
   177     CleanupStack::Pop();
   183     CleanupStack::Pop();
   178     return pSelf;
   184     return pSelf;
   213 		iLockedQCount++;
   219 		iLockedQCount++;
   214 		}
   220 		}
   215 	}
   221 	}
   216 
   222 
   217 /**
   223 /**
   218 Read data from a single page. If the page is not found or not valid anymore, read media onto iActive page
   224     Read data from a single page. If the page is not found or not valid anymore, read media onto iActive page first.
   219 first.
   225     The data will be _Appended_ the the descriptor aDes. The caller is responsible for maintaining this descriptor.
   220 @param	aPos	the starting position of the media address to be read.
   226 
   221 @param	aLength	the length of the content to be read.
   227     @param	aPos	the starting position of the media address to be read.
   222 @param	aDes	the descriptor to contain the content.
   228     @param	aLength	the length of the content to be read.
   223 @pre	aLength should be no more than page size.
   229     @param	aDes	the descriptor to contain the content.
       
   230     @pre	aLength should be no more than page size.
   224 */
   231 */
   225 void CDynamicDirCache::ReadDataFromSinglePageL(TInt64 aPos, TInt aLength, TDes8& aDes)
   232 void CDynamicDirCache::ReadDataFromSinglePageL(TInt64 aPos, TInt aLength, TDes8& aDes)
   226 	{
   233 	{
   227     //-- the data section is in the cache page entirely, take data directly from the cache
   234     //-- the data section is in the cache page entirely, take data directly from the cache
   228 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   235 	TDynamicDirCachePage* pPage = FindPageByPos(aPos);
   229     if (pPage)
   236     if (pPage)
   230     	{
   237     	{
   231 		// lock page before reading,
   238 		// lock page before reading,
   232     	if (LockPage(pPage) != NULL)
   239     	if (LockPage(pPage) != NULL)
   233     		{
   240     		{
   234     		// read data
   241     		// read data and append them to the descriptor
   235             aDes.Copy(pPage->PtrInPage(aPos), aLength);
   242             aDes.Append(pPage->PtrInPage(aPos), aLength);
       
   243 
   236 
   244 
   237             // if page is from unlocked queue, insert it onto the last page of the locked
   245             // 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
   246             //  queue. this is to avoid excessive locking and unlocking operations that is
   239             //  highly likely to happen for following reads.
   247             //  highly likely to happen for following reads.
   240             if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   248             if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
   256 
   264 
   257 	if (!pPage)
   265 	if (!pPage)
   258 		{
   266 		{
   259         // if page not found or page data not valid anymore, use active page to read data in
   267         // if page not found or page data not valid anymore, use active page to read data in
   260         pPage = UpdateActivePageL(aPos);
   268         pPage = UpdateActivePageL(aPos);
   261         // read data
   269         // read data and append them to the descriptor
   262         aDes.Copy(pPage->PtrInPage(aPos), aLength);
   270         aDes.Append(pPage->PtrInPage(aPos), aLength);
   263     	}
   271     	}
   264 
   272 
   265 	}
   273 	}
   266 
   274 
   267 //====================================================================
   275 //====================================================================
   303         //-- 1. read data that are already in the current page
   311         //-- 1. read data that are already in the current page
   304         ReadDataFromSinglePageL(currMediaPos, bytesToPageEnd, aDes);
   312         ReadDataFromSinglePageL(currMediaPos, bytesToPageEnd, aDes);
   305         dataLen -= bytesToPageEnd;
   313         dataLen -= bytesToPageEnd;
   306         currMediaPos += bytesToPageEnd;
   314         currMediaPos += bytesToPageEnd;
   307 
   315 
   308         TPtr8 dataNext = aDes.MidTPtr(aDes.Length());
       
   309 
       
   310         //-- 2. read whole pages of data
   316         //-- 2. read whole pages of data
   311         while (dataLen >= PageSz)
   317         while (dataLen >= PageSz)
   312         	{
   318         	{
   313         	//-- find out if currMediaPos is in cache. If not, find a spare page and read data there
   319         	//-- find out if currMediaPos is in cache. If not, find a spare page and read data there
   314         	ReadDataFromSinglePageL(currMediaPos, PageSz, dataNext);
   320             ReadDataFromSinglePageL(currMediaPos, PageSz, aDes);
   315             currMediaPos += PageSz;
   321             currMediaPos += PageSz;
   316             dataLen -= PageSz;
   322             dataLen -= PageSz;
   317             dataNext = dataNext.MidTPtr(dataNext.Length());
       
   318         	}
   323         	}
   319 
   324 
   320         //-- 3. read the rest of the data
   325         //-- 3. read the rest of the data
   321         if(dataLen > 0)
   326         if(dataLen > 0)
   322             {
   327             {
   323         	ReadDataFromSinglePageL(currMediaPos, dataLen, dataNext);
   328             ReadDataFromSinglePageL(currMediaPos, dataLen, aDes);
   324             }
   329             }
   325         } //else((TUint32)aLength <= bytesToPageEnd)
   330         } //else((TUint32)aLength <= bytesToPageEnd)
   326 	}
   331 	}
   327 
   332 
   328 /**
   333 /**
   370 		{
   375 		{
   371 		UnlockPage(pPage);
   376 		UnlockPage(pPage);
   372 		}
   377 		}
   373 
   378 
   374 	// always make writting events MRU
   379 	// always make writting events MRU
   375 	MakePageMRU(aPos);
   380 	DoMakePageMRU(aPos);
   376     return;
   381     return;
   377 	}
   382 	}
   378 
   383 
   379 /**
   384 /**
   380 Implementation of pure virtual function.
   385 Implementation of pure virtual function.
   445         User::Leave(nErr);
   450         User::Leave(nErr);
   446         }
   451         }
   447 	}
   452 	}
   448 
   453 
   449 /**
   454 /**
   450 Implementation of pure virtual function.
   455     Invalidate the cache
   451 @see	MWTCacheInterface::InvalidateCache()
   456     @see	MWTCacheInterface::InvalidateCache()
   452 */
   457 */
   453 void CDynamicDirCache::InvalidateCache(void)
   458 void CDynamicDirCache::DoInvalidateCache(void)
   454 	{
   459 	{
   455 	__PRINT2(_L("CDynamicDirCache::InvalidateCache(locked=%d, unlocked=%d)"), iLockedQCount, iUnlockedQCount);
   460 	__PRINT2(_L("CDynamicDirCache::InvalidateCache(locked=%d, unlocked=%d)"), iLockedQCount, iUnlockedQCount);
   456 	// we should never decommit locked pages as they needs to be reserved anyway
   461 	// we should never decommit locked pages as they needs to be reserved anyway
   457 	// the overhead of unnecessary page committing operations
   462 	// the overhead of unnecessary page committing operations
   458 	while(!iLockedQ.IsEmpty())
   463 
       
   464 	TInt pagesToRemoveFromLockedQueue = iLockedQCount - iPermanentlyAllocatedPageCount;
       
   465 	TInt n;
       
   466 	for (n=0; n<pagesToRemoveFromLockedQueue; n++)
   459 		{
   467 		{
   460 		TDynamicDirCachePage* page = iLockedQ.Last();
   468 		TDynamicDirCachePage* page = iLockedQ.Last();
   461 		DeQueue(page);						// remove from queue
   469 		DeQueue(page);						// remove from queue
   462 		LookupTblRemove(page->StartPos());	// remove from lookuptable
   470 		LookupTblRemove(page->StartPos());	// remove from lookuptable
       
   471 		DecommitPage(page);					// inform cache client to decommit page memory
   463 		delete page;
   472 		delete page;
   464 		}
   473 		}
   465 	ASSERT(iLockedQCount == 0);
   474 	ASSERT(iLockedQCount == iPermanentlyAllocatedPageCount);
       
   475 
       
   476 	TDblQueIter<TDynamicDirCachePage> q(iLockedQ);
       
   477 	q.SetToFirst();
       
   478 	while((TDynamicDirCachePage*) q)
       
   479 		{
       
   480 		TDynamicDirCachePage* page = q++;
       
   481 		LookupTblRemove(page->StartPos());// remove from lookuptable
       
   482 		ResetPagePos(page);				// reset start media position (0), invalidate page content
       
   483 		}
   466 
   484 
   467 	// however we should decommit unlocked pages here
   485 	// however we should decommit unlocked pages here
   468 	while (!iUnlockedQ.IsEmpty())
   486 	while (!iUnlockedQ.IsEmpty())
   469 		{
   487 		{
   470 		TDynamicDirCachePage* page = iUnlockedQ.Last();
   488 		TDynamicDirCachePage* page = iUnlockedQ.Last();
   473 		DecommitPage(page);					// inform cache client to decommit page memory
   491 		DecommitPage(page);					// inform cache client to decommit page memory
   474 		delete page;
   492 		delete page;
   475 		}
   493 		}
   476 	ASSERT(iUnlockedQCount == 0);
   494 	ASSERT(iUnlockedQCount == 0);
   477 
   495 
   478     ASSERT(iLookupTable.Count() == 0);
   496 	ASSERT(iLockedQCount == iPermanentlyAllocatedPageCount);
   479 	iLookupTable.Close();
       
   480 
   497 
   481 	ASSERT(iCacheMemoryClient);
   498 	ASSERT(iCacheMemoryClient);
   482 
   499 	}
   483 	// initialize cache state.
   500 
   484 	// Note that once the client is reset, all pages lose connection with the client
   501 /**
   485 	//	including the active page. So we will need to reset and re-allocate active page
   502 Implementation of pure virtual function.
   486 	//	properly.
   503 @see	MWTCacheInterface::InvalidateCache()
   487 	if (iCacheMemoryClient)
   504 */
   488     	iCacheMemoryClient->Reset();
   505 void CDynamicDirCache::InvalidateCache(void)
   489 
   506 	{
   490 	// reset and re-allocate active page
   507 	DoInvalidateCache();
   491 	ResetPagePos(iActivePage);				// reset start media position (0), invalidate page content
   508 	}
   492 	TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
       
   493 	// this should always succeed as the client has just been reset and there are always reserved pages
       
   494 	ASSERT(startRamAddr);
       
   495 	iActivePage->SetStartPtr(startRamAddr);	// set RAM address
       
   496 	}
       
   497 
       
   498 
   509 
   499 /** this method isn't implemented*/
   510 /** this method isn't implemented*/
   500 void CDynamicDirCache::InvalidateCachePage(TUint64 /*aPos*/)
   511 void CDynamicDirCache::InvalidateCachePage(TUint64 /*aPos*/)
   501     {
   512     {
   502     ASSERT(0);
   513     ASSERT(0);
   631 TUint32 CDynamicDirCache::PageSizeInBytesLog2() const
   642 TUint32 CDynamicDirCache::PageSizeInBytesLog2() const
   632 	{
   643 	{
   633 	return iPageSizeLog2;
   644 	return iPageSizeLog2;
   634 	}
   645 	}
   635 
   646 
   636 /**
   647 
   637 Implementation of pure virtual function.
   648 void CDynamicDirCache::DoMakePageMRU(TInt64 aPos)
   638 @see	MWTCacheInterface::MakePageMRU()
   649 	{
   639 */
   650 //	__PRINT1(_L("MakePageMRU (%lx)"), aPos);
   640 void CDynamicDirCache::MakePageMRU(TInt64 aPos)
       
   641 	{
       
   642 	__PRINT1(_L("MakePageMRU (%lx)"), aPos);
       
   643 //	__PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages);
   651 //	__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
   652 	// check the MRU page first, if it is already the MRU page, we can return immediately
   645 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   653 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   646 	if (!iLockedQ.IsEmpty())
   654 	if (!iLockedQ.IsEmpty())
   647 		{
   655 		{
   687     	}
   695     	}
   688 
   696 
   689     // by now, the page is either locked or active page
   697     // by now, the page is either locked or active page
   690 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   698 	ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
   691 
   699 
       
   700 
       
   701 
       
   702 	TBool allocateNewPage = pPage == iLockedQ.Last() && !CacheIsFull();
       
   703 
       
   704 
   692 	switch (pPage->PageType())
   705 	switch (pPage->PageType())
   693 		{
   706 		{
   694 		// if the page is the active page, we will need to find a new active page for replacement
       
   695 		case TDynamicDirCachePage::EActivePage:
       
   696 			{
       
   697 			TDynamicDirCachePage* newAP = NULL;
       
   698 			// if there is more cache room available, try to create a new page first
       
   699 			if (!CacheIsFull())
       
   700 				{
       
   701 				// allocate and lock a new page
       
   702 				TRAPD(err, newAP = AllocateAndLockNewPageL(0));
       
   703 				// if any error ocurrs, return immediately
       
   704 				if (err != KErrNone)
       
   705 					{
       
   706 					// unlock the page that was originally unlocked before leave
       
   707 					if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
       
   708 						{
       
   709 						UnlockPage(pPage);
       
   710 						}
       
   711 					return;
       
   712 					}
       
   713 
       
   714 				if (newAP)
       
   715 					{
       
   716 					// replace the active page with the new page
       
   717 					newAP->SetPageType(TDynamicDirCachePage::EActivePage);
       
   718 					iActivePage = newAP;
       
   719 					}
       
   720 				}
       
   721 
       
   722 			// if cache has grown to its max size, or new page allocation failed
       
   723 			if (!newAP)
       
   724 				{
       
   725 				// try to lock the LRU page on the unlocked page queque first
       
   726 				if (!iUnlockedQ.IsEmpty())
       
   727 					{
       
   728 					newAP = iUnlockedQ.Last();
       
   729 					ASSERT(newAP->IsValid());
       
   730 					if (LockPage(newAP) != NULL)
       
   731 						{
       
   732 						// deque, reset pos, set new type
       
   733 						DeQueue(newAP);
       
   734 		        		LookupTblRemove(newAP->StartPos());
       
   735 						ResetPagePos(newAP);
       
   736 						newAP->SetPageType(TDynamicDirCachePage::EActivePage);
       
   737 						// replace active page
       
   738 						iActivePage = newAP;
       
   739 						}
       
   740 					// if falied locking the LRU page from unclocked queque,
       
   741 					// delete it
       
   742 					else
       
   743 						{
       
   744 						DeQueue(newAP);
       
   745 		        		LookupTblRemove(newAP->StartPos());
       
   746 		        		DecommitPage(newAP);
       
   747 		        		delete newAP;
       
   748 		        		newAP = NULL;
       
   749 						}
       
   750 					}
       
   751 				}
       
   752 
       
   753 			// if still have not found new active page
       
   754 			// grab the LRU page from Locked Page Queue for active page
       
   755 			if (!newAP)
       
   756 				{
       
   757 				ASSERT(!iLockedQ.IsEmpty());
       
   758 				newAP = iLockedQ.Last();
       
   759 				// deque, reset pos, set new type
       
   760 				DeQueue(newAP);
       
   761         		LookupTblRemove(newAP->StartPos());
       
   762 				ResetPagePos(newAP);
       
   763 				newAP->SetPageType(TDynamicDirCachePage::EActivePage);
       
   764 				// replace active page
       
   765 				iActivePage = newAP;
       
   766 				}
       
   767 
       
   768 			// we should always be able to find a locked page for active page
       
   769 			ASSERT(newAP != NULL);
       
   770 
       
   771 			// make original page (i.e. former active page) MRU
       
   772 			// add onto locked queue
       
   773 			AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
       
   774 			// add onto lookuptbl, as active page is not on lookup tbl originally
       
   775 			LookupTblAdd(pPage);
       
   776 			// check cache limit
       
   777 			CheckThresholds();
       
   778 			return;
       
   779 			}
       
   780 		case TDynamicDirCachePage::EUnlocked:
   707 		case TDynamicDirCachePage::EUnlocked:
   781 			{
   708 			{
   782 			// if page was originally on Unlocked Page Queque, remove it from Unlocked Page Queue, add it
   709 			// 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
   710 			// to the Locked Page Queue and make it MRU
   784 			DeQueue(pPage);
   711 			DeQueue(pPage);
   785 			AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   712 			AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   786 			// check cache limit
   713 			// check cache limit
   787 			CheckThresholds();
   714 			CheckThresholds();
   788 			return;
       
   789 			}
   715 			}
   790 		case TDynamicDirCachePage::ELocked:
   716 		case TDynamicDirCachePage::ELocked:
   791 			{
   717 			{
   792 			// otherwise the page was on Locked Page Queue, make it MRU
   718 			// otherwise the page was on Locked Page Queue, make it MRU
   793 			// no need to check cache limit
   719 			// no need to check cache limit
   794 			if (pPage != iLockedQ.First())
   720 			if (pPage != iLockedQ.First())
   795 				{
   721 				{
   796 				DeQueue(pPage);
   722 				DeQueue(pPage);
   797 				AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   723 				AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
   798 				return;
       
   799 				}
   724 				}
   800 			break;
   725 			break;
   801 			}
   726 			}
   802 		default:
   727 		default:
   803 			ASSERT(0);
   728 			ASSERT(0);
   804 		}
   729 		}
       
   730 
       
   731 	if (allocateNewPage)
       
   732 		{
       
   733 		TDynamicDirCachePage* nPage = NULL;
       
   734 		TRAPD(err, nPage = AllocateAndLockNewPageL(0));
       
   735 		if (err == KErrNone)
       
   736 			{
       
   737 
       
   738 			// about to add a page to end of locked queue, so lie about iLockedQCount
       
   739 			iLockedQCount++;
       
   740 			CheckThresholds();
       
   741 			iLockedQCount--;
       
   742 
       
   743 			iLockedQ.AddLast(*nPage);
       
   744 			nPage->SetPageType(TDynamicDirCachePage::ELocked);
       
   745 			++iLockedQCount;
       
   746 			LookupTblAdd(nPage);
       
   747 			}
       
   748 		}
       
   749 	}
       
   750 
       
   751 /**
       
   752     Implementation of pure virtual function.
       
   753     @see	MDiskSpecialAccessor::MakePageMRU()
       
   754 */
       
   755 void CDynamicDirCache::MakePageMRU(TInt64 aPos)
       
   756 	{
       
   757 	DoMakePageMRU(aPos);
   805 	}
   758 	}
   806 
   759 
   807 //====================================================================
   760 //====================================================================
   808 /**
   761 /**
   809 Internal query function, to check if aPos is cached or not. iActive page is included in searching.
   762 Internal query function, to check if aPos is cached or not. iActive page is included in searching.
   810 */
   763 */
   811 TDynamicDirCachePage* CDynamicDirCache::FindPageByPos(TInt64 aPos)
   764 TDynamicDirCachePage* CDynamicDirCache::FindPageByPos(TInt64 aPos)
   812 	{
   765 	{
   813 	__PRINT1(_L("CDynamicDirCache::FindPageByPos(aPos=%lx)"), aPos);
   766 //	__PRINT1(_L("CDynamicDirCache::FindPageByPos(aPos=%lx)"), aPos);
   814     // align the page position
   767     // align the page position
   815 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   768 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   816 
   769 
   817 	if ((iActivePage->StartPos() == pageStartMedPos))
       
   818 		{
       
   819 		ASSERT(iActivePage->IsValid());
       
   820 		return iActivePage;
       
   821 		}
       
   822 
       
   823 	// search in lookup table
   770 	// search in lookup table
   824 	return LookupTblFind(pageStartMedPos);
   771 	return LookupTblFind(pageStartMedPos);
   825 	}
   772 	}
   826 
   773 
   827 /**
   774 /**
   830 TDynamicDirCachePage* CDynamicDirCache::UpdateActivePageL(TInt64 aPos)
   777 TDynamicDirCachePage* CDynamicDirCache::UpdateActivePageL(TInt64 aPos)
   831 	{
   778 	{
   832     // align the page position
   779     // align the page position
   833 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   780 	TInt64 pageStartMedPos = CalcPageStartPos(aPos);
   834 
   781 
   835 	if (iActivePage->StartPos() == pageStartMedPos && iActivePage->IsValid())
   782 	ASSERT(!iLockedQ.IsEmpty());
   836 		{
   783 	TDynamicDirCachePage* activePage = iLockedQ.Last();
   837 		return iActivePage;
   784 
   838 		}
   785 	if (activePage->StartPos() == pageStartMedPos && activePage->IsValid())
   839 
   786 		{
   840 	__PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, iActivePage->StartPos());
   787 		return activePage;
       
   788 		}
       
   789 
       
   790 	__PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos());
       
   791 
       
   792 	activePage->Deque();
       
   793 	LookupTblRemove(activePage->StartPos());
   841 
   794 
   842 	// set start med pos value, no other effects, only available to active page
   795 	// set start med pos value, no other effects, only available to active page
   843 	iActivePage->SetPos(pageStartMedPos);
   796 	activePage->SetPos(pageStartMedPos);
   844 
   797 
   845 	// read data, make active page valid
   798 	// read data, make active page valid
   846 	TUint8* data = iActivePage->PtrInPage(iActivePage->iStartMedPos);
   799 	TUint8* data = activePage->PtrInPage(activePage->iStartMedPos);
   847     TPtr8 dataPtr(data, iPageSizeInBytes);
   800     TPtr8 dataPtr(data, iPageSizeInBytes);
   848     const TInt nErr = iDrive.ReadNonCritical(iActivePage->iStartMedPos, iPageSizeInBytes, dataPtr);
   801 	
       
   802     const TInt nErr = iDrive.ReadNonCritical(activePage->iStartMedPos, iPageSizeInBytes, dataPtr);
       
   803 
       
   804 	iLockedQ.AddLast(*activePage);
       
   805 	LookupTblAdd(activePage);
       
   806 
   849     if(nErr !=KErrNone)
   807     if(nErr !=KErrNone)
   850         {
   808         {
   851         // some serious problem occured during reading, invalidate cache.
   809         // some serious problem occured during reading, invalidate cache.
   852         InvalidateCache();
   810         DoInvalidateCache();
   853         User::Leave(nErr);
   811         User::Leave(nErr);
   854         }
   812         }
   855     iActivePage->SetValid(ETrue);
   813     activePage->SetValid(ETrue);
   856 
   814 
   857     return iActivePage;
   815     return activePage;
   858 	}
   816 	}
   859 
   817 
   860 /**
   818 /**
   861 Check if the number of (locked pages + iActive page) and unlocked pages have exceeded minimum allowed page
   819 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.
   820 number and maximum allowed page number respectively.
   969 		q.SetToFirst();
   927 		q.SetToFirst();
   970 		TInt i = 0;
   928 		TInt i = 0;
   971 		while((TDynamicDirCachePage*)q)
   929 		while((TDynamicDirCachePage*)q)
   972 			{
   930 			{
   973 			TDynamicDirCachePage* pP = q++;
   931 			TDynamicDirCachePage* pP = q++;
   974 			__PRINT3(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, size=%d)"), i++, pP->StartPos(), pP->PageSizeInBytes());
   932 			__PRINT5(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
   975 			}
   933 			}
   976 		}
   934 		}
   977 	if (!iUnlockedQ.IsEmpty())
   935 	if (!iUnlockedQ.IsEmpty())
   978 		{
   936 		{
   979 		TDblQueIter<TDynamicDirCachePage> q(iUnlockedQ);
   937 		TDblQueIter<TDynamicDirCachePage> q(iUnlockedQ);
   980 		q.SetToFirst();
   938 		q.SetToFirst();
   981 		TInt i = 0;
   939 		TInt i = 0;
   982 		while((TDynamicDirCachePage*)q)
   940 		while((TDynamicDirCachePage*)q)
   983 			{
   941 			{
   984 			TDynamicDirCachePage* pP = q++;
   942 			TDynamicDirCachePage* pP = q++;
   985 			__PRINT3(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, size=%u)"), i++, pP->StartPos(), pP->PageSizeInBytes());
   943 			__PRINT5(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
   986 			}
   944 			}
   987 		}
   945 		}
   988 	__PRINT2(_L("=== CDynamicDirCache::iActivePage\t[*](pos=%lx, size=%u)"), iActivePage->StartPos(), iActivePage->PageSizeInBytes());
       
   989 
   946 
   990 	if (iLookupTable.Count())
   947 	if (iLookupTable.Count())
   991 		{
   948 		{
   992 		TInt i = 0;
   949 		TInt i = 0;
   993 		THashSetIter<TLookupEntry> iter(iLookupTable);
   950 		THashSetIter<TLookupEntry> iter(iLookupTable);
   994 		TLookupEntry* pEntry;
   951 		TLookupEntry* pEntry;
   995 		pEntry = (TLookupEntry*) iter.Next();
   952 		pEntry = (TLookupEntry*) iter.Next();
   996 		while(pEntry)
   953 		while(pEntry)
   997 			{
   954 			{
   998 			TDynamicDirCachePage* pP = pEntry->iPage;
   955 			TDynamicDirCachePage* pP = pEntry->iPage;
   999 			__PRINT3(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, size=%u)"), i++, pP->StartPos(), pP->PageSizeInBytes());
   956 			__PRINT5(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
  1000 			pEntry = (TLookupEntry*) iter.Next();
   957 			pEntry = (TLookupEntry*) iter.Next();
  1001 			};
   958 			};
  1002 		}
   959 		}
  1003 	__PRINT(_L("===========================================\n"));
   960 	__PRINT(_L("===========================================\n"));
  1004 	}
   961 	}
  1126 	{
  1083 	{
  1127 	ASSERT(aPage);
  1084 	ASSERT(aPage);
  1128 	if (!aPage)
  1085 	if (!aPage)
  1129 		return KErrArgument;
  1086 		return KErrArgument;
  1130 
  1087 
  1131 	// page must be dequed first or it is active page
       
  1132 	if (aPage->iType != TDynamicDirCachePage::EActivePage && aPage->iType != TDynamicDirCachePage::EUnknown)
       
  1133 		{
       
  1134 		ASSERT(0);
       
  1135 		return KErrArgument;
       
  1136 		}
       
  1137 
       
  1138 	if (aType == TDynamicDirCachePage::ELocked)
  1088 	if (aType == TDynamicDirCachePage::ELocked)
  1139 		{
  1089 		{
  1140 		iLockedQ.AddFirst(*aPage);
  1090 		iLockedQ.AddFirst(*aPage);
  1141 		aPage->SetPageType(TDynamicDirCachePage::ELocked);
  1091 		aPage->SetPageType(TDynamicDirCachePage::ELocked);
  1142 		++iLockedQCount;
  1092 		++iLockedQCount;
  1217 		}
  1167 		}
  1218 
  1168 
  1219 	TLookupEntry* entry = iLookupTable.Find(TLookupEntry(aPos, 0, NULL));
  1169 	TLookupEntry* entry = iLookupTable.Find(TLookupEntry(aPos, 0, NULL));
  1220 	if(entry)
  1170 	if(entry)
  1221 		{
  1171 		{
  1222 		ASSERT(entry->iPage->IsValid());
  1172 		// last entry on used queue is used as the 'active' page & may not be valid
       
  1173 		if (!entry->iPage->IsValid())
       
  1174 			return NULL;
       
  1175 
  1223 		return entry->iPage;
  1176 		return entry->iPage;
  1224 		}
  1177 		}
  1225 
  1178 
  1226 	return NULL;
  1179 	return NULL;
  1227 	}
  1180 	}