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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
19 #include "SqlAssert.h"
20 #include "SqlCompactEntry.h"
21 #include "SqlCompactTimer.h"
22 #include "SqliteSymbian.h" //TSqlFreePageCallback
23 #include "OstTraceDefinitions.h"
24 #ifdef OST_TRACE_COMPILER_IN_USE
25 #include "SqlCompactEntryTraces.h"
27 #include "SqlTraceDef.h"
29 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33 Creates a new CSqlCompactEntry instance.
35 @param aFullName The full database name, including the path.
36 @param aConnFactoryL MSqlCompactConn factory function.
37 @param aSettings Background compaction settings/thresholds
38 @param aTimer The background compaction timer object
40 When the free pages threshold is reached, the background compaction
41 for this entry will be kicked-off.
43 @return A pointer to the created CSqlCompactEntry instance
45 @leave KErrNoMemory, an out of memory condition has occurred;
46 Note that the function may also leave with some other database specific
47 errors categorised as ESqlDbError, and other system-wide error codes.
49 @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter)
50 @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
52 CSqlCompactEntry* CSqlCompactEntry::NewLC(const TDesC& aFullName, TSqlCompactConnFactoryL aConnFactoryL,
53 const TSqlCompactSettings& aSettings, CSqlCompactTimer& aTimer)
55 SQL_TRACE_COMPACT(OstTraceExt1(TRACE_INTERNALS, CSQLCOMPACTENTRY_NEWLC_ENTRY, "Entry;0;CSqlCompactEntry::NewLC;aFullName=%S", __SQLPRNSTR(aFullName)));
56 __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC2(ESqlPanicBadArgument));
57 __ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC2(ESqlPanicBadArgument));
58 CSqlCompactEntry* self = new (ELeave) CSqlCompactEntry(aSettings, aTimer);
59 CleanupStack::PushL(self);
60 self->ConstructL(aFullName, aConnFactoryL);
61 SQL_TRACE_COMPACT(OstTrace1(TRACE_INTERNALS, CSQLCOMPACTENTRY_NEWLC_EXIT, "Exit;0x%X;CSqlCompactEntry::NewLC", (TUint)self));
66 Destroys the CSqlCompactEntry instance. The database connection will be closed.
68 CSqlCompactEntry::~CSqlCompactEntry()
70 SQL_TRACE_COMPACT(OstTraceExt3(TRACE_INTERNALS, CSQLCOMPACTENTRY_CSQLCOMPACTENTRY2, "0x%X;CSqlCompactEntry::~CSqlCompactEntry;iState=%d;iPageCount=%d", (TUint)this, (TInt)iState, iPageCount));
71 if(iState == CSqlCompactEntry::EInProgress)
73 iTimer.DeQueue(*this);
77 iConnection->Release();
83 Increments the entry reference counter.
85 @return The new reference counter value.
87 TInt CSqlCompactEntry::AddRef()
89 SQL_TRACE_COMPACT(OstTraceExt4(TRACE_INTERNALS, CSQLCOMPACTENTRY_ADDREF, "0x%X;CSqlCompactEntry::AddRef;iState=%d;iPageCount=%d;iRefCounter=%d", (TUint)this, (TInt)iState, iPageCount, iRefCounter));
90 SQLCOMPACTENTRY_INVARIANT();
95 Decrements the entry reference counter.
96 If the counter reaches zero, the CSqlCompactEntry instance will be destroyed.
98 @return The new reference counter value.
100 TInt CSqlCompactEntry::Release()
102 SQL_TRACE_COMPACT(OstTraceExt4(TRACE_INTERNALS, CSQLCOMPACTENTRY_RELEASE, "0x%X;CSqlCompactEntry::Release;iState=%d;iPageCount=%d;iRefCounter=%d", (TUint)this, (TInt)iState, iPageCount, iRefCounter));
103 SQLCOMPACTENTRY_INVARIANT();
104 TInt rc = --iRefCounter;
113 SQLite calls this function when the free pages count reaches the threshold.
114 The callback must have been registered at the moment of the database connection creation in order this to happen.
115 The callback implementation will schedule a background compaction (kicking-off the timer).
116 If a background compaction has already been scheduled, the implementation will only update the iPageCount data
119 @param aThis A pointer to the CSqlCompactEntry object for which the free page count reached or is above the threshold.
120 @param aFreePageCount Free pages count.
122 @panic SqlDb 4 In _DEBUG mode. NULL aThis parameter.
123 @panic SqlDb 4 In _DEBUG mode. aFreePageCount is negative or zero.
125 /* static */ void CSqlCompactEntry::FreePageCallback(void* aThis, TInt aFreePageCount)
127 __ASSERT_DEBUG(aThis != NULL, __SQLPANIC2(ESqlPanicBadArgument));
128 __ASSERT_DEBUG(aFreePageCount > 0, __SQLPANIC2(ESqlPanicBadArgument));
130 CSqlCompactEntry& entry = *(static_cast <CSqlCompactEntry*> (aThis));
131 SQL_TRACE_COMPACT(OstTraceExt3(TRACE_INTERNALS, CSQLCOMPACTENTRY_FREEPAGECALLBACK, "0x%X;CSqlCompactEntry::FreePageCallback;aFreePageCount=%d;iState=%d", (TUint)aThis, aFreePageCount, (TInt)entry.iState));
132 if(entry.iFreePageCallbackDisabled)
133 {//The callback is disabled during the background compaction step.
134 //The server is single-threaded, so no other client can activate the callback.
135 //During the background compaction step the callback can be activated only by the completion of the background
136 //compaction in which case if "entry.iPageCount" is bigger than the threshold, the page counter will be set from here
137 //and set second time from CSqlCompactEntry::Compact() - the counter value will be reduced twice.
141 entry.iPageCount = aFreePageCount;
142 if(entry.iState == CSqlCompactEntry::EInactive)
144 entry.iState = CSqlCompactEntry::EInProgress;
145 entry.iTimer.Queue(entry);
150 Initializes the CSqlCompactEntry data members with their default values.
152 @param aSettings Background compaction settings/thresholds
154 CSqlCompactEntry::CSqlCompactEntry(const TSqlCompactSettings& aSettings, CSqlCompactTimer& aTimer) :
155 iSettings(aSettings),
158 iState(CSqlCompactEntry::EInactive)
163 Initializes the created CSqlCompactEntry instance.
164 Schedules a background compaction if the free pages count is above the threshold.
166 @param aFullName The full database name, including the path.
167 @param aConnFactoryL MSqlCompactConn factory function.
169 @panic SqlDb 4 In _DEBUG mode. Too short or too long database name (aFullName parameter)
170 @panic SqlDb 4 In _DEBUG mode. NULL aConnFactoryL.
171 @panic SqlDb 7 In _DEBUG mode. The CSqlCompactEntry instance has been initialized already.
173 void CSqlCompactEntry::ConstructL(const TDesC& aFullName, TSqlCompactConnFactoryL aConnFactoryL)
175 __ASSERT_DEBUG(aFullName.Length() > 0 && aFullName.Length() <= KMaxFileName, __SQLPANIC(ESqlPanicBadArgument));
176 __ASSERT_DEBUG(aConnFactoryL != NULL, __SQLPANIC(ESqlPanicBadArgument));
177 __ASSERT_DEBUG(!iConnection, __SQLPANIC(ESqlPanicInternalError));
179 __SQLLEAVE_IF_ERROR(iFullName.Create(aFullName));
181 //The second parameter of TSqlFreePageCallback's constructor is expected the be threshold in pages.
182 //But the connection is not established yet and the page size is not known. Hence the threshold parameter
183 //value is initialized with the threshold in Kbs. The connection construction is expected to convert
184 //the threshold from Kbs to pages when the connection with the database is established.
185 TSqlFreePageCallback callback(this, iSettings.iFreePageThresholdKb, &CSqlCompactEntry::FreePageCallback);
186 iConnection = (*aConnFactoryL)(aFullName, callback);
187 __ASSERT_DEBUG(iConnection != NULL, __SQLPANIC(ESqlPanicInternalError));
189 //"callback.iThreshold > 0" is an indication that the background compaction should be kicked-off
190 if(callback.iThreshold > 0)
192 //Kick-off the compaction timer, if the number of the free pages is above the threshold.
193 CSqlCompactEntry::FreePageCallback(this, callback.iThreshold);
196 SQLCOMPACTENTRY_INVARIANT();
200 Performs a compaction step on the database.
201 If the number of the free pages is bigger than the number of pages removed in one compaction step,
202 the function will reschedule itself for another compaction step.
203 If the database file is corrupted, then the function will remove the database entry from the timer queue -
204 the database won't be compacted anymore.
206 @return KErrNoMemory, an out of memory condition has occurred;
207 Note that the function may also return some other database specific
208 errors categorised as ESqlDbError, and other system-wide error codes.
210 @panic SqlDb 7 In _DEBUG mode. iPageCount <= 0 - no free pages to be processed.
211 @panic SqlDb 7 In _DEBUG mode. iState != CSqlCompactEntry::EInProgress.
213 TInt CSqlCompactEntry::Compact()
215 SQL_TRACE_COMPACT(OstTraceExt3(TRACE_INTERNALS, CSQLCOMPACTENTRY_COMPACT_ENTRY, "Entry;0x%X;CSqlCompactEntry::Compact;aFreePageCount=%d;iState=%d", (TUint)this, iPageCount, (TInt)iState));
216 SQLCOMPACTENTRY_INVARIANT();
217 __ASSERT_DEBUG(iPageCount > 0, __SQLPANIC(ESqlPanicInternalError));
218 __ASSERT_DEBUG(iState == CSqlCompactEntry::EInProgress, __SQLPANIC(ESqlPanicInternalError));
219 TInt processedPageCount = 0;
220 iFreePageCallbackDisabled = ETrue;
221 TInt err = Connection().Compact(iPageCount, processedPageCount, iSettings.iStepLength);
222 iFreePageCallbackDisabled = EFalse;
223 __ASSERT_DEBUG(processedPageCount >= 0, __SQLPANIC(ESqlPanicInternalError));
226 iPageCount -= processedPageCount;
227 if(processedPageCount == 0)
231 __ASSERT_DEBUG(iPageCount >= 0, __SQLPANIC(ESqlPanicInternalError));
233 TBool stopCompaction = err == KSqlErrCorrupt || err == KSqlErrNotDb || err == KErrCorrupt || err == KErrDisMounted;
234 if(iPageCount <= 0 || stopCompaction)
235 {//No more pages to compact or the file is corrupted . Stop the compacting, move to EInactive state, remove from the timer queue.
237 iTimer.DeQueue(*this);
239 SQL_TRACE_COMPACT(OstTraceExt4(TRACE_INTERNALS, CSQLCOMPACTENTRY_COMPACT_EXIT, "Exit;0x%X;CSqlCompactEntry::Compact;iPageCount=%d;iState=%d;err=%d", (TUint)this, iPageCount, (TInt)iState, err));
240 SQLCOMPACTENTRY_INVARIANT();
245 Returns the full database name, including the path.
247 @return Full database name.
249 const TDesC& CSqlCompactEntry::FullName() const
251 SQLCOMPACTENTRY_INVARIANT();
256 Resets the CSqlCompactEntry internal state.
257 That means - (1) no scheduled compaction step and (2) no pending free pages to be removed.
259 void CSqlCompactEntry::ResetState()
261 SQLCOMPACTENTRY_INVARIANT();
262 iState = CSqlCompactEntry::EInactive;
264 SQLCOMPACTENTRY_INVARIANT();
268 Returns a reference to the MSqlCompactConn interface.
269 @return A reference to the MSqlCompactConn interface.
271 @panic SqlDb 7 NULL MSqlCompactConn interface.
273 MSqlCompactConn& CSqlCompactEntry::Connection()
275 SQLCOMPACTENTRY_INVARIANT();
276 __ASSERT_ALWAYS(iConnection != NULL, __SQLPANIC(ESqlPanicInternalError));
282 CSqlCompactEntry invariant.
284 void CSqlCompactEntry::Invariant() const
286 __ASSERT_DEBUG(iFullName.Length() > 0 && iFullName.Length() <= KMaxFileName, __SQLPANIC(ESqlPanicInternalError));
287 __ASSERT_DEBUG(iConnection != NULL, __SQLPANIC(ESqlPanicInternalError));
288 __ASSERT_DEBUG(iRefCounter > 0, __SQLPANIC(ESqlPanicInternalError));
289 __ASSERT_DEBUG(iState == CSqlCompactEntry::EInactive || iState == CSqlCompactEntry::EInProgress, __SQLPANIC(ESqlPanicInternalError));
290 __ASSERT_DEBUG(iPageCount >= 0, __SQLPANIC(ESqlPanicInternalError));
291 iSettings.Invariant();