37 @param aOwnerCache pointer of the cache that owns this page |
37 @param aOwnerCache pointer of the cache that owns this page |
38 @param aStartMedPos the start address on the media that this page caches |
38 @param aStartMedPos the start address on the media that this page caches |
39 @param aStartRamAddr the start address in the ram that this page content lives |
39 @param aStartRamAddr the start address in the ram that this page content lives |
40 */ |
40 */ |
41 TDynamicDirCachePage::TDynamicDirCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr) |
41 TDynamicDirCachePage::TDynamicDirCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr) |
42 :iStartMedPos(aStartMedPos), |
42 :iStartMedPos(aStartMedPos), |
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 |
102 /** |
102 /** |
103 Constructor of CDynamicDirCache. |
103 Constructor of CDynamicDirCache. |
104 @param aDrive local drive interface to read/write media |
104 @param aDrive local drive interface to read/write media |
105 @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. |
106 @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. |
107 @param aPageSizeInBytesLog2 the log2 value of page size in bytes, assumes page size is always a power of two |
107 @param aPageSizeInBytesLog2 Log2 of the page size in bytes, this is the cache read granularity |
108 */ |
108 @param aWrGranularityLog2 Log2(cache write granularity) |
109 CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2) |
109 */ |
110 :iPageSizeLog2(aPageSizeInBytesLog2), |
110 CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2, TUint32 aWrGranularityLog2) |
111 iMinSizeInPages(aMinPageNum), |
111 :iPageSizeLog2(aPageSizeInBytesLog2), |
112 iMaxSizeInPages(aMaxPageNum), |
112 iWrGranularityLog2(aWrGranularityLog2), |
113 iDrive(aDrive), |
113 iMinSizeInPages(aMinPageNum), |
114 iLockedQ(_FOFF(TDynamicDirCachePage, iLink)), |
114 iMaxSizeInPages(aMaxPageNum), |
115 iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)), |
115 iDrive(aDrive), |
116 iLockedQCount(0), |
116 iLockedQ(_FOFF(TDynamicDirCachePage, iLink)), |
117 iUnlockedQCount(0), |
117 iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)), |
118 iHashFunction(HashFunction), |
118 iLockedQCount(0), |
119 iIdentityFunction(IdentityFunction), |
119 iUnlockedQCount(0), |
120 iLookupTable(iHashFunction, iIdentityFunction) |
120 iHashFunction(HashFunction), |
|
121 iIdentityFunction(IdentityFunction), |
|
122 iLookupTable(iHashFunction, iIdentityFunction) |
121 { |
123 { |
122 iPageSizeInBytes = 1 << aPageSizeInBytesLog2; |
124 iPageSizeInBytes = 1 << aPageSizeInBytesLog2; |
123 iCacheDisabled = EFalse; |
125 iCacheDisabled = EFalse; |
124 iMinCacheSizeInBytes = aMinPageNum << aPageSizeInBytesLog2; |
126 iMinCacheSizeInBytes = aMinPageNum << aPageSizeInBytesLog2; |
125 iMaxCacheSizeInBytes = aMaxPageNum << aPageSizeInBytesLog2; |
127 iMaxCacheSizeInBytes = aMaxPageNum << aPageSizeInBytesLog2; |
172 } |
174 } |
173 |
175 |
174 /** |
176 /** |
175 Static factory function of CDynamicDirCache |
177 Static factory function of CDynamicDirCache |
176 */ |
178 */ |
177 CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName) |
179 CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2, const TDesC& aClientName) |
178 { |
180 { |
179 __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<<aPageSizeLog2); |
181 __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<<aPageSizeLog2); |
180 CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2); |
182 CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2, aWrGranularityLog2); |
181 CleanupStack::PushL(pSelf); |
183 CleanupStack::PushL(pSelf); |
182 pSelf->ConstructL(aClientName); |
184 pSelf->ConstructL(aClientName); |
183 CleanupStack::Pop(); |
185 CleanupStack::Pop(); |
184 return pSelf; |
186 return pSelf; |
185 } |
187 } |
336 @param aPos the starting position of the media address to be write. |
338 @param aPos the starting position of the media address to be write. |
337 @param aData the starting address that the writing content lives in the ram. |
339 @param aData the starting address that the writing content lives in the ram. |
338 @param aDataLen the length of the content to be written. |
340 @param aDataLen the length of the content to be written. |
339 @pre aDataLen should be no more than page size. |
341 @pre aDataLen should be no more than page size. |
340 */ |
342 */ |
341 void CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen) |
343 TDynamicDirCachePage* CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen) |
342 { |
344 { |
343 ASSERT(aDataLen <= iPageSizeInBytes); |
345 ASSERT(aDataLen <= iPageSizeInBytes); |
344 //-- the data section is in the cache page entirely, take data directly from the cache |
346 //-- the data section is in the cache page entirely, take data directly from the cache |
345 TDynamicDirCachePage* pPage = FindPageByPos(aPos); |
347 TDynamicDirCachePage* pPage = FindPageByPos(aPos); |
346 if (pPage) |
348 if (pPage) |
405 TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos); |
408 TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos); |
406 |
409 |
407 // __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd); |
410 // __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd); |
408 |
411 |
409 if(dataLen <= bytesToPageEnd) |
412 if(dataLen <= bytesToPageEnd) |
410 { |
413 {//-- make small write a multiple of a write granularity size (if it is used at all) |
411 WriteDataOntoSinglePageL(aPos, pData, dataLen); |
414 //-- this is not the best way to use write granularity, but we would need to refactor cache pages code to make it normal |
|
415 |
|
416 TDynamicDirCachePage* pPage = WriteDataOntoSinglePageL(aPos, pData, dataLen); |
|
417 TPtrC8 desBlock(aDes); |
|
418 |
|
419 if(iWrGranularityLog2) |
|
420 {//-- write granularity is used |
|
421 const TInt64 newPos = (aPos >> iWrGranularityLog2) << iWrGranularityLog2; //-- round position down to the granularity unit size |
|
422 TUint32 newLen = (TUint32)(aPos - newPos)+dataLen; |
|
423 newLen = RoundUp(newLen, iWrGranularityLog2); |
|
424 |
|
425 const TUint8* pd = pPage->PtrInPage(newPos); |
|
426 desBlock.Set(pd, newLen); |
|
427 aPos = newPos; |
|
428 |
|
429 } |
|
430 |
|
431 //-- write data to the media |
|
432 const TInt nErr = iDrive.WriteCritical(aPos, desBlock); |
|
433 if(nErr != KErrNone) |
|
434 {//-- some serious problem occured during writing, invalidate cache. |
|
435 InvalidateCache(); |
|
436 User::Leave(nErr); |
|
437 } |
|
438 |
|
439 |
412 } |
440 } |
413 else |
441 else |
414 { |
442 {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write |
|
443 //-- this is a very rare case. |
415 __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!")); |
444 __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!")); |
416 |
445 |
417 //-- Data to be written cross cache page boundary or probably we have more than 1 page to write |
446 //-- Data to be written cross cache page boundary or probably we have more than 1 page to write |
418 TInt64 currMediaPos(aPos); |
447 TInt64 currMediaPos(aPos); |
419 |
448 |
437 //-- 3. write the rest of the data |
466 //-- 3. write the rest of the data |
438 if(dataLen > 0) |
467 if(dataLen > 0) |
439 { |
468 { |
440 WriteDataOntoSinglePageL(currMediaPos, pData, dataLen); |
469 WriteDataOntoSinglePageL(currMediaPos, pData, dataLen); |
441 } |
470 } |
442 }// else(dataLen <= bytesToPageEnd) |
|
443 |
|
444 |
471 |
445 //-- write data to the media |
472 //-- write data to the media |
446 const TInt nErr = iDrive.WriteCritical(aPos,aDes); |
473 const TInt nErr = iDrive.WriteCritical(aPos,aDes); |
447 if(nErr != KErrNone) |
474 if(nErr != KErrNone) |
448 {//-- some serious problem occured during writing, invalidate cache. |
475 {//-- some serious problem occured during writing, invalidate cache. |
449 InvalidateCache(); |
476 InvalidateCache(); |
450 User::Leave(nErr); |
477 User::Leave(nErr); |
451 } |
478 } |
|
479 |
|
480 |
|
481 }// else(dataLen <= bytesToPageEnd) |
|
482 |
|
483 |
452 } |
484 } |
453 |
485 |
454 /** |
486 /** |
455 Invalidate the cache |
487 Invalidate the cache |
456 @see MWTCacheInterface::InvalidateCache() |
488 @see MWTCacheInterface::InvalidateCache() |
516 |
548 |
517 /** |
549 /** |
518 Implementation of pure virtual function. |
550 Implementation of pure virtual function. |
519 @see MWTCacheInterface::PosCached() |
551 @see MWTCacheInterface::PosCached() |
520 */ |
552 */ |
521 TUint32 CDynamicDirCache::PosCached(const TInt64& aPos, TInt64& aCachedPosStart) |
553 TUint32 CDynamicDirCache::PosCached(TInt64 aPos) |
522 { |
554 { |
523 const TInt64 pageStartMedPos = CalcPageStartPos(aPos); |
555 const TInt64 pageStartMedPos = CalcPageStartPos(aPos); |
524 |
556 |
525 // only search the page in lookup table |
557 // only search the page in lookup table |
526 // NOTE: we don't count the active page into acount here, |
558 // NOTE: we don't count the active page into acount here, |
533 if (LockPage(pPage) != NULL) |
565 if (LockPage(pPage) != NULL) |
534 { |
566 { |
535 // __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos); |
567 // __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos); |
536 // have to unlock it before returning, otherwise there will be memory leak |
568 // have to unlock it before returning, otherwise there will be memory leak |
537 UnlockPage(pPage); |
569 UnlockPage(pPage); |
538 aCachedPosStart = pPage->StartPos(); |
|
539 return pPage->PageSizeInBytes(); |
570 return pPage->PageSizeInBytes(); |
540 } |
571 } |
541 else // if the unlocked page is not valid anymore, remove it |
572 else // if the unlocked page is not valid anymore, remove it |
542 { |
573 { |
543 DeQueue(pPage); |
574 DeQueue(pPage); |