persistentstorage/sql/SRC/Common/SqlBufFlat.h
changeset 0 08ec8eefde2f
child 23 26645d81f48d
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2006-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 
       
    16 #ifndef __SQLBUFFLAT_H__
       
    17 #define __SQLBUFFLAT_H__
       
    18 
       
    19 #include <e32base.h>
       
    20 #include "SqlPanic.h"
       
    21 
       
    22 //Forward declarations
       
    23 class TSqlBufRIterator;
       
    24 class CSqlSecurityPolicy;
       
    25 class TSqlSecurityPolicyIterator;
       
    26 
       
    27 #ifdef _DEBUG
       
    28 const TUint64 KSqlBufFlatMagicValue = 0xAA11BB44221199EEULL;//TInt64 for 8-byte alignment
       
    29 #define SQLFLATBUF_INVARIANT() Invariant()
       
    30 #else
       
    31 #define SQLFLATBUF_INVARIANT() void(0)
       
    32 #endif
       
    33 
       
    34 /**
       
    35 RSqlBufFlat class manages a flat memory buffer with fixed elements count.
       
    36 Each element (or field) of the flat buffer has a type and variable length data and is accessible using an
       
    37 index. The data may be NULL.
       
    38 The RSqlBufFlat objects are used for sending/receiving data between client dlls and servers, 
       
    39 because once the buffer filled, a pointer to the flat buffer data can be used to send the whole buffer in a single
       
    40 IPC call, which is more effective than using a stream like transfer.
       
    41 
       
    42 RSqlBufFlat public functions are not very convenient for storing/retrieving values based on the column type 
       
    43 and there are two additional classes which may be used instead of working with the flat buffer directly: 
       
    44 TSqlBufRIterator and TSqlBufWIterator.
       
    45 
       
    46 The physical structure of the flat buffer is:
       
    47 ---------------------------
       
    48 | SysData | Header | Data |
       
    49 ---------------------------
       
    50 - "SysData" has fixed length and contains fields with about the buffer used size, elements count, header size;
       
    51 - "Header"  has fixed length, which depends of the number of elements and contains cells, one per element.
       
    52             Each cell contains information about: element type, element data length, the start position of the 
       
    53             element data in the flat buffer, "present"/"not present" flag. "Not present" means that no memory
       
    54             is reserved for the element data, but the buffer "knows" what is the element type and element data length;
       
    55             (In the current design there is no "Present"/"Not present flag". If the data position is 0, that indicates
       
    56             the element is "Not present"). See RSqlBufFlat::TCell comments for details.
       
    57 - "Data"    Is the dynamic part of the buffer which may grow during the operations with the flat buffer (setting
       
    58             element data);
       
    59             
       
    60 "Present"/"Not present" attribute has a key role in the large data transfers between the client and the server.
       
    61 In order to optimize memory usage, usually the client specifies what can be the max field size. The server
       
    62 knows that and when it fills a particular flat buffer, which has to be sent to the client, it puts in the
       
    63 flat buffer only the pieces of data whose size is less than the specified "large data" size. Any data piece whose
       
    64 size is larger will be set as "Not present" in the flat buffer. The "Not present" field will have all the
       
    65 attributes, like type and size, but won't have any data or any allocated flat buffer memory.
       
    66 So the client, when it receives the flat buffer, will know the field type and size and if it wants to get the field data,
       
    67 will have to make an additional call to the server. 
       
    68 
       
    69 Note that the fields in the buffer are 8-byte aligned.
       
    70 
       
    71 Typical examples how the buffer can be used:
       
    72 
       
    73 Case 1 - a dll client wants to receive from the server a flat buffer data. 
       
    74 
       
    75 @code
       
    76 RSqlBufFlat bufFlat;
       
    77 bufFlat.SetCount(N);								//N is the field count
       
    78 ....
       
    79 bufFlat.Reset();									//Clears the content of the buffer without shrinking it.
       
    80 ipcArgs.Set(0, bufFlat.MaxSize());					//Tell the server what is the flat buffer max size
       
    81 ipcArgs.Set(1, &bufFlat.BufPtr());
       
    82 TInt rc = session.SendReceive(funcNum, ipcArgs);
       
    83 if(rc > KSqlClientBufOverflowCode)
       
    84 	{												//the client buffer is not big enough and has to be resized
       
    85 	rc = bufFlat.ReAlloc(err - KSqlClientBufOverflowCode);
       
    86 	if(rc != KErrNone)
       
    87 		{
       
    88 		return rc;
       
    89 		}
       
    90 	ipcArgs.Set(0, bufFlat.MaxSize());
       
    91 	ipcArgs.Set(1, &bufFlat.BufPtr());
       
    92 	rc = session.SendReceive(funcNum, ipcArgs);
       
    93 	}
       
    94 @endcode
       
    95 
       
    96 Case 2 - a dll client wants to send to the server a flat buffer data. 
       
    97 
       
    98 @code
       
    99 RSqlBufFlat bufFlat;
       
   100 bufFlat.SetCount(N);								//N is the field count
       
   101 ....
       
   102 TPtrC8 ptr(bufFlat.BufDes());
       
   103 TInt err = session.SendReceive(funcNum, TIpcArgs(ptr.Length(), &ptr));
       
   104 @endcode
       
   105 
       
   106 Case 3 - the server wants to return to the client a flat buffer data.
       
   107 @code
       
   108 RSqlBufFlat bufFlat;
       
   109 bufFlat.SetCount(N);								//N is the field count
       
   110 ....
       
   111 TInt maxCliBufSize = msg.Int0();					//The max size of the client buffer
       
   112 if(maxCliBufSize < bufFlat.Size())
       
   113 	{
       
   114 	return bufFlat.Size() + KSqlClientBufOverflowCode;//Tell the client that its buffer is too small
       
   115 	}
       
   116 msg.WriteL(1, bufFlat.BufDes());
       
   117 @endcode
       
   118 
       
   119 Case 4 - the server wants to receive from the client a flat buffer data.
       
   120 @code
       
   121 RSqlBufFlat bufFlat;
       
   122 bufFlat.SetCount(N);								//N is the field count
       
   123 ....
       
   124 TInt cliBufFlatLen = aMessage.Int0();
       
   125 TInt err = bufFlat.ReAlloc(cliBufFlatLen);			//Reallocate memory for the flat buffer
       
   126 if(err != KErrNone)
       
   127 	{
       
   128 	return err;
       
   129 	}
       
   130 msg.ReadL(1, bufFlat.BufPtr());
       
   131 @endcode
       
   132 
       
   133 Case 5 - the server (or the client) wants to fill the flat buffer with some data.
       
   134 @code
       
   135 RSqlBufFlat bufFlat;
       
   136 bufFlat.SetCount(N);								//N is the field count
       
   137 ....
       
   138 TInt err = flatBuf.SetCount(M);						//If the field count has to be changed to M
       
   139 if(err != KErrNone)
       
   140 	{
       
   141 	return err;
       
   142 	}
       
   143 //use the TSqlBufWIterator iterator to fill the buffer
       
   144 @endcode
       
   145 
       
   146 @see TSqlBufRIterator
       
   147 @see TSqlBufWIterator
       
   148 @see RSqlBufFlat::TCell
       
   149 @see RSqlBufFlat::TBufFlat
       
   150 
       
   151 @internalComponent
       
   152 */
       
   153 class RSqlBufFlat
       
   154 	{
       
   155 	friend class TSqlBufRIterator;
       
   156 	friend class CSqlSecurityPolicy;
       
   157 	friend class TSqlSecurityPolicyIterator;
       
   158 
       
   159 public:	
       
   160 	//This enum has to be in the "public" section because it is used by TCell (declared as "private" in RSqlBufFlat)
       
   161 	enum 
       
   162 		{
       
   163 		EWidthType = 3, 					//Bit width of the "Type" field of the header cell
       
   164 		EWidthLen = 29						//Bit width of the "Length" field of the header cell
       
   165 		};
       
   166 	//This enum has to be in the "public" section because it is used by TCell (declared as "private" in RSqlBufFlat)
       
   167 	enum 
       
   168 		{
       
   169 		EMaxType = 1 << EWidthType, 		//Max allowed flat buffer field type
       
   170 		EMaxLength = 1 << EWidthLen			//Max allowed flat buffer field length
       
   171 		};
       
   172 
       
   173 	RSqlBufFlat();
       
   174 	TInt SetCount(TInt aCount);
       
   175 	TInt ReAlloc(TInt aSize);
       
   176 	void ResetAndMinimize();
       
   177 	void Reset();
       
   178 	void Close();
       
   179 	inline TInt Count() const;
       
   180 	inline TInt Size() const;
       
   181 	inline TInt MaxSize() const;
       
   182 	
       
   183 	TInt SetField(TInt aIndex, TInt aType, const void* aData, TInt aDataLength);
       
   184 	
       
   185 	inline const TDesC8& BufDes() const;
       
   186 	inline TPtr8& BufPtr();
       
   187 	
       
   188 private:	//Data type declarations
       
   189 	/**
       
   190 	TCell represents the structure of header cells.
       
   191 	Each cells contains the following fields:
       
   192 	- Flat buffer field type;
       
   193 	- Flat buffer field length;
       
   194 	- Flat buffer field data position;
       
   195 	  = if 0 then the field is "Not present" (no memory is reserved for the field data, the field data is missing);
       
   196 	  = if positive - the field data position in the flat buffer (counting from the beginning of the header);
       
   197 	  = if negative - the field is "Not present", but memory has been reserved for it;
       
   198 	  
       
   199 	RSqlBufFlat class offers fast, indexed access to the header cells.
       
   200 	
       
   201 	@see RSqlBufFlat
       
   202 	*/
       
   203 	struct TCell
       
   204 		{
       
   205 		inline TInt Type() const {return (iBits >> RSqlBufFlat::EWidthLen) & (RSqlBufFlat::EMaxType - 1);}
       
   206 		inline TInt Size() const {return (iBits & (RSqlBufFlat::EMaxLength - 1));}
       
   207 		TUint32	iBits;						//element type: EWidthType bits & element length: EWidthLen bits.
       
   208 		TInt32	iPos;						//element data position, relative to the beginning of the header.
       
   209 											//                       Zero if the element is not present.
       
   210 											//                       Negative if the element is not present but memory is reserved.
       
   211 		};
       
   212 
       
   213 	enum {EExpandSize = 256};				//iBuf min expansion size - it must be a power of 2 and 
       
   214 											//                          (EExpandSize % 8) should be 0.
       
   215 	/**
       
   216 	TBufFlat structure represents the "SysData" part of the flat buffer (see RSqlBufFlat comments), beyond which
       
   217 	begins the flat buffer header and "Data" part.
       
   218 
       
   219 	TBufFlat structure contains information about:
       
   220 	- Flat buffer elements count;
       
   221 	- Flat buffer header size;
       
   222 	- The size of used part of the flat buffer;
       
   223 
       
   224 	@see RSqlBufFlat
       
   225 	*/
       
   226 	struct TBufFlat
       
   227 		{
       
   228 		TInt	iCount;			//element count
       
   229 		TInt	iHeaderSize;	//buffer header size	
       
   230 		TInt	iSize;			//used buffer size
       
   231 		TInt	iReserved;		//maintains TBufFlat 8-byte aligned
       
   232 		};
       
   233 	
       
   234 private:	//Method declarations
       
   235 	void DoInit();
       
   236 	TInt DoReAlloc(TInt aSize);
       
   237 	inline TInt Available() const;
       
   238 	void DoSet(TInt aIndex, TInt aType, const void* aData, TInt aDataLength);
       
   239 	TInt Reserve(TInt aLength);
       
   240 	void Invariant() const;
       
   241 	inline const TCell* Header() const;
       
   242 	inline TCell* Header();
       
   243 	inline TInt SysDataSize() const;
       
   244 	
       
   245 private:	//Data declarations
       
   246 	// IPC data
       
   247 	TBufFlat*		iBuf;
       
   248 	// non-IPC data
       
   249 	TInt			iMaxSize;	//max buffer size (allocated memory), not part of RSqlBufFlat data (IPC - sent/received).
       
   250 								//iMaxSize can't be part of the IPC data, because it may be overwritten, which leads to 
       
   251 								//"hard to detect" problems. For example:
       
   252 								//  - client sends to the server in/out flat buffer with max size 256 bytes (allocated);
       
   253 								//  - the server has a flat buffer which max size is 512, but the used size is 200;
       
   254 								//  - the client flat buffer has enough space for those 200 bytes, so the server will
       
   255 								//    copy its flat buffer content to the client flat buffer. The client's flat buffer
       
   256 								//    iMaxSize data member will lose its original value (256) and will have new value assigned -
       
   257 								//    512. But the client flat buffer does not have 512 bytes allocated!
       
   258 	mutable TPtrC8	iBufPtrC;	//it is set to point to iBuf. Not part of RSqlBufFlat data (IPC - sent/received)
       
   259 	mutable TPtr8	iBufPtr;	//it is set to point to iBuf. Not part of RSqlBufFlat data (IPC - sent/received)
       
   260 	};
       
   261 
       
   262 #include "SqlBufFlat.inl"
       
   263 
       
   264 #endif//__SQLBUFFLAT_H__