os/persistentdata/persistentstorage/sqlite3api/OsLayer/FileBuf64.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
#include "FileBuf64.h"
sl@0
    16
#include "OstTraceDefinitions.h"
sl@0
    17
#ifdef OST_TRACE_COMPILER_IN_USE
sl@0
    18
#include "FileBuf64Traces.h"
sl@0
    19
#endif
sl@0
    20
#include "SqliteTraceDef.h"
sl@0
    21
sl@0
    22
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
    23
sl@0
    24
/**
sl@0
    25
This constant is used for initializing the RFileBuf64::iFileSize data member and means that
sl@0
    26
the iFileSize is not yet initialized with the real file size value. 
sl@0
    27
(RFileBuf64::iFileSize caches the file size value)
sl@0
    28
@internalComponent
sl@0
    29
*/
sl@0
    30
static const TInt KFileSizeNotSet = -1;
sl@0
    31
sl@0
    32
/**
sl@0
    33
This constant is used as a default initializer for the RFileBuf64::iNextReadFilePos data member,
sl@0
    34
indicating that the "guessed" file read offset is invalid and should not be used.
sl@0
    35
@internalComponent
sl@0
    36
*/
sl@0
    37
static const TInt KNextReadFilePosNotSet = -1;
sl@0
    38
sl@0
    39
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
    40
///////////////////////////        FBUF INVARIANT      ///////////////////////////////////////////////////////////////
sl@0
    41
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
    42
sl@0
    43
#ifdef _DEBUG
sl@0
    44
sl@0
    45
#define __FILEBUF64_INVARIANT() Invariant()
sl@0
    46
sl@0
    47
#else //_DEBUG
sl@0
    48
sl@0
    49
#define __FILEBUF64_INVARIANT() void(0)
sl@0
    50
sl@0
    51
#endif//_DEBUG
sl@0
    52
sl@0
    53
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
    54
///////////////////////////        RFileBuf64    /////////////////////////////////////////////////////////////////////
sl@0
    55
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
    56
	
sl@0
    57
/**
sl@0
    58
Initializes RFileBuf64 data members with their default values.
sl@0
    59
sl@0
    60
@param aSize Max file buffer size (capacity) in bytes.
sl@0
    61
sl@0
    62
@panic Sqlite3 1 In _DEBUG mode - aSize is 0 or negative.
sl@0
    63
*/
sl@0
    64
RFileBuf64::RFileBuf64(TInt aSize) :
sl@0
    65
	iCapacity(aSize),
sl@0
    66
	iBase(NULL),
sl@0
    67
	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize)
sl@0
    68
	{
sl@0
    69
	SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_RFILEBUF64, "FBuf;0x%X;RFileBuf64::RFileBuf64;aSize=%d;iReadAheadSize=%d", (TUint)this, aSize, iReadAheadSize));
sl@0
    70
	__ASSERT_DEBUG(aSize > 0, __SQLITEPANIC(EFBufPanicCapacity));
sl@0
    71
	}
sl@0
    72
sl@0
    73
/**
sl@0
    74
Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
sl@0
    75
If the file already exists, an error is returned.
sl@0
    76
If the resulting path does not exist, then the operation cannot proceed and the function returns an error code.
sl@0
    77
sl@0
    78
@param aFs       The file server session.
sl@0
    79
@param aFileName The name of the file. Any path components (i.e. drive letter
sl@0
    80
                 or directory), which are not specified, are taken from
sl@0
    81
                 the session path.
sl@0
    82
@param aFileMode The mode in which the file is opened. See TFileMode for details.
sl@0
    83
sl@0
    84
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
    85
sl@0
    86
@see TFileMode
sl@0
    87
@see RFile64::Create()
sl@0
    88
sl@0
    89
@panic Sqlite3  7 In _DEBUG mode - Invalid aFs object (null file session handle).
sl@0
    90
@panic Sqlite3 10 In _DEBUG mode - Invalid file name length (zero file name length).
sl@0
    91
*/
sl@0
    92
TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
sl@0
    93
	{
sl@0
    94
	__ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
sl@0
    95
	__ASSERT_DEBUG(aFileName.Length() > 0, __SQLITEPANIC(EFBufPanicFileNameLen));
sl@0
    96
	
sl@0
    97
	TInt err = DoPreInit();
sl@0
    98
	if(err == KErrNone)
sl@0
    99
	    {
sl@0
   100
	    err = iFile.Create(aFs, aFileName, aFileMode);
sl@0
   101
	    }
sl@0
   102
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_CREATE, "FBuf;0x%X;RFileBuf64::Create;aFs.Handle()=0x%X;aFileName=%S;iFile.SubSessionHandle()=0x%X;err=%d", (TUint)this, (TUint)aFs.Handle(), __SQLITEPRNSTR(aFileName), (TUint)iFile.SubSessionHandle(), err));
sl@0
   103
	DoPostInit(err);
sl@0
   104
	return err;
sl@0
   105
	}
sl@0
   106
sl@0
   107
/**
sl@0
   108
Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
sl@0
   109
If the file does not already exist, an error is returned.
sl@0
   110
sl@0
   111
@param aFs       The file server session.
sl@0
   112
@param aFileName The name of the file. Any path components (i.e. drive letter
sl@0
   113
                 or directory), which are not specified, are taken from
sl@0
   114
                 the session path.
sl@0
   115
@param aFileMode The mode in which the file is opened. See TFileMode for details.
sl@0
   116
sl@0
   117
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   118
sl@0
   119
@see TFileMode
sl@0
   120
@see RFile64::Open()
sl@0
   121
sl@0
   122
@panic Sqlite3  7 In _DEBUG mode - Invalid aFs object (null file session handle).
sl@0
   123
@panic Sqlite3 10 In _DEBUG mode - Invalid file name length (zero file name length).
sl@0
   124
*/
sl@0
   125
TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
sl@0
   126
	{
sl@0
   127
	__ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
sl@0
   128
	__ASSERT_DEBUG(aFileName.Length() > 0, __SQLITEPANIC(EFBufPanicFileNameLen));
sl@0
   129
	
sl@0
   130
    TInt err = DoPreInit();
sl@0
   131
    if(err == KErrNone)
sl@0
   132
        {
sl@0
   133
        err = iFile.Open(aFs, aFileName, aFileMode);
sl@0
   134
        }
sl@0
   135
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_OPEN, "FBuf;0x%X;RFileBuf64::Open;aFs.Handle()=0x%X;aFileName=%S;iFile.SubSessionHandle()=0x%X;err=%d", (TUint)this, (TUint)aFs.Handle(), __SQLITEPRNSTR(aFileName), (TUint)iFile.SubSessionHandle(), err));
sl@0
   136
    DoPostInit(err);
sl@0
   137
	return err;
sl@0
   138
	}
sl@0
   139
sl@0
   140
/**
sl@0
   141
Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
sl@0
   142
RFileBuf64 public interface.
sl@0
   143
sl@0
   144
@param aFs       The file server session.
sl@0
   145
@param aPath     The directory in which the file is created.
sl@0
   146
@param aFileName On return, contains the full path and file name of the file.
sl@0
   147
                 The filename is guaranteed to be unique within the directory
sl@0
   148
                 specified by aPath.
sl@0
   149
@param aFileMode The mode in which the file is opened. The access mode is
sl@0
   150
                 automatically set to EFileWrite. See TFileMode for details.
sl@0
   151
sl@0
   152
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   153
sl@0
   154
@see TFileMode
sl@0
   155
@see RFile64::Temp()
sl@0
   156
sl@0
   157
@panic Sqlite3  7 In _DEBUG mode - Invalid aFs object (null file session handle).
sl@0
   158
*/
sl@0
   159
TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
sl@0
   160
	{
sl@0
   161
	__ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
sl@0
   162
	
sl@0
   163
    TInt err = DoPreInit();
sl@0
   164
    if(err == KErrNone)
sl@0
   165
        {
sl@0
   166
        err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
sl@0
   167
        }
sl@0
   168
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_TEMP, "FBuf;0x%X;RFileBuf64::Temp;aFs.Handle()=0x%X;aFileName=%S;iFile.SubSessionHandle()=0x%X;err=%d", (TUint)this, (TUint)aFs.Handle(), __SQLITEPRNSTR(aFileName), (TUint)iFile.SubSessionHandle(), err));
sl@0
   169
    DoPostInit(err);
sl@0
   170
	return err;
sl@0
   171
	}
sl@0
   172
sl@0
   173
/**
sl@0
   174
Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
sl@0
   175
the RFileBuf64 resources. 
sl@0
   176
RFileBuf64::Flush() should be called before RFileBuf64::Close() to ensure that if there are pending data, they will
sl@0
   177
be written to the file and if the operation fails, the caller will be notified with an appropriate return error.
sl@0
   178
sl@0
   179
@see RFileBuf64::Flush()
sl@0
   180
*/
sl@0
   181
void RFileBuf64::Close()
sl@0
   182
	{
sl@0
   183
	SQLITE_TRACE_FBUF(OstTraceExt2(TRACE_INTERNALS, RFILEBUF64_CLOSE, "FBuf;0x%X;RFileBuf64::Close;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle()));
sl@0
   184
	if(iFile.SubSessionHandle() != 0 && iBase != 0)
sl@0
   185
		{
sl@0
   186
		(void)DoFileWrite2();
sl@0
   187
		}
sl@0
   188
	iFile.Close();
sl@0
   189
	User::Free(iBase);
sl@0
   190
	iBase = 0;
sl@0
   191
	}
sl@0
   192
sl@0
   193
/**
sl@0
   194
Calculates and sets optimal read-ahead buffer size.
sl@0
   195
aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
sl@0
   196
sl@0
   197
Initialization rules:
sl@0
   198
Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and 
sl@0
   199
        a power of two then the read-ahead value will be
sl@0
   200
        initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise
sl@0
   201
        the buffer capacity will be used as a read-ahead value). 
sl@0
   202
Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize.
sl@0
   203
        If aBlockSize passes the checks then it will be used as a read-ahead value. 
sl@0
   204
sl@0
   205
@param aBlockSize The size of a file block in bytes
sl@0
   206
@param aReadRecBufSize The recommended buffer size for optimised reading performance
sl@0
   207
sl@0
   208
@return The new read-ahead value
sl@0
   209
sl@0
   210
@see TVolumeIOParamInfo
sl@0
   211
*/
sl@0
   212
TInt RFileBuf64::SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize)
sl@0
   213
	{
sl@0
   214
	__FILEBUF64_INVARIANT();
sl@0
   215
	if((aReadRecBufSize & (aReadRecBufSize - 1)) == 0 && aReadRecBufSize > RFileBuf64::KDefaultReadAheadSize)
sl@0
   216
		{
sl@0
   217
		iReadAheadSize = aReadRecBufSize > iCapacity ? iCapacity : aReadRecBufSize;
sl@0
   218
		}
sl@0
   219
	else if((aBlockSize & (aBlockSize - 1)) == 0 && aBlockSize > RFileBuf64::KDefaultReadAheadSize)
sl@0
   220
		{
sl@0
   221
		iReadAheadSize = aBlockSize > iCapacity ? iCapacity : aBlockSize;
sl@0
   222
		}
sl@0
   223
	SQLITE_TRACE_FBUF(OstTraceExt4(TRACE_INTERNALS, RFILEBUF64_SETREADAHEADSIZE, "FBuf;0x%X;RFileBuf64::SetReadAheadSize;aBlockSize=%d;aReadRecBufSize=%d;iReadAheadSize=%d", (TUint)this, aBlockSize, aReadRecBufSize, iReadAheadSize));
sl@0
   224
	__FILEBUF64_INVARIANT();
sl@0
   225
	return iReadAheadSize;
sl@0
   226
	}
sl@0
   227
sl@0
   228
/**
sl@0
   229
Reads from the file at the specified position (aFilePos).
sl@0
   230
If the data to be read is in the buffer, then the data will be taken from the buffer.
sl@0
   231
sl@0
   232
@param aFilePos Position of first byte to be read.  This is an offset from
sl@0
   233
            the start of the file. 
sl@0
   234
            If aPos is beyond the end of the file, the function returns
sl@0
   235
            a zero length descriptor.
sl@0
   236
@param aDes Descriptor into which binary data is read. Any existing contents 
sl@0
   237
            are overwritten. On return, its length is set to the number of
sl@0
   238
            bytes read.
sl@0
   239
            
sl@0
   240
@return KErrNone if successful, otherwise one of the other system-wide error  codes.
sl@0
   241
sl@0
   242
@panic Sqlite3  4 In _DEBUG mode - negative aFilePos value.
sl@0
   243
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   244
sl@0
   245
@see RFileBuf64::Invariant()
sl@0
   246
*/
sl@0
   247
TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
sl@0
   248
	{
sl@0
   249
	__ASSERT_DEBUG(aFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
sl@0
   250
	__FILEBUF64_INVARIANT();
sl@0
   251
	aDes.SetLength(0);
sl@0
   252
	//1. The output buffer max len is 0
sl@0
   253
	if(aDes.MaxLength() == 0)
sl@0
   254
		{
sl@0
   255
		__FILEBUF64_INVARIANT();
sl@0
   256
		return KErrNone;	
sl@0
   257
		}
sl@0
   258
	//2. Initialize the "iFileSize" if it is not initialized yet
sl@0
   259
	TInt err = DoFileSize();
sl@0
   260
	if(err != KErrNone)
sl@0
   261
		{
sl@0
   262
		__FILEBUF64_INVARIANT();
sl@0
   263
		return err;	
sl@0
   264
		}
sl@0
   265
	//3. Too big "read" request - read directly from the file
sl@0
   266
	TInt len = aDes.MaxLength();
sl@0
   267
	if(len > iCapacity)
sl@0
   268
		{
sl@0
   269
		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
sl@0
   270
			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
sl@0
   271
			err = DoFileWrite1(aFilePos);
sl@0
   272
			}
sl@0
   273
		if(err == KErrNone)
sl@0
   274
			{
sl@0
   275
			err = iFile.Read(aFilePos, aDes);
sl@0
   276
			SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_READ1, "FBuf;0x%X;RFileBuf64::Read;TooBigRq;iFileSize=%lld;aFilePos=%lld;len=%d;err=%d", (TUint)this, iFileSize, aFilePos, len, err));
sl@0
   277
			}
sl@0
   278
		__FILEBUF64_INVARIANT();
sl@0
   279
		return err;
sl@0
   280
		}
