1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sql/SRC/Server/Compact/SqlCompact.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,269 @@
1.4 +// Copyright (c) 2008-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 "SqlAssert.h"
1.20 +#include "SqlCompact.h"
1.21 +#include "SqlCompactEntry.h"
1.22 +#include "SqlCompactTimer.h"
1.23 +#include "SqlUtil.h"
1.24 +#include "OstTraceDefinitions.h"
1.25 +#ifdef OST_TRACE_COMPILER_IN_USE
1.26 +#include "SqlCompactTraces.h"
1.27 +#endif
1.28 +#include "SqlTraceDef.h"
1.29 +
1.30 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.31 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.32 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.33 +
1.34 +/**
1.35 +Initializes the background compaction settings with their default values.
1.36 +*/
1.37 +TSqlCompactSettings::TSqlCompactSettings() :
1.38 + iStepLength(KSqlCompactStepLengthMs),
1.39 + iFreePageThresholdKb(KSqlCompactFreePageThresholdKb)
1.40 + {
1.41 + }
1.42 +
1.43 +#ifdef _DEBUG
1.44 +/**
1.45 +CSqlCompactSettings invariant.
1.46 +*/
1.47 +void TSqlCompactSettings::Invariant() const
1.48 + {
1.49 + __ASSERT_DEBUG(iStepLength > 0, __SQLPANIC(ESqlPanicInternalError));
1.50 + __ASSERT_DEBUG(iFreePageThresholdKb >= 0, __SQLPANIC(ESqlPanicInternalError));
1.51 + }
1.52 +#endif//_DEBUG
1.53 +
1.54 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.55 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.56 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.57 +
1.58 +/**
1.59 +The granularity of the container maintained by CSqlCompactor
1.60 +
1.61 +@see CSqlCompactor
1.62 +@internalComponent
1.63 +*/
1.64 +const TInt KEntriesGranularity = 16;
1.65 +
1.66 +/**
1.67 +Creates a new CSqlCompactor instance.
1.68 +
1.69 +@param aConnFactoryL MSqlCompactConn factory function.
1.70 +@param aCompactStepInterval The time interval (ms) between the background compaction steps.
1.71 +
1.72 +@return A pointer to the created CSqlCompactor instance
1.73 +
1.74 +@leave KErrNoMemory, an out of memory condition has occurred;
1.75 + Note that the function may also leave with some other database specific
1.76 + errors categorised as ESqlDbError, and other system-wide error codes.
1.77 +
1.78 +@panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
1.79 +@panic SqlDb 4 In _DEBUG mode. Zero or negative aCompactStepInterval.
1.80 +*/
1.81 +CSqlCompactor* CSqlCompactor::NewL(TSqlCompactConnFactoryL aConnFactoryL, TInt aCompactStepInterval)
1.82 + {
1.83 + __ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC2(ESqlPanicBadArgument));
1.84 + __ASSERT_DEBUG(aCompactStepInterval > 0, __SQLPANIC2(ESqlPanicBadArgument));
1.85 + CSqlCompactor* self = new (ELeave) CSqlCompactor(aConnFactoryL);
1.86 + CleanupStack::PushL(self);
1.87 + self->ConstructL(aCompactStepInterval);
1.88 + CleanupStack::Pop(self);
1.89 + return self;
1.90 + }
1.91 +
1.92 +/**
1.93 +Destroys the CSqlCompactor instance.
1.94 +Any entries left in the container will be destroyed.
1.95 +*/
1.96 +CSqlCompactor::~CSqlCompactor()
1.97 + {
1.98 + for(TInt idx=iEntries.Count()-1;idx>=0;--idx)
1.99 + {
1.100 + __ASSERT_DEBUG(iEntries[idx] != NULL, __SQLPANIC(ESqlPanicInternalError));
1.101 + while(iEntries[idx]->Release() != 0)
1.102 + {
1.103 + }
1.104 + }
1.105 + iEntries.Close();
1.106 + delete iTimer;
1.107 + }
1.108 +
1.109 +/**
1.110 +Restarts the background compaction timer.
1.111 +This function should be called from the server side session object's ServiceL().
1.112 +If ServiceL() is being executed at the moment, it is very likely that the SQL client(s) will issue another
1.113 +request few ms later. In order to not delay the processing of the client(s) requests, ServiceL() should call
1.114 +at the end RestartTimer(). If there are database entries scheduled for a background compaction, the compaction
1.115 +will be delayed by the time interval used by the CSqlCompactTimer object (default value - KSqlCompactStepInterval).
1.116 +
1.117 +@see CSqlCompactTimer
1.118 +@see KSqlCompactStepInterval
1.119 +*/
1.120 +void CSqlCompactor::RestartTimer()
1.121 + {
1.122 + SQLCOMPACTOR_INVARIANT();
1.123 + iTimer->Restart();
1.124 + SQLCOMPACTOR_INVARIANT();
1.125 + }
1.126 +
1.127 +/**
1.128 +If an entry referring to a database with name aFullName does not exist in the container, a new entry will be created,
1.129 +a connection with the database established.
1.130 +If an entry with the specified name already exists, no new entry wil be created, the reference counter of the existing one
1.131 +will be incremented.
1.132 +
1.133 +@param aFullName The full database name, including the path.
1.134 +@param aSettings Per-database background compaction settings
1.135 +
1.136 +@leave KErrNoMemory, an out of memory condition has occurred;
1.137 + Note that the function may also leave with some other database specific
1.138 + errors categorised as ESqlDbError, and other system-wide error codes.
1.139 +
1.140 +@panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter)
1.141 +@panic SqlDb 7 In _DEBUG mode. An entry with the specified name has been found but the entry is NULL.
1.142 +*/
1.143 +void CSqlCompactor::AddEntryL(const TDesC& aFullName, const TSqlCompactSettings& aSettings)
1.144 + {
1.145 + __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC(ESqlPanicBadArgument));
1.146 + SQLCOMPACTOR_INVARIANT();
1.147 + CSqlCompactEntry* entry = NULL;
1.148 + TInt idx = iEntries.FindInOrder(aFullName, &CSqlCompactor::Search);
1.149 + if(idx == KErrNotFound)
1.150 + {
1.151 + SQL_TRACE_COMPACT(OstTraceExt4(TRACE_INTERNALS, CSQLCOMPACTOR_ADDENTRYL1, "0x%X;CSqlCompactor::AddEntryL;New entry;aFullName=%S;iStepLength=%d;iFreePageThreashold=%d", (TUint)this, __SQLPRNSTR(aFullName), aSettings.iStepLength, aSettings.iFreePageThresholdKb));
1.152 + entry = CSqlCompactEntry::NewLC(aFullName, iConnFactoryL, aSettings, *iTimer);
1.153 + TLinearOrder<CSqlCompactEntry> order(&CSqlCompactor::Compare);
1.154 + __SQLLEAVE_IF_ERROR(iEntries.InsertInOrder(entry, order));
1.155 + CleanupStack::Pop(entry);
1.156 + }
1.157 + else
1.158 + {
1.159 + SQL_TRACE_COMPACT(OstTraceExt4(TRACE_INTERNALS, CSQLCOMPACTOR_ADDENTRYL2, "0x%X;CSqlCompactor::AddEntryL;Reuse entry;aFullName=%S;iStepLength=%d;iFreePageThreashold=%d", (TUint)this, __SQLPRNSTR(aFullName), aSettings.iStepLength, aSettings.iFreePageThresholdKb));
1.160 + entry = iEntries[idx];
1.161 + __ASSERT_DEBUG(entry != NULL, __SQLPANIC(ESqlPanicInternalError));
1.162 + (void)entry->AddRef();
1.163 + }
1.164 + SQLCOMPACTOR_INVARIANT();
1.165 + }
1.166 +
1.167 +/**
1.168 +Decrements the reference counter of the specified entry.
1.169 +If the counter reaches zero, the entry will be destroyed and removed from the container,
1.170 +the database connection - closed.
1.171 +
1.172 +@param aFullName The full database name, including the path.
1.173 +*/
1.174 +void CSqlCompactor::ReleaseEntry(const TDesC& aFullName)
1.175 + {
1.176 + SQL_TRACE_COMPACT(OstTraceExt2(TRACE_INTERNALS, CSQLCOMPACTOR_RELEASEENTRY1, "0x%X;CSqlCompactor::ReleaseEntry;aFullName=%S", (TUint)this, __SQLPRNSTR(aFullName)));
1.177 + SQLCOMPACTOR_INVARIANT();
1.178 + TInt idx = iEntries.FindInOrder(aFullName, &CSqlCompactor::Search);
1.179 + __ASSERT_DEBUG(idx >= 0, __SQLPANIC(ESqlPanicInternalError));
1.180 + if(idx >= 0)
1.181 + {
1.182 + CSqlCompactEntry* entry = iEntries[idx];
1.183 + __ASSERT_DEBUG(entry != NULL, __SQLPANIC(ESqlPanicInternalError));
1.184 + if(entry)
1.185 + {
1.186 + if(entry->Release() == 0)
1.187 + {
1.188 + iEntries.Remove(idx);
1.189 +#ifdef _DEBUG
1.190 +//This is used prevent the failure of the resource allocation checking for debug mode.
1.191 + if(iEntries.Count() == 0)
1.192 + {
1.193 + iEntries.Reset();
1.194 + }
1.195 +#endif
1.196 + }
1.197 + }
1.198 + }
1.199 + SQLCOMPACTOR_INVARIANT();
1.200 + }
1.201 +
1.202 +/**
1.203 +Initializes the CSqlCompactor data members with their default values.
1.204 +
1.205 +@param aConnFactoryL MSqlCompactConn factory function.
1.206 +
1.207 +@panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
1.208 +*/
1.209 +CSqlCompactor::CSqlCompactor(TSqlCompactConnFactoryL aConnFactoryL) :
1.210 + iConnFactoryL(aConnFactoryL),
1.211 + iEntries(KEntriesGranularity)
1.212 + {
1.213 + __ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC(ESqlPanicBadArgument));
1.214 + }
1.215 +
1.216 +/**
1.217 +Initializes the created CSqlCompactor instance.
1.218 +
1.219 +@param aCompactStepInterval The time interval between the background compaction steps.
1.220 +
1.221 +@panic SqlDb 4 In _DEBUG mode. Zero or negative aCompactStepInterval.
1.222 +*/
1.223 +void CSqlCompactor::ConstructL(TInt aCompactStepInterval)
1.224 + {
1.225 + __ASSERT_DEBUG(aCompactStepInterval > 0, __SQLPANIC(ESqlPanicBadArgument));
1.226 + iTimer = CSqlCompactTimer::NewL(aCompactStepInterval);
1.227 + }
1.228 +
1.229 +/**
1.230 +Static method used internally for performing a search in the container using database name as a key.
1.231 +
1.232 +@param aFullName The full database name, including the path.
1.233 +@param aEntry CSqlCompactor reference.
1.234 +*/
1.235 +/* static */TInt CSqlCompactor::Search(const TDesC* aFullName, const CSqlCompactEntry& aEntry)
1.236 + {
1.237 + __ASSERT_DEBUG(&aEntry != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.238 + __ASSERT_DEBUG(aFullName != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.239 + const TDesC& fullName = *aFullName;
1.240 + __ASSERT_DEBUG(fullName.Length() > 0 && fullName.Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
1.241 + __ASSERT_DEBUG(aEntry.FullName().Length() > 0 && aEntry.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
1.242 + return fullName.CompareF(aEntry.FullName());
1.243 + }
1.244 +
1.245 +/**
1.246 +Static method used internally for performing a search in the container using a CSqlCompactEntry reference as a key.
1.247 +*/
1.248 +/* static */TInt CSqlCompactor::Compare(const CSqlCompactEntry& aLeft, const CSqlCompactEntry& aRight)
1.249 + {
1.250 + __ASSERT_DEBUG(&aLeft != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.251 + __ASSERT_DEBUG(&aRight != NULL, __SQLPANIC2(ESqlPanicInternalError));
1.252 + __ASSERT_DEBUG(aLeft.FullName().Length() > 0 && aLeft.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
1.253 + __ASSERT_DEBUG(aRight.FullName().Length() > 0 && aRight.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
1.254 + return aLeft.FullName().CompareF(aRight.FullName());
1.255 + }
1.256 +
1.257 +#ifdef _DEBUG
1.258 +/**
1.259 +CSqlCompactor invariant.
1.260 +*/
1.261 +void CSqlCompactor::Invariant() const
1.262 + {
1.263 + __ASSERT_DEBUG(iConnFactoryL != NULL, __SQLPANIC(ESqlPanicInternalError));
1.264 + __ASSERT_DEBUG(iTimer != NULL, __SQLPANIC(ESqlPanicInternalError));
1.265 + iTimer->Invariant();
1.266 + for(TInt idx=iEntries.Count()-1;idx>=0;--idx)
1.267 + {
1.268 + __ASSERT_DEBUG(iEntries[idx] != NULL, __SQLPANIC(ESqlPanicInternalError));
1.269 + iEntries[idx]->Invariant();
1.270 + }
1.271 + }
1.272 +#endif//_DEBUG