persistentstorage/sqlite3api/OsLayer/FileBuf64.h
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 #ifndef FILEBUF64_H
       
    16 #define FILEBUF64_H
       
    17 
       
    18 #include <f32file.h>
       
    19 #include <f32file64.h>
       
    20 
       
    21 //Forward declaration
       
    22 struct MFileInitializer64;
       
    23 
       
    24 /**
       
    25 The RFileBuf64 class provides buffered file read/write operations on a single RFile64 object.
       
    26 RFileBuf64::Read() and RFileBuf64::Write() methods may boost the performance of the read/write file operations up to 30% 
       
    27 if compared to their RFile64 equivalents. Especially this is true in the case of a set of sequential read or write
       
    28 operations when the file offset of operation N+1 is the end file offset of operation N plus one byte.
       
    29 
       
    30 The RFileBuf64 public methods declarations match the declarations of the most often used RFile64 public methods.
       
    31 That makes the source code migration from RFile64 to RFileBuf64 easier (or from RFileBuf64 to RFile64).
       
    32 
       
    33 The RFileBuf64 capabilities are similar to those of the RFileBuf class, except the fact that RFileBuf
       
    34 uses 32-bit file offsets, RFileBuf64 uses 64-bit file offsets and RFileBuf64 provides optimised read-ahead operations,
       
    35 crafted especially for the case when RFileBuf64 is used with a page based database management system (like SQLite).
       
    36 
       
    37 Usage notes:
       
    38 @code
       
    39 	- an object of RFileBuf64 type must be defined first, specifying the max size (capacity) of the buffer as a parameter
       
    40 	  of the constructor:
       
    41 	  
       
    42 	  	RFileBuf64 fbuf(<N>);//<N> is the buffer capacity in bytes
       
    43 	  	
       
    44 	- the second step is to initialize the just defined RFileBuf64 object by calling one of the "resource acquisition"
       
    45 	  methods: RFileBuf64::Create(), RFileBuf64::Open() or RFileBuf64::Temp().
       
    46 	  
       
    47 	  In details, to create a file and access it through a RFileBuf64 object:
       
    48 	  
       
    49 	  	RFs fs;
       
    50 	  	//initialize the file session
       
    51 	  	...
       
    52 	  	RFileBuf64 fbuf(<N>);									//<N> is the buffer capacity in bytes
       
    53 	  	TInt err = fbuf.Create(fs, <file name>, <file mode>);
       
    54 	  	//check the error
       
    55 	  	
       
    56 	  To open an existing file and access it through a RFileBuf64 object:
       
    57 
       
    58 	  	RFs fs;
       
    59 	  	//initialize the file session
       
    60 	  	...
       
    61 	  	RFileBuf64 fbuf(<N>);									//<N> is the buffer capacity in bytes
       
    62 	  	TInt err = fbuf.Open(fs, <file name>, <file mode>);
       
    63 	  	//check the error
       
    64 	  
       
    65 	  To create a temporary file and access it through a RFileBuf64 object:
       
    66 
       
    67 	  	RFs fs;
       
    68 	  	//initialize the file session
       
    69 	  	...
       
    70 	  	RFileBuf64 fbuf(<N>);									//<N> is the buffer capacity in bytes
       
    71 	  	TInt err = fbuf.Temp(fs, <path>, <file name>, <file mode>);
       
    72 	  	//check the error
       
    73 	  
       
    74 	- if the RFileBuf64 object is initialised successfully, now the public RFileBuf64 methods can be called to perform
       
    75 	  requested operations on the file:
       
    76 	  
       
    77 	  	err = fbuf.Write(<file pos>, <data>);
       
    78 	  	//check the error
       
    79 	  	....
       
    80 	  	err = fbuf.Read(<file pos>, <buf>);
       
    81 	  	//check the error
       
    82 	  	....
       
    83 	  Note: do not forget to call RFileBuf64::Flush() at the moment when you want to ensure that the file data
       
    84 	  	    (possibly buffered) is really written to the file.
       
    85 
       
    86 	- The final step is to close the RFileBuf64 object and the corresponding file thus realising the used resouces:
       
    87 	
       
    88 		fbuf.Close();
       
    89 	  
       
    90 @endcode
       
    91 
       
    92 Implementation notes: the current RFileBuf64 implementation is optimised for use by the SQLite OS porting layer.
       
    93 	After a detailed investigation of the performed by SQLite file read/write operations it was found that buffering of
       
    94 	two or more logical file writes into a single physical file write has a positive impact (as expected) on the performance 
       
    95 	of the database write operations. But the picture is quite different for the file read operations. The database data is
       
    96 	organised in pages with fixed size. After a database is created and set of insert/update/delete operations is performed 
       
    97 	on it, after a while the database pages (identified by their numbers) are not sequential in the database file and using
       
    98 	a read-ahead buffer with fixed size makes no sense because for each "page read" request of N bytes, the RFileBuf64 object
       
    99 	will read up to K bytes, K >= N, where K is the read-ahead value in bytes. Since the "read page" requests in general are 
       
   100 	not sequential (relatively to the page numbers), obviously the read-ahead data is wasted and the "read page" performance
       
   101 	is negatively impacted. This observation is true in general except two cases:
       
   102 		- sequential scan of a database table;
       
   103 		- reading of a BLOB column;
       
   104 	In these two cases it is likely that the table/blob data occupies pages with sequential numbers located in a continuous
       
   105 	file area. Then if a read-ahead buffer is used that will have a positive impact on the "read page" performance, because
       
   106 	the number of the read IPC calls to the file server will be reduced.
       
   107 	In order to satisfy those two orthogonal requirements, the RFileBuf64 implementation uses a "read file offset prediction"
       
   108 	algorithm:
       
   109 		- The file buffer object is created with 0 read-ahead value;
       
   110 		- After each "file read" operation the buffer implementation "guesses" what might be the file offset of the
       
   111 		  next file read operation (it is possible because the database data is organised in pages with fixed size and
       
   112 		  generally all "file read" requests are for reading a database page) and stores the value in one of its data members;
       
   113 		- If the file offset of the next file read operation matches the "guessed" offset, the read-ahead value is changed from
       
   114 		  0 to 1024 bytes (1024 bytes is the default database page size);
       
   115 		- Every next match of the "guessed" file offset value doubles the read-ahead value. But the max read-ahead value is
       
   116 		  capped by the capacity of the buffer;
       
   117 		- If the file offset of the next file read operation does not match the "guessed" file offset, then the read-ahead
       
   118 		  value is set back to 0;
       
   119 	Shortly, depending of the nature of the file read requests, the RFileBuf64 object will dynamically change the read-ahead
       
   120 	value thus minimising the amount of the wasted read data and improving the "file read" performance in general.
       
   121 
       
   122 @see RFile64
       
   123 @see RFileBuf
       
   124 
       
   125 @internalComponent
       
   126 */
       
   127 class RFileBuf64
       
   128 	{
       
   129 	enum {KDefaultReadAheadSize = 1024};//Default size in bytes of the read-ahead buffer
       
   130 	
       
   131 public:
       
   132 	RFileBuf64(TInt aSize);
       
   133 
       
   134 	TInt Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode);
       
   135 	TInt Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode);
       
   136 	TInt Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode);
       
   137 	void Close();
       
   138 	TInt SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize);
       
   139 
       
   140 	TInt Read(TInt64 aFilePos, TDes8& aDes);
       
   141 	TInt Write(TInt64 aFilePos, const TDesC8& aData);
       
   142 
       
   143 	TInt Size(TInt64& aFileSize);
       
   144 	TInt SetSize(TInt64 aFileSize);
       
   145 	TInt Lock(TInt64 aFilePos, TInt64 aLength) const;
       
   146 	TInt UnLock(TInt64 aFilePos, TInt64 aLength) const;
       
   147 	TInt Flush(TBool aResetCachedFileSize = EFalse);
       
   148 
       
   149 	TInt Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const;
       
   150 
       
   151 private:
       
   152 	void Invariant() const;
       
   153 	TInt DoInit(MFileInitializer64& aFileInitializer);
       
   154 	void DoDiscard();
       
   155 	TInt DoFileSize();
       
   156 	TInt DoSetFileSize(TInt64 aFileSize);
       
   157 	TInt DoFileFlush();
       
   158 	TInt DoFileWrite();
       
   159 	TInt DoFileWrite1(TInt64 aNewFilePos);
       
   160 	TInt DoFileWrite2(TInt64 aNewFilePos = 0LL);
       
   161 	void DoDiscardBufferedReadData();
       
   162 	
       
   163 private:
       
   164 	//Buffer related
       
   165 	const TInt	iCapacity;				//The buffer size. Indicates how much data can be put in.
       
   166 	TUint8*		iBase;					//Pointer to the beginning of the buffer.
       
   167 	TInt		iLength;				//The length of the data currently held in the buffer.
       
   168 	//File related
       
   169 	TInt64		iFilePos;				//The file position associated with the beginning of the buffer.
       
   170 	TInt64		iFileSize;				//The file size.
       
   171 	RFile64		iFile;					//The file object.
       
   172 	//Read-ahead related
       
   173 	TBool		iDirty;					//The buffer contains pending data to be written to the file
       
   174 	TInt64		iNextReadFilePos;		//The guessed file position of the next "file read" operation
       
   175 	TInt		iNextReadFilePosHits;	//How many times the guessed file position of the "file read" operation was correct
       
   176 	TInt		iReadAheadSize;
       
   177 
       
   178 	//Profiler related
       
   179 #ifdef _SQLPROFILER
       
   180 public:
       
   181     inline void	ProfilerReset()
       
   182     	{
       
   183     	iFileReadCount = 0; iFileReadAmount = 0; iFileWriteCount = 0; iFileWriteAmount = 0; iFileSizeCount = 0; iFileSetSizeCount = 0; iFileFlushCount = 0;
       
   184     	}
       
   185 	TInt		iFileReadCount;		//The number of the non-buffered file reads (RFile64::Read() calls).
       
   186 	TInt64		iFileReadAmount;	//The amount of the data read from the file.
       
   187 	TInt		iFileWriteCount;	//The number of the non-buffered file writes (RFile64::Write() calls).
       
   188 	TInt64		iFileWriteAmount;	//The amount of the data written to the file.
       
   189 	TInt		iFileSizeCount;		//The number of non-buffered RFile64::Size() calls.
       
   190 	TInt		iFileSetSizeCount;	//The number of non-buffered RFile64::SetSize() calls.
       
   191 	TInt		iFileFlushCount;	//The number of RFile64::Flush() calls.
       
   192 #endif
       
   193 	
       
   194 	};
       
   195 
       
   196 #endif//FILEBUF64_H