sl@0: // Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "SqlAssert.h" sl@0: #include "SqlCompact.h" sl@0: #include "SqlCompactEntry.h" sl@0: #include "SqlCompactTimer.h" sl@0: #include "SqlUtil.h" sl@0: #include "OstTraceDefinitions.h" sl@0: #ifdef OST_TRACE_COMPILER_IN_USE sl@0: #include "SqlCompactTraces.h" sl@0: #endif sl@0: #include "SqlTraceDef.h" sl@0: sl@0: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: /** sl@0: Initializes the background compaction settings with their default values. sl@0: */ sl@0: TSqlCompactSettings::TSqlCompactSettings() : sl@0: iStepLength(KSqlCompactStepLengthMs), sl@0: iFreePageThresholdKb(KSqlCompactFreePageThresholdKb) sl@0: { sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: /** sl@0: CSqlCompactSettings invariant. sl@0: */ sl@0: void TSqlCompactSettings::Invariant() const sl@0: { sl@0: __ASSERT_DEBUG(iStepLength > 0, __SQLPANIC(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(iFreePageThresholdKb >= 0, __SQLPANIC(ESqlPanicInternalError)); sl@0: } sl@0: #endif//_DEBUG sl@0: sl@0: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: /** sl@0: The granularity of the container maintained by CSqlCompactor sl@0: sl@0: @see CSqlCompactor sl@0: @internalComponent sl@0: */ sl@0: const TInt KEntriesGranularity = 16; sl@0: sl@0: /** sl@0: Creates a new CSqlCompactor instance. sl@0: sl@0: @param aConnFactoryL MSqlCompactConn factory function. sl@0: @param aCompactStepInterval The time interval (ms) between the background compaction steps. sl@0: sl@0: @return A pointer to the created CSqlCompactor instance sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred; sl@0: Note that the function may also leave with some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL. sl@0: @panic SqlDb 4 In _DEBUG mode. Zero or negative aCompactStepInterval. sl@0: */ sl@0: CSqlCompactor* CSqlCompactor::NewL(TSqlCompactConnFactoryL aConnFactoryL, TInt aCompactStepInterval) sl@0: { sl@0: __ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC2(ESqlPanicBadArgument)); sl@0: __ASSERT_DEBUG(aCompactStepInterval > 0, __SQLPANIC2(ESqlPanicBadArgument)); sl@0: CSqlCompactor* self = new (ELeave) CSqlCompactor(aConnFactoryL); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aCompactStepInterval); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: Destroys the CSqlCompactor instance. sl@0: Any entries left in the container will be destroyed. sl@0: */ sl@0: CSqlCompactor::~CSqlCompactor() sl@0: { sl@0: for(TInt idx=iEntries.Count()-1;idx>=0;--idx) sl@0: { sl@0: __ASSERT_DEBUG(iEntries[idx] != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: while(iEntries[idx]->Release() != 0) sl@0: { sl@0: } sl@0: } sl@0: iEntries.Close(); sl@0: delete iTimer; sl@0: } sl@0: sl@0: /** sl@0: Restarts the background compaction timer. sl@0: This function should be called from the server side session object's ServiceL(). sl@0: If ServiceL() is being executed at the moment, it is very likely that the SQL client(s) will issue another sl@0: request few ms later. In order to not delay the processing of the client(s) requests, ServiceL() should call sl@0: at the end RestartTimer(). If there are database entries scheduled for a background compaction, the compaction sl@0: will be delayed by the time interval used by the CSqlCompactTimer object (default value - KSqlCompactStepInterval). sl@0: sl@0: @see CSqlCompactTimer sl@0: @see KSqlCompactStepInterval sl@0: */ sl@0: void CSqlCompactor::RestartTimer() sl@0: { sl@0: SQLCOMPACTOR_INVARIANT(); sl@0: iTimer->Restart(); sl@0: SQLCOMPACTOR_INVARIANT(); sl@0: } sl@0: sl@0: /** sl@0: If an entry referring to a database with name aFullName does not exist in the container, a new entry will be created, sl@0: a connection with the database established. sl@0: If an entry with the specified name already exists, no new entry wil be created, the reference counter of the existing one sl@0: will be incremented. sl@0: sl@0: @param aFullName The full database name, including the path. sl@0: @param aSettings Per-database background compaction settings sl@0: sl@0: @leave KErrNoMemory, an out of memory condition has occurred; sl@0: Note that the function may also leave with some other database specific sl@0: errors categorised as ESqlDbError, and other system-wide error codes. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter) sl@0: @panic SqlDb 7 In _DEBUG mode. An entry with the specified name has been found but the entry is NULL. sl@0: */ sl@0: void CSqlCompactor::AddEntryL(const TDesC& aFullName, const TSqlCompactSettings& aSettings) sl@0: { sl@0: __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC(ESqlPanicBadArgument)); sl@0: SQLCOMPACTOR_INVARIANT(); sl@0: CSqlCompactEntry* entry = NULL; sl@0: TInt idx = iEntries.FindInOrder(aFullName, &CSqlCompactor::Search); sl@0: if(idx == KErrNotFound) sl@0: { sl@0: 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)); sl@0: entry = CSqlCompactEntry::NewLC(aFullName, iConnFactoryL, aSettings, *iTimer); sl@0: TLinearOrder order(&CSqlCompactor::Compare); sl@0: __SQLLEAVE_IF_ERROR(iEntries.InsertInOrder(entry, order)); sl@0: CleanupStack::Pop(entry); sl@0: } sl@0: else sl@0: { sl@0: 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)); sl@0: entry = iEntries[idx]; sl@0: __ASSERT_DEBUG(entry != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: (void)entry->AddRef(); sl@0: } sl@0: SQLCOMPACTOR_INVARIANT(); sl@0: } sl@0: sl@0: /** sl@0: Decrements the reference counter of the specified entry. sl@0: If the counter reaches zero, the entry will be destroyed and removed from the container, sl@0: the database connection - closed. sl@0: sl@0: @param aFullName The full database name, including the path. sl@0: */ sl@0: void CSqlCompactor::ReleaseEntry(const TDesC& aFullName) sl@0: { sl@0: SQL_TRACE_COMPACT(OstTraceExt2(TRACE_INTERNALS, CSQLCOMPACTOR_RELEASEENTRY1, "0x%X;CSqlCompactor::ReleaseEntry;aFullName=%S", (TUint)this, __SQLPRNSTR(aFullName))); sl@0: SQLCOMPACTOR_INVARIANT(); sl@0: TInt idx = iEntries.FindInOrder(aFullName, &CSqlCompactor::Search); sl@0: __ASSERT_DEBUG(idx >= 0, __SQLPANIC(ESqlPanicInternalError)); sl@0: if(idx >= 0) sl@0: { sl@0: CSqlCompactEntry* entry = iEntries[idx]; sl@0: __ASSERT_DEBUG(entry != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: if(entry) sl@0: { sl@0: if(entry->Release() == 0) sl@0: { sl@0: iEntries.Remove(idx); sl@0: #ifdef _DEBUG sl@0: //This is used prevent the failure of the resource allocation checking for debug mode. sl@0: if(iEntries.Count() == 0) sl@0: { sl@0: iEntries.Reset(); sl@0: } sl@0: #endif sl@0: } sl@0: } sl@0: } sl@0: SQLCOMPACTOR_INVARIANT(); sl@0: } sl@0: sl@0: /** sl@0: Initializes the CSqlCompactor data members with their default values. sl@0: sl@0: @param aConnFactoryL MSqlCompactConn factory function. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL. sl@0: */ sl@0: CSqlCompactor::CSqlCompactor(TSqlCompactConnFactoryL aConnFactoryL) : sl@0: iConnFactoryL(aConnFactoryL), sl@0: iEntries(KEntriesGranularity) sl@0: { sl@0: __ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC(ESqlPanicBadArgument)); sl@0: } sl@0: sl@0: /** sl@0: Initializes the created CSqlCompactor instance. sl@0: sl@0: @param aCompactStepInterval The time interval between the background compaction steps. sl@0: sl@0: @panic SqlDb 4 In _DEBUG mode. Zero or negative aCompactStepInterval. sl@0: */ sl@0: void CSqlCompactor::ConstructL(TInt aCompactStepInterval) sl@0: { sl@0: __ASSERT_DEBUG(aCompactStepInterval > 0, __SQLPANIC(ESqlPanicBadArgument)); sl@0: iTimer = CSqlCompactTimer::NewL(aCompactStepInterval); sl@0: } sl@0: sl@0: /** sl@0: Static method used internally for performing a search in the container using database name as a key. sl@0: sl@0: @param aFullName The full database name, including the path. sl@0: @param aEntry CSqlCompactor reference. sl@0: */ sl@0: /* static */TInt CSqlCompactor::Search(const TDesC* aFullName, const CSqlCompactEntry& aEntry) sl@0: { sl@0: __ASSERT_DEBUG(&aEntry != NULL, __SQLPANIC2(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(aFullName != NULL, __SQLPANIC2(ESqlPanicInternalError)); sl@0: const TDesC& fullName = *aFullName; sl@0: __ASSERT_DEBUG(fullName.Length() > 0 && fullName.Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(aEntry.FullName().Length() > 0 && aEntry.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError)); sl@0: return fullName.CompareF(aEntry.FullName()); sl@0: } sl@0: sl@0: /** sl@0: Static method used internally for performing a search in the container using a CSqlCompactEntry reference as a key. sl@0: */ sl@0: /* static */TInt CSqlCompactor::Compare(const CSqlCompactEntry& aLeft, const CSqlCompactEntry& aRight) sl@0: { sl@0: __ASSERT_DEBUG(&aLeft != NULL, __SQLPANIC2(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(&aRight != NULL, __SQLPANIC2(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(aLeft.FullName().Length() > 0 && aLeft.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(aRight.FullName().Length() > 0 && aRight.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError)); sl@0: return aLeft.FullName().CompareF(aRight.FullName()); sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: /** sl@0: CSqlCompactor invariant. sl@0: */ sl@0: void CSqlCompactor::Invariant() const sl@0: { sl@0: __ASSERT_DEBUG(iConnFactoryL != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: __ASSERT_DEBUG(iTimer != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: iTimer->Invariant(); sl@0: for(TInt idx=iEntries.Count()-1;idx>=0;--idx) sl@0: { sl@0: __ASSERT_DEBUG(iEntries[idx] != NULL, __SQLPANIC(ESqlPanicInternalError)); sl@0: iEntries[idx]->Invariant(); sl@0: } sl@0: } sl@0: #endif//_DEBUG