|
1 // Copyright (c) 2002-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 #include "logservsession.h" |
|
17 #include "LogNotify.h" |
|
18 #include "LogServServer.h" |
|
19 #include "logservpanic.h" |
|
20 #include "LogServView.h" |
|
21 #include "LogServOperationBase.h" |
|
22 #include "LogServBackupInterface.h" |
|
23 #include "LogServOperationFactory.h" |
|
24 #include "LogServOperationManager.h" |
|
25 #include "LogServDatabaseChangeInterface.h" |
|
26 #include "LogServDatabaseChangeDefinition.h" |
|
27 #include "LogServSqlStrings.h" |
|
28 |
|
29 // Constants |
|
30 const TInt KLogViewListGranuality = 5; |
|
31 const TInt KLogServPendingGlobalChangesArrayGranularity = 3; |
|
32 |
|
33 |
|
34 ///////////////////////////////////////////////////////////////////////////////////////// |
|
35 // -----> CLogServSession (source) |
|
36 ///////////////////////////////////////////////////////////////////////////////////////// |
|
37 |
|
38 CLogServSession::CLogServSession(TLogServSessionId aSessionId, |
|
39 MLogServSessionLifetimeObserver& aObserver, |
|
40 MLogServBackupInterface& aBackupInterface, |
|
41 MLogServTaskInterface& aTaskInterface, |
|
42 MLogServOperationManager& aOperationManager, |
|
43 MLogServDatabaseChangeInterface& aChangeInterface, |
|
44 MLogServDatabaseTransactionInterface& aDatabase) : |
|
45 iSessionId(aSessionId), |
|
46 iObserver(aObserver), |
|
47 iBackupInterface(aBackupInterface), |
|
48 iTaskInterface(aTaskInterface), |
|
49 iOperationManager(aOperationManager), |
|
50 iChangeInterface(aChangeInterface), |
|
51 iDatabase(aDatabase), |
|
52 iViewList(KLogViewListGranuality), |
|
53 iPendingGlobalChanges(KLogServPendingGlobalChangesArrayGranularity) |
|
54 { |
|
55 iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventCreated); |
|
56 } |
|
57 |
|
58 CLogServSession::~CLogServSession() |
|
59 { |
|
60 LOGTEXT3("CLogServSession::~CLogServSession() - client logging off: %S, %d", &iClientThreadName, iSessionId); |
|
61 |
|
62 iOperationManager.OMCancel(iSessionId, ETrue); |
|
63 |
|
64 delete iPackage; |
|
65 delete iNotify; |
|
66 |
|
67 iChangeInterface.DCIRequestChangeNotificationsCancel(*this); |
|
68 // |
|
69 iViewList.ResetAndDestroy(); |
|
70 iViewList.Close(); |
|
71 iPendingGlobalChanges.Close(); |
|
72 // |
|
73 iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventDestroyed); |
|
74 |
|
75 LOGTEXT2("CLogServSession::~CLogServSession() - client dead %d", iSessionId); |
|
76 LOGTEXT(""); |
|
77 } |
|
78 |
|
79 ///////////////////////////////////////////////////////////////////////////////////////// |
|
80 ///////////////////////////////////////////////////////////////////////////////////////// |
|
81 ///////////////////////////////////////////////////////////////////////////////////////// |
|
82 |
|
83 void CLogServSession::DCOHandleGlobalChangeEventL(const TLogServDatabaseChangeDefinition& aChange) |
|
84 { |
|
85 if (iExtendedNotificationRequested) |
|
86 User::LeaveIfError(iPendingGlobalChanges.Append(aChange)); |
|
87 ExtendedNotifyCompleteL(KErrNone); |
|
88 } |
|
89 |
|
90 ///////////////////////////////////////////////////////////////////////////////////////// |
|
91 ///////////////////////////////////////////////////////////////////////////////////////// |
|
92 ///////////////////////////////////////////////////////////////////////////////////////// |
|
93 void CLogServSession::CreateL() |
|
94 { |
|
95 iPackage = CLogPackage::NewL(); |
|
96 |
|
97 // Request change notifications |
|
98 iChangeInterface.DCIRequestChangeNotificationsL(*this); |
|
99 } |
|
100 |
|
101 // |
|
102 // Handle a client request. |
|
103 // |
|
104 // Leaving is handled by CLogServ::RunError() which reports the error code to the client |
|
105 // Note: operation add themselves to the server active queue in their constructor |
|
106 // The server active object owns them and deletes them when necessary |
|
107 // So the iffy looking code below won't actually leak memory |
|
108 // |
|
109 void CLogServSession::ServiceL(const RMessage2& aMessage) |
|
110 { |
|
111 LOGTEXT3("CLogServSession::ServiceL(%S, %d)", &iClientThreadName, aMessage.Function()); |
|
112 |
|
113 switch(aMessage.Function()) |
|
114 { |
|
115 /** |
|
116 * Overall operation management |
|
117 */ |
|
118 case ELogOperationGetResult: |
|
119 case ELogOperationCancel: |
|
120 case ELogOperationInitiate: |
|
121 ServiceOperationFunctionL(aMessage); |
|
122 break; |
|
123 |
|
124 /** |
|
125 * Notification related |
|
126 */ |
|
127 case ELogNotify: |
|
128 { |
|
129 if (!iNotify) |
|
130 { |
|
131 iNotify = CLogNotify::NewL(iBackupInterface, iChangeInterface, Server().Priority()); |
|
132 |
|
133 #ifdef LOGGING_ENABLED |
|
134 iNotify->SetClientThreadName(iClientThreadName); |
|
135 #endif |
|
136 } |
|
137 |
|
138 if (!iNotify->IsActive()) |
|
139 { |
|
140 const TTimeIntervalMicroSeconds32 delayTime = reinterpret_cast<TInt>(aMessage.Ptr0()); |
|
141 |
|
142 //Validate time value |
|
143 if(delayTime.Int() < 0) |
|
144 { |
|
145 User::Leave(KErrArgument); |
|
146 } |
|
147 iNotify->Notify(delayTime, aMessage); |
|
148 } |
|
149 else |
|
150 ::PanicClientL(aMessage, ELogAlreadyActive19); |
|
151 break; |
|
152 } |
|
153 case ELogNotifyCancel: |
|
154 { |
|
155 if (iNotify) |
|
156 iNotify->Cancel(); |
|
157 aMessage.Complete(KErrCancel); |
|
158 break; |
|
159 } |
|
160 case ELogNotifyExtended: |
|
161 { |
|
162 if (iExtendedNotificationMessage == RMessage2()) |
|
163 { |
|
164 iExtendedNotificationMessage = aMessage; |
|
165 iExtendedNotificationRequested = ETrue; |
|
166 } |
|
167 else |
|
168 ::PanicClientL(aMessage, ELogExtendedMessageAlreadyActive); |
|
169 break; |
|
170 } |
|
171 case ELogNotifyExtendedCancel: |
|
172 { |
|
173 if (iExtendedNotificationMessage != RMessage2()) |
|
174 ExtendedNotifyCompleteL(KErrCancel); |
|
175 // |
|
176 iExtendedNotificationRequested = EFalse; |
|
177 iPendingGlobalChanges.Reset(); |
|
178 iPendingGlobalChanges.GranularCompress(); |
|
179 // |
|
180 aMessage.Complete(KErrCancel); |
|
181 break; |
|
182 } |
|
183 |
|
184 /** |
|
185 * View functionality |
|
186 */ |
|
187 case ELogViewCreate: |
|
188 case ELogViewDelete: |
|
189 case ELogViewCount: |
|
190 case ELogViewOperationInitiate: |
|
191 case ELogViewChangeNotificationsRequest: |
|
192 case ELogViewChangeNotificationsCancel: |
|
193 case ELogViewFetchChanges: |
|
194 case ELogViewNotifyLockStatusChange: |
|
195 case ELogViewNotifyLockStatusChangeCancel: |
|
196 ServiceViewFunctionL(aMessage); |
|
197 break; |
|
198 |
|
199 /** |
|
200 * Misc. (debug) functionality |
|
201 */ |
|
202 #ifdef _DEBUG |
|
203 case ELogMakeTransient: |
|
204 { |
|
205 Server().MakeTransient((TBool)aMessage.Ptr0()); |
|
206 aMessage.Complete(KErrNone); |
|
207 break; |
|
208 } |
|
209 case ELogIsServerReady: |
|
210 { |
|
211 const TBool serverReady = (iBackupInterface.BIErrorValueForCurrentState() == KErrNone); |
|
212 aMessage.Complete(serverReady); |
|
213 break; |
|
214 } |
|
215 case ELogSetHeapFail: |
|
216 { |
|
217 User::__DbgSetAllocFail(RHeap::EUser, RHeap::TAllocFail(aMessage.Int0()),aMessage.Int1()); |
|
218 aMessage.Complete(KErrNone); |
|
219 break; |
|
220 } |
|
221 #endif// _DEBUG |
|
222 /** |
|
223 * Unknown operations |
|
224 */ |
|
225 default: |
|
226 ::PanicClientL(aMessage, ELogIllegalFunction); |
|
227 break; |
|
228 } |
|
229 } |
|
230 |
|
231 /** |
|
232 If aError is KErrBadDescriptor, then panic the client, else - default error handling. |
|
233 KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad |
|
234 descriptor to the server. |
|
235 */ |
|
236 void CLogServSession::ServiceError(const RMessage2& aMessage,TInt aError) |
|
237 { |
|
238 if(aError == KErrBadDescriptor) |
|
239 { |
|
240 //The __LOGPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call |
|
241 //from a leaving call will terminate the server. |
|
242 aMessage.Panic(KLogServ, ELogBadDescriptor); |
|
243 } |
|
244 CSession2::ServiceError(aMessage, aError); |
|
245 } |
|
246 |
|
247 ///////////////////////////////////////////////////////////////////////////////////////// |
|
248 ///////////////////////////////////////////////////////////////////////////////////////// |
|
249 ///////////////////////////////////////////////////////////////////////////////////////// |
|
250 |
|
251 CLogServServer& CLogServSession::Server() const |
|
252 { |
|
253 return *static_cast<CLogServServer*>(const_cast<CServer2*>(CSession2::Server())); |
|
254 } |
|
255 |
|
256 ///////////////////////////////////////////////////////////////////////////////////////// |
|
257 ///////////////////////////////////////////////////////////////////////////////////////// |
|
258 ///////////////////////////////////////////////////////////////////////////////////////// |
|
259 |
|
260 |
|
261 CLogServViewBase& CLogServSession::ViewByIdL(TUint32 aViewId) |
|
262 { |
|
263 const TInt index = ViewPositionById(aViewId); |
|
264 User::LeaveIfError(index); |
|
265 return *iViewList[index]; |
|
266 } |
|
267 |
|
268 TInt CLogServSession::ViewPositionById(TUint32 aViewId) const |
|
269 { |
|
270 const TInt count = iViewList.Count(); |
|
271 for(TInt i=0; i<count; i++) |
|
272 { |
|
273 const CLogServViewBase& view = *iViewList[i]; |
|
274 if (view.ViewId() == aViewId) |
|
275 return i; |
|
276 } |
|
277 return KErrNotFound; |
|
278 } |
|
279 |
|
280 |
|
281 void CLogServSession::ReadClientServerDataL(TLogClientServerData& aClientServerData, |
|
282 const RMessage2 &aMessage, TInt aMinOperation, TInt aMaxOperation) |
|
283 { |
|
284 |
|
285 TInt length = aMessage.GetDesLengthL(0); |
|
286 if(length != sizeof(TLogClientServerData)) |
|
287 { |
|
288 User::Leave(KErrBadDescriptor); |
|
289 } |
|
290 |
|
291 TPckg<TLogClientServerData> pData(aClientServerData); |
|
292 aMessage.ReadL(0, pData); |
|
293 |
|
294 //Validate Operation Type |
|
295 if((aClientServerData.iOperationType < aMinOperation) || |
|
296 (aClientServerData.iOperationType > aMaxOperation)) |
|
297 { |
|
298 User::Leave(KErrArgument); |
|
299 } |
|
300 } |
|
301 |
|
302 void CLogServSession::ServiceViewFunctionL(const RMessage2& aMessage) |
|
303 { |
|
304 switch(aMessage.Function()) |
|
305 { |
|
306 case ELogViewCreate: |
|
307 { |
|
308 iViewList.ReserveL(iViewList.Count() + 1); |
|
309 // Type is first parameter, view id is second |
|
310 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
311 const TLogViewType type = static_cast<TLogViewType>(aMessage.Int1()); |
|
312 |
|
313 //Validate type value |
|
314 if((type < ELogViewTypeEvent)||(type > ELogViewTypeDuplicate)) |
|
315 { |
|
316 User::Leave(KErrArgument); |
|
317 } |
|
318 |
|
319 // Ask the factory to create it |
|
320 CLogServViewBase* view = LogServFactory::NewViewL(type, id, iDatabase, iBackupInterface, *iPackage, aMessage); |
|
321 TInt err = iViewList.Append(view); |
|
322 __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved)); |
|
323 aMessage.Complete(err); |
|
324 break; |
|
325 } |
|
326 case ELogViewDelete: |
|
327 { |
|
328 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
329 TInt indexAndError = ViewPositionById(id); |
|
330 if (indexAndError >= 0) |
|
331 { |
|
332 delete iViewList[indexAndError]; |
|
333 iViewList.Remove(indexAndError); |
|
334 indexAndError = KErrNone; |
|
335 } |
|
336 aMessage.Complete(indexAndError); |
|
337 break; |
|
338 } |
|
339 case ELogViewCount: |
|
340 { |
|
341 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
342 CLogServViewBase& view = ViewByIdL(id); |
|
343 const TInt count = view.Count(); |
|
344 aMessage.Complete(count); |
|
345 break; |
|
346 } |
|
347 case ELogViewOperationInitiate: |
|
348 { |
|
349 // We don't allow any operations during a backup |
|
350 iBackupInterface.BIValidateStateForDatabaseOperationL(); |
|
351 // |
|
352 TLogClientServerData clientServerData; |
|
353 ReadClientServerDataL(clientServerData,aMessage, |
|
354 ELogOperationViewSetup, ELogOperationViewWindowFetch); |
|
355 |
|
356 // |
|
357 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int1()); |
|
358 CLogServViewBase& view = ViewByIdL(id); |
|
359 |
|
360 // Create operation. Operations are owned by the operation manager (they are added to a queue) |
|
361 // when the objects are created, so this does not leak any memory. |
|
362 CLogServOperationBase* operation = LogServFactory::NewViewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId, view); |
|
363 (void) operation; |
|
364 break; |
|
365 } |
|
366 case ELogViewChangeNotificationsRequest: |
|
367 { |
|
368 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
369 CLogServViewBase& view = ViewByIdL(id); |
|
370 view.RequestChangeNotifications(aMessage); |
|
371 break; |
|
372 } |
|
373 case ELogViewChangeNotificationsCancel: |
|
374 { |
|
375 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
376 CLogServViewBase& view = ViewByIdL(id); |
|
377 view.RequestChangeNotificationsCancel(); |
|
378 aMessage.Complete(KErrNone); |
|
379 break; |
|
380 } |
|
381 case ELogViewFetchChanges: |
|
382 { |
|
383 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
384 CLogServViewBase& view = ViewByIdL(id); |
|
385 view.RequestChangesL(aMessage); |
|
386 aMessage.Complete(KErrNone); |
|
387 break; |
|
388 } |
|
389 case ELogViewNotifyLockStatusChange: |
|
390 { |
|
391 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
392 CLogServViewBase& view = ViewByIdL(id); |
|
393 view.RequestLockStatusChanges(aMessage); |
|
394 break; |
|
395 } |
|
396 case ELogViewNotifyLockStatusChangeCancel: |
|
397 { |
|
398 const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0()); |
|
399 CLogServViewBase& view = ViewByIdL(id); |
|
400 view.RequestLockStatusChangesCancel(); |
|
401 aMessage.Complete(KErrNone); |
|
402 break; |
|
403 } |
|
404 } |
|
405 } |
|
406 |
|
407 void CLogServSession::ServiceOperationFunctionL(const RMessage2& aMessage) |
|
408 { |
|
409 // We don't allow any operations during a backup |
|
410 iBackupInterface.BIValidateStateForDatabaseOperationL(); |
|
411 // |
|
412 TLogClientServerData clientServerData; |
|
413 ReadClientServerDataL(clientServerData,aMessage, ELogOperationEventAdd,ELogOperationMaintain); |
|
414 // |
|
415 const TInt function = aMessage.Function(); |
|
416 // |
|
417 const TLogOperationId& operationId = clientServerData.iOperationId; |
|
418 #ifdef LOGGING_ENABLED |
|
419 const TLogOperationType& operationType = clientServerData.iOperationType; |
|
420 #endif |
|
421 LOGTEXT4("CLogServSession::ServiceOperationFunctionL() - Operation function for client %S: Id: %d, Type: %d", &iClientThreadName, operationId, operationType); |
|
422 // |
|
423 switch(function) |
|
424 { |
|
425 case ELogOperationGetResult: |
|
426 LOGTEXT("CLogServSession::ServiceOperationFunctionL() - getting result"); |
|
427 iOperationManager.OMGetResultL(operationId, iSessionId, aMessage); |
|
428 aMessage.Complete(KErrNone); |
|
429 break; |
|
430 case ELogOperationCancel: |
|
431 LOGTEXT("CLogServSession::ServiceOperationFunctionL() - cancelling"); |
|
432 iOperationManager.OMCancel(operationId, iSessionId, ETrue); |
|
433 aMessage.Complete(KErrCancel); |
|
434 break; |
|
435 case ELogOperationInitiate: |
|
436 LOGTEXT("CLogServSession::ServiceOperationFunctionL() - initiating"); |
|
437 // Create operation. Operations are owned by the operation manager (they are added to a queue) |
|
438 // when the objects are created, so this does not leak any memory. |
|
439 CLogServOperationBase* operation = LogServFactory::NewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId); |
|
440 (void) operation; |
|
441 break; |
|
442 } |
|
443 LOGTEXT("CLogServSession::ServiceOperationFunctionL() - end"); |
|
444 } |
|
445 |
|
446 void CLogServSession::ExtendedNotifyCompleteL(TInt aCompletionCode) |
|
447 { |
|
448 const TInt count = iPendingGlobalChanges.Count(); |
|
449 if (iExtendedNotificationMessage != RMessage2() && (count || aCompletionCode < KErrNone)) |
|
450 { |
|
451 if (aCompletionCode >= KErrNone && count) |
|
452 { |
|
453 const TLogServDatabaseChangeDefinition& change = iPendingGlobalChanges[0]; |
|
454 // |
|
455 const TPckgBuf<TInt> pContext(change.iChangeType.iUid); |
|
456 const TPckg<TInt> pParam1(change.iChangeParam1); |
|
457 const TPckg<TInt> pParam2(change.iChangeParam2); |
|
458 const TPckg<TInt> pParam3(change.iChangeParam3); |
|
459 // |
|
460 iExtendedNotificationMessage.WriteL(0, pContext); |
|
461 iExtendedNotificationMessage.WriteL(1, pParam1); |
|
462 iExtendedNotificationMessage.WriteL(2, pParam2); |
|
463 iExtendedNotificationMessage.WriteL(3, pParam3); |
|
464 // |
|
465 iPendingGlobalChanges.Remove(0); |
|
466 } |
|
467 // |
|
468 iExtendedNotificationMessage.Complete(aCompletionCode); |
|
469 } |
|
470 } |