os/persistentdata/persistentstorage/sql/SRC/Client/SqlDatabaseImpl.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sql/SRC/Client/SqlDatabaseImpl.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,289 @@
     1.4 +// Copyright (c) 2005-2010 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 +//
    1.18 +
    1.19 +#include "SqlSecurityImpl.h"	//CSqlSecurityPolicy
    1.20 +#include "SqlDatabaseImpl.h"	//CSqlDatabaseImpl
    1.21 +#include <e32debug.h>
    1.22 +
    1.23 +/**
    1.24 +Manual compaction - max compacton step execution time in microseconds.
    1.25 +
    1.26 +@internalComponent
    1.27 +*/
    1.28 +static const TInt KCompactMaxStepTimeUs = 100000;
    1.29 +
    1.30 +/**
    1.31 +Minimal amount of free database space to be removed by the compaction steps.
    1.32 +
    1.33 +@internalComponent
    1.34 +*/
    1.35 +static const TInt KCompactMinStepSize =  2 * 1024;
    1.36 +
    1.37 +/**
    1.38 +The amount of free database space to be removed by the first compaction step.
    1.39 +
    1.40 +@internalComponent
    1.41 +*/
    1.42 +static const TInt KCompactStartStepSize = 32 * 1024;
    1.43 +
    1.44 +/**
    1.45 +The aim of the function is to determine the maximum size of space to be freed, which fits within the time constraint.
    1.46 +The decision is based on the time spent on the pervious compaction step.
    1.47 +If the time is bigger than KCompactMaxStepTimeUs then the space will be reduced by factor of 2 (slow media),
    1.48 +bet will never be less than KCompactMinStepSize.
    1.49 +If the time is less than the KCompactMaxStepTimeUs/2 then the space will be increased by factor of 2 (fast media).
    1.50 +
    1.51 +@param aRemaining The remaining free database space.
    1.52 +@param aStep The size of the space removed by the previous compaction step.
    1.53 +@param aTime The execution time of the previous compaction step.
    1.54 +
    1.55 +@return The size in bytes if the next comaction step - the amount of space to be removed.
    1.56 +
    1.57 +@see KMaxStepTimeUs
    1.58 +@see KMinStepSize
    1.59 +@see KStartStepSize
    1.60 +
    1.61 +@internalComponent
    1.62 +*/
    1.63 +static TInt CalcCompactionStep(TInt aRemaining, TInt aStep, TInt aTime)
    1.64 +	{
    1.65 +	if(aTime > KCompactMaxStepTimeUs)
    1.66 +		{
    1.67 +		aStep /= 2;
    1.68 +		if(aStep < KCompactMinStepSize)
    1.69 +			{
    1.70 +			aStep = KCompactMinStepSize; 
    1.71 +			}
    1.72 +		}
    1.73 +	else if(aTime <= (KCompactMaxStepTimeUs / 2))
    1.74 +		{
    1.75 +		aStep *= 2;
    1.76 +		}
    1.77 +	if(aRemaining < aStep)
    1.78 +		{//If, for example, aStep is 4000 bytes, aRemaining is 2000 bytes, then the step should be 2000,  
    1.79 +		 //because that is what is left in the database as a free space.
    1.80 +		aStep = aRemaining;
    1.81 +		}
    1.82 +	return aStep;
    1.83 +	}
    1.84 + 
    1.85 +/**
    1.86 +Creates a new CSqlDatabaseImpl instance.
    1.87 +
    1.88 +CSqlDatabaseImpl implements RSqlDatabase, which means that CSqlDatabaseImpl instance will be created from 
    1.89 +RSqlDatabase functions doing RSqlDatabase instance initialization - Create() and Open().
    1.90 +
    1.91 +@param aFunction It may have one of the following values: 																																																																																																																																																																																																																																																																																																																																																																																																							
    1.92 + ESqlSrvDbCreate       - Create a shared non-secure or private secure database;
    1.93 + ESqlSrvDbCreateSecure - Create a shared secure database;
    1.94 + ESqlSrvDbOpen         - Open a shared non-secure, shared secure or private secure database;
    1.95 +	
    1.96 +@param aDbFileName The name of the file that is to host the database.
    1.97 +				   If it is a secure database, then the format of the name is 
    1.98 +				   \<drive\>:\<[SID]database file name excluding the path\>. "[SID]" refers to the application SID.
    1.99 +				   If it is a non-secure database then aDbFileName should contain the full path name of the file 
   1.100 +				   that is to host the database.
   1.101 +@param aSecurityPolicy The container for the security policies. 
   1.102 +				   aSecurityPolicy is NULL if aDbFileName refers to a non-secure database.
   1.103 +@param aConfig the configuration string "PARAM=VALUE;...."
   1.104 +
   1.105 +@return A pointer to the created CSqlDatabaseImpl instance.
   1.106 +
   1.107 +@leave KErrNoMemory, an out of memory condition has occurred;
   1.108 +       KErrBadName, the file name is invalid - it has either a zero length or it is the name of a directory;
   1.109 +       KErrArgument, system table name found in the security policies (aSecurityPolicy);
   1.110 +       KErrAlreadyExists, the file already exists;
   1.111 +       KErrNotReady, the drive does not exist or is not ready;
   1.112 +       KErrInUse, the file is already open;
   1.113 +       KErrNotFound, database file not found;
   1.114 +       KErrGeneral, missing or invalid security policies (if the database to be opened is a secure database);
   1.115 +       KErrNotSupported, incompatible SQL security version (if the database to be opened is a secure database).
   1.116 +       KErrPermissionDenied, the caller does not satisfy the relevant database security policies.
   1.117 +                      Note that the function may leave with database specific errors categorised as ESqlDbError and
   1.118 +                      other system-wide error codes.
   1.119 +                      
   1.120 +@see RSqlDatabase
   1.121 +@see RSqlDatabase::Create()
   1.122 +@see RSqlDatabase::Open()
   1.123 +@see TSqlSrvFunction
   1.124 +@see CSqlSecurityPolicy
   1.125 +*/
   1.126 +CSqlDatabaseImpl* CSqlDatabaseImpl::NewL(TSqlSrvFunction aFunction, const TDesC& aDbFileName, 
   1.127 +										 const CSqlSecurityPolicy* aSecurityPolicy,
   1.128 +										 const TDesC8* aConfig)
   1.129 +	{
   1.130 +	CSqlDatabaseImpl* self = new (ELeave) CSqlDatabaseImpl;
   1.131 +	CleanupStack::PushL(self);
   1.132 +	self->ConstructL(aFunction, aDbFileName, aSecurityPolicy, aConfig);
   1.133 +	CleanupStack::Pop(self);
   1.134 +	return self;
   1.135 +	}
   1.136 +
   1.137 +/**
   1.138 +Initializes the created CSqlDatabaseImpl instance.
   1.139 +
   1.140 +@param aFunction It may have one of the following values:
   1.141 +  ESqlSrvDbCreate       - Create a shared non-secure or private secure database;
   1.142 +  ESqlSrvDbCreateSecure - Create a shared secure database;
   1.143 +  ESqlSrvDbOpen         - Open a shared non-secure, shared secure or private secure database;
   1.144 +
   1.145 +@param aDbFileName The name of the file that is to host the database.
   1.146 +				   If it is a secure database, then the format of the name is 
   1.147 +				   \<drive\>:\<[SID]database file name excluding the path\>. "[SID]" refers to the application SID.
   1.148 +				   If it is a non-secure database then aDbFileName should contain the full path name of the file 
   1.149 +				   that is to host the database.
   1.150 +@param aSecurityPolicy The container for the security policies. 
   1.151 +				   aSecurityPolicy is NULL if aDbFileName refers to a non-secure database.
   1.152 +@param aConfig the configuration string "PARAM=VALUE;...."
   1.153 +
   1.154 +@leave KErrNoMemory, an out of memory condition has occurred;
   1.155 +       KErrBadName, the file name is invalid - it has either a zero length or it is the name of a directory;
   1.156 +       KErrArgument, system table name found in the security policies (aSecurityPolicy);
   1.157 +       KErrAlreadyExists, the file already exists;
   1.158 +       KErrNotReady, the drive does not exist or is not ready;
   1.159 +       KErrInUse, the file is already open;
   1.160 +       KErrNotFound, database file not found;
   1.161 +       KErrGeneral, missing or invalid security policies (if the database to be opened is a secure database);
   1.162 +       KErrNotSupported, incompatible SQL security version (if the database to be opened is a secure database).
   1.163 +       KErrPermissionDenied, the caller does not satisfy the relevant database security policies.
   1.164 +                      Note that the function may leave with database specific errors categorised as ESqlDbError and
   1.165 +                      other system-wide error codes.
   1.166 +
   1.167 +@see CSqlDatabaseImpl::NewL()
   1.168 +
   1.169 +@panic SqlDb 4 In _DEBUG mode. aSecurityPolicy is NULL, but the request is for opening/creating a secure database.
   1.170 +*/
   1.171 +void CSqlDatabaseImpl::ConstructL(TSqlSrvFunction aFunction, const TDesC& aDbFileName, 
   1.172 +								  const CSqlSecurityPolicy* aSecurityPolicy, const TDesC8* aConfig)
   1.173 +	{
   1.174 +	TPtrC8 securityPolicyData;
   1.175 +	if(aFunction == ESqlSrvDbCreateSecure)	
   1.176 +		{
   1.177 +		__ASSERT_DEBUG(aSecurityPolicy != NULL, __SQLPANIC(ESqlPanicBadArgument));
   1.178 +		const RSqlBufFlat& bufFlat = aSecurityPolicy->BufFlat();
   1.179 +		securityPolicyData.Set(bufFlat.BufDes());
   1.180 +		}
   1.181 +	__SQLLEAVE_IF_ERROR(Session().Connect(aFunction, aDbFileName, securityPolicyData, aConfig));
   1.182 +	}
   1.183 +
   1.184 +/**
   1.185 +Frees the allocated by CSqlDatabaseImpl instance memory and other resources.
   1.186 +*/
   1.187 +CSqlDatabaseImpl::~CSqlDatabaseImpl()
   1.188 +	{
   1.189 +	Session().Close();
   1.190 +	}
   1.191 +
   1.192 +/**
   1.193 +Creates and returns a copy of the database security policies object.
   1.194 +The caller is responsible for destroying the returned CSqlSecurityPolicy instance.
   1.195 +
   1.196 +Implements RSqlDatabase::GetSecurityPolicyL().
   1.197 +
   1.198 +@return A copy of the database security policies object. 
   1.199 +        The returned copy must be destroyed by the caller.
   1.200 +        
   1.201 +@leave KErrNotSupported, the current database is not a secure database;
   1.202 +       KErrNoMemory, an out of memory condition has occurred;
   1.203 +
   1.204 +@see RSqlDatabase
   1.205 +@see RSqlDatabase::GetSecurityPolicyL()
   1.206 +*/
   1.207 +CSqlSecurityPolicy* CSqlDatabaseImpl::CloneSecurityPolicyL()
   1.208 +	{
   1.209 +	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
   1.210 +	CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
   1.211 +	__SQLLEAVE_IF_ERROR(Session().GetSecurityPolicy(dbPolicy->BufFlat()));
   1.212 +	CleanupStack::Pop(dbPolicy);
   1.213 +	return dbPolicy;
   1.214 +	}
   1.215 +
   1.216 +/**
   1.217 +Implements RSqlDatabase::Compact().
   1.218 +
   1.219 +@param aSize Can be one of:
   1.220 +				 RSqlDatabase::EMaxCompaction - requests a full database compaction. All free pages
   1.221 +				  (if any exists) will be removed;
   1.222 +				 Positive integer value - the server will attempt to compact the database removing 
   1.223 +				  at most aSize bytes from the database file, rounded up to the nearest page count, 
   1.224 +				  e.g. request for removing 1 byte will remove one free page from the database;
   1.225 +@param aDbName The attached database name or KNullDesC for the main database
   1.226 +
   1.227 +@return Zero or positive integer - the operation has completed succesfully, the return value is the
   1.228 +         						   size of the removed free space in bytes,
   1.229 +		KErrArgument, Invalid aSize value;
   1.230 +        KErrBadName, Invalid (too long) attached database name;
   1.231 +        KSqlErrReadOnly, Read-only database;
   1.232 +        KSqlErrGeneral, There is no an attached database with aDbName name;
   1.233 +                  Note that database specific errors categorised as ESqlDbError, and
   1.234 +                  other system-wide error codes may also be returned.
   1.235 +
   1.236 +Usage of the IPC call arguments:
   1.237 +Arg 0: [out]	How much space in bytes should be compacted, all free pages should be removed if the
   1.238 +				parameter value is RSqlDatabase::EMaxCompaction.
   1.239 +Arg 1: [out]	The database name length in characters
   1.240 +Arg 2: [out]	The attached database name or KNullDesC for the main database
   1.241 +*/
   1.242 +TInt CSqlDatabaseImpl::Compact(TInt aSize, const TDesC& aDbName)
   1.243 +	{
   1.244 +	if(aSize < 0)
   1.245 +		{
   1.246 +		if(aSize != RSqlDatabase::EMaxCompaction)
   1.247 +			{
   1.248 +			return KErrArgument;
   1.249 +			}
   1.250 +		aSize = KMaxTInt;
   1.251 +		}
   1.252 +	TInt remaining = aSize;
   1.253 +	TInt compacted = 0;
   1.254 +	TInt step = KCompactStartStepSize;
   1.255 +	TInt rc = 0;
   1.256 +	TTimeIntervalMicroSeconds interval(0);
   1.257 +	while(remaining > 0)
   1.258 +		{
   1.259 +		step = ::CalcCompactionStep(remaining, step, interval.Int64());
   1.260 +		TTime start;
   1.261 +		start.HomeTime();
   1.262 +		rc = Session().SendReceive(ESqlSrvDbCompact, TIpcArgs(step, aDbName.Length(), &aDbName));
   1.263 +		if(rc <= 0)
   1.264 +			{
   1.265 +			break;	
   1.266 +			}
   1.267 +		TTime end;
   1.268 +		end.HomeTime();
   1.269 +		interval = end.MicroSecondsFrom(start);
   1.270 +		remaining -= rc;				
   1.271 +		compacted += rc;
   1.272 +		}
   1.273 +	return rc < 0 ? rc : compacted;
   1.274 +	}
   1.275 +
   1.276 +/**
   1.277 +Usage of the IPC call arguments:
   1.278 +Arg 0: [out]	How much space in bytes should be compacted, all free pages should be removed if the
   1.279 +				parameter value is RSqlDatabase::EMaxCompaction.
   1.280 +Arg 1: [out]	The database name length in characters
   1.281 +Arg 2: [out]	The attached database name or KNullDesC for the main database
   1.282 +*/
   1.283 +void CSqlDatabaseImpl::Compact(TInt aSize, const TDesC& aDbName, TRequestStatus& aStatus)
   1.284 +	{
   1.285 +	if(aSize == 0)
   1.286 +		{
   1.287 +		TRequestStatus* stat = &aStatus;
   1.288 +		User::RequestComplete(stat, 0);
   1.289 +		return;
   1.290 +		}
   1.291 +	Session().SendReceive(ESqlSrvDbCompact, TIpcArgs(aSize, aDbName.Length(), &aDbName), aStatus);
   1.292 +	}