First public contribution.
1 // Copyright (c) 2008-2010 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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
15 #include "FileBuf64.h"
16 #include "OstTraceDefinitions.h"
17 #ifdef OST_TRACE_COMPILER_IN_USE
18 #include "FileBuf64Traces.h"
20 #include "SqliteTraceDef.h"
22 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
25 This constant is used for initializing the RFileBuf64::iFileSize data member and means that
26 the iFileSize is not yet initialized with the real file size value.
27 (RFileBuf64::iFileSize caches the file size value)
30 static const TInt KFileSizeNotSet = -1;
33 This constant is used as a default initializer for the RFileBuf64::iNextReadFilePos data member,
34 indicating that the "guessed" file read offset is invalid and should not be used.
37 static const TInt KNextReadFilePosNotSet = -1;
39 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40 /////////////////////////// FBUF INVARIANT ///////////////////////////////////////////////////////////////
41 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45 #define __FILEBUF64_INVARIANT() Invariant()
49 #define __FILEBUF64_INVARIANT() void(0)
53 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 /////////////////////////// RFileBuf64 /////////////////////////////////////////////////////////////////////
55 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58 Initializes RFileBuf64 data members with their default values.
60 @param aSize Max file buffer size (capacity) in bytes.
62 @panic Sqlite3 1 In _DEBUG mode - aSize is 0 or negative.
64 RFileBuf64::RFileBuf64(TInt aSize) :
67 iReadAheadSize(RFileBuf64::KDefaultReadAheadSize)
69 SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_RFILEBUF64, "FBuf;0x%X;RFileBuf64::RFileBuf64;aSize=%d;iReadAheadSize=%d", (TUint)this, aSize, iReadAheadSize));
70 __ASSERT_DEBUG(aSize > 0, __SQLITEPANIC(EFBufPanicCapacity));
74 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
75 If the file already exists, an error is returned.
76 If the resulting path does not exist, then the operation cannot proceed and the function returns an error code.
78 @param aFs The file server session.
79 @param aFileName The name of the file. Any path components (i.e. drive letter
80 or directory), which are not specified, are taken from
82 @param aFileMode The mode in which the file is opened. See TFileMode for details.
84 @return KErrNone if successful, otherwise one of the other system-wide error codes.
87 @see RFile64::Create()
89 @panic Sqlite3 7 In _DEBUG mode - Invalid aFs object (null file session handle).
90 @panic Sqlite3 10 In _DEBUG mode - Invalid file name length (zero file name length).
92 TInt RFileBuf64::Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
94 __ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
95 __ASSERT_DEBUG(aFileName.Length() > 0, __SQLITEPANIC(EFBufPanicFileNameLen));
97 TInt err = DoPreInit();
100 err = iFile.Create(aFs, aFileName, aFileMode);
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));
108 Initializes the RFileBuf64 object and opens an existing file that will be accessed through RFileBuf64 public interface.
109 If the file does not already exist, an error is returned.
111 @param aFs The file server session.
112 @param aFileName The name of the file. Any path components (i.e. drive letter
113 or directory), which are not specified, are taken from
115 @param aFileMode The mode in which the file is opened. See TFileMode for details.
117 @return KErrNone if successful, otherwise one of the other system-wide error codes.
122 @panic Sqlite3 7 In _DEBUG mode - Invalid aFs object (null file session handle).
123 @panic Sqlite3 10 In _DEBUG mode - Invalid file name length (zero file name length).
125 TInt RFileBuf64::Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode)
127 __ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
128 __ASSERT_DEBUG(aFileName.Length() > 0, __SQLITEPANIC(EFBufPanicFileNameLen));
130 TInt err = DoPreInit();
133 err = iFile.Open(aFs, aFileName, aFileMode);
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));
141 Initializes the RFileBuf64 object and creates and opens a temporary file with unique name that will be accessed through
142 RFileBuf64 public interface.
144 @param aFs The file server session.
145 @param aPath The directory in which the file is created.
146 @param aFileName On return, contains the full path and file name of the file.
147 The filename is guaranteed to be unique within the directory
149 @param aFileMode The mode in which the file is opened. The access mode is
150 automatically set to EFileWrite. See TFileMode for details.
152 @return KErrNone if successful, otherwise one of the other system-wide error codes.
157 @panic Sqlite3 7 In _DEBUG mode - Invalid aFs object (null file session handle).
159 TInt RFileBuf64::Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode)
161 __ASSERT_DEBUG(aFs.Handle() != 0, __SQLITEPANIC(EFBufPanicFsHandle));
163 TInt err = DoPreInit();
166 err = iFile.Temp(aFs, aPath, aFileName, aFileMode);
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));
174 Writes to the file the pending data (if the buffer contains pending data), closes the file and releases
175 the RFileBuf64 resources.
176 RFileBuf64::Flush() should be called before RFileBuf64::Close() to ensure that if there are pending data, they will
177 be written to the file and if the operation fails, the caller will be notified with an appropriate return error.
179 @see RFileBuf64::Flush()
181 void RFileBuf64::Close()
183 SQLITE_TRACE_FBUF(OstTraceExt2(TRACE_INTERNALS, RFILEBUF64_CLOSE, "FBuf;0x%X;RFileBuf64::Close;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle()));
184 if(iFile.SubSessionHandle() != 0 && iBase != 0)
186 (void)DoFileWrite2();
194 Calculates and sets optimal read-ahead buffer size.
195 aBlockSize and aReadRecBufSize values are retrieved by the caller from the file system.
197 Initialization rules:
198 Rule 1: If aReadRecBufSize is positive, bigger than the default read-ahead and
199 a power of two then the read-ahead value will be
200 initialized with aReadRecBufSize (if aReadRecBufSize is less than the buffer capacity otherwise
201 the buffer capacity will be used as a read-ahead value).
202 Rule 2: If rule#1 is not applicable then the same checks, as in rule#1, are performed this time for aBlockSize.
203 If aBlockSize passes the checks then it will be used as a read-ahead value.
205 @param aBlockSize The size of a file block in bytes
206 @param aReadRecBufSize The recommended buffer size for optimised reading performance
208 @return The new read-ahead value
210 @see TVolumeIOParamInfo
212 TInt RFileBuf64::SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize)
214 __FILEBUF64_INVARIANT();
215 if((aReadRecBufSize & (aReadRecBufSize - 1)) == 0 && aReadRecBufSize > RFileBuf64::KDefaultReadAheadSize)
217 iReadAheadSize = aReadRecBufSize > iCapacity ? iCapacity : aReadRecBufSize;
219 else if((aBlockSize & (aBlockSize - 1)) == 0 && aBlockSize > RFileBuf64::KDefaultReadAheadSize)
221 iReadAheadSize = aBlockSize > iCapacity ? iCapacity : aBlockSize;
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));
224 __FILEBUF64_INVARIANT();
225 return iReadAheadSize;
229 Reads from the file at the specified position (aFilePos).
230 If the data to be read is in the buffer, then the data will be taken from the buffer.
232 @param aFilePos Position of first byte to be read. This is an offset from
233 the start of the file.
234 If aPos is beyond the end of the file, the function returns
235 a zero length descriptor.
236 @param aDes Descriptor into which binary data is read. Any existing contents
237 are overwritten. On return, its length is set to the number of
240 @return KErrNone if successful, otherwise one of the other system-wide error codes.
242 @panic Sqlite3 4 In _DEBUG mode - negative aFilePos value.
243 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
245 @see RFileBuf64::Invariant()
247 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
249 __ASSERT_DEBUG(aFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
250 __FILEBUF64_INVARIANT();
252 //1. The output buffer max len is 0
253 if(aDes.MaxLength() == 0)
255 __FILEBUF64_INVARIANT();
258 //2. Initialize the "iFileSize" if it is not initialized yet
259 TInt err = DoFileSize();
262 __FILEBUF64_INVARIANT();
265 //3. Too big "read" request - read directly from the file
266 TInt len = aDes.MaxLength();
269 if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
270 {//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
271 err = DoFileWrite1(aFilePos);
275 err = iFile.Read(aFilePos, aDes);
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));
278 __FILEBUF64_INVARIANT();
281 //4. The requested data size is smaller than the buffer capacity
282 TUint8* outptr = const_cast <TUint8*> (aDes.Ptr());
283 while(len > 0 && err == KErrNone && aFilePos < iFileSize)
285 //1. If part or all of the data is in the buffer - copy the data to the target location
286 if(aFilePos >= iFilePos && aFilePos < (iFilePos + iLength))
288 TInt blocklen = Min(len, (iFilePos + iLength - aFilePos));
289 outptr = Mem::Copy(outptr, iBase + (aFilePos - iFilePos), blocklen);
291 aFilePos += blocklen;
293 //2. Perform a read-ahead operation
296 //Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
297 err = DoFileWrite1(aFilePos);
302 if(iNextReadFilePos != aFilePos)
303 {//Guessed read ahead was wrong. Direct "file read" operation
304 iNextReadFilePosHits = 0;
305 TPtr8 ptr2(outptr, len);
306 err = iFile.Read(aFilePos, ptr2);
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));
310 iNextReadFilePos = aFilePos + len;
311 len -= ptr2.Length();
315 //The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
316 const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize
317 if(iNextReadFilePosHits < KMaxReadFilePosHits)
319 ++iNextReadFilePosHits;
321 TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
322 TInt align = (aFilePos + len + maxReadAhead) & (iReadAheadSize - 1);
323 TInt readahead = maxReadAhead - align;
326 // if read-ahead doesn't cross block boundary do it all
327 readahead = maxReadAhead;
329 TPtr8 ptr(iBase, Min(iCapacity, (len + readahead)));
330 err = iFile.Read(aFilePos, ptr);
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));
335 iLength = ptr.Length();
336 iNextReadFilePos = iFilePos + iLength;
348 aDes.SetLength(aDes.MaxLength() - len);
349 __FILEBUF64_INVARIANT();
354 Writes to the file at the specified offset (aFilePos) within the file.
355 If certain conditions are met, the data will be stored in the buffer - no call to the file server.
357 @param aFilePos The offset from the start of the file at which the first byte is written.
358 If a position beyond the end of the file is specified, then
359 the write operation begins at the end of the file.
360 If the position has been locked, then the write fails.
362 @param aData The descriptor from which binary data is written. The function writes
363 the entire contents of aData to the file.
365 @return KErrNone if successful, otherwise one of the other system-wide error codes.
367 @panic Sqlite3 4 In _DEBUG mode - negative aFilePos value.
368 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
370 @see RFileBuf64::Invariant()
372 TInt RFileBuf64::Write(TInt64 aFilePos, const TDesC8& aData)
374 __ASSERT_DEBUG(aFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
375 __FILEBUF64_INVARIANT();
376 if(aData.Length() == 0)
378 __FILEBUF64_INVARIANT();
381 TInt err = DoFileSize();
384 __FILEBUF64_INVARIANT();
387 DoDiscardBufferedReadData();
388 const TUint8* data = aData.Ptr();
389 for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
391 //1. The new write pos is before the buffered file pos
392 if(aFilePos < iFilePos)
394 //If the new data sticks to/overlapps the old data and there is room in the buffer to move the old data
395 //toward the end, then the new data can be copied at the beginning of the buffer.
396 if((aFilePos + len) >= iFilePos && (iFilePos - aFilePos) <= (iCapacity - iLength))
398 (void)Mem::Copy(iBase + (iFilePos - aFilePos), iBase, iLength); //Make room - move the existing data toward the end
399 (void)Mem::Copy(iBase, data, len); //of the buffer. Stick the new data to the old data
400 iLength += (iFilePos - aFilePos);
401 iFilePos = aFilePos; //The new file pos is associated with the buffer
402 iFileSize = Max(iFileSize, (iFilePos + iLength));
403 len = 0; //No more new data
407 //The "aFilePos" is too far before the "iFilePos". Write the buffer and associate the new pos with the buffer
409 err = DoFileWrite2(aFilePos);
412 //2. The new write pos is after the associated file pos + the data length.
413 else if(aFilePos > (iFilePos + iLength))
415 if(aFilePos > iFileSize) //Beyond the end of the file
417 if((iFilePos + iLength) == iFileSize && (aFilePos - iFilePos) < iCapacity)
418 { //but within the buffer => extend the file with zeros.
419 Mem::FillZ(iBase + iLength, aFilePos - iFilePos - iLength);
420 iLength = aFilePos - iFilePos;
421 iFileSize = Max(iFileSize, (iFilePos + iLength));
425 //Beyond the end of the file and not in the buffer - set file size.
427 err = DoSetFileSize(aFilePos);
431 //Within the file, not in the buffer - write the buffer and associate the new file pos with the buffer
433 err = DoFileWrite2(aFilePos);
436 //3. The new write pos is in the buffer, but the data length is too big
437 // (For SQLite is OK, otherwise the whole block must be written to the file)
438 //4. The new write pos is in the buffer, the data entirely fits in the buffer
441 if(iCapacity == iLength) //The buffer is full. Write the buffer and associate the new file pos
443 err = DoFileWrite2(aFilePos);
447 TInt amount = Min(len, (iCapacity - (aFilePos - iFilePos)));
448 const TUint8* end = Mem::Copy(iBase + (aFilePos - iFilePos), data, amount);
449 iLength = Max(iLength, (end - iBase));
450 iFileSize = Max(iFileSize, (iFilePos + iLength));
458 __FILEBUF64_INVARIANT();
463 Gets the current file size.
465 @param aFileSize On return, the size of the file in bytes.
467 @return KErrNone if successful, otherwise one of the other system-wide error codes.
469 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
471 @see RFileBuf64::Invariant()
473 TInt RFileBuf64::Size(TInt64& aFileSize)
475 __FILEBUF64_INVARIANT();
476 TInt err = DoFileSize();
479 aFileSize = iFileSize;
481 __FILEBUF64_INVARIANT();
488 If the size of the file is reduced, data may be lost from the end of the file.
492 1. The current file position remains unchanged unless SetSize() reduces the size
493 of the file in such a way that the current file position is now beyond
494 the end of the file. In this case, the current file position is set to
497 2. If the file was not opened for writing, an error is returned.
499 @param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
501 @return KErrNone if successful, otherwise one of the other system-wide error codes.
503 @panic Sqlite3 5 In _DEBUG mode - negative aFileSize value.
504 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
506 @see RFileBuf64::Invariant()
508 TInt RFileBuf64::SetSize(TInt64 aFileSize)
510 __ASSERT_DEBUG(aFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
511 __FILEBUF64_INVARIANT();
512 return DoSetFileSize(aFileSize);
516 Locks a region within the file as defined by a range of bytes.
520 @param aFilePos Position in file from which to lock; this is the offset from the beginning of the file.
521 @param aLength Number of bytes to lock.
523 @return KErrNone if successful, otherwise one of the other system-wide error
526 TInt RFileBuf64::Lock(TInt64 aFilePos, TInt64 aLength) const
528 __FILEBUF64_INVARIANT();
529 TInt err = iFile.Lock(aFilePos, aLength);
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));
535 Unlocks a region within the file as defined by a range of bytes.
537 @see RFile64::UnLock()
539 @param aFilePos Position in file from which to unlock; this is the offset from the beginning of the file.
540 @param aLength Number of bytes to unlock.
542 @return KErrNone if successful, otherwise one of the other system-wide error codes.
544 TInt RFileBuf64::UnLock(TInt64 aFilePos, TInt64 aLength) const
546 __FILEBUF64_INVARIANT();
547 TInt err = iFile.UnLock(aFilePos, aLength);
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));
553 Writes the pending data and then flushes the file.
555 Although RFileBuf64::Close() also flushes internal buffers, it is better
556 to call RFileBuf64::Flush() before the file is closed. This is because Close() returns no
557 error information, so there is no way of telling whether the final data was
558 written to the file successfully or not.
560 @param aFlush The caller should call this function with aResetCachedFileSize parameter set,
561 when the buffer file is shared between threads.
563 @return KErrNone if successful, otherwise one of the other system-wide error codes.
565 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
567 @see RFileBuf64::Invariant()
569 TInt RFileBuf64::Flush(TBool aResetCachedFileSize /*= EFalse*/)
571 __FILEBUF64_INVARIANT();
572 TInt err = DoFileFlush();
573 if(aResetCachedFileSize && err == KErrNone)
574 {//Unset the iFileSize to force the file buffers used by the other threads to re-read the file size.
575 iFileSize = KFileSizeNotSet;
581 Gets information about the drive on which this file resides.
583 @param aDriveNumber On return, the drive number.
585 @param aDriveInfo On return, contains information describing the drive
586 and the medium mounted on it. The value of TDriveInfo::iType
587 shows whether the drive contains media.
589 @return KErrNone if successful, otherwise one of the other system-wide error codes.
591 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
593 @see RFileBuf64::Invariant()
595 TInt RFileBuf64::Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const
597 __FILEBUF64_INVARIANT();
598 TInt err = iFile.Drive(aDriveNumber, aDriveInfo);
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));
604 Initializes RFileBuf64 data members with their initial values.
605 Allocates memory for the file buffer.
607 @return KErrNone if successful,
608 KErrNoMemory out of memory;
610 TInt RFileBuf64::DoPreInit()
613 iReadAheadSize = RFileBuf64::KDefaultReadAheadSize;
614 iBase = static_cast <TUint8*> (User::Alloc(iCapacity));
615 return iBase ? KErrNone : KErrNoMemory;
619 Performs post-initialization of the RFileBuf64 object.
620 If aInitErr is not KErrNone, then the buffer memory will be released.
622 @param aInitErr The result of the performed before the call RFileBuf64 initialization.
624 void RFileBuf64::DoPostInit(TInt aInitErr)
626 if(aInitErr != KErrNone)
634 Discards the content of the RFileBuf64 object returning it to the state as if it has just been created.
636 void RFileBuf64::DoDiscard()
640 iFileSize = KFileSizeNotSet;
642 iNextReadFilePos = KNextReadFilePosNotSet;
643 iNextReadFilePosHits = 0;
647 Gets the current file size.
648 If iFileSize value is valid, then no call to the file server will be made.
649 Otherwise the file server will be called and the file size - stored (cached) in iFileSize data member for later use.
651 @return KErrNone if successful, otherwise one of the other system-wide error codes.
653 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
655 @see RFileBuf64::Invariant()
657 TInt RFileBuf64::DoFileSize()
659 __FILEBUF64_INVARIANT();
660 if(iFileSize != KFileSizeNotSet)
662 __FILEBUF64_INVARIANT();
665 TInt err = iFile.Size(iFileSize);
666 SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_DOFILESIZE, "FBuf;0x%X;RFileBuf64::DoFileSize;iFileSize=%lld;err=%d", (TUint)this, iFileSize, err));
671 __FILEBUF64_INVARIANT();
677 If the buffer contains pending data, the data will be written to the file
678 before the "set file size" operation, if certain conditions are met.
680 @param aFileSize The new size of the file, in bytes. This value must not be negative, otherwise the function raises a panic.
682 @return KErrNone if successful, otherwise one of the other system-wide error codes.
684 @panic Sqlite3 5 In _DEBUG mode - negative aFileSize value.
685 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
687 @see RFileBuf64::Invariant()
689 TInt RFileBuf64::DoSetFileSize(TInt64 aFileSize)
691 __ASSERT_DEBUG(aFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
692 __FILEBUF64_INVARIANT();
693 if(aFileSize < iFilePos)
698 //If the new file size is "in" the buffer then change the "iLength"
699 else if(aFileSize < (iFilePos + iLength))
701 iLength = aFileSize - iFilePos;
703 TInt err = iFile.SetSize(aFileSize);
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));
711 iFileSize = aFileSize;
713 __FILEBUF64_INVARIANT();
718 Writes the pending data and flushes the file.
720 @return KErrNone if successful, otherwise one of the other system-wide error codes.
722 See RFileBuf64::Invariant() for possible panics that may occur when this method is called.
724 @see RFileBuf64::Invariant()
726 TInt RFileBuf64::DoFileFlush()
728 __FILEBUF64_INVARIANT();
729 TInt err = DoFileWrite2();//Write the buffer if the iDirty flag is set. Do not preserve the buffer content and file pos.
732 __FILEBUF64_INVARIANT();
736 SQLITE_TRACE_FBUF(OstTraceExt3(TRACE_INTERNALS, RFILEBUF64_DOFILEFLUSH, "FBuf;0x%X;RFileBuf64::DoFileFlush;iFileSize=%lld;err=%d", (TUint)this, iFileSize, err));
742 __FILEBUF64_INVARIANT();
747 Writes the buffered data to the file if the iLength value is > 0.
748 If the file write operation extends the file, the iFileSize data member will be initialized with the new file size.
749 No changes occur in the other data member values.
751 @return KErrNone if successful, otherwise one of the other system-wide error codes.
753 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
755 @see RFileBuf64::DoFileWrite1()
756 @see RFileBuf64::DoFileWrite2()
757 @see RFileBuf64::Invariant()
759 TInt RFileBuf64::DoFileWrite()
761 __FILEBUF64_INVARIANT();
764 __FILEBUF64_INVARIANT();
767 TPtrC8 data(iBase, iLength);
768 TInt err = iFile.Write(iFilePos, data);
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));
772 iFileSize = Max(iFileSize, (iFilePos + iLength));
778 __FILEBUF64_INVARIANT();
783 Writes the buffered data to the file if the iDirty flag is set.
784 If the iDirty flag is set and the file write operation was successful, the iFilePos will be initialized with
785 the aNewFilePos value, the iLength will be set to 0.
786 This method is called from RFileBuf64::Read(), where:
787 - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
788 with aNewFilePos - the offset in the file where the next file read operation should start from;
789 - if the buffer contains cached reads, then nothing happens, the buffer content will be kept;
790 The function resets the iDirty flag.
792 @param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
793 the aNewFilePos value.
795 @return KErrNone if successful, otherwise one of the other system-wide error codes.
797 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
799 @panic Sqlite3 4 In _DEBUG mode - negative aNewFilePos value.
801 @see RFileBuf64::Read()
802 @see RFileBuf64::DoFileWrite()
803 @see RFileBuf64::DoFileWrite2()
804 @see RFileBuf64::Invariant()
806 TInt RFileBuf64::DoFileWrite1(TInt64 aNewFilePos)
808 __ASSERT_DEBUG(aNewFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
809 __FILEBUF64_INVARIANT();
816 iFilePos = aNewFilePos;
821 __FILEBUF64_INVARIANT();
826 Writes the buffered data to the file if the iDirty flag is set.
827 If the file write operation was successful or if the iDirty flag was not set, the iFilePos will be initialized with
828 the aNewFilePos value, the iLength will be set to 0.
829 This method is called from RFileBuf64::Write() an other RFileBuf64 methods (but not from RFileBuf64::Read()), where:
830 - if the buffer contains cached writes (iDirty flag is set), the buffer has to be flushed and iFilePos initialized
831 with aNewFilePos - the offset in the file for which the write data will be cached in the buffer;
832 - if the buffer contains cached reads, then the buffer content will be destroyed, iFilePos initialized with aNewFilePos
833 and iLength set to 0;
834 The function resets the iDirty flag.
835 The difference between RFileBuf64::DoFileWrite1() and RFileBuf64::DoFileWrite2() is:
836 - RFileBuf64::DoFileWrite1() perserves the buffer content if iDirty is not set;
837 - RFileBuf64::DoFileWrite2() always destroys the buffer content and initializes iFilePos;
839 @param aNewFilePos If the buffer is successfully written to the file the iFilePos data member will be initialized with
840 the aNewFilePos value.
842 @return KErrNone if successful, otherwise one of the other system-wide error codes.
844 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
846 @panic Sqlite3 4 In _DEBUG mode - negative aNewFilePos value.
848 @see RFileBuf64::Write()
849 @see RFileBuf64::DoFileWrite()
850 @see RFileBuf64::DoFileWrite1()
851 @see RFileBuf64::Invariant()
853 TInt RFileBuf64::DoFileWrite2(TInt64 aNewFilePos)
855 __ASSERT_DEBUG(aNewFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
856 __FILEBUF64_INVARIANT();
864 iFilePos = aNewFilePos;
868 __FILEBUF64_INVARIANT();
873 This function discards the buffer content if the buffer contains cached read data.
874 The function is called from RFileBuf64::Write(), because if the buffer contains cached read data,
875 they cannot be mixed with the cached write data.
876 Reason: for example the buffer contains 8Kb cached read data from file offset 0.
877 The data write request is 10 bytes at offset 4000. The write data will be cached,
878 because the buffer contains data from from this file area: [0..8192].
879 The iDirty flag will be set. Later when RFileBuf64::Flush() is called, the whole
880 8Kb buffer will be written. There is nothing wrong with that, the file content will be consistent.
881 But from performance point of view: 8Kb written vs. 10 bytes written - that may badly impact the performance.
883 @see RFileBuf64::Write()
885 See RFileBuf64::Invariant() for other possible panics that may occur when this method is called.
887 void RFileBuf64::DoDiscardBufferedReadData()
889 __FILEBUF64_INVARIANT();
890 if(!iDirty && iLength > 0)
894 iNextReadFilePos = KNextReadFilePosNotSet;
895 iNextReadFilePosHits = 0;
897 __FILEBUF64_INVARIANT();
903 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
904 (except the init/destroy methods).
906 @panic Sqlite3 11 In _DEBUG mode - null "this" pointer.
907 @panic Sqlite3 1 In _DEBUG mode - negative iCapacity value.
908 @panic Sqlite3 2 In _DEBUG mode - the buffer pointer is null (possible the buffer is not allocated or already destroyed).
909 @panic Sqlite3 3 In _DEBUG mode - invalid iLength value (negative or bigger than iCapacity).
910 @panic Sqlite3 4 In _DEBUG mode - negative iFilePos value.
911 @panic Sqlite3 5 In _DEBUG mode - set but negative iFileSize value.
912 @panic Sqlite3 6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
913 @panic Sqlite3 13 In _DEBUG mode - set but negative iNextReadFilePos value.
914 @panic Sqlite3 14 In _DEBUG mode - negative iNextReadFilePosHits value.
915 @panic Sqlite3 15 In _DEBUG mode - iReadAheadSize is negative or is not power of two.
917 void RFileBuf64::Invariant() const
919 __ASSERT_DEBUG(this != 0, __SQLITEPANIC(EFBufPanicNullThis));
920 __ASSERT_DEBUG(iCapacity > 0, __SQLITEPANIC(EFBufPanicCapacity));
921 __ASSERT_DEBUG(iBase != 0, __SQLITEPANIC(EFBufPanicNullBuf));
922 __ASSERT_DEBUG(iLength >= 0 && iLength <= iCapacity, __SQLITEPANIC(EFBufPanicBufLen));
923 __ASSERT_DEBUG(iFilePos >= 0, __SQLITEPANIC(EFBufPanicFilePos));
924 __ASSERT_DEBUG(iFileSize == KFileSizeNotSet || iFileSize >= 0, __SQLITEPANIC(EFBufPanicFileSize));
925 __ASSERT_DEBUG(iFile.SubSessionHandle() != 0, __SQLITEPANIC(EFBufPanicFileHandle));
926 __ASSERT_DEBUG(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, __SQLITEPANIC(EFBufPanicNextReadFilePos));
927 __ASSERT_DEBUG(iNextReadFilePosHits >= 0, __SQLITEPANIC(EFBufPanicNextReadFilePosHits));
928 __ASSERT_DEBUG(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, __SQLITEPANIC(EFBufPanicFileBlockSize));