|
1 // Copyright (c) 2001-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 //#define __BACKUP_LOGGING |
|
17 |
|
18 #ifdef __BACKUP_LOGGING |
|
19 #define _BACKUPLOG( a ) RFileLogger::WriteFormat(_L("msgs"),_L("backup.txt"),EFileLoggingModeAppend, a ); |
|
20 #define _BACKUPLOGERR( a, b ) RFileLogger::WriteFormat(_L("msgs"),_L("backup.txt"),EFileLoggingModeAppend, a , b); |
|
21 #else |
|
22 #define _BACKUPLOG( a ) |
|
23 #define _BACKUPLOGERR( a, b ) |
|
24 #endif |
|
25 |
|
26 #include "CMsvBackupHandler.h" |
|
27 #include "MSVSERV.H" |
|
28 #include "MSVSTD.H" |
|
29 #include "msvdbadapter.h" |
|
30 #include "msvindexadapter.h" |
|
31 #include <msvapi.h> |
|
32 #include <e32base.h> |
|
33 #include <e32property.h> |
|
34 #include <connect/sbdefs.h> |
|
35 |
|
36 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE) |
|
37 _LIT(KDBFileNamePath,"\\messaging.db"); |
|
38 #else |
|
39 _LIT(KDBFileNamePath,"\\private\\10281e17\\[1000484B]messaging.db"); |
|
40 #endif |
|
41 |
|
42 CMsvBackupHandler* CMsvBackupHandler::NewL(CMsvServer& aServer) |
|
43 { |
|
44 CMsvBackupHandler* self=new (ELeave) CMsvBackupHandler(aServer); |
|
45 CleanupStack::PushL(self); |
|
46 self->ConstructL(); |
|
47 CleanupStack::Pop(self); |
|
48 return(self); |
|
49 } |
|
50 |
|
51 CMsvBackupHandler::CMsvBackupHandler(CMsvServer& aServer) : iServer(aServer) |
|
52 { |
|
53 } |
|
54 |
|
55 CMsvBackupHandler::~CMsvBackupHandler() |
|
56 { |
|
57 _BACKUPLOG(_L("backup handler ending\r\n")); |
|
58 |
|
59 // Unregister ourselves with backup server |
|
60 if (iBackup) |
|
61 { |
|
62 iBackup->DeregisterFile(iFileName); |
|
63 delete iBackup; |
|
64 } |
|
65 } |
|
66 |
|
67 void CMsvBackupHandler::ConstructL() |
|
68 { |
|
69 _BACKUPLOG(_L("Backup handler started\r\n")) |
|
70 |
|
71 TParse parse; |
|
72 |
|
73 RFs fs; |
|
74 CleanupClosePushL(fs); |
|
75 User::LeaveIfError(fs.Connect()); |
|
76 TPtrC driveName = TDriveUnit(MessageServer::CurrentDriveL(fs)).Name(); |
|
77 iFileName = KDBFileNamePath; |
|
78 parse.Set(iFileName, &driveName, NULL); |
|
79 CleanupStack::PopAndDestroy(); // fs |
|
80 iFileName=parse.FullName(); |
|
81 iState=EHaveLock; |
|
82 |
|
83 // Create backup session |
|
84 iBackup = CBaBackupSessionWrapper::NewL(); |
|
85 |
|
86 // Register with the backup server |
|
87 iBackup->RegisterFileL(iFileName, *this); |
|
88 // All done |
|
89 _BACKUPLOGERR(_L("File Registered with Backup Server: \"%S\"\r\n"), &iFileName); |
|
90 } |
|
91 |
|
92 |
|
93 TBool CMsvBackupHandler::Locked() |
|
94 { |
|
95 if(iState==EHaveLock) |
|
96 { |
|
97 return(EFalse); |
|
98 } |
|
99 else |
|
100 { |
|
101 return(ETrue); |
|
102 } |
|
103 } |
|
104 |
|
105 #ifdef __BACKUP_LOGGING |
|
106 void CMsvBackupHandler::ChangeFileLockL(const TDesC& aFileAffected, TFileLockFlags aFlags) |
|
107 #else |
|
108 void CMsvBackupHandler::ChangeFileLockL(const TDesC& /*aFileAffected*/, TFileLockFlags aFlags) |
|
109 #endif |
|
110 { |
|
111 _BACKUPLOG(_L("Got backup event\r\n")) |
|
112 _BACKUPLOGERR(_L("File affected: \"%S\"\r\n"), &aFileAffected); |
|
113 |
|
114 switch(aFlags) |
|
115 { |
|
116 case ETakeLock: // this state gives me the lock back after it has been taken away from me. |
|
117 { |
|
118 _BACKUPLOG(_L("Take lock\r\n")) |
|
119 if(iState==EReleasedForBackup) |
|
120 { |
|
121 iState=EHaveLock; |
|
122 _BACKUPLOG(_L("from backup\r\n")) |
|
123 |
|
124 |
|
125 //Change error state to none |
|
126 iServer.Context().IndexAdapter()->SetErrorState(KErrNone); |
|
127 |
|
128 //Change State |
|
129 iServer.SetStartupState(EMsvNullNotification); |
|
130 |
|
131 _BACKUPLOG(_L("Reloading context\r\n")) |
|
132 ReloadContextL(); |
|
133 } |
|
134 else if(iState==EReleasedForRestore) |
|
135 { |
|
136 // Reload context will result in this object being deleted |
|
137 // therefore this is no longer valid; |
|
138 iState=EHaveLock; |
|
139 //reload as its a new db after restore |
|
140 ReloadContextL(); |
|
141 } |
|
142 else |
|
143 { |
|
144 _BACKUPLOG(_L("bad state\r\n")) |
|
145 __ASSERT_DEBUG(EFalse,PanicServer(EMsvBackupHandlerInUnkownState)); |
|
146 } |
|
147 break; |
|
148 } |
|
149 case EReleaseLockNoAccess: |
|
150 { |
|
151 // please release the lock and don't read or write to the file |
|
152 _BACKUPLOG(_L("release no access\r\n")) |
|
153 |
|
154 // Need to find whether this file lock release request is due to a restore happening. |
|
155 // It is possible that the file system may need us to release our locks for some other |
|
156 // purpose such as formatting an MMC card. |
|
157 TInt backupRestoreState = 0; |
|
158 |
|
159 RProperty property; |
|
160 TInt err = property.Get(KUidSystemCategory, conn::KUidBackupRestoreKey, backupRestoreState); |
|
161 property.Close(); |
|
162 User::LeaveIfError(err); |
|
163 |
|
164 _BACKUPLOGERR(_L("backupRestoreStateValue: \"0x%08x\"\r\n"), backupRestoreState); |
|
165 |
|
166 if ((backupRestoreState & conn::EBURRestoreFull) || (backupRestoreState & conn::EBURRestorePartial)) |
|
167 { |
|
168 // This means they will be restoring the file so I will |
|
169 // have to cope with a new index when I get the lock back. |
|
170 if(DetachFromFile(KMsvIndexRestore)!=EFalse) |
|
171 { |
|
172 _BACKUPLOG(_L("A genuine restore is happening\r\n")) |
|
173 iState=EReleasedForRestore; |
|
174 } |
|
175 } |
|
176 else |
|
177 { |
|
178 // Not a restore operation, so no need to reload the index when |
|
179 // I get the lock back. |
|
180 // Use KMsvIndexRestore to tell the index not to write anything to disk |
|
181 // while the file system is locked... |
|
182 if(DetachFromFile(KMsvIndexRestore)!=EFalse) |
|
183 { |
|
184 // ...but use EReleasedForBackup here so that we don't reload the index from disk |
|
185 // when we get the ETakeLock notification - this would overwrite any index |
|
186 // changes that have happened while the file system was locked, which we want to |
|
187 // keep if the file system was locked for any reason other than Restore. |
|
188 _BACKUPLOG(_L("File system detached for read and write, but not for a restore\r\n")) |
|
189 iState=EReleasedForBackup; |
|
190 } |
|
191 } |
|
192 |
|
193 _BACKUPLOG(_L("released for no access\r\n")) |
|
194 break; |
|
195 } |
|
196 case EReleaseLockReadOnly: |
|
197 { |
|
198 // please release the lock and don't write to the file, I won't read |
|
199 // or write but I also assume the file is being backed up and therefore |
|
200 // the same index will be there when I have finished. |
|
201 _BACKUPLOG(_L("release no read only\r\n")) |
|
202 if(DetachFromFile(KMsvIndexBackup)!=EFalse) |
|
203 { |
|
204 iState=EReleasedForBackup; |
|
205 } |
|
206 _BACKUPLOG(_L("released for read only\r\n")) |
|
207 break; |
|
208 } |
|
209 default: |
|
210 { |
|
211 _BACKUPLOG(_L("bad event\r\n")) |
|
212 __ASSERT_DEBUG(EFalse,PanicServer(EMsvBackupObserverGotUnknownEvent)); |
|
213 break; |
|
214 } |
|
215 } |
|
216 }; |
|
217 |
|
218 |
|
219 TBool CMsvBackupHandler::DetachFromFile(TInt aErrorState) |
|
220 { |
|
221 // if the context is currently in an error state don't do anything, |
|
222 // the current implications of this are that when the disk is removed |
|
223 // or the wrong disk is in the drive and we are asked to release a lock |
|
224 // on the file we won't. |
|
225 _BACKUPLOG(_L("detach to file\r\n")) |
|
226 |
|
227 TInt error = KErrNone; |
|
228 error = iServer.Context().IndexAdapter()->ErrorState(); |
|
229 |
|
230 if(error == KErrNone) |
|
231 { |
|
232 _BACKUPLOG(_L("context good for closing\r\n")) |
|
233 _BACKUPLOG(_L("closing\r\n")) |
|
234 |
|
235 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
236 TUint currDriveIndex = CMsvPreferredDriveList::GetDriveList()->CurrentDriveIndex(); |
|
237 TDriveNumber currDriveNum = CMsvPreferredDriveList::GetDriveList()->CurrentDriveNumber(); |
|
238 |
|
239 // Flush Cache. This will also detach the DB. |
|
240 TRAP(error, iServer.Context().IndexAdapter()->RemoveDriveL(KCurrentDriveId, currDriveIndex, EFalse)); |
|
241 if(error) |
|
242 return(EFalse); |
|
243 // current drive is detached from DB, so cannot access any entries from Database, so will |
|
244 // assing iDbAdpter pointer to temporary iTempDbAdapter pointer and assin NULL to iDbAdpter. |
|
245 iServer.Context().IndexAdapter()->BackupDbAdpter(); |
|
246 TRAP(error, CMsvPreferredDriveList::GetDriveList()->UpdateDriveIdL(currDriveIndex, KCurrentDriveId)); |
|
247 if(error) |
|
248 return(EFalse); |
|
249 #else |
|
250 iEntry.iSize = iServer.Context().IndexAdapter()->GetDbAdapter()->Size(); |
|
251 iServer.Context().IndexAdapter()->DeleteDbAdapter(); |
|
252 #endif // #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
253 |
|
254 _BACKUPLOG(_L("closed\r\n")) |
|
255 |
|
256 iServer.Context().IndexAdapter()->SetErrorState(aErrorState); |
|
257 iServer.SetStartupState(EMsvMediaUnavailable); |
|
258 return(ETrue); |
|
259 } |
|
260 else |
|
261 { |
|
262 return(EFalse); |
|
263 } |
|
264 } |
|
265 |
|
266 |
|
267 |
|
268 // CreateIndexL will result in this object being deleted |
|
269 // so this is no longer valid |
|
270 void CMsvBackupHandler::ReloadContextL() |
|
271 { |
|
272 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT) |
|
273 // for attaching current drive to main Database, assign iDbAdpter with iTempDbAdapter. |
|
274 iServer.Context().IndexAdapter()->RestoreDbAdpter(); |
|
275 iServer.Context().IndexAdapter()->ReloadCacheL(); |
|
276 #else |
|
277 iServer.CreateIndexL(ETrue); |
|
278 #endif |
|
279 } |
|
280 |