sl@0
   281
	//4. The requested data size is smaller than the buffer capacity
sl@0
   282
	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
sl@0
   283
	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
sl@0
   284
		{
sl@0
   285
		//1. If part or all of the data is in the buffer - copy the data to the target location
sl@0
   286
		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
sl@0
   287
			{
sl@0
   288
			TInt blocklen = Min(len, (iFilePos + iLength - aFilePos));
sl@0
   289
			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen);
sl@0
   290
			len -= blocklen;
sl@0
   291
			aFilePos += blocklen;
sl@0
   292
			}
sl@0
   293
		//2. Perform a read-ahead operation
sl@0
   294
		else
sl@0
   295
			{
sl@0
   296
			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
sl@0
   297
			err = DoFileWrite1(aFilePos);
sl@0
   298
			if(err != KErrNone)
sl@0
   299
				{
sl@0
   300
				break;	
sl@0
   301
				}
sl@0
   302
			if(iNextReadFilePos != aFilePos)
sl@0
   303
				{//Guessed read ahead was wrong. Direct "file read" operation
sl@0
   304
				iNextReadFilePosHits = 0;
sl@0
   305
				TPtr8 ptr2(outptr, len);
sl@0
   306
				err = iFile.Read(aFilePos, ptr2);
sl@0
   307
				SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_READ2, "FBuf;0x%X;RFileBuf64::Read;Read;iFileSize=%lld;aFilePos=%lld;len=%d;err=%d", (TUint)this, iFileSize, aFilePos, len, err));
sl@0
   308
				if(err == KErrNone)
sl@0
   309
					{
sl@0
   310
					iNextReadFilePos = aFilePos + len;
sl@0
   311
					len -= ptr2.Length();
sl@0
   312
					}
sl@0
   313
				break;
sl@0
   314
				}
sl@0
   315
			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
sl@0
   316
			const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize
sl@0
   317
			if(iNextReadFilePosHits < KMaxReadFilePosHits)
sl@0
   318
				{
sl@0
   319
				++iNextReadFilePosHits;
sl@0
   320
				}
sl@0
   321
			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
sl@0
   322
			TInt align = (aFilePos + len + maxReadAhead) & (iReadAheadSize - 1);
sl@0
   323
			TInt readahead = maxReadAhead - align;
sl@0
   324
			if(readahead < 0)
sl@0
   325
				{
sl@0
   326
				// if read-ahead doesn't cross block boundary do it all
sl@0
   327
				readahead = maxReadAhead;	
sl@0
   328
				}
sl@0
   329
			TPtr8 ptr(iBase, Min(iCapacity, (len + readahead)));
sl@0
   330
			err = iFile.Read(aFilePos, ptr);
sl@0
   331
			SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_READ3, "FBuf;0x%X;RFileBuf64::Read;ReadAhead;iFileSize=%lld;aFilePos=%lld;len=%d;err=%d", (TUint)this, iFileSize, aFilePos, ptr.MaxLength(), err));
sl@0
   332
			if(err == KErrNone)
sl@0
   333
				{
sl@0
   334
				iFilePos = aFilePos;
sl@0
   335
				iLength = ptr.Length();	
sl@0
   336
				iNextReadFilePos = iFilePos + iLength;
sl@0
   337
				if(iLength == 0)
sl@0
   338
					{
sl@0
   339
					break;	
sl@0
   340
					}
sl@0
   341
				}
sl@0
   342
			else
sl@0
   343
				{
sl@0
   344
				DoDiscard();	
sl@0
   345
				}
sl@0
   346
			}
sl@0
   347
		}
sl@0
   348
	aDes.SetLength(aDes.MaxLength() - len);
sl@0
   349
	__FILEBUF64_INVARIANT();
sl@0
   350
	return err;
sl@0
   351
	}
sl@0
   352
	
sl@0
   353
