userlibandfileserver/fileserver/sfile/sf_memory_client.cpp
changeset 9 96e5fb8b040d
child 11 329ab0095843
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfile\sf_memory_client.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include <e32std.h>
       
    24 #include <e32std_private.h>
       
    25 #include "sf_std.h"
       
    26 #include <e32uid.h>
       
    27 #include <e32wins.h>
       
    28 #include <f32file.h>
       
    29 #include "sf_memory_man.h"
       
    30 #include "sf_memory_client.h"
       
    31 
       
    32 
       
    33 CCacheMemoryClient::~CCacheMemoryClient()
       
    34 	{
       
    35 	const TUint32 segCnt = iTouchedRegionFlag <= iReservedRegionMarkInSegs ? 
       
    36 										iReservedRegionMarkInSegs : iTouchedRegionFlag;
       
    37 	DecommitSegments(iBase, segCnt);
       
    38 	iReusablePagePool.Close();
       
    39 	delete iName;
       
    40 	}
       
    41 
       
    42 /**
       
    43 Static factory function for CCacheMemoryClient
       
    44 @param	aManager	reference of CCacheMemoryManager that this client register with
       
    45 @param	aClientName	the unique identification of CCacheMemoryClient
       
    46 @param	aOffsetInBytes	the offset to the base position of CCacheMemoryManager it registered
       
    47 @param	aMinSizeInSegs	the minimum client size in segments, equals to the number of reserved segments
       
    48 @param	aMaxSizeInSegs	the maximum client size in segments
       
    49 */
       
    50 CCacheMemoryClient* CCacheMemoryClient::NewL(CCacheMemoryManager& aManager, const TDesC& aClientName, TUint32 aOffsetInBytes, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs)
       
    51 	{
       
    52 	// only create clients when sensible parameters are provided, otherwise will cause fatal error to file server 
       
    53 	if (aMinSizeInSegs > 0 && aMaxSizeInSegs >= aMinSizeInSegs && aClientName.Length() > 0)
       
    54 		{
       
    55 		CCacheMemoryClient* self = new(ELeave) CCacheMemoryClient(aManager, aMinSizeInSegs, aMaxSizeInSegs);
       
    56 		CleanupStack::PushL(self);
       
    57 		self->ConstructL(aClientName, aOffsetInBytes);
       
    58 		CleanupStack::Pop(1, self);
       
    59 		return self;
       
    60 		}
       
    61 	return NULL;
       
    62 	}
       
    63 
       
    64 /**
       
    65 Constructor of CCacheMemoryClient
       
    66 @param	aManager	reference of CCacheMemoryManager that this client register with
       
    67 @param	aMinSizeInSegs	the minimum client size in segments, equals to the number of reserved segments
       
    68 @param	aMaxSizeInSegs	the maximum client size in segments
       
    69 */
       
    70 CCacheMemoryClient::CCacheMemoryClient(CCacheMemoryManager& aManager, TUint32 aMinSizeInSegs, TUint32 aMaxSizeInSegs)
       
    71 :iManager(aManager),
       
    72 iMinSizeInSegs(aMinSizeInSegs),
       
    73 iMaxSizeInSegs(aMaxSizeInSegs)
       
    74 	{
       
    75 	}
       
    76 
       
    77 /**
       
    78 Second phase constructor of CCacheMemoryClient
       
    79 @param	aClientName	the unique identification of CCacheMemoryClient
       
    80 @param	aOffsetInBytes	the offset to the base position of CCacheMemoryManager it registered
       
    81 */
       
    82 void CCacheMemoryClient::ConstructL(const TDesC& aClientName, TUint32 aOffsetInBytes)
       
    83 	{
       
    84     __PRINT4(_L("CCacheMemoryClient::ConstructL(%S, min=%d, max=%d, base=0x%X)"), &aClientName, iMinSizeInSegs, iMaxSizeInSegs, iBase);
       
    85 	iName = HBufC::NewMaxL(aClientName.Length());
       
    86 	*iName = aClientName;
       
    87 	iSegSizeInBytesLog2 = iManager.SegmentSizeInBytesLog2();
       
    88 	iSegSizeInBytes = 1 << iSegSizeInBytesLog2;
       
    89 	iReusablePagePool.Close();
       
    90 	iReusablePagePool.ReserveL(iMinSizeInSegs);
       
    91 	iBase = iManager.Base() + aOffsetInBytes;
       
    92 	iReservedRegionMarkInSegs = iMinSizeInSegs;
       
    93 	TInt r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs);
       
    94 	ASSERT(r==KErrNone);
       
    95 	User::LeaveIfError(r);
       
    96 	iTouchedRegionFlag = 0;
       
    97 	__PRINT(_L("CCacheMemoryClient::ConstructL() return 0"));
       
    98 	}
       
    99 
       
   100 /**
       
   101 Reset the client state, this is normally issued from the cache it connected with.
       
   102 For exmaple, a FAT volume is dismounted so the directory cache needs to be reset.
       
   103 Although the cache is reset, the CCacheMemoryClient object should not be destroyed and the reserved region should still 
       
   104 be hold to make sure when the cache re-connect with the CCacheMemoryClient, it will not fail due to OOM conditions.
       
   105 
       
   106 @internalTechnology
       
   107 @released
       
   108 */
       
   109 EXPORT_C void CCacheMemoryClient::Reset()
       
   110 	{
       
   111 	__PRINT3(_L("CCacheMemoryClient::Reset(%S, reserved=%d, touched=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag);
       
   112 	
       
   113 	// reset the cache memeory client to initial states: 
       
   114 	//     1. all memory that have been 'touched' should be decommitted
       
   115 	//     2. the reserved region of memory should be re-locked
       
   116 
       
   117 	// if we have touched more than reserved region of memory, we shall decommit all of them 
       
   118 	if (iTouchedRegionFlag > iReservedRegionMarkInSegs)
       
   119 	    {
       
   120 	    TInt r = DecommitSegments(iBase, iTouchedRegionFlag);
       
   121 	    if (r != KErrNone)  // this 'if() {}' is to remove build warnings in debug mode, same is below
       
   122 	        {
       
   123 	        ASSERT(0);
       
   124 	        }
       
   125 	    }
       
   126 	else   // otherwise we decommit the reserved region of memory only.
       
   127 	    {
       
   128 	    TInt r = DecommitSegments(iBase, iReservedRegionMarkInSegs);
       
   129 	    if (r != KErrNone)  // this 'if() {}' is to remove build warnings in debug mode, same is below
       
   130 	        {
       
   131 	        ASSERT(0);
       
   132 	        }
       
   133 	    }
       
   134 
       
   135     // re-lock the reserved region of memory
       
   136 	TInt r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs);
       
   137     if (r != KErrNone)
       
   138         {
       
   139         ASSERT(0);
       
   140         }
       
   141 
       
   142 	iTouchedRegionFlag = 0;
       
   143 	iReusablePagePool.Close();
       
   144 	iReusablePagePool.Reserve(iReservedRegionMarkInSegs);
       
   145 	}
       
   146 
       
   147 /**
       
   148 Commit an unused set of contiguous segments. 
       
   149 @param	aSegmentCount	the segment number to be commited.
       
   150 @return	TUint8*	the starting ram address of the commited segments.
       
   151 
       
   152 @internalTechnology
       
   153 @released
       
   154 */
       
   155 EXPORT_C TUint8* CCacheMemoryClient::AllocateAndLockSegments(TUint32 aSegmentCount)
       
   156 	{
       
   157 	__PRINT4(_L("CCacheMemoryClient::AllocateAndLockSegments(%S, segs=%d, reserved=%d, touched=%d)"), iName, aSegmentCount, iReservedRegionMarkInSegs, iTouchedRegionFlag);
       
   158 //	__PRINT2(_L("iBase = 0x%x, segcnt = %d"), iBase, aSegmentCount);
       
   159     TUint8* addr = NULL;
       
   160     // if we are walking through the reserved region first time, we should
       
   161     // make assumption that this area is locked already
       
   162     if (iTouchedRegionFlag + aSegmentCount <= iReservedRegionMarkInSegs)
       
   163        	{
       
   164        	addr = iBase + (iTouchedRegionFlag << iSegSizeInBytesLog2);
       
   165        	iTouchedRegionFlag += aSegmentCount;
       
   166 //       	__PRINT3(_L("!! USED RESERVED SEGS: addr=0x%x, touched=%d, reserved=%d"), addr, iTouchedRegionFlag, iReservedRegionMarkInSegs);
       
   167        	return addr;
       
   168        	}
       
   169     
       
   170 	// if we have used up reserved region, get new pages from reusable pool first
       
   171     if (iReusablePagePool.Count())
       
   172     	{
       
   173 		addr = iReusablePagePool[0];
       
   174 		iReusablePagePool.Remove(0);
       
   175 //       	__PRINT2(_L("!! USED REUSABLE POOL SEGS: addr=0x%x, reusable.Count()=%d"), addr, iReusablePagePool.Count());
       
   176     	}
       
   177     // or we grow the touched region flag
       
   178     else
       
   179     	{
       
   180     	addr = iBase + (iTouchedRegionFlag << iSegSizeInBytesLog2);
       
   181     	iTouchedRegionFlag += aSegmentCount;
       
   182 //       	__PRINT2(_L("!! GROW TOUCHED SEGS: addr=0x%x, touched=%d"), addr, iTouchedRegionFlag);
       
   183     	}
       
   184 	
       
   185     // parameter validation
       
   186     ASSERT(((addr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount <= iMaxSizeInSegs);
       
   187     if(((addr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs)
       
   188     	{
       
   189     	ASSERT(0);
       
   190     	return NULL;
       
   191     	}
       
   192 
       
   193     TInt r = iManager.AllocateAndLockSegments(addr, aSegmentCount);
       
   194 	if (r != KErrNone)
       
   195 		return NULL;
       
   196 
       
   197 	return addr;
       
   198 	}
       
   199 
       
   200 /**
       
   201 Decommit a set of contiguous segments. 
       
   202 @param	aStartRamAddr	the start ram address of the region to be decommitted.
       
   203 @param	aSegmentCount	the segment number to be decommited.
       
   204 @return		KErrNone if succeed, otherwise a system-wide error code.
       
   205 
       
   206 @internalTechnology
       
   207 @released
       
   208 */
       
   209 EXPORT_C TInt CCacheMemoryClient::DecommitSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
       
   210 	{
       
   211 	__PRINT4(_L("CCacheMemoryClient::DecommitSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, aSegmentCount);
       
   212 	// parameter validation
       
   213 	if(aStartRamAddr < iBase || 
       
   214 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
       
   215 		{
       
   216 		ASSERT(0);
       
   217 		return KErrArgument;
       
   218 		}
       
   219 	
       
   220 	TInt err = iManager.DecommitSegments(aStartRamAddr, aSegmentCount);
       
   221 	ASSERT(err == KErrNone);
       
   222 	if (err != KErrNone)
       
   223 		return err;
       
   224 	iReusablePagePool.Append(aStartRamAddr);
       
   225 	return KErrNone;
       
   226 	}
       
   227 
       
   228 /**
       
   229 Lock a set of contiguous segments. 
       
   230 @param	aStartRamAddr	the start ram address of the region to be locked.
       
   231 @param	aSegmentCount	the segment number to be locked.
       
   232 @return		KErrNone if succeed, otherwise a system-wide error code.
       
   233 
       
   234 @internalTechnology
       
   235 @released
       
   236 */
       
   237 EXPORT_C TInt CCacheMemoryClient::LockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
       
   238 	{
       
   239 	__PRINT4(_L("CCacheMemoryClient::LockSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, (aStartRamAddr - iBase) >> iSegSizeInBytesLog2);
       
   240 	// parameter validation
       
   241 	if(aStartRamAddr < iBase || 
       
   242 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
       
   243 		{
       
   244 		ASSERT(0);
       
   245 		return KErrArgument;
       
   246 		}
       
   247 	return iManager.LockSegments(aStartRamAddr, aSegmentCount);
       
   248 	}
       
   249 
       
   250 /**
       
   251 Unlock a set of contiguous segments. 
       
   252 @param	aStartRamAddr	the start ram address of the region to be unlocked.
       
   253 @param	aSegmentCount	the segment number to be unlocked.
       
   254 @return		KErrNone if succeed, otherwise a system-wide error code.
       
   255 
       
   256 @internalTechnology
       
   257 @released
       
   258 */
       
   259 EXPORT_C TInt CCacheMemoryClient::UnlockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
       
   260 	{
       
   261 	__PRINT4(_L("CCacheMemoryClient::UnlockSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, (aStartRamAddr - iBase) >> iSegSizeInBytesLog2);
       
   262 	// validate parameters
       
   263 	if(aStartRamAddr < iBase || 
       
   264 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
       
   265 		{
       
   266 		ASSERT(0);
       
   267 		return KErrArgument;
       
   268 		}
       
   269 	return iManager.UnlockSegments(aStartRamAddr, aSegmentCount);
       
   270 	}
       
   271 
       
   272 //////////////////////////// auxiliary functions /////////////////////////
       
   273 TUint32 CCacheMemoryClient::MaxSizeInBytes()
       
   274 	{
       
   275 	return iMaxSizeInSegs  << iSegSizeInBytesLog2;
       
   276 	}
       
   277 
       
   278 const TDesC& CCacheMemoryClient::Name() const
       
   279 	{
       
   280 	return *iName;
       
   281 	}
       
   282