persistentstorage/sql/OsLayer/FileBuf64.cpp
branchGCC_SURGE
changeset 38 c4e342fcf0c8
parent 35 0d6db0a14001
child 41 3256212fc81f
equal deleted inserted replaced
27:ba32e40d9f36 38:c4e342fcf0c8
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
    20 
    20 
    21 #ifdef _SQLPROFILER
    21 #ifdef _SQLPROFILER
    22 
    22 
    23 extern TBool TheOsCallTimeDetailedProfileEnabled;//If true, the OS porting layer call details are enabled and for each call an entry will be added to the log file (epocwind.out).
    23 extern TBool TheOsCallTimeDetailedProfileEnabled;//If true, the OS porting layer call details are enabled and for each call an entry will be added to the log file (epocwind.out).
    24 
    24 
    25 #define PROFILE_READ(pos,amount) \
    25 #define PROFILE_READ(pos, amount, err) \
    26 	do \
    26 	do \
    27 		{ \
    27 		{ \
    28 		if(TheOsCallTimeDetailedProfileEnabled) \
    28 		if(TheOsCallTimeDetailedProfileEnabled) \
    29 			{ \
    29 			{ \
    30 			++iFileReadCount; iFileReadAmount += (amount); \
    30 			++iFileReadCount; iFileReadAmount += (amount); \
    31 			RDebug::Print(_L(" -- FRead    this=%X, Cnt=%d, Pos=%ld, Amt=%d, Ttl=%ld\r\n"), (TUint32)this, iFileReadCount,  pos, amount, iFileReadAmount); \
    31 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Read¬%d¬%ld¬%d¬%ld¬%d\r\n"), (TUint32)this, iFileReadCount, pos, amount, iFileReadAmount, err); \
    32 			} \
    32 			} \
    33 		} while(0)
    33 		} while(0)
    34 	
    34 	
    35 #define PROFILE_WRITE(pos,amount) \
    35 #define PROFILE_WRITE(pos, amount, err) \
    36 	do \
    36 	do \
    37 		{ \
    37 		{ \
    38 		if(TheOsCallTimeDetailedProfileEnabled) \
    38 		if(TheOsCallTimeDetailedProfileEnabled) \
    39 			{ \
    39 			{ \
    40 			++iFileWriteCount; iFileWriteAmount += (amount); \
    40 			++iFileWriteCount; iFileWriteAmount += (amount); \
    41 			RDebug::Print(_L(" -- FWrite   this=%X, Cnt=%d, Pos=%ld, Amt=%d, Ttl=%ld\r\n"), (TUint32)this, iFileWriteCount, pos, amount, iFileWriteAmount); \
    41 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Write¬%d¬%ld¬%d¬%ld¬%d\r\n"), (TUint32)this, iFileWriteCount, pos, amount, iFileWriteAmount, err); \
    42 			} \
    42 			} \
    43 		} while(0)
    43 		} while(0)
    44 
    44 
    45 #define PROFILE_SIZE() \
    45 #define PROFILE_SIZE(size, err) \
    46 	do \
    46 	do \
    47 		{ \
    47 		{ \
    48 		if(TheOsCallTimeDetailedProfileEnabled) \
    48 		if(TheOsCallTimeDetailedProfileEnabled) \
    49 			{ \
    49 			{ \
    50 			++iFileSizeCount; \
    50 			++iFileSizeCount; \
    51 			RDebug::Print(_L(" -- FSize    this=%X, Cnt=%d\r\n"), (TUint32)this, iFileSizeCount); \
    51 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Size¬%d¬%ld¬¬¬%d\r\n"), (TUint32)this, iFileSizeCount, size, err); \
    52 			} \
    52 			} \
    53 		} while(0)
    53 		} while(0)
    54 
    54 
    55 #define PROFILE_SETSIZE() \
    55 #define PROFILE_SETSIZE(size, err) \
    56 	do \
    56 	do \
    57 		{ \
    57 		{ \
    58 		if(TheOsCallTimeDetailedProfileEnabled) \
    58 		if(TheOsCallTimeDetailedProfileEnabled) \
    59 			{ \
    59 			{ \
    60 			++iFileSetSizeCount; \
    60 			++iFileSetSizeCount; \
    61 			RDebug::Print(_L(" -- FSetSize this=%X, Cnt=%d\r\n"), (TUint32)this, iFileSetSizeCount); \
    61 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬SetSize¬%d¬%ld¬¬¬%d\r\n"), (TUint32)this, iFileSetSizeCount, size, err); \
    62 			} \
    62 			} \
    63 		} while(0)
    63 		} while(0)
    64 
    64 
    65 #define PROFILE_FLUSH()	\
    65 #define PROFILE_FLUSH(err)	\
    66 	do \
    66 	do \
    67 		{ \
    67 		{ \
    68 		if(TheOsCallTimeDetailedProfileEnabled) \
    68 		if(TheOsCallTimeDetailedProfileEnabled) \
    69 			{ \
    69 			{ \
    70 			++iFileFlushCount; \
    70 			++iFileFlushCount; \
    71 			RDebug::Print(_L(" -- FFlush   this=%X, Cnt=%d\r\n"), (TUint32)this, iFileFlushCount); \
    71 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Flush¬%d¬¬¬¬%d\r\n"), (TUint32)this, iFileFlushCount, err); \
    72 			} \
    72 			} \
    73 		} while(0)
    73 		} while(0)
    74 
    74 
       
    75 #define PROFILE_CREATE(fname, err) \
       
    76 	do \
       
    77 		{ \
       
    78 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    79 			{ \
       
    80 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Create¬¬¬¬¬%d¬%S\r\n"), (TUint32)this, err, &fname); \
       
    81 			} \
       
    82 		} while(0)
       
    83 
       
    84 #define PROFILE_OPEN(fname, err) \
       
    85 	do \
       
    86 		{ \
       
    87 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    88 			{ \
       
    89 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Open¬¬¬¬¬%d¬%S\r\n"), (TUint32)this, err, &fname); \
       
    90 			} \
       
    91 		} while(0)
       
    92 
       
    93 #define PROFILE_TEMP(fname, err) \
       
    94 	do \
       
    95 		{ \
       
    96 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    97 			{ \
       
    98 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Temp¬¬¬¬¬%d¬%S\r\n"), (TUint32)this, err, &fname); \
       
    99 			} \
       
   100 		} while(0)
       
   101 
       
   102 #define PROFILE_ADOPT(fname, err) \
       
   103 	do \
       
   104 		{ \
       
   105 		if(TheOsCallTimeDetailedProfileEnabled) \
       
   106 			{ \
       
   107 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Adopt¬¬¬¬¬%d¬%S\r\n"), (TUint32)this, err, &fname); \
       
   108 			} \
       
   109 		} while(0)
       
   110 
       
   111 #define PROFILE_CLOSE() \
       
   112 	do \
       
   113 		{ \
       
   114 		if(TheOsCallTimeDetailedProfileEnabled) \
       
   115 			{ \
       
   116 			RDebug::Print(_L("[SQL-FBUF]¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬\"%X\"¬Close¬¬¬¬¬¬\r\n"), (TUint32)this); \
       
   117 			} \
       
   118 		} while(0)
       
   119 
    75 //Resets the profiler counters
   120 //Resets the profiler counters
    76 void RFileBuf64::ProfilerReset()
   121 void RFileBuf64::ProfilerReset()
    77 	{
   122 	{
    78 	iFileReadCount = 0; iFileReadAmount = 0; iFileWriteCount = 0; iFileWriteAmount = 0; iFileSizeCount = 0; iFileSetSizeCount = 0; iFileFlushCount = 0;
   123 	iFileReadCount = 0; iFileReadAmount = 0; iFileWriteCount = 0; iFileWriteAmount = 0; iFileSizeCount = 0; iFileSetSizeCount = 0; iFileFlushCount = 0;
    79 	}
   124 	}
    80 
   125 
    81 #else
   126 #else
    82 
   127 
    83 #define PROFILE_READ(pos,amount)	void(0)
   128 #define PROFILE_READ(pos,amount, err)	void(0)
    84 #define PROFILE_WRITE(pos,amount)	void(0)
   129 #define PROFILE_WRITE(pos,amount, err)	void(0)
    85 
   130 
    86 #define PROFILE_SIZE()			void(0)
   131 #define PROFILE_SIZE(size, err)			void(0)
    87 #define PROFILE_SETSIZE()		void(0)
   132 #define PROFILE_SETSIZE(size, err)		void(0)
    88 #define PROFILE_FLUSH()			void(0)
   133 #define PROFILE_FLUSH(err)				void(0)
       
   134 
       
   135 #define PROFILE_CREATE(fname, err)		void(0)
       
   136 #define PROFILE_OPEN(fname, err)		void(0)
       
   137 #define PROFILE_TEMP(fname, err)		void(0)
       
   138 #define PROFILE_ADOPT(fname, err)		void(0)
       
   139 #define PROFILE_CLOSE()					void(0)
    89 
   140 
    90 #endif//_SQLPROFILER
   141 #endif//_SQLPROFILER
    91 
   142 
    92 /**
   143 /**
    93 This constant is used for initializing the RFileBuf64::iFileSize data member and means that
   144 This constant is used for initializing the RFileBuf64::iFileSize data member and means that
   142 	EFBufPanicNullThis,
   193 	EFBufPanicNullThis,
   143 	EFBufPanicDirty,
   194 	EFBufPanicDirty,
   144 	EFBufPanicNextReadFilePos,
   195 	EFBufPanicNextReadFilePos,
   145 	EFBufPanicNextReadFilePosHits,
   196 	EFBufPanicNextReadFilePosHits,
   146 	EFBufPanicFileBlockSize,			//15
   197 	EFBufPanicFileBlockSize,			//15
       
   198 	EFBufPanicRwDataLength,
   147 	};
   199 	};
   148 
   200 
   149 /**
   201 /**
   150 Helper function used in the implementation of the __FBUF64_ASSERT() macro.
   202 Helper function used in the implementation of the __FBUF64_ASSERT() macro.
   151 In case if the expression in __FBUF64_ASSERT() macro evaluates to false, 
   203 In case if the expression in __FBUF64_ASSERT() macro evaluates to false, 
   196 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   248 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   197 	
   249 	
   198 /**
   250 /**
   199 Initializes RFileBuf64 data members with their default values.
   251 Initializes RFileBuf64 data members with their default values.
   200 
   252 
   201 @param aSize Max file buffer size (capacity) in bytes.
   253 @param aMinCapacity Minimal file buffer size (capacity) in bytes.
   202 
   254 
   203 @panic FBuf64 1 In _DEBUG mode - aSize is 0 or negative.
   255 @panic FBuf64 1 In _DEBUG mode - aMinCapacity is 0 or negative.
   204 */
   256 */
   205 RFileBuf64::RFileBuf64(TInt aSize) :
   257 RFileBuf64::RFileBuf64(TInt aMinCapacity) :
   206 	iCapacity(aSize),
   258 	iCapacity(aMinCapacity),
   207 	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize)
   259 	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize),
   208 	{
   260 	iOptimized(EFalse)
   209 	__FBUF64_ASSERT(aSize > 0, EFBufPanicCapacity);
   261 	{
       
   262 	__FBUF64_ASSERT(aMinCapacity > 0, EFBufPanicCapacity);
   210 	}
   263 	}
   211 
   264 
   212 /**
   265 /**
   213 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
   266 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
   214 If the file already exists, an error is returned.
   267 If the file already exists, an error is returned.
   236 	TInt err = DoPreInit();
   289 	TInt err = DoPreInit();
   237 	if(err == KErrNone)
   290 	if(err == KErrNone)
   238 	    {
   291 	    {
   239 	    err = iFile.Create(aFs, aFileName, aFileMode);
   292 	    err = iFile.Create(aFs, aFileName, aFileMode);
   240 	    }
   293 	    }
       
   294 	PROFILE_CREATE(aFileName, err);
   241 	return DoPostInit(err);
   295 	return DoPostInit(err);
   242 	}
   296 	}
   243 
   297 
   244 /**
   298 /**
   245 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   299 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   267     TInt err = DoPreInit();
   321     TInt err = DoPreInit();
   268     if(err == KErrNone)
   322     if(err == KErrNone)
   269         {
   323         {
   270         err = iFile.Open(aFs, aFileName, aFileMode);
   324         err = iFile.Open(aFs, aFileName, aFileMode);
   271         }
   325         }
       
   326 	PROFILE_OPEN(aFileName, err);
   272     return DoPostInit(err);
   327     return DoPostInit(err);
   273 	}
   328 	}
   274 
   329 
   275 /**
   330 /**
   276 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   331 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   298     TInt err = DoPreInit();
   353     TInt err = DoPreInit();
   299     if(err == KErrNone)
   354     if(err == KErrNone)
   300         {
   355         {
   301         err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
   356         err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
   302         }
   357         }
       
   358 	PROFILE_TEMP(aFileName, err);
   303     return DoPostInit(err);
   359     return DoPostInit(err);
   304 	}
   360 	}
   305 
   361 
   306 /**
   362 /**
   307 Initializes the RFileBuf64 object and creates and adopts an already open file from a client that will be accessed through 
   363 Initializes the RFileBuf64 object and creates and adopts an already open file from a client that will be accessed through 
   334     TInt err = DoPreInit();
   390     TInt err = DoPreInit();
   335     if(err == KErrNone)
   391     if(err == KErrNone)
   336         {
   392         {
   337         err = iFile.AdoptFromClient(aMsg, aFsIndex, aFileIndex);
   393         err = iFile.AdoptFromClient(aMsg, aFsIndex, aFileIndex);
   338         }
   394         }
       
   395 	PROFILE_ADOPT(KNullDesC, err);
   339     return DoPostInit(err);
   396     return DoPostInit(err);
   340 	}
   397 	}
   341 
   398 
   342 /**
   399 /**
   343 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   400 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   354 		(void)DoFileWrite2();
   411 		(void)DoFileWrite2();
   355 		}
   412 		}
   356 	iFile.Close();
   413 	iFile.Close();
   357 	User::Free(iBase);
   414 	User::Free(iBase);
   358 	iBase = 0;
   415 	iBase = 0;
       
   416 	PROFILE_CLOSE();
   359 	}
   417 	}
   360 
   418 
   361 /**
   419 /**
   362 Calculates and sets optimal read-ahead buffer size.
   420 Calculates and sets optimal read-ahead buffer size.
   363 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
   421 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
   415 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
   473 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
   416 	{
   474 	{
   417 	__FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos);
   475 	__FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos);
   418 	__FILEBUF64_INVARIANT();
   476 	__FILEBUF64_INVARIANT();
   419 	aDes.SetLength(0);
   477 	aDes.SetLength(0);
   420 	//1. The output buffer max len is 0
   478 	//0. The output buffer max len is 0
   421 	if(aDes.MaxLength() == 0)
   479 	if(aDes.MaxLength() == 0)
   422 		{
   480 		{
   423 		__FILEBUF64_INVARIANT();
   481 		__FILEBUF64_INVARIANT();
   424 		return KErrNone;	
   482 		return KErrNone;	
   425 		}
   483 		}
   426 	//2. Initialize the "iFileSize" if it is not initialized yet
   484 	//1. Initialize the "iFileSize" if it is not initialized yet
   427 	TInt err = DoFileSize();
   485 	TInt err = DoFileSize();
   428 	if(err != KErrNone)
   486 	if(err != KErrNone)
   429 		{
   487 		{
   430 		__FILEBUF64_INVARIANT();
   488 		__FILEBUF64_INVARIANT();
   431 		return err;	
   489 		return err;	
   432 		}
   490 		}
       
   491 	//2. Optimize the buffer capacity
       
   492 	TInt len = aDes.MaxLength();
       
   493 	if((err = DoSetCapacity(len)) != KErrNone)
       
   494 		{
       
   495 		return err;
       
   496 		}
   433 	//3. Too big "read" request - read directly from the file
   497 	//3. Too big "read" request - read directly from the file
   434 	TInt len = aDes.MaxLength();
       
   435 	if(len > iCapacity)
   498 	if(len > iCapacity)
   436 		{
   499 		{
   437 		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
   500 		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
   438 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   501 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   439 			err = DoFileWrite1(aFilePos);
   502 			err = DoFileWrite1(aFilePos);
   440 			}
   503 			}
   441 		if(err == KErrNone)
   504 		if(err == KErrNone)
   442 			{
   505 			{
   443 			err = iFile.Read(aFilePos, aDes);
   506 			err = iFile.Read(aFilePos, aDes);
   444 			PROFILE_READ(aFilePos, aDes.Size());
   507 			PROFILE_READ(aFilePos, aDes.Size(), err);
   445 			}
   508 			}
   446 		__FILEBUF64_INVARIANT();
   509 		__FILEBUF64_INVARIANT();
   447 		return err;
   510 		return err;
   448 		}
   511 		}
   449 	//4. The requested data size is smaller than the buffer capacity
   512 	//4. The requested data size is smaller than the buffer capacity
   470 			if(iNextReadFilePos != aFilePos)
   533 			if(iNextReadFilePos != aFilePos)
   471 				{//Guessed read ahead was wrong. Direct "file read" operation
   534 				{//Guessed read ahead was wrong. Direct "file read" operation
   472 				iNextReadFilePosHits = 0;
   535 				iNextReadFilePosHits = 0;
   473 				TPtr8 ptr2(outptr, len);
   536 				TPtr8 ptr2(outptr, len);
   474 				err = iFile.Read(aFilePos, ptr2);
   537 				err = iFile.Read(aFilePos, ptr2);
   475 				PROFILE_READ(aFilePos, ptr2.Size());
   538 				PROFILE_READ(aFilePos, ptr2.Size(), err);
   476 				if(err == KErrNone)
   539 				if(err == KErrNone)
   477 					{
   540 					{
   478 					iNextReadFilePos = aFilePos + len;
   541 					iNextReadFilePos = aFilePos + len;
   479 					len -= ptr2.Length();
   542 					len -= ptr2.Length();
   480 					}
   543 					}
   481 				break;
   544 				break;
   482 				}
   545 				}
   483 			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
   546 			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
   484 			const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize
   547 			const TInt KMaxReadFilePosHits = 4;//The max read-ahead buffer size can be up to 2^4 times the iReadAheadSize
   485 			if(iNextReadFilePosHits < KMaxReadFilePosHits)
   548 			if(iNextReadFilePosHits < KMaxReadFilePosHits)
   486 				{
   549 				{
   487 				++iNextReadFilePosHits;
   550 				++iNextReadFilePosHits;
   488 				}
   551 				}
   489 			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
   552 			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
   494 				// if read-ahead doesn't cross block boundary do it all
   557 				// if read-ahead doesn't cross block boundary do it all
   495 				readahead = maxReadAhead;	
   558 				readahead = maxReadAhead;	
   496 				}
   559 				}
   497 			TPtr8 ptr(iBase, Min(iCapacity, (len + readahead)));
   560 			TPtr8 ptr(iBase, Min(iCapacity, (len + readahead)));
   498 			err = iFile.Read(aFilePos, ptr);
   561 			err = iFile.Read(aFilePos, ptr);
   499 			PROFILE_READ(aFilePos, ptr.Size());
   562 			PROFILE_READ(aFilePos, ptr.Size(), err);
   500 			if(err == KErrNone)
   563 			if(err == KErrNone)
   501 				{
   564 				{
   502 				iFilePos = aFilePos;
   565 				iFilePos = aFilePos;
   503 				iLength = ptr.Length();	
   566 				iLength = ptr.Length();	
   504 				iNextReadFilePos = iFilePos + iLength;
   567 				iNextReadFilePos = iFilePos + iLength;
   549 	TInt err = DoFileSize();
   612 	TInt err = DoFileSize();
   550 	if(err != KErrNone)
   613 	if(err != KErrNone)
   551 		{
   614 		{
   552 		__FILEBUF64_INVARIANT();
   615 		__FILEBUF64_INVARIANT();
   553 		return err;	
   616 		return err;	
       
   617 		}
       
   618 	if((err = DoSetCapacity(aData.Length())) != KErrNone)
       
   619 		{
       
   620 		return err;
   554 		}
   621 		}
   555 	DoDiscardBufferedReadData();
   622 	DoDiscardBufferedReadData();
   556 	const TUint8* data = aData.Ptr();
   623 	const TUint8* data = aData.Ptr();
   557 	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
   624 	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
   558 		{
   625 		{
   785 	if(iFileSize != KFileSizeNotSet)
   852 	if(iFileSize != KFileSizeNotSet)
   786 		{
   853 		{
   787 		__FILEBUF64_INVARIANT();
   854 		__FILEBUF64_INVARIANT();
   788 		return KErrNone;
   855 		return KErrNone;
   789 		}
   856 		}
   790 	PROFILE_SIZE();
       
   791 	TInt err = iFile.Size(iFileSize);
   857 	TInt err = iFile.Size(iFileSize);
       
   858 	PROFILE_SIZE(iFileSize, err);
   792 	if(err != KErrNone)
   859 	if(err != KErrNone)
   793 		{
   860 		{
   794 		DoDiscard();
   861 		DoDiscard();
   795 		}
   862 		}
   796 	__FILEBUF64_INVARIANT();
   863 	__FILEBUF64_INVARIANT();
   823 	//If the new file size is "in" the buffer then change the "iLength"
   890 	//If the new file size is "in" the buffer then change the "iLength"
   824 	else if(aFileSize < (iFilePos + iLength))
   891 	else if(aFileSize < (iFilePos + iLength))
   825 		{
   892 		{
   826 		iLength = aFileSize - iFilePos;
   893 		iLength = aFileSize - iFilePos;
   827 		}
   894 		}
   828 	PROFILE_SETSIZE();
       
   829 	TInt err = iFile.SetSize(aFileSize);
   895 	TInt err = iFile.SetSize(aFileSize);
       
   896 	PROFILE_SETSIZE(aFileSize, err);
   830 	if(err != KErrNone)
   897 	if(err != KErrNone)
   831 		{
   898 		{
   832 		DoDiscard();
   899 		DoDiscard();
   833 		}
   900 		}
   834 	else
   901 	else
   855 	if(err != KErrNone)
   922 	if(err != KErrNone)
   856 		{
   923 		{
   857 		__FILEBUF64_INVARIANT();
   924 		__FILEBUF64_INVARIANT();
   858 		return err;	
   925 		return err;	
   859 		}
   926 		}
   860 	PROFILE_FLUSH();
       
   861 	err = iFile.Flush();
   927 	err = iFile.Flush();
       
   928 	PROFILE_FLUSH(err);
   862 	if(err != KErrNone)
   929 	if(err != KErrNone)
   863 		{
   930 		{
   864 		DoDiscard();
   931 		DoDiscard();
   865 		}
   932 		}
   866 	iLength = 0;
   933 	iLength = 0;
   887 	if(iLength == 0)
   954 	if(iLength == 0)
   888 		{
   955 		{
   889 		__FILEBUF64_INVARIANT();
   956 		__FILEBUF64_INVARIANT();
   890 		return KErrNone;	
   957 		return KErrNone;	
   891 		}
   958 		}
   892 	PROFILE_WRITE(iFilePos, iLength);
       
   893 	TPtrC8 data(iBase, iLength);		
   959 	TPtrC8 data(iBase, iLength);		
   894 	TInt err = iFile.Write(iFilePos, data);
   960 	TInt err = iFile.Write(iFilePos, data);
       
   961 	PROFILE_WRITE(iFilePos, iLength, err);
   895 	if(err == KErrNone)
   962 	if(err == KErrNone)
   896 		{
   963 		{
   897 		iFileSize = Max(iFileSize, (iFilePos + iLength));
   964 		iFileSize = Max(iFileSize, (iFilePos + iLength));
   898 		}
   965 		}
   899 	else
   966 	else
  1020 		iNextReadFilePosHits = 0;
  1087 		iNextReadFilePosHits = 0;
  1021 		}
  1088 		}
  1022 	__FILEBUF64_INVARIANT();
  1089 	__FILEBUF64_INVARIANT();
  1023 	}
  1090 	}
  1024 
  1091 
       
  1092 /**
       
  1093 Sets the most appropriate buffer capacity based on the database page size.
       
  1094 The function does a lazy evaluation. The first time the function is called and 
       
  1095 aRwDataLength parameter is recognized to be a database or journal page size, the new (optimal)
       
  1096 buffer capacity is calculated and set. All next DoSetCapacity() calls will detect that the new
       
  1097 capacity is already set and will return KErrNone.
       
  1098 
       
  1099 @param  aRwDataLength The length of the data being read or written.
       
  1100 @return KErrNone The new capacity was set successfully,
       
  1101         KErrNoMemory Out of memory.
       
  1102 */
       
  1103 TInt RFileBuf64::DoSetCapacity(TInt aRwDataLength)
       
  1104 	{
       
  1105 	const TInt KMinPageCount = 4;//the buffer capacity should be at least (KMinPageCount * page size) 
       
  1106 	                             //but not less than the original capacity.
       
  1107 	const TInt KDefaultPageSize = 1024;//The journal header size is equal to 512 bytes, so it is not easy
       
  1108                                        //to detect the 512 bytes page size. 
       
  1109 	
       
  1110 	__FBUF64_ASSERT(aRwDataLength > 0, EFBufPanicRwDataLength);
       
  1111 	__FILEBUF64_INVARIANT();
       
  1112 	if(iOptimized)
       
  1113 		{
       
  1114 		__FILEBUF64_INVARIANT();
       
  1115 		return KErrNone;
       
  1116 		}
       
  1117 	if((aRwDataLength & (aRwDataLength - 1)) != 0 || aRwDataLength < KDefaultPageSize)
       
  1118 		{
       
  1119 		__FILEBUF64_INVARIANT();
       
  1120 		return KErrNone;
       
  1121 		}
       
  1122 	//Here: aRwDataLength is power of 2 and is bigger than the default db page size.
       
  1123 	//aRwDataLength is the size of the db page.
       
  1124 	const TInt pageSize = aRwDataLength;
       
  1125 	TInt cnt = iCapacity / pageSize;//how many pages can fit in the buffer now
       
  1126 	TInt pageCount = Max(cnt, KMinPageCount);//the number of pages that should fit in the new buffer
       
  1127 	TInt newBufCapacity = pageCount * pageSize;
       
  1128 	if(newBufCapacity != iCapacity)
       
  1129 		{
       
  1130 		TUint8* newBase = static_cast <TUint8*> (User::ReAlloc(iBase, newBufCapacity));
       
  1131 		if(!newBase)
       
  1132 			{
       
  1133 			__FILEBUF64_INVARIANT();
       
  1134 			return KErrNoMemory;
       
  1135 			}
       
  1136 		iBase = newBase;
       
  1137 		iCapacity = newBufCapacity;
       
  1138 		//Adjust the initial read-ahead size to be multiple of the page size.
       
  1139 		if((iReadAheadSize % pageSize) != 0)
       
  1140 			{
       
  1141 			TInt q = iReadAheadSize / pageSize;
       
  1142 			iReadAheadSize = q != 0 ? pageSize * q : pageSize;
       
  1143 			}
       
  1144 		}
       
  1145 	iOptimized = ETrue;
       
  1146 	__FILEBUF64_INVARIANT();
       
  1147 	return KErrNone;
       
  1148 	}
       
  1149 
  1025 #ifdef _DEBUG
  1150 #ifdef _DEBUG
  1026 
  1151 
  1027 /**
  1152 /**
  1028 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
  1153 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
  1029 (except the init/destroy methods).
  1154 (except the init/destroy methods).
  1035 @panic FBuf64   4 In _DEBUG mode - negative iFilePos value.
  1160 @panic FBuf64   4 In _DEBUG mode - negative iFilePos value.
  1036 @panic FBuf64   5 In _DEBUG mode - set but negative iFileSize value.
  1161 @panic FBuf64   5 In _DEBUG mode - set but negative iFileSize value.
  1037 @panic FBuf64   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
  1162 @panic FBuf64   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
  1038 @panic FBuf64  13 In _DEBUG mode - set but negative iNextReadFilePos value.
  1163 @panic FBuf64  13 In _DEBUG mode - set but negative iNextReadFilePos value.
  1039 @panic FBuf64  14 In _DEBUG mode - negative iNextReadFilePosHits value.
  1164 @panic FBuf64  14 In _DEBUG mode - negative iNextReadFilePosHits value.
  1040 @panic FBuf64  15 In _DEBUG mode - iReadAheadSize is negative or is not power of two.
  1165 @panic FBuf64  15 In _DEBUG mode - iReadAheadSize is negative or is bigger than iCapacity.
  1041 */
  1166 */
  1042 void RFileBuf64::Invariant() const
  1167 void RFileBuf64::Invariant() const
  1043 	{
  1168 	{
  1044 	__FBUF64_ASSERT(this != 0, EFBufPanicNullThis);
  1169 	__FBUF64_ASSERT(this != 0, EFBufPanicNullThis);
  1045 	__FBUF64_ASSERT(iCapacity > 0, EFBufPanicCapacity);
  1170 	__FBUF64_ASSERT(iCapacity > 0, EFBufPanicCapacity);
  1048 	__FBUF64_ASSERT(iFilePos >= 0, EFBufPanicFilePos);
  1173 	__FBUF64_ASSERT(iFilePos >= 0, EFBufPanicFilePos);
  1049 	__FBUF64_ASSERT(iFileSize == KFileSizeNotSet || iFileSize >= 0, EFBufPanicFileSize);
  1174 	__FBUF64_ASSERT(iFileSize == KFileSizeNotSet || iFileSize >= 0, EFBufPanicFileSize);
  1050 	__FBUF64_ASSERT(iFile.SubSessionHandle() != 0, EFBufPanicFileHandle);
  1175 	__FBUF64_ASSERT(iFile.SubSessionHandle() != 0, EFBufPanicFileHandle);
  1051 	__FBUF64_ASSERT(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, EFBufPanicNextReadFilePos);
  1176 	__FBUF64_ASSERT(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, EFBufPanicNextReadFilePos);
  1052 	__FBUF64_ASSERT(iNextReadFilePosHits >= 0, EFBufPanicNextReadFilePosHits);
  1177 	__FBUF64_ASSERT(iNextReadFilePosHits >= 0, EFBufPanicNextReadFilePosHits);
  1053 	__FBUF64_ASSERT(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, EFBufPanicFileBlockSize);
  1178 	__FBUF64_ASSERT(iReadAheadSize > 0, EFBufPanicFileBlockSize);
  1054 	}
  1179 	}
  1055 	
  1180 	
  1056 #endif
  1181 #endif