persistentstorage/sql/OsLayer/FileBuf64.h
changeset 0 08ec8eefde2f
child 10 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(), RFileBuf64::Temp() or RFileBuf64::AdoptFromClient().
       
    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 	  To open a file from handle and access it through a RFileBuf64 object:
       
    75 
       
    76 	  	RFs fs;
       
    77 	  	//initialize the file session
       
    78 	  	...
       
    79 	  	RFileBuf64 fbuf(<N>);									//<N> is the buffer capacity in bytes
       
    80 	  	TInt err = fbuf.AdoptFromClient(<msg>, <fs handle index>, <file handle index>);
       
    81 	  	//check the error
       
    82 
       
    83 	- if the RFileBuf64 object is initialised successfully, now the public RFileBuf64 methods can be called to perform
       
    84 	  requested operations on the file:
       
    85 	  
       
    86 	  	err = fbuf.Write(<file pos>, <data>);
       
    87 	  	//check the error
       
    88 	  	....
       
    89 	  	err = fbuf.Read(<file pos>, <buf>);
       
    90 	  	//check the error
       
    91 	  	....
       
    92 	  Note: do not forget to call RFileBuf64::Flush() at the moment when you want to ensure that the file data
       
    93 	  	    (possibly buffered) is really written to the file.
       
    94 
       
    95 	- The final step is to close the RFileBuf64 object and the corresponding file thus realising the used resouces:
       
    96 	
       
    97 		fbuf.Close();
       
    98 	  
       
    99 @endcode
       
   100 
       
   101 Implementation notes: the current RFileBuf64 implementation is optimised for use by the SQLite OS porting layer.
       
   102 	After a detailed investigation of the performed by SQLite file read/write operations it was found that buffering of
       
   103 	two or more logical file writes into a single physical file write has a positive impact (as expected) on the performance 
       
   104 	of the database write operations. But the picture is quite different for the file read operations. The database data is
       
   105 	organised in pages with fixed size. After a database is created and set of insert/update/delete operations is performed 
       
   106 	on it, after a while the database pages (identified by their numbers) are not sequential in the database file and using
       
   107 	a read-ahead buffer with fixed size makes no sense because for each "page read" request of N bytes, the RFileBuf64 object
       
   108 	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 
       
   109 	not sequential (relatively to the page numbers), obviously the read-ahead data is wasted and the "read page" performance
       
   110 	is negatively impacted. This observation is true in general except two cases:
       
   111 		- sequential scan of a database table;
       
   112 		- reading of a BLOB column;
       
   113 	In these two cases it is likely that the table/blob data occupies pages with sequential numbers located in a continuous
       
   114 	file area. Then if a read-ahead buffer is used that will have a positive impact on the "read page" performance, because
       
   115 	the number of the read IPC calls to the file server will be reduced.
       
   116 	In order to satisfy those two orthogonal requirements, the RFileBuf64 implementation uses a "read file offset prediction"
       
   117 	algorithm:
       
   118 		- The file buffer object is created with 0 read-ahead value;
       
   119 		- After each "file read" operation the buffer implementation "guesses" what might be the file offset of the
       
   120 		  next file read operation (it is possible because the database data is organised in pages with fixed size and
       
   121 		  generally all "file read" requests are for reading a database page) and stores the value in one of its data members;
       
   122 		- If the file offset of the next file read operation matches the "guessed" offset, the read-ahead value is changed from
       
   123 		  0 to 1024 bytes (1024 bytes is the default database page size);
       
   124 		- Every next match of the "guessed" file offset value doubles the read-ahead value. But the max read-ahead value is
       
   125 		  capped by the capacity of the buffer;
       
   126 		- If the file offset of the next file read operation does not match the "guessed" file offset, then the read-ahead
       
   127 		  value is set back to 0;
       
   128 	Shortly, depending of the nature of the file read requests, the RFileBuf64 object will dynamically change the read-ahead
       
   129 	value thus minimising the amount of the wasted read data and improving the "file read" performance in general.
       
   130 
       
   131 @see RFile64
       
   132 @see RFileBuf
       
   133 
       
   134 @internalComponent
       
   135 */
       
   136 class RFileBuf64
       
   137 	{
       
   138 	friend void SetReadAheadSizeTest();
       
   139 	
       
   140 	enum {KDefaultReadAheadSize = 1024};//Default size in bytes of the read-ahead buffer
       
   141 	
       
   142 public:
       
   143 	RFileBuf64(TInt aSize);
       
   144 
       
   145 	TInt Create(RFs& aFs, const TDesC& aFileName, TUint aFileMode);
       
   146 	TInt Open(RFs& aFs, const TDesC& aFileName, TUint aFileMode);
       
   147 	TInt Temp(RFs& aFs, const TDesC& aPath, TFileName& aFileName, TUint aFileMode);
       
   148 	TInt AdoptFromClient(const RMessage2& aMsg, TInt aFsIndex, TInt aFileIndex);
       
   149 	void Close();
       
   150 	TInt SetReadAheadSize(TInt aBlockSize, TInt aReadRecBufSize);
       
   151 
       
   152 	TInt Read(TInt64 aFilePos, TDes8& aDes);
       
   153 	TInt Write(TInt64 aFilePos, const TDesC8& aData);
       
   154 
       
   155 	TInt Size(TInt64& aFileSize);
       
   156 	TInt SetSize(TInt64 aFileSize);
       
   157 	TInt Flush();
       
   158 
       
   159 	TInt Drive(TInt& aDriveNumber, TDriveInfo& aDriveInfo) const;
       
   160 
       
   161 private:
       
   162 	void Invariant() const;
       
   163 	TInt DoInit(MFileInitializer64& aFileInitializer);
       
   164 	void DoDiscard();
       
   165 	TInt DoFileSize();
       
   166 	TInt DoSetFileSize(TInt64 aFileSize);
       
   167 	TInt DoFileFlush();
       
   168 	TInt DoFileWrite();
       
   169 	TInt DoFileWrite1(TInt64 aNewFilePos);
       
   170 	TInt DoFileWrite2(TInt64 aNewFilePos = 0LL);
       
   171 	void DoDiscardBufferedReadData();
       
   172 	
       
   173 private:
       
   174 	//Buffer related
       
   175 	const TInt	iCapacity;				//The buffer size. Indicates how much data can be put in.
       
   176 	TUint8*		iBase;					//Pointer to the beginning of the buffer.
       
   177 	TInt		iLength;				//The length of the data currently held in the buffer.
       
   178 	//File related
       
   179 	TInt64		iFilePos;				//The file position associated with the beginning of the buffer.
       
   180 	TInt64		iFileSize;				//The file size.
       
   181 	RFile64		iFile;					//The file object.
       
   182 	//Read-ahead related
       
   183 	TBool		iDirty;					//The buffer contains pending data to be written to the file
       
   184 	TInt64		iNextReadFilePos;		//The guessed file position of the next "file read" operation
       
   185 	TInt		iNextReadFilePosHits;	//How many times the guessed file position of the "file read" operation was correct
       
   186 	TInt		iReadAheadSize;
       
   187 
       
   188 	//Profiler related
       
   189 #ifdef _SQLPROFILER
       
   190 public:
       
   191     void		ProfilerReset();
       
   192     
       
   193 	TInt		iFileReadCount;		//The number of the non-buffered file reads (RFile64::Read() calls).
       
   194 	TInt64		iFileReadAmount;	//The amount of the data read from the file.
       
   195 	TInt		iFileWriteCount;	//The number of the non-buffered file writes (RFile64::Write() calls).
       
   196 	TInt64		iFileWriteAmount;	//The amount of the data written to the file.
       
   197 	TInt		iFileSizeCount;		//The number of non-buffered RFile64::Size() calls.
       
   198 	TInt		iFileSetSizeCount;	//The number of non-buffered RFile64::SetSize() calls.
       
   199 	TInt		iFileFlushCount;	//The number of RFile64::Flush() calls.
       
   200 #endif
       
   201 	
       
   202 	};
       
   203 
       
   204 #endif//FILEBUF64_H