persistentstorage/sqlite3api/OsLayer/FileBuf64.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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 "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 //
       
    15 #include "FileBuf64.h"
       
    16 
       
    17 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    18 ///////////////////////////        PROFILER       ////////////////////////////////////////////////////////////////////
       
    19 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    20 
       
    21 #ifdef _SQLPROFILER
       
    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).
       
    24 
       
    25 #define PROFILE_READ(pos,amount) \
       
    26 	do \
       
    27 		{ \
       
    28 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    29 			{ \
       
    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); \
       
    32 			} \
       
    33 		} while(0)
       
    34 	
       
    35 #define PROFILE_WRITE(pos,amount) \
       
    36 	do \
       
    37 		{ \
       
    38 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    39 			{ \
       
    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); \
       
    42 			} \
       
    43 		} while(0)
       
    44 
       
    45 #define PROFILE_SIZE() \
       
    46 	do \
       
    47 		{ \
       
    48 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    49 			{ \
       
    50 			++iFileSizeCount; \
       
    51 			RDebug::Print(_L(" -- FSize    this=%X, Cnt=%d\r\n"), (TUint32)this, iFileSizeCount); \
       
    52 			} \
       
    53 		} while(0)
       
    54 
       
    55 #define PROFILE_SETSIZE() \
       
    56 	do \
       
    57 		{ \
       
    58 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    59 			{ \
       
    60 			++iFileSetSizeCount; \
       
    61 			RDebug::Print(_L(" -- FSetSize this=%X, Cnt=%d\r\n"), (TUint32)this, iFileSetSizeCount); \
       
    62 			} \
       
    63 		} while(0)
       
    64 
       
    65 #define PROFILE_FLUSH()	\
       
    66 	do \
       
    67 		{ \
       
    68 		if(TheOsCallTimeDetailedProfileEnabled) \
       
    69 			{ \
       
    70 			++iFileFlushCount; \
       
    71 			RDebug::Print(_L(" -- FFlush   this=%X, Cnt=%d\r\n"), (TUint32)this, iFileFlushCount); \
       
    72 			} \
       
    73 		} while(0)
       
    74 
       
    75 #else
       
    76 
       
    77 #define PROFILE_READ(pos,amount)	void(0)
       
    78 #define PROFILE_WRITE(pos,amount)	void(0)
       
    79 
       
    80 #define PROFILE_SIZE()			void(0)
       
    81 #define PROFILE_SETSIZE()		void(0)
       
    82 #define PROFILE_FLUSH()			void(0)
       
    83 
       
    84 #endif//_SQLPROFILER
       
    85 
       
    86 /**
       
    87 This constant is used for initializing the RFileBuf64::iFileSize data member and means that
       
    88 the iFileSize is not yet initialized with the real file size value. 
       
    89 (RFileBuf64::iFileSize caches the file size value)
       
    90 @internalComponent
       
    91 */
       
    92 static const TInt KFileSizeNotSet = -1;
       
    93 
       
    94 /**
       
    95 This constant is used as a default initializer for the RFileBuf64::iNextReadFilePos data member,
       
    96 indicating that the "guessed" file read offset is invalid and should not be used.
       
    97 @internalComponent
       
    98 */
       
    99 static const TInt KNextReadFilePosNotSet = -1;
       
   100 
       
   101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   102 ///////////////////////////        ASSERTS & INVARIANT      //////////////////////////////////////////////////////////
       
   103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   104 
       
   105 #ifdef _DEBUG
       
   106 
       
   107 #define __FILEBUF64_INVARIANT() Invariant()
       
   108 
       
   109 /**
       
   110 String literal used in _DEBUG mode for indicating that the reported panic happened inside the RFileBuf64 implementation.
       
   111 
       
   112 @see TFileBufPanic64
       
   113 @internalComponent
       
   114 */
       
   115 _LIT(KPanicCategory, "FBuf64");
       
   116 
       
   117 /**
       
   118 Set of numeric constants used together with the KPanicCategory string literal in _DEBUG mode for providing more detailed
       
   119 information about the reason of the panic.
       
   120 
       
   121 @see KPanicCategory
       
   122 @internalComponent
       
   123 */
       
   124 enum TFileBufPanic64
       
   125 	{
       
   126 	EFBufPanicCapacity = 1,				//1
       
   127 	EFBufPanicNullBuf,
       
   128 	EFBufPanicBufLen,
       
   129 	EFBufPanicFilePos,
       
   130 	EFBufPanicFileSize,					//5
       
   131 	EFBufPanicFileHandle,
       
   132 	EFBufPanicFsHandle,
       
   133 	EFBufPanicMsgHandle,
       
   134 	EFBufPanicMsgIndex,
       
   135 	EFBufPanicFileNameLen,				//10
       
   136 	EFBufPanicNullThis,
       
   137 	EFBufPanicDirty,
       
   138 	EFBufPanicNextReadFilePos,
       
   139 	EFBufPanicNextReadFilePosHits,
       
   140 	EFBufPanicFileBlockSize,			//15
       
   141 	};
       
   142 
       
   143 /**
       
   144 Helper function used in the implementation of the __FBUF64_ASSERT() macro.
       
   145 In case if the expression in __FBUF64_ASSERT() macro evaluates to false, 
       
   146 PanicFileBuf64() will use the supplied aLine and aPanicCode arguments together with the KPanicCategory string literal
       
   147 to prepare and print out a line (including the time of the panic) to the default log. The calling thread will be panic'ed
       
   148 after that.
       
   149 
       
   150 @see TFileBufPanic64
       
   151 @see KPanicCategory
       
   152 @internalComponent
       
   153 */
       
   154 static void PanicFileBuf64(TInt aLine, TFileBufPanic64 aPanicCode)
       
   155 	{
       
   156 	TTime time;
       
   157 	time.HomeTime();
       
   158 	TDateTime dt = time.DateTime();
       
   159 	TBuf<16> tbuf;
       
   160 	tbuf.Format(_L("%02d:%02d:%02d.%06d"), dt.Hour(), dt.Minute(), dt.Second(), dt.MicroSecond());
       
   161 	
       
   162 	TBuf<64> buf;
       
   163 	_LIT(KFormat,"**%S:RFileBuf64 panic %d, at line(%d)");
       
   164 	buf.Format(KFormat, &tbuf, aPanicCode, aLine);
       
   165 	RDebug::Print(buf);
       
   166 	User::Panic(KPanicCategory, aPanicCode);
       
   167 	}
       
   168 
       
   169 /**
       
   170 This macro should be used when there is a need to panic the client/server if "expr" condition is not satisfied.
       
   171 Works in only in debug mode. In release mode evaluates to nothing.
       
   172 
       
   173 @see TFileBufPanic64
       
   174 @see KPanicCategory
       
   175 @see PanicFileBuf64()
       
   176 @internalComponent
       
   177 */
       
   178 #define __FBUF64_ASSERT(expr, panicCode)	(void)(!(expr) ? ::PanicFileBuf64(__LINE__, panicCode) : void(0))
       
   179 
       
   180 #else //_DEBUG
       
   181 
       
   182 #define __FILEBUF64_INVARIANT() void(0)
       
   183 
       
   184 #define __FBUF64_ASSERT(expr, panicCode) 	void(0)
       
   185 
       
   186 #endif//_DEBUG
       
   187 
       
   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    /////////////////////////////////////////////////////////////////////
       
   228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   229 	
       
   230 /**
       
   231 Initializes RFileBuf64 data members with their default values.
       
   232 
       
   233 @param aSize Max file buffer size (capacity) in bytes.
       
   234 
       
   235 @panic FBuf64 1 In _DEBUG mode - aSize is 0 or negative.
       
   236 */
       
   237 RFileBuf64::RFileBuf64(TInt aSize) :
       
   238 	iCapacity(aSize),
       
   239 	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize)
       
   240 	{
       
   241 	__FBUF64_ASSERT(aSize > 0, EFBufPanicCapacity);
       
   242 	}
       
   243 
       
   244 /**
       
   245 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
       
   246 If the file already exists, an error is returned.
       
   247 If the resulting path does not exist, then the operation cannot proceed and the function returns an error code.
       
   248 
       
   249 @param aFs       The file server session.
       
   250 @param aFileName The name of the file. Any path components (i.e. drive letter
       
   251                  or directory), which are not specified, are taken from
       
   252                  the session path.
       
   253 @param aFileMode The mode in which the file is opened. See TFileMode for details.
       
   254 
       
   255 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   256 
       
   257 @see TFileMode
       
   258 @see RFile64::Create()
       
   259 @see MFileInitializer64
       
   260 
       
   261 @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).
       
   263 */
       
   264 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
       
   265 	{
       
   266 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
       
   267 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
       
   268 	
       
   269 	struct TFileCreateInitializer64 : public MFileInitializer64
       
   270 		{
       
   271 		inline TFileCreateInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) :
       
   272 			iFs(aFs),
       
   273 			iFileName(aFileName),
       
   274 			iFileMode(aFileMode)
       
   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 	}
       
   288 
       
   289 /**
       
   290 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.
       
   292 
       
   293 @param aFs       The file server session.
       
   294 @param aFileName The name of the file. Any path components (i.e. drive letter
       
   295                  or directory), which are not specified, are taken from
       
   296                  the session path.
       
   297 @param aFileMode The mode in which the file is opened. See TFileMode for details.
       
   298 
       
   299 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   300 
       
   301 @see TFileMode
       
   302 @see RFile64::Open()
       
   303 @see MFileInitializer64
       
   304 
       
   305 @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).
       
   307 */
       
   308 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
       
   309 	{
       
   310 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
       
   311 	__FBUF64_ASSERT(aFileName.Length() > 0, EFBufPanicFileNameLen);
       
   312 	
       
   313 	struct TFileOpenInitializer64 : public MFileInitializer64
       
   314 		{
       
   315 		inline TFileOpenInitializer64(RFs& aFs, const TDesC& aFileName, TUint aFileMode) :
       
   316 			iFs(aFs),
       
   317 			iFileName(aFileName),
       
   318 			iFileMode(aFileMode)
       
   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 	}
       
   332 
       
   333 /**
       
   334 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
       
   335 RFileBuf64 public interface.
       
   336 
       
   337 @param aFs       The file server session.
       
   338 @param aPath     The directory in which the file is created.
       
   339 @param aFileName On return, contains the full path and file name of the file.
       
   340                  The filename is guaranteed to be unique within the directory
       
   341                  specified by aPath.
       
   342 @param aFileMode The mode in which the file is opened. The access mode is
       
   343                  automatically set to EFileWrite. See TFileMode for details.
       
   344 
       
   345 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   346 
       
   347 @see TFileMode
       
   348 @see RFile64::Temp()
       
   349 @see MFileInitializer64
       
   350 
       
   351 @panic FBuf64  7 In _DEBUG mode - Invalid aFs object (null file session handle).
       
   352 */
       
   353 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
       
   354 	{
       
   355 	__FBUF64_ASSERT(aFs.Handle() != 0, EFBufPanicFsHandle);
       
   356 	
       
   357 	struct TFileTempInitializer64 : public MFileInitializer64
       
   358 		{
       
   359 		inline TFileTempInitializer64(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode) :
       
   360 			iFs(aFs),
       
   361 			iPath(aPath),
       
   362 			iFileName(aFileName),
       
   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 	}
       
   378 
       
   379 /**
       
   380 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
       
   381 the RFileBuf64 resources. 
       
   382 RFileBuf64::Flush() should be called before RFileBuf64::Close() to ensure that if there are pending data, they will
       
   383 be written to the file and if the operation fails, the caller will be notified with an appropriate return error.
       
   384 
       
   385 @see RFileBuf64::Flush()
       
   386 */
       
   387 void RFileBuf64::Close()
       
   388 	{
       
   389 	if(iFile.SubSessionHandle() != 0 && iBase != 0)
       
   390 		{
       
   391 		(void)DoFileWrite2();
       
   392 		}
       
   393 	iFile.Close();
       
   394 	User::Free(iBase);
       
   395 	iBase = 0;
       
   396 	}
       
   397 
       
   398 /**
       
   399 Calculates and sets optimal read-ahead buffer size.
       
   400 
       
   401 @param aBlockSize The size of a file block in bytes
       
   402 @param aReadRecBufSize The recommended buffer size for optimised reading performance
       
   403 
       
   404 @return The new read-ahead value
       
   405 
       
   406 @see TVolumeIOParamInfo
       
   407 */
       
   408 TInt RFileBuf64::SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize)
       
   409 	{
       
   410 	__FILEBUF64_INVARIANT();
       
   411 	if(aReadRecBufSize > 0 && (aReadRecBufSize & (aReadRecBufSize - 1)) == 0 && aReadRecBufSize > RFileBuf64::KDefaultReadAheadSize)
       
   412 		{
       
   413 		iReadAheadSize = aReadRecBufSize > iCapacity ? iCapacity : aReadRecBufSize;
       
   414 		}
       
   415 	else if(aBlockSize > 0 && (aBlockSize & (aBlockSize - 1)) == 0 && aBlockSize > RFileBuf64::KDefaultReadAheadSize)
       
   416 		{
       
   417 		iReadAheadSize = aBlockSize > iCapacity ? iCapacity : aBlockSize;
       
   418 		}
       
   419 	__FILEBUF64_INVARIANT();
       
   420 	return iReadAheadSize;
       
   421 	}
       
   422 
       
   423 /**
       
   424 Reads from the file at the specified position (aFilePos).
       
   425 If the data to be read is in the buffer, then the data will be taken from the buffer.
       
   426 
       
   427 @param aFilePos Position of first byte to be read.  This is an offset from
       
   428             the start of the file. 
       
   429             If aPos is beyond the end of the file, the function returns
       
   430             a zero length descriptor.
       
   431 @param aDes Descriptor into which binary data is read. Any existing contents 
       
   432             are overwritten. On return, its length is set to the number of
       
   433             bytes read.
       
   434             
       
   435 @return KErrNone if successful, otherwise one of the other system-wide error  codes.
       
   436 
       
   437 @panic FBuf64  4 In _DEBUG mode - negative aFilePos value.
       
   438 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
   439 
       
   440 @see RFileBuf64::Invariant()
       
   441 */
       
   442 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
       
   443 	{
       
   444 	__FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos);
       
   445 	__FILEBUF64_INVARIANT();
       
   446 	aDes.SetLength(0);
       
   447 	//1. The output buffer max len is 0
       
   448 	if(aDes.MaxLength() == 0)
       
   449 		{
       
   450 		__FILEBUF64_INVARIANT();
       
   451 		return KErrNone;	
       
   452 		}
       
   453 	//2. Initialize the "iFileSize" if it is not initialized yet
       
   454 	TInt err = DoFileSize();
       
   455 	if(err != KErrNone)
       
   456 		{
       
   457 		__FILEBUF64_INVARIANT();
       
   458 		return err;	
       
   459 		}
       
   460 	//3. Too big "read" request - read directly from the file
       
   461 	TInt len = aDes.MaxLength();
       
   462 	if(len > iCapacity)
       
   463 		{
       
   464 		if((aFilePos + len) > iFilePos && !(aFilePos >= (iFilePos + iLength)))
       
   465 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
       
   466 			err = DoFileWrite1(aFilePos);
       
   467 			}
       
   468 		if(err == KErrNone)
       
   469 			{
       
   470 			err = iFile.Read(aFilePos, aDes);
       
   471 			PROFILE_READ(aFilePos, aDes.Size());
       
   472 			}
       
   473 		__FILEBUF64_INVARIANT();
       
   474 		return err;
       
   475 		}
       
   476 	//4. The requested data size is smaller than the buffer capacity
       
   477 	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
       
   478 	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
       
   479 		{
       
   480 		//1. If part of all of the data is in the buffer - copy the data to the target location
       
   481 		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
       
   482 			{
       
   483 			TInt l = Min(len, (iFilePos + iLength - aFilePos));
       
   484 			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), l);
       
   485 			len -= l;
       
   486 			aFilePos += l;
       
   487 			}
       
   488 		//2. Perform a read-ahead operation
       
   489 		else
       
   490 			{
       
   491 			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
       
   492 			err = DoFileWrite1(aFilePos);
       
   493 			if(err != KErrNone)
       
   494 				{
       
   495 				break;	
       
   496 				}
       
   497 			if(iNextReadFilePos != aFilePos)
       
   498 				{//Direct "file read" operation
       
   499 				iNextReadFilePosHits = 0;
       
   500 				TPtr8 ptr2(outptr, len);
       
   501 				err = iFile.Read(aFilePos, ptr2);
       
   502 				PROFILE_READ(aFilePos, ptr2.Size());
       
   503 				if(err == KErrNone)
       
   504 					{
       
   505 					iNextReadFilePos = aFilePos + len;
       
   506 					len -= ptr2.Length();
       
   507 					}
       
   508 				break;
       
   509 				}
       
   510 			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
       
   511 			const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize
       
   512 			if(iNextReadFilePosHits < KMaxReadFilePosHits)
       
   513 				{
       
   514 				++iNextReadFilePosHits;
       
   515 				}
       
   516 			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
       
   517 			TInt align = (aFilePos + len + maxReadAhead) & (iReadAheadSize - 1);
       
   518 			TInt readahead = maxReadAhead - align;
       
   519 			if(readahead < 0)
       
   520 				{
       
   521 				// if read-ahead doesn't cross block boundary do it all
       
   522 				readahead = maxReadAhead;	
       
   523 				}
       
   524 			TPtr8 ptr(iBase, Min(iCapacity, (len + readahead)));
       
   525 			err = iFile.Read(aFilePos, ptr);
       
   526 			PROFILE_READ(aFilePos, ptr.Size());
       
   527 			if(err == KErrNone)
       
   528 				{
       
   529 				iFilePos = aFilePos;
       
   530 				iLength = ptr.Length();	
       
   531 				iNextReadFilePos = iFilePos + iLength;
       
   532 				if(iLength == 0)
       
   533 					{
       
   534 					break;	
       
   535 					}
       
   536 				}
       
   537 			else
       
   538 				{
       
   539 				DoDiscard();	
       
   540 				}
       
   541 			}
       
   542 		}
       
   543 	aDes.SetLength(aDes.MaxLength() - len);
       
   544 	__FILEBUF64_INVARIANT();
       
   545 	return err;
       
   546 	}
       
   547 	
       
   548 /**
       
   549 Writes to the file at the specified offset (aFilePos) within the file.
       
   550 If certain conditions are met, the data will be stored in the buffer - no call to the file server.
       
   551 
       
   552 @param aFilePos The offset from the start of the file at which the first byte is written. 
       
   553                 If a position beyond the end of the file is specified, then
       
   554                 the write operation begins at the end of the file.
       
   555                 If the position has been locked, then the write fails.
       
   556             
       
   557 @param aData The descriptor from which binary data is written. The function writes 
       
   558              the entire contents of aData to the file.
       
   559 
       
   560 @return KErrNone if successful, otherwise one of the other system-wide error  codes.
       
   561 
       
   562 @panic FBuf64  4 In _DEBUG mode - negative aFilePos value.
       
   563 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
   564 
       
   565 @see RFileBuf64::Invariant()
       
   566 */
       
   567 TInt RFileBuf64::Write(TInt64 aFilePos, const TDesC8& aData)
       
   568 	{
       
   569 	__FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos);
       
   570 	__FILEBUF64_INVARIANT();
       
   571 	if(aData.Length() == 0)
       
   572 		{
       
   573 		__FILEBUF64_INVARIANT();
       
   574 		return KErrNone;	
       
   575 		}
       
   576 	TInt err = DoFileSize();
       
   577 	if(err != KErrNone)
       
   578 		{
       
   579 		__FILEBUF64_INVARIANT();
       
   580 		return err;	
       
   581 		}
       
   582 	DoDiscardBufferedReadData();
       
   583 	const TUint8* data = aData.Ptr();
       
   584 	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
       
   585 		{
       
   586 		//1. The new write pos is before the buffered file pos
       
   587 		if(aFilePos < iFilePos)
       
   588 			{
       
   589 			//If the new data sticks to/overlapps the old data and there is room in the buffer to move the old data 
       
   590 			//toward the end, then the new data can be copied at the beginning of the buffer.
       
   591 			if((aFilePos + len) >= iFilePos && (iFilePos - aFilePos) <= (iCapacity - iLength))
       
   592 				{
       
   593 				(void)Mem::Copy(iBase + (iFilePos - aFilePos), iBase, iLength);	//Make room - move the existing data toward the end
       
   594 				(void)Mem::Copy(iBase, data, len);								//of the buffer. Stick the new data to the old data
       
   595 				iLength += (iFilePos - aFilePos);
       
   596 				iFilePos = aFilePos;										//The new file pos is associated with the buffer
       
   597 				iFileSize = Max(iFileSize, (iFilePos + iLength));
       
   598 				len = 0;													//No more new data
       
   599 				iDirty = ETrue;	
       
   600 				}
       
   601 			else
       
   602 			//The "aFilePos" is too far before the "iFilePos". Write the buffer and associate the new pos with the buffer
       
   603 				{
       
   604 				err = DoFileWrite2(aFilePos);
       
   605 				}
       
   606 			}
       
   607 		//2. The new write pos is after the associated file pos + the data length.
       
   608 		else if(aFilePos > (iFilePos + iLength))
       
   609 			{
       
   610 			if(aFilePos > iFileSize)											//Beyond the end of the file
       
   611 				{
       
   612 				if((iFilePos + iLength) == iFileSize && (aFilePos - iFilePos) < iCapacity)	
       
   613 					{															//but within the buffer => extend the file with zeros.
       
   614 					Mem::FillZ(iBase + iLength, aFilePos - iFilePos - iLength);
       
   615 					iLength = aFilePos - iFilePos;
       
   616 					iFileSize = Max(iFileSize, (iFilePos + iLength));
       
   617 					iDirty = ETrue;	
       
   618 					}
       
   619 				else									
       
   620 				//Beyond the end of the file and not in the buffer - set file size.
       
   621 					{
       
   622 					err = DoSetFileSize(aFilePos);
       
   623 					}
       
   624 				}
       
   625 			else										
       
   626 			//Within the file, not in the buffer - write the buffer and associate the new file pos with the buffer
       
   627 				{
       
   628 				err = DoFileWrite2(aFilePos);
       
   629 				}
       
   630 			}
       
   631 		//3. The new write pos is in the buffer, but the data length is too big
       
   632 		//   (For SQLite is OK, otherwise the whole block must be written to the file)
       
   633 		//4. The new write pos is in the buffer, the data entirely fits in the buffer
       
   634 		else
       
   635 			{
       
   636 			if(iCapacity == iLength)			//The buffer is full. Write the buffer and associate the new file pos
       
   637 				{
       
   638 				err = DoFileWrite2(aFilePos);
       
   639 				}
       
   640 			if(err == KErrNone)
       
   641 				{
       
   642 				TInt amount = Min(len, (iCapacity - (aFilePos - iFilePos)));
       
   643 				const TUint8* end = Mem::Copy(iBase + (aFilePos - iFilePos), data, amount);
       
   644 				iLength = Max(iLength, (end - iBase));
       
   645 				iFileSize = Max(iFileSize, (iFilePos + iLength));
       
   646 				len -= amount;
       
   647 				data += amount;
       
   648 				aFilePos += amount;
       
   649 				iDirty = ETrue;	
       
   650 				}
       
   651 			}
       
   652 		}
       
   653 	__FILEBUF64_INVARIANT();
       
   654 	return err;
       
   655 	}
       
   656 	
       
   657 /**
       
   658 Gets the current file size.
       
   659 
       
   660 @param aFileSize On return, the size of the file in bytes.
       
   661 
       
   662 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   663 
       
   664 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
       
   665 
       
   666 @see RFileBuf64::Invariant()
       
   667 */
       
   668 TInt RFileBuf64::Size(TInt64& aFileSize)
       
   669 	{
       
   670 	__FILEBUF64_INVARIANT();
       
   671 	TInt err = DoFileSize();
       
   672 	if(err == KErrNone)
       
   673 		{
       
   674 		aFileSize = iFileSize;
       
   675 		}
       
   676 	__FILEBUF64_INVARIANT();
       
   677 	return err;
       
   678 	}
       
   679 
       
   680 /**
       
   681 Sets the file size.
       
   682 
       
   683 If the size of the file is reduced, data may be lost from the end of the file.
       
   684 
       
   685 Note:
       
   686 
       
   687 1. The current file position remains unchanged unless SetSize() reduces the size 
       
   688    of the file in such a way that the current file position is now beyond
       
   689    the end of the file. In this case, the current file position is set to
       
   690    the end of file. 
       
   691 
       
   692 2. If the file was not opened for writing, an error is returned.
       
   693 
       
   694 @param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
       
   695 
       
   696 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   697 
       
   698 @panic FBuf64  5 In _DEBUG mode - negative aFileSize value.
       
   699 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
   700 
       
   701 @see RFileBuf64::Invariant()
       
   702 */
       
   703 TInt RFileBuf64::SetSize(TInt64 aFileSize)
       
   704 	{
       
   705 	__FBUF64_ASSERT(aFileSize >= 0, EFBufPanicFileSize);
       
   706 	__FILEBUF64_INVARIANT();
       
   707 	return DoSetFileSize(aFileSize);
       
   708 	}
       
   709 
       
   710 /**
       
   711 Locks a region within the file as defined by a range of bytes.
       
   712 
       
   713 @see RFile64::Lock()
       
   714 
       
   715 @param aFilePos Position in file from which to lock; this is the  offset from the beginning of the file.
       
   716 @param aLength  Number of bytes to lock.
       
   717 
       
   718 @return KErrNone if successful, otherwise one of the other  system-wide error 
       
   719         codes.
       
   720 */
       
   721 TInt RFileBuf64::Lock(TInt64 aFilePos, TInt64 aLength) const
       
   722 	{
       
   723 	__FILEBUF64_INVARIANT();
       
   724 	return iFile.Lock(aFilePos, aLength);
       
   725 	}
       
   726 	
       
   727 /**
       
   728 Unlocks a region within the file as defined by a range of bytes.
       
   729 
       
   730 @see RFile64::UnLock()
       
   731 
       
   732 @param aFilePos Position in file from which to unlock; this is the  offset from the beginning of the file.
       
   733 @param aLength  Number of bytes to unlock.
       
   734 
       
   735 @return KErrNone if successful, otherwise one of the other  system-wide error codes.
       
   736 */
       
   737 TInt RFileBuf64::UnLock(TInt64 aFilePos, TInt64 aLength) const
       
   738 	{
       
   739 	__FILEBUF64_INVARIANT();
       
   740 	return iFile.UnLock(aFilePos, aLength);
       
   741 	}
       
   742 
       
   743 /**
       
   744 Writes the pending data and then flushes the file.
       
   745 
       
   746 Although RFileBuf64::Close() also flushes internal buffers, it is better
       
   747 to call RFileBuf64::Flush() before the file is closed. This is because Close() returns no 
       
   748 error information, so there is no way of telling whether the final data was 
       
   749 written to the file successfully or not.
       
   750 
       
   751 @param aFlush The caller should call this function with aResetCachedFileSize parameter set, 
       
   752 			  when the buffer file is shared between threads.
       
   753 
       
   754 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   755 
       
   756 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
       
   757 
       
   758 @see RFileBuf64::Invariant()
       
   759 */
       
   760 TInt RFileBuf64::Flush(TBool aResetCachedFileSize /*= EFalse*/)
       
   761 	{
       
   762 	__FILEBUF64_INVARIANT();
       
   763 	TInt err = DoFileFlush();
       
   764 	if(aResetCachedFileSize && err == KErrNone)
       
   765 		{//Unset the iFileSize to force the file buffers used by the other threads to re-read the file size.
       
   766 		iFileSize = KFileSizeNotSet;
       
   767 		}
       
   768 	return err;
       
   769 	}
       
   770 
       
   771 /**
       
   772 Gets information about the drive on which this file resides.
       
   773  
       
   774 @param aDriveNumber On return, the drive number.
       
   775 
       
   776 @param aDriveInfo   On return, contains information describing the drive
       
   777                     and the medium mounted on it. The value of TDriveInfo::iType
       
   778                     shows whether the drive contains media.
       
   779 
       
   780 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   781 
       
   782 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
       
   783 
       
   784 @see RFileBuf64::Invariant()
       
   785 */
       
   786 TInt RFileBuf64::Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const
       
   787 	{
       
   788 	__FILEBUF64_INVARIANT();
       
   789 	return iFile.Drive(aDriveNumber, aDriveInfo);
       
   790 	}
       
   791 
       
   792 /**
       
   793 Performs the fixed part of the RFileBuf64 initialization and then calls MFileInitializer64::Init() to perform
       
   794 the variable part of the initialization.
       
   795 
       
   796 @param aFileInitializer A reference to an initializer object that implements MFileInitializer64::Init()
       
   797 
       
   798 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   799 */
       
   800 TInt RFileBuf64::DoInit(MFileInitializer64& aFileInitializer)
       
   801 	{
       
   802 	DoDiscard();
       
   803 	iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
       
   804 	TInt err = KErrNoMemory;
       
   805 	iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
       
   806 	if(!iBase)
       
   807 		{
       
   808 		return KErrNoMemory;	
       
   809 		}
       
   810 	err = aFileInitializer.Init(iFile);
       
   811 	if(err != KErrNone)
       
   812 		{
       
   813 		User::Free(iBase);
       
   814 		iBase = 0;
       
   815 		}
       
   816 	return err;
       
   817 	}
       
   818 
       
   819 /**
       
   820 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
       
   821 */
       
   822 void RFileBuf64::DoDiscard()
       
   823 	{
       
   824 	iLength = 0;
       
   825 	iFilePos = 0;
       
   826 	iFileSize = KFileSizeNotSet;
       
   827 	iDirty = EFalse;
       
   828 	iNextReadFilePos = KNextReadFilePosNotSet;
       
   829 	iNextReadFilePosHits = 0;
       
   830 	}
       
   831 
       
   832 /**
       
   833 Gets the current file size. 
       
   834 If iFileSize value is valid, then no call to the file server will be made.
       
   835 Otherwise the file server will be called and the file size - stored (cached) in iFileSize data member for later use.
       
   836 
       
   837 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   838 
       
   839 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
       
   840 
       
   841 @see RFileBuf64::Invariant()
       
   842 */
       
   843 TInt RFileBuf64::DoFileSize()
       
   844 	{
       
   845 	__FILEBUF64_INVARIANT();
       
   846 	if(iFileSize != KFileSizeNotSet)
       
   847 		{
       
   848 		__FILEBUF64_INVARIANT();
       
   849 		return KErrNone;
       
   850 		}
       
   851 	PROFILE_SIZE();
       
   852 	TInt err = iFile.Size(iFileSize);
       
   853 	if(err != KErrNone)
       
   854 		{
       
   855 		DoDiscard();
       
   856 		}
       
   857 	__FILEBUF64_INVARIANT();
       
   858 	return err;
       
   859 	}
       
   860 
       
   861 /**
       
   862 Sets the file size.
       
   863 If the buffer contains pending data, the data will be written to the file 
       
   864 before the "set file size" operation, if certain conditions are met. 
       
   865 
       
   866 @param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
       
   867 
       
   868 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   869 
       
   870 @panic FBuf64  5 In _DEBUG mode - negative aFileSize value.
       
   871 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
   872 
       
   873 @see RFileBuf64::Invariant()
       
   874 */
       
   875 TInt RFileBuf64::DoSetFileSize(TInt64 aFileSize)
       
   876 	{
       
   877 	__FBUF64_ASSERT(aFileSize >= 0, EFBufPanicFileSize);
       
   878 	__FILEBUF64_INVARIANT();
       
   879 	if(aFileSize < iFilePos)
       
   880 		{
       
   881 		iDirty = EFalse;
       
   882 		iLength = 0;	
       
   883 		}
       
   884 	//If the new file size is "in" the buffer then change the "iLength"
       
   885 	else if(aFileSize < (iFilePos + iLength))
       
   886 		{
       
   887 		iLength = aFileSize - iFilePos;
       
   888 		}
       
   889 	PROFILE_SETSIZE();
       
   890 	TInt err = iFile.SetSize(aFileSize);
       
   891 	if(err != KErrNone)
       
   892 		{
       
   893 		DoDiscard();
       
   894 		}
       
   895 	else
       
   896 		{
       
   897 		iFileSize = aFileSize;
       
   898 		}
       
   899 	__FILEBUF64_INVARIANT();
       
   900 	return err;
       
   901 	}
       
   902 
       
   903 /**
       
   904 Writes the pending data and flushes the file.
       
   905 
       
   906 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   907 
       
   908 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
       
   909 
       
   910 @see RFileBuf64::Invariant()
       
   911 */
       
   912 TInt RFileBuf64::DoFileFlush()
       
   913 	{
       
   914 	__FILEBUF64_INVARIANT();
       
   915 	TInt err = DoFileWrite2();//Write the buffer if the iDirty flag is set. Do not preserve the buffer content and file pos.
       
   916 	if(err != KErrNone)
       
   917 		{
       
   918 		__FILEBUF64_INVARIANT();
       
   919 		return err;	
       
   920 		}
       
   921 	PROFILE_FLUSH();
       
   922 	err = iFile.Flush();
       
   923 	if(err != KErrNone)
       
   924 		{
       
   925 		DoDiscard();
       
   926 		}
       
   927 	iLength = 0;
       
   928 	__FILEBUF64_INVARIANT();
       
   929 	return err;
       
   930 	}
       
   931 
       
   932 /**
       
   933 Writes the buffered data to the file if the iLength value is > 0.
       
   934 If the file write operation extends the file, the iFileSize data member will be initialized with the new file size.
       
   935 No changes occur in the other data member values.
       
   936 
       
   937 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   938 
       
   939 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
   940 
       
   941 @see RFileBuf64::DoFileWrite1()
       
   942 @see RFileBuf64::DoFileWrite2()
       
   943 @see RFileBuf64::Invariant()
       
   944 */
       
   945 TInt RFileBuf64::DoFileWrite()
       
   946 	{
       
   947 	__FILEBUF64_INVARIANT();
       
   948 	if(iLength == 0)
       
   949 		{
       
   950 		__FILEBUF64_INVARIANT();
       
   951 		return KErrNone;	
       
   952 		}
       
   953 	PROFILE_WRITE(iFilePos, iLength);
       
   954 	TPtrC8 data(iBase, iLength);		
       
   955 	TInt err = iFile.Write(iFilePos, data);
       
   956 	if(err == KErrNone)
       
   957 		{
       
   958 		iFileSize = Max(iFileSize, (iFilePos + iLength));
       
   959 		}
       
   960 	else
       
   961 		{
       
   962 		DoDiscard();
       
   963 		}
       
   964 	__FILEBUF64_INVARIANT();
       
   965 	return err;
       
   966 	}
       
   967 
       
   968 /**
       
   969 Writes the buffered data to the file if the iDirty flag is set.
       
   970 If the iDirty flag is set and the file write operation was successful, the iFilePos will be initialized with
       
   971 the aNewFilePos value, the iLength will be set to 0.
       
   972 This method is called from RFileBuf64::Read(), where:
       
   973  - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
       
   974    with aNewFilePos - the offset in the file where the next file read operation should start from;
       
   975  - if the buffer contains cached reads, then nothing happens, the buffer content will be kept;
       
   976 The function resets the iDirty flag.
       
   977 
       
   978 @param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
       
   979 				   the aNewFilePos value.
       
   980 
       
   981 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
   982 
       
   983 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
   984 				   
       
   985 @panic FBuf64  4 In _DEBUG mode - negative aNewFilePos value.
       
   986 
       
   987 @see RFileBuf64::Read()
       
   988 @see RFileBuf64::DoFileWrite()
       
   989 @see RFileBuf64::DoFileWrite2()
       
   990 @see RFileBuf64::Invariant()
       
   991 */
       
   992 TInt RFileBuf64::DoFileWrite1(TInt64 aNewFilePos)
       
   993 	{
       
   994 	__FBUF64_ASSERT(aNewFilePos >= 0, EFBufPanicFilePos);
       
   995 	__FILEBUF64_INVARIANT();
       
   996 	TInt err = KErrNone;
       
   997 	if(iDirty)
       
   998 		{
       
   999 		err = DoFileWrite();
       
  1000 		if(err == KErrNone)	
       
  1001 			{
       
  1002 			iFilePos = aNewFilePos;
       
  1003 			iLength = 0;
       
  1004 			}
       
  1005 		}
       
  1006 	iDirty = EFalse;
       
  1007 	__FILEBUF64_INVARIANT();
       
  1008 	return err;		
       
  1009 	}
       
  1010 
       
  1011 /*
       
  1012 Writes the buffered data to the file if the iDirty flag is set.
       
  1013 If the file write operation was successful or if the iDirty flag was not set, the iFilePos will be initialized with
       
  1014 the aNewFilePos value, the iLength will be set to 0.
       
  1015 This method is called from RFileBuf64::Write() an other RFileBuf64 methods (but not from RFileBuf64::Read()), where:
       
  1016  - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
       
  1017    with aNewFilePos - the offset in the file for which the write data will be cached in the buffer;
       
  1018  - if the buffer contains cached reads, then the buffer content will be destroyed, iFilePos initialized with aNewFilePos
       
  1019    and iLength set to 0;
       
  1020 The function resets the iDirty flag.
       
  1021 The difference between RFileBuf64::DoFileWrite1() and RFileBuf64::DoFileWrite2() is:
       
  1022  - RFileBuf64::DoFileWrite1() perserves the buffer content if iDirty is not set;
       
  1023  - RFileBuf64::DoFileWrite2() always destroys the buffer content and initializes iFilePos;
       
  1024 
       
  1025 @param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
       
  1026 				   the aNewFilePos value.
       
  1027 
       
  1028 @return KErrNone if successful, otherwise one of the other system-wide error codes.
       
  1029 
       
  1030 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
  1031 				   
       
  1032 @panic FBuf64  4 In _DEBUG mode - negative aNewFilePos value.
       
  1033 
       
  1034 @see RFileBuf64::Write()
       
  1035 @see RFileBuf64::DoFileWrite()
       
  1036 @see RFileBuf64::DoFileWrite1()
       
  1037 @see RFileBuf64::Invariant()
       
  1038 */
       
  1039 TInt RFileBuf64::DoFileWrite2(TInt64 aNewFilePos)
       
  1040 	{
       
  1041 	__FBUF64_ASSERT(aNewFilePos >= 0, EFBufPanicFilePos);
       
  1042 	__FILEBUF64_INVARIANT();
       
  1043 	TInt err = KErrNone;
       
  1044 	if(iDirty)
       
  1045 		{
       
  1046 		err = DoFileWrite();
       
  1047 		}
       
  1048 	if(err == KErrNone)	
       
  1049 		{
       
  1050 		iFilePos = aNewFilePos;
       
  1051 		iLength = 0;
       
  1052 		}
       
  1053 	iDirty = EFalse;
       
  1054 	__FILEBUF64_INVARIANT();
       
  1055 	return err;
       
  1056 	}
       
  1057 
       
  1058 /**
       
  1059 This function discards the buffer content if the buffer contains cached read data.
       
  1060 The function is called from RFileBuf64::Write(), because if the buffer contains cached read data,
       
  1061 they cannot be mixed with the cached write data.
       
  1062 Reason: for example the buffer contains 8Kb cached read data from file offset 0.
       
  1063         The data write request is 10 bytes at offset 4000. The write data will be cached,
       
  1064         because the buffer contains data from from this file area: [0..8192].
       
  1065         The iDirty flag will be set. Later when RFileBuf64::Flush() is called, the whole
       
  1066         8Kb buffer will be written. There is nothing wrong with that, the file content will be consistent.
       
  1067         But from performance point of view: 8Kb written vs. 10 bytes written - that may badly impact the performance.
       
  1068 
       
  1069 @see RFileBuf64::Write()
       
  1070 
       
  1071 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
       
  1072 */
       
  1073 void RFileBuf64::DoDiscardBufferedReadData()
       
  1074 	{
       
  1075 	__FILEBUF64_INVARIANT();
       
  1076 	if(!iDirty && iLength > 0)
       
  1077 		{
       
  1078 		iLength = 0;
       
  1079 		iFilePos = 0;
       
  1080 		iNextReadFilePos = KNextReadFilePosNotSet;
       
  1081 		iNextReadFilePosHits = 0;
       
  1082 		}
       
  1083 	__FILEBUF64_INVARIANT();
       
  1084 	}
       
  1085 
       
  1086 #ifdef _DEBUG
       
  1087 
       
  1088 /**
       
  1089 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
       
  1090 (except the init/destroy methods).
       
  1091 
       
  1092 @panic FBuf64  11 In _DEBUG mode - null "this" pointer.
       
  1093 @panic FBuf64   1 In _DEBUG mode - negative iCapacity value.
       
  1094 @panic FBuf64   2 In _DEBUG mode - the buffer pointer is null (possible the buffer is not allocated or already destroyed).
       
  1095 @panic FBuf64   3 In _DEBUG mode - invalid iLength value (negative or bigger than iCapacity).
       
  1096 @panic FBuf64   4 In _DEBUG mode - negative iFilePos value.
       
  1097 @panic FBuf64   5 In _DEBUG mode - set but negative iFileSize value.
       
  1098 @panic FBuf64   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
       
  1099 @panic FBuf64  13 In _DEBUG mode - set but negative iNextReadFilePos value.
       
  1100 @panic FBuf64  14 In _DEBUG mode - negative iNextReadFilePosHits value.
       
  1101 @panic FBuf64  15 In _DEBUG mode - iReadAheadSize is negative or is not power of two.
       
  1102 */
       
  1103 void RFileBuf64::Invariant() const
       
  1104 	{
       
  1105 	__FBUF64_ASSERT(this != 0, EFBufPanicNullThis);
       
  1106 	__FBUF64_ASSERT(iCapacity > 0, EFBufPanicCapacity);
       
  1107 	__FBUF64_ASSERT(iBase != 0, EFBufPanicNullBuf);
       
  1108 	__FBUF64_ASSERT(iLength >= 0 && iLength <= iCapacity, EFBufPanicBufLen);
       
  1109 	__FBUF64_ASSERT(iFilePos >= 0, EFBufPanicFilePos);
       
  1110 	__FBUF64_ASSERT(iFileSize == KFileSizeNotSet || iFileSize >= 0, EFBufPanicFileSize);
       
  1111 	__FBUF64_ASSERT(iFile.SubSessionHandle() != 0, EFBufPanicFileHandle);
       
  1112 	__FBUF64_ASSERT(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, EFBufPanicNextReadFilePos);
       
  1113 	__FBUF64_ASSERT(iNextReadFilePosHits >= 0, EFBufPanicNextReadFilePosHits);
       
  1114 	__FBUF64_ASSERT(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, EFBufPanicFileBlockSize);
       
  1115 	}
       
  1116 	
       
  1117 #endif