userlibandfileserver/fileserver/sfile/sf_memory_client.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	iName = HBufC::NewMaxL(aClientName.Length());
       
    85 	*iName = aClientName;
       
    86 	iSegSizeInBytesLog2 = iManager.SegmentSizeInBytesLog2();
       
    87 	iSegSizeInBytes = 1 << iSegSizeInBytesLog2;
       
    88 	iReusablePagePool.Close();
       
    89 	iReusablePagePool.ReserveL(iMinSizeInSegs);
       
    90 	iBase = iManager.Base() + aOffsetInBytes;
       
    91 	iReservedRegionMarkInSegs = iMinSizeInSegs;
       
    92 	TInt r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs);
       
    93 	ASSERT(r==KErrNone);
       
    94 	User::LeaveIfError(r);
       
    95 	iTouchedRegionFlag = 0;
       
    96 	__PRINT4(_L("CCacheMemoryClient::ConstructL(%S, min=%d, max=%d, base=0x%X)"), &aClientName, iMinSizeInSegs, iMaxSizeInSegs, iBase);
       
    97 	}
       
    98 
       
    99 /**
       
   100 Reset the client state, this is normally issued from the cache it connected with.
       
   101 For exmaple, a FAT volume is dismounted so the directory cache needs to be reset.
       
   102 Although the cache is reset, the CCacheMemoryClient object should not be destroyed and the reserved region should still 
       
   103 be hold to make sure when the cache re-connect with the CCacheMemoryClient, it will not fail due to OOM conditions.
       
   104 
       
   105 @internalTechnology
       
   106 @released
       
   107 */
       
   108 EXPORT_C void CCacheMemoryClient::Reset()
       
   109 	{
       
   110 	__PRINT3(_L("CCacheMemoryClient::Reset(%S, reserved=%d, touched=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag);
       
   111 	
       
   112 	// in case that client user has incorrectly decommited reserved region (normally on destruction), 
       
   113 	//	we should re-commit reserved region here to prepare the next connection.
       
   114 	TInt r = DecommitSegments(iBase, iReservedRegionMarkInSegs);
       
   115 	if (r != KErrNone)	// this 'if() {}' is to remove build warnings in debug mode, same is below
       
   116 		{
       
   117 		ASSERT(0);
       
   118 		}
       
   119 
       
   120 	r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs);
       
   121 	if (r != KErrNone)
       
   122 		{
       
   123 		ASSERT(0);
       
   124 		}
       
   125 
       
   126 	// if we have touched more than reserved, we also need to make sure it's decommitted.
       
   127 	if (iTouchedRegionFlag > iReservedRegionMarkInSegs)
       
   128 		{
       
   129 		TInt r = iManager.DecommitSegments(iBase + (iReservedRegionMarkInSegs << iSegSizeInBytesLog2), iTouchedRegionFlag - iReservedRegionMarkInSegs);
       
   130 		if (r != KErrNone)
       
   131 			{
       
   132 			ASSERT(0);
       
   133 			}
       
   134 		}
       
   135 	
       
   136 	iTouchedRegionFlag = 0;
       
   137 	iReusablePagePool.Close();
       
   138 	iReusablePagePool.Reserve(iReservedRegionMarkInSegs);
       
   139 	}
       
   140 
       
   141 /**
       
   142 Commit an unused set of contiguous segments. 
       
   143 @param	aSegmentCount	the segment number to be commited.
       
   144 @return	TUint8*	the starting ram address of the commited segments.
       
   145 
       
   146 @internalTechnology
       
   147 @released
       
   148 */
       
   149 EXPORT_C TUint8* CCacheMemoryClient::AllocateAndLockSegments(TUint32 aSegmentCount)
       
   150 	{
       
   151 	__PRINT3(_L("CCacheMemoryClient::AllocateAndLockSegments(%S, reserved=%d, touched=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag);
       
   152 //	__PRINT2(_L("iBase = 0x%x, segcnt = %d"), iBase, aSegmentCount);
       
   153     TUint8* addr = NULL;
       
   154     // if we are walking through the reserved region first time, we should
       
   155     // make assumption that this area is locked already
       
   156     if (iTouchedRegionFlag + aSegmentCount <= iReservedRegionMarkInSegs)
       
   157        	{
       
   158        	addr = iBase + (iTouchedRegionFlag << iSegSizeInBytesLog2);
       
   159        	iTouchedRegionFlag += aSegmentCount;
       
   160 //       	__PRINT3(_L("!! USED RESERVED SEGS: addr=0x%x, touched=%d, reserved=%d"), addr, iTouchedRegionFlag, iReservedRegionMarkInSegs);
       
   161        	return addr;
       
   162        	}
       
   163     
       
   164 	// if we have used up reserved region, get new pages from reusable pool first
       
   165     if (iReusablePagePool.Count())
       
   166     	{
       
   167 		addr = iReusablePagePool[0];
       
   168 		iReusablePagePool.Remove(0);
       
   169 //       	__PRINT2(_L("!! USED REUSABLE POOL SEGS: addr=0x%x, reusable.Count()=%d"), addr, iReusablePagePool.Count());
       
   170     	}
       
   171     // or we grow the touched region flag
       
   172     else
       
   173     	{
       
   174     	addr = iBase + (iTouchedRegionFlag << iSegSizeInBytesLog2);
       
   175     	iTouchedRegionFlag += aSegmentCount;
       
   176 //       	__PRINT2(_L("!! GROW TOUCHED SEGS: addr=0x%x, touched=%d"), addr, iTouchedRegionFlag);
       
   177     	}
       
   178 	
       
   179     // parameter validation
       
   180     ASSERT(((addr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount <= iMaxSizeInSegs);
       
   181     if(((addr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs)
       
   182     	{
       
   183     	ASSERT(0);
       
   184     	return NULL;
       
   185     	}
       
   186 
       
   187     TInt r = iManager.AllocateAndLockSegments(addr, aSegmentCount);
       
   188 	if (r != KErrNone)
       
   189 		return NULL;
       
   190 
       
   191 	return addr;
       
   192 	}
       
   193 
       
   194 /**
       
   195 Decommit a set of contiguous segments. 
       
   196 @param	aStartRamAddr	the start ram address of the region to be decommitted.
       
   197 @param	aSegmentCount	the segment number to be decommited.
       
   198 @return		KErrNone if succeed, otherwise a system-wide error code.
       
   199 
       
   200 @internalTechnology
       
   201 @released
       
   202 */
       
   203 EXPORT_C TInt CCacheMemoryClient::DecommitSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
       
   204 	{
       
   205 	__PRINT4(_L("CCacheMemoryClient::DecommitSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, aSegmentCount);
       
   206 	// parameter validation
       
   207 	if(aStartRamAddr < iBase || 
       
   208 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
       
   209 		{
       
   210 		ASSERT(0);
       
   211 		return KErrArgument;
       
   212 		}
       
   213 	
       
   214 	TInt err = iManager.DecommitSegments(aStartRamAddr, aSegmentCount);
       
   215 	ASSERT(err == KErrNone);
       
   216 	if (err != KErrNone)
       
   217 		return err;
       
   218 	iReusablePagePool.Append(aStartRamAddr);
       
   219 	return KErrNone;
       
   220 	}
       
   221 
       
   222 /**
       
   223 Lock a set of contiguous segments. 
       
   224 @param	aStartRamAddr	the start ram address of the region to be locked.
       
   225 @param	aSegmentCount	the segment number to be locked.
       
   226 @return		KErrNone if succeed, otherwise a system-wide error code.
       
   227 
       
   228 @internalTechnology
       
   229 @released
       
   230 */
       
   231 EXPORT_C TInt CCacheMemoryClient::LockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
       
   232 	{
       
   233 	__PRINT4(_L("CCacheMemoryClient::LockSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, (aStartRamAddr - iBase) >> iSegSizeInBytesLog2);
       
   234 	// parameter validation
       
   235 	if(aStartRamAddr < iBase || 
       
   236 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
       
   237 		{
       
   238 		ASSERT(0);
       
   239 		return KErrArgument;
       
   240 		}
       
   241 	return iManager.LockSegments(aStartRamAddr, aSegmentCount);
       
   242 	}
       
   243 
       
   244 /**
       
   245 Unlock a set of contiguous segments. 
       
   246 @param	aStartRamAddr	the start ram address of the region to be unlocked.
       
   247 @param	aSegmentCount	the segment number to be unlocked.
       
   248 @return		KErrNone if succeed, otherwise a system-wide error code.
       
   249 
       
   250 @internalTechnology
       
   251 @released
       
   252 */
       
   253 EXPORT_C TInt CCacheMemoryClient::UnlockSegments(TUint8* aStartRamAddr, TUint32 aSegmentCount)
       
   254 	{
       
   255 	__PRINT4(_L("CCacheMemoryClient::UnlockSegments(%S, reserved=%d, touched=%d, segNo=%d)"), iName, iReservedRegionMarkInSegs, iTouchedRegionFlag, (aStartRamAddr - iBase) >> iSegSizeInBytesLog2);
       
   256 	// validate parameters
       
   257 	if(aStartRamAddr < iBase || 
       
   258 			(((aStartRamAddr - iBase) >> iSegSizeInBytesLog2) + aSegmentCount > iMaxSizeInSegs))
       
   259 		{
       
   260 		ASSERT(0);
       
   261 		return KErrArgument;
       
   262 		}
       
   263 	return iManager.UnlockSegments(aStartRamAddr, aSegmentCount);
       
   264 	}
       
   265 
       
   266 //////////////////////////// auxiliary functions /////////////////////////
       
   267 TUint32 CCacheMemoryClient::MaxSizeInBytes()
       
   268 	{
       
   269 	return iMaxSizeInSegs  << iSegSizeInBytesLog2;
       
   270 	}
       
   271 
       
   272 const TDesC& CCacheMemoryClient::Name() const
       
   273 	{
       
   274 	return *iName;
       
   275 	}
       
   276