Update contrib.
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfat\sl_cache.cpp
21 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
22 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
24 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
26 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
29 //---------------------------------------------------------------------------------------------------------------------------------
32 CWTCachePage factory function.
33 @param aPageSizeLog2 Log2(cache page size in bytes)
34 @return a pointer to the created object.
36 CWTCachePage* CWTCachePage::NewL(TUint32 aPageSizeLog2)
38 CWTCachePage* pSelf = new (ELeave)CWTCachePage;
39 pSelf->ConstructL(aPageSizeLog2);
45 2nd stage constructor.
46 @param aPageSizeLog2 Log2(cache page size in bytes)
48 void CWTCachePage::ConstructL(TUint32 aPageSizeLog2)
50 iData.CreateMaxL(1 << aPageSizeLog2);
53 CWTCachePage::CWTCachePage()
55 iStartPos = 0xDeadDeadul;
59 CWTCachePage::~CWTCachePage()
66 //---------------------------------------------------------------------------------------------------------------------------------
68 CMediaWTCache::CMediaWTCache(TFatDriveInterface& aDrive)
69 :iDrive(aDrive), iPageSizeLog2(0), iAllPagesValid(EFalse)
71 iCacheDisabled = EFalse;
75 CMediaWTCache::~CMediaWTCache()
78 TInt cnt = iPages.Count();
89 Directory cache factory function.
91 @param aDrive reference to the driver for media access.
92 @param aNumPages number of cache pages to be created
93 @param aPageSizeLog2 Log2 of the page size in bytes
95 @return a pointer to the created object.
97 CMediaWTCache* CMediaWTCache::NewL(TFatDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2)
99 #ifndef ENABLE_DEDICATED_DIR_CACHE
100 //-- dedicated directory cache isn't enabled
101 (void)aDrive; //-- supress compiler's warning
102 (void)aClusterSizeLog2;
106 //-- dedicated directory cache is enabled, create it
107 ASSERT(aPageSizeLog2);
110 CMediaWTCache* pSelf = new (ELeave) CMediaWTCache(aDrive);
112 CleanupStack::PushL(pSelf);
113 pSelf->ConstructL(aNumPages, aPageSizeLog2);
122 2nd stage constructor.
123 @param aNumPages number of pages in the directory cache.
124 @param aPageSizeLog2 Log2(single cache page size in bytes)
126 void CMediaWTCache::ConstructL(TUint32 aNumPages, TUint32 aPageSizeLog2)
128 ASSERT(aNumPages && aPageSizeLog2);
130 __PRINT2(_L("#CMediaWTCache::CreateL() Pages=%d, PageSize=%d"), aNumPages, 1<<aPageSizeLog2);
132 iPageSizeLog2 = aPageSizeLog2;
134 //-- create cache pages
135 for(TUint cnt=0; cnt<aNumPages; ++cnt)
137 CWTCachePage* pPage = CWTCachePage::NewL(aPageSizeLog2);
138 iPages.Append(pPage);
146 @return size of the cache in bytes. Can be 0.
148 TUint32 CMediaWTCache::CacheSizeInBytes() const
150 const TUint32 cacheSz = iPages.Count() << iPageSizeLog2; //-- Page size is always power of 2
155 Implementation of pure virtual function.
156 @see MWTCacheInterface::MakePageMRU()
158 void CMediaWTCache::MakePageMRU(TInt64 /*aPos*/)
164 Implementation of pure virtual function.
165 @see MWTCacheInterface::PageSizeInBytesLog2()
167 TUint32 CMediaWTCache::PageSizeInBytesLog2() const
169 return iPageSizeLog2;
175 @param aFunction control function
176 @param aParam1 just arbitrary parameter
177 @param aParam2 just arbitrary parameter
178 @return Standard error code.
181 TInt CMediaWTCache::Control(TUint32 aFunction, TUint32 aParam1, TAny* /*aParam2*/)
183 TInt nRes = KErrNotSupported;
188 //-- disable / enable cache, for debug
189 //-- if aParam1 !=0 cache will be disabled, enabled otherwise
191 iCacheDisabled = aParam1 ? 1 : 0;
202 __PRINT1(_L("CMediaWTCache::Control() invalid function: %d"), aFunction);
207 (void)aFunction; //-- supress warnings
209 User::Invariant(); //-- don't call this method in release build
215 //-------------------------------------------------------------------------------------
217 Invalidate whole cache
219 void CMediaWTCache::InvalidateCache(void)
221 const TUint nPages = iPages.Count();
222 for(TUint i=0; i<nPages; ++i)
224 iPages[i]->iValid=EFalse;
227 iAllPagesValid = EFalse;
230 //-------------------------------------------------------------------------------------
232 invalidate a single cache page if the aPos is cached (belongs to some page)
233 If the cache user wants to invalidate some media address range, it will have to calculate
234 pages positions itself. The best way to do this - is to write another method that takes lenght of the
235 region being invalidated.
237 @param aPos media position. If it is cached, the corresponding single cache page will be marked as invalid
239 void CMediaWTCache::InvalidateCachePage(TUint64 aPos)
241 const TUint nPages = iPages.Count();
242 for(TUint i=0; i<nPages; ++i)
244 if( iPages[i]->PosCached(aPos))
246 iPages[i]->iValid=EFalse;
247 iAllPagesValid = EFalse;
254 //-------------------------------------------------------------------------------------
257 Find cache page by given media position.
259 @param aPos linear media position
260 @return positive cache page number or -1 if no pages containing data at aPos found.
262 TInt CMediaWTCache::FindPageByPos(TInt64 aPos) const
264 const TUint nPages = iPages.Count();
265 for(TUint i=0; i<nPages; ++i)
267 if( iPages[i]->PosCached(aPos))
275 Push given page aPageNo to the 1st position in the pages array. Used for LRU mechanism
277 @param aPageNo page number to be made LRU
279 void CMediaWTCache::MakePageLRU(TInt aPageNo)
284 return; //-- nothing to do
286 const TInt nPages = iPages.Count();
287 ASSERT(aPageNo < nPages);
291 CWTCachePage* pPage=iPages[aPageNo];
293 iPages.Remove(aPageNo);
294 iPages.Insert(pPage,0); //-- insert the pointer to the 1st position in the array
295 ASSERT(nPages == iPages.Count());
300 Find a spare page or evict the last from LRU list
304 TUint32 CMediaWTCache::GrabPage() const
306 const TUint nPages = iPages.Count();
309 {//-- try to find unused cache page
310 for(TUint i=0; i<nPages; ++i)
312 if(! iPages[i]->iValid)
313 return i; //-- found unused page
317 //-- no spare pages, evict the last one, it shall be last used
318 iAllPagesValid = ETrue;
323 Find a spare page or evict the last from LRU list, then read data to this page from media starting from aPos
325 @param aPos media linear position from where the data will be read to the page
326 @return cache page number
328 TUint32 CMediaWTCache::GrabReadPageL(TInt64 aPos)
330 //-- find a spare or page to evict
331 TUint nPage = GrabPage();
332 CWTCachePage& page = *iPages[nPage];
334 //-- read data to this page
335 page.iStartPos = CalcPageStartPos(aPos);
337 __PRINT4(_L("#CMediaWTCache::GrabReadPageL() Reading page:%d, Pos=0x%x, PageStartPos=0x%x, page=0x%X"),nPage, (TUint32)aPos, (TUint32)page.iStartPos, iPages[nPage]);
339 const TInt nErr = iDrive.ReadNonCritical(page.iStartPos, PageSize(), page.iData);
341 {//-- some serious problem occured during reading, invalidate cache.
352 Try to find the page with cached data at "aPos" media position.
353 If such page found, returns its number, otherwise takes least recently used page and reads data there.
355 @param aPos media linear position to find in the cache
356 @return cache page number
359 TUint32 CMediaWTCache::FindOrGrabReadPageL(TInt64 aPos)
361 //-- find out if aPos is in cache
362 TInt nPage=FindPageByPos(aPos);
365 {//-- no page contains data to read
366 nPage = GrabReadPageL(aPos); //-- find a spare page and read data into it
373 Finds out if the media position "aPosToSearch" is in the cache and returns cache page information in this case.
375 @param aPosToSearch linear media position to lookup in the cache
376 @param aCachedPosStart if "aPosToSearch" is cached, here will be media position of this page start
378 @return 0 if aPosToSearch isn't cached, otherwise cache page size in bytes (see also aCachedPosStart).
380 TUint32 CMediaWTCache::PosCached(const TInt64& aPosToSearch, TInt64& aCachedPosStart)
382 TInt nPage = FindPageByPos(aPosToSearch);
384 return 0; //-- cache page containing aPos not found
386 aCachedPosStart = iPages[nPage]->iStartPos;
392 Read data from the media through the directory cache.
394 @param aPos linear media position to start reading with
395 @param aLength how many bytes to read
396 @param aDes data will be placed there
398 void CMediaWTCache::ReadL(TInt64 aPos,TInt aLength,TDes8& aDes)
403 {//-- cache is disabled for debug purposes
404 User::LeaveIfError(iDrive.ReadNonCritical(aPos, aLength, aDes));
409 const TUint32 PageSz = PageSize();//-- cache page size
411 //-- find out if aPos is in cache. If not, find a spare page and read data there
412 TInt nPage = FindOrGrabReadPageL(aPos);
413 CWTCachePage* pPage = iPages[nPage];
415 const TUint32 bytesToPageEnd = (TUint32)(pPage->iStartPos+PageSz - aPos); //-- number of bytes from aPos to the end of the page
417 // __PRINT5(_L("CMediaWTCache::ReadL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, aLength, pPage->iStartPos, PageSz, bytesToPageEnd);
418 if((TUint32)aLength <= bytesToPageEnd)
419 {//-- the data section is in the cache page entirely, take data directly from the cache
420 aDes.Copy(pPage->PtrInCachePage(aPos), aLength);
423 {//-- Data to be read cross cache page boundary or probably we have more than 1 page to read
425 TUint32 dataLen(aLength); //-- current data length
426 TInt64 currMediaPos(aPos); //-- current media position
428 //-- 1. read data that are already in the current page
429 aDes.Copy(pPage->PtrInCachePage(currMediaPos), bytesToPageEnd);
431 dataLen -= bytesToPageEnd;
432 currMediaPos += bytesToPageEnd;
434 //-- 2. read whole pages of data
435 while(dataLen >= PageSz)
437 nPage = FindOrGrabReadPageL(currMediaPos); //-- find out if currMediaPos is in cache. If not, find a spare page and read data there
438 pPage = iPages[nPage];
440 aDes.Append(pPage->PtrInCachePage(currMediaPos),PageSz);
443 currMediaPos += PageSz;
445 MakePageLRU(nPage); //-- push the page to the top of the priority list
448 //-- 3. read the rest of the data
451 nPage = FindOrGrabReadPageL(currMediaPos); //-- find out if currMediaPos is in cache. If not, find a spare page and read data there
452 pPage = iPages[nPage];
454 aDes.Append(pPage->PtrInCachePage(currMediaPos), dataLen);
457 } //else((TUint32)aLength <= bytesToPageEnd)
460 MakePageLRU(nPage); //-- push the page to the top of the priority list
465 Write data to the media through the directory cache.
467 @param aPos linear media position to start writing with
468 @param aDes data to write
470 void CMediaWTCache::WriteL(TInt64 aPos,const TDesC8& aDes)
475 {//-- cache is disabled for debug purposes
476 User::LeaveIfError(iDrive.WriteCritical(aPos,aDes));
481 TUint32 dataLen = aDes.Size();
482 const TUint8* pData = aDes.Ptr();
483 const TUint32 PageSz = PageSize(); //-- cache page size
485 //-- find out if aPos is in cache. If not, find a spare page and read data there
486 TInt nPage = FindOrGrabReadPageL(aPos);
487 CWTCachePage* pPage = iPages[nPage];
489 const TUint32 bytesToPageEnd = (TUint32)(pPage->iStartPos+PageSize() - aPos); //-- number of bytes from aPos to the end of the page
490 // __PRINT5(_L("CMediaWTCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pPage->iStartPos, PageSz, bytesToPageEnd);
491 if(dataLen <= bytesToPageEnd)
492 {//-- data section completely fits to the cache page
493 Mem::Copy(pPage->PtrInCachePage(aPos), pData, dataLen); //-- update cache
496 {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write
498 TInt64 currMediaPos(aPos); //-- current media position
500 //-- 1. update the current page
501 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, bytesToPageEnd);
503 pData += bytesToPageEnd;
504 currMediaPos += bytesToPageEnd;
505 dataLen -= bytesToPageEnd;
507 //-- 2. write whole pages of data to the cache
508 while(dataLen >= PageSz)
510 nPage = FindPageByPos(currMediaPos); //-- ?? shall we read data there ??
513 pPage = iPages[nPage];
514 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, PageSz);
515 MakePageLRU(nPage); //-- push the page to the top of the priority list
521 currMediaPos += PageSz;
525 //-- 3. write the rest of the data
528 nPage = FindOrGrabReadPageL(currMediaPos); //-- find out if currMediaPos is in cache. If not, find a spare page and read data there
529 pPage = iPages[nPage];
531 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, dataLen);
534 }// else(dataLen <= bytesToPageEnd)
537 //-- write data to the media
538 const TInt nErr = iDrive.WriteCritical(aPos,aDes);
540 {//-- some serious problem occured during writing, invalidate cache.
545 MakePageLRU(nPage); //-- push the page to the top of the priority list