os/persistentdata/persistentstorage/sql/SRC/Server/Compact/SqlCompact.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2008-2010 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 #include "SqlAssert.h"
    17 #include "SqlCompact.h"
    18 #include "SqlCompactEntry.h"
    19 #include "SqlCompactTimer.h"
    20 #include "SqlUtil.h"
    21 #include "OstTraceDefinitions.h"
    22 #ifdef OST_TRACE_COMPILER_IN_USE
    23 #include "SqlCompactTraces.h"
    24 #endif
    25 #include "SqlTraceDef.h"
    26 
    27 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    28 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    29 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    30 
    31 /**
    32 Initializes the background compaction settings with their default values.
    33 */
    34 TSqlCompactSettings::TSqlCompactSettings() :
    35 	iStepLength(KSqlCompactStepLengthMs),
    36 	iFreePageThresholdKb(KSqlCompactFreePageThresholdKb)
    37 	{
    38 	}
    39 
    40 #ifdef _DEBUG
    41 /**
    42 CSqlCompactSettings invariant.
    43 */
    44 void TSqlCompactSettings::Invariant() const
    45 	{
    46 	__ASSERT_DEBUG(iStepLength > 0, __SQLPANIC(ESqlPanicInternalError));
    47 	__ASSERT_DEBUG(iFreePageThresholdKb >= 0, __SQLPANIC(ESqlPanicInternalError));
    48 	}
    49 #endif//_DEBUG
    50 
    51 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    52 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    53 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    54 
    55 /**
    56 The granularity of the container maintained by CSqlCompactor
    57 
    58 @see CSqlCompactor
    59 @internalComponent
    60 */
    61 const TInt KEntriesGranularity = 16;
    62 
    63 /**
    64 Creates a new CSqlCompactor instance.
    65 
    66 @param aConnFactoryL MSqlCompactConn factory function.
    67 @param aCompactStepInterval The time interval (ms) between the background compaction steps.
    68 
    69 @return A pointer to the created CSqlCompactor instance
    70 
    71 @leave KErrNoMemory, an out of memory condition has occurred;
    72                      Note that the function may also leave with some other database specific 
    73                      errors categorised as ESqlDbError, and other system-wide error codes.
    74 
    75 @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
    76 @panic SqlDb 4 In _DEBUG mode. Zero or negative aCompactStepInterval.
    77 */
    78 CSqlCompactor* CSqlCompactor::NewL(TSqlCompactConnFactoryL aConnFactoryL, TInt aCompactStepInterval)
    79 	{
    80 	__ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC2(ESqlPanicBadArgument));
    81 	__ASSERT_DEBUG(aCompactStepInterval > 0, __SQLPANIC2(ESqlPanicBadArgument));
    82 	CSqlCompactor* self = new (ELeave) CSqlCompactor(aConnFactoryL);
    83 	CleanupStack::PushL(self);
    84 	self->ConstructL(aCompactStepInterval);
    85 	CleanupStack::Pop(self);
    86 	return self;
    87 	}
    88 
    89 /**
    90 Destroys the CSqlCompactor instance. 
    91 Any entries left in the container will be destroyed.
    92 */
    93 CSqlCompactor::~CSqlCompactor()
    94 	{
    95 	for(TInt idx=iEntries.Count()-1;idx>=0;--idx)
    96 		{
    97 		__ASSERT_DEBUG(iEntries[idx] != NULL, __SQLPANIC(ESqlPanicInternalError));
    98 		while(iEntries[idx]->Release() != 0)
    99 			{
   100 			}
   101 		}
   102 	iEntries.Close();
   103 	delete iTimer;
   104 	}
   105 
   106 /**
   107 Restarts the background compaction timer. 
   108 This function should be called from the server side session object's ServiceL(). 
   109 If ServiceL() is being executed at the moment, it is very likely that the SQL client(s) will issue another
   110 request few ms later. In order to not delay the processing of the client(s) requests, ServiceL() should call
   111 at the end RestartTimer(). If there are database entries scheduled for a background compaction, the compaction
   112 will be delayed by the time interval used by the CSqlCompactTimer object (default value - KSqlCompactStepInterval).
   113 
   114 @see CSqlCompactTimer
   115 @see KSqlCompactStepInterval
   116 */
   117 void CSqlCompactor::RestartTimer()
   118 	{
   119 	SQLCOMPACTOR_INVARIANT();
   120 	iTimer->Restart();
   121 	SQLCOMPACTOR_INVARIANT();
   122 	}
   123 
   124 /**
   125 If an entry referring to a database with name aFullName does not exist in the container, a new entry will be created,
   126 a connection with the database established.
   127 If an entry with the specified name already exists, no new entry wil be created, the reference counter of the existing one 
   128 will be incremented.
   129 
   130 @param aFullName The full database name, including the path.
   131 @param aSettings Per-database background compaction settings
   132 
   133 @leave KErrNoMemory, an out of memory condition has occurred;
   134                      Note that the function may also leave with some other database specific 
   135                      errors categorised as ESqlDbError, and other system-wide error codes.
   136 
   137 @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter)
   138 @panic SqlDb 7 In _DEBUG mode. An entry with the specified name has been found but the entry is NULL.
   139 */
   140 void CSqlCompactor::AddEntryL(const TDesC& aFullName, const TSqlCompactSettings& aSettings)
   141 	{
   142 	__ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC(ESqlPanicBadArgument));
   143 	SQLCOMPACTOR_INVARIANT();
   144 	CSqlCompactEntry* entry = NULL;
   145 	TInt idx = iEntries.FindInOrder(aFullName, &CSqlCompactor::Search);
   146 	if(idx == KErrNotFound)
   147 		{
   148 		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));
   149 		entry = CSqlCompactEntry::NewLC(aFullName, iConnFactoryL, aSettings, *iTimer);
   150 		TLinearOrder<CSqlCompactEntry> order(&CSqlCompactor::Compare);
   151 		__SQLLEAVE_IF_ERROR(iEntries.InsertInOrder(entry, order));
   152 		CleanupStack::Pop(entry);
   153 		}
   154 	else
   155 		{
   156 		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));
   157 		entry = iEntries[idx];
   158 		__ASSERT_DEBUG(entry != NULL, __SQLPANIC(ESqlPanicInternalError));
   159 		(void)entry->AddRef();
   160 		}
   161 	SQLCOMPACTOR_INVARIANT();
   162 	}
   163 
   164 /**
   165 Decrements the reference counter of the specified entry.
   166 If the counter reaches zero, the entry will be destroyed and removed from the container, 
   167 the database connection - closed.
   168 
   169 @param aFullName The full database name, including the path.
   170 */
   171 void CSqlCompactor::ReleaseEntry(const TDesC& aFullName)
   172 	{
   173 	SQL_TRACE_COMPACT(OstTraceExt2(TRACE_INTERNALS, CSQLCOMPACTOR_RELEASEENTRY1, "0x%X;CSqlCompactor::ReleaseEntry;aFullName=%S", (TUint)this, __SQLPRNSTR(aFullName)));
   174 	SQLCOMPACTOR_INVARIANT();
   175 	TInt idx = iEntries.FindInOrder(aFullName, &CSqlCompactor::Search);
   176 	__ASSERT_DEBUG(idx >= 0, __SQLPANIC(ESqlPanicInternalError));
   177 	if(idx >= 0)
   178 		{
   179 		CSqlCompactEntry* entry = iEntries[idx];
   180 		__ASSERT_DEBUG(entry != NULL, __SQLPANIC(ESqlPanicInternalError));
   181 		if(entry)
   182 			{
   183 			if(entry->Release() == 0)
   184 				{
   185 				iEntries.Remove(idx);			
   186 #ifdef _DEBUG
   187 //This is used prevent the failure of the resource allocation checking for debug mode. 
   188 				if(iEntries.Count() == 0)
   189 				    {
   190                     iEntries.Reset();
   191 				    }
   192 #endif  
   193 				}
   194 			}
   195 		}
   196 	SQLCOMPACTOR_INVARIANT();
   197 	}
   198 
   199 /**
   200 Initializes the CSqlCompactor data members with their default values.
   201 
   202 @param aConnFactoryL MSqlCompactConn factory function.
   203 
   204 @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
   205 */
   206 CSqlCompactor::CSqlCompactor(TSqlCompactConnFactoryL aConnFactoryL) :
   207 	iConnFactoryL(aConnFactoryL),
   208 	iEntries(KEntriesGranularity)
   209 	{
   210 	__ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC(ESqlPanicBadArgument));
   211 	}
   212 
   213 /**
   214 Initializes the created CSqlCompactor instance.
   215 
   216 @param aCompactStepInterval The time interval between the background compaction steps.
   217 
   218 @panic SqlDb 4 In _DEBUG mode. Zero or negative aCompactStepInterval.
   219 */
   220 void CSqlCompactor::ConstructL(TInt aCompactStepInterval)
   221 	{
   222 	__ASSERT_DEBUG(aCompactStepInterval > 0, __SQLPANIC(ESqlPanicBadArgument));
   223 	iTimer = CSqlCompactTimer::NewL(aCompactStepInterval);
   224 	}
   225 
   226 /**
   227 Static method used internally for performing a search in the container using database name as a key.
   228 
   229 @param aFullName The full database name, including the path.
   230 @param aEntry CSqlCompactor reference.
   231 */
   232 /* static */TInt CSqlCompactor::Search(const TDesC* aFullName, const CSqlCompactEntry& aEntry)
   233 	{
   234 	__ASSERT_DEBUG(&aEntry != NULL, __SQLPANIC2(ESqlPanicInternalError));
   235 	__ASSERT_DEBUG(aFullName != NULL, __SQLPANIC2(ESqlPanicInternalError));
   236 	const TDesC& fullName = *aFullName;
   237 	__ASSERT_DEBUG(fullName.Length() > 0 && fullName.Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
   238 	__ASSERT_DEBUG(aEntry.FullName().Length() > 0 && aEntry.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
   239 	return fullName.CompareF(aEntry.FullName());
   240 	}
   241 
   242 /**
   243 Static method used internally for performing a search in the container using a CSqlCompactEntry reference as a key.
   244 */
   245 /* static */TInt CSqlCompactor::Compare(const CSqlCompactEntry& aLeft, const CSqlCompactEntry& aRight)
   246 	{
   247 	__ASSERT_DEBUG(&aLeft != NULL, __SQLPANIC2(ESqlPanicInternalError));
   248 	__ASSERT_DEBUG(&aRight != NULL, __SQLPANIC2(ESqlPanicInternalError));
   249 	__ASSERT_DEBUG(aLeft.FullName().Length() > 0 && aLeft.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
   250 	__ASSERT_DEBUG(aRight.FullName().Length() > 0 && aRight.FullName().Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicInternalError));
   251 	return aLeft.FullName().CompareF(aRight.FullName());
   252 	}
   253 
   254 #ifdef _DEBUG
   255 /**
   256 CSqlCompactor invariant.
   257 */
   258 void CSqlCompactor::Invariant() const
   259 	{
   260 	__ASSERT_DEBUG(iConnFactoryL != NULL, __SQLPANIC(ESqlPanicInternalError));
   261 	__ASSERT_DEBUG(iTimer != NULL, __SQLPANIC(ESqlPanicInternalError));
   262 	iTimer->Invariant();
   263 	for(TInt idx=iEntries.Count()-1;idx>=0;--idx)
   264 		{
   265 		__ASSERT_DEBUG(iEntries[idx] != NULL, __SQLPANIC(ESqlPanicInternalError));
   266 		iEntries[idx]->Invariant();
   267 		}
   268 	}
   269 #endif//_DEBUG