os/persistentdata/persistentstorage/dbms/sdbms/SD_SESS.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/dbms/sdbms/SD_SESS.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1056 @@
     1.4 +// Copyright (c) 1998-2009 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 +// DBMS server-session and support classes
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <s32file.h>
    1.22 +#include "SD_STD.H"
    1.23 +#include "Sd_DbList.h"
    1.24 +
    1.25 +using namespace DBSC;
    1.26 +
    1.27 +/*
    1.28 +CDbsSession class is updated now to with a support for DBMS security policies.
    1.29 +What idea sits behind the update:
    1.30 +1) DBMS server has a set of server side CDbsSession objects.
    1.31 +2) Each CDbsSession object has a list of CDbsSession::TEntry items.
    1.32 +   Each CDbsSession::TEntry item holds a server side DBMS object, which is
    1.33 +   used to perform client requests.
    1.34 +3) CDbsSession::TEntry object could be:
    1.35 +	- EDbsDatabase - database object. It operates at database level.
    1.36 +		OpenDatabaseL is the method, which creates it.
    1.37 +	- EDbsIncremental - incremental object. It operates either at database or table level.
    1.38 +		NewIncrementalL is the method, which creates it.
    1.39 +	- EDbsCursor - cursor object. It operates at table level.
    1.40 +		NewCursorL is the method, which creates it.
    1.41 +	- EDbsConstraint - constraint object. It is used at table level and needs the same
    1.42 +		security policy as its table.
    1.43 +	- EDbsStream - stream object. It operates either at database or table level.
    1.44 +		NewStreamL are the methods, which create it.
    1.45 +	- EDbsObserver - observer object. It operates at database level.
    1.46 +4) When DBMS server is used in a security environment, database/table security policies 
    1.47 +	describe allowed W/R operations for the database/tables.
    1.48 +5) Each database/table has a security policy object assiciated with it. It may be accessed
    1.49 +	using MPolicy interface.
    1.50 +6) There is a MPolicySpace interface, which holds a collection of MPolicy interfaces
    1.51 +	for the database/tables. MPolicy interfaces can be queried using MPolicySpace methods.
    1.52 +7) All DBMS server side objects, described in (3), operate at database/table level. In a
    1.53 +	security environment, the client's access rights has to be checked, before performing
    1.54 +	particular database/table operation.
    1.55 +	It is known at the moment of DBMS object creation, on which database/table it will operate.
    1.56 +	The database/table cannot be changed during the DBMS object life time.
    1.57 +	At the moment of DBMS object creation, the related database/table interface is queried and
    1.58 +	stored in CDbsSession::TEntry::iPolicy data member. 
    1.59 +	It is an error if CDbsSession::TEntry item exists without a security policy.
    1.60 +8) Every time, when a client needs particular DBMS server functionality and CDbsSession::ServiceL
    1.61 +	has been called, the session object will find which DBMS server object has to be used and
    1.62 +	asserts client's access rights against its security policy.
    1.63 +	If the client has not enough access rights to perform desired DBMS operation, the DBMS
    1.64 +	session will leave with KErrPermissionDenied error code.
    1.65 +	======================================================================================
    1.66 +	In one sentence - every time, when an object from CDbsSession::TEntry list is about to 
    1.67 +	perform particular operation at database/table level, the associated database/table 
    1.68 +	security policy will be checked and the opration may be rejected.
    1.69 +*/
    1.70 +
    1.71 +// Class CDbsSession::TEntry
    1.72 +
    1.73 +//
    1.74 +// release the object
    1.75 +//
    1.76 +void CDbsSession::TEntry::Release()
    1.77 +	{
    1.78 +	TDbsType t=Type();
    1.79 +	__ASSERT(t!=EDbsFree);
    1.80 +	if (t==EDbsObserver)
    1.81 +		delete STATIC_CAST(CDbsObserver::HObserver*,iObject);
    1.82 +	else if (t==EDbsStream)
    1.83 +		delete STATIC_CAST(HDbsStream*,iObject);
    1.84 +	else
    1.85 +		CDbObject::Destroy(STATIC_CAST(CDbObject*,iObject));
    1.86 +	iType=TUint8(EDbsFree);
    1.87 +	iPolicy = NULL;
    1.88 +	}
    1.89 +
    1.90 +#ifdef __DBDUMP__
    1.91 +//Using CDbsSession::TEntry::Dump() method you can dump the TEntry's content
    1.92 +//into a stream. Note that the dump works only if you have __DBDUMP__ macro defined.
    1.93 +void CDbsSession::TEntry::Dump(RFile& aFile) const
    1.94 +	{
    1.95 +	_LIT8(KClassName, "CDbsSession::TEntry. this=%X");
    1.96 +	_LIT8(KType, "Type=%S");
    1.97 +	_LIT8(KMagic, "Magic=%d");
    1.98 +	_LIT8(KCrLf, "\r\n");
    1.99 +	_LIT8(KEnd, "====");
   1.100 +	TPtrC8 KDbsType[EDbsMaxType + 1] = {_L8("Free"), _L8("Database"), _L8("Incremental"), _L8("Cursor"), _L8("Constraint"), _L8("Stream"), _L8("Observer")};
   1.101 +	TBuf8<40> buf;
   1.102 +
   1.103 +	buf.Format(KClassName, this);
   1.104 +	(void)aFile.Write(buf);
   1.105 +	(void)aFile.Write(KCrLf);
   1.106 +	buf.Format(KType, &KDbsType[iType]);
   1.107 +	(void)aFile.Write(buf);
   1.108 +	(void)aFile.Write(KCrLf);
   1.109 +	buf.Format(KMagic, iMagic);
   1.110 +	(void)aFile.Write(buf);
   1.111 +	(void)aFile.Write(KCrLf);
   1.112 +	__ASSERT(iPolicy);
   1.113 +	iPolicy->Dump(aFile);
   1.114 +	(void)aFile.Write(KEnd);
   1.115 +	(void)aFile.Write(KCrLf);
   1.116 +	}
   1.117 +#endif//__DBDUMP__
   1.118 +
   1.119 +// Class CDbsSession
   1.120 +
   1.121 +//
   1.122 +// Release all this clients resources
   1.123 +// Streams must be released before cursors, and everything before the connection
   1.124 +//
   1.125 +CDbsSession::~CDbsSession()
   1.126 +	{
   1.127 +	TEntry* const base=&iIx[0];
   1.128 +	if (base)
   1.129 +		{
   1.130 +		TInt type=EDbsMaxType;
   1.131 +		do	{
   1.132 +			for (TEntry* e=base+iSize;--e>=base;)
   1.133 +				{
   1.134 +				if (e->iType==type)
   1.135 +					e->Release();
   1.136 +				}
   1.137 +			} while (--type>EDbsFree);
   1.138 +		User::Free(base);
   1.139 +		}
   1.140 +	iDbPolicyRqColl.Close();
   1.141 +    delete iSessDriveSpace;
   1.142 +	Server().RemoveSession();
   1.143 +	}
   1.144 +
   1.145 +/**
   1.146 +Overrides virtual CSession2::Create2().
   1.147 +Creates iSessDriveSpace instance.
   1.148 +*/
   1.149 +void CDbsSession::CreateL()
   1.150 +    {
   1.151 +    iSessDriveSpace = CDbsSessDriveSpace::NewL(Server().DriveSpaceCol());
   1.152 +    }
   1.153 +
   1.154 +//
   1.155 +// provide for CSession
   1.156 +// If this leaves, we complete message through ServiceError(...)
   1.157 +//
   1.158 +void CDbsSession::ServiceL(const RMessage2& aMessage)
   1.159 +	{
   1.160 +	//set received message in server so it can be used in cleanup when server panics.
   1.161 +	CPolicyProxy& policyProxy = Server().PolicyProxy();
   1.162 +	TDbsFunction f=DbsFunction(aMessage.Function());
   1.163 +	if (f&KDbsObjectReturn)		// may return a derived object
   1.164 +		AllocL();	// ensure index space
   1.165 +	TInt r=0;//object handle
   1.166 +	TInt h=DbsHandle(aMessage.Function());
   1.167 +	if (h==KDbsSessionHandle)
   1.168 +		{	// session based requests
   1.169 +		switch (f&~KDbsObjectReturn)
   1.170 +			{
   1.171 +		case EDbsResourceMark:
   1.172 +			ResourceCountMarkStart();
   1.173 +			break;
   1.174 +		case EDbsResourceCheck:
   1.175 +			ResourceCountMarkEnd(aMessage);
   1.176 +			break;
   1.177 +		case EDbsResourceCount:
   1.178 +			r=CountResources();
   1.179 +			break;
   1.180 +		case EDbsSetHeapFailure:
   1.181 +			User::__DbgSetAllocFail(RHeap::EUser,RHeap::TAllocFail(aMessage.Int0()),aMessage.Int1());
   1.182 +			break;
   1.183 +		case EDbsOpenDatabase:
   1.184 +			r=OpenDatabaseL(aMessage);
   1.185 +			break;
   1.186 +		case EDbsReserveDriveSpace:
   1.187 +			ReserveDriveSpaceL(static_cast <TDriveNumber> (aMessage.Int0()));
   1.188 +			break;
   1.189 +        case EDbsFreeReservedSpace:
   1.190 +	        FreeReservedSpace(static_cast <TDriveNumber> (aMessage.Int0()));
   1.191 +			break;
   1.192 +		case EDbsReserveGetAccess:
   1.193 +			GetReserveAccessL(static_cast <TDriveNumber> (aMessage.Int0()));
   1.194 +			break;
   1.195 +		case EDbsReserveReleaseAccess:
   1.196 +			ReleaseReserveAccess(static_cast <TDriveNumber> (aMessage.Int0()));
   1.197 +			break;
   1.198 +		default:
   1.199 +			r=ExtServiceL(aMessage, static_cast <TDbsFunction> (f&~KDbsObjectReturn));
   1.200 +			break;
   1.201 +			}
   1.202 +		}
   1.203 +	else
   1.204 +		{	// object based requests
   1.205 +		TEntry& e=Object(h);
   1.206 +		__ASSERT(e.iPolicy);
   1.207 +		policyProxy.CheckL(aMessage, *e.iPolicy);
   1.208 +		TDbsFunction dbmsFuncNo = static_cast <TDbsFunction> (f & ~KDbsObjectReturn);
   1.209 +		switch (dbmsFuncNo)
   1.210 +			{
   1.211 +	// the common close function
   1.212 +		case EDbsClose:
   1.213 +			//If this is a database object, remove the related pair (handle, uid) from iDbPolicyRqColl collection.
   1.214 +			if(e.Type() == EDbsDatabase)
   1.215 +				{
   1.216 +				iDbPolicyRqColl.Remove(h);
   1.217 +				}
   1.218 +			Free(e);
   1.219 +			break;
   1.220 +	// database functions
   1.221 +		case EDbsDatabaseAuthenticate:
   1.222 +			{
   1.223 +            __LEAVE(KErrNotSupported);             
   1.224 +			}
   1.225 +			break;
   1.226 +		case EDbsDatabaseDestroy:
   1.227 +			r=e.Database().Destroy();
   1.228 +			break;
   1.229 +		case EDbsDatabaseBegin:
   1.230 +			r=e.Database().Begin();
   1.231 +			break;
   1.232 +		case EDbsDatabaseCommit:
   1.233 +			r=e.Database().Commit();
   1.234 +			break;
   1.235 +		case EDbsDatabaseRollback:
   1.236 +			e.Database().Rollback();
   1.237 +			break;
   1.238 +		case EDbsDatabaseProperty:
   1.239 +			r=e.Database().Property(CDbDatabase::TProperty(aMessage.Int0()));
   1.240 +			break;
   1.241 +		case EDbsDatabaseTables:
   1.242 +			{//The new stream object will have the same security policy as the database
   1.243 +			 //Read only stream
   1.244 +			CDbTableNames* names=CDbTableNames::NewLC();
   1.245 +			e.Database().TablesL(*names);
   1.246 +			r=NewStreamL(names,Externalizer(names),aMessage,e.iPolicy);
   1.247 +			}
   1.248 +			break;
   1.249 +		case EDbsDatabaseColumns:
   1.250 +			{//The new stream object will have the same security policy as the database
   1.251 +			 //Read only stream
   1.252 +			CDbColSet* set=CDbColSet::NewLC();
   1.253 +			e.Database().ColumnsL(*set,ReadName0L(0,aMessage));
   1.254 +			r=NewStreamL(set,Externalizer(set),aMessage,e.iPolicy);
   1.255 +			}
   1.256 +			break;
   1.257 +		case EDbsDatabaseIndexes:
   1.258 +			{//The new stream object will have the same security policy as the database
   1.259 +			 //Read only stream
   1.260 +			CDbIndexNames* names=CDbIndexNames::NewLC();
   1.261 +			e.Database().IndexesL(*names,ReadName0L(0,aMessage));
   1.262 +			r=NewStreamL(names,Externalizer(names),aMessage,e.iPolicy);
   1.263 +			}
   1.264 +			break;
   1.265 +		case EDbsDatabaseKeys:
   1.266 +			{//The new stream object will have the same security policy as the database
   1.267 +			 //Read only stream
   1.268 +			CDbKey* key=CDbKey::NewLC();
   1.269 +			e.Database().KeysL(*key,ReadName0L(0,aMessage),ReadName1L(1,aMessage));
   1.270 +			r=NewStreamL(key,Externalizer(key),aMessage,e.iPolicy);
   1.271 +			}
   1.272 +			break;
   1.273 +		case EDbsDatabaseCreateTable:
   1.274 +			{
   1.275 +			const TDesC& name=ReadName0L(0,aMessage);
   1.276 +			CDbColSet* set=ColSetLC(1,aMessage);
   1.277 +			CDbKey* primary=0;
   1.278 +			if (aMessage.Ptr2())
   1.279 +				primary=KeyLC(2,aMessage);
   1.280 +
   1.281 +			e.Database().CreateTableL(name,*set,primary);
   1.282 +			if (primary)
   1.283 +				CleanupStack::PopAndDestroy();	// primary
   1.284 +			CleanupStack::PopAndDestroy();	// set
   1.285 +			}
   1.286 +			break;
   1.287 +		case EDbsDatabaseOpenObserver:
   1.288 +			//The new observer object will have the same security policy as the database
   1.289 +			r=Add(CDbsConnection::Source(e.Database()).ObserverL(),e.iPolicy);
   1.290 +			break;
   1.291 +		case EDbsDatabaseOpenUtility:
   1.292 +			{//The new incremental object will have the same security policy as the database
   1.293 +			TInt step;
   1.294 +			r=NewIncrementalL(e.Database().UtilityL(CDbDatabase::TUtility(aMessage.Int0()),step),step,aMessage,e.iPolicy);
   1.295 +			}
   1.296 +			break;
   1.297 +		case EDbsDatabaseOpenDropTable:
   1.298 +			{//The new incremental object will have the same security policy as the database
   1.299 +			TInt step;
   1.300 +			const TDesC& name=ReadName0L(0,aMessage);
   1.301 +			r=NewIncrementalL(e.Database().DropTableL(name,step),step,aMessage,e.iPolicy);
   1.302 +			}
   1.303 +			break;
   1.304 +		case EDbsDatabaseOpenAlterTable:
   1.305 +			{//The new incremental object will have the same security policy as the database
   1.306 +			TInt step;
   1.307 +			const TDesC& name=ReadName0L(0,aMessage);
   1.308 +			CDbColSet* set=ColSetLC(1,aMessage);
   1.309 +			r=NewIncrementalL(e.Database().AlterTableL(name,*set,step),step,aMessage,e.iPolicy);
   1.310 +			CleanupStack::PopAndDestroy();	// set
   1.311 +			}
   1.312 +			break;
   1.313 +		case EDbsDatabaseOpenCreateIndex:
   1.314 +			{//The new incremental object will have the same security policy as the database
   1.315 +			TInt step;
   1.316 +			const TDesC& name=ReadName0L(0,aMessage);
   1.317 +			const TDesC& table=ReadName1L(1,aMessage);
   1.318 +			CDbKey* key=KeyLC(2,aMessage);
   1.319 +			r=NewIncrementalL(e.Database().CreateIndexL(name,table,*key,step),step,aMessage,e.iPolicy);
   1.320 +			CleanupStack::PopAndDestroy();	// key
   1.321 +			}
   1.322 +			break;
   1.323 +		case EDbsDatabaseOpenDropIndex:
   1.324 +			{//The new incremental object will have the same security policy as the database
   1.325 +			TInt step;
   1.326 +			const TDesC& name=ReadName0L(0,aMessage);
   1.327 +			const TDesC& table=ReadName1L(1,aMessage);
   1.328 +			r=NewIncrementalL(e.Database().DropIndexL(name,table,step),step,aMessage,e.iPolicy);
   1.329 +			}
   1.330 +			break;
   1.331 +		case EDbsDatabaseExecute:
   1.332 +			{//The new incremental object will have the same security policy as the database or table - sql dependent.
   1.333 +			//In order EDbsDatabaseExecute request to be performed, the DBMS session has already
   1.334 +			//checked the client capabilities at the database level.
   1.335 +			//Now, the sql string will be parsed and the client capabilities will be checked
   1.336 +			//again at more specific database or table level.
   1.337 +			TInt init;
   1.338 +			HBufC* sql=ReadHBufLC(0,aMessage);
   1.339 +			const TDbPolicyRequest& rq = iDbPolicyRqColl[h];
   1.340 +			TPolicyType policyType = EPTNone;
   1.341 +			const MPolicy* policy = policyProxy.SqlPolicyL(rq, *sql, policyType);
   1.342 +			policyProxy.CheckL(policyType, aMessage, *policy);			
   1.343 +			r=NewIncrementalL(e.Database().ExecuteL(*sql,TDbTextComparison(aMessage.Int1()),init),init,aMessage,policy);
   1.344 +			CleanupStack::PopAndDestroy(sql);
   1.345 +			}
   1.346 +			break;
   1.347 +		case EDbsDatabasePrepareView:
   1.348 +			{//The new cursor object will have the same security policy as the table in the sql string.
   1.349 +			//In order EDbsDatabasePrepareView request to be performed, the DBMS session has already
   1.350 +			//checked the client capabilities at the database level.
   1.351 +			//Now, the sql string will be parsed and the client capabilities will be checked
   1.352 +			//again at table level.
   1.353 +			HBufC* sql=ReadHBufLC(0,aMessage);
   1.354 +			const TDbPolicyRequest& rq = iDbPolicyRqColl[h];
   1.355 +			TPolicyType policyType = EPTNone;
   1.356 +			const MPolicy* policy = policyProxy.SqlPolicyL(rq, *sql, policyType);
   1.357 +			policyProxy.CheckL(policyType, aMessage, *policy);			
   1.358 +			TPckgBuf<TDbWindow> window;
   1.359 +			aMessage.ReadL(2,window);
   1.360 +			TInt mode=aMessage.Int1();
   1.361 +			CDbCursor* cursor=e.Database().ViewL(TDbQuery(*sql,TDbTextComparison(mode&0xff)),window(),RDbRowSet::TAccess(mode>>8));
   1.362 +			r=NewCursorL(cursor,aMessage,policy);
   1.363 +			CleanupStack::PopAndDestroy(sql);
   1.364 +			}
   1.365 +			break;
   1.366 +		case EDbsDatabaseOpenTable:
   1.367 +			{//The new cursor object will have the same security policy as the table
   1.368 +			const TDesC& name=ReadName0L(0,aMessage);
   1.369 +			const TDbPolicyRequest& rq = iDbPolicyRqColl[h];
   1.370 +			const MPolicy* policy = policyProxy.TblPolicyL(rq, name);
   1.371 +			//Check caller capabilities against the table policy
   1.372 +			RDbRowSet::TAccess accessType = static_cast <RDbRowSet::TAccess> (aMessage.Int1());
   1.373 +			TPolicyType policyType = accessType == RDbRowSet::EReadOnly ? EPTRead : EPTWrite;
   1.374 +			policyProxy.CheckL(policyType, aMessage, *policy);
   1.375 +			//Create cursor
   1.376 +			r=NewCursorL(e.Database().TableL(name,accessType),aMessage,policy);
   1.377 +			}
   1.378 +			break;
   1.379 +	// Incremental functions
   1.380 +		case EDbsIncrementalNext:
   1.381 +			{
   1.382 +			TPckgBuf<TInt> step=aMessage.Int0();
   1.383 +			r=e.Incremental().NextL(step());
   1.384 +			aMessage.WriteL(1,step);
   1.385 +			}
   1.386 +			break;
   1.387 +	// Observer functions
   1.388 +		case EDbsObserverNotify:
   1.389 +			e.Observer().Notify(aMessage);
   1.390 +			return;		// deferred completion of the message!
   1.391 +		case EDbsObserverCancel:
   1.392 +			e.Observer().Cancel();
   1.393 +			break;
   1.394 +	// cursor functions
   1.395 +		case EDbsCursorColumnTypes:
   1.396 +			{
   1.397 +			TInt count=e.Cursor().ColumnCount();
   1.398 +			TUint8* types=(TUint8*)User::AllocLC(count);
   1.399 +			for (TInt ii=count;--ii>=0;)
   1.400 +				types[ii]=TUint8(e.Cursor().ColumnType(ii+1));
   1.401 +			aMessage.WriteL(3,TPtrC8(types,count));
   1.402 +			CleanupStack::PopAndDestroy();
   1.403 +			}
   1.404 +			break;
   1.405 +		case EDbsCursorReset:
   1.406 +			e.Cursor().Reset();
   1.407 +			break;
   1.408 +		case EDbsCursorEvaluate:
   1.409 +			r=e.Cursor().EvaluateL()?1:0;
   1.410 +			break;
   1.411 +		case EDbsCursorUnevaluated:
   1.412 +			r=e.Cursor().Unevaluated()?1:0;
   1.413 +			break;
   1.414 +		case EDbsCursorSetIndex:
   1.415 +			{
   1.416 +			const TDesC* name=0;
   1.417 +			if (aMessage.Ptr0())
   1.418 +				name=&ReadName0L(0,aMessage);
   1.419 +			e.Cursor().SetIndexL(name);
   1.420 +			}
   1.421 +			break;
   1.422 +		case EDbsCursorSeek:
   1.423 +			{
   1.424 +			TDbLookupKey* key=LookupKeyLC(0,aMessage.Int1(),aMessage);
   1.425 +			r=e.Cursor().SeekL(*key,RDbTable::TComparison(aMessage.Int2()))?1:0;
   1.426 +			CleanupStack::PopAndDestroy();		// key;
   1.427 +			}
   1.428 +			break;
   1.429 +		case EDbsCursorAtBeginning:
   1.430 +			r=e.Cursor().AtBeginning()?1:0;
   1.431 +			break;
   1.432 +		case EDbsCursorAtEnd:
   1.433 +			r=e.Cursor().AtEnd()?1:0;
   1.434 +			break;
   1.435 +		case EDbsCursorAtRow:
   1.436 +			r=e.Cursor().AtRow()?1:0;
   1.437 +			break;
   1.438 +		case EDbsCursorCount:
   1.439 +			r=e.Cursor().CountL(RDbRowSet::TAccuracy(aMessage.Int0()))+1;
   1.440 +			break;
   1.441 +		case EDbsCursorGotoPos:
   1.442 +			if (e.Cursor().GotoL(RDbRowSet::TPosition(aMessage.Int0())))
   1.443 +				{
   1.444 +				e.Cursor().GetL();
   1.445 +				r=RetrieveRowL(e.Cursor(),aMessage);
   1.446 +				}
   1.447 +			break;
   1.448 +		case EDbsCursorBookmark:
   1.449 +			{
   1.450 +			TPckgBuf<TDbBookmark::TMark> mark;
   1.451 +			e.Cursor().Bookmark(mark());
   1.452 +			aMessage.WriteL(3,mark);
   1.453 +			}
   1.454 +			break;
   1.455 +		case EDbsCursorGotoBookmark:
   1.456 +			{
   1.457 +			TPckgBuf<TDbBookmark::TMark> mark;
   1.458 +			aMessage.ReadL(0,mark);
   1.459 +			e.Cursor().GotoL(mark());
   1.460 +			}
   1.461 +			break;
   1.462 +		case EDbsCursorGet:
   1.463 +			e.Cursor().GetL();
   1.464 +			r=RetrieveRowL(e.Cursor(),aMessage);
   1.465 +			break;
   1.466 +		case EDbsCursorInsert:
   1.467 +			e.Cursor().InsertL(CDbCursor::TInsert(aMessage.Int0()));
   1.468 +			r=RetrieveRowL(e.Cursor(),aMessage);
   1.469 +			break;
   1.470 +		case EDbsCursorUpdate:
   1.471 +			e.Cursor().UpdateL();
   1.472 +			r=RetrieveRowL(e.Cursor(),aMessage);
   1.473 +			break;
   1.474 +		case EDbsCursorRetrieveRow:	// pass the row buffer back to the client
   1.475 +			r=RetrieveRowL(e.Cursor(),aMessage);
   1.476 +			break;
   1.477 +		case EDbsCursorCancel:
   1.478 +			e.Cursor().Cancel();
   1.479 +			break;
   1.480 +		case EDbsCursorPut:
   1.481 +			PutRowL(e.Cursor(),aMessage);
   1.482 +			e.Cursor().PutL();
   1.483 +			break;
   1.484 +		case EDbsCursorDelete:
   1.485 +			e.Cursor().DeleteL();
   1.486 +			break;
   1.487 +		case EDbsCursorColumns:
   1.488 +			{// reduce memory usage by extracting and stream columns individually
   1.489 +			 //Read only stream
   1.490 +			RWriteStream strm(HBufBuf::NewLC());
   1.491 +			TInt count=e.Cursor().ColumnCount();
   1.492 +			strm.WriteInt32L(count);
   1.493 +			TDbCol col;
   1.494 +			for (TInt ii=0;++ii<=count;)
   1.495 +				{
   1.496 +				e.Cursor().ColumnDef(col,ii);
   1.497 +				strm<<col;
   1.498 +				}
   1.499 +			strm.CommitL();
   1.500 +			TInt ext=strm.Sink()->SizeL();
   1.501 +			CleanupStack::Pop();			// stream
   1.502 +			r=NewStreamL(strm.Sink(),aMessage,e.iPolicy,ext);
   1.503 +			}
   1.504 +			break;
   1.505 +		case EDbsCursorColumnDef:
   1.506 +			{
   1.507 +			TPckgBuf<TDbCol> col;
   1.508 +			e.Cursor().ColumnDef(col(),aMessage.Int0());
   1.509 +			aMessage.WriteL(3,col);
   1.510 +			}
   1.511 +			break;
   1.512 +		case EDbsCursorSetNull:
   1.513 +			__ASSERT(TDbCol::IsLong(e.Cursor().ColumnType(aMessage.Int0())));
   1.514 +			e.Cursor().SetNullL(aMessage.Int0());
   1.515 +			break;
   1.516 +		case EDbsCursorColumnSize:
   1.517 +			__ASSERT(TDbCol::IsLong(e.Cursor().ColumnType(aMessage.Int0())));
   1.518 +			r=e.Cursor().ColumnSize(aMessage.Int0());
   1.519 +			break;
   1.520 +		case EDbsCursorColumnSource:
   1.521 +			__ASSERT(TDbCol::IsLong(e.Cursor().ColumnType(aMessage.Int0())));
   1.522 +			{//The new stream object will have the same security policy as the table
   1.523 +			 //Read only stream, used for large BLOB fields.
   1.524 +			TDbColNo col=aMessage.Int0();
   1.525 +			CDbCursor& cursor=e.Cursor();
   1.526 +			r=NewStreamL(cursor.ColumnSourceL(col),aMessage,e.iPolicy,cursor.ColumnSize(col));
   1.527 +			}
   1.528 +			break;
   1.529 +		case EDbsCursorColumnSink:
   1.530 +			//The new stream object will have the same security policy as the table
   1.531 +			//Write stream, used for large BLOB fields.
   1.532 +			r=NewStreamL(e.Cursor().ColumnSinkL(aMessage.Int0()),aMessage,e.iPolicy);
   1.533 +			break;
   1.534 +		case EDbsCursorOpenConstraint:
   1.535 +			{//The new constraint object will have the same security policy as the table
   1.536 +			HBufC* sql=ReadHBufLC(0,aMessage);
   1.537 +			CDbRowConstraint* ct=e.Cursor().ConstraintL(TDbQuery(*sql,TDbTextComparison(aMessage.Int1())));
   1.538 +			CleanupStack::PopAndDestroy();	//sql
   1.539 +			r=Add(ct, e.iPolicy);
   1.540 +			}
   1.541 +			break;
   1.542 +		case EDbsCursorMatch:
   1.543 +			r=e.Cursor().MatchL(Object(aMessage.Int0()).Constraint())?1:0;
   1.544 +			break;
   1.545 +		case EDbsCursorFind:
   1.546 +			{
   1.547 +			HBufC* sql=ReadHBufLC(0,aMessage);
   1.548 +			TDbQuery q(*sql,TDbTextComparison(aMessage.Int1()));
   1.549 +			r=e.Cursor().FindL(RDbRowSet::TDirection(aMessage.Int2()),q)-KErrNotFound;
   1.550 +			CleanupStack::PopAndDestroy();	//sql
   1.551 +			}
   1.552 +			break;
   1.553 +			// stream functions
   1.554 +		case EDbsStreamRead:
   1.555 +			{
   1.556 +			r=e.Stream().ReadL(aMessage);
   1.557 +			}
   1.558 +			break;
   1.559 +		case EDbsStreamWrite:
   1.560 +			{
   1.561 +			e.Stream().WriteL(aMessage);
   1.562 +			}
   1.563 +			break;
   1.564 +		case EDbsStreamSize:
   1.565 +			{
   1.566 +			r=e.Stream().SizeL();
   1.567 +			}
   1.568 +			break;
   1.569 +		case EDbsStreamSynch:
   1.570 +			{
   1.571 +			e.Stream().SynchL();
   1.572 +			}
   1.573 +			break;
   1.574 +	// we don't know about any other functions
   1.575 +		default:
   1.576 +			r=KErrNotSupported;
   1.577 +			break;
   1.578 +			}
   1.579 +		}
   1.580 +
   1.581 +	// don't complete message if we have paniced client, just reset variable;
   1.582 +	if (!aMessage.IsNull())
   1.583 +		aMessage.Complete(r);
   1.584 +	}
   1.585 +
   1.586 +
   1.587 +// Handle an error from CDbsSession::ServiceL()
   1.588 +// A bad descriptor error implies a badly programmed client, so panic it;
   1.589 +// otherwise use the default handling (report the error to the client)
   1.590 +void CDbsSession::ServiceError(const RMessage2& aMessage,TInt aError)
   1.591 + 	{
   1.592 +#ifdef __DBDUMP__
   1.593 +	Dump();
   1.594 +#endif//__DBDUMP__
   1.595 + 	if (aError==KErrBadDescriptor)
   1.596 + 		{
   1.597 + 		// this completes message as well so we have to handle it in
   1.598 + 		// ServiceL
   1.599 + 		_LIT(KCategory,"DBMS-server");
   1.600 + 		Server().Panic(KCategory,EDbsBadDescriptor);
   1.601 + 		}
   1.602 + 	CSession2::ServiceError(aMessage,aError);
   1.603 +   	}
   1.604 +
   1.605 +// Read aPtr as a name
   1.606 +const TDesC& CDbsSession::ReadName0L(TInt aIndex,const RMessage2& aMessage)
   1.607 +	{
   1.608 +	TDes& name=Server().Name0();
   1.609 +	aMessage.ReadL(aIndex,name);
   1.610 +	return name;
   1.611 +	}
   1.612 +
   1.613 +// Read Ptr1 as a name
   1.614 +const TDesC& CDbsSession::ReadName1L(TInt aIndex,const RMessage2& aMessage)
   1.615 +	{
   1.616 +	TDes& name=Server().Name1();
   1.617 +	aMessage.ReadL(aIndex,name);
   1.618 +	return name;
   1.619 +	}
   1.620 +
   1.621 +// Reads aPtr as a variable length 8-bit descriptor
   1.622 +HBufC8* CDbsSession::ReadHBuf8LC(TInt aIndex,const RMessage2& aMessage)
   1.623 +	{
   1.624 +	TInt len= aMessage.GetDesLengthL(aIndex);
   1.625 +	HBufC8* buf=HBufC8::NewLC(len);
   1.626 +	TPtr8 read(buf->Des());
   1.627 +	aMessage.ReadL(aIndex,read);
   1.628 +	return buf;
   1.629 +	}
   1.630 +
   1.631 +// Reads aPtr as a variable length build-width descriptor
   1.632 +HBufC* CDbsSession::ReadHBufLC(TInt aIndex,const RMessage2& aMessage)
   1.633 +	{
   1.634 +	TInt len= aMessage.GetDesLengthL(aIndex);
   1.635 +	HBufC* buf=HBufC::NewLC(len);
   1.636 +	TPtr read(buf->Des());
   1.637 +	aMessage.ReadL(aIndex,read);
   1.638 +	return buf;
   1.639 +	}
   1.640 +
   1.641 +// Pulls a column set from the client
   1.642 +CDbColSet* CDbsSession::ColSetLC(TInt aIndex,const RMessage2& aMessage)
   1.643 +	{
   1.644 +	CDbColSet* set=CDbColSet::NewLC();
   1.645 +	HBufC8* data=ReadHBuf8LC(aIndex,aMessage);
   1.646 +	RDesReadStream strm(*data);
   1.647 +	strm>>*set;
   1.648 +	CleanupStack::PopAndDestroy();	// data
   1.649 +	return set;
   1.650 +	}
   1.651 +
   1.652 +// Pulls a key from the client
   1.653 +CDbKey* CDbsSession::KeyLC(TInt aIndex,const RMessage2& aMessage)
   1.654 +	{
   1.655 +	CDbKey* key=CDbKey::NewLC();
   1.656 +	HBufC8* data=ReadHBuf8LC(aIndex,aMessage);
   1.657 +	RDesReadStream strm(*data);
   1.658 +	strm>>*key;
   1.659 +	CleanupStack::PopAndDestroy();	// data
   1.660 +	return key;
   1.661 +	}
   1.662 +
   1.663 +// Reconstructs a TDbLookupKey from the message parameter
   1.664 +TDbLookupKey* CDbsSession::LookupKeyLC(TInt aIndex,TInt aSize,const RMessage2& aMessage)
   1.665 +	{
   1.666 +	TDbLookupKey* key=(TDbLookupKey*)User::AllocLC(aSize);
   1.667 +	TPtr8 pckg((TUint8*)key,aSize);
   1.668 +	aMessage.ReadL(aIndex,pckg); 
   1.669 +	TDbLookupKey::SColumn* iter=CONST_CAST(TDbLookupKey::SColumn*,key->First());
   1.670 +	const TDbLookupKey::SColumn* end=iter+key->Count();
   1.671 +	if ((TUint8*)end-(TUint8*)key<aSize)
   1.672 +		{	// there is some text data following...
   1.673 +		do
   1.674 +			{
   1.675 +			switch (iter->iType)
   1.676 +				{
   1.677 +			default:
   1.678 +				break;
   1.679 +			case EDbColText8:
   1.680 +				iter->iDes8.iPtr=(TUint8*)key+TInt(iter->iDes8.iPtr);
   1.681 +				break;
   1.682 +			case EDbColText16:
   1.683 +				iter->iDes16.iPtr=(TUint16*)((TUint8*)key+TInt(iter->iDes8.iPtr));
   1.684 +				break;
   1.685 +				};
   1.686 +			} while (++iter<end);
   1.687 +		}
   1.688 +	return key;
   1.689 +	}
   1.690 +
   1.691 +// Reads the row from the client buffer into the server-side buffer
   1.692 +void CDbsSession::ReadRowL(RDbRow& aRow,TInt aSize,const RMessage2& aMessage)
   1.693 +	{
   1.694 +	if (aSize)
   1.695 +		{
   1.696 +		aRow.GrowL(aSize);
   1.697 +		TPtr8 buf((TUint8*)aRow.First(),aSize);
   1.698 +		aMessage.ReadL(0,buf);
   1.699 +		}
   1.700 +	aRow.SetSize(aSize);
   1.701 +	}
   1.702 +
   1.703 +// Writes a row from the client into the cursor
   1.704 +// Any blobs which are modified must not be transferred into the cursor row buffer
   1.705 +void CDbsSession::PutRowL(CDbCursor& aCursor,const RMessage2& aMessage)
   1.706 +	{
   1.707 +	RDbRow* pRow=aCursor.RowBuffer();
   1.708 +	TInt size= aMessage.Int1();
   1.709 +	const TBool omitBlobs=aMessage.Int2();
   1.710 +
   1.711 +	if (!omitBlobs && pRow)
   1.712 +		{	// write straight into cursor row
   1.713 +		ReadRowL(*pRow,size,aMessage);
   1.714 +		return;
   1.715 +		}
   1.716 +	RDbRow row;
   1.717 +	row.PushL();
   1.718 +	ReadRowL(row,size,aMessage);
   1.719 +	TInt max=aCursor.ColumnCount();
   1.720 +	for (TInt ii=0;++ii<=max;)
   1.721 +		{
   1.722 +		if (omitBlobs && TDbCol::IsLong(aCursor.ColumnType(ii)))
   1.723 +			;
   1.724 +		else
   1.725 +			aCursor.Column(ii).SetL(row.ColCell(ii));
   1.726 +		}
   1.727 +	CleanupStack::PopAndDestroy();		// row
   1.728 +	}
   1.729 +
   1.730 +// Writes the row buffer to the client row buffer, if big enough
   1.731 +// If the client buffer is too small it will attempt a second retrieval
   1.732 +TInt CDbsSession::WriteRowL(const RDbRow& aRow,const RMessage2& aMessage)
   1.733 +	{
   1.734 +	TInt size=aRow.Size();
   1.735 +	if (size>0 && size<=aMessage.Int2())
   1.736 +		aMessage.WriteL(3,TPtrC8((const TUint8*)aRow.First(),size));
   1.737 +	return size+1;		// return 0 reserved for Goto
   1.738 +	}
   1.739 +
   1.740 +// Returns a row to the client
   1.741 +TInt CDbsSession::RetrieveRowL(CDbCursor& aCursor,const RMessage2& aMessage)
   1.742 +	{
   1.743 +	RDbRow* pRow=aCursor.RowBuffer();
   1.744 +	if (pRow)	// direct row transfer
   1.745 +		return WriteRowL(*pRow,aMessage);
   1.746 +	// need to retrieve columns independantly
   1.747 +	RDbRow row;
   1.748 +	row.PushL();
   1.749 +	TInt max=aCursor.ColumnCount();
   1.750 +	for (TInt ii=0;++ii<=max;)
   1.751 +		TDbColumn(row,ii).SetL(aCursor.ColumnC(ii));
   1.752 +	TInt size=WriteRowL(row,aMessage);
   1.753 +	CleanupStack::PopAndDestroy();	// row
   1.754 +	return size;
   1.755 +	}
   1.756 +
   1.757 +//This method creates new EDbsCursor type object.
   1.758 +//It is used at table level so it needs table object security policies.
   1.759 +//The related table MPolicy interface will be 
   1.760 +//put together with the EDbsCursor object in TEntry list.
   1.761 +//
   1.762 +//Complete the cursor construction
   1.763 +TInt CDbsSession::NewCursorL(CDbCursor* aCursor,const RMessage2& aMessage, const MPolicy* aTblSecurityPolicy)
   1.764 +	{
   1.765 +	aCursor->PushL();		// it has a context: use safe cleanup
   1.766 +	TPckgBuf<TDbsColumns> cols;
   1.767 +	TInt ii=cols().iCount=aCursor->ColumnCount();
   1.768 +	if (ii<=cols().EMax)
   1.769 +		{
   1.770 +		while (--ii>=0)
   1.771 +			cols().iData[ii]=TUint8(aCursor->ColumnType(ii+1));
   1.772 +		}
   1.773 +	aMessage.WriteL(3,cols);
   1.774 +	CleanupStack::Pop(aCursor);
   1.775 +	return Add(aCursor, aTblSecurityPolicy);
   1.776 +	}
   1.777 +
   1.778 +//This method creates new EDbsIncremental type object.
   1.779 +//It is used either at database or  table level so it needs database or table object
   1.780 +//security policies. The related database/table MPolicy interface will be
   1.781 +//put together with the EDbsIncremental object in TEntry list.
   1.782 +//
   1.783 +//Complete a message which returns an incremental object by writing the step back
   1.784 +//When there is no work to do, aIncremental may be 0: then return a null handle
   1.785 +TInt CDbsSession::NewIncrementalL(CDbIncremental* aIncremental,
   1.786 +								  TInt& aInit,const RMessage2& aMessage,
   1.787 +								  const MPolicy* aPolicy)
   1.788 +	{
   1.789 +	aIncremental->PushL();		// it has a context: use safe cleanup
   1.790 +	aMessage.WriteL(3,TPckgC<TInt>(aInit));
   1.791 +	CleanupStack::Pop();
   1.792 +	return aIncremental ? Add(aIncremental, aPolicy) : 0;
   1.793 +	}
   1.794 +
   1.795 +//This method creates new EDbsStream type object.
   1.796 +//It is used either at database or table level so it needs either 
   1.797 +//database or table object security policies.
   1.798 +//The related database/table MPolicy interface will be
   1.799 +//put together with the EDbsStream object in TEntry list.
   1.800 +//
   1.801 +//Complete a stream based message return
   1.802 +TInt CDbsSession::NewStreamL(MStreamBuf* aHost,const RMessage2& aMessage,
   1.803 +							 const MPolicy* aPolicy,TInt aExtent)
   1.804 +	{
   1.805 +	aHost->PushL();
   1.806 +	TPckgBuf<TDbsStreamBuf> buf;
   1.807 +	if (aExtent>0)	// read the first buffer-full
   1.808 +		aHost->ReadL(buf().iData,Min(aExtent,KDbsStreamBufSize));
   1.809 +	TInt h=0;
   1.810 +	if (aExtent<0 || aExtent>KDbsStreamBufSize)
   1.811 +		{	// create the stream object
   1.812 +		HDbsStream* stream = new(ELeave) HDbsStream(aHost,KDbsStreamBufSize);
   1.813 +		h=Add(stream, aPolicy);
   1.814 +		CleanupStack::Pop();		// aHost
   1.815 +		}
   1.816 +	else	// no more data to send
   1.817 +		CleanupStack::PopAndDestroy();		// aHost
   1.818 +	if (aExtent>=0)
   1.819 +		{
   1.820 +		buf().iExt=aExtent;
   1.821 +		aMessage.WriteL(3,buf);
   1.822 +		}
   1.823 +	return h;
   1.824 +	}
   1.825 +
   1.826 +//This method creates new EDbsStream type object.
   1.827 +//It is used at database level so it needs the database object security policies.
   1.828 +//The related database MPolicy interface will be 
   1.829 +//put together with the EDbsStream object in TEntry list.
   1.830 +//
   1.831 +//Generic object passing code
   1.832 +//aPtr should be on the cleanup stack, aExter can externalize it
   1.833 +TInt CDbsSession::NewStreamL(TAny* aPtr,TExternalizeFunction aExter,
   1.834 +							 const RMessage2& aMessage, const MPolicy* aDbSecurityPolicy)
   1.835 +	{
   1.836 +	RWriteStream strm(HBufBuf::NewLC());
   1.837 +	aExter(aPtr,strm);
   1.838 +	strm.CommitL();
   1.839 +	TInt ext=strm.Sink()->SizeL();
   1.840 +	CleanupStack::Pop();			// host
   1.841 +	CleanupStack::PopAndDestroy();	// aPtr
   1.842 +	TInt res = NewStreamL(strm.Sink(),aMessage,aDbSecurityPolicy,ext);
   1.843 +	return res;
   1.844 +	}
   1.845 +
   1.846 +//allocates a free entry if required
   1.847 +void CDbsSession::AllocL()
   1.848 +	{
   1.849 +	__ASSERT(TUint(iFree)<=TUint(iSize));
   1.850 +	if (iFree==iSize)
   1.851 +		{
   1.852 +		TInt size=iSize+EIndexGranularity;
   1.853 +		if (size>KDbsIndexLimit)	// maximum number of objects reached
   1.854 +			__LEAVE(KErrNoMemory);
   1.855 +		TEntry* ix=iIx=(TEntry*)User::ReAllocL(iIx,size*sizeof(TEntry));
   1.856 +		iSize=size;
   1.857 +		for (TInt ii=iFree;ii<size;)
   1.858 +			{
   1.859 +			TEntry& e=ix[ii];
   1.860 +			e.iNext=++ii;
   1.861 +			e.iType=TUint8(EDbsFree);
   1.862 +			e.iPolicy = NULL;
   1.863 +			}
   1.864 +		}
   1.865 +	}
   1.866 +
   1.867 +// Sets the free entry and return a handle to it
   1.868 +TInt CDbsSession::DoAdd(TAny* aObject,TDbsType aType, const MPolicy* aPolicy)
   1.869 +	{
   1.870 +	__ASSERT(TUint(iFree)<TUint(iSize));
   1.871 +	__ASSERT(aType!=EDbsFree);
   1.872 +	TInt ix=iFree;
   1.873 +	TEntry& e=iIx[ix];
   1.874 +	__ASSERT(e.Type()==EDbsFree);
   1.875 +	iFree=e.iNext;
   1.876 +	__ASSERT(TUint(iFree)<=TUint(iSize));
   1.877 +	e.iObject=aObject;
   1.878 +	e.iType=TUint8(aType);
   1.879 +	e.iPolicy = aPolicy;
   1.880 +	TInt magic=(e.iMagic+1)&KDbsMagicMask;
   1.881 +	e.iMagic=TUint8(magic);
   1.882 +	return DbsMakeHandle(ix,magic,aType);
   1.883 +	}
   1.884 +
   1.885 +// releases the object and the entry to the free pool
   1.886 +void CDbsSession::Free(TEntry& aEntry)
   1.887 +	{
   1.888 +	__ASSERT(TUint(iFree)<=TUint(iSize));
   1.889 +	aEntry.Release();
   1.890 +	aEntry.iNext=iFree;
   1.891 +	iFree=&aEntry-&iIx[0];
   1.892 +	__ASSERT(TUint(iFree)<TUint(iSize));
   1.893 +	}
   1.894 +
   1.895 +CDbsSession::TEntry& CDbsSession::Object(TInt aHandle)
   1.896 +	{
   1.897 +	TEntry* e=0;
   1.898 +	TInt ix=DbsObjectIndex(aHandle);
   1.899 +	if (TUint(ix)<TUint(iSize))
   1.900 +		{
   1.901 +		e=&iIx[ix];
   1.902 +		if (DbsMakeHandle(ix,e->iMagic,e->Type())!=aHandle)
   1.903 +			e=0;
   1.904 +		}
   1.905 +	__ASSERT_ALWAYS(e && e->iPolicy,::Panic(EDbsBadHandle));
   1.906 +	return *e;
   1.907 +	}
   1.908 +
   1.909 +// Reports how many objects are allocated by the client
   1.910 +TInt CDbsSession::CountResources()
   1.911 +	{
   1.912 +	TInt alloc=0;
   1.913 +	const TEntry* const base=iIx;
   1.914 +	if (base)
   1.915 +		{
   1.916 +		for (const TEntry* e=base+iSize;--e>=base;)
   1.917 +			{
   1.918 +			if (e->Type()!=EDbsFree)
   1.919 +				++alloc;
   1.920 +			}
   1.921 +		}
   1.922 +	return alloc;
   1.923 +	}
   1.924 +
   1.925 +#ifdef __DBDUMP__
   1.926 +//Using CDbsSession::Dump() method you can dump the session content
   1.927 +//into a stream. Note that the dump works only if you have __DBDUMP__ macro defined.
   1.928 +void CDbsSession::Dump()
   1.929 +	{
   1.930 +	RFile dumpFile;
   1.931 +	RFs fileSess;
   1.932 +	TInt err = fileSess.Connect();
   1.933 +	if(err == KErrNone)
   1.934 +		{
   1.935 +		_LIT(KDumpFileName, "_:\\PUBLIC\\DBMS\\DUMP%X.TXT");
   1.936 +		TFileName dumpFileName(KDumpFileName);
   1.937 +		dumpFileName[0] = 'A' + static_cast<TInt>(RFs::GetSystemDrive());
   1.938 +		
   1.939 +		TBuf<40> buf;
   1.940 +		buf.Format(dumpFileName, this);
   1.941 +		err = fileSess.MkDirAll(buf);
   1.942 +		if(err == KErrNone || err == KErrAlreadyExists)
   1.943 +			{
   1.944 +			err = dumpFile.Replace(fileSess, buf, EFileWrite);
   1.945 +			if(err == KErrNone)
   1.946 +				{
   1.947 +				TEntry* const base = iIx;
   1.948 +				if(base)
   1.949 +					{
   1.950 +					for(TEntry* e=base+iSize;--e>=base;)
   1.951 +						{
   1.952 +						if(e->Type() != EDbsFree)
   1.953 +							{
   1.954 +							e->Dump(dumpFile);
   1.955 +							}
   1.956 +						}
   1.957 +					}//end of - if(base)
   1.958 +				}//end of - if(err == KErrNone)
   1.959 +			}
   1.960 +		}//end of - if(err == KErrNone)
   1.961 +	dumpFile.Close();
   1.962 +	fileSess.Close();
   1.963 +	RDebug::Print(_L("CDbsSession::Dump() error=%d\n"), err);
   1.964 +	__ASSERT_ALWAYS(err == KErrNone, User::Invariant());
   1.965 +	}
   1.966 +#endif//__DBDUMP__
   1.967 +
   1.968 +/**
   1.969 +Reserves a prederfined amount of disk space on aDrive drive. 
   1.970 +At the moment the max possible amount, allowed by the file server, is reserved on aDrive drive.
   1.971 +
   1.972 +Use this call to ensure that if your "delete records" transaction fails because of "out of
   1.973 +disk space" circumstances, you can get an access to the already reserved disk space and
   1.974 +complete your transaction successfully the second time.
   1.975 +
   1.976 +There is no strong, 100% guarantee, that the reserved disk space will always help the client
   1.977 +in "low memory" situations.
   1.978 +
   1.979 +This method processes EDbsReserveDriveSpace message.
   1.980 +
   1.981 +@param aDrive Drive number to reserve space on
   1.982 +@leave KErrArgument Invalid aDrive value.
   1.983 +@leave CDbsSessDriveSpace::ReserveL() leaving error codes
   1.984 +@see CDbsSessDriveSpace::ReserveL()
   1.985 +*/
   1.986 +void CDbsSession::ReserveDriveSpaceL(TDriveNumber aDrive)
   1.987 +	{
   1.988 +	if(aDrive < EDriveA || aDrive > EDriveZ)
   1.989 +        {
   1.990 +        __LEAVE(KErrArgument);
   1.991 +        }
   1.992 +    iSessDriveSpace->ReserveL(aDrive);
   1.993 +	}
   1.994 +
   1.995 +/**
   1.996 +The method frees the reserved by the DBMS session disk space.
   1.997 +
   1.998 +This method processes EDbsFreeReservedSpace message.
   1.999 +
  1.1000 +@param aDrive Drive number, which reserved space has to be freed.
  1.1001 +@see CDbsSessDriveSpace::Free()
  1.1002 +@panic Client side panic "DBMS-server 10" in debug mode, if the drive number is invalid.
  1.1003 +@panic In debug mode there will be a panic with the line number as an error code if 
  1.1004 +       there is no reserved disk space for aDrive. 
  1.1005 +@panic In debug mode there will be a panic with the line number as an error code if 
  1.1006 +       the reserved disk space is granted but not released.
  1.1007 +*/
  1.1008 +void CDbsSession::FreeReservedSpace(TDriveNumber aDrive)
  1.1009 +    {
  1.1010 +    TBool valid = aDrive >= EDriveA && aDrive <= EDriveZ;
  1.1011 +    __ASSERT_DEBUG(valid, ::Panic(EDbsInvalidDrive));
  1.1012 +    if(valid)
  1.1013 +        {
  1.1014 +        iSessDriveSpace->Free(aDrive);
  1.1015 +        }
  1.1016 +    }
  1.1017 +
  1.1018 +/**
  1.1019 +Grants access to a given area on a given drive for CDbsSession session.
  1.1020 +Note this session must have reserved space on this particular drive in order to be 
  1.1021 +granted access to the reserved area.
  1.1022 +
  1.1023 +This method processes EDbsReserveGetAccess message.
  1.1024 +  
  1.1025 +@param aDrive Drive number with a reserved disk space, an access to which is requested.
  1.1026 +@leave KErrArgument Invalid drive.
  1.1027 +@leave CDbsSessDriveSpace::GrantAccessL() leaving error codes
  1.1028 +@see CDbsSessDriveSpace::GrantAccessL()
  1.1029 +*/
  1.1030 +void CDbsSession::GetReserveAccessL(TDriveNumber aDrive)
  1.1031 +	{
  1.1032 +	if(aDrive < EDriveA || aDrive > EDriveZ)
  1.1033 +        {
  1.1034 +        __LEAVE(KErrArgument);
  1.1035 +        }
  1.1036 +    iSessDriveSpace->GrantAccessL(aDrive);
  1.1037 +	}
  1.1038 +
  1.1039 +/**
  1.1040 +Revokes access on a given drive for CDbsSession session.
  1.1041 +
  1.1042 +This method processes EDbsReserveReleaseAccess message.
  1.1043 +  
  1.1044 +@param aDrive Drive number with a reserved disk space, the access to which has to be released.
  1.1045 +@panic Client side panic "DBMS-server 10" in debug mode, if the drive number is invalid.
  1.1046 +@panic In debug mode there will be a panic with the line number as an error code if 
  1.1047 +       there is no reserved disk space for aDrive. 
  1.1048 +@panic In debug mode there will be a panic with the line number as an error code if 
  1.1049 +       there is no granted access to the reserved disk space. 
  1.1050 +*/
  1.1051 +void CDbsSession::ReleaseReserveAccess(TDriveNumber aDrive)
  1.1052 +	{
  1.1053 +    TBool valid = aDrive >= EDriveA && aDrive <= EDriveZ;
  1.1054 +    __ASSERT_DEBUG(valid, ::Panic(EDbsInvalidDrive));
  1.1055 +    if(valid)
  1.1056 +        {
  1.1057 +        iSessDriveSpace->ReleaseAccess(aDrive);
  1.1058 +        }
  1.1059 +	}