/**
sl@0
   354
Writes to the file at the specified offset (aFilePos) within the file.
sl@0
   355
If certain conditions are met, the data will be stored in the buffer - no call to the file server.
sl@0
   356
sl@0
   357
@param aFilePos The offset from the start of the file at which the first byte is written. 
sl@0
   358
                If a position beyond the end of the file is specified, then
sl@0
   359
                the write operation begins at the end of the file.
sl@0
   360
                If the position has been locked, then the write fails.
sl@0
   361
            
sl@0
   362
@param aData The descriptor from which binary data is written. The function writes 
sl@0
   363
             the entire contents of aData to the file.
sl@0
   364
sl@0
   365
@return KErrNone if successful, otherwise one of the other system-wide error  codes.
sl@0
   366
sl@0
   367
@panic Sqlite3  4 In _DEBUG mode - negative aFilePos value.
sl@0
   368
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   369
sl@0
   370
@see RFileBuf64::Invariant()
sl@0
   371
*/
sl@0
   372
TInt RFileBuf64::Write(TInt64 aFilePos, const TDesC8& aData)
sl@0
   373
	{
sl@0
   374
	__ASSERT_DEBUG(aFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
sl@0
   375
	__FILEBUF64_INVARIANT();
sl@0
   376
	if(aData.Length() == 0)
sl@0
   377
		{
sl@0
   378
		__FILEBUF64_INVARIANT();
sl@0
   379
		return KErrNone;	
sl@0
   380
		}
sl@0
   381
	TInt err = DoFileSize();
sl@0
   382
	if(err != KErrNone)
sl@0
   383
		{
sl@0
   384
		__FILEBUF64_INVARIANT();
sl@0
   385
		return err;	
sl@0
   386
		}
sl@0
   387
	DoDiscardBufferedReadData();
sl@0
   388
	const TUint8* data = aData.Ptr();
sl@0
   389
	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
sl@0
   390
		{
sl@0
   391
		//1. The new write pos is before the buffered file pos
sl@0
   392
		if(aFilePos < iFilePos)
sl@0
   393
			{
sl@0
   394
			//If the new data sticks to/overlapps the old data and there is room in the buffer to move the old data 
sl@0
   395
			//toward the end, then the new data can be copied at the beginning of the buffer.
sl@0
   396
			if((aFilePos + len) >= iFilePos && (iFilePos - aFilePos) <= (iCapacity - iLength))
sl@0
   397
				{
sl@0
   398
				(void)Mem::Copy(iBase + (iFilePos - aFilePos), iBase, iLength);	//Make room - move the existing data toward the end
sl@0
   399
				(void)Mem::Copy(iBase, data, len);								//of the buffer. Stick the new data to the old data
sl@0
   400
				iLength += (iFilePos - aFilePos);
sl@0
   401
				iFilePos = aFilePos;										//The new file pos is associated with the buffer
sl@0
   402
				iFileSize = Max(iFileSize, (iFilePos + iLength));
sl@0
   403
				len = 0;													//No more new data
sl@0
   404
				iDirty = ETrue;	
sl@0
   405
				}
sl@0
   406
			else
sl@0
   407
			//The "aFilePos" is too far before the "iFilePos". Write the buffer and associate the new pos with the buffer
sl@0
   408
				{
sl@0
   409
				err = DoFileWrite2(aFilePos);
sl@0
   410
				}
sl@0
   411
			}
sl@0
   412
		//2. The new write pos is after the associated file pos + the data length.
sl@0
   413
		else if(aFilePos > (iFilePos + iLength))
sl@0
   414
			{
sl@0
   415
			if(aFilePos > iFileSize)											//Beyond the end of the file
sl@0
   416
				{
sl@0
   417
				if((iFilePos + iLength) == iFileSize && (aFilePos - iFilePos) < iCapacity)	
sl@0
   418
					{															//but within the buffer => extend the file with zeros.
sl@0
   419
					Mem::FillZ(iBase + iLength, aFilePos - iFilePos - iLength);
sl@0
   420
					iLength = aFilePos - iFilePos;
sl@0
   421
					iFileSize = Max(iFileSize, (iFilePos + iLength));
sl@0
   422
					iDirty = ETrue;	
sl@0
   423
					}
sl@0
   424
				else									
sl@0
   425
				//Beyond the end of the file and not in the buffer - set file size.
sl@0
   426
					{
sl@0
   427
					err = DoSetFileSize(aFilePos);
sl@0
   428
					}
sl@0
   429
				}
sl@0
   430
			else										
sl@0
   431
			//Within the file, not in the buffer - write the buffer and associate the new file pos with the buffer
sl@0
   432
				{
sl@0
   433
				err = DoFileWrite2(aFilePos);
sl@0
   434
				}
sl@0
   435
			}
sl@0
   436
		//3. The new write pos is in the buffer, but the data length is too big
sl@0
   437
		//   (For SQLite is OK, otherwise the whole block must be written to the file)
sl@0
   438
		//4. The new write pos is in the buffer, the data entirely fits in the buffer
sl@0
   439
		else
sl@0
   440
			{
sl@0
   441
			if(iCapacity == iLength)			//The buffer is full. Write the buffer and associate the new file pos
sl@0
   442
				{
sl@0
   443
				err = DoFileWrite2(aFilePos);
sl@0
   444
				}
sl@0
   445
			if(err == KErrNone)
sl@0
   446
				{
sl@0
   447
				TInt amount = Min(len, (iCapacity - (aFilePos - iFilePos)));
sl@0
   448
				const TUint8* end = Mem::Copy(iBase + (aFilePos - iFilePos), data, amount);
sl@0
   449
				iLength = Max(iLength, (end - iBase));
sl@0
   450
				iFileSize = Max(iFileSize, (iFilePos + iLength));
sl@0
   451
				len -= amount;
sl@0
   452
				data += amount;
sl@0
   453
				aFilePos += amount;
sl@0
   454
				iDirty = ETrue;	
sl@0
   455
				}
sl@0
   456
			}
sl@0
   457
		}
sl@0
   458
	__FILEBUF64_INVARIANT();
sl@0
   459
	return err;
sl@0
   460
	}
sl@0
   461
	
sl@0
   462
/**
sl@0
   463
Gets the current file size.
sl@0
   464
sl@0
   465
@param aFileSize On return, the size of the file in bytes.
sl@0
   466
sl@0
   467
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   468
sl@0
   469
See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
sl@0
   470
sl@0
   471
@see RFileBuf64::Invariant()
sl@0
   472
*/
sl@0
   473
TInt RFileBuf64::Size(TInt64& aFileSize)
sl@0
   474
	{
sl@0
   475
	__FILEBUF64_INVARIANT();
sl@0
   476
	TInt err = DoFileSize();
sl@0
   477
	if(err == KErrNone)
sl@0
   478
		{
sl@0
   479
		aFileSize = iFileSize;
sl@0
   480
		}
sl@0
   481
	__FILEBUF64_INVARIANT();
sl@0
   482
	return err;
sl@0
   483
	}
sl@0
   484
sl@0
   485
/**
sl@0
   486
Sets the file size.
sl@0
   487
sl@0
   488
If the size of the file is reduced, data may be lost from the end of the file.
sl@0
   489
sl@0
   490
Note:
sl@0
   491
sl@0
   492
1. The current file position remains unchanged unless SetSize() reduces the size 
sl@0
   493
   of the file in such a way that the current file position is now beyond
sl@0
   494
   the end of the file. In this case, the current file position is set to
sl@0
   495
   the end of file. 
sl@0
   496
sl@0
   497
2. If the file was not opened for writing, an error is returned.
sl@0
   498
sl@0
   499
@param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
sl@0
   500
sl@0
   501
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   502
sl@0
   503
@panic Sqlite3  5 In _DEBUG mode - negative aFileSize value.
sl@0
   504
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   505
sl@0
   506
@see RFileBuf64::Invariant()
sl@0
   507
*/
sl@0
   508
TInt RFileBuf64::SetSize(TInt64 aFileSize)
sl@0
   509
	{
sl@0
   510
	__ASSERT_DEBUG(aFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
sl@0
   511
	__FILEBUF64_INVARIANT();
sl@0
   512
	return DoSetFileSize(aFileSize);
sl@0
   513
	}
sl@0
   514
sl@0
   515
/**
sl@0
   516
Locks a region within the file as defined by a range of bytes.
sl@0
   517
sl@0
   518
@see RFile64::Lock()
sl@0
   519
sl@0
   520
@param aFilePos Position in file from which to lock; this is the  offset from the beginning of the file.
sl@0
   521
@param aLength  Number of bytes to lock.
sl@0
   522
sl@0
   523
@return KErrNone if successful, otherwise one of the other  system-wide error 
sl@0
   524
        codes.
sl@0
   525
*/
sl@0
   526
TInt RFileBuf64::Lock(TInt64 aFilePos, TInt64 aLength) const
sl@0
   527
	{
sl@0
   528
	__FILEBUF64_INVARIANT();
sl@0
   529
	TInt err = iFile.Lock(aFilePos, aLength);
sl@0
   530
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_LOCK, "FBuf;0x%X;RFileBuf64::Lock;iFileSize=%lld;aFilePos=%lld;aLength=%lld;err=%d", (TUint)this, iFileSize, aFilePos, aLength, err));
sl@0
   531
	return err;
sl@0
   532
	}
