--- 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<<aPageSizeLog2);
- CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2);
+ CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2, aWrGranularityLog2);
CleanupStack::PushL(pSelf);
pSelf->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<TDynamicDirCachePage> 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<TDynamicDirCachePage> 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<TDynamicDirCachePage> 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<TLookupEntry> 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<TDynamicDirCachePage> 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<TLookupEntry> 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
/**