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