|
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 "LogServOperationQueue.h" |
|
17 |
|
18 // User includes |
|
19 #include "logservpanic.h" |
|
20 #include "LogServOperationBase.h" |
|
21 #include "LogServTaskInterface.h" |
|
22 |
|
23 |
|
24 ///////////////////////////////////////////////////////////////////////////////////////// |
|
25 // -----> CLogServOperationQueue (source) |
|
26 ///////////////////////////////////////////////////////////////////////////////////////// |
|
27 |
|
28 CLogServOperationQueue::CLogServOperationQueue(MLogServTaskInterface& aTaskInterface, TInt aPriority) |
|
29 : CActive(aPriority), |
|
30 iTaskInterface(aTaskInterface), |
|
31 iQueuePending(CLogServOperationBase::QueueOffset()), |
|
32 iQueueCompleted(CLogServOperationBase::QueueOffset()) |
|
33 { |
|
34 CActiveScheduler::Add(this); |
|
35 } |
|
36 |
|
37 CLogServOperationQueue::~CLogServOperationQueue() |
|
38 { |
|
39 Cancel(); |
|
40 // |
|
41 CLogServOperationBase* item = NULL; |
|
42 // |
|
43 TSglQueIter<CLogServOperationBase> pendingIterator(iQueuePending); |
|
44 while ((item = pendingIterator++) != NULL) |
|
45 { |
|
46 delete item; |
|
47 } |
|
48 // |
|
49 TSglQueIter<CLogServOperationBase> completedIterator(iQueueCompleted); |
|
50 while ((item = completedIterator++) != NULL) |
|
51 { |
|
52 delete item; |
|
53 } |
|
54 } |
|
55 |
|
56 CLogServOperationQueue* CLogServOperationQueue::NewL(MLogServTaskInterface& aTaskInterface, TInt aPriority) |
|
57 { |
|
58 CLogServOperationQueue* self = new(ELeave) CLogServOperationQueue(aTaskInterface, aPriority); |
|
59 return self; |
|
60 } |
|
61 |
|
62 ///////////////////////////////////////////////////////////////////////////////////////// |
|
63 ///////////////////////////////////////////////////////////////////////////////////////// |
|
64 ///////////////////////////////////////////////////////////////////////////////////////// |
|
65 |
|
66 void CLogServOperationQueue::OMOperationQueueAdd(CLogServOperationBase& aOp) |
|
67 // |
|
68 // Add a new event to the queue and restart processing if necessary |
|
69 // |
|
70 { |
|
71 LOGTEXT3("CLogServOperationQueue::OMOperationQueueAdd() - Type: %d, Id: %d", aOp.Type(), aOp.Id()); |
|
72 // |
|
73 iQueuePending.AddLast(aOp); |
|
74 if (!IsActive()) |
|
75 CompleteRequest(); |
|
76 // |
|
77 LOGTEXT("CLogServOperationQueue::OMOperationQueueAdd() - end"); |
|
78 } |
|
79 |
|
80 // |
|
81 // Removes an operation from the relevant server queue |
|
82 // |
|
83 void CLogServOperationQueue::OMOperationQueueRemove(CLogServOperationBase& aOperation) |
|
84 { |
|
85 const TLogOperationId operationId = aOperation.Id(); |
|
86 const TLogServSessionId sessionId = aOperation.SessionId(); |
|
87 // |
|
88 LOGTEXT3("CLogServOperationQueue::OMOperationQueueRemove() - Id: %d, SessionId: %d", operationId, sessionId); |
|
89 // |
|
90 if(QueueContainsOperation(iQueuePending, operationId, sessionId)) |
|
91 { |
|
92 iQueuePending.Remove(aOperation); |
|
93 } |
|
94 else |
|
95 { |
|
96 iQueueCompleted.Remove(aOperation); |
|
97 } |
|
98 // |
|
99 LOGTEXT("CLogServOperationQueue::OMOperationQueueRemove() - end"); |
|
100 } |
|
101 |
|
102 void CLogServOperationQueue::OMGetResultL(TLogOperationId aId, TLogServSessionId aSessionId, const RMessage2& aMessageToWriteTo) |
|
103 // |
|
104 // Get the result of a specific operation |
|
105 // |
|
106 { |
|
107 LOGTEXT3("CLogServOperationQueue::OMGetResultL() - Id: %d, SessionId: %d", aId, aSessionId); |
|
108 |
|
109 // Look for the op |
|
110 CLogServOperationBase* op = FindOperation(iQueueCompleted, aId, aSessionId); |
|
111 |
|
112 // If we found it, then return the result |
|
113 if (op != NULL) |
|
114 { |
|
115 op->WriteL(aMessageToWriteTo); |
|
116 delete op; |
|
117 } |
|
118 // |
|
119 LOGTEXT("CLogServOperationQueue::OMGetResultL() - end"); |
|
120 } |
|
121 |
|
122 void CLogServOperationQueue::OMCancel(TLogOperationId aOpId, TLogServSessionId aSessionId, TBool aCompleteRequest) |
|
123 // |
|
124 // Cancel a specific operation |
|
125 // |
|
126 { |
|
127 LOGTEXT4("CLogServOperationQueue::OMCancel() - Id: %d, SessionId: %d, CompleteRequest: %d", aOpId, aSessionId, aCompleteRequest); |
|
128 |
|
129 if (iCurrentOperation && iCurrentOperation->SessionId() == aSessionId && (aOpId == KLogNullOperationId || iCurrentOperation->Id() == aOpId)) |
|
130 { |
|
131 // We need to cancel the current active operation because it belongs to this session |
|
132 // |
|
133 // This should complete the request with KErrCancel causing RunL to leave |
|
134 // RunError completes the request and removes the operation from the pending queue |
|
135 iTaskInterface.TaskCancelCurrent(); |
|
136 // |
|
137 if (!aCompleteRequest) |
|
138 iCurrentOperation->ClearMessagePointer(); |
|
139 } |
|
140 else |
|
141 { |
|
142 // The active operation doesn't belong to this session - just remove any relevant operations from the queues |
|
143 // |
|
144 // We are taking advantage of the fact that a session will only ever have one operation outstanding |
|
145 // so a cancel request basically means - cancel everything belonging to the session |
|
146 CLogServOperationBase* op = NULL; |
|
147 while((op = FindOperation(iQueuePending, aOpId, aSessionId)) != NULL) |
|
148 { |
|
149 if (aCompleteRequest) |
|
150 { |
|
151 op->Cancel(); |
|
152 } |
|
153 |
|
154 // The operation dequeues itself from the containing queue in its destructor via |
|
155 // the MLogServOperationManager abstract interface. |
|
156 delete op; |
|
157 |
|
158 // We can exit now if we were looking for a particular operation |
|
159 if (aOpId > KLogNullOperationId) |
|
160 { |
|
161 return; |
|
162 } |
|
163 } |
|
164 |
|
165 // Just delete the completed operation |
|
166 DeleteFromQueue(iQueueCompleted, aOpId, aSessionId); |
|
167 } |
|
168 // |
|
169 LOGTEXT("CLogServOperationQueue::OMCancel() - end"); |
|
170 } |
|
171 |
|
172 // |
|
173 // Stop/cancel and delete all operations belonging to a particular session |
|
174 // If the session has just died we don't want to complete the request - the kernel would panic us |
|
175 // |
|
176 void CLogServOperationQueue::OMCancel(TLogServSessionId aSessionId, TBool aCompleteRequest) |
|
177 { |
|
178 OMCancel(KLogNullOperationId, aSessionId, aCompleteRequest); |
|
179 } |
|
180 |
|
181 ///////////////////////////////////////////////////////////////////////////////////////// |
|
182 ///////////////////////////////////////////////////////////////////////////////////////// |
|
183 ///////////////////////////////////////////////////////////////////////////////////////// |
|
184 |
|
185 void CLogServOperationQueue::RunL() |
|
186 // |
|
187 // Called to indicate that the operation has completed - so complete the client request |
|
188 // |
|
189 { |
|
190 LOGTEXT2("CLogServOperationQueue::RunL(%d)", iStatus.Int()); |
|
191 |
|
192 // If the queue has just been restarted there won't be an existing operation |
|
193 if (iCurrentOperation) |
|
194 { |
|
195 LOGTEXT3("CLogServOperationQueue::RunL() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id()); |
|
196 |
|
197 // Handle errors in RunError |
|
198 User::LeaveIfError(iStatus.Int()); |
|
199 |
|
200 // Remember the type of operation for later |
|
201 const TLogOperationType type = iCurrentOperation->Type(); |
|
202 |
|
203 // Complete the operation |
|
204 if (iCurrentOperation->CompleteProcessingL(iStatus.Int()) == CLogServOperationBase::EOperationComplete) |
|
205 { |
|
206 LOGTEXT("CLogServOperationQueue::RunL() - Operation is complete, deleting it"); |
|
207 delete iCurrentOperation; |
|
208 iCurrentOperation = NULL; |
|
209 } |
|
210 else |
|
211 { |
|
212 // The client is going to ask for some results. |
|
213 // |
|
214 // Move the operation to another queue until it's done |
|
215 // The session will actually delete the operation |
|
216 LOGTEXT("CLogServOperationQueue::RunL() - Operation result awaiting client fetch"); |
|
217 iQueuePending.Remove(*iCurrentOperation); |
|
218 iQueueCompleted.AddLast(*iCurrentOperation); |
|
219 } |
|
220 |
|
221 // Any errors from maintenance will be ignored because the operation is null |
|
222 iCurrentOperation = NULL; |
|
223 |
|
224 LOGTEXT("CLogServOperationQueue::RunL() - Starting maintenance"); |
|
225 iTaskInterface.TaskMaintenanceStartL(iStatus, type != ELogOperationEventGet); |
|
226 SetActive(); |
|
227 } |
|
228 else |
|
229 { |
|
230 LOGTEXT("CLogServOperationQueue::RunL() - finding next operation"); |
|
231 |
|
232 // Start the next operation |
|
233 StartNextOpL(); |
|
234 } |
|
235 |
|
236 LOGTEXT("CLogServOperationQueue::RunL() - end"); |
|
237 } |
|
238 |
|
239 void CLogServOperationQueue::DoCancel() |
|
240 // |
|
241 // Implements cancel policy. Only called if the maintenance is active? |
|
242 // |
|
243 { |
|
244 iTaskInterface.TaskCancelCurrent(); |
|
245 } |
|
246 |
|
247 TInt CLogServOperationQueue::RunError(TInt aError) |
|
248 // |
|
249 // Handle errors |
|
250 // |
|
251 { |
|
252 LOGTEXT2("CLogServOperationQueue::RunError(%d)", aError); |
|
253 |
|
254 if (iCurrentOperation) |
|
255 { |
|
256 LOGTEXT3("CLogServOperationQueue::RunError() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id()); |
|
257 |
|
258 // Fail the client request with the error |
|
259 if (iCurrentOperation->HaveMessagePointer()) |
|
260 iCurrentOperation->Complete(aError); |
|
261 delete iCurrentOperation; |
|
262 iCurrentOperation = NULL; |
|
263 } |
|
264 |
|
265 // Restart by mending the database if necessary |
|
266 TRAPD(mendError, iTaskInterface.TaskMaintenanceStartL(iStatus, ETrue)); |
|
267 if (mendError) |
|
268 { |
|
269 LOGTEXT2("CLogServOperationQueue::RunError() - mend error: %d)", mendError); |
|
270 |
|
271 // Just ignore the maintenance error and complete ourselves so we continue to execute operations |
|
272 CompleteRequest(KErrNone); |
|
273 } |
|
274 else |
|
275 { |
|
276 LOGTEXT("CLogServOperationQueue::RunError() - setting active again"); |
|
277 SetActive(); |
|
278 } |
|
279 |
|
280 LOGTEXT("CLogServOperationQueue::RunError() - end"); |
|
281 return KErrNone; |
|
282 } |
|
283 |
|
284 void CLogServOperationQueue::CompleteRequest(TInt aCompletionCode) |
|
285 { |
|
286 TRequestStatus* status = &iStatus; |
|
287 User::RequestComplete(status, aCompletionCode); |
|
288 SetActive(); |
|
289 } |
|
290 |
|
291 void CLogServOperationQueue::StartNextOpL() |
|
292 // |
|
293 // Start the next operation on the queue |
|
294 // |
|
295 { |
|
296 LOGTEXT("CLogServOperationQueue::StartNextOpL()"); |
|
297 |
|
298 iCurrentOperation = NULL; |
|
299 if (!IsActive() && !iQueuePending.IsEmpty()) |
|
300 { |
|
301 iCurrentOperation = iQueuePending.First(); |
|
302 |
|
303 LOGTEXT3("CLogServOperationQueue::StartNextOpL() - New next operation, Type: %d, Id: %d", iCurrentOperation->Type(), iCurrentOperation->Id()); |
|
304 |
|
305 iCurrentOperation->StartL(iStatus); |
|
306 SetActive(); |
|
307 } |
|
308 |
|
309 LOGTEXT("CLogServOperationQueue::StartNextOpL() - end"); |
|
310 } |
|
311 |
|
312 void CLogServOperationQueue::DeleteFromQueue(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId) |
|
313 // |
|
314 // Delete all operations belonging to a particular session from a queue |
|
315 // |
|
316 { |
|
317 LOGTEXT3("CLogServOperationQueue::DeleteFromQueue() - aId: %d, aSessionId: %d", aOperationId, aSessionId); |
|
318 |
|
319 CLogServOperationBase* op = NULL; |
|
320 while((op = FindOperation(aQueue, aOperationId, aSessionId)) != NULL) |
|
321 { |
|
322 delete op; |
|
323 |
|
324 // We can exit now if we were looking for a particular operation |
|
325 if (aOperationId > KLogNullOperationId) |
|
326 { |
|
327 LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - operation found successfully"); |
|
328 return; |
|
329 } |
|
330 } |
|
331 |
|
332 #ifdef LOGGING_ENABLED |
|
333 if (aOperationId != KLogNullOperationId) |
|
334 { |
|
335 LOGTEXT2("CLogServOperationQueue::DeleteFromQueue() - operation id '%d' wasn't found!", aOperationId); |
|
336 } |
|
337 #endif |
|
338 |
|
339 LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - end"); |
|
340 } |
|
341 |
|
342 TBool CLogServOperationQueue::QueueContainsOperation(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId) |
|
343 // |
|
344 // Finds an operation in a queue |
|
345 // |
|
346 { |
|
347 LOGTEXT3("CLogServOperationQueue::QueueContainsOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId); |
|
348 |
|
349 TSglQueIter<CLogServOperationBase> iter(aQueue); |
|
350 CLogServOperationBase* item = NULL; |
|
351 |
|
352 while ((item = iter++) != NULL) |
|
353 { |
|
354 if (item->Id() == aOperationId && item->SessionId() == aSessionId) |
|
355 { |
|
356 LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - operation found within queue"); |
|
357 return ETrue; |
|
358 } |
|
359 } |
|
360 |
|
361 LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - queue doesn't contain operation"); |
|
362 return EFalse; |
|
363 } |
|
364 |
|
365 CLogServOperationBase* CLogServOperationQueue::FindOperation(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId) |
|
366 // |
|
367 // Find the first operation in a queue belonging to a particular session |
|
368 // |
|
369 { |
|
370 LOGTEXT3("CLogServOperationQueue::FindOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId); |
|
371 |
|
372 TSglQueIter<CLogServOperationBase> iter(aQueue); |
|
373 CLogServOperationBase* item = NULL; |
|
374 |
|
375 while ((item = iter++) != NULL) |
|
376 { |
|
377 if (item->SessionId() == aSessionId && (aOperationId == KLogNullOperationId || item->Id() == aOperationId)) |
|
378 { |
|
379 LOGTEXT("CLogServOperationQueue::FindOperation() - operation found successfully"); |
|
380 return item; |
|
381 } |
|
382 } |
|
383 |
|
384 LOGTEXT("CLogServOperationQueue::FindOperation() - operation not found"); |
|
385 return NULL; |
|
386 } |