26 @return a pointer to the created object. |
26 @return a pointer to the created object. |
27 */ |
27 */ |
28 CWTCachePage* CWTCachePage::NewL(TUint32 aPageSizeLog2) |
28 CWTCachePage* CWTCachePage::NewL(TUint32 aPageSizeLog2) |
29 { |
29 { |
30 CWTCachePage* pSelf = new (ELeave)CWTCachePage; |
30 CWTCachePage* pSelf = new (ELeave)CWTCachePage; |
31 pSelf->ConstructL(aPageSizeLog2); |
31 |
|
32 pSelf->iData.CreateMaxL(1 << aPageSizeLog2); |
32 |
33 |
33 return pSelf; |
34 return pSelf; |
34 } |
35 } |
35 |
36 |
36 /** |
|
37 2nd stage constructor. |
|
38 @param aPageSizeLog2 Log2(cache page size in bytes) |
|
39 */ |
|
40 void CWTCachePage::ConstructL(TUint32 aPageSizeLog2) |
|
41 { |
|
42 iData.CreateMaxL(1 << aPageSizeLog2); |
|
43 } |
|
44 |
37 |
45 CWTCachePage::CWTCachePage() |
38 CWTCachePage::CWTCachePage() |
46 { |
39 { |
47 iStartPos = 0xDeadDeadul; |
40 iStartPos = 0xDeadDeadul; |
48 iValid = 0; |
41 iValid = 0; |
80 /** |
73 /** |
81 Directory cache factory function. |
74 Directory cache factory function. |
82 |
75 |
83 @param aDrive reference to the driver for media access. |
76 @param aDrive reference to the driver for media access. |
84 @param aNumPages number of cache pages to be created |
77 @param aNumPages number of cache pages to be created |
85 @param aPageSizeLog2 Log2 of the page size in bytes |
78 @param aPageSizeLog2 Log2 of the page size in bytes, this is the cache read granularity |
|
79 @param aWrGranularityLog2 Log2(cache write granularity) |
86 |
80 |
87 @return a pointer to the created object. |
81 @return a pointer to the created object. |
88 */ |
82 */ |
89 CMediaWTCache* CMediaWTCache::NewL(TDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2) |
83 CMediaWTCache* CMediaWTCache::NewL(TDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2) |
90 { |
84 { |
91 #ifndef ENABLE_DEDICATED_DIR_CACHE |
|
92 //-- dedicated directory cache isn't enabled |
|
93 (void)aDrive; //-- supress compiler's warning |
|
94 (void)aClusterSizeLog2; |
|
95 return NULL; |
|
96 #else |
|
97 |
|
98 //-- dedicated directory cache is enabled, create it |
|
99 ASSERT(aPageSizeLog2); |
|
100 ASSERT(aNumPages); |
|
101 |
85 |
102 CMediaWTCache* pSelf = new (ELeave) CMediaWTCache(aDrive); |
86 CMediaWTCache* pSelf = new (ELeave) CMediaWTCache(aDrive); |
103 |
87 |
104 CleanupStack::PushL(pSelf); |
88 CleanupStack::PushL(pSelf); |
105 pSelf->ConstructL(aNumPages, aPageSizeLog2); |
89 pSelf->InitialiseL(aNumPages, aPageSizeLog2, aWrGranularityLog2); |
106 CleanupStack::Pop(); |
90 CleanupStack::Pop(); |
107 |
91 |
108 return pSelf; |
92 return pSelf; |
109 |
|
110 #endif |
|
111 } |
93 } |
112 |
94 |
113 /** |
95 /** |
114 2nd stage constructor. |
96 2nd stage constructor. |
115 @param aNumPages number of pages in the directory cache. |
97 @param aNumPages number of pages in the directory cache. |
116 @param aPageSizeLog2 Log2(single cache page size in bytes) |
98 @param aPageSizeLog2 Log2 of the page size in bytes, this is the cache read granularity |
117 */ |
99 @param aWrGranularityLog2 Log2(cache write granularity) |
118 void CMediaWTCache::ConstructL(TUint32 aNumPages, TUint32 aPageSizeLog2) |
100 */ |
|
101 void CMediaWTCache::InitialiseL(TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2) |
119 { |
102 { |
120 ASSERT(aNumPages && aPageSizeLog2); |
103 ASSERT(aNumPages && aPageSizeLog2); |
121 |
104 |
122 __PRINT2(_L("#CMediaWTCache::CreateL() Pages=%d, PageSize=%d"), aNumPages, 1<<aPageSizeLog2); |
105 __PRINT3(_L("#CMediaWTCache::InitialiseL() Pages=%d, PageSzLog2=%d, WrGrLog2:%d"), aNumPages, aPageSizeLog2, aWrGranularityLog2); |
|
106 |
|
107 ASSERT(aNumPages); |
|
108 ASSERT(aPageSizeLog2); |
|
109 |
|
110 if(aWrGranularityLog2) |
|
111 { |
|
112 ASSERT(aWrGranularityLog2 >= KDefSectorSzLog2 && aWrGranularityLog2 <= aPageSizeLog2); |
|
113 } |
123 |
114 |
124 iPageSizeLog2 = aPageSizeLog2; |
115 iPageSizeLog2 = aPageSizeLog2; |
|
116 iWrGranularityLog2 = aWrGranularityLog2; |
125 |
117 |
126 //-- create cache pages |
118 //-- create cache pages |
127 for(TUint cnt=0; cnt<aNumPages; ++cnt) |
119 for(TUint cnt=0; cnt<aNumPages; ++cnt) |
128 { |
120 { |
129 CWTCachePage* pPage = CWTCachePage::NewL(aPageSizeLog2); |
121 CWTCachePage* pPage = CWTCachePage::NewL(aPageSizeLog2); |
367 @param aPosToSearch linear media position to lookup in the cache |
359 @param aPosToSearch linear media position to lookup in the cache |
368 @param aCachedPosStart if "aPosToSearch" is cached, here will be media position of this page start |
360 @param aCachedPosStart if "aPosToSearch" is cached, here will be media position of this page start |
369 |
361 |
370 @return 0 if aPosToSearch isn't cached, otherwise cache page size in bytes (see also aCachedPosStart). |
362 @return 0 if aPosToSearch isn't cached, otherwise cache page size in bytes (see also aCachedPosStart). |
371 */ |
363 */ |
372 TUint32 CMediaWTCache::PosCached(const TInt64& aPosToSearch, TInt64& aCachedPosStart) |
364 TUint32 CMediaWTCache::PosCached(TInt64 aPosToSearch) |
373 { |
365 { |
374 TInt nPage = FindPageByPos(aPosToSearch); |
366 TInt nPage = FindPageByPos(aPosToSearch); |
375 if(nPage <0 ) |
367 if(nPage <0 ) |
376 return 0; //-- cache page containing aPos not found |
368 return 0; //-- cache page containing aPos not found |
377 |
369 |
378 aCachedPosStart = iPages[nPage]->iStartPos; |
|
379 |
|
380 return PageSize(); |
370 return PageSize(); |
381 } |
371 } |
382 |
372 |
383 /** |
373 /** |
384 Read data from the media through the directory cache. |
374 Read data from the media through the directory cache. |
481 const TUint32 bytesToPageEnd = (TUint32)(pPage->iStartPos+PageSize() - aPos); //-- number of bytes from aPos to the end of the page |
471 const TUint32 bytesToPageEnd = (TUint32)(pPage->iStartPos+PageSize() - aPos); //-- number of bytes from aPos to the end of the page |
482 // __PRINT5(_L("CMediaWTCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pPage->iStartPos, PageSz, bytesToPageEnd); |
472 // __PRINT5(_L("CMediaWTCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pPage->iStartPos, PageSz, bytesToPageEnd); |
483 if(dataLen <= bytesToPageEnd) |
473 if(dataLen <= bytesToPageEnd) |
484 {//-- data section completely fits to the cache page |
474 {//-- data section completely fits to the cache page |
485 Mem::Copy(pPage->PtrInCachePage(aPos), pData, dataLen); //-- update cache |
475 Mem::Copy(pPage->PtrInCachePage(aPos), pData, dataLen); //-- update cache |
|
476 |
|
477 //-- make small write a multiple of a write granularity size (if it is used at all) |
|
478 //-- this is not the best way to use write granularity, but we would need to refactor cache pages code to make it normal |
|
479 TPtrC8 desBlock(aDes); |
|
480 |
|
481 if(iWrGranularityLog2) |
|
482 {//-- write granularity is used |
|
483 const TInt64 newPos = (aPos >> iWrGranularityLog2) << iWrGranularityLog2; //-- round position down to the write granularity size |
|
484 TUint32 newLen = (TUint32)(aPos - newPos)+dataLen; //-- round block size up to the write granularity size |
|
485 newLen = RoundUp(newLen, iWrGranularityLog2); |
|
486 |
|
487 const TUint8* pd = pPage->PtrInCachePage(newPos); |
|
488 desBlock.Set(pd, newLen); |
|
489 aPos = newPos; |
|
490 } |
|
491 |
|
492 |
|
493 //-- write data to the media |
|
494 const TInt nErr = iDrive.WriteCritical(aPos, desBlock); |
|
495 if(nErr != KErrNone) |
|
496 {//-- some serious problem occured during writing, invalidate cache. |
|
497 InvalidateCache(); |
|
498 User::Leave(nErr); |
|
499 } |
|
500 |
486 } |
501 } |
487 else |
502 else |
488 {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write |
503 {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write |
|
504 //-- this is a very rare case. |
489 |
505 |
490 TInt64 currMediaPos(aPos); //-- current media position |
506 TInt64 currMediaPos(aPos); //-- current media position |
491 |
507 |
492 //-- 1. update the current page |
508 //-- 1. update the current page |
493 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, bytesToPageEnd); |
509 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, bytesToPageEnd); |
521 pPage = iPages[nPage]; |
537 pPage = iPages[nPage]; |
522 |
538 |
523 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, dataLen); |
539 Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, dataLen); |
524 } |
540 } |
525 |
541 |
526 }// else(dataLen <= bytesToPageEnd) |
|
527 |
|
528 |
|
529 //-- write data to the media |
542 //-- write data to the media |
530 const TInt nErr = iDrive.WriteCritical(aPos,aDes); |
543 const TInt nErr = iDrive.WriteCritical(aPos,aDes); |
531 if(nErr != KErrNone) |
544 if(nErr != KErrNone) |
532 {//-- some serious problem occured during writing, invalidate cache. |
545 {//-- some serious problem occured during writing, invalidate cache. |
533 InvalidateCache(); |
546 InvalidateCache(); |
534 User::Leave(nErr); |
547 User::Leave(nErr); |
535 } |
548 } |
536 |
549 |
|
550 }// else(dataLen <= bytesToPageEnd) |
|
551 |
|
552 |
|
553 |
537 MakePageLRU(nPage); //-- push the page to the top of the priority list |
554 MakePageLRU(nPage); //-- push the page to the top of the priority list |
538 } |
555 } |
539 |
556 |
540 |
557 |
541 |
558 |