persistentstorage/sql/OsLayer/FileBuf64.cpp
changeset 15 3eacc0623088
parent 0 08ec8eefde2f
child 11 667e88a979d7
equal deleted inserted replaced
14:15018f1726c7 15:3eacc0623088
   190 #define __FBUF64_ASSERT(expr, panicCode) 	void(0)
   190 #define __FBUF64_ASSERT(expr, panicCode) 	void(0)
   191 
   191 
   192 #endif//_DEBUG
   192 #endif//_DEBUG
   193 
   193 
   194 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   194 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   195 ///////////////////////////        MFileInitializer64    /////////////////////////////////////////////////////////////
       
   196 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   197 
       
   198 /**
       
   199 MFileInitializer64 interface provides only one abstract method - Init() that is used during the initialization of
       
   200 the RFileBuf64 objects.
       
   201 Here is what is the problem MFileInitializer64 tries to solve.
       
   202 RFileBuf64 has 4 different "resource acquisition" methods - Create(), Open(), Temp() and AdoptFromClient().
       
   203 They perform different actions and have different input arguments.
       
   204 This is the variable part of the RFileBuf64 initialization.
       
   205 Apart from that, RFileBuf64 has a "fixed" initialization part that does not change whatever the variable part is.
       
   206 If MFileInitializer64 interface is not used then the following chunk of code has to be duplicated 4 times:
       
   207 @code
       
   208 	TInt err = do_fixed_init();
       
   209 	if(err == KErrNone)
       
   210 		{
       
   211 		err = do_variable_init();
       
   212 		if(err != KErrNone)
       
   213 			{
       
   214 			revert_fixed_init();
       
   215 			}
       
   216 		}
       
   217 	return err;
       
   218 @endcode
       
   219 In order to avoid the code duplication, the fixed part of the initialization is moved to RFileBuf64::DoInit(), which
       
   220 is given a reference to a MFileInitializer64 derived class that performas the variable part of the initialization.
       
   221 4 different MFileInitializer64 derived classes are provided for the 4 different "resource acquisition" methods.
       
   222 All they store the variable part of the RFileBuf64 initialization parameters and implement MFileInitializer64::Init().
       
   223 
       
   224 @see RFileBuf64::DoInit()
       
   225 @internalComponent
       
   226 */
       
   227 struct MFileInitializer64
       
   228 	{
       
   229 	virtual TInt Init(RFile64& aFile) = 0;
       
   230 	};
       
   231 	
       
   232 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   233 ///////////////////////////        RFileBuf64    /////////////////////////////////////////////////////////////////////
   195 ///////////////////////////        RFileBuf64    /////////////////////////////////////////////////////////////////////
   234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   196 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   235 	
   197 	
   236 /**
   198 /**
   237 Initializes RFileBuf64 data members with their default values.
   199 Initializes RFileBuf64 data members with their default values.
   260 
   222 
   261 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   223 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   262 
   224 
   263 @see TFileMode
   225 @see TFileMode
   264 @see RFile64::Create()
   226 @see RFile64::Create()
   265 @see MFileInitializer64
       
   266 
   227 
   267 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   228 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   268 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   229 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   269 */
   230 */
   270 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   231 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   271 	{
   232 	{
   272 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   233 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   273 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   234 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   274 	
   235 	
   275 	struct TFileCreateInitializer64 : public MFileInitializer64
   236 	TInt err = DoPreInit();
   276 		{
   237 	if(err == KErrNone)
   277 		inline TFileCreateInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) :
   238 	    {
   278 			iFs(aFs),
   239 	    err = iFile.Create(aFs, aFileName, aFileMode);
   279 			iFileName(aFileName),
   240 	    }
   280 			iFileMode(aFileMode)
   241 	return DoPostInit(err);
   281 			{
       
   282 			}
       
   283 		virtual TInt Init(RFile64& aFile)
       
   284 			{
       
   285 			return aFile.Create(iFs, iFileName, iFileMode);
       
   286 			}
       
   287 		RFs& 			iFs;
       
   288 		const TDesC& 	iFileName;
       
   289 		TUint 			iFileMode;
       
   290 		} initializer(aFs, aFileName, aFileMode);
       
   291 		
       
   292 	return DoInit(initializer);
       
   293 	}
   242 	}
   294 
   243 
   295 /**
   244 /**
   296 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   245 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   297 If the file does not already exist, an error is returned.
   246 If the file does not already exist, an error is returned.
   304 
   253 
   305 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   254 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   306 
   255 
   307 @see TFileMode
   256 @see TFileMode
   308 @see RFile64::Open()
   257 @see RFile64::Open()
   309 @see MFileInitializer64
       
   310 
   258 
   311 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   259 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   312 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   260 @panic FBuf64 10 In _DEBUG mode - Invalid file name length (zero file name length).
   313 */
   261 */
   314 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   262 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   315 	{
   263 	{
   316 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   264 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   317 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   265 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
   318 	
   266 	
   319 	struct TFileOpenInitializer64 : public MFileInitializer64
   267     TInt err = DoPreInit();
   320 		{
   268     if(err == KErrNone)
   321 		inline TFileOpenInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) :
   269         {
   322 			iFs(aFs),
   270         err = iFile.Open(aFs, aFileName, aFileMode);
   323 			iFileName(aFileName),
   271         }
   324 			iFileMode(aFileMode)
   272     return DoPostInit(err);
   325 			{
       
   326 			}
       
   327 		virtual TInt Init(RFile64& aFile)
       
   328 			{
       
   329 			return aFile.Open(iFs, iFileName, iFileMode);
       
   330 			}
       
   331 		RFs& 			iFs;
       
   332 		const TDesC& 	iFileName;
       
   333 		TUint 			iFileMode;
       
   334 		} initializer(aFs, aFileName, aFileMode);
       
   335 
       
   336 	return DoInit(initializer);
       
   337 	}
   273 	}
   338 
   274 
   339 /**
   275 /**
   340 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   276 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   341 RFileBuf64 public interface.
   277 RFileBuf64 public interface.
   350 
   286 
   351 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   287 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   352 
   288 
   353 @see TFileMode
   289 @see TFileMode
   354 @see RFile64::Temp()
   290 @see RFile64::Temp()
   355 @see MFileInitializer64
       
   356 
   291 
   357 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   292 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   358 */
   293 */
   359 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
   294 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
   360 	{
   295 	{
   361 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   296 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
   362 	
   297 	
   363 	struct TFileTempInitializer64 : public MFileInitializer64
   298     TInt err = DoPreInit();
   364 		{
   299     if(err == KErrNone)
   365 		inline TFileTempInitializer64(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) :
   300         {
   366 			iFs(aFs),
   301         err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
   367 			iPath(aPath),
   302         }
   368 			iFileName(aFileName),
   303     return DoPostInit(err);
   369 			iFileMode(aFileMode)
       
   370 			{
       
   371 			}
       
   372 		virtual TInt Init(RFile64& aFile)
       
   373 			{
       
   374 			return aFile.Temp(iFs, iPath, iFileName, iFileMode);
       
   375 			}
       
   376 		RFs& 			iFs;
       
   377 		const TDesC& 	iPath;
       
   378 		TFileName& 		iFileName;
       
   379 		TUint 			iFileMode;
       
   380 		} initializer(aFs, aPath, aFileName, aFileMode);
       
   381 	
       
   382 	return DoInit(initializer);
       
   383 	}
   304 	}
   384 
   305 
   385 /**
   306 /**
   386 Initializes the RFileBuf64 object and creates and adopts an already open file from a client that will be accessed through 
   307 Initializes the RFileBuf64 object and creates and adopts an already open file from a client that will be accessed through 
   387 RFileBuf64 public interface.
   308 RFileBuf64 public interface.
   396             
   317             
   397 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   318 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   398 
   319 
   399 @see TFileMode
   320 @see TFileMode
   400 @see RFile64::AdoptFromClient()
   321 @see RFile64::AdoptFromClient()
   401 @see MFileInitializer64
       
   402 @see KMaxMessageArguments
   322 @see KMaxMessageArguments
   403 
   323 
   404 @panic FBuf64  8 In _DEBUG mode - Invalid aMsg object (null message handle).
   324 @panic FBuf64  8 In _DEBUG mode - Invalid aMsg object (null message handle).
   405 @panic FBuf64  9 In _DEBUG mode - Invalid file session handle message slot index or invalid file handle message slot index.
   325 @panic FBuf64  9 In _DEBUG mode - Invalid file session handle message slot index or invalid file handle message slot index.
   406                  (Probably negative index or index bigger or equal to KMaxMessageArguments)
   326                  (Probably negative index or index bigger or equal to KMaxMessageArguments)
   409 	{
   329 	{
   410 	__FBUF64_ASSERT(aMsg.Handle() != 0, EFBufPanicMsgHandle);
   330 	__FBUF64_ASSERT(aMsg.Handle() != 0, EFBufPanicMsgHandle);
   411 	__FBUF64_ASSERT(aFsIndex >= 0 && aFsIndex < KMaxMessageArguments, EFBufPanicMsgIndex);
   331 	__FBUF64_ASSERT(aFsIndex >= 0 && aFsIndex < KMaxMessageArguments, EFBufPanicMsgIndex);
   412 	__FBUF64_ASSERT(aFileIndex >= 0 && aFileIndex < KMaxMessageArguments, EFBufPanicMsgIndex);
   332 	__FBUF64_ASSERT(aFileIndex >= 0 && aFileIndex < KMaxMessageArguments, EFBufPanicMsgIndex);
   413 	
   333 	
   414 	struct TFileAdoptInitializer64 : public MFileInitializer64
   334     TInt err = DoPreInit();
   415 		{
   335     if(err == KErrNone)
   416 		inline TFileAdoptInitializer64(const RMessage2& aMsg, TInt aFsIndex, TInt aFileIndex) :
   336         {
   417 			iMsg(aMsg),
   337         err = iFile.AdoptFromClient(aMsg, aFsIndex, aFileIndex);
   418 			iFsIndex(aFsIndex),
   338         }
   419 			iFileIndex(aFileIndex)
   339     return DoPostInit(err);
   420 			{
       
   421 			}
       
   422 		virtual TInt Init(RFile64& aFile)
       
   423 			{
       
   424 			return aFile.AdoptFromClient(iMsg, iFsIndex, iFileIndex);
       
   425 			}
       
   426 		const RMessage2&	iMsg;
       
   427 		TInt 				iFsIndex;
       
   428 		TInt				iFileIndex;
       
   429 		} initializer(aMsg, aFsIndex, aFileIndex);
       
   430 	
       
   431 	return DoInit(initializer);
       
   432 	}
   340 	}
   433 
   341 
   434 /**
   342 /**
   435 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   343 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   436 the RFileBuf64 resources. 
   344 the RFileBuf64 resources. 
   450 	iBase = 0;
   358 	iBase = 0;
   451 	}
   359 	}
   452 
   360 
   453 /**
   361 /**
   454 Calculates and sets optimal read-ahead buffer size.
   362 Calculates and sets optimal read-ahead buffer size.
       
   363 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
       
   364 
       
   365 Initialization rules:
       
   366 Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and 
       
   367         a power of two then the read-ahead value will be
       
   368         initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise
       
   369         the buffer capacity will be used as a read-ahead value). 
       
   370 Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize.
       
   371         If aBlockSize passes the checks then it will be used as a read-ahead value. 
       
   372 
   455 
   373 
   456 @param aBlockSize The size of a file block in bytes
   374 @param aBlockSize The size of a file block in bytes
   457 @param aReadRecBufSize The recommended buffer size for optimised reading performance
   375 @param aReadRecBufSize The recommended buffer size for optimised reading performance
   458 
   376 
   459 @return The new read-ahead value
   377 @return The new read-ahead value
   514 		}
   432 		}
   515 	//3. Too big "read" request - read directly from the file
   433 	//3. Too big "read" request - read directly from the file
   516 	TInt len = aDes.MaxLength();
   434 	TInt len = aDes.MaxLength();
   517 	if(len > iCapacity)
   435 	if(len > iCapacity)
   518 		{
   436 		{
   519 		if((aFilePos + len) > iFilePos && !(aFilePos >= (iFilePos + iLength)))
   437 		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
   520 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   438 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   521 			err = DoFileWrite1(aFilePos);
   439 			err = DoFileWrite1(aFilePos);
   522 			}
   440 			}
   523 		if(err == KErrNone)
   441 		if(err == KErrNone)
   524 			{
   442 			{
   530 		}
   448 		}
   531 	//4. The requested data size is smaller than the buffer capacity
   449 	//4. The requested data size is smaller than the buffer capacity
   532 	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
   450 	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
   533 	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
   451 	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
   534 		{
   452 		{
   535 		//1. If part of all of the data is in the buffer - copy the data to the target location
   453 		//1. If part or all of the data is in the buffer - copy the data to the target location
   536 		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
   454 		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
   537 			{
   455 			{
   538 			TInt l = Min(len, (iFilePos + iLength - aFilePos));
   456 			TInt blocklen = Min(len, (iFilePos + iLength - aFilePos));
   539 			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), l);
   457 			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen);
   540 			len -= l;
   458 			len -= blocklen;
   541 			aFilePos += l;
   459 			aFilePos += blocklen;
   542 			}
   460 			}
   543 		//2. Perform a read-ahead operation
   461 		//2. Perform a read-ahead operation
   544 		else
   462 		else
   545 			{
   463 			{
   546 			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   464 			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   548 			if(err != KErrNone)
   466 			if(err != KErrNone)
   549 				{
   467 				{
   550 				break;	
   468 				break;	
   551 				}
   469 				}
   552 			if(iNextReadFilePos != aFilePos)
   470 			if(iNextReadFilePos != aFilePos)
   553 				{//Direct "file read" operation
   471 				{//Guessed read ahead was wrong. Direct "file read" operation
   554 				iNextReadFilePosHits = 0;
   472 				iNextReadFilePosHits = 0;
   555 				TPtr8 ptr2(outptr, len);
   473 				TPtr8 ptr2(outptr, len);
   556 				err = iFile.Read(aFilePos, ptr2);
   474 				err = iFile.Read(aFilePos, ptr2);
   557 				PROFILE_READ(aFilePos, ptr2.Size());
   475 				PROFILE_READ(aFilePos, ptr2.Size());
   558 				if(err == KErrNone)
   476 				if(err == KErrNone)
   802 	__FILEBUF64_INVARIANT();
   720 	__FILEBUF64_INVARIANT();
   803 	return iFile.Drive(aDriveNumber, aDriveInfo);
   721 	return iFile.Drive(aDriveNumber, aDriveInfo);
   804 	}
   722 	}
   805 
   723 
   806 /**
   724 /**
   807 Performs the fixed part of the RFileBuf64 initialization and then calls MFileInitializer64::Init() to perform
   725 Initializes RFileBuf64 data members with their initial values.   
   808 the variable part of the initialization.
   726 Allocates memory for the file buffer. 
   809 
   727  
   810 @param aFileInitializer A reference to an initializer object that implements MFileInitializer64::Init()
   728 @return KErrNone if successful, 
   811 
   729         KErrNoMemory out of memory;
   812 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   730 */
   813 */
   731 TInt RFileBuf64::DoPreInit()
   814 TInt RFileBuf64::DoInit(MFileInitializer64& aFileInitializer)
   732     {
   815 	{
   733     DoDiscard();
   816 	DoDiscard();
   734     iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
   817 	iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
   735     iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
   818 	TInt err = KErrNoMemory;
   736     return iBase ? KErrNone : KErrNoMemory; 
   819 	iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
   737     }
   820 	if(!iBase)
   738 
   821 		{
   739 /**
   822 		return KErrNoMemory;	
   740 Performs post-initialization of the RFileBuf64 object.   
   823 		}
   741 If aInitErr is not KErrNone, then the buffer memory will be released.
   824 	err = aFileInitializer.Init(iFile);
   742 The function returns the aInitErr value to the caller. 
   825 	if(err != KErrNone)
   743 
   826 		{
   744 @param aInitErr The result of the performed before the call RFileBuf64 initialization.
   827 		User::Free(iBase);
   745  
   828 		iBase = 0;
   746 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   829 		}
   747 */
   830 	return err;
   748 TInt RFileBuf64::DoPostInit(TInt aInitErr)
   831 	}
   749     {
       
   750     if(aInitErr != KErrNone)
       
   751         {
       
   752         User::Free(iBase);
       
   753         iBase = 0;
       
   754         }
       
   755     return aInitErr;
       
   756     }
   832 
   757 
   833 /**
   758 /**
   834 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
   759 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
   835 */
   760 */
   836 void RFileBuf64::DoDiscard()
   761 void RFileBuf64::DoDiscard()