42 __SQLLEAVE_IF_ERROR2(lex.Val(num, EHex)); |
48 __SQLLEAVE_IF_ERROR2(lex.Val(num, EHex)); |
43 return num; |
49 return num; |
44 } |
50 } |
45 |
51 |
46 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
52 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
47 |
53 /////////////////////////////// CSqlBurEventMonitor ////////////////////////////////////////////////////////// |
48 // string consts |
54 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
49 _LIT(KRestoreFilter,"*.rst"); // the filter for restore files |
55 |
50 _LIT(KBackupFilter,"*.bak");// the filter for backup files |
56 /** |
51 _LIT(KRestoreSuffix,".bak.rst"); // the suffix for restore files (a shortcut by using double suffix :) |
57 Standard two phase construction. Creates a CSqlBurEventMonitor instance. |
52 |
58 @param aInterface A reference to an interface that is used for retrieving list of databases to be sent for backup. |
53 const TUint K8to16bitShift = 1; |
59 @return An instance of the backup notifier |
54 |
60 @leave KErrNoMemory, an out of memory condition has occurred; |
55 /** Standard two phase construction |
61 Note that the function may also leave with some other system-wide error codes. |
56 @return an instance of the backup client |
62 */ |
57 @param a pointer to the SQL server which must have implemented the |
63 CSqlBurEventMonitor* CSqlBurEventMonitor::NewL(MSqlSrvBurInterface& aInterface) |
58 TSqlSrvBurInterface interface |
64 { |
59 @leave if no memory |
65 CSqlBurEventMonitor* self = new (ELeave) CSqlBurEventMonitor(aInterface); |
60 */ |
|
61 CSqlBackupClient* CSqlBackupClient::NewLC(MSqlSrvBurInterface *aInterface) |
|
62 { |
|
63 CSqlBackupClient *self=(CSqlBackupClient *)new(ELeave) CSqlBackupClient(aInterface); |
|
64 CleanupStack::PushL(self); |
66 CleanupStack::PushL(self); |
65 self->ConstructL(); |
67 self->ConstructL(); |
66 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPCLIENT_NEWLC, "0x%X;CSqlBackupClient::NewLC", (TUint)self)); |
68 CleanupStack::Pop(self); |
|
69 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPNOTIFIER_NEWL, "0x%X;CSqlBurEventMonitor::NewL", (TUint)self)); |
67 return self; |
70 return self; |
68 } |
71 } |
69 |
72 |
70 /** Standard two phase construction |
73 /** |
71 @return an instance of the backup client |
74 Releases the allocated resources. |
72 @param a pointer to the SQL server which must have implemented the |
75 */ |
73 TSqlSrvBurInterface interface |
76 CSqlBurEventMonitor::~CSqlBurEventMonitor() |
74 @leave if no memory |
77 { |
75 */ |
78 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPNOTIFIER_CSQLBACKUPNOTIFIER2, "0x%X;CSqlBurEventMonitor::~CSqlBurEventMonitor", (TUint)this)); |
76 CSqlBackupClient* CSqlBackupClient::NewL(MSqlSrvBurInterface *aInterface) |
79 Cancel(); |
77 { |
80 iBurProperty.Close(); |
78 CSqlBackupClient *self=(CSqlBackupClient *) NewLC(aInterface); |
81 DestroyContent(); |
79 CleanupStack::Pop(); |
82 } |
80 return self; |
83 |
81 } |
84 /** |
82 |
85 Initializes data members with their default values. |
83 /** Standard two phase construction |
86 @param aInterface A reference to an interface that is used for retrieving list of databases to be sent for backup. |
84 @param a pointer to the SQL server which must have implemented the |
|
85 TSqlSrvBurInterface interface |
|
86 */ |
87 */ |
87 CSqlBackupClient::CSqlBackupClient(MSqlSrvBurInterface *aInterface) |
88 CSqlBurEventMonitor::CSqlBurEventMonitor(MSqlSrvBurInterface& aInterface) : |
88 : CActive(EPriorityStandard), iInterface(aInterface) |
89 CActive(EPriorityStandard), |
89 { |
90 iBurInterface(aInterface) |
90 } |
91 { |
91 |
92 } |
92 /** Usual tidy up |
93 |
93 */ |
94 /** |
94 CSqlBackupClient::~CSqlBackupClient() |
95 Initializes the created CSqlBurEventMonitor object. |
95 { |
96 @leave KErrNoMemory, an out of memory condition has occurred; |
96 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_CSQLBACKUPCLIENT2, "0x%X;CSqlBackupClient::~CSqlBackupClient;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle())); |
97 Note that the function may also leave with some other system-wide error codes. |
97 |
|
98 // cancel outstanding requests |
|
99 Cancel(); |
|
100 |
|
101 // release the pub/sub property |
|
102 iBurProperty.Close(); |
|
103 |
|
104 // the file list array |
|
105 iFileList.Close(); |
|
106 |
|
107 // close the file |
|
108 iFile.Close(); |
|
109 |
|
110 // nuke the active backup client |
|
111 delete iActiveBackupClient; |
|
112 } |
|
113 |
|
114 /** Standard two phase construction |
|
115 @leave if non memory or StartL leaves |
|
116 */ |
98 */ |
117 void CSqlBackupClient::ConstructL() |
99 void CSqlBurEventMonitor::ConstructL() |
118 { |
100 { |
119 // attach to backup/restore publish/subscribe property |
101 __SQLLEAVE_IF_ERROR(iBurProperty.Attach(KSqlBurPropertyCategoryUid, KSqlBurBackupRestoreKey)); |
120 __SQLLEAVE_IF_ERROR(iBurProperty.Attach(KUidSystemCategory,KUidBackupRestoreKey)); |
|
121 |
|
122 // add us to the scheduler |
|
123 CActiveScheduler::Add(this); |
102 CActiveScheduler::Add(this); |
124 |
|
125 // set active and request notification of changes to backup |
|
126 // and restore publish/subscribe property |
|
127 StartL(); |
|
128 } |
|
129 |
|
130 /** |
|
131 Cancel the outstanding B&R request |
|
132 */ |
|
133 void CSqlBackupClient::DoCancel() |
|
134 { |
|
135 iBurProperty.Cancel(); |
|
136 } |
|
137 |
|
138 /** Not implemented |
|
139 @return a flag indicating whether we actioned the error |
|
140 @param the error unused |
|
141 */ |
|
142 TInt CSqlBackupClient::RunError(TInt aError) |
|
143 { |
|
144 UNUSED_ARG(aError); |
|
145 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RUNERROR, "0x%X;CSqlBackupClient::RunError;aError=%d", (TUint)this, aError)); |
|
146 // just satisfy it that we did something! |
|
147 return KErrNone; |
|
148 } |
|
149 |
|
150 /** Kick off the BUR client |
|
151 @leave if TestBurStatusL leaves |
|
152 */ |
|
153 void CSqlBackupClient::StartL() |
|
154 { |
|
155 TestBurStatusL(); |
|
156 NotifyChange(); |
|
157 } |
|
158 |
|
159 /** Resubscribe and wait for events |
|
160 */ |
|
161 void CSqlBackupClient::NotifyChange() |
|
162 { |
|
163 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_NOTIFYCHANGE, "0x%X;CSqlBackupClient::NotifyChange;iBurProperty.Handle()=0x%X", (TUint)this, (TUint)iBurProperty.Handle())); |
|
164 iBurProperty.Subscribe(iStatus); |
103 iBurProperty.Subscribe(iStatus); |
165 SetActive(); |
104 SetActive(); |
166 } |
105 } |
167 |
106 |
168 /** Something happened. Find out what. |
107 /** |
169 Create an instance of BUR client if required |
108 RunL() is called when the value of the {KUidSystemCategory, KUidBackupRestoreKey} gets changed. |
170 Delete it if no longer required |
109 That indicates: a backup or a restore is about to begin. |
171 This is for performance reasons |
110 |
172 @leave if ConfirmReadyForBURL leaves |
111 How the function works: |
173 */ |
112 - When a backup or restore notification is received, the function will subscribe again for notifications from |
174 void CSqlBackupClient::TestBurStatusL() |
113 the backup and restore property and will read the property status; |
175 { |
114 - If the property status is conn::EBURUnset or conn::EBURNormal, the function will destroy iSqlBurCallback |
176 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPCLIENT_TESTBURSTATUSL_ENTRY, "Entry;0x%X;CSqlBackupClient::TestBurStatusL", (TUint)this)); |
115 and iActiveBackupClient interfaces. No more callbacks will be reseived from the backup and restore server. |
|
116 This is the end of the backup or restore processing; |
|
117 - If the property status is conn::EBURBackupFull, conn::EBURBackupPartial, conn::EBURRestoreFull or |
|
118 conn::EBURRestorePartial, the function will create iSqlBurCallback and iActiveBackupClient interface |
|
119 (iActiveBackupClient's NewL() receives iSqlBurCallback as an input parameter, registering this way the callback |
|
120 in the backup and restore server to be called later, when sending or retrieving data to/from the server). |
|
121 If the property read and the interface creation operations have been successful, the function will call |
|
122 ConfirmReadyForBURL(KErrNone) to notify the backup and restore server that the SQL server is ready to send/retrieve |
|
123 backup/restore data. |
|
124 If the current notification is that a backup is about to begin, after the confirmation the backup and restore server will |
|
125 call CSqlBurCallback::InitialiseGetProxyBackupDataL() once per {client secure id, drive} |
|
126 followed by CSqlBurCallback::GetBackupDataSectionL() calls to retrieve the backup data. |
|
127 If the current notification is that a restore is about to begin, after the confirmation the backup and restore server will |
|
128 call CSqlBurCallback::InitialiseRestoreProxyBaseDataL() once per {client secure id, drive} |
|
129 followed by CSqlBurCallback::RestoreBaseDataSectionL() calls to send the restore data. |
|
130 |
|
131 The current implementation has one design flaw. If a backup or restore notification is received, there are at lest 3 |
|
132 places before the ConfirmReadyForBURL() call, where the code may leave: |
|
133 - the "property get" operation; |
|
134 - the iSqlBurCallback creation; |
|
135 - the iActiveBackupClient creation; |
|
136 If a leave occurs at some of the mentioned places, that leave will be trapped by the current CActiveScheduler object |
|
137 and CSqlBurEventMonitor::RunError() will be called with the leaved error code. |
|
138 Problem #1: CSqlBurEventMonitor::RunError() won't do anything with the error (apart from printing a trace in the OST builds). |
|
139 The error is silently suppressed. The backup or restore won't start. But the client won't see any notification |
|
140 for that problem. |
|
141 Problem #2: ConfirmReadyForBURL() won't be called. According to the backup and restore documentation, if |
|
142 ConfirmReadyForBURL() is called with KErrNone parameter, that's a confirmation for the backup and restore |
|
143 server to start the processing. If ConfirmReadyForBURL() is called with an error different than KErrNone, |
|
144 that's a confirmation for the backup and restore server that the client is not ready. No backup or restore |
|
145 will be started. The remote backup client will be notified about the problem. |
|
146 After an investigation it was found that the same problems do exist in all active backup clients, none of them has |
|
147 solved the problems. Then, the code here will be kept as it is, it might be too dangerous to do a change right now. |
|
148 |
|
149 @see CSqlBurEventMonitor::RunError() |
|
150 @see CSqlBurCallback |
|
151 @see CActiveBackupClient |
|
152 @see CSqlBurCallback::InitialiseGetProxyBackupDataL() |
|
153 @see CSqlBurCallback::GetBackupDataSectionL() |
|
154 @see CSqlBurCallback::InitialiseRestoreProxyBaseDataL() |
|
155 @see CSqlBurCallback::RestoreBaseDataSectionL() |
|
156 |
|
157 @leave KErrNoMemory, an out of memory condition has occurred; |
|
158 Note that the function may also leave with some other system-wide error codes. |
|
159 */ |
|
160 void CSqlBurEventMonitor::RunL() |
|
161 { |
|
162 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPNOTIFIER_RUNL_ENTRY, "Entry;0x%X;CSqlBurEventMonitor::RunL", (TUint)this)); |
|
163 iBurProperty.Subscribe(iStatus); |
|
164 SetActive(); |
177 TInt status; |
165 TInt status; |
178 __SQLTRACE_BURVAR(TInt err = KErrNone); |
166 __SQLLEAVE_IF_ERROR(iBurProperty.Get(status)); |
179 if((__SQLTRACE_BUREXPR(err =) iBurProperty.Get(status)) != KErrNotFound) |
167 status &= conn::KBURPartTypeMask; |
180 { |
|
181 status&=KBURPartTypeMask; |
|
182 #ifdef _SQL_RDEBUG_PRINT |
168 #ifdef _SQL_RDEBUG_PRINT |
183 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_TESTBURSTATUSL1, "0x%X;CSqlBackupClient::TestBurStatusL;status=%d", (TUint)this, status)); |
169 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPNOTIFIER_RUNL1, "0x%X;CSqlBurEventMonitor::RunL;status=%d", (TUint)this, status)); |
184 #else |
170 #else |
185 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_TESTBURSTATUSL2, "0x%X;CSqlBackupClient::TestBurStatusL;status=%{TBURPartType}", (TUint)this, status)); |
171 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPNOTIFIER_RUNL2, "0x%X;CSqlBurEventMonitor::RunL;status=%{TBURPartType}", (TUint)this, status)); |
186 #endif |
172 #endif |
187 switch(status) |
173 switch(status) |
|
174 { |
|
175 case conn::EBURBackupFull: |
|
176 case conn::EBURBackupPartial: |
|
177 case conn::EBURRestoreFull: |
|
178 case conn::EBURRestorePartial: |
188 { |
179 { |
189 case EBURUnset: // same as EBURNormal |
180 // we only do full backups and full restores |
190 case EBURNormal: |
181 if(!(iSqlBurCallback && iActiveBackupClient)) |
191 delete iActiveBackupClient; |
182 { |
192 iActiveBackupClient=NULL; |
183 DestroyContent(); |
193 break; |
184 TRAPD(err, CreateContentL()); |
194 case EBURBackupFull: |
185 if(err != KErrNone) |
195 case EBURBackupPartial: |
186 { |
196 case EBURRestoreFull: |
187 DestroyContent(); |
197 case EBURRestorePartial: |
188 __SQLLEAVE(err); |
198 // we only do full backups and full restores |
189 } |
199 if(!iActiveBackupClient) |
190 } |
200 { |
191 iActiveBackupClient->ConfirmReadyForBURL(KErrNone); |
201 iActiveBackupClient=CActiveBackupClient::NewL(this); |
|
202 } |
|
203 iActiveBackupClient->ConfirmReadyForBURL(KErrNone); |
|
204 break; |
|
205 default: |
|
206 break; |
|
207 } |
192 } |
|
193 break; |
|
194 //case conn::EBURUnset: |
|
195 //case conn::EBURNormal: |
|
196 default: |
|
197 DestroyContent(); |
|
198 break; |
208 } |
199 } |
209 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_TESTBURSTATUSL_EXIT, "Exit;0x%X;CSqlBackupClient::TestBurStatusL;iProperty.Get() err=%d", (TUint)this, err)); |
200 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPNOTIFIER_EXIT, "Exit;0x%X;CSqlBurEventMonitor::RunL", (TUint)this)); |
210 } |
201 SQL_BUR_TEST_STOP(); |
211 |
202 } |
212 /** Called when BUE notifies a BUR event |
203 |
213 @leave if TestBurStatusL leaves |
204 /** |
214 */ |
205 Cancels the subscribtion for {KUidSystemCategory, KUidBackupRestoreKey} property changes. |
215 void CSqlBackupClient::RunL() |
206 */ |
216 { |
207 void CSqlBurEventMonitor::DoCancel() |
217 NotifyChange(); |
208 { |
218 TestBurStatusL(); |
209 iBurProperty.Cancel(); |
219 } |
210 } |
220 |
211 |
221 /** This is supposed to allow the BUE to know in advance how much |
212 /** |
222 data is coming - but unfortunately there is no way to know this |
213 No-op. The method does nothing with the reported from CSqlBurEventMonitor::RunL() error |
223 at this stage since we don't even know yet what SID is being processed |
214 (apart from logging a trace in OST builds). |
224 So we just answer some number to make the BUE happy. It doesn't |
215 Actually, the right action is to return KErrNone (as it is implemented), otherwise the default implementation of |
225 actually rely on this number so there is no risk - the aFinishedFlag |
216 CActiveScheduler::Error() will panic the current thread. |
226 indicates the end of data, not the value returned here. It is |
217 |
227 supposed to allow the BUE to optimise its behaviour by know up front |
218 @see CActiveScheduler::Error() |
228 the data volume. |
219 @see CSqlBurEventMonitor::RunL() |
229 @return an arbitrary number |
220 |
230 @param TDrive unused |
221 @return The RunL() error, if the RunL() call leaves. |
231 */ |
222 @param The RunL() error |
232 TUint CSqlBackupClient::GetExpectedDataSize(TDriveNumber aDrive) |
223 */ |
|
224 TInt CSqlBurEventMonitor::RunError(TInt aError) |
|
225 { |
|
226 UNUSED_ARG(aError); |
|
227 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RUNERROR, "0x%X;CSqlBurEventMonitor::RunError;aError=%d", (TUint)this, aError)); |
|
228 SQL_BUR_TEST_SET_ERROR(aError); |
|
229 SQL_BUR_TEST_STOP(); |
|
230 return KErrNone; |
|
231 } |
|
232 |
|
233 /** |
|
234 Creates iActiveBackupClient and iSqlBurCallback objects. |
|
235 */ |
|
236 void CSqlBurEventMonitor::CreateContentL() |
|
237 { |
|
238 iSqlBurCallback = CSqlBurCallback::NewL(iBurInterface); |
|
239 iActiveBackupClient = conn::CActiveBackupClient::NewL(iSqlBurCallback); |
|
240 } |
|
241 |
|
242 /** |
|
243 Destroys iActiveBackupClient and iSqlBurCallback objects. |
|
244 */ |
|
245 void CSqlBurEventMonitor::DestroyContent() |
|
246 { |
|
247 delete iActiveBackupClient; |
|
248 iActiveBackupClient = NULL; |
|
249 delete iSqlBurCallback; |
|
250 iSqlBurCallback = NULL; |
|
251 } |
|
252 |
|
253 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
254 /////////////////////////////// CSqlBackupClient ///////////////////////////////////////////////////////////// |
|
255 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
256 |
|
257 |
|
258 /** |
|
259 Creates new CSqlBurCallback instance. |
|
260 The CSqlBurEventMonitor object monitors the state of the {KUidSystemCategory, KUidBackupRestoreKey} |
|
261 property. When a backup or a restore is about to begin, the CSqlBurEventMonitor object creates a |
|
262 CSqlBurCallback instance, establishes a connection with the B&R server and passes a pointer to |
|
263 the CSqlBurCallback callback to the BYR conenction. |
|
264 The CSqlBurCallback methods will be called during the backup/restore for sending/retrieving data. |
|
265 |
|
266 @param aInterface A reference to an interface that is used for retrieving list of databases to be sent for backup. |
|
267 @return A pointer to the created CSqlBurCallback instance |
|
268 @leave KErrNoMemory, an out of memory condition has occurred; |
|
269 Note that the function may also leave with some other system-wide error codes. |
|
270 */ |
|
271 CSqlBurCallback* CSqlBurCallback::NewL(MSqlSrvBurInterface& aInterface) |
|
272 { |
|
273 CSqlBurCallback* self = new (ELeave) CSqlBurCallback(aInterface); |
|
274 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPCLIENT_NEWLC, "0x%X;CSqlBurCallback::NewL", (TUint)self)); |
|
275 return self; |
|
276 } |
|
277 |
|
278 /** |
|
279 Initializes CSqlBurCallback data members with their default values. |
|
280 @param aInterface A reference to an interface that is used for retrieving list of databases to be sent for backup. |
|
281 */ |
|
282 CSqlBurCallback::CSqlBurCallback(MSqlSrvBurInterface& aInterface) : |
|
283 iInterface(aInterface) |
|
284 { |
|
285 } |
|
286 |
|
287 /** |
|
288 Releases the allocated resources. |
|
289 */ |
|
290 CSqlBurCallback::~CSqlBurCallback() |
|
291 { |
|
292 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_CSQLBACKUPCLIENT2, "0x%X;CSqlBurCallback::~CSqlBurCallback;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle())); |
|
293 BackupCleanup(); |
|
294 (void)RestoreCleanup(); |
|
295 } |
|
296 |
|
297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
298 ///////////////////////////////////// Full backup ////////////////////////////////////////////////////////// |
|
299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
300 |
|
301 /** |
|
302 This is called to let us know that the given SID is to be backed up. |
|
303 We ask the SQL server (using iInterface, see MSqlSrvBurInterface for more details) |
|
304 for a list of databases that want to be backed up. |
|
305 |
|
306 The backup is initiated by a notification received in CSqlBurEventMonitor::RunL() method. |
|
307 InitialiseGetProxyBackupDataL() is called once per {client secure id, drive} and each |
|
308 InitialiseGetProxyBackupDataL() call is followed after that by a set of CSqlBurCallback::GetBackupDataSectionL() calls, |
|
309 made from the backup and restore client dll. |
|
310 |
|
311 During GetBackupDataSectionL() calls the CSqlBurCallback object will read the content of the databases from the list, |
|
312 retrieved from the MSqlSrvBurInterface::GetBackUpListL() call and send the content to the backup and restore server. |
|
313 |
|
314 @see MSqlSrvBurInterface |
|
315 @see CSqlBurEventMonitor::RunL() |
|
316 @see CSqlBurCallback::GetBackupDataSectionL() |
|
317 @see CSqlServer::GetBackUpListL() |
|
318 |
|
319 @param aSid the UID of the application to backup |
|
320 @param aDrive the drive to be backed up |
|
321 @leave KErrNoMemory, an out of memory condition has occurred; |
|
322 Note that the function may also leave with some other system-wide error codes. |
|
323 */ |
|
324 void CSqlBurCallback::InitialiseGetProxyBackupDataL(TSecureId aSid, TDriveNumber aDrive) |
|
325 { |
|
326 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_INITIALIZEGETPROXYBACKUPDATAL, "0x%X;CSqlBurCallback::InitialiseGetProxyBackupDataL;aSid=0x%X;aDrive=%d", (TUint)this, (TUint)aSid.iId, (TInt)aDrive)); |
|
327 BackupCleanup(); |
|
328 iInterface.GetBackUpListL(aSid, aDrive, iFileList); |
|
329 iFileIndex = 0; |
|
330 iState = EBackupNoFileOpen; |
|
331 iBackupError = KErrNone; |
|
332 } |
|
333 |
|
334 /** |
|
335 This is supposed to allow the B&R framework to know in advance how much |
|
336 data is coming - but unfortunately there is no way to know this |
|
337 at this stage since we don't even know yet what SID is being processed |
|
338 So we just answer some number to make the BUE happy. It doesn't |
|
339 actually rely on this number so there is no risk - the aFinishedFlag |
|
340 indicates the end of data, not the value returned here. It is |
|
341 supposed to allow the BUE to optimise its behaviour by know up front |
|
342 the data volume. |
|
343 |
|
344 @see CSqlBurEventMonitor::RunL() |
|
345 @see CSqlBurCallback::InitialiseGetProxyBackupDataL() |
|
346 |
|
347 @param aDrive Unused parameter (the drive number is logged in OST builds). |
|
348 @return an arbitrary number (1024 at the moment) |
|
349 */ |
|
350 TUint CSqlBurCallback::GetExpectedDataSize(TDriveNumber aDrive) |
233 { |
351 { |
234 UNUSED_ARG(aDrive); |
352 UNUSED_ARG(aDrive); |
235 // we have no idea at this point - we even don't know who is to be backed up yet |
353 // we have no idea at this point - we even don't know who is to be backed up yet |
236 const TUint KArbitraryNumber = 1024; |
354 const TUint KArbitraryNumber = 1024; |
237 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETEXPECTEDDATASIZE, "0x%X;CSqlBackupClient::GetExpectedDataSize;aDrive=%d;rc=%u", (TUint)this, (TInt)aDrive, KArbitraryNumber)); |
355 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETEXPECTEDDATASIZE, "0x%X;CSqlBurCallback::GetExpectedDataSize;aDrive=%d;rc=%u", (TUint)this, (TInt)aDrive, KArbitraryNumber)); |
238 return KArbitraryNumber; |
356 return KArbitraryNumber; |
239 } |
357 } |
240 |
358 |
241 /** This is the backup state machine |
359 /** |
242 Because the data has to be sent back in sections and the various |
360 This is the backup state machine |
243 components of the dataflow may straddle chunks, we have to keep |
361 Because the data has to be sent back in sections and the various |
244 track of where we are between each transfer - a state machine is |
362 components of the dataflow may straddle chunks, we have to keep |
245 the simplest and most understandable implementation |
363 track of where we are between each transfer - a state machine is |
246 @param TPtr this is where the data will be put to be passed back |
364 the simplest and most understandable implementation. |
247 @param TBool set to true when all data has been submitted for backup |
365 |
248 @leave |
366 Please note how the function processes the errors occuring during the backup. |
249 */ |
367 If an error occurs, the error is not propagated back to the B&R server immediatelly. |
250 void CSqlBackupClient::GetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinishedFlag) |
368 The error is stored in iBurError data member and is reported at the end of the backup process. |
251 { |
369 The reason for such unusual error reporting poicy is: the SQL server performs full backup of possibly more |
252 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETBACKUPDATASECTIONL0, "0x%X;CSqlBackupClient::GetBackupDataSectionL;iState=%d;iFileIndex=%d", (TUint)this, (TInt)iState, iFileIndex)); |
370 than one database file. If an error occurs during the backup of the first file for example, the backup |
|
371 process should not stop at that point. All files will be processed and then at the end, the error will be reproted. |
|
372 |
|
373 In details, the function runs a state machine, where: |
|
374 - every file in the list retrieved in InitialiseGetProxyBackupDataL() is opened; |
|
375 - the file is read and 32-bit checksum over the file data - calculated; |
|
376 - a file backup header is prepared, including there the file size, file name, file name length, protocol verison number |
|
377 and the checksum. The header is sent to the backup restore server; |
|
378 - the file data is read and sent to the backup and restore server; |
|
379 - during the described above sequence no leave ever occurs. The error that occurs during the file processing, |
|
380 is stored into a data member of CSqlBurCallback class. At the end, after the last file in the list is processed, |
|
381 the backup and restore server will get a notification (via a User::Leave() call) regarding the error; |
|
382 The used error reporting policy allows all files to be process without interrupting the backup process. |
|
383 For example, if there are 5 files to be sent to the backup and restore server, an error that occurs during the |
|
384 processing of file #3, won't prevent files #4 and #5 from being sent for backup. |
|
385 |
|
386 @see CSqlBurEventMonitor::RunL() |
|
387 @see CSqlBurCallback::InitialiseGetProxyBackupDataL() |
|
388 |
|
389 @param aBuffer Output parameter, the buffer where the data will be put to be passed back |
|
390 @param aFinishedFlag Set to true when all data has been submitted for backup |
|
391 @leave KErrNoMemory, an out of memory condition has occurred; |
|
392 Note that the function may also leave with some other system-wide error codes. |
|
393 */ |
|
394 void CSqlBurCallback::GetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinishedFlag) |
|
395 { |
253 // don't assume they set it to false |
396 // don't assume they set it to false |
254 aFinishedFlag=EFalse; |
397 aFinishedFlag=EFalse; |
255 // any files to backup |
398 // any files to backup |
256 if(iFileList.Count()==0) |
399 if(iFileList.Count()==0) |
257 { |
400 { |
258 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETBACKUPDATASECTIONL1, "0x%X;CSqlBackupClient::GetBackupDataSectionL;file count is 0", (TUint)this)); |
401 // nothing to backup |
259 // nothing to backup - just return the finished flag |
402 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETBACKUPDATASECTIONL1, "0x%X;CSqlBurCallback::GetBackupDataSectionL;file count is 0", (TUint)this)); |
260 aFinishedFlag=ETrue; |
403 aFinishedFlag = ETrue; |
261 // clear down the list |
404 BackupCleanup(); |
262 iFileList.Reset(); |
|
263 // iFileList closed in dtor |
|
264 return; |
405 return; |
265 } |
406 } |
266 |
407 |
267 // run the state machine |
408 // run the state machine |
268 for(TInt bufFreeSpace=aBuffer.MaxSize()-aBuffer.Size(); bufFreeSpace>0; bufFreeSpace=aBuffer.MaxSize()-aBuffer.Size()) |
409 for(TInt bufFreeSpace=aBuffer.MaxSize()-aBuffer.Size(); bufFreeSpace>0; bufFreeSpace=aBuffer.MaxSize()-aBuffer.Size()) |
383 } |
542 } |
384 break; |
543 break; |
385 } |
544 } |
386 case EBackupEndOfFile: |
545 case EBackupEndOfFile: |
387 { |
546 { |
388 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETBACKUPDATASECTIONL4, "0x%X;CSqlBackupClient::GetBackupDataSectionL;END;iFile.SubSessionHandle()=0x%X;iFileIndex=%d", (TUint)this, (TUint)iFile.SubSessionHandle(), iFileIndex)); |
547 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETBACKUPDATASECTIONL7, "0x%X;CSqlBurCallback::GetBackupDataSectionL;END;iFile.SubSessionHandle()=0x%X;iFileIndex=%d", (TUint)this, (TUint)iFile.SubSessionHandle(), iFileIndex)); |
389 iFile.Close(); |
548 iFile.Close(); |
390 ++iFileIndex; // move on to next file |
549 ++iFileIndex; // move on to next file |
391 iState = EBackupNoFileOpen; // go round again |
550 iState = EBackupNoFileOpen; // go round again |
392 break; |
551 break; |
393 } |
552 } |
394 default: |
553 default: |
395 { |
554 __ASSERT_DEBUG(EFalse, __SQLPANIC(ESqlPanicInternalError)); |
396 break; |
555 break; |
397 } |
|
398 }//end of the "switch" statement |
556 }//end of the "switch" statement |
399 }//end of the "for" statement |
557 }//end of the "for" statement |
400 } |
558 } |
401 |
559 |
402 /** This is called by BUE when the restore has completed |
560 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
403 Nothing to do here except tell the server |
561 ///////////////////////////////////// Full restore ///////////////////////////////////////////////////////// |
404 @param TDrive the drive that is being restored (unused) |
562 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
405 */ |
563 |
406 void CSqlBackupClient::RestoreComplete(TDriveNumber aDrive) |
564 /** |
407 { |
565 Called when the BUE wants to start sending data to us. |
|
566 Creates the folder (if the folder does not exist) where the temporary files will be created during the restore process. |
|
567 Deletes all files from the restore folder. |
|
568 |
|
569 The restore is initiated by a notification received in CSqlBurEventMonitor::RunL() method. |
|
570 InitialiseRestoreProxyBaseDataL() is called once per {client secure id, drive} and each |
|
571 InitialiseRestoreProxyBaseDataLL() call is followed after that by a set of CSqlBurCallback::RestoreBaseDataSectionL() |
|
572 calls, made from the backup and restore client dll. |
|
573 |
|
574 During RestoreBaseDataSectionLL() calls the CSqlBurCallback object will receive data from the backup and resore server. |
|
575 |
|
576 @see CSqlBurEventMonitor::RunL() |
|
577 @see CSqlBurCallback::RestoreBaseDataSectionL() |
|
578 |
|
579 @param aSid the UID of the application that is to be restored. Not used (only logged in OST builds). |
|
580 @param aDrive the drive to restore. |
|
581 @leave KErrNoMemory, an out of memory condition has occurred; |
|
582 Note that the function may also leave with some other system-wide error codes. |
|
583 */ |
|
584 void CSqlBurCallback::InitialiseRestoreProxyBaseDataL(TSecureId aSid, TDriveNumber aDrive) |
|
585 { |
|
586 UNUSED_ARG(aSid); |
408 UNUSED_ARG(aDrive); |
587 UNUSED_ARG(aDrive); |
409 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTORECOMPLETE, "0x%X;CSqlBackupClient::RestoreComplete;aDrive=%d", (TUint)this, (TInt)aDrive)); |
588 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_INITIALIZERESTOREPROXYBASEDATAL, "0x%X;CSqlBurCallback::InitialiseRestoreProxyBaseDataL;aSid=0x%X;aDrive=%d", (TUint)this, (TUint)aSid.iId, (TInt)aDrive)); |
410 } |
589 iBuffer.Zero(); |
411 |
590 iState = ERestoreExpectChecksum; |
412 /** This is called to let us know that the given SID is to be backed up |
591 iRestoreDrive = aDrive; |
413 We ask the SQL server for a list of databases that want to be backed |
592 iRestoreId = aSid; |
414 up - this is because the backup flag is an internal metadata object |
593 //Create the directory for the temporary files created during the restore process. |
415 in the database, and to decouple we don't want to have to know how |
594 TFileName privatePath; |
416 this data is stored. |
595 __SQLLEAVE_IF_ERROR(iInterface.Fs().PrivatePath(privatePath)); |
417 @param TSecureSid the UID of the application to backup |
596 TDriveUnit driveUnit(iRestoreDrive); |
418 @param TDriveNumber the drive to be backed up (unused) |
597 TDriveName driveName = driveUnit.Name(); |
419 @leave |
598 privatePath.Insert(0, driveName); |
420 */ |
599 __SQLLEAVE_IF_ERROR(iParse.Set(KSqlBurRestoreDir, &privatePath, 0)); |
421 void CSqlBackupClient::InitialiseGetProxyBackupDataL(TSecureId aSid, TDriveNumber aDrive) |
600 iRestoreDir.Copy(iParse.FullName()); |
|
601 iRestoreDir.Append(KPathDelimiter); |
|
602 TInt err = iInterface.Fs().MkDirAll(iRestoreDir); |
|
603 if(err != KErrAlreadyExists) |
|
604 { |
|
605 __SQLLEAVE_IF_ERROR(err); |
|
606 } |
|
607 //Cleanup the restore directory |
|
608 err = RestoreCleanup(); |
|
609 if(err != KErrNotFound) |
|
610 { |
|
611 __SQLLEAVE_IF_ERROR(err); |
|
612 } |
|
613 } |
|
614 |
|
615 /** |
|
616 This is called by BUE when the restore has completed. |
|
617 |
|
618 @see CSqlBurEventMonitor::RunL() |
|
619 @see CSqlBurCallback::InitialiseRestoreProxyBaseDataL() |
|
620 |
|
621 @param aDrive the drive that is being restored. Not used (only logged in OST builds). |
|
622 */ |
|
623 void CSqlBurCallback::RestoreComplete(TDriveNumber aDrive) |
422 { |
624 { |
423 UNUSED_ARG(aDrive); |
625 UNUSED_ARG(aDrive); |
424 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_INITIALIZEGETPROXYBACKUPDATAL, "0x%X;CSqlBackupClient::InitialiseGetProxyBackupDataL;aSid=0x%X;aDrive=%d", (TUint)this, (TUint)aSid.iId, (TInt)aDrive)); |
626 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTORECOMPLETE, "0x%X;CSqlBurCallback::RestoreComplete;aDrive=%d", (TUint)this, (TInt)aDrive)); |
425 // get the list of database files to back up - this is provided by the SQL server |
627 iRestoreDrive = TDriveNumber(-1); |
426 GetBackupListL(aSid); |
628 iRestoreId = TSecureId(KNullUid); |
427 // this is the index of the file being processed - point to the beginning |
629 } |
428 iFileIndex=0; |
630 |
429 // the first state of the backup state machine |
631 /** |
430 iState=EBackupNoFileOpen; |
632 This is repeatedly called by the BUE to send us chunks of restore data (for the current SID) |
431 // save the sid for notifying the server when the backup is complete |
633 Becuase the data is spread over chunks we need to manage the state across mutiple calls |
432 iSid=aSid; |
634 to this method so we use a state machine. |
433 } |
635 |
434 |
636 The function runs the state machine and for each file block detected in the coming data, the function does: |
435 /** Called when the BUE wants to start sending data to us |
637 - creates a temporary file in the restore directory (created by InitialiseRestoreProxyBaseDataL()); |
436 @param TSecureId the UID of the application that is to be restored |
638 - stores the file data in the created temporary file; |
437 @param TDriveNumber the drive to restore (unused) |
639 - During the 2 steps descirbed above, if an error occurs, that erro will be reproted to the backup and restore |
438 @leave |
640 server (via a User::Leave() call); |
439 */ |
641 - When all data is received and stored in temporary files in the restore directory, |
440 void CSqlBackupClient::InitialiseRestoreProxyBaseDataL(TSecureId aSid, TDriveNumber aDrive) |
642 for each received file the function will: |
441 { |
643 = move the original database file to the restore directory with a ".bak" extension added to the file name; |
442 UNUSED_ARG(aDrive); |
644 = move the temporary file, which has the same name as the original database file, to the location of the |
443 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_INITIALIZERESTOREPROXYBASEDATAL, "0x%X;CSqlBackupClient::InitialiseRestoreProxyBaseDataL;aSid=0x%X;aDrive=%d", (TUint)this, (TUint)aSid.iId, (TInt)aDrive)); |
645 original database file - the SQL server private data cage; |
444 iBuffer.Zero(); |
646 = delete the file with the ".bak" extension; |
445 // this is the first state of the restore state machine |
647 The three steps described above are implemented as "all or none" operation - if an error occurs during step (2), |
446 iState=ERestoreExpectChecksum; |
648 the content of the original database file will be restored from the file with the ".bak" extension. |
447 iAnyData=EFalse; // to keep track in the state machine whether any data was actually sent |
649 |
448 // save the sid for notifying the server when the restore is done |
650 @see CSqlBurEventMonitor::RunL() |
449 iSid=aSid; |
651 @see CSqlBurCallback::InitialiseRestoreProxyBaseDataL() |
450 } |
652 |
451 |
653 @param aInBuffer Buffer with data to be restored |
452 /** This is repeatedly called by the BUE to send us chunks of restore data (for the current SID) |
654 @param aFinishedFlag Set when there is not more data to restore |
453 Becuase the data is spread over chunks we need to manage the state across mutiple calls |
655 @leave KErrNoMemory, an out of memory condition has occurred; |
454 to this method so we use a state machine |
656 Note that the function may also leave with some other system-wide error codes. |
455 @leave KErrCorrupt if the data is incomplete or the checksum fails |
657 */ |
456 @param TDesc8 the data to be restored |
658 void CSqlBurCallback::RestoreBaseDataSectionL(TDesC8& aInBuffer, TBool aFinishedFlag) |
457 @param TBool set when there is not more data to restore |
659 { |
458 |
|
459 Attention!!! This function won't work properly if aInBuffer parameter contains odd number of bytes!!! |
|
460 (a legacy problem, if it is a problem at all, because the B&R engine probably sends the data in chunks with even size) |
|
461 */ |
|
462 void CSqlBackupClient::RestoreBaseDataSectionL(TDesC8& aInBuffer, TBool aFinishedFlag) |
|
463 { |
|
464 SQL_TRACE_BUR(OstTraceExt4(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL0, "0x%X;CSqlBackupClient::RestoreBaseDataSectionL;iState=%d;aInBuffer.Length()=%d;aFinishedFlag=%d", (TUint)this, (TInt)iState, aInBuffer.Length(), (TInt)aFinishedFlag)); |
|
465 // used to walk the buffer |
660 // used to walk the buffer |
466 // got a new buffer - because each time this method is called, we have a |
661 // got a new buffer - because each time this method is called, we have a |
467 // fresh chunk of data |
662 // fresh chunk of data |
468 TInt inBufferPos = 0; |
663 TInt inBufferPos = 0; |
469 |
664 |
470 // to mark when the state machine is through |
665 // to mark when the state machine is through |
471 TBool done = EFalse; |
666 TBool done = EFalse; |
472 |
667 |
473 // check whether this is an empty restore |
668 // check whether this is an empty restore |
474 if(aFinishedFlag && !iAnyData) |
669 if(aFinishedFlag && aInBuffer.Size() == 0) |
475 { |
670 { |
476 // we have to do this and not rely on aFinishedFlag alone, becuase |
|
477 // if aFinished is used, we'll process the last state of the machine |
|
478 // which does tidyup, except that if there was no data, no tidyup should |
|
479 // be done |
|
480 return; |
671 return; |
481 } |
672 } |
482 |
673 |
483 // run the machine |
674 TInt iterations = 0; |
|
675 |
|
676 // run the state machine |
484 do |
677 do |
485 { |
678 { |
486 // how many bytes are there available in the buffer for processing? |
679 // how many bytes are there available in the buffer for processing? |
487 TInt bytesAvailable = aInBuffer.Size() - inBufferPos; |
680 TInt bytesAvailable = aInBuffer.Size() - inBufferPos; |
488 // the reason why we are testing finishedFlag is because we must |
681 // the reason why we are testing finishedFlag is because we must |
578 break; |
759 break; |
579 } |
760 } |
580 case ERestoreExpectFileName: // the name of the file to restore |
761 case ERestoreExpectFileName: // the name of the file to restore |
581 { |
762 { |
582 CopyBufData(aInBuffer, inBufferPos, iBuffer, iFileNameSize); |
763 CopyBufData(aInBuffer, inBufferPos, iBuffer, iFileNameSize); |
583 SQL_TRACE_BUR(OstTraceExt4(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL2, "0x%X;CSqlBackupClient::RestoreBaseDataSectionL;BEGIN;iBuffer=%S;iBuffer.Length()=%d;iFileNameSize=%d", (TUint)this, __SQLPRNSTR(iBuffer), iBuffer.Length(), iFileNameSize)); |
764 SQL_TRACE_BUR(OstTraceExt4(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL2, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;BEGIN;iBuffer=%S;iBuffer.Length()=%d;iFileNameSize=%d", (TUint)this, __SQLPRNSTR(iBuffer), iBuffer.Length(), iFileNameSize)); |
584 if(iBuffer.Length() == iFileNameSize) |
765 if(iBuffer.Length() == iFileNameSize) |
585 { |
766 { |
586 iState = ERestoreExpectData; |
767 iState = ERestoreExpectData; |
587 iBuffer.Append(KRestoreSuffix); |
768 TParse parse; |
588 // now we start writing the data to the target file |
769 __SQLLEAVE_IF_ERROR(parse.Set(iBuffer, 0, 0)); |
589 // write to a temp - double disk space potentially |
770 __SQLLEAVE_IF_ERROR(iParse.Set(parse.NameAndExt(), &iRestoreDir, 0)); |
590 // once all the temp files are created, then they are renamed to the |
771 TPtrC fname(iParse.FullName()); |
591 // real file names in one fell swoop |
772 //The database is restored first to a temporary file, in the restore folder, on the same drive. |
592 __SQLLEAVE_IF_ERROR(iFile.Replace(iInterface->Fs(), iBuffer, EFileWrite | EFileShareExclusive)); |
773 __SQLLEAVE_IF_ERROR(iFile.Replace(iInterface.Fs(), fname, EFileWrite | EFileShareExclusive)); |
593 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL3, "0x%X;CSqlBackupClient::RestoreBaseDataSectionL;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle())); |
774 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL3, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;fname=%S;iFile.SubSessionHandle()=0x%X", (TUint)this, __SQLPRNSTR(fname), (TUint)iFile.SubSessionHandle())); |
594 iBuffer.Zero(); |
775 iBuffer.Zero(); |
595 } |
776 } |
596 break; |
777 break; |
597 } |
778 } |
598 case ERestoreExpectData: // now for the data |
779 case ERestoreExpectData: // now for the data |
599 { |
780 { |
600 TInt len = Min((aInBuffer.Size() - inBufferPos), iFileSize); |
781 TInt len = Min((aInBuffer.Size() - inBufferPos), iFileSize); |
601 __SQLLEAVE_IF_ERROR(iFile.Write(aInBuffer.Mid(inBufferPos, len))); |
782 TInt err = iFile.Write(aInBuffer.Mid(inBufferPos, len)); |
|
783 if(err != KErrNone) |
|
784 { |
|
785 (void)RestoreCleanup(); |
|
786 __SQLLEAVE(err); |
|
787 } |
602 inBufferPos += len; |
788 inBufferPos += len; |
603 iFileSize -= len; |
789 iFileSize -= len; |
604 if(iFileSize == 0) |
790 if(iFileSize == 0) |
605 { |
791 { |
606 iState = ERestoreComplete; |
792 iState = ERestoreComplete; |
607 } |
793 } |
608 break; |
794 break; |
609 } |
795 } |
610 case ERestoreComplete: // file completely restored |
796 case ERestoreComplete: // file completely restored |
611 { |
797 { |
612 // calculate the checksum |
798 TUint64 checkSum64 = 0; |
613 TUint32 cksum = CheckSumL(iFile) & KMaxTUint32; |
799 TInt restoreErr = iFile.Flush(); |
614 |
800 if(restoreErr == KErrNone) |
615 // done with the file now - has to follow checksum cos it |
801 { |
616 // expects ann open file |
802 // calculate the checksum |
617 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL4, "0x%X;CSqlBackupClient::RestoreBaseDataSectionL;END;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle())); |
803 restoreErr = CheckSum(iFile, checkSum64); |
618 __SQLLEAVE_IF_ERROR(iFile.Flush()); |
804 } |
619 iFile.Close(); |
805 iFile.Close(); |
620 |
806 if(restoreErr != KErrNone) |
621 // validate that the checksum matches |
807 { |
622 if(cksum!=iChecksum) |
808 (void)RestoreCleanup(); |
|
809 __SQLLEAVE(restoreErr); |
|
810 } |
|
811 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL4, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;END;iFile.SubSessionHandle()=0x%X", (TUint)this, (TUint)iFile.SubSessionHandle())); |
|
812 TUint32 checkSum32 = checkSum64 & KMaxTUint32; |
|
813 if(checkSum32 != iChecksum) |
623 { |
814 { |
|
815 (void)RestoreCleanup(); |
624 __SQLLEAVE(KErrCorrupt); |
816 __SQLLEAVE(KErrCorrupt); |
625 } |
817 } |
626 |
818 if((aInBuffer.Size() - inBufferPos) > 0) |
627 // end of data - or another file to be restored? |
819 {//There are bytes to be consumed in the input buffer |
628 if(aFinishedFlag) |
820 iState = ERestoreExpectChecksum; |
629 { |
821 break; |
630 // we need to rename all the |
822 } |
631 // temp rst files to the real database names |
823 SQL_TRACE_BUR(OstTrace1(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL5, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;aFinishedFlag=ETrue", (TUint)this)); |
632 CDir *dir=NULL; |
824 //End of data. We have all data restored in the restore folder. |
633 __SQLLEAVE_IF_ERROR(iInterface->Fs().GetDir(KRestoreFilter,KEntryAttNormal,ESortNone,dir)); |
825 //The final step of the "restoring files" process consists of the following sub-steps: |
634 CleanupStack::PushL(dir); |
826 // - Rename the database file to be restored to a file with ".bak" extension |
635 TInt err2 = KErrNone; |
827 // - Rename the file with the restored data to the database file |
636 for(TInt a=0;a<dir->Count();++a) |
828 // - Delete the file with ".bak" extension |
|
829 //Do not leave during the restore process! Restore as much files as possible. |
|
830 //The only excpetion is TParse::Set() - if it fails it is a fatal error, the |
|
831 //restored file path cannot be constructed. |
|
832 __ASSERT_DEBUG(iRestoreDrive != TDriveNumber(-1), __SQLPANIC(ESqlPanicInternalError)); |
|
833 __ASSERT_DEBUG(iRestoreId != TSecureId(KNullUid), __SQLPANIC(ESqlPanicInternalError)); |
|
834 //Include the aUid and the "*" mask |
|
835 TUidName uidName = (static_cast <TUid> (iRestoreId)).Name(); |
|
836 TBuf<KMaxUidName + sizeof(KSqlBurAllFiles)> fileNameMask(uidName); |
|
837 fileNameMask.Append(KSqlBurAllFiles); |
|
838 __SQLLEAVE_IF_ERROR(iParse.Set(fileNameMask, &iRestoreDir, 0)); |
|
839 CDir* dir = NULL; |
|
840 TPtrC searchPattern(iParse.FullName()); |
|
841 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL55, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;search pattern=%S", (TUint)this, __SQLPRNSTR(searchPattern))); |
|
842 restoreErr = iInterface.Fs().GetDir(searchPattern, KEntryAttNormal, ESortNone, dir); |
|
843 if(restoreErr == KErrNone) |
|
844 { |
|
845 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL6, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;restored files=%d", (TUint)this, dir->Count())); |
|
846 for(TInt i=0;i<dir->Count();++i) |
637 { |
847 { |
638 TEntry entry=(*dir)[a]; |
848 const TEntry& entry = (*dir)[i]; |
639 TPtrC rst=entry.iName.Des(); |
849 __SQLLEAVE_IF_ERROR(iParse.Set(entry.iName, &iRestoreDir, 0)); |
640 TInt len=rst.Length(); |
850 TFileName dbName(iParse.FullName()); |
641 // format <filename>.db.bak.rst |
851 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL7, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;restored file=%S", (TUint)this, __SQLPRNSTR(dbName))); |
642 // just a convenience! |
852 TInt pos = dbName.Find(KSqlBurRestoreDir); |
643 TPtrC bak(rst.Left(len - 4));//".rst" part excluded |
853 __ASSERT_DEBUG(pos >= 0, __SQLPANIC(ESqlPanicInternalError)); |
644 TPtrC db(rst.Left(len - 8));//".bak.rst" part excluded |
854 dbName.Delete(pos, KSqlBurRestoreDir().Length() + 1);//"+1" for the path delimitier |
645 |
855 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL8, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;database=%S", (TUint)this, __SQLPRNSTR(dbName))); |
646 // first, rename the orig .db as .bak just in case |
856 TFileName bakDbName(iParse.FullName()); |
647 // ok if not found - might have been deleted. |
857 bakDbName.Append(KSqlBurBackupExt); |
648 //the ".bak" file, if exists, will be deleted first. |
858 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL9, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;backup file=%S", (TUint)this, __SQLPRNSTR(dbName))); |
649 (void)iInterface->Fs().Delete(bak); |
859 //Now, dbName contains the original database (full path), iParse - the restored file, |
650 TInt err=iInterface->Fs().Rename(db,bak); |
860 //bakDbName - backup file name |
651 SQL_TRACE_BUR(OstTraceExt4(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL5, "0x%X;CSqlBackupClient::RestoreBaseDataSectionL;END;bak=%S;db=%S;err=%d", (TUint)this, __SQLPRNSTR(bak), __SQLPRNSTR(db), err)); |
861 TInt err = iInterface.Fs().Rename(dbName, bakDbName); |
652 if(err == KErrNone || err == KErrNotFound) |
862 if(err == KErrNone || err == KErrNotFound) |
653 { |
863 { |
654 // now, rename the .rst as .db |
864 err = iInterface.Fs().Rename(iParse.FullName(), dbName); |
655 err = iInterface->Fs().Rename(rst,db); |
865 if(err == KErrNone) |
|
866 {//commit: delete the backup database file |
|
867 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL10, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;Commit;file=%S", (TUint)this, __SQLPRNSTR(dbName))); |
|
868 (void)iInterface.Fs().Delete(bakDbName); |
|
869 } |
|
870 else |
|
871 {//rollback: restore the original database file |
|
872 err = iInterface.Fs().Rename(bakDbName, dbName); |
|
873 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL11, "0x%X;CSqlBurCallback::RestoreBaseDataSectionL;Rollback;file=%S;err=%d", (TUint)this, __SQLPRNSTR(dbName), err)); |
|
874 } |
656 } |
875 } |
657 if(err != KErrNone && err2 == KErrNone) |
876 if(err != KErrNone && err != KErrNotFound) |
658 { |
877 { |
659 //The idea here is to not report the error immediatelly by calling LeaveIfError(). |
878 if(restoreErr == KErrNone) |
660 //If we leave here, the next database restore may also fail, for example, if the current database is still open by |
879 { |
661 //its owner. Then "TInt err=iInterface->Fs().Rename(db,bak);" will fail again. |
880 restoreErr = err; |
662 err2 = err; |
881 } |
663 } |
882 } |
664 // if we got here, we have a backup of the original database in .db.bak |
883 }//for(...) |
665 // and the new database in .db |
884 delete dir; |
666 }//end of for(...) |
885 }//iInterface.Fs().GetDir(...) |
667 __SQLLEAVE_IF_ERROR(err2); |
886 done = ETrue; |
668 |
887 (void)RestoreCleanup(); |
669 // clean up dir |
888 if(restoreErr != KErrNone) |
670 //delete dir; |
889 { |
671 CleanupStack::PopAndDestroy(dir); |
890 __SQLLEAVE(restoreErr); |
672 dir=NULL; |
891 } |
673 |
|
674 // now delete all the .bak files |
|
675 // we do this here and not part of the earlier loop |
|
676 // because we want to make sure that we have a coherent set of database |
|
677 // files that belong together and not bits of old and new |
|
678 __SQLLEAVE_IF_ERROR(iInterface->Fs().GetDir(KBackupFilter,KEntryAttNormal,ESortNone,dir)); |
|
679 CleanupStack::PushL(dir); |
|
680 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_RESTOREBASEDATASECTONL6, "0x%X;CSqlBackupClient::RestoreBaseDataSectionL;bak files count=%d", (TUint)this, dir->Count())); |
|
681 for(TInt a1=0;a1<dir->Count();++a1) |
|
682 { |
|
683 TEntry entry=(*dir)[a1]; |
|
684 TPtrC bak=entry.iName.Des(); |
|
685 __SQLLEAVE_IF_ERROR(iInterface->Fs().Delete(bak)); |
|
686 } |
|
687 |
|
688 // clean up dir |
|
689 //delete dir; |
|
690 CleanupStack::PopAndDestroy(dir); |
|
691 dir=NULL; |
|
692 done=ETrue; |
|
693 } |
|
694 else |
|
695 { |
|
696 iState=ERestoreExpectChecksum; |
|
697 } |
|
698 |
|
699 break; |
892 break; |
700 } |
893 } |
701 default: |
894 default: |
702 break; |
895 __ASSERT_DEBUG(EFalse, __SQLPANIC(ESqlPanicInternalError)); |
|
896 break; |
|
897 }//switch(...) |
|
898 if((aInBuffer.Size() - inBufferPos) == bytesAvailable) |
|
899 {//No bytes have been consumed from the buffer. |
|
900 if(++iterations > 1 && !done) |
|
901 {//This is the second iteration in the loop where no bytes have been consumed from the input buffer. |
|
902 //But the "done" flag is still false. Corrupted archive. |
|
903 __SQLLEAVE(KErrCorrupt); |
|
904 } |
703 } |
905 } |
704 } while(!done); |
906 } while(!done); |
705 } |
907 } |
706 |
908 |
707 /** The operation was terminated - we should tidyup here (as best we can) |
909 /** |
708 Nothing needs to be done for a backup. Restore is more |
910 The operation was terminated - we should tidyup here (as best we can) |
709 complicated in the case of an interruption. |
911 Backup: close the file, free the allocated memory for the file names. |
710 What we need to do here is move all the backup files |
912 Restore: since the final restore step is a non-leaving one, nothing special needs to be done here - |
711 back to being db files.... |
913 RestoreCleanup() is called to close the file and delete if there are any temporary files left. |
712 */ |
914 */ |
713 void CSqlBackupClient::TerminateMultiStageOperation() |
915 void CSqlBurCallback::TerminateMultiStageOperation() |
714 { |
916 { |
715 // backup/restore terminated, try to tidy up! Can't leave, can't Panic!!!!! |
917 BackupCleanup(); |
716 // rename all the .bak files to .db |
918 (void)RestoreCleanup(); |
717 CDir *dir=NULL; |
919 } |
718 TInt rc=iInterface->Fs().GetDir(KBackupFilter,KEntryAttNormal,ESortNone,dir); |
920 |
719 SQL_TRACE_BUR(OstTraceExt3(TRACE_INTERNALS, CSQLBACKUPCLIENT_TERMINATEMULTISTAGEOPERATION1, "0x%X;CSqlBackupClient::TerminateMultiStageOperation;Fs().GetDir() err=%d;file count=%d", (TUint)this, rc, rc == KErrNone ? dir->Count() : 0)); |
921 /** |
720 if(KErrNone!=rc) |
922 We do our own checksumming so we don't need this |
721 { |
923 @return the checksum |
722 // can't get a file list - can't do anything |
924 @param aDrive the drive affected (unused) |
723 return; |
925 */ |
724 } |
926 TUint CSqlBurCallback::GetDataChecksum(TDriveNumber /* aDrive */) |
725 for(TInt a=0;a<dir->Count();++a) |
|
726 { |
|
727 TEntry entry=(*dir)[a]; |
|
728 TPtrC bak=entry.iName.Des(); |
|
729 TInt len=bak.Length(); |
|
730 TPtrC db(bak.Left(len-4));//".bak" part excluded |
|
731 rc=iInterface->Fs().Delete(db); // rename does not overwrite |
|
732 if(KErrNone == rc) |
|
733 { |
|
734 rc = iInterface->Fs().Rename(bak,db); |
|
735 } |
|
736 //The function cannot leave or return an error. The only thing which could be done here is to print out something |
|
737 //and continue with the next file. |
|
738 if(KErrNone != rc) |
|
739 { |
|
740 SQL_TRACE_BUR(OstTraceExt4(TRACE_INTERNALS, CSQLBACKUPCLIENT_TERMINATEMULTISTAGEOPERATION2, "0x%X;CSqlBackupClient::TerminateMultiStageOperation;Fs().Rename() err=%d;bak=%S;db=%S", (TUint)this, rc, __SQLPRNSTR(bak), __SQLPRNSTR(db))); |
|
741 } |
|
742 // backup restored ok |
|
743 } |
|
744 // cleanup dir |
|
745 delete dir; |
|
746 } |
|
747 |
|
748 /** We do our own checksumming so we don't need this |
|
749 @return the checksum |
|
750 @param TDriveNumber the drive affected (unused) |
|
751 */ |
|
752 TUint CSqlBackupClient::GetDataChecksum(TDriveNumber /* aDrive */) |
|
753 { |
927 { |
754 // not required - not implemented |
928 // not required - not implemented |
755 const TUint KArbitraryNumber = 1024; |
929 const TUint KArbitraryNumber = 1024; |
756 return KArbitraryNumber; |
930 return KArbitraryNumber; |
757 } |
931 } |
758 |
932 |
759 /** We don't support incremental backup |
933 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
760 */ |
934 /////////////////////////// Incremental backup/restore //////////////////////////////////////////////////// |
761 void CSqlBackupClient::GetSnapshotDataL(TDriveNumber /* aDrive */, TPtr8& /* aBuffer */, |
935 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
762 TBool& /* aFinishedFlag */) |
936 |
763 { |
937 /** |
764 // incremental backup not supported |
938 We don't support incremental backup |
|
939 */ |
|
940 void CSqlBurCallback::GetSnapshotDataL(TDriveNumber /* aDrive */, TPtr8& /* aBuffer */, TBool& /* aFinishedFlag */) |
|
941 { |
765 __SQLLEAVE(KErrNotSupported); |
942 __SQLLEAVE(KErrNotSupported); |
766 } |
943 } |
767 |
944 |
768 /** We don't support incremental backup |
945 /** |
769 */ |
946 We don't support incremental backup |
770 void CSqlBackupClient::InitialiseGetBackupDataL(TDriveNumber /* aDrive */) |
947 */ |
771 { |
948 void CSqlBurCallback::InitialiseGetBackupDataL(TDriveNumber /* aDrive */) |
772 // incremental backup not supported |
949 { |
773 __SQLLEAVE(KErrNotSupported); |
950 __SQLLEAVE(KErrNotSupported); |
774 } |
951 } |
775 |
952 |
776 /** We don't support incremental backup |
953 /** |
777 */ |
954 We don't support incremental backup |
778 void CSqlBackupClient::InitialiseRestoreBaseDataL(TDriveNumber /* aDrive */) |
955 */ |
779 { |
956 void CSqlBurCallback::InitialiseRestoreBaseDataL(TDriveNumber /* aDrive */) |
780 // incremental backup not supported |
957 { |
781 __SQLLEAVE(KErrNotSupported); |
958 __SQLLEAVE(KErrNotSupported); |
782 } |
959 } |
783 |
960 |
784 /** We don't support incremental backup |
961 /** |
785 */ |
962 We don't support incremental backup |
786 void CSqlBackupClient::InitialiseRestoreIncrementDataL(TDriveNumber /* aDrive */) |
963 */ |
787 { |
964 void CSqlBurCallback::InitialiseRestoreIncrementDataL(TDriveNumber /* aDrive */) |
788 // incremental backup not supported |
965 { |
789 __SQLLEAVE(KErrNotSupported); |
966 __SQLLEAVE(KErrNotSupported); |
790 } |
967 } |
791 |
968 |
792 /** We don't support incremental backup |
969 /** |
793 */ |
970 We don't support incremental backup |
794 void CSqlBackupClient::RestoreIncrementDataSectionL(TDesC8& /* aBuffer */, TBool /* aFinishedFlag */) |
971 */ |
795 { |
972 void CSqlBurCallback::RestoreIncrementDataSectionL(TDesC8& /* aBuffer */, TBool /* aFinishedFlag */) |
796 // incremental backup not supported |
973 { |
797 __SQLLEAVE(KErrNotSupported); |
974 __SQLLEAVE(KErrNotSupported); |
798 } |
975 } |
799 |
976 |
800 /** We don't support incremental backup |
977 /** |
801 */ |
978 We don't support incremental backup |
802 void CSqlBackupClient::AllSnapshotsSuppliedL() |
979 */ |
803 { |
980 void CSqlBurCallback::AllSnapshotsSuppliedL() |
804 // incremental backup not supported |
981 { |
805 // cannot leave or panic! |
982 } |
806 } |
983 |
807 |
984 /** |
808 /** We don't support incremental backup |
985 We don't support incremental backup |
809 */ |
986 */ |
810 void CSqlBackupClient::ReceiveSnapshotDataL(TDriveNumber /* aDrive */, TDesC8& /* aBuffer */, |
987 void CSqlBurCallback::ReceiveSnapshotDataL(TDriveNumber /* aDrive */, TDesC8& /* aBuffer */, TBool /* aFinishedFlag */) |
811 TBool /* aFinishedFlag */) |
988 { |
812 { |
|
813 // incremental backup not supported |
|
814 __SQLLEAVE(KErrNotSupported); |
989 __SQLLEAVE(KErrNotSupported); |
815 } |
990 } |
816 |
991 |
817 /** |
992 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
818 Get a list of database files that need to be backed up |
993 /////////////////////////// Helper functions ////////////////////////////////////////////////////////////// |
819 This is decided by the SQL server on the basis of the UID provided |
994 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
820 and whether the metadata in the database indicates that this data |
995 |
821 should be backed up or not. The list of database files is populated |
996 /** |
822 into the iFileList array. |
997 A simple checksumming algorithm to allow a degree |
823 @leave |
998 of trust that the backup and restore worked. |
824 @param TSecureSid the UID of the data owner |
999 Note the file pointer will be back at the start when the function call completes successfully. |
825 */ |
1000 In case of an error, the position of the file pointer is undetermined. |
826 void CSqlBackupClient::GetBackupListL(TSecureId aSid) |
1001 |
827 { |
1002 @param aOpenFile Already opened database file on which the checksum is calculated. |
828 SQL_TRACE_BUR(OstTraceExt2(TRACE_INTERNALS, CSQLBACKUPCLIENT_GETBACKUPLISTL, "0x%X;CSqlBackupClient::GetBackupListL;aSid=0x%X", (TUint)this, (TUint)aSid.iId)); |
1003 @param aCheckSum Output parameter. The checksum is returned in this parameter. |
829 // we own the array - the SQL server just populates it |
1004 @return KErrNoMemory, an out of memory condition has occurred; |
830 iInterface->GetBackUpListL(aSid,iFileList); |
1005 Note that the function may also return some other system-wide error codes. |
831 } |
1006 */ |
832 |
1007 TInt CSqlBurCallback::CheckSum(const RFile64& aOpenFile, TUint64& aCheckSum) const |
833 /** A simple checksumming algorithm to allow a degree |
|
834 of trust that the backup and restore worked |
|
835 This is visble externally because the test harness |
|
836 needs to use it - NOTE the file pointer will be back at the |
|
837 start when this function ends. |
|
838 @leave |
|
839 @param RFile64 an OPEN file to checksum |
|
840 */ |
|
841 TUint64 CSqlBackupClient::CheckSumL(const RFile64& aOpenFile) const |
|
842 { |
1008 { |
843 // scoot through the database file building the checksum |
1009 // scoot through the database file building the checksum |
844 TInt64 seekPos=0; // rewind first |
1010 aCheckSum = 0; |
845 __SQLLEAVE_IF_ERROR(aOpenFile.Seek(ESeekStart,seekPos)); |
1011 TInt64 seekPos = 0; // rewind first |
846 TUint64 total=0; |
1012 TInt err = aOpenFile.Seek(ESeekStart, seekPos); |
|
1013 if(err != KErrNone) |
|
1014 { |
|
1015 return err; |
|
1016 } |
847 const TUint KCheckSumBlockSize = 4 * 1024; |
1017 const TUint KCheckSumBlockSize = 4 * 1024; |
848 HBufC8* block=HBufC8::NewLC(KCheckSumBlockSize); |
1018 HBufC8* buf = HBufC8::New(KCheckSumBlockSize); |
849 TPtr8 ptr=block->Des(); |
1019 if(!buf) |
|
1020 { |
|
1021 return KErrNoMemory; |
|
1022 } |
|
1023 TPtr8 ptr = buf->Des(); |
850 for(;;) |
1024 for(;;) |
851 { |
1025 { |
852 __SQLLEAVE_IF_ERROR(aOpenFile.Read(ptr)); |
1026 err = aOpenFile.Read(ptr); |
853 TInt len=ptr.Length(); |
1027 if(err != KErrNone) |
854 if(len==0) |
1028 { |
|
1029 delete buf; |
|
1030 return err; |
|
1031 } |
|
1032 TInt len = ptr.Length(); |
|
1033 if(len == 0) |
855 { |
1034 { |
856 break; |
1035 break; |
857 } |
1036 } |
858 // calculate the checksum |
1037 // calculate the checksum |
859 for(TInt i=0;i<len;++i) |
1038 for(TInt i=0;i<len;++i) |
860 { |
1039 { |
861 total = (total << 1) | (total >> 63); |
1040 aCheckSum = (aCheckSum << 1) | (aCheckSum >> 63); |
862 total += ptr[i]; |
1041 aCheckSum += ptr[i]; |
863 } |
1042 } |
864 }; |
1043 }; |
865 CleanupStack::PopAndDestroy(block); |
1044 delete buf; |
866 // restore file position |
1045 // restore file position |
867 seekPos=0; |
1046 seekPos = 0; |
868 __SQLLEAVE_IF_ERROR(aOpenFile.Seek(ESeekStart,seekPos)); |
1047 err = aOpenFile.Seek(ESeekStart,seekPos); |
869 return total; |
1048 return err; |
870 } |
1049 } |
871 |
1050 |
872 //Reads the content of aInBuf from position aInBufReadPos and stores the data into aOutBuf. |
1051 /** |
873 //aDataLen is the length of the data. If the input buffer does not contain all the data, then only the |
1052 Reads the content of aInBuf from position aInBufReadPos and stores the data into aOutBuf. |
874 //available data will be copied to the output buffer. |
1053 aDataLen is the length of the data. If the input buffer does not contain all the data, then only the |
875 // |
1054 available data will be copied to the output buffer. |
876 //Attention!!! This function won't work properly if aInBuf parameter contains odd number of bytes!!! |
1055 |
877 //(a legacy problem, if it is a problem at all, because the B&R engine probably sends the data in chunks with even size) |
1056 How the function works. It is called during the restore process and aInBuf parameter contains a block of raw |
878 // |
1057 data sent by the B&R server. The calling function, RestoreBaseDataSectionL(), uses a state |
879 //How the function works. It is called during the restore process and aInBuf parameter contains a block of raw |
1058 machine to processes the incoming data. At particular moment RestoreBaseDataSectionL() will process the data header |
880 //data sent by the B&R server. The calling function, RestoreBaseDataSectionL(), uses a state |
1059 and will have to read "aDataLen" 16-bit characters at position "aInBufReadPos". If there are "aDataLen" characters |
881 //machine to processes the incoming data. At particular moment RestoreBaseDataSectionL() will process the data header |
1060 at position "aInBufReadPos" and enough free space in "aOutBuf", CopyBufData() will copy all of them, |
882 //and will have to read "aDataLen" 16-bit characters at position "aInBufReadPos". If there are "aDataLen" characters |
1061 otherwise CopyBufData() will copy as much characters as possible (in which case RestoreBaseDataSectionL() will |
883 //at position "aInBufReadPos" and enough free space in "aOutBuf", CopyBufData() will copy all of them, |
1062 stay in the same state, waiting for more data from the B&R server). |
884 //otherwise CopyBufData() will copy as much characters as possible (in which case RestoreBaseDataSectionL() will |
1063 |
885 //stay in the same state, waiting for more data from the B&R server). |
1064 @param aInBuf 8-bit buffer with input data |
886 // |
1065 @param aInBufReadPos The position in the buffer from which the read operation starts. |
887 void CSqlBackupClient::CopyBufData(const TDesC8& aInBuf, TInt& aInBufReadPos, TDes& aOutBuf, TInt aDataLen) |
1066 When the "buffer read" operatio completes, aInBufReadPos is updated with the |
|
1067 number of bytes read from the input buffer. |
|
1068 @param aOutBuf 16-bit output buffer. The data read from the input buffer is stored in the output buffer. |
|
1069 @param aDataLen How much bytes to be read from the input buffer. Note that if there is not enough |
|
1070 data in the input buffer, the function will read as much as possible from the input buffer. |
|
1071 The aInBufReadPos in/out parameter will be updated with the actual number of bytes read. |
|
1072 */ |
|
1073 void CSqlBurCallback::CopyBufData(const TDesC8& aInBuf, TInt& aInBufReadPos, TDes& aOutBuf, TInt aDataLen) |
888 { |
1074 { |
889 __ASSERT_DEBUG(aInBufReadPos >= 0, __SQLPANIC(ESqlPanicBadArgument)); |
1075 __ASSERT_DEBUG(aInBufReadPos >= 0, __SQLPANIC(ESqlPanicBadArgument)); |
890 __ASSERT_DEBUG(aDataLen > 0, __SQLPANIC(ESqlPanicBadArgument)); |
1076 __ASSERT_DEBUG(aDataLen > 0, __SQLPANIC(ESqlPanicBadArgument)); |
891 __ASSERT_DEBUG(!(aInBuf.Length() & 0x01), __SQLPANIC(ESqlPanicInternalError)); |
|
892 |
1077 |
893 TInt needed = (aDataLen - aOutBuf.Length()) << K8to16bitShift; |
1078 TInt needed = (aDataLen - aOutBuf.Length()) << K8to16bitShift; |
894 TInt available = aInBuf.Size() - aInBufReadPos; |
1079 TInt available = aInBuf.Size() - aInBufReadPos; |
895 TInt len = Min(needed, available); |
1080 TInt len = Min(needed, available); |
896 TPtrC8 ptr8 = aInBuf.Mid(aInBufReadPos, len); |
1081 TPtrC8 ptr8 = aInBuf.Mid(aInBufReadPos, len); |
897 aInBufReadPos += len; |
1082 aInBufReadPos += len; |
898 |
1083 |
899 len >>= K8to16bitShift; |
1084 len >>= K8to16bitShift; |
900 aOutBuf.Append((const TUint16*)ptr8.Ptr(), len); |
1085 aOutBuf.Append((const TUint16*)ptr8.Ptr(), len); |
901 } |
1086 } |
|
1087 |
|
1088 /** |
|
1089 Cleans up the allocated during the backup resources - file handles, buffers allocated for the file names. |
|
1090 */ |
|
1091 void CSqlBurCallback::BackupCleanup() |
|
1092 { |
|
1093 for(TInt i=0;i<iFileList.Count();++i) |
|
1094 { |
|
1095 delete iFileList[i]; |
|
1096 } |
|
1097 iFileList.Close(); |
|
1098 iFile.Close(); |
|
1099 } |
|
1100 |
|
1101 /** |
|
1102 Deletes created during the restore temporary files. |
|
1103 */ |
|
1104 TInt CSqlBurCallback::RestoreCleanup() |
|
1105 { |
|
1106 if(iRestoreDir.Find(KSqlBurRestoreDir) < 0) |
|
1107 {//iRestoreDir is not initialized - that means RestoreCleanup() was called either from the |
|
1108 //destructor or from the TerminateMultistageOperation() during a backup. |
|
1109 return KErrNone; |
|
1110 } |
|
1111 iFile.Close(); |
|
1112 CFileMan* fm = NULL; |
|
1113 TRAPD(err, fm = CFileMan::NewL(iInterface.Fs())); |
|
1114 if(err == KErrNone) |
|
1115 { |
|
1116 TFileName allFiles; |
|
1117 allFiles.Copy(iRestoreDir); |
|
1118 allFiles.Append(KSqlBurAllFiles); |
|
1119 err = fm->Delete(allFiles); |
|
1120 delete fm; |
|
1121 } |
|
1122 return err; |
|
1123 } |
|
1124 |
|
1125 /** |
|
1126 Stores the error occured during backup for furhter processing. |
|
1127 Please note that the function asserts if the aError parameter is KErrNone. |
|
1128 Call the function only with a real error. |
|
1129 |
|
1130 @param aError The backup error to be stored |
|
1131 */ |
|
1132 void CSqlBurCallback::SetBackupError(TInt aError) |
|
1133 { |
|
1134 __ASSERT_DEBUG(aError != KErrNone, __SQLPANIC(ESqlPanicBadArgument)); |
|
1135 if(aError != KErrNotFound && aError != KErrPathNotFound) |
|
1136 { |
|
1137 if(iBackupError == KErrNone || aError == KErrDiskFull || aError == KErrCorrupt) |
|
1138 { |
|
1139 iBackupError = aError; |
|
1140 } |
|
1141 } |
|
1142 } |