sl@0
   533
	
sl@0
   534
/**
sl@0
   535
Unlocks a region within the file as defined by a range of bytes.
sl@0
   536
sl@0
   537
@see RFile64::UnLock()
sl@0
   538
sl@0
   539
@param aFilePos Position in file from which to unlock; this is the  offset from the beginning of the file.
sl@0
   540
@param aLength  Number of bytes to unlock.
sl@0
   541
sl@0
   542
@return KErrNone if successful, otherwise one of the other  system-wide error codes.
sl@0
   543
*/
sl@0
   544
TInt RFileBuf64::UnLock(TInt64 aFilePos, TInt64 aLength) const
sl@0
   545
	{
sl@0
   546
	__FILEBUF64_INVARIANT();
sl@0
   547
	TInt err = iFile.UnLock(aFilePos, aLength);
sl@0
   548
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_UNLOCK, "FBuf;0x%X;RFileBuf64::UnLock;iFileSize=%lld;aFilePos=%lld;aLength=%lld;err=%d", (TUint)this, iFileSize, aFilePos, aLength, err));
sl@0
   549
	return err;
sl@0
   550
	}
sl@0
   551
sl@0
   552
/**
sl@0
   553
Writes the pending data and then flushes the file.
sl@0
   554
sl@0
   555
Although RFileBuf64::Close() also flushes internal buffers, it is better
sl@0
   556
to call RFileBuf64::Flush() before the file is closed. This is because Close() returns no 
sl@0
   557
error information, so there is no way of telling whether the final data was 
sl@0
   558
written to the file successfully or not.
sl@0
   559
sl@0
   560
@param aFlush The caller should call this function with aResetCachedFileSize parameter set, 
sl@0
   561
			  when the buffer file is shared between threads.
sl@0
   562
sl@0
   563
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   564
sl@0
   565
See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
sl@0
   566
sl@0
   567
@see RFileBuf64::Invariant()
sl@0
   568
*/
sl@0
   569
TInt RFileBuf64::Flush(TBool aResetCachedFileSize /*= EFalse*/)
sl@0
   570
	{
sl@0
   571
	__FILEBUF64_INVARIANT();
sl@0
   572
	TInt err = DoFileFlush();
sl@0
   573
	if(aResetCachedFileSize && err == KErrNone)
sl@0
   574
		{//Unset the iFileSize to force the file buffers used by the other threads to re-read the file size.
sl@0
   575
		iFileSize = KFileSizeNotSet;
sl@0
   576
		}
sl@0
   577
	return err;
sl@0
   578
	}
sl@0
   579
sl@0
   580
/**
sl@0
   581
Gets information about the drive on which this file resides.
sl@0
   582
 
sl@0
   583
@param aDriveNumber On return, the drive number.
sl@0
   584
sl@0
   585
@param aDriveInfo   On return, contains information describing the drive
sl@0
   586
                    and the medium mounted on it. The value of TDriveInfo::iType
sl@0
   587
                    shows whether the drive contains media.
sl@0
   588
sl@0
   589
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   590
sl@0
   591
See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
sl@0
   592
sl@0
   593
@see RFileBuf64::Invariant()
sl@0
   594
*/
sl@0
   595
