diff -r 2d65c2f76d7b -r 947f0dc9f7a8 userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp Fri Apr 16 16:24:37 2010 +0300 @@ -39,11 +39,11 @@ @param aStartRamAddr the start address in the ram that this page content lives */ TDynamicDirCachePage::TDynamicDirCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr) -:iStartMedPos(aStartMedPos), -iStartRamAddr(aStartRamAddr), -iOwnerCache(aOwnerCache), -iValid(EFalse), -iLocked(EFalse) + :iStartMedPos(aStartMedPos), + iStartRamAddr(aStartRamAddr), + iOwnerCache(aOwnerCache), + iValid(EFalse), + iLocked(EFalse) { //__PRINT3(_L("TDynamicDirCachePage::TDynamicDirCachePage(aStartMedPos=%lx, aStartRamAddr=0x%X, aPageSize=%u)"), aStartMedPos, aStartRamAddr, PageSizeInBytes()); iType = EUnknown; @@ -104,20 +104,22 @@ @param aDrive local drive interface to read/write media @param aMinPageNum the minimum page number for the cache, includes iActive page and locked pages. @param aMaxPageNum the maximum page number for the cache, includes iActive page, locked pages and unlocked pages. -@param aPageSizeInBytesLog2 the log2 value of page size in bytes, assumes page size is always a power of two + @param aPageSizeInBytesLog2 Log2 of the page size in bytes, this is the cache read granularity + @param aWrGranularityLog2 Log2(cache write granularity) */ -CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2) -:iPageSizeLog2(aPageSizeInBytesLog2), -iMinSizeInPages(aMinPageNum), -iMaxSizeInPages(aMaxPageNum), -iDrive(aDrive), -iLockedQ(_FOFF(TDynamicDirCachePage, iLink)), -iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)), -iLockedQCount(0), -iUnlockedQCount(0), -iHashFunction(HashFunction), -iIdentityFunction(IdentityFunction), -iLookupTable(iHashFunction, iIdentityFunction) +CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2, TUint32 aWrGranularityLog2) + :iPageSizeLog2(aPageSizeInBytesLog2), + iWrGranularityLog2(aWrGranularityLog2), + iMinSizeInPages(aMinPageNum), + iMaxSizeInPages(aMaxPageNum), + iDrive(aDrive), + iLockedQ(_FOFF(TDynamicDirCachePage, iLink)), + iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)), + iLockedQCount(0), + iUnlockedQCount(0), + iHashFunction(HashFunction), + iIdentityFunction(IdentityFunction), + iLookupTable(iHashFunction, iIdentityFunction) { iPageSizeInBytes = 1 << aPageSizeInBytesLog2; iCacheDisabled = EFalse; @@ -157,7 +159,8 @@ // allocate as many permanently locked pages as there are threads - plus one // otherwise DoMakePageMRU() won't work properly with only one thread //-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool) - iPermanentlyAllocatedPageCount = 1; + const TUint KThreadCount = 1; + iPermanentlyAllocatedPageCount = KThreadCount + 1; if (iPermanentlyAllocatedPageCount > iMinSizeInPages) iMinSizeInPages = iPermanentlyAllocatedPageCount; @@ -174,10 +177,10 @@ /** Static factory function of CDynamicDirCache */ -CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName) +CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2, const TDesC& aClientName) { __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<ConstructL(aClientName); CleanupStack::Pop(); @@ -338,7 +341,7 @@ @param aDataLen the length of the content to be written. @pre aDataLen should be no more than page size. */ -void CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen) +TDynamicDirCachePage* CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen) { ASSERT(aDataLen <= iPageSizeInBytes); //-- the data section is in the cache page entirely, take data directly from the cache @@ -378,7 +381,8 @@ // always make writting events MRU DoMakePageMRU(aPos); - return; + + return pPage; } /** @@ -407,11 +411,37 @@ // __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd); if(dataLen <= bytesToPageEnd) - { - WriteDataOntoSinglePageL(aPos, pData, dataLen); + {//-- make small write a multiple of a write granularity size (if it is used at all) + //-- this is not the best way to use write granularity, but we would need to refactor cache pages code to make it normal + + TDynamicDirCachePage* pPage = WriteDataOntoSinglePageL(aPos, pData, dataLen); + TPtrC8 desBlock(aDes); + + if(iWrGranularityLog2) + {//-- write granularity is used + const TInt64 newPos = (aPos >> iWrGranularityLog2) << iWrGranularityLog2; //-- round position down to the granularity unit size + TUint32 newLen = (TUint32)(aPos - newPos)+dataLen; + newLen = RoundUp(newLen, iWrGranularityLog2); + + const TUint8* pd = pPage->PtrInPage(newPos); + desBlock.Set(pd, newLen); + aPos = newPos; + + } + + //-- write data to the media + const TInt nErr = iDrive.WriteCritical(aPos, desBlock); + if(nErr != KErrNone) + {//-- some serious problem occured during writing, invalidate cache. + InvalidateCache(); + User::Leave(nErr); + } + + } else - { + {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write + //-- this is a very rare case. __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!")); //-- Data to be written cross cache page boundary or probably we have more than 1 page to write @@ -439,8 +469,6 @@ { WriteDataOntoSinglePageL(currMediaPos, pData, dataLen); } - }// else(dataLen <= bytesToPageEnd) - //-- write data to the media const TInt nErr = iDrive.WriteCritical(aPos,aDes); @@ -449,6 +477,11 @@ InvalidateCache(); User::Leave(nErr); } + + + }// else(dataLen <= bytesToPageEnd) + + } /** @@ -518,7 +551,7 @@ Implementation of pure virtual function. @see MWTCacheInterface::PosCached() */ -TUint32 CDynamicDirCache::PosCached(const TInt64& aPos, TInt64& aCachedPosStart) +TUint32 CDynamicDirCache::PosCached(TInt64 aPos) { const TInt64 pageStartMedPos = CalcPageStartPos(aPos); @@ -535,7 +568,6 @@ // __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos); // have to unlock it before returning, otherwise there will be memory leak UnlockPage(pPage); - aCachedPosStart = pPage->StartPos(); return pPage->PageSizeInBytes(); } else // if the unlocked page is not valid anymore, remove it @@ -551,7 +583,6 @@ else if (pPage) { __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) on Locked Queue!"), aPos); - aCachedPosStart = pPage->StartPos(); return pPage->PageSizeInBytes(); } @@ -649,6 +680,9 @@ { // __PRINT1(_L("MakePageMRU (%lx)"), aPos); // __PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages); + // check there are at least two locked pages + ASSERT(iLockedQCount > 1); + // check the MRU page first, if it is already the MRU page, we can return immediately TInt64 pageStartMedPos = CalcPageStartPos(aPos); if (!iLockedQ.IsEmpty()) @@ -787,7 +821,7 @@ return activePage; } - __PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos()); + //__PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos()); activePage->Deque(); LookupTblRemove(activePage->StartPos()); @@ -919,46 +953,49 @@ @see CDynamicDirCache::Control() */ void CDynamicDirCache::Dump() - { - __PRINT(_L("======== CDynamicDirCache::Dump =========")); - if (!iLockedQ.IsEmpty()) - { - TDblQueIter q(iLockedQ); - q.SetToFirst(); - TInt i = 0; - while((TDynamicDirCachePage*)q) - { - TDynamicDirCachePage* pP = q++; - __PRINT5(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes()); - } - } - if (!iUnlockedQ.IsEmpty()) - { - TDblQueIter q(iUnlockedQ); - q.SetToFirst(); - TInt i = 0; - while((TDynamicDirCachePage*)q) - { - TDynamicDirCachePage* pP = q++; - __PRINT5(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes()); - } - } + { + __PRINT(_L("======== CDynamicDirCache::Dump =========")); + if (!iLockedQ.IsEmpty()) + { + TDblQueIter q(iLockedQ); + q.SetToFirst(); + TInt i = 0; + while((TDynamicDirCachePage*)q) + { + TDynamicDirCachePage* pP = q++; + __PRINT5(_L("=== CDynamicDirCache::iLockedQ [%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes()); + } + } + __PRINT(_L("=== CDynamicDirCache:: --------------------")); - if (iLookupTable.Count()) - { - TInt i = 0; - THashSetIter iter(iLookupTable); - TLookupEntry* pEntry; - pEntry = (TLookupEntry*) iter.Next(); - while(pEntry) - { - TDynamicDirCachePage* pP = pEntry->iPage; - __PRINT5(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes()); - pEntry = (TLookupEntry*) iter.Next(); - }; - } - __PRINT(_L("===========================================\n")); - } + if (!iUnlockedQ.IsEmpty()) + { + TDblQueIter q(iUnlockedQ); + q.SetToFirst(); + TInt i = 0; + while((TDynamicDirCachePage*)q) + { + TDynamicDirCachePage* pP = q++; + __PRINT5(_L("=== CDynamicDirCache::iUnlockedQ [%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes()); + } + } + __PRINT(_L("=== CDynamicDirCache:: --------------------")); + + if (iLookupTable.Count()) + { + TInt i = 0; + THashSetIter iter(iLookupTable); + TLookupEntry* pEntry; + pEntry = (TLookupEntry*) iter.Next(); + while(pEntry) + { + TDynamicDirCachePage* pP = pEntry->iPage; + __PRINT5(_L("=== CDynamicDirCache::iLookupTable [%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes()); + pEntry = (TLookupEntry*) iter.Next(); + }; + } + __PRINT(_L("===========================================\n")); + } #endif //_DEBUG /**