userlibandfileserver/fileserver/sfat32/sl_disk.cpp
changeset 2 4122176ea935
child 6 0173bcd7697c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfat32/sl_disk.cpp	Mon Dec 21 16:14:42 2009 +0000
@@ -0,0 +1,494 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32\sfat\sl_disk.cpp
+// 
+//
+
+#include "sl_disk.h"
+#include "sl_cache.h"
+#include "sl_dir_cache.h"
+
+/**
+@file
+*/
+
+
+//################################################################################################################################
+//#     CRawDisk implementation
+//################################################################################################################################
+
+
+/**
+    Factory function. Constructs objects of the classes derived from CRawDisk.
+    
+    @param  aOwner      reference to the onwning FAT Mount class
+    @param  aLocDrvCaps local drive capabilities from the media driver
+    @return pointer to the constructed object. May be NULL on error.
+*/
+CRawDisk* CRawDisk::NewL(CFatMountCB& aOwner, const TLocalDriveCaps& aLocDrvCaps)
+{
+    __PRINT1(_L("CRawDisk::NewL() drv:%d"), aOwner.DriveNumber());
+
+    if(aLocDrvCaps.iMediaAtt & KMediaAttVariableSize)
+    {//-- this is the RAM drive "attribute"
+        ASSERT((aLocDrvCaps.iDriveAtt & (KDriveAttInternal|KDriveAttLocal)) && aLocDrvCaps.iType == EMediaRam);
+        if(!aLocDrvCaps.iBaseAddress)
+        {
+            ASSERT(0);
+            return NULL;
+        }
+
+        return CRamDisk::NewL(aOwner);
+    }
+
+    //-- create CAtaDisk by default
+    return CAtaDisk::NewL(aOwner);
+}
+
+
+CRawDisk::CRawDisk(CFatMountCB& aOwner)
+    {
+    iFatMount = &aOwner;
+    }
+
+/**
+    Default implementation. Initialises and re-initialises the object.
+*/
+void CRawDisk::InitializeL()
+    {
+    ASSERT(iFatMount);
+    }
+
+
+TInt CRawDisk::GetLastErrorInfo(TDes8& /*aErrorInfo*/) const
+	{
+	return KErrNotSupported;
+	}
+
+//################################################################################################################################
+//##    CAtaDisk class implementation
+//################################################################################################################################
+
+CAtaDisk::CAtaDisk(CFatMountCB& aFatMount)
+         :CRawDisk(aFatMount), iDrive(aFatMount.DriveInterface())
+	{
+	}
+
+CAtaDisk::~CAtaDisk()
+    {
+    delete ipDirCache;
+    delete iUidCache;
+    
+    }
+
+
+//-------------------------------------------------------------------------------------
+
+/**
+    CAtaDisk factory method.
+    
+    @param  aFatMount reference to the owner.
+    @return pointer to the constructed object.
+*/
+CAtaDisk* CAtaDisk::NewL(CFatMountCB& aFatMount)
+	{
+	__PRINT1(_L("CAtaDisk::NewL() drv:%d"), aFatMount.DriveNumber());
+
+    CAtaDisk* pSelf = new (ELeave) CAtaDisk(aFatMount);
+    
+    CleanupStack::PushL(pSelf);
+    
+    pSelf->ConstructL();
+    pSelf->InitializeL();
+    
+    CleanupStack::Pop();
+
+	return pSelf;
+	}
+
+//-------------------------------------------------------------------------------------
+
+/** 2nd stage constructor */
+void CAtaDisk::ConstructL()
+    {
+    //===========================  create data WT cache that is primarily used for caching exacutable modules' UIDs
+    const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page 
+    const TUint32 KUidCachePages = 64;     //-- 64 pages; total cache size is 32K 
+
+    iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2);
+
+
+    //=========================== create directory cache
+    
+    //-- Get dir. cache parameters from config. They may be set in estart.txt for a specified drive.
+    const TUint32 KDirCacheSize = iFatMount->FatConfig().DirCacheSize(); //- Total directory cache size, bytes.
+    const TUint32 KMaxDirCachePageSzLog2 = iFatMount->FatConfig().DirCacheMaxPageSizeLog2(); //- Log2 of the Max. dir. cache page.
+
+    __PRINT2(_L("CAtaDisk::ConstructL() Dir Cache config:%d,%d"),KDirCacheSize,KMaxDirCachePageSzLog2);
+
+    ASSERT(KDirCacheSize >= K1KiloByte && KDirCacheSize <= K1MegaByte);
+    ASSERT((KMaxDirCachePageSzLog2 >= KDefSectorSzLog2) && (Pow2(KMaxDirCachePageSzLog2) <= KDirCacheSize));
+
+    //-- calculate the size and number of pages for the dir. cache. 
+    //-- if the mount's cluster size is less than max. page size from config, the page size will be cluster size.
+    //-- otherwise it will be the value from config. I.e  the minimal page size is cluster size; the maximal page size is taken from config.
+    //-- The number of pages depends on total cache size and page size.
+    const TUint clustSizeLog2 = iFatMount->ClusterSizeLog2(); //-- current FAT cluster size Log2
+    const TUint32 pageSzLog2 = (clustSizeLog2 <= KMaxDirCachePageSzLog2) ? clustSizeLog2 : KMaxDirCachePageSzLog2;
+    const TUint32 numPages = KDirCacheSize / (Pow2(pageSzLog2));
+
+    ASSERT(!ipDirCache);
+
+#ifdef USE_DP_DIR_CACHE
+
+    //=========================== create Demand Paging type of the directory cache
+
+    // initialize cache memory manager as all file systems have mounted by now
+	if(CCacheMemoryManagerFactory::CacheMemoryManager())
+		{
+		// Note: the configuration data of min and max cache size are aligned with the memory size it
+		//	occupies in kernel as we are using demand paging subsystem for dynamic cache size support. 
+		//  Therefore, they are refered as 'Mem Size' in following calculation.
+		//  However, 'Data Size' refers to the logical size of a page, i.e. the actual data size each page
+		//  contains.
+		// The constraints we have to consider when setting up the dynamic cache:
+		// 	1. each page's data size is aligned with cluster size, unless cluster size is bigger than
+		//  	the default maximum page size allowed (typically 32 KB).
+		// 	2. if page's data size is smaller than segment size (typically 4 KB), i.e. the unit size of 
+		//     	demand paging subsystem's page management, we will still use up the whole segment for
+		// 		that page.
+		//  3. the default min and max cache's memory size is pre-defined in  fat_config.cpp file.
+		// 		(see KDef_DynamicDirCacheMin & KDef_DynamicDirCacheMax).
+
+		// calculate page data size (logical view of page size)
+	    const TUint32 DefMaxCachePageLog2 = iFatMount->FatConfig().DynamicDirCacheMaxPageSizeLog2();
+	    const TUint32 PageDataSizeLog2 = clustSizeLog2 < DefMaxCachePageLog2 ? clustSizeLog2 : DefMaxCachePageLog2;
+	    
+		// calculate page number, based on memory size we have reserved
+	    const TUint32 SegmentSizeLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
+	    const TUint32 PageMemSizeLog2 = PageDataSizeLog2 < SegmentSizeLog2 ? SegmentSizeLog2 : PageDataSizeLog2;
+	    TUint32 CacheSizeMinInPages = iFatMount->FatConfig().DynamicDirCacheSizeMin() >> PageMemSizeLog2;
+	    TUint32 CacheSizeMaxInPages = iFatMount->FatConfig().DynamicDirCacheSizeMax() >> PageMemSizeLog2;
+
+	    // cache memory client is connected via name 
+	    TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:");
+		clientName.Append('A'+iFatMount->DriveNumber());
+
+		TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName));
+		if (err == KErrNone)
+	    	{
+	    	__PRINT4(_L("CDynamicDirCache::NewL(drv:%C, minPageNum:%u, maxPageNum:%u, pageDataSize:%u)\n"), 'A'+iFatMount->DriveNumber(), CacheSizeMinInPages, CacheSizeMaxInPages, 1<<PageDataSizeLog2);
+	    	return;
+	    	}
+		}
+#endif // USE_DP_DIR_CACHE
+
+    //=========================== create legacy type of the directory cache
+    ASSERT(!ipDirCache);
+
+    ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2);
+    __PRINT3(_L("CDirCache::NewL(drive: %C, NumPages=%d, PageSize=%u)"), 'A'+iFatMount->DriveNumber(), numPages, 1<<pageSzLog2);
+    
+    }
+
+//-------------------------------------------------------------------------------------
+
+/**
+    Initialises and re-initialises the object.
+*/
+void CAtaDisk::InitializeL()
+{
+    CRawDisk::InitializeL();
+    
+    //-- there is a little issue here. after formatting FAT mounts's cluster size can change.
+    //-- dir. cache page size depends on the cluster size. This method doesn't change the dir. cache page size.
+    //-- At present it is done in CFatMountCB::InitializeL() that deletes this object and then reconstructs it again.
+
+    //-- invalidate directory cache here
+    ipDirCache->InvalidateCache();
+    
+    TInt64  cacheBasePos;
+    
+    if(iFatMount->FatType() == EFat32)
+        {
+        //-- this is FAT32, all directories including Root are files and aligned to the cluster heap boundary
+        //-- set dir. cache base position to the cluster heap boundary
+        const TUint32 offsetMask = (1 << iFatMount->ClusterSizeLog2() )-1;
+        cacheBasePos = (iFatMount->ClusterBasePosition() & offsetMask);
+        }
+    else
+        {
+        //-- this is FAT12/16. Root directory is a separate volume object and has no alignment.
+        //-- set cache base position to its beginning.
+        cacheBasePos = iFatMount->StartOfRootDirInBytes();
+        }
+
+    ipDirCache->SetCacheBasePos(cacheBasePos);
+    
+}
+
+//-------------------------------------------------------------------------------------
+
+/**
+    Read data from the media through LRU data cache cache. 
+
+    @param  aPos        absolute media position
+    @param  aLength     how many bytes to read
+    @param  aDes        data descriptor
+
+    @leave on error
+*/
+void CAtaDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
+	{
+    __PRINT3(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aLength);
+    iUidCache->ReadL(aPos, aLength, aDes);
+	}
+
+//-------------------------------------------------------------------------------------
+
+/**
+    Write data to the media through LRU data cache
+
+    @param  aPos        absolute media position
+    @param  aDes        data descriptor
+
+    @leave on error
+*/
+void CAtaDisk::WriteCachedL(TInt64 aPos, const TDesC8& aDes)
+	{
+    __PRINT3(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aDes.Size());
+    iUidCache->WriteL(aPos, aDes);
+	}
+
+
+//-------------------------------------------------------------------------------------
+
+/**
+    Read data from the media directly without any caches.
+    Mostly used by file IO
+
+    @param  aPos        absolute media position
+    @param  aLength     how many bytes to read
+	@param  aTrg		Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
+	@param  aMessage	Refrence to server message from request
+	@param  anOffset	Offset into read data to write
+
+    @leave on error
+*/
+void CAtaDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,const RMessagePtr2 &aMessage,TInt anOffset) const
+	{
+
+	__PRINT4(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
+	User::LeaveIfError(iDrive.ReadNonCritical(aPos,aLength,aTrg,aMessage,anOffset));
+	}
+
+//-------------------------------------------------------------------------------------
+
+/**
+    Write data to the media directly without any cached.
+    Mostly used by file IO
+
+    This method shall invalidate some data caches to keep them in synch with the media.
+
+    @param aPos		Media position in bytes
+    @param aLength	Length in bytes of write
+	@param aTrg		Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
+	@param aMessage	Refrence to server message from request, contains data
+	@param anOffset	Offset into write data to use in write
+
+    @leave on error
+*/
+void CAtaDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* aSrc,const RMessagePtr2 &aMessage,TInt anOffset)
+	{
+    __PRINT4(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
+
+	//-- write data to the media directly
+    User::LeaveIfError(iDrive.WriteNonCritical(aPos,aLength,aSrc,aMessage,anOffset));
+
+    //-- we need to invalidate UID cache page that corresponds to aPos (if any). This is UID caching specific. UID is stored in the first few bytes of 
+    //-- the executable module and therefore belongs to one cache page only.
+    //-- If someone writes to the beginning of the exe module file, corresponding UID cache page will be invalidated and re-read from the media later
+    iUidCache->InvalidateCachePage(aPos); 
+
+    //-- invalidate affected(if any) part of the FAT cache in the case if someone used to write data to FAT area, which usually do not happen 
+    iFatMount->FAT().InvalidateCacheL(aPos,aLength);
+
+	}
+
+//-------------------------------------------------------------------------------------
+
+/** Get information for last disk error */
+TInt CAtaDisk::GetLastErrorInfo(TDes8& aErrorInfo) const
+	{
+	return iDrive.GetLastErrorInfo(aErrorInfo);
+	}
+
+
+//-------------------------------------------------------------------------------------
+/** Invalidate whole UID cache */
+void CAtaDisk::InvalidateUidCache()
+{
+    ASSERT(iUidCache);
+    iUidCache->InvalidateCache();
+}
+
+/** 
+    Invalidate the UID cache page that has aPos cached.
+    This method doesn't pay attention to the length of the block being invalidated because
+    UID lives in the very beginning of the exe module and always fits into a single page
+*/
+void CAtaDisk::InvalidateUidCachePage(TUint64 aPos)
+{
+    ASSERT(iUidCache);
+    iUidCache->InvalidateCachePage(aPos);
+}
+
+
+//################################################################################################################################
+//##    CRamDisk class implementation
+//################################################################################################################################
+
+
+/**
+    CRamDisk factory method.
+    
+    @param  aFatMount reference to the owner.
+    @return pointer to the constructed object.
+*/
+CRamDisk* CRamDisk::NewL(CFatMountCB& aFatMount)
+	{
+    __PRINT1(_L("CRamDisk::NewL() drv:%d"), aFatMount.DriveNumber());
+	CRamDisk* pSelf = new(ELeave)CRamDisk(aFatMount);
+
+    CleanupStack::PushL(pSelf);
+  
+    pSelf->InitializeL();
+    
+    CleanupStack::Pop();
+
+	return pSelf;
+	}
+
+CRamDisk::CRamDisk(CFatMountCB& aFatMount)
+	     :CRawDisk(aFatMount)
+    {
+	}
+
+//-------------------------------------------------------------------------------------
+
+/**
+    Initialises and re-initialises the object.
+*/
+void CRamDisk::InitializeL()
+{
+    CRawDisk::InitializeL();
+
+    //-- set the RAM disk base
+    TLocalDriveCapsV2 caps;
+    TPckg<TLocalDriveCapsV2> capsPckg(caps);
+    User::LeaveIfError(iFatMount->LocalDrive()->Caps(capsPckg));
+  
+    ASSERT(caps.iMediaAtt & KMediaAttVariableSize);
+    
+    //-- set RAM disk base
+    iRamDiskBase = caps.iBaseAddress; 
+    ASSERT(iRamDiskBase);
+}
+
+
+
+/** @return the start address of the Ram Drive in low memory */
+TUint8* CRamDisk::RamDiskBase() const
+	{
+	return iRamDiskBase;
+	}
+
+//-------------------------------------------------------------------------------------
+//
+// Read aLength of data from the disk
+//
+void CRamDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
+	{
+	
+	__PRINT3(_L("CRamDisk::ReadL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),I64LOW(aPos),aLength);
+	__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
+	Mem::Copy((TUint8*)aDes.Ptr(),RamDiskBase()+I64LOW(aPos),aLength);
+	aDes.SetLength(aLength);
+	}
+
+//-------------------------------------------------------------------------------------
+//
+// Write aLength of data to the disk
+//
+void CRamDisk::WriteCachedL(TInt64 aPos,const TDesC8& aDes)
+	{
+
+	__PRINT3(_L("CRamDisk::WriteL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),aPos,aDes.Length());
+	__ASSERT_ALWAYS(aPos+aDes.Length()<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
+	Mem::Copy(RamDiskBase()+I64LOW(aPos),(TUint8*)aDes.Ptr(),aDes.Length());
+	}
+	
+
+//-------------------------------------------------------------------------------------
+//
+// Read from ramDrive into thread relative descriptor
+//
+void CRamDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* /*aTrg*/,const RMessagePtr2 &aMessage,TInt anOffset) const
+	{
+	__PRINT2(_L("CRamDisk::ReadL TAny* Pos 0x%x, Len %d"),aPos,aLength);
+	__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
+	TUint8* pos=RamDiskBase()+I64LOW(aPos);
+	TPtrC8 buf(pos,aLength);
+	aMessage.WriteL(0,buf,anOffset);
+	}
+
+//-------------------------------------------------------------------------------------
+//
+// Write from thread relative descriptor into ramDrive
+//
+void CRamDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* /*aSrc*/,const RMessagePtr2 &aMessage,TInt anOffset)
+	{
+	__PRINT2(_L("CRamDisk::WriteL TAny* Pos 0x%x, Len %d"),aPos,aLength);
+	__ASSERT_ALWAYS(aPos+aLength<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
+	TUint8* pos=RamDiskBase()+I64LOW(aPos);
+	TPtr8 buf(pos,aLength);
+	aMessage.ReadL(0,buf,anOffset);
+	}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+