TInt RFileBuf64::Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const
sl@0
   596
	{
sl@0
   597
	__FILEBUF64_INVARIANT();
sl@0
   598
	TInt err = iFile.Drive(aDriveNumber, aDriveInfo);
sl@0
   599
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_DRIVE, "FBuf;0x%X;RFileBuf64::Drive;aDriveNumber=%d;driveAtt=0x%X;mediaAtt=0x%X;err=%d", (TUint)this, aDriveNumber, (TUint)aDriveInfo.iDriveAtt, (TUint)aDriveInfo.iMediaAtt, err));
sl@0
   600
	return err;
sl@0
   601
	}
sl@0
   602
sl@0
   603
/**
sl@0
   604
Initializes RFileBuf64 data members with their initial values.   
sl@0
   605
Allocates memory for the file buffer. 
sl@0
   606
 
sl@0
   607
@return KErrNone if successful, 
sl@0
   608
        KErrNoMemory out of memory;
sl@0
   609
*/
sl@0
   610
TInt RFileBuf64::DoPreInit()
sl@0
   611
    {
sl@0
   612
    DoDiscard();
sl@0
   613
    iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
sl@0
   614
    iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
sl@0
   615
    return iBase ? KErrNone : KErrNoMemory; 
sl@0
   616
    }
sl@0
   617
sl@0
   618
/**
sl@0
   619
Performs post-initialization of the RFileBuf64 object.   
sl@0
   620
If aInitErr is not KErrNone, then the buffer memory will be released.
sl@0
   621
sl@0
   622
@param aInitErr The result of the performed before the call RFileBuf64 initialization.
sl@0
   623
*/
sl@0
   624
void RFileBuf64::DoPostInit(TInt aInitErr)
sl@0
   625
    {
sl@0
   626
    if(aInitErr != KErrNone)
sl@0
   627
        {
sl@0
   628
        User::Free(iBase);
sl@0
   629
        iBase = 0;
sl@0
   630
        }
sl@0
   631
    }
sl@0
   632
sl@0
   633
/**
sl@0
   634
Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
sl@0
   635
*/
sl@0
   636
void RFileBuf64::DoDiscard()
sl@0
   637
	{
sl@0
   638
	iLength = 0;
sl@0
   639
	iFilePos = 0;
sl@0
   640
	iFileSize = KFileSizeNotSet;
sl@0
   641
	iDirty = EFalse;
sl@0
   642
	iNextReadFilePos = KNextReadFilePosNotSet;
sl@0
   643
	iNextReadFilePosHits = 0;
sl@0
   644
	}
sl@0
   645
sl@0
   646
/**
sl@0
   647
Gets the current file size. 
sl@0
   648
If iFileSize value is valid, then no call to the file server will be made.
sl@0
   649
Otherwise the file server will be called and the file size - stored (cached) in iFileSize data member for later use.
sl@0
   650
sl@0
   651
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   652
sl@0
   653
See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
sl@0
   654
sl@0
   655
@see RFileBuf64::Invariant()
sl@0
   656
*/
sl@0
   657
TInt RFileBuf64::DoFileSize()
sl@0
   658
	{
sl@0
   659
	__FILEBUF64_INVARIANT();
sl@0
   660
	if(iFileSize != KFileSizeNotSet)
sl@0
   661
		{
sl@0
   662
		__FILEBUF64_INVARIANT();
sl@0
   663
		return KErrNone;
sl@0
   664
		}
sl@0
   665
	TInt err = iFile.Size(iFileSize);
sl@0
   666
	SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_DOFILESIZE, "FBuf;0x%X;RFileBuf64::DoFileSize;iFileSize=%lld;err=%d", (TUint)this, iFileSize, err));
sl@0
   667
	if(err != KErrNone)
sl@0
   668
		{
sl@0
   669
		DoDiscard();
sl@0
   670
		}
sl@0
   671
	__FILEBUF64_INVARIANT();
sl@0
   672
	return err;
sl@0
   673
	}
sl@0
   674
sl@0
   675
/**
sl@0
   676
Sets the file size.
sl@0
   677
If the buffer contains pending data, the data will be written to the file 
sl@0
   678
before the "set file size" operation, if certain conditions are met. 
sl@0
   679
sl@0
   680
@param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
sl@0
   681
sl@0
   682
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   683
sl@0
   684
@panic Sqlite3  5 In _DEBUG mode - negative aFileSize value.
sl@0
   685
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   686
sl@0
   687
@see RFileBuf64::Invariant()
sl@0
   688
*/
sl@0
   689
TInt RFileBuf64::DoSetFileSize(TInt64 aFileSize)
sl@0
   690
	{
sl@0
   691
	__ASSERT_DEBUG(aFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
sl@0
   692
	__FILEBUF64_INVARIANT();
sl@0
   693
	if(aFileSize < iFilePos)
sl@0
   694
		{
sl@0
   695
		iDirty = EFalse;
sl@0
   696
		iLength = 0;	
sl@0
   697
		}
sl@0
   698
	//If the new file size is "in" the buffer then change the "iLength"
sl@0
   699
	else if(aFileSize < (iFilePos + iLength))
sl@0
   700
		{
sl@0
   701
		iLength = aFileSize - iFilePos;
sl@0
   702
		}
sl@0
   703
	TInt err = iFile.SetSize(aFileSize);
sl@0
   704
	SQLITE_TRACE_FBUF(OstTraceExt4(TRACE_INTERNALS, RFILEBUF64_DOSETFILESIZE, "FBuf;0x%X;RFileBuf64::DoSetFileSize;iFileSize=%lld;aFileSize=%lld;err=%d", (TUint)this, iFileSize, aFileSize, err));
sl@0
   705
	if(err != KErrNone)
sl@0
   706
		{
sl@0
   707
		DoDiscard();
sl@0
   708
		}
sl@0
   709
	else
sl@0
   710
		{
sl@0
   711
		iFileSize = aFileSize;
sl@0
   712
		}
sl@0
   713
	__FILEBUF64_INVARIANT();
sl@0
   714
	return err;
sl@0
   715
	}
sl@0
   716
sl@0
   717
/**
sl@0
   718
Writes the pending data and flushes the file.
sl@0
   719
sl@0
   720
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   721
sl@0
   722
See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
sl@0
   723
sl@0
   724
@see RFileBuf64::Invariant()
sl@0
   725
*/
sl@0
   726
TInt RFileBuf64::DoFileFlush()
sl@0
   727
	{
sl@0
   728
	__FILEBUF64_INVARIANT();
sl@0
   729
	TInt err = DoFileWrite2();//Write the buffer if the iDirty flag is set. Do not preserve the buffer content and file pos.
sl@0
   730
	if(err != KErrNone)
sl@0
   731
		{
sl@0
   732
		__FILEBUF64_INVARIANT();
sl@0
   733
		return err;	
sl@0
   734
		}
sl@0
   735
	err = iFile.Flush();
sl@0
   736
	SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_DOFILEFLUSH, "FBuf;0x%X;RFileBuf64::DoFileFlush;iFileSize=%lld;err=%d", (TUint)this, iFileSize, err));
