os/persistentdata/persistentstorage/sqlite3api/OsLayer/FileBuf64.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/OsLayer/FileBuf64.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,931 @@
     1.4 +// Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +#include "FileBuf64.h"
    1.19 +#include "OstTraceDefinitions.h"
    1.20 +#ifdef OST_TRACE_COMPILER_IN_USE
    1.21 +#include "FileBuf64Traces.h"
    1.22 +#endif
    1.23 +#include "SqliteTraceDef.h"
    1.24 +
    1.25 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.26 +
    1.27 +/**
    1.28 +This constant is used for initializing the RFileBuf64::iFileSize data member and means that
    1.29 +the iFileSize is not yet initialized with the real file size value. 
    1.30 +(RFileBuf64::iFileSize caches the file size value)
    1.31 +@internalComponent
    1.32 +*/
    1.33 +static const TInt KFileSizeNotSet = -1;
    1.34 +
    1.35 +/**
    1.36 +This constant is used as a default initializer for the RFileBuf64::iNextReadFilePos data member,
    1.37 +indicating that the "guessed" file read offset is invalid and should not be used.
    1.38 +@internalComponent
    1.39 +*/
    1.40 +static const TInt KNextReadFilePosNotSet = -1;
    1.41 +
    1.42 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.43 +///////////////////////////        FBUF INVARIANT      ///////////////////////////////////////////////////////////////
    1.44 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.45 +
    1.46 +#ifdef _DEBUG
    1.47 +
    1.48 +#define __FILEBUF64_INVARIANT() Invariant()
    1.49 +
    1.50 +#else //_DEBUG
    1.51 +
    1.52 +#define __FILEBUF64_INVARIANT() void(0)
    1.53 +
    1.54 +#endif//_DEBUG
    1.55 +
    1.56 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.57 +///////////////////////////        RFileBuf64    /////////////////////////////////////////////////////////////////////
    1.58 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.59 +	
    1.60 +/**
    1.61 +Initializes RFileBuf64 data members with their default values.
    1.62 +
    1.63 +@param aSize Max file buffer size (capacity) in bytes.
    1.64 +
    1.65 +@panic Sqlite3 1 In _DEBUG mode - aSize is 0 or negative.
    1.66 +*/
    1.67 +RFileBuf64::RFileBuf64(TInt aSize) :
    1.68 +	iCapacity(aSize),
    1.69 +	iBase(NULL),
    1.70 +	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize)
    1.71 +	{
    1.72 +	SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_RFILEBUF64, "FBuf;0x%X;RFileBuf64::RFileBuf64;aSize=%d;iReadAheadSize=%d", (TUint)this, aSize, iReadAheadSize));
    1.73 +	__ASSERT_DEBUG(aSize > 0, __SQLITEPANIC(EFBufPanicCapacity));
    1.74 +	}
    1.75 +
    1.76 +/**
    1.77 +Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
    1.78 +If the file already exists, an error is returned.
    1.79 +If the resulting path does not exist, then the operation cannot proceed and the function returns an error code.
    1.80 +
    1.81 +@param aFs       The file server session.
    1.82 +@param aFileName The name of the file. Any path components (i.e. drive letter
    1.83 +                 or directory), which are not specified, are taken from
    1.84 +                 the session path.
    1.85 +@param aFileMode The mode in which the file is opened. See TFileMode for details.
    1.86 +
    1.87 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
    1.88 +
    1.89 +@see TFileMode
    1.90 +@see RFile64::Create()
    1.91 +
    1.92 +@panic Sqlite3  7 In _DEBUG mode - Invalid aFs object (null file session handle).
    1.93 +@panic Sqlite3 10 In _DEBUG mode - Invalid file name length (zero file name length).
    1.94 +*/
    1.95 +TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
    1.96 +	{
    1.97 +	__ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
    1.98 +	__ASSERT_DEBUG(aFileName.Length() > 0, __SQLITEPANIC(EFBufPanicFileNameLen));
    1.99 +	
   1.100 +	TInt err = DoPreInit();
   1.101 +	if(err == KErrNone)
   1.102 +	    {
   1.103 +	    err = iFile.Create(aFs, aFileName, aFileMode);
   1.104 +	    }
   1.105 +	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));
   1.106 +	DoPostInit(err);
   1.107 +	return err;
   1.108 +	}
   1.109 +
   1.110 +/**
   1.111 +Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
   1.112 +If the file does not already exist, an error is returned.
   1.113 +
   1.114 +@param aFs       The file server session.
   1.115 +@param aFileName The name of the file. Any path components (i.e. drive letter
   1.116 +                 or directory), which are not specified, are taken from
   1.117 +                 the session path.
   1.118 +@param aFileMode The mode in which the file is opened. See TFileMode for details.
   1.119 +
   1.120 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.121 +
   1.122 +@see TFileMode
   1.123 +@see RFile64::Open()
   1.124 +
   1.125 +@panic Sqlite3  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   1.126 +@panic Sqlite3 10 In _DEBUG mode - Invalid file name length (zero file name length).
   1.127 +*/
   1.128 +TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
   1.129 +	{
   1.130 +	__ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
   1.131 +	__ASSERT_DEBUG(aFileName.Length() > 0, __SQLITEPANIC(EFBufPanicFileNameLen));
   1.132 +	
   1.133 +    TInt err = DoPreInit();
   1.134 +    if(err == KErrNone)
   1.135 +        {
   1.136 +        err = iFile.Open(aFs, aFileName, aFileMode);
   1.137 +        }
   1.138 +	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));
   1.139 +    DoPostInit(err);
   1.140 +	return err;
   1.141 +	}
   1.142 +
   1.143 +/**
   1.144 +Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through 
   1.145 +RFileBuf64 public interface.
   1.146 +
   1.147 +@param aFs       The file server session.
   1.148 +@param aPath     The directory in which the file is created.
   1.149 +@param aFileName On return, contains the full path and file name of the file.
   1.150 +                 The filename is guaranteed to be unique within the directory
   1.151 +                 specified by aPath.
   1.152 +@param aFileMode The mode in which the file is opened. The access mode is
   1.153 +                 automatically set to EFileWrite. See TFileMode for details.
   1.154 +
   1.155 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.156 +
   1.157 +@see TFileMode
   1.158 +@see RFile64::Temp()
   1.159 +
   1.160 +@panic Sqlite3  7 In _DEBUG mode - Invalid aFs object (null file session handle).
   1.161 +*/
   1.162 +TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
   1.163 +	{
   1.164 +	__ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
   1.165 +	
   1.166 +    TInt err = DoPreInit();
   1.167 +    if(err == KErrNone)
   1.168 +        {
   1.169 +        err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
   1.170 +        }
   1.171 +	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));
   1.172 +    DoPostInit(err);
   1.173 +	return err;
   1.174 +	}
   1.175 +
   1.176 +/**
   1.177 +Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
   1.178 +the RFileBuf64 resources. 
   1.179 +RFileBuf64::Flush() should be called before RFileBuf64::Close() to ensure that if there are pending data, they will
   1.180 +be written to the file and if the operation fails, the caller will be notified with an appropriate return error.
   1.181 +
   1.182 +@see RFileBuf64::Flush()
   1.183 +*/
   1.184 +void RFileBuf64::Close()
   1.185 +	{
   1.186 +	SQLITE_TRACE_FBUF(OstTraceExt2(TRACE_INTERNALS, RFILEBUF64_CLOSE, "FBuf;0x%X;RFileBuf64::Close;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle()));
   1.187 +	if(iFile.SubSessionHandle() != 0 && iBase != 0)
   1.188 +		{
   1.189 +		(void)DoFileWrite2();
   1.190 +		}
   1.191 +	iFile.Close();
   1.192 +	User::Free(iBase);
   1.193 +	iBase = 0;
   1.194 +	}
   1.195 +
   1.196 +/**
   1.197 +Calculates and sets optimal read-ahead buffer size.
   1.198 +aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
   1.199 +
   1.200 +Initialization rules:
   1.201 +Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and 
   1.202 +        a power of two then the read-ahead value will be
   1.203 +        initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise
   1.204 +        the buffer capacity will be used as a read-ahead value). 
   1.205 +Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize.
   1.206 +        If aBlockSize passes the checks then it will be used as a read-ahead value. 
   1.207 +
   1.208 +@param aBlockSize The size of a file block in bytes
   1.209 +@param aReadRecBufSize The recommended buffer size for optimised reading performance
   1.210 +
   1.211 +@return The new read-ahead value
   1.212 +
   1.213 +@see TVolumeIOParamInfo
   1.214 +*/
   1.215 +TInt RFileBuf64::SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize)
   1.216 +	{
   1.217 +	__FILEBUF64_INVARIANT();
   1.218 +	if((aReadRecBufSize & (aReadRecBufSize - 1)) == 0 && aReadRecBufSize > RFileBuf64::KDefaultReadAheadSize)
   1.219 +		{
   1.220 +		iReadAheadSize = aReadRecBufSize > iCapacity ? iCapacity : aReadRecBufSize;
   1.221 +		}
   1.222 +	else if((aBlockSize & (aBlockSize - 1)) == 0 && aBlockSize > RFileBuf64::KDefaultReadAheadSize)
   1.223 +		{
   1.224 +		iReadAheadSize = aBlockSize > iCapacity ? iCapacity : aBlockSize;
   1.225 +		}
   1.226 +	SQLITE_TRACE_FBUF(OstTraceExt4(TRACE_INTERNALS, RFILEBUF64_SETREADAHEADSIZE, "FBuf;0x%X;RFileBuf64::SetReadAheadSize;aBlockSize=%d;aReadRecBufSize=%d;iReadAheadSize=%d", (TUint)this, aBlockSize, aReadRecBufSize, iReadAheadSize));
   1.227 +	__FILEBUF64_INVARIANT();
   1.228 +	return iReadAheadSize;
   1.229 +	}
   1.230 +
   1.231 +/**
   1.232 +Reads from the file at the specified position (aFilePos).
   1.233 +If the data to be read is in the buffer, then the data will be taken from the buffer.
   1.234 +
   1.235 +@param aFilePos Position of first byte to be read.  This is an offset from
   1.236 +            the start of the file. 
   1.237 +            If aPos is beyond the end of the file, the function returns
   1.238 +            a zero length descriptor.
   1.239 +@param aDes Descriptor into which binary data is read. Any existing contents 
   1.240 +            are overwritten. On return, its length is set to the number of
   1.241 +            bytes read.
   1.242 +            
   1.243 +@return KErrNone if successful, otherwise one of the other system-wide error  codes.
   1.244 +
   1.245 +@panic Sqlite3  4 In _DEBUG mode - negative aFilePos value.
   1.246 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.247 +
   1.248 +@see RFileBuf64::Invariant()
   1.249 +*/
   1.250 +TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
   1.251 +	{
   1.252 +	__ASSERT_DEBUG(aFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
   1.253 +	__FILEBUF64_INVARIANT();
   1.254 +	aDes.SetLength(0);
   1.255 +	//1. The output buffer max len is 0
   1.256 +	if(aDes.MaxLength() == 0)
   1.257 +		{
   1.258 +		__FILEBUF64_INVARIANT();
   1.259 +		return KErrNone;	
   1.260 +		}
   1.261 +	//2. Initialize the "iFileSize" if it is not initialized yet
   1.262 +	TInt err = DoFileSize();
   1.263 +	if(err != KErrNone)
   1.264 +		{
   1.265 +		__FILEBUF64_INVARIANT();
   1.266 +		return err;	
   1.267 +		}
   1.268 +	//3. Too big "read" request - read directly from the file
   1.269 +	TInt len = aDes.MaxLength();
   1.270 +	if(len > iCapacity)
   1.271 +		{
   1.272 +		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
   1.273 +			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   1.274 +			err = DoFileWrite1(aFilePos);
   1.275 +			}
   1.276 +		if(err == KErrNone)
   1.277 +			{
   1.278 +			err = iFile.Read(aFilePos, aDes);
   1.279 +			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));
   1.280 +			}
   1.281 +		__FILEBUF64_INVARIANT();
   1.282 +		return err;
   1.283 +		}
   1.284 +	//4. The requested data size is smaller than the buffer capacity
   1.285 +	TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
   1.286 +	while(len > 0 && err == KErrNone && aFilePos < iFileSize)
   1.287 +		{
   1.288 +		//1. If part or all of the data is in the buffer - copy the data to the target location
   1.289 +		if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
   1.290 +			{
   1.291 +			TInt blocklen = Min(len, (iFilePos + iLength - aFilePos));
   1.292 +			outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen);
   1.293 +			len -= blocklen;
   1.294 +			aFilePos += blocklen;
   1.295 +			}
   1.296 +		//2. Perform a read-ahead operation
   1.297 +		else
   1.298 +			{
   1.299 +			//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   1.300 +			err = DoFileWrite1(aFilePos);
   1.301 +			if(err != KErrNone)
   1.302 +				{
   1.303 +				break;	
   1.304 +				}
   1.305 +			if(iNextReadFilePos != aFilePos)
   1.306 +				{//Guessed read ahead was wrong. Direct "file read" operation
   1.307 +				iNextReadFilePosHits = 0;
   1.308 +				TPtr8 ptr2(outptr, len);
   1.309 +				err = iFile.Read(aFilePos, ptr2);
   1.310 +				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));
   1.311 +				if(err == KErrNone)
   1.312 +					{
   1.313 +					iNextReadFilePos = aFilePos + len;
   1.314 +					len -= ptr2.Length();
   1.315 +					}
   1.316 +				break;
   1.317 +				}
   1.318 +			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
   1.319 +			const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize
   1.320 +			if(iNextReadFilePosHits < KMaxReadFilePosHits)
   1.321 +				{
   1.322 +				++iNextReadFilePosHits;
   1.323 +				}
   1.324 +			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
   1.325 +			TInt align = (aFilePos + len + maxReadAhead) & (iReadAheadSize - 1);
   1.326 +			TInt readahead = maxReadAhead - align;
   1.327 +			if(readahead < 0)
   1.328 +				{
   1.329 +				// if read-ahead doesn't cross block boundary do it all
   1.330 +				readahead = maxReadAhead;	
   1.331 +				}
   1.332 +			TPtr8 ptr(iBase, Min(iCapacity, (len + readahead)));
   1.333 +			err = iFile.Read(aFilePos, ptr);
   1.334 +			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));
   1.335 +			if(err == KErrNone)
   1.336 +				{
   1.337 +				iFilePos = aFilePos;
   1.338 +				iLength = ptr.Length();	
   1.339 +				iNextReadFilePos = iFilePos + iLength;
   1.340 +				if(iLength == 0)
   1.341 +					{
   1.342 +					break;	
   1.343 +					}
   1.344 +				}
   1.345 +			else
   1.346 +				{
   1.347 +				DoDiscard();	
   1.348 +				}
   1.349 +			}
   1.350 +		}
   1.351 +	aDes.SetLength(aDes.MaxLength() - len);
   1.352 +	__FILEBUF64_INVARIANT();
   1.353 +	return err;
   1.354 +	}
   1.355 +	
   1.356 +/**
   1.357 +Writes to the file at the specified offset (aFilePos) within the file.
   1.358 +If certain conditions are met, the data will be stored in the buffer - no call to the file server.
   1.359 +
   1.360 +@param aFilePos The offset from the start of the file at which the first byte is written. 
   1.361 +                If a position beyond the end of the file is specified, then
   1.362 +                the write operation begins at the end of the file.
   1.363 +                If the position has been locked, then the write fails.
   1.364 +            
   1.365 +@param aData The descriptor from which binary data is written. The function writes 
   1.366 +             the entire contents of aData to the file.
   1.367 +
   1.368 +@return KErrNone if successful, otherwise one of the other system-wide error  codes.
   1.369 +
   1.370 +@panic Sqlite3  4 In _DEBUG mode - negative aFilePos value.
   1.371 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.372 +
   1.373 +@see RFileBuf64::Invariant()
   1.374 +*/
   1.375 +TInt RFileBuf64::Write(TInt64 aFilePos, const TDesC8& aData)
   1.376 +	{
   1.377 +	__ASSERT_DEBUG(aFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
   1.378 +	__FILEBUF64_INVARIANT();
   1.379 +	if(aData.Length() == 0)
   1.380 +		{
   1.381 +		__FILEBUF64_INVARIANT();
   1.382 +		return KErrNone;	
   1.383 +		}
   1.384 +	TInt err = DoFileSize();
   1.385 +	if(err != KErrNone)
   1.386 +		{
   1.387 +		__FILEBUF64_INVARIANT();
   1.388 +		return err;	
   1.389 +		}
   1.390 +	DoDiscardBufferedReadData();
   1.391 +	const TUint8* data = aData.Ptr();
   1.392 +	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
   1.393 +		{
   1.394 +		//1. The new write pos is before the buffered file pos
   1.395 +		if(aFilePos < iFilePos)
   1.396 +			{
   1.397 +			//If the new data sticks to/overlapps the old data and there is room in the buffer to move the old data 
   1.398 +			//toward the end, then the new data can be copied at the beginning of the buffer.
   1.399 +			if((aFilePos + len) >= iFilePos && (iFilePos - aFilePos) <= (iCapacity - iLength))
   1.400 +				{
   1.401 +				(void)Mem::Copy(iBase + (iFilePos - aFilePos), iBase, iLength);	//Make room - move the existing data toward the end
   1.402 +				(void)Mem::Copy(iBase, data, len);								//of the buffer. Stick the new data to the old data
   1.403 +				iLength += (iFilePos - aFilePos);
   1.404 +				iFilePos = aFilePos;										//The new file pos is associated with the buffer
   1.405 +				iFileSize = Max(iFileSize, (iFilePos + iLength));
   1.406 +				len = 0;													//No more new data
   1.407 +				iDirty = ETrue;	
   1.408 +				}
   1.409 +			else
   1.410 +			//The "aFilePos" is too far before the "iFilePos". Write the buffer and associate the new pos with the buffer
   1.411 +				{
   1.412 +				err = DoFileWrite2(aFilePos);
   1.413 +				}
   1.414 +			}
   1.415 +		//2. The new write pos is after the associated file pos + the data length.
   1.416 +		else if(aFilePos > (iFilePos + iLength))
   1.417 +			{
   1.418 +			if(aFilePos > iFileSize)											//Beyond the end of the file
   1.419 +				{
   1.420 +				if((iFilePos + iLength) == iFileSize && (aFilePos - iFilePos) < iCapacity)	
   1.421 +					{															//but within the buffer => extend the file with zeros.
   1.422 +					Mem::FillZ(iBase + iLength, aFilePos - iFilePos - iLength);
   1.423 +					iLength = aFilePos - iFilePos;
   1.424 +					iFileSize = Max(iFileSize, (iFilePos + iLength));
   1.425 +					iDirty = ETrue;	
   1.426 +					}
   1.427 +				else									
   1.428 +				//Beyond the end of the file and not in the buffer - set file size.
   1.429 +					{
   1.430 +					err = DoSetFileSize(aFilePos);
   1.431 +					}
   1.432 +				}
   1.433 +			else										
   1.434 +			//Within the file, not in the buffer - write the buffer and associate the new file pos with the buffer
   1.435 +				{
   1.436 +				err = DoFileWrite2(aFilePos);
   1.437 +				}
   1.438 +			}
   1.439 +		//3. The new write pos is in the buffer, but the data length is too big
   1.440 +		//   (For SQLite is OK, otherwise the whole block must be written to the file)
   1.441 +		//4. The new write pos is in the buffer, the data entirely fits in the buffer
   1.442 +		else
   1.443 +			{
   1.444 +			if(iCapacity == iLength)			//The buffer is full. Write the buffer and associate the new file pos
   1.445 +				{
   1.446 +				err = DoFileWrite2(aFilePos);
   1.447 +				}
   1.448 +			if(err == KErrNone)
   1.449 +				{
   1.450 +				TInt amount = Min(len, (iCapacity - (aFilePos - iFilePos)));
   1.451 +				const TUint8* end = Mem::Copy(iBase + (aFilePos - iFilePos), data, amount);
   1.452 +				iLength = Max(iLength, (end - iBase));
   1.453 +				iFileSize = Max(iFileSize, (iFilePos + iLength));
   1.454 +				len -= amount;
   1.455 +				data += amount;
   1.456 +				aFilePos += amount;
   1.457 +				iDirty = ETrue;	
   1.458 +				}
   1.459 +			}
   1.460 +		}
   1.461 +	__FILEBUF64_INVARIANT();
   1.462 +	return err;
   1.463 +	}
   1.464 +	
   1.465 +/**
   1.466 +Gets the current file size.
   1.467 +
   1.468 +@param aFileSize On return, the size of the file in bytes.
   1.469 +
   1.470 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.471 +
   1.472 +See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
   1.473 +
   1.474 +@see RFileBuf64::Invariant()
   1.475 +*/
   1.476 +TInt RFileBuf64::Size(TInt64& aFileSize)
   1.477 +	{
   1.478 +	__FILEBUF64_INVARIANT();
   1.479 +	TInt err = DoFileSize();
   1.480 +	if(err == KErrNone)
   1.481 +		{
   1.482 +		aFileSize = iFileSize;
   1.483 +		}
   1.484 +	__FILEBUF64_INVARIANT();
   1.485 +	return err;
   1.486 +	}
   1.487 +
   1.488 +/**
   1.489 +Sets the file size.
   1.490 +
   1.491 +If the size of the file is reduced, data may be lost from the end of the file.
   1.492 +
   1.493 +Note:
   1.494 +
   1.495 +1. The current file position remains unchanged unless SetSize() reduces the size 
   1.496 +   of the file in such a way that the current file position is now beyond
   1.497 +   the end of the file. In this case, the current file position is set to
   1.498 +   the end of file. 
   1.499 +
   1.500 +2. If the file was not opened for writing, an error is returned.
   1.501 +
   1.502 +@param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
   1.503 +
   1.504 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.505 +
   1.506 +@panic Sqlite3  5 In _DEBUG mode - negative aFileSize value.
   1.507 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.508 +
   1.509 +@see RFileBuf64::Invariant()
   1.510 +*/
   1.511 +TInt RFileBuf64::SetSize(TInt64 aFileSize)
   1.512 +	{
   1.513 +	__ASSERT_DEBUG(aFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
   1.514 +	__FILEBUF64_INVARIANT();
   1.515 +	return DoSetFileSize(aFileSize);
   1.516 +	}
   1.517 +
   1.518 +/**
   1.519 +Locks a region within the file as defined by a range of bytes.
   1.520 +
   1.521 +@see RFile64::Lock()
   1.522 +
   1.523 +@param aFilePos Position in file from which to lock; this is the  offset from the beginning of the file.
   1.524 +@param aLength  Number of bytes to lock.
   1.525 +
   1.526 +@return KErrNone if successful, otherwise one of the other  system-wide error 
   1.527 +        codes.
   1.528 +*/
   1.529 +TInt RFileBuf64::Lock(TInt64 aFilePos, TInt64 aLength) const
   1.530 +	{
   1.531 +	__FILEBUF64_INVARIANT();
   1.532 +	TInt err = iFile.Lock(aFilePos, aLength);
   1.533 +	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));
   1.534 +	return err;
   1.535 +	}
   1.536 +	
   1.537 +/**
   1.538 +Unlocks a region within the file as defined by a range of bytes.
   1.539 +
   1.540 +@see RFile64::UnLock()
   1.541 +
   1.542 +@param aFilePos Position in file from which to unlock; this is the  offset from the beginning of the file.
   1.543 +@param aLength  Number of bytes to unlock.
   1.544 +
   1.545 +@return KErrNone if successful, otherwise one of the other  system-wide error codes.
   1.546 +*/
   1.547 +TInt RFileBuf64::UnLock(TInt64 aFilePos, TInt64 aLength) const
   1.548 +	{
   1.549 +	__FILEBUF64_INVARIANT();
   1.550 +	TInt err = iFile.UnLock(aFilePos, aLength);
   1.551 +	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));
   1.552 +	return err;
   1.553 +	}
   1.554 +
   1.555 +/**
   1.556 +Writes the pending data and then flushes the file.
   1.557 +
   1.558 +Although RFileBuf64::Close() also flushes internal buffers, it is better
   1.559 +to call RFileBuf64::Flush() before the file is closed. This is because Close() returns no 
   1.560 +error information, so there is no way of telling whether the final data was 
   1.561 +written to the file successfully or not.
   1.562 +
   1.563 +@param aFlush The caller should call this function with aResetCachedFileSize parameter set, 
   1.564 +			  when the buffer file is shared between threads.
   1.565 +
   1.566 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.567 +
   1.568 +See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
   1.569 +
   1.570 +@see RFileBuf64::Invariant()
   1.571 +*/
   1.572 +TInt RFileBuf64::Flush(TBool aResetCachedFileSize /*= EFalse*/)
   1.573 +	{
   1.574 +	__FILEBUF64_INVARIANT();
   1.575 +	TInt err = DoFileFlush();
   1.576 +	if(aResetCachedFileSize && err == KErrNone)
   1.577 +		{//Unset the iFileSize to force the file buffers used by the other threads to re-read the file size.
   1.578 +		iFileSize = KFileSizeNotSet;
   1.579 +		}
   1.580 +	return err;
   1.581 +	}
   1.582 +
   1.583 +/**
   1.584 +Gets information about the drive on which this file resides.
   1.585 + 
   1.586 +@param aDriveNumber On return, the drive number.
   1.587 +
   1.588 +@param aDriveInfo   On return, contains information describing the drive
   1.589 +                    and the medium mounted on it. The value of TDriveInfo::iType
   1.590 +                    shows whether the drive contains media.
   1.591 +
   1.592 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.593 +
   1.594 +See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
   1.595 +
   1.596 +@see RFileBuf64::Invariant()
   1.597 +*/
   1.598 +TInt RFileBuf64::Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const
   1.599 +	{
   1.600 +	__FILEBUF64_INVARIANT();
   1.601 +	TInt err = iFile.Drive(aDriveNumber, aDriveInfo);
   1.602 +	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));
   1.603 +	return err;
   1.604 +	}
   1.605 +
   1.606 +/**
   1.607 +Initializes RFileBuf64 data members with their initial values.   
   1.608 +Allocates memory for the file buffer. 
   1.609 + 
   1.610 +@return KErrNone if successful, 
   1.611 +        KErrNoMemory out of memory;
   1.612 +*/
   1.613 +TInt RFileBuf64::DoPreInit()
   1.614 +    {
   1.615 +    DoDiscard();
   1.616 +    iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
   1.617 +    iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
   1.618 +    return iBase ? KErrNone : KErrNoMemory; 
   1.619 +    }
   1.620 +
   1.621 +/**
   1.622 +Performs post-initialization of the RFileBuf64 object.   
   1.623 +If aInitErr is not KErrNone, then the buffer memory will be released.
   1.624 +
   1.625 +@param aInitErr The result of the performed before the call RFileBuf64 initialization.
   1.626 +*/
   1.627 +void RFileBuf64::DoPostInit(TInt aInitErr)
   1.628 +    {
   1.629 +    if(aInitErr != KErrNone)
   1.630 +        {
   1.631 +        User::Free(iBase);
   1.632 +        iBase = 0;
   1.633 +        }
   1.634 +    }
   1.635 +
   1.636 +/**
   1.637 +Discards the content of the RFileBuf64 object returning it to the state as if it has just been created. 
   1.638 +*/
   1.639 +void RFileBuf64::DoDiscard()
   1.640 +	{
   1.641 +	iLength = 0;
   1.642 +	iFilePos = 0;
   1.643 +	iFileSize = KFileSizeNotSet;
   1.644 +	iDirty = EFalse;
   1.645 +	iNextReadFilePos = KNextReadFilePosNotSet;
   1.646 +	iNextReadFilePosHits = 0;
   1.647 +	}
   1.648 +
   1.649 +/**
   1.650 +Gets the current file size. 
   1.651 +If iFileSize value is valid, then no call to the file server will be made.
   1.652 +Otherwise the file server will be called and the file size - stored (cached) in iFileSize data member for later use.
   1.653 +
   1.654 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.655 +
   1.656 +See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
   1.657 +
   1.658 +@see RFileBuf64::Invariant()
   1.659 +*/
   1.660 +TInt RFileBuf64::DoFileSize()
   1.661 +	{
   1.662 +	__FILEBUF64_INVARIANT();
   1.663 +	if(iFileSize != KFileSizeNotSet)
   1.664 +		{
   1.665 +		__FILEBUF64_INVARIANT();
   1.666 +		return KErrNone;
   1.667 +		}
   1.668 +	TInt err = iFile.Size(iFileSize);
   1.669 +	SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_DOFILESIZE, "FBuf;0x%X;RFileBuf64::DoFileSize;iFileSize=%lld;err=%d", (TUint)this, iFileSize, err));
   1.670 +	if(err != KErrNone)
   1.671 +		{
   1.672 +		DoDiscard();
   1.673 +		}
   1.674 +	__FILEBUF64_INVARIANT();
   1.675 +	return err;
   1.676 +	}
   1.677 +
   1.678 +/**
   1.679 +Sets the file size.
   1.680 +If the buffer contains pending data, the data will be written to the file 
   1.681 +before the "set file size" operation, if certain conditions are met. 
   1.682 +
   1.683 +@param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
   1.684 +
   1.685 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.686 +
   1.687 +@panic Sqlite3  5 In _DEBUG mode - negative aFileSize value.
   1.688 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.689 +
   1.690 +@see RFileBuf64::Invariant()
   1.691 +*/
   1.692 +TInt RFileBuf64::DoSetFileSize(TInt64 aFileSize)
   1.693 +	{
   1.694 +	__ASSERT_DEBUG(aFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
   1.695 +	__FILEBUF64_INVARIANT();
   1.696 +	if(aFileSize < iFilePos)
   1.697 +		{
   1.698 +		iDirty = EFalse;
   1.699 +		iLength = 0;	
   1.700 +		}
   1.701 +	//If the new file size is "in" the buffer then change the "iLength"
   1.702 +	else if(aFileSize < (iFilePos + iLength))
   1.703 +		{
   1.704 +		iLength = aFileSize - iFilePos;
   1.705 +		}
   1.706 +	TInt err = iFile.SetSize(aFileSize);
   1.707 +	SQLITE_TRACE_FBUF(OstTraceExt4(TRACE_INTERNALS, RFILEBUF64_DOSETFILESIZE, "FBuf;0x%X;RFileBuf64::DoSetFileSize;iFileSize=%lld;aFileSize=%lld;err=%d", (TUint)this, iFileSize, aFileSize, err));
   1.708 +	if(err != KErrNone)
   1.709 +		{
   1.710 +		DoDiscard();
   1.711 +		}
   1.712 +	else
   1.713 +		{
   1.714 +		iFileSize = aFileSize;
   1.715 +		}
   1.716 +	__FILEBUF64_INVARIANT();
   1.717 +	return err;
   1.718 +	}
   1.719 +
   1.720 +/**
   1.721 +Writes the pending data and flushes the file.
   1.722 +
   1.723 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.724 +
   1.725 +See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
   1.726 +
   1.727 +@see RFileBuf64::Invariant()
   1.728 +*/
   1.729 +TInt RFileBuf64::DoFileFlush()
   1.730 +	{
   1.731 +	__FILEBUF64_INVARIANT();
   1.732 +	TInt err = DoFileWrite2();//Write the buffer if the iDirty flag is set. Do not preserve the buffer content and file pos.
   1.733 +	if(err != KErrNone)
   1.734 +		{
   1.735 +		__FILEBUF64_INVARIANT();
   1.736 +		return err;	
   1.737 +		}
   1.738 +	err = iFile.Flush();
   1.739 +	SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_DOFILEFLUSH, "FBuf;0x%X;RFileBuf64::DoFileFlush;iFileSize=%lld;err=%d", (TUint)this, iFileSize, err));
   1.740 +	if(err != KErrNone)
   1.741 +		{
   1.742 +		DoDiscard();
   1.743 +		}
   1.744 +	iLength = 0;
   1.745 +	__FILEBUF64_INVARIANT();
   1.746 +	return err;
   1.747 +	}
   1.748 +
   1.749 +/**
   1.750 +Writes the buffered data to the file if the iLength value is > 0.
   1.751 +If the file write operation extends the file, the iFileSize data member will be initialized with the new file size.
   1.752 +No changes occur in the other data member values.
   1.753 +
   1.754 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.755 +
   1.756 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.757 +
   1.758 +@see RFileBuf64::DoFileWrite1()
   1.759 +@see RFileBuf64::DoFileWrite2()
   1.760 +@see RFileBuf64::Invariant()
   1.761 +*/
   1.762 +TInt RFileBuf64::DoFileWrite()
   1.763 +	{
   1.764 +	__FILEBUF64_INVARIANT();
   1.765 +	if(iLength == 0)
   1.766 +		{
   1.767 +		__FILEBUF64_INVARIANT();
   1.768 +		return KErrNone;	
   1.769 +		}
   1.770 +	TPtrC8 data(iBase, iLength);		
   1.771 +	TInt err = iFile.Write(iFilePos, data);
   1.772 +	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));
   1.773 +	if(err == KErrNone)
   1.774 +		{
   1.775 +		iFileSize = Max(iFileSize, (iFilePos + iLength));
   1.776 +		}
   1.777 +	else
   1.778 +		{
   1.779 +		DoDiscard();
   1.780 +		}
   1.781 +	__FILEBUF64_INVARIANT();
   1.782 +	return err;
   1.783 +	}
   1.784 +
   1.785 +/**
   1.786 +Writes the buffered data to the file if the iDirty flag is set.
   1.787 +If the iDirty flag is set and the file write operation was successful, the iFilePos will be initialized with
   1.788 +the aNewFilePos value, the iLength will be set to 0.
   1.789 +This method is called from RFileBuf64::Read(), where:
   1.790 + - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
   1.791 +   with aNewFilePos - the offset in the file where the next file read operation should start from;
   1.792 + - if the buffer contains cached reads, then nothing happens, the buffer content will be kept;
   1.793 +The function resets the iDirty flag.
   1.794 +
   1.795 +@param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
   1.796 +				   the aNewFilePos value.
   1.797 +
   1.798 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.799 +
   1.800 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.801 +				   
   1.802 +@panic Sqlite3  4 In _DEBUG mode - negative aNewFilePos value.
   1.803 +
   1.804 +@see RFileBuf64::Read()
   1.805 +@see RFileBuf64::DoFileWrite()
   1.806 +@see RFileBuf64::DoFileWrite2()
   1.807 +@see RFileBuf64::Invariant()
   1.808 +*/
   1.809 +TInt RFileBuf64::DoFileWrite1(TInt64 aNewFilePos)
   1.810 +	{
   1.811 +	__ASSERT_DEBUG(aNewFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
   1.812 +	__FILEBUF64_INVARIANT();
   1.813 +	TInt err = KErrNone;
   1.814 +	if(iDirty)
   1.815 +		{
   1.816 +		err = DoFileWrite();
   1.817 +		if(err == KErrNone)	
   1.818 +			{
   1.819 +			iFilePos = aNewFilePos;
   1.820 +			iLength = 0;
   1.821 +			}
   1.822 +		}
   1.823 +	iDirty = EFalse;
   1.824 +	__FILEBUF64_INVARIANT();
   1.825 +	return err;		
   1.826 +	}
   1.827 +
   1.828 +/*
   1.829 +Writes the buffered data to the file if the iDirty flag is set.
   1.830 +If the file write operation was successful or if the iDirty flag was not set, the iFilePos will be initialized with
   1.831 +the aNewFilePos value, the iLength will be set to 0.
   1.832 +This method is called from RFileBuf64::Write() an other RFileBuf64 methods (but not from RFileBuf64::Read()), where:
   1.833 + - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
   1.834 +   with aNewFilePos - the offset in the file for which the write data will be cached in the buffer;
   1.835 + - if the buffer contains cached reads, then the buffer content will be destroyed, iFilePos initialized with aNewFilePos
   1.836 +   and iLength set to 0;
   1.837 +The function resets the iDirty flag.
   1.838 +The difference between RFileBuf64::DoFileWrite1() and RFileBuf64::DoFileWrite2() is:
   1.839 + - RFileBuf64::DoFileWrite1() perserves the buffer content if iDirty is not set;
   1.840 + - RFileBuf64::DoFileWrite2() always destroys the buffer content and initializes iFilePos;
   1.841 +
   1.842 +@param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
   1.843 +				   the aNewFilePos value.
   1.844 +
   1.845 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.846 +
   1.847 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.848 +				   
   1.849 +@panic Sqlite3  4 In _DEBUG mode - negative aNewFilePos value.
   1.850 +
   1.851 +@see RFileBuf64::Write()
   1.852 +@see RFileBuf64::DoFileWrite()
   1.853 +@see RFileBuf64::DoFileWrite1()
   1.854 +@see RFileBuf64::Invariant()
   1.855 +*/
   1.856 +TInt RFileBuf64::DoFileWrite2(TInt64 aNewFilePos)
   1.857 +	{
   1.858 +	__ASSERT_DEBUG(aNewFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
   1.859 +	__FILEBUF64_INVARIANT();
   1.860 +	TInt err = KErrNone;
   1.861 +	if(iDirty)
   1.862 +		{
   1.863 +		err = DoFileWrite();
   1.864 +		}
   1.865 +	if(err == KErrNone)	
   1.866 +		{
   1.867 +		iFilePos = aNewFilePos;
   1.868 +		iLength = 0;
   1.869 +		}
   1.870 +	iDirty = EFalse;
   1.871 +	__FILEBUF64_INVARIANT();
   1.872 +	return err;
   1.873 +	}
   1.874 +
   1.875 +/**
   1.876 +This function discards the buffer content if the buffer contains cached read data.
   1.877 +The function is called from RFileBuf64::Write(), because if the buffer contains cached read data,
   1.878 +they cannot be mixed with the cached write data.
   1.879 +Reason: for example the buffer contains 8Kb cached read data from file offset 0.
   1.880 +        The data write request is 10 bytes at offset 4000. The write data will be cached,
   1.881 +        because the buffer contains data from from this file area: [0..8192].
   1.882 +        The iDirty flag will be set. Later when RFileBuf64::Flush() is called, the whole
   1.883 +        8Kb buffer will be written. There is nothing wrong with that, the file content will be consistent.
   1.884 +        But from performance point of view: 8Kb written vs. 10 bytes written - that may badly impact the performance.
   1.885 +
   1.886 +@see RFileBuf64::Write()
   1.887 +
   1.888 +See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
   1.889 +*/
   1.890 +void RFileBuf64::DoDiscardBufferedReadData()
   1.891 +	{
   1.892 +	__FILEBUF64_INVARIANT();
   1.893 +	if(!iDirty && iLength > 0)
   1.894 +		{
   1.895 +		iLength = 0;
   1.896 +		iFilePos = 0;
   1.897 +		iNextReadFilePos = KNextReadFilePosNotSet;
   1.898 +		iNextReadFilePosHits = 0;
   1.899 +		}
   1.900 +	__FILEBUF64_INVARIANT();
   1.901 +	}
   1.902 +
   1.903 +#ifdef _DEBUG
   1.904 +
   1.905 +/**
   1.906 +RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
   1.907 +(except the init/destroy methods).
   1.908 +
   1.909 +@panic Sqlite3  11 In _DEBUG mode - null "this" pointer.
   1.910 +@panic Sqlite3   1 In _DEBUG mode - negative iCapacity value.
   1.911 +@panic Sqlite3   2 In _DEBUG mode - the buffer pointer is null (possible the buffer is not allocated or already destroyed).
   1.912 +@panic Sqlite3   3 In _DEBUG mode - invalid iLength value (negative or bigger than iCapacity).
   1.913 +@panic Sqlite3   4 In _DEBUG mode - negative iFilePos value.
   1.914 +@panic Sqlite3   5 In _DEBUG mode - set but negative iFileSize value.
   1.915 +@panic Sqlite3   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
   1.916 +@panic Sqlite3  13 In _DEBUG mode - set but negative iNextReadFilePos value.
   1.917 +@panic Sqlite3  14 In _DEBUG mode - negative iNextReadFilePosHits value.
   1.918 +@panic Sqlite3  15 In _DEBUG mode - iReadAheadSize is negative or is not power of two.
   1.919 +*/
   1.920 +void RFileBuf64::Invariant() const
   1.921 +	{
   1.922 +	__ASSERT_DEBUG(this != 0, __SQLITEPANIC(EFBufPanicNullThis));
   1.923 +	__ASSERT_DEBUG(iCapacity > 0, __SQLITEPANIC(EFBufPanicCapacity));
   1.924 +	__ASSERT_DEBUG(iBase != 0, __SQLITEPANIC(EFBufPanicNullBuf));
   1.925 +	__ASSERT_DEBUG(iLength >= 0 && iLength <= iCapacity, __SQLITEPANIC(EFBufPanicBufLen));
   1.926 +	__ASSERT_DEBUG(iFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
   1.927 +	__ASSERT_DEBUG(iFileSize == KFileSizeNotSet || iFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
   1.928 +	__ASSERT_DEBUG(iFile.SubSessionHandle() != 0, __SQLITEPANIC(EFBufPanicFileHandle));
   1.929 +	__ASSERT_DEBUG(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, __SQLITEPANIC(EFBufPanicNextReadFilePos));
   1.930 +	__ASSERT_DEBUG(iNextReadFilePosHits >= 0, __SQLITEPANIC(EFBufPanicNextReadFilePosHits));
   1.931 +	__ASSERT_DEBUG(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, __SQLITEPANIC(EFBufPanicFileBlockSize));
   1.932 +	}
   1.933 +	
   1.934 +#endif