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