sl@0
   737
	if(err != KErrNone)
sl@0
   738
		{
sl@0
   739
		DoDiscard();
sl@0
   740
		}
sl@0
   741
	iLength = 0;
sl@0
   742
	__FILEBUF64_INVARIANT();
sl@0
   743
	return err;
sl@0
   744
	}
sl@0
   745
sl@0
   746
/**
sl@0
   747
Writes the buffered data to the file if the iLength value is > 0.
sl@0
   748
If the file write operation extends the file, the iFileSize data member will be initialized with the new file size.
sl@0
   749
No changes occur in the other data member values.
sl@0
   750
sl@0
   751
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   752
sl@0
   753
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   754
sl@0
   755
@see RFileBuf64::DoFileWrite1()
sl@0
   756
@see RFileBuf64::DoFileWrite2()
sl@0
   757
@see RFileBuf64::Invariant()
sl@0
   758
*/
sl@0
   759
TInt RFileBuf64::DoFileWrite()
sl@0
   760
	{
sl@0
   761
	__FILEBUF64_INVARIANT();
sl@0
   762
	if(iLength == 0)
sl@0
   763
		{
sl@0
   764
		__FILEBUF64_INVARIANT();
sl@0
   765
		return KErrNone;	
sl@0
   766
		}
sl@0
   767
	TPtrC8 data(iBase, iLength);		
sl@0
   768
	TInt err = iFile.Write(iFilePos, data);
sl@0
   769
	SQLITE_TRACE_FBUF(OstTraceExt5(TRACE_INTERNALS, RFILEBUF64_DOFILEWRITE, "FBuf;0x%X;RFileBuf64::DoFileWrite;iFileSize=%lld;iFilePos=%lld;iLength=%d;err=%d", (TUint)this, iFileSize, iFilePos, iLength, err));
sl@0
   770
	if(err == KErrNone)
sl@0
   771
		{
sl@0
   772
		iFileSize = Max(iFileSize, (iFilePos + iLength));
sl@0
   773
		}
sl@0
   774
	else
sl@0
   775
		{
sl@0
   776
		DoDiscard();
sl@0
   777
		}
sl@0
   778
	__FILEBUF64_INVARIANT();
sl@0
   779
	return err;
sl@0
   780
	}
sl@0
   781
sl@0
   782
/**
sl@0
   783
Writes the buffered data to the file if the iDirty flag is set.
sl@0
   784
If the iDirty flag is set and the file write operation was successful, the iFilePos will be initialized with
sl@0
   785
the aNewFilePos value, the iLength will be set to 0.
sl@0
   786
This method is called from RFileBuf64::Read(), where:
sl@0
   787
 - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
sl@0
   788
   with aNewFilePos - the offset in the file where the next file read operation should start from;
sl@0
   789
 - if the buffer contains cached reads, then nothing happens, the buffer content will be kept;
sl@0
   790
The function resets the iDirty flag.
sl@0
   791
sl@0
   792
@param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
sl@0
   793
				   the aNewFilePos value.
sl@0
   794
sl@0
   795
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   796
sl@0
   797
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   798
				   
sl@0
   799
@panic Sqlite3  4 In _DEBUG mode - negative aNewFilePos value.
sl@0
   800
sl@0
   801
@see RFileBuf64::Read()
sl@0
   802
@see RFileBuf64::DoFileWrite()
sl@0
   803
@see RFileBuf64::DoFileWrite2()
sl@0
   804
@see RFileBuf64::Invariant()
sl@0
   805
*/
sl@0
   806
