|
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 |
|
17 /** |
|
18 * HEADER FILES |
|
19 */ |
|
20 |
|
21 #include "cmsvversion0version1converter.h" |
|
22 #include "cmsvversion1version2converter.h" |
|
23 //#include "cmsvconverterwaiter.h" |
|
24 |
|
25 |
|
26 // literals |
|
27 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) |
|
28 _LIT(KMessagingDBName, "\\messaging.db"); |
|
29 #else |
|
30 _LIT(KMessagingDBName,"[1000484B]messaging.db"); |
|
31 _LIT(KMessagingDBFilePath,"\\Private\\1000484b\\Mail2\\"); |
|
32 #endif |
|
33 |
|
34 |
|
35 /** |
|
36 NewL() |
|
37 Constructs a new message converter object. This is singleton instatiation. |
|
38 |
|
39 @param aDriveNumber: |
|
40 @return None |
|
41 @internalComponent |
|
42 */ |
|
43 CMessageConverterManager* CMessageConverterManager::NewL(TDriveNumber aDriveNumber) |
|
44 |
|
45 { |
|
46 CMessageConverterManager* self = new(ELeave) CMessageConverterManager(aDriveNumber); |
|
47 CleanupStack::PushL(self); |
|
48 self->ConstructL(); |
|
49 |
|
50 CleanupStack::Pop(self); |
|
51 return self; |
|
52 } |
|
53 |
|
54 /** |
|
55 StartConversion() |
|
56 Fetches the drive number requested for conversion, constructs converter manager object |
|
57 and initiates the conversion for that drive. |
|
58 |
|
59 @param aDrive: Requested Drive for conversion. |
|
60 @return TInt: System wide error codes. |
|
61 @internalComponent |
|
62 */ |
|
63 TInt CMessageConverterManager::StartConversion(TAny* aDrive) |
|
64 { |
|
65 __UHEAP_MARK; |
|
66 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
67 if(!cleanup) |
|
68 { |
|
69 return KErrNoMemory; |
|
70 } |
|
71 |
|
72 |
|
73 TInt err= KErrNone; |
|
74 TDriveNumber driveNum = *(static_cast<const TDriveNumber*>(aDrive)); |
|
75 CMessageConverterManager* self = NULL; |
|
76 TRAP(err, self = CMessageConverterManager::NewL(driveNum)); |
|
77 |
|
78 // do the conversion |
|
79 if(!err) |
|
80 { |
|
81 CleanupStack::PushL(self); |
|
82 TRAP(err , self->DoConversionL()); |
|
83 CleanupStack::PopAndDestroy(); |
|
84 } |
|
85 |
|
86 delete cleanup; |
|
87 __UHEAP_MARKEND; |
|
88 |
|
89 return err; |
|
90 } |
|
91 |
|
92 /** |
|
93 CMessageConverterManager() |
|
94 Default constructor |
|
95 |
|
96 @param None |
|
97 @return None |
|
98 @internalComponent |
|
99 */ |
|
100 CMessageConverterManager::CMessageConverterManager(TDriveNumber aDriveNumber):iDrive(aDriveNumber) |
|
101 { |
|
102 } |
|
103 |
|
104 /** |
|
105 ConstructL() |
|
106 Second phase constructor. |
|
107 |
|
108 @param aDriveNumber: |
|
109 @param conversionResume: |
|
110 @return None |
|
111 @internalComponent |
|
112 */ |
|
113 void CMessageConverterManager::ConstructL() |
|
114 { |
|
115 User::LeaveIfError(ifsSession.Connect()); |
|
116 iConversionTablePresent = ETrue; |
|
117 iDeleteDatabase = -1; |
|
118 iInitialVersion = -1; |
|
119 } |
|
120 |
|
121 /** |
|
122 ~CMessageConverterManager() |
|
123 Destructor |
|
124 |
|
125 @param None |
|
126 @return None |
|
127 @internalComponent |
|
128 */ |
|
129 CMessageConverterManager::~CMessageConverterManager() |
|
130 { |
|
131 delete iMessageDbAdapter; |
|
132 delete iDbAdapter; |
|
133 |
|
134 if(iDeleteDatabase == 0) |
|
135 { |
|
136 TRAP_IGNORE(RollBackVersion0Version1ConversionL()); |
|
137 } |
|
138 else if(iDeleteDatabase == 1) |
|
139 { |
|
140 TRAP_IGNORE(RollBackVersion1Version2ConversionL()); |
|
141 } |
|
142 |
|
143 } |
|
144 |
|
145 /** |
|
146 DoConversionL() |
|
147 Initialises message store conversion and starts conversion between the required versions. |
|
148 |
|
149 @param None |
|
150 @return None |
|
151 @internalComponent |
|
152 */ |
|
153 void CMessageConverterManager::DoConversionL() |
|
154 { |
|
155 // Start from beginning or Resume |
|
156 InitialiseMessageStoreConversionL(); |
|
157 |
|
158 switch(iConversionVersion) |
|
159 { |
|
160 case 1: // version 0 version 1 conversion |
|
161 //Start from beginning or resume Resume v0 to v1 |
|
162 { |
|
163 iInitialVersion = 0; |
|
164 |
|
165 RFile file; |
|
166 TInt error = file.Open(ifsSession, iFilePath, EFileShareAny|EFileWrite); |
|
167 |
|
168 // check disk space |
|
169 TVolumeInfo info; |
|
170 ifsSession.Volume(info,iDrive); |
|
171 |
|
172 TInt indexFileSize; |
|
173 file.Size(indexFileSize); |
|
174 |
|
175 TInt reqDiskSpace; |
|
176 reqDiskSpace = indexFileSize * 2; |
|
177 |
|
178 file.Close(); |
|
179 ifsSession.Close(); |
|
180 |
|
181 if(reqDiskSpace * 2 < info.iFree) |
|
182 { |
|
183 |
|
184 iIndexFileConverter = CMsvVersion0Version1Converter::NewL(*iDbAdapter,iDrive,iConversionResume); |
|
185 CleanupStack::PushL(iIndexFileConverter); |
|
186 |
|
187 TRAP(error,iIndexFileConverter->ConvertMessageStoreL()); |
|
188 |
|
189 if(error != KErrNone) |
|
190 { |
|
191 iDeleteDatabase = 0; |
|
192 User::Leave(error); |
|
193 } |
|
194 |
|
195 if(iConversionResume) |
|
196 { |
|
197 iConversionResume = EFalse; |
|
198 } |
|
199 CleanupStack::PopAndDestroy(); //iIndexFileConverter |
|
200 |
|
201 iDbAdapter->ChangeVersionL(1); //We have a version 1 db now |
|
202 } |
|
203 else // disk check failed. Lets leave conversion status table if there is one. |
|
204 { |
|
205 User::Leave(KErrDiskFull); |
|
206 } |
|
207 } |
|
208 |
|
209 case 2: // version 1 version 2 conversion |
|
210 { |
|
211 if(iInitialVersion !=0 ) |
|
212 { |
|
213 iInitialVersion = 1; |
|
214 } |
|
215 |
|
216 iMessageConverter = CMsvVersion1Version2Converter::NewL(*iDbAdapter,*iMessageDbAdapter,iDrive,iConversionResume); |
|
217 CleanupStack::PushL(iMessageConverter); |
|
218 |
|
219 TRAPD(error,iMessageConverter->ConvertMessageStoreL()); |
|
220 if(error) |
|
221 { |
|
222 if(iInitialVersion == 1) |
|
223 { |
|
224 iDeleteDatabase = 1; |
|
225 } |
|
226 else |
|
227 { |
|
228 iDeleteDatabase = 0; |
|
229 } |
|
230 User::Leave(error); |
|
231 } |
|
232 |
|
233 CleanupStack::PopAndDestroy(iMessageConverter); //iMessageConverter |
|
234 |
|
235 iDbAdapter->ChangeVersionL(2); |
|
236 } |
|
237 } |
|
238 // We are done. Delete the status table. |
|
239 iDbAdapter->RemoveConversionStatusTableL(); |
|
240 |
|
241 // remove index file |
|
242 RemoveIndexFileL(iDrive); |
|
243 } |
|
244 |
|
245 /** |
|
246 InitialiseMessageStoreConversionL() |
|
247 Checks if the conversion is to be resumed. If yes, than identifies the message store version |
|
248 to be converted. |
|
249 If its a new conversion request than it creates the necessary tables and initiases the adapter |
|
250 classes accordingly. |
|
251 |
|
252 @param None |
|
253 @return None |
|
254 @internalComponent |
|
255 */ |
|
256 void CMessageConverterManager::InitialiseMessageStoreConversionL() |
|
257 { |
|
258 TParse parse; |
|
259 TPtrC drive = TDriveUnit(iDrive).Name(); |
|
260 parse.Set(KMessagingDBName, &drive, NULL); |
|
261 iDBFileName = parse.FullName(); |
|
262 |
|
263 iFilePath.Append(drive); |
|
264 iFilePath.Append(KIndexFilePath); |
|
265 |
|
266 iConversionResume = ResumeConversionL(); |
|
267 /* |
|
268 iConversionResume can have the following conditions set. |
|
269 ETrue - Conversion is to be resumed. |
|
270 EFalse - New conversion Request. |
|
271 */ |
|
272 if(iConversionResume) |
|
273 { |
|
274 if(iConversionTablePresent) |
|
275 { |
|
276 iDbAdapter = CMsvDBAdapter::OpenL(iDBFileName); // open the db |
|
277 |
|
278 // get resumption point from conversion resume table. |
|
279 iDbAdapter->GetConversionStatusL(iResumeStatus); |
|
280 |
|
281 if(iResumeStatus.targetVersion == 1) |
|
282 { |
|
283 iConversionVersion = 1; |
|
284 } |
|
285 else |
|
286 { |
|
287 iConversionVersion = 2; |
|
288 } |
|
289 } |
|
290 else |
|
291 { |
|
292 // new request for version 1 version 2 conversion. |
|
293 // Index file already migrated to SQlite DB. |
|
294 iDbAdapter = CMsvDBAdapter::OpenL(iDBFileName); // open the db |
|
295 iDbAdapter->CreateConversionStatusTableL(); |
|
296 iConversionVersion = 2; |
|
297 iConversionResume = EFalse; |
|
298 } |
|
299 } |
|
300 else |
|
301 { |
|
302 // New request for version 1 version 2 conversion. |
|
303 // Index file still in file. |
|
304 |
|
305 CMsvDBAdapter::CreateDBL(iDrive); |
|
306 iDbAdapter = CMsvDBAdapter::OpenL(iDBFileName); |
|
307 iDbAdapter->ConstructSortTableL(); |
|
308 iDbAdapter->CreateConversionStatusTableL(); |
|
309 iConversionVersion = 1; |
|
310 } |
|
311 iDbAdapter->InitializeL(); |
|
312 // change to invalid versionss |
|
313 iDbAdapter->ChangeVersionL(-1); |
|
314 // Get a handle to message adapter |
|
315 iMessageDbAdapter = CMsvMessageDBAdapter::NewL(iDbAdapter,ETrue); |
|
316 // Our handles are created . and we are good to start |
|
317 } |
|
318 |
|
319 /** |
|
320 ResumeConversionL() |
|
321 Checks if the conversion is to be resumed by looking for conversion status table. |
|
322 |
|
323 @param None |
|
324 @return TBool :Boolean flag specifying if conversion is to be resumed. |
|
325 @internalComponent |
|
326 */ |
|
327 TBool CMessageConverterManager::ResumeConversionL() |
|
328 { |
|
329 // DB exists, Check for conversion Status Table |
|
330 _LIT16(KFindConversionStatusTableQuery, "SELECT COUNT(*) FROM SQLITE_MASTER WHERE NAME LIKE 'ConversionStatus';"); |
|
331 |
|
332 RSqlDatabase temp; |
|
333 CleanupClosePushL(temp); |
|
334 |
|
335 TRAPD(err , temp.OpenL(iDBFileName)); |
|
336 |
|
337 if(err == KErrNone) |
|
338 { |
|
339 // Database found. Check if are resuming. |
|
340 RBuf16 headerTableQuery; |
|
341 CleanupClosePushL(headerTableQuery); |
|
342 headerTableQuery.CreateL(80); |
|
343 |
|
344 headerTableQuery.Append(KFindConversionStatusTableQuery); |
|
345 |
|
346 TInt count = 0; |
|
347 TSqlScalarFullSelectQuery query(temp); |
|
348 count = query.SelectIntL(headerTableQuery); |
|
349 |
|
350 headerTableQuery.Close(); |
|
351 temp.Close(); |
|
352 CleanupStack::PopAndDestroy(); //headerTableQuery |
|
353 CleanupStack::PopAndDestroy(); // temp |
|
354 |
|
355 if(count != 1) |
|
356 { |
|
357 // we did not find the status table. version 1 version 2 conversion |
|
358 iConversionTablePresent = EFalse; |
|
359 } |
|
360 // version 1 version 2 resume. |
|
361 return ETrue; |
|
362 } |
|
363 // database is not present. This is version 0 to version 1 conversion |
|
364 temp.Close(); |
|
365 CleanupStack::PopAndDestroy(); // temp |
|
366 return EFalse; |
|
367 } |
|
368 |
|
369 /** |
|
370 RemoveIndexFileL() |
|
371 Removes the index file. This a called once the conversion completes successfully for a drive. |
|
372 |
|
373 @param aDrive: Drive Number. |
|
374 @return None |
|
375 */ |
|
376 void CMessageConverterManager::RemoveIndexFileL(TDriveNumber aDrive) |
|
377 { |
|
378 RFs fs; |
|
379 User::LeaveIfError(fs.Connect()); |
|
380 CleanupClosePushL(fs); |
|
381 TPtrC drive(TDriveUnit(aDrive).Name()); |
|
382 |
|
383 RBuf path; |
|
384 CleanupClosePushL(path); |
|
385 path.CreateL(KMaxPath); |
|
386 |
|
387 path.Append(drive); |
|
388 path.Append(KIndexFilePath); |
|
389 |
|
390 TInt error = fs.Delete(path); |
|
391 CleanupStack::PopAndDestroy(2); // path |
|
392 } |
|
393 |
|
394 /** |
|
395 RollBackVersion0Version1ConversionL() |
|
396 Rolls back any changes done during version 0 to version 1 conversion |
|
397 |
|
398 @param None: |
|
399 @return None |
|
400 @internalComponent |
|
401 */ |
|
402 void CMessageConverterManager::RollBackVersion0Version1ConversionL() |
|
403 { |
|
404 RFs fs; |
|
405 User::LeaveIfError(fs.Connect()); |
|
406 CleanupClosePushL(fs); |
|
407 |
|
408 TPtrC drive(TDriveUnit(iDrive).Name()); |
|
409 |
|
410 RBuf path; |
|
411 CleanupClosePushL(path); |
|
412 path.CreateL(KMaxPath); |
|
413 |
|
414 path.Append(drive); |
|
415 |
|
416 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) |
|
417 path.Append(KMessagingDBName); |
|
418 #else |
|
419 { |
|
420 path.Append(KMessagingDBFilePath); |
|
421 path.Append(KMessagingDBName); |
|
422 } |
|
423 #endif |
|
424 //TInt err = fs.Delete(path); |
|
425 TInt err = RSqlDatabase::Delete(path); |
|
426 CleanupStack::PopAndDestroy(2); // path ,fs |
|
427 |
|
428 fs.Close(); |
|
429 } |
|
430 |
|
431 /** |
|
432 RollBackVersion1Version2ConversionL() |
|
433 Rolls back any changes done during version 1 to version 2 conversion |
|
434 |
|
435 @param None: |
|
436 @return None |
|
437 @internalComponent |
|
438 */ |
|
439 void CMessageConverterManager::RollBackVersion1Version2ConversionL() |
|
440 { |
|
441 RSqlDatabase temp; |
|
442 CleanupClosePushL(temp); |
|
443 |
|
444 TPtrC drive(TDriveUnit(iDrive).Name()); |
|
445 |
|
446 RBuf path; |
|
447 CleanupClosePushL(path); |
|
448 path.CreateL(KMaxPath); |
|
449 |
|
450 path.Append(drive); |
|
451 |
|
452 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) |
|
453 path.Append(KMessagingDBName); |
|
454 #else |
|
455 { |
|
456 path.Append(KMessagingDBFilePath); |
|
457 path.Append(KMessagingDBName); |
|
458 } |
|
459 #endif |
|
460 |
|
461 temp.OpenL(path); |
|
462 |
|
463 // lets delete the tables we have created. |
|
464 |
|
465 _LIT16(KDropTableQuerySmtp, "DROP table if exists Header_268439592;"); |
|
466 _LIT16(KDropTableQueryPop, "DROP table if exists Header_268439593;"); |
|
467 _LIT16(KDropTableQueryImap, "DROP table if exists Header_268439594;"); |
|
468 _LIT16(KDropTableQuerySms, "DROP table if exists Header_268439596;"); |
|
469 _LIT16(KDropTableQueryConversionStatus, "DROP table if exists ConversionStatus;"); |
|
470 |
|
471 TInt err = temp.Exec(KDropTableQuerySmtp); |
|
472 err = temp.Exec(KDropTableQueryPop); |
|
473 err = temp.Exec(KDropTableQueryImap); |
|
474 err = temp.Exec(KDropTableQuerySms); |
|
475 err = temp.Exec(KDropTableQueryConversionStatus); |
|
476 |
|
477 temp.Close(); |
|
478 CleanupStack::PopAndDestroy(2); // temp |
|
479 } |