persistentstorage/sqlite3api/OsLayer/FileBuf64.cpp
branchRCL_3
changeset 8 fa9941cf3867
parent 0 08ec8eefde2f
child 9 667e88a979d7
equal deleted inserted replaced
6:5ffdb8f2067f 8:fa9941cf3867
   184 #define __FBUF64_ASSERT(expr, panicCode) 	void(0)
   184 #define __FBUF64_ASSERT(expr, panicCode) 	void(0)
   185 
   185 
   186 #endif//_DEBUG
   186 #endif//_DEBUG
   187 
   187 
   188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   189 ///////////////////////////        MFileInitializer64    /////////////////////////////////////////////////////////////
       
   190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   191 
       
   192 /**
       
   193 MFileInitializer64 interface provides only one abstract method - Init() that is used during the initialization of
       
   194 the RFileBuf64 objects.
       
   195 Here is what is the problem MFileInitializer64 tries to solve.
       
   196 RFileBuf64 has 4 different "resource acquisition" methods - Create(), Open() and Temp().
       
   197 They perform different actions and have different input arguments.
       
   198 This is the variable part of the RFileBuf64 initialization.
       
   199 Apart from that, RFileBuf64 has a "fixed" initialization part that does not change whatever the variable part is.
       
   200 If MFileInitializer64 interface is not used then the following chunk of code has to be duplicated 4 times:
       
   201 @code
       
   202 	TInt err = do_fixed_init();
       
   203 	if(err == KErrNone)
       
   204 		{
       
   205 		err = do_variable_init();
       
   206 		if(err != KErrNone)
       
   207 			{
       
   208 			revert_fixed_init();
       
   209 			}
       
   210 		}
       
   211 	return err;
       
   212 @endcode
       
   213 In order to avoid the code duplication, the fixed part of the initialization is moved to RFileBuf64::DoInit(), which
       
   214 is given a reference to a MFileInitializer64 derived class that performas the variable part of the initialization.
       
   215 4 different MFileInitializer64 derived classes are provided for the 4 different "resource acquisition" methods.
       
   216 All they store the variable part of the RFileBuf64 initialization parameters and implement MFileInitializer64::Init().
       
   217 
       
   218 @see RFileBuf64::DoInit()
       
   219 @internalComponent
       
   220 */
       
   221 struct MFileInitializer64
       
   222 	{
       
   223 	virtual TInt Init(RFile64& aFile) = 0;
       
   224 	};
       
   225 	
       
   226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   227 ///////////////////////////        RFileBuf64    /////////////////////////////////////////////////////////////////////
   189 ///////////////////////////        RFileBuf64    /////////////////////////////////////////////////////////////////////
   228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   229 	
   191 	
   230 /**
   192 /**
   231 Initializes RFileBuf64 data members with their default values.
   193 Initializes RFileBuf64 data members with their default values.
   254 
   216 
   255 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   217 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   256 
   218 
   257 @see TFileMode
   219 @see TFileMode
   258 @see RFile64::Create()
   220 @see RFile64::Create()
   259 @see MFileInitializer64
       
   260 
   221 
   261 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   222 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   262 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   223 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   263 */
   224 */
   264 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   225 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   265 	{
   226 	{
   266 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   227 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   267 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   228 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   268 	
   229 	
   269 	struct TFileCreateInitializer64 : public MFileInitializer64
   230     TInt err = DoPreInit();
   270 		{
   231     if(err == KErrNone)
   271 		inline TFileCreateInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) :
   232         {
   272 			iFs(aFs),
   233         err = iFile.Create(aFs, aFileName, aFileMode);
   273 			iFileName(aFileName),
   234         }
   274 			iFileMode(aFileMode)
   235     return DoPostInit(err);
   275 			{
       
   276 			}
       
   277 		virtual TInt Init(RFile64& aFile)
       
   278 			{
       
   279 			return aFile.Create(iFs, iFileName, iFileMode);
       
   280 			}
       
   281 		RFs& 			iFs;
       
   282 		const TDesC& 	iFileName;
       
   283 		TUint 			iFileMode;
       
   284 		} initializer(aFs, aFileName, aFileMode);
       
   285 		
       
   286 	return DoInit(initializer);
       
   287 	}
   236 	}
   288 
   237 
   289 /**
   238 /**
   290 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   239 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   291 If the file does not already exist, an error is returned.
   240 If the file does not already exist, an error is returned.
   298 
   247 
   299 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   248 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   300 
   249 
   301 @see TFileMode
   250 @see TFileMode
   302 @see RFile64::Open()
   251 @see RFile64::Open()
   303 @see MFileInitializer64
       
   304 
   252 
   305 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   253 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   306 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   254 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   307 */
   255 */
   308 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   256 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   309 	{
   257 	{
   310 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   258 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   311 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   259 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   312 	
   260     
   313 	struct TFileOpenInitializer64 : public MFileInitializer64
   261     TInt err = DoPreInit();
   314 		{
   262     if(err == KErrNone)
   315 		inline TFileOpenInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) :
   263         {
   316 			iFs(aFs),
   264         err = iFile.Open(aFs, aFileName, aFileMode);
   317 			iFileName(aFileName),
   265         }
   318 			iFileMode(aFileMode)
   266     return DoPostInit(err);
   319 			{
       
   320 			}
       
   321 		virtual TInt Init(RFile64& aFile)
       
   322 			{
       
   323 			return aFile.Open(iFs, iFileName, iFileMode);
       
   324 			}
       
   325 		RFs& 			iFs;
       
   326 		const TDesC& 	iFileName;
       
   327 		TUint 			iFileMode;
       
   328 		} initializer(aFs, aFileName, aFileMode);
       
   329 
       
   330 	return DoInit(initializer);
       
   331 	}
   267 	}
   332 
   268 
   333 /**
   269 /**
   334 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   270 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   335 RFileBuf64 public interface.
   271 RFileBuf64 public interface.
   344 
   280 
   345 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   281 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   346 
   282 
   347 @see TFileMode
   283 @see TFileMode
   348 @see RFile64::Temp()
   284 @see RFile64::Temp()
   349 @see MFileInitializer64
       
   350 
   285 
   351 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   286 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   352 */
   287 */
   353 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
   288 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
   354 	{
   289 	{
   355 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   290 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   356 	
   291     
   357 	struct TFileTempInitializer64 : public MFileInitializer64
   292     TInt err = DoPreInit();
   358 		{
   293     if(err == KErrNone)
   359 		inline TFileTempInitializer64(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) :
   294         {
   360 			iFs(aFs),
   295         err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
   361 			iPath(aPath),
   296         }
   362 			iFileName(aFileName),
   297     return DoPostInit(err);
   363 			iFileMode(aFileMode)
       
   364 			{
       
   365 			}
       
   366 		virtual TInt Init(RFile64& aFile)
       
   367 			{
       
   368 			return aFile.Temp(iFs, iPath, iFileName, iFileMode);
       
   369 			}
       
   370 		RFs& 			iFs;
       
   371 		const TDesC& 	iPath;
       
   372 		TFileName& 		iFileName;
       
   373 		TUint 			iFileMode;
       
   374 		} initializer(aFs, aPath, aFileName, aFileMode);
       
   375 	
       
   376 	return DoInit(initializer);
       
   377 	}
   298 	}
   378 
   299 
   379 /**
   300 /**
   380 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   301 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   381 the RFileBuf64 resources. 
   302 the RFileBuf64 resources. 
   395 	iBase = 0;
   316 	iBase = 0;
   396 	}
   317 	}
   397 
   318 
   398 /**
   319 /**
   399 Calculates and sets optimal read-ahead buffer size.
   320 Calculates and sets optimal read-ahead buffer size.
       
   321 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
       
   322 
       
   323 Initialization rules:
       
   324 Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and 
       
   325         a power of two then the read-ahead value will be
       
   326         initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise
       
   327         the buffer capacity will be used as a read-ahead value). 
       
   328 Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize.
       
   329         If aBlockSize passes the checks then it will be used as a read-ahead value. 
   400 
   330 
   401 @param aBlockSize The size of a file block in bytes
   331 @param aBlockSize The size of a file block in bytes
   402 @param aReadRecBufSize The recommended buffer size for optimised reading performance
   332 @param aReadRecBufSize The recommended buffer size for optimised reading performance
   403 
   333 
   404 @return The new read-ahead value
   334 @return The new read-ahead value
   475 		}
   405 		}
   476 	//4. The requested data size is smaller than the buffer capacity
   406 	//4. The requested data size is smaller than the buffer capacity
   477 	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
   407 	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
   478 	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
   408 	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
   479 		{
   409 		{
   480 		//1. If part of all of the data is in the buffer - copy the data to the target location
   410 		//1. If part or all of the data is in the buffer - copy the data to the target location
   481 		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
   411 		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
   482 			{
   412 			{
   483 			TInt l = Min(len, (iFilePos + iLength - aFilePos));
   413 			TInt blocklen = Min(len, (iFilePos + iLength - aFilePos));
   484 			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), l);
   414 			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen);
   485 			len -= l;
   415 			len -= blocklen;
   486 			aFilePos += l;
   416 			aFilePos += blocklen;
   487 			}
   417 			}
   488 		//2. Perform a read-ahead operation
   418 		//2. Perform a read-ahead operation
   489 		else
   419 		else
   490 			{
   420 			{
   491 			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   421 			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   493 			if(err != KErrNone)
   423 			if(err != KErrNone)
   494 				{
   424 				{
   495 				break;	
   425 				break;	
   496 				}
   426 				}
   497 			if(iNextReadFilePos != aFilePos)
   427 			if(iNextReadFilePos != aFilePos)
   498 				{//Direct "file read" operation
   428 				{//Guessed read ahead was wrong. Direct "file read" operation
   499 				iNextReadFilePosHits = 0;
   429 				iNextReadFilePosHits = 0;
   500 				TPtr8 ptr2(outptr, len);
   430 				TPtr8 ptr2(outptr, len);
   501 				err = iFile.Read(aFilePos, ptr2);
   431 				err = iFile.Read(aFilePos, ptr2);
   502 				PROFILE_READ(aFilePos, ptr2.Size());
   432 				PROFILE_READ(aFilePos, ptr2.Size());
   503 				if(err == KErrNone)
   433 				if(err == KErrNone)
   788 	__FILEBUF64_INVARIANT();
   718 	__FILEBUF64_INVARIANT();
   789 	return iFile.Drive(aDriveNumber, aDriveInfo);
   719 	return iFile.Drive(aDriveNumber, aDriveInfo);
   790 	}
   720 	}
   791 
   721 
   792 /**
   722 /**
   793 Performs the fixed part of the RFileBuf64 initialization and then calls MFileInitializer64::Init() to perform
   723 Initializes RFileBuf64 data members with their initial values.   
   794 the variable part of the initialization.
   724 Allocates memory for the file buffer. 
   795 
   725  
   796 @param aFileInitializer A reference to an initializer object that implements MFileInitializer64::Init()
   726 @return KErrNone if successful, 
   797 
   727         KErrNoMemory out of memory;
   798 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   728 */
   799 */
   729 TInt RFileBuf64::DoPreInit()
   800 TInt RFileBuf64::DoInit(MFileInitializer64& aFileInitializer)
   730     {
   801 	{
   731     DoDiscard();
   802 	DoDiscard();
   732     iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
   803 	iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
   733     iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
   804 	TInt err = KErrNoMemory;
   734     return iBase ? KErrNone : KErrNoMemory; 
   805 	iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
   735     }
   806 	if(!iBase)
   736 
   807 		{
   737 /**
   808 		return KErrNoMemory;	
   738 Performs post-initialization of the RFileBuf64 object.   
   809 		}
   739 If aInitErr is not KErrNone, then the buffer memory will be released.
   810 	err = aFileInitializer.Init(iFile);
   740 The function returns the aInitErr value to the caller. 
   811 	if(err != KErrNone)
   741 
   812 		{
   742 @param aInitErr The result of the performed before the call RFileBuf64 initialization.
   813 		User::Free(iBase);
   743  
   814 		iBase = 0;
   744 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   815 		}
   745 */
   816 	return err;
   746 TInt RFileBuf64::DoPostInit(TInt aInitErr)
   817 	}
   747     {
       
   748     if(aInitErr != KErrNone)
       
   749         {
       
   750         User::Free(iBase);
       
   751         iBase = 0;
       
   752         }
       
   753     return aInitErr;
       
   754     }
   818 
   755 
   819 /**
   756 /**
   820 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
   757 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
   821 */
   758 */
   822 void RFileBuf64::DoDiscard()
   759 void RFileBuf64::DoDiscard()