TInt RFileBuf64::DoFileWrite1(TInt64 aNewFilePos)
sl@0
   807
	{
sl@0
   808
	__ASSERT_DEBUG(aNewFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
sl@0
   809
	__FILEBUF64_INVARIANT();
sl@0
   810
	TInt err = KErrNone;
sl@0
   811
	if(iDirty)
sl@0
   812
		{
sl@0
   813
		err = DoFileWrite();
sl@0
   814
		if(err == KErrNone)	
sl@0
   815
			{
sl@0
   816
			iFilePos = aNewFilePos;
sl@0
   817
			iLength = 0;
sl@0
   818
			}
sl@0
   819
		}
sl@0
   820
	iDirty = EFalse;
sl@0
   821
	__FILEBUF64_INVARIANT();
sl@0
   822
	return err;		
sl@0
   823
	}
sl@0
   824
sl@0
   825
/*
sl@0
   826
Writes the buffered data to the file if the iDirty flag is set.
sl@0
   827
If the file write operation was successful or if the iDirty flag was not set, the iFilePos will be initialized with
sl@0
   828
the aNewFilePos value, the iLength will be set to 0.
sl@0
   829
This method is called from RFileBuf64::Write() an other RFileBuf64 methods (but not from RFileBuf64::Read()), where:
sl@0
   830
 - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
sl@0
   831
   with aNewFilePos - the offset in the file for which the write data will be cached in the buffer;
sl@0
   832
 - if the buffer contains cached reads, then the buffer content will be destroyed, iFilePos initialized with aNewFilePos
sl@0
   833
   and iLength set to 0;
sl@0
   834
The function resets the iDirty flag.
sl@0
   835
The difference between RFileBuf64::DoFileWrite1() and RFileBuf64::DoFileWrite2() is:
sl@0
   836
 - RFileBuf64::DoFileWrite1() perserves the buffer content if iDirty is not set;
sl@0
   837
 - RFileBuf64::DoFileWrite2() always destroys the buffer content and initializes iFilePos;
sl@0
   838
sl@0
   839
@param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
sl@0
   840
				   the aNewFilePos value.
sl@0
   841
sl@0
   842
@return KErrNone if successful, otherwise one of the other system-wide error codes.
sl@0
   843
sl@0
   844
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   845
				   
sl@0
   846
@panic Sqlite3  4 In _DEBUG mode - negative aNewFilePos value.
sl@0
   847
sl@0
   848
@see RFileBuf64::Write()
sl@0
   849
@see RFileBuf64::DoFileWrite()
sl@0
   850
@see RFileBuf64::DoFileWrite1()
sl@0
   851
@see RFileBuf64::Invariant()
sl@0
   852
*/
sl@0
   853
TInt RFileBuf64::DoFileWrite2(TInt64 aNewFilePos)
sl@0
   854
	{
sl@0
   855
	__ASSERT_DEBUG(aNewFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
sl@0
   856
	__FILEBUF64_INVARIANT();
sl@0
   857
	TInt err = KErrNone;
sl@0
   858
	if(iDirty)
sl@0
   859
		{
sl@0
   860
		err = DoFileWrite();
sl@0
   861
		}
sl@0
   862
	if(err == KErrNone)	
sl@0
   863
		{
sl@0
   864
		iFilePos = aNewFilePos;
sl@0
   865
		iLength = 0;
sl@0
   866
		}
sl@0
   867
	iDirty = EFalse;
sl@0
   868
	__FILEBUF64_INVARIANT();
sl@0
   869
	return err;
sl@0
   870
	}
sl@0
   871
sl@0
   872
/**
sl@0
   873
This function discards the buffer content if the buffer contains cached read data.
sl@0
   874
The function is called from RFileBuf64::Write(), because if the buffer contains cached read data,
sl@0
   875
they cannot be mixed with the cached write data.
sl@0
   876
Reason: for example the buffer contains 8Kb cached read data from file offset 0.
sl@0
   877
        The data write request is 10 bytes at offset 4000. The write data will be cached,
sl@0
   878
        because the buffer contains data from from this file area: [0..8192].
sl@0
   879
        The iDirty flag will be set. Later when RFileBuf64::Flush() is called, the whole
sl@0
   880
        8Kb buffer will be written. There is nothing wrong with that, the file content will be consistent.
sl@0
   881
        But from performance point of view: 8Kb written vs. 10 bytes written - that may badly impact the performance.
sl@0
   882
sl@0
   883
@see RFileBuf64::Write()
sl@0
   884
sl@0
   885
See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
sl@0
   886
*/
sl@0
   887
void RFileBuf64::DoDiscardBufferedReadData()
sl@0
   888
	{
sl@0
   889
	__FILEBUF64_INVARIANT();
sl@0
   890
	if(!iDirty && iLength > 0)
sl@0
   891
		{
sl@0
   892
		iLength = 0;
sl@0
   893
		iFilePos = 0;
sl@0
   894
		iNextReadFilePos = KNextReadFilePosNotSet;
sl@0
   895
		iNextReadFilePosHits = 0;
sl@0
   896
		}
sl@0
   897
	__FILEBUF64_INVARIANT();
sl@0
   898
	}
sl@0
   899
sl@0
   900
#ifdef _DEBUG
sl@0
   901
sl@0
   902
/**
sl@0
   903
RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
sl@0
   904
(except the init/destroy methods).
sl@0
   905
sl@0
   906
@panic Sqlite3  11 In _DEBUG mode - null "this" pointer.
sl@0
   907
@panic Sqlite3   1 In _DEBUG mode - negative iCapacity value.
sl@0
   908
@panic Sqlite3   2 In _DEBUG mode - the buffer pointer is null (possible the buffer is not allocated or already destroyed).
sl@0
   909
@panic Sqlite3   3 In _DEBUG mode - invalid iLength value (negative or bigger than iCapacity).
sl@0
   910
@panic Sqlite3   4 In _DEBUG mode - negative iFilePos value.
sl@0
   911
@panic Sqlite3   5 In _DEBUG mode - set but negative iFileSize value.
sl@0
   912
@panic Sqlite3   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
sl@0
   913
@panic Sqlite3  13 In _DEBUG mode - set but negative iNextReadFilePos value.
sl@0
   914
@panic Sqlite3  14 In _DEBUG mode - negative iNextReadFilePosHits value.
sl@0
   915
@panic Sqlite3  15 In _DEBUG mode - iReadAheadSize is negative or is not power of two.
sl@0
   916
*/
sl@0
   917
void RFileBuf64::Invariant() const
sl@0
   918
	{
sl@0
   919
	__ASSERT_DEBUG(this != 0, __SQLITEPANIC(EFBufPanicNullThis));
sl@0
   920
	__ASSERT_DEBUG(iCapacity > 0, __SQLITEPANIC(EFBufPanicCapacity));
sl@0
   921
	__ASSERT_DEBUG(iBase != 0, __SQLITEPANIC(EFBufPanicNullBuf));
sl@0
   922
	__ASSERT_DEBUG(iLength >= 0 && iLength <= iCapacity, __SQLITEPANIC(EFBufPanicBufLen));
sl@0
   923
	__ASSERT_DEBUG(iFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
sl@0
   924
	__ASSERT_DEBUG(iFileSize == KFileSizeNotSet || iFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
sl@0
   925
	__ASSERT_DEBUG(iFile.SubSessionHandle() != 0, __SQLITEPANIC(EFBufPanicFileHandle));
sl@0
   926
	__ASSERT_DEBUG(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, __SQLITEPANIC(EFBufPanicNextReadFilePos));
sl@0
   927
	__ASSERT_DEBUG(iNextReadFilePosHits >= 0, __SQLITEPANIC(EFBufPanicNextReadFilePosHits));
sl@0
   928
	__ASSERT_DEBUG(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, __SQLITEPANIC(EFBufPanicFileBlockSize));
sl@0
   929
	}
sl@0
   930
	
sl@0
   931
#endif