persistentstorage/sql/SRC/Server/Compact/SqlCompactEntry.cpp
changeset 0 08ec8eefde2f
child 12 31a8f755b7fe
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2008-2009 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 <e32debug.h>
       
    17 #include <hal.h>
       
    18 #include <sqldb.h>
       
    19 #include "SqlPanic.h"
       
    20 #include "SqlCompactEntry.h"
       
    21 #include "SqlCompactTimer.h"
       
    22 #include "SqliteSymbian.h"		//TSqlFreePageCallback
       
    23 
       
    24 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    25 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    26 
       
    27 /**
       
    28 Creates a new CSqlCompactEntry instance.
       
    29 
       
    30 @param aFullName The full database name, including the path.
       
    31 @param aConnFactoryL MSqlCompactConn factory function.
       
    32 @param aSettings Background compaction settings/thresholds
       
    33 @param aTimer The background compaction timer object
       
    34 
       
    35 When the free pages threshold reach certain the threshold, the background compaction 
       
    36 for this entry will be kicked-off.
       
    37 
       
    38 @return A pointer to the created CSqlCompactEntry instance
       
    39 
       
    40 @leave KErrNoMemory, an out of memory condition has occurred;
       
    41                      Note that the function may also leave with some other database specific 
       
    42                      errors categorised as ESqlDbError, and other system-wide error codes.
       
    43 
       
    44 @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter)
       
    45 @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
       
    46 */
       
    47 CSqlCompactEntry* CSqlCompactEntry::NewLC(const TDesC& aFullName, TSqlCompactConnFactoryL aConnFactoryL, 
       
    48 										  const TSqlCompactSettings& aSettings, CSqlCompactTimer& aTimer)
       
    49 	{
       
    50 	__SQLASSERT(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, ESqlPanicBadArgument); 
       
    51 	__SQLASSERT(aConnFactoryL != NULL, ESqlPanicBadArgument);
       
    52 	CSqlCompactEntry* self = new (ELeave) CSqlCompactEntry(aSettings, aTimer);
       
    53 	CleanupStack::PushL(self);
       
    54 	self->ConstructL(aFullName, aConnFactoryL);
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 /**
       
    59 Destroys the CSqlCompactEntry instance. The database connection will be closed.
       
    60 */
       
    61 CSqlCompactEntry::~CSqlCompactEntry()
       
    62 	{
       
    63 	if(iState == CSqlCompactEntry::EInProgress)
       
    64 		{
       
    65 		iTimer.DeQueue(*this);
       
    66 		}
       
    67 	if(iConnection)
       
    68 		{
       
    69 		iConnection->Release();	
       
    70 		}
       
    71 	iFullName.Close();
       
    72 	}
       
    73 
       
    74 /**
       
    75 Increments the entry reference counter.
       
    76 
       
    77 @return The new reference counter value.
       
    78 */
       
    79 TInt CSqlCompactEntry::AddRef()
       
    80 	{
       
    81 	SQLCOMPACTENTRY_INVARIANT();
       
    82 	return ++iRefCounter;
       
    83 	}
       
    84 
       
    85 /**
       
    86 Decrements the entry reference counter.
       
    87 If the counter reaches zero, the CSqlCompactEntry instance will be destroyed.
       
    88 
       
    89 @return The new reference counter value.
       
    90 */
       
    91 TInt CSqlCompactEntry::Release()
       
    92 	{
       
    93 	SQLCOMPACTENTRY_INVARIANT();
       
    94 	TInt rc = --iRefCounter;
       
    95 	if(rc == 0)
       
    96 		{
       
    97 		delete this;	
       
    98 		}
       
    99 	return rc;
       
   100 	}
       
   101 
       
   102 /**
       
   103 SQLite calls this function when the free pages count reaches the threshold.
       
   104 The callback must have been registered at the moment of the database connection creation in order this to happen.
       
   105 The callback implementation will schedule a background compaction (kicking-off the timer).
       
   106 If a background compaction has already been scheduled, the implementation will only update the iPageCount data
       
   107 meber value.
       
   108 
       
   109 @param aThis A pointer to the CSqlCompactEntry object for which the free page count reached or is above the threshold.
       
   110 @param aFreePageCount Free pages count.
       
   111 
       
   112 @panic SqlDb 4 In _DEBUG mode. NULL aThis parameter.
       
   113 @panic SqlDb 4 In _DEBUG mode. aFreePageCount is negative or zero.
       
   114 */
       
   115 /* static */ void CSqlCompactEntry::FreePageCallback(void* aThis, TInt aFreePageCount)
       
   116 	{
       
   117 	__SQLASSERT(aThis != NULL, ESqlPanicBadArgument); 
       
   118 	__SQLASSERT(aFreePageCount > 0, ESqlPanicBadArgument); 
       
   119 	
       
   120 	CSqlCompactEntry& entry = *(static_cast <CSqlCompactEntry*> (aThis));
       
   121 	if(entry.iFreePageCallbackDisabled)
       
   122 		{//The callback is disabled during the background compaction step.
       
   123 		 //The server is single-threaded, so no other client can activate the callback.
       
   124 		 //During the background compaction step the callback can be activated only by the completion of the background 
       
   125 		 //compaction in which case if "entry.iPageCount" is bigger than the threshold, the page counter will be set from here
       
   126 		 //and set second time from CSqlCompactEntry::Compact() - the counter value will be reduced twice.
       
   127 		return;	
       
   128 		}
       
   129 	
       
   130 	entry.iPageCount = aFreePageCount;
       
   131 	if(entry.iState == CSqlCompactEntry::EInactive)
       
   132 		{
       
   133 		entry.iState = CSqlCompactEntry::EInProgress;
       
   134 		entry.iTimer.Queue(entry);
       
   135 		}
       
   136 	}
       
   137 
       
   138 /**
       
   139 Initializes the CSqlCompactEntry data members with their default values.
       
   140 
       
   141 @param aSettings Background compaction settings/thresholds
       
   142 */
       
   143 CSqlCompactEntry::CSqlCompactEntry(const TSqlCompactSettings& aSettings, CSqlCompactTimer& aTimer) :
       
   144 	iSettings(aSettings),
       
   145 	iTimer(aTimer),
       
   146 	iRefCounter(1),
       
   147 	iState(CSqlCompactEntry::EInactive)
       
   148 	{
       
   149 	}
       
   150 
       
   151 /**
       
   152 Initializes the created CSqlCompactEntry instance.
       
   153 Schedules a background compaction if the free pages count is above the threshold.
       
   154 
       
   155 @param aFullName The full database name, including the path.
       
   156 @param aConnFactoryL MSqlCompactConn factory function.
       
   157 
       
   158 @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter)
       
   159 @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
       
   160 @panic SqlDb 7 In _DEBUG mode. The CSqlCompactEntry instance has been initialized already.
       
   161 */
       
   162 void CSqlCompactEntry::ConstructL(const TDesC& aFullName, TSqlCompactConnFactoryL aConnFactoryL)
       
   163 	{
       
   164 	__SQLASSERT(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, ESqlPanicBadArgument); 
       
   165 	__SQLASSERT(aConnFactoryL != NULL, ESqlPanicBadArgument);
       
   166 	__SQLASSERT(!iConnection, ESqlPanicInternalError);
       
   167 	
       
   168 	__SQLLEAVE_IF_ERROR(iFullName.Create(aFullName));
       
   169 
       
   170 	//The second parameter of TSqlFreePageCallback's constructor is expected the be threshold in pages.
       
   171 	//But the connection is not established yet and the page size is not known. Hence the threshold parameter
       
   172 	//value is initialized with the threshold in Kbs. The connection construction is expected to convert
       
   173 	//the threshold from Kbs to pages when the connection with the database is established.
       
   174 	TSqlFreePageCallback callback(this, iSettings.iFreePageThresholdKb, &CSqlCompactEntry::FreePageCallback);
       
   175 	iConnection = (*aConnFactoryL)(aFullName, callback);
       
   176 	__SQLASSERT(iConnection != NULL, ESqlPanicInternalError);
       
   177 	
       
   178 	//"callback.iThreshold > 0" is an indication that the background compaction should be kicked-off
       
   179 	if(callback.iThreshold > 0) 
       
   180 		{
       
   181 		//Kick-off the compaction timer, if the number of the free pages is above the threshold.
       
   182 		CSqlCompactEntry::FreePageCallback(this, callback.iThreshold);
       
   183 		}
       
   184 		
       
   185 	SQLCOMPACTENTRY_INVARIANT();
       
   186 	}
       
   187 
       
   188 /**
       
   189 Performs a compaction step on the database.
       
   190 If the number of the free pages is bigger than the number of pages removed in one compaction step,
       
   191 the function will reschedule itself for another compaction step.
       
   192 
       
   193 @return KErrNoMemory, an out of memory condition has occurred;
       
   194                       Note that the function may also return some other database specific 
       
   195                       errors categorised as ESqlDbError, and other system-wide error codes.
       
   196 
       
   197 @panic SqlDb 7 In _DEBUG mode. iPageCount <= 0 - no free pages to be processed.
       
   198 @panic SqlDb 7 In _DEBUG mode. iState != CSqlCompactEntry::EInProgress.
       
   199 */
       
   200 TInt CSqlCompactEntry::Compact()
       
   201 	{
       
   202 	//RDebug::Print(_L("++ CSqlCompactEntry::Compact() ++\r\n"));
       
   203 	SQLCOMPACTENTRY_INVARIANT();
       
   204 	__SQLASSERT(iPageCount > 0, ESqlPanicInternalError);
       
   205 	__SQLASSERT(iState == CSqlCompactEntry::EInProgress, ESqlPanicInternalError);
       
   206 	TInt processedPageCount = 0;
       
   207 	iFreePageCallbackDisabled = ETrue;
       
   208 	TInt err = Connection().Compact(iPageCount, processedPageCount, iSettings.iStepLength);
       
   209 	iFreePageCallbackDisabled = EFalse;
       
   210 	__SQLASSERT(processedPageCount >= 0, ESqlPanicInternalError);
       
   211 	if(err == KErrNone)
       
   212 		{
       
   213 		if(processedPageCount > 0)
       
   214 			{
       
   215 			iPageCount -= processedPageCount;
       
   216 			}
       
   217 		else
       
   218 			{
       
   219 			iPageCount = 0;
       
   220 			}
       
   221 		__SQLASSERT(iPageCount >= 0, ESqlPanicInternalError);
       
   222 		}
       
   223 	if(iPageCount <= 0)
       
   224 		{//No more pages to compact. Stop the compacting, move to EInactive state, remove from the timer queue.
       
   225 		ResetState();
       
   226 		iTimer.DeQueue(*this);
       
   227 		}
       
   228 	SQLCOMPACTENTRY_INVARIANT();
       
   229 	return err;
       
   230 	}
       
   231 
       
   232 /**
       
   233 Returns the full database name, including the path.
       
   234 
       
   235 @return Full database name.
       
   236 */
       
   237 const TDesC& CSqlCompactEntry::FullName() const
       
   238 	{
       
   239 	SQLCOMPACTENTRY_INVARIANT();
       
   240 	return iFullName;
       
   241 	}
       
   242 
       
   243 /**
       
   244 Resets the CSqlCompactEntry internal state.
       
   245 That means - (1) no scheduled compaction step and (2) no pending free pages to be removed.
       
   246 */
       
   247 void CSqlCompactEntry::ResetState()
       
   248 	{
       
   249 	SQLCOMPACTENTRY_INVARIANT();
       
   250 	iState = CSqlCompactEntry::EInactive;
       
   251 	iPageCount = 0;
       
   252 	SQLCOMPACTENTRY_INVARIANT();
       
   253 	}
       
   254 
       
   255 /**
       
   256 Returns a reference to the MSqlCompactConn interface.
       
   257 @return A reference to the MSqlCompactConn interface.
       
   258 
       
   259 @panic SqlDb 7 NULL MSqlCompactConn interface.
       
   260 */
       
   261 MSqlCompactConn& CSqlCompactEntry::Connection()
       
   262 	{
       
   263 	SQLCOMPACTENTRY_INVARIANT();
       
   264 	__SQLASSERT_ALWAYS(iConnection != NULL, ESqlPanicInternalError);
       
   265 	return *iConnection;
       
   266 	}
       
   267 
       
   268 #ifdef _DEBUG
       
   269 /**
       
   270 CSqlCompactEntry invariant.
       
   271 */
       
   272 void CSqlCompactEntry::Invariant() const
       
   273 	{
       
   274 	__SQLASSERT(iFullName.Length() > 0 && iFullName.Length() <= KMaxFileName, ESqlPanicInternalError); 
       
   275 	__SQLASSERT(iConnection != NULL, ESqlPanicInternalError);
       
   276 	__SQLASSERT(iRefCounter > 0, ESqlPanicInternalError);
       
   277 	__SQLASSERT(iState == CSqlCompactEntry::EInactive || iState == CSqlCompactEntry::EInProgress, ESqlPanicInternalError);
       
   278 	__SQLASSERT(iPageCount >= 0, ESqlPanicInternalError);
       
   279 	iSettings.Invariant();
       
   280 	}
       
   281 #endif//_DEBUG