userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp
branchRCL_3
changeset 19 4a8fed1c0ef6
parent 6 0173bcd7697c
child 20 597aaf25e343
--- a/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp	Tue Feb 02 01:24:03 2010 +0200
+++ b/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp	Sat Feb 20 00:10:51 2010 +0200
@@ -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;
@@ -174,10 +176,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 +340,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 +380,8 @@
 
 	// always make writting events MRU
 	DoMakePageMRU(aPos);
-    return;
+    
+    return pPage;
 	}
 
 /**
@@ -407,11 +410,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 +468,6 @@
             {
             WriteDataOntoSinglePageL(currMediaPos, pData, dataLen);
             }
-        }// else(dataLen <= bytesToPageEnd)
-
 
     //-- write data to the media
     const TInt nErr = iDrive.WriteCritical(aPos,aDes);
@@ -449,6 +476,11 @@
         InvalidateCache();
         User::Leave(nErr);
         }
+
+
+        }// else(dataLen <= bytesToPageEnd)
+
+
 	}
 
 /**
@@ -518,7 +550,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 +567,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 +582,6 @@
 	else if (pPage)
 		{
 		__PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) on Locked Queue!"), aPos);
-	    aCachedPosStart = pPage->StartPos();
 		return pPage->PageSizeInBytes();
 		}