os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServOperationQueue.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServOperationQueue.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,391 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "LogServOperationQueue.h"
1.20 +
1.21 +// User includes
1.22 +#include "logservpanic.h"
1.23 +#include "LogServOperationBase.h"
1.24 +#include "LogServTaskInterface.h"
1.25 +
1.26 +
1.27 +/////////////////////////////////////////////////////////////////////////////////////////
1.28 +// -----> CLogServOperationQueue (source)
1.29 +/////////////////////////////////////////////////////////////////////////////////////////
1.30 +
1.31 +CLogServOperationQueue::CLogServOperationQueue(MLogServTaskInterface& aTaskInterface, TInt aPriority)
1.32 +: CActive(aPriority),
1.33 + iTaskInterface(aTaskInterface),
1.34 + iQueuePending(CLogServOperationBase::QueueOffset()),
1.35 + iQueueCompleted(CLogServOperationBase::QueueOffset())
1.36 + {
1.37 + CActiveScheduler::Add(this);
1.38 + }
1.39 +
1.40 +CLogServOperationQueue::~CLogServOperationQueue()
1.41 + {
1.42 + Cancel();
1.43 + //
1.44 + CLogServOperationBase* item = NULL;
1.45 + //
1.46 + TSglQueIter<CLogServOperationBase> pendingIterator(iQueuePending);
1.47 + while ((item = pendingIterator++) != NULL)
1.48 + {
1.49 + delete item;
1.50 + }
1.51 + //
1.52 + TSglQueIter<CLogServOperationBase> completedIterator(iQueueCompleted);
1.53 + while ((item = completedIterator++) != NULL)
1.54 + {
1.55 + delete item;
1.56 + }
1.57 + }
1.58 +
1.59 +CLogServOperationQueue* CLogServOperationQueue::NewL(MLogServTaskInterface& aTaskInterface, TInt aPriority)
1.60 + {
1.61 + CLogServOperationQueue* self = new(ELeave) CLogServOperationQueue(aTaskInterface, aPriority);
1.62 + return self;
1.63 + }
1.64 +
1.65 +/////////////////////////////////////////////////////////////////////////////////////////
1.66 +/////////////////////////////////////////////////////////////////////////////////////////
1.67 +/////////////////////////////////////////////////////////////////////////////////////////
1.68 +
1.69 +void CLogServOperationQueue::OMOperationQueueAdd(CLogServOperationBase& aOp)
1.70 +//
1.71 +// Add a new event to the queue and restart processing if necessary
1.72 +//
1.73 + {
1.74 + LOGTEXT3("CLogServOperationQueue::OMOperationQueueAdd() - Type: %d, Id: %d", aOp.Type(), aOp.Id());
1.75 + //
1.76 + iQueuePending.AddLast(aOp);
1.77 + if (!IsActive())
1.78 + CompleteRequest();
1.79 + //
1.80 + LOGTEXT("CLogServOperationQueue::OMOperationQueueAdd() - end");
1.81 + }
1.82 +
1.83 +//
1.84 +// Removes an operation from the relevant server queue
1.85 +//
1.86 +void CLogServOperationQueue::OMOperationQueueRemove(CLogServOperationBase& aOperation)
1.87 + {
1.88 + const TLogOperationId operationId = aOperation.Id();
1.89 + const TLogServSessionId sessionId = aOperation.SessionId();
1.90 + //
1.91 + LOGTEXT3("CLogServOperationQueue::OMOperationQueueRemove() - Id: %d, SessionId: %d", operationId, sessionId);
1.92 + //
1.93 + if(QueueContainsOperation(iQueuePending, operationId, sessionId))
1.94 + {
1.95 + iQueuePending.Remove(aOperation);
1.96 + }
1.97 + else
1.98 + {
1.99 + iQueueCompleted.Remove(aOperation);
1.100 + }
1.101 + //
1.102 + LOGTEXT("CLogServOperationQueue::OMOperationQueueRemove() - end");
1.103 + }
1.104 +
1.105 +void CLogServOperationQueue::OMGetResultL(TLogOperationId aId, TLogServSessionId aSessionId, const RMessage2& aMessageToWriteTo)
1.106 +//
1.107 +// Get the result of a specific operation
1.108 +//
1.109 + {
1.110 + LOGTEXT3("CLogServOperationQueue::OMGetResultL() - Id: %d, SessionId: %d", aId, aSessionId);
1.111 +
1.112 + // Look for the op
1.113 + CLogServOperationBase* op = FindOperation(iQueueCompleted, aId, aSessionId);
1.114 +
1.115 + // If we found it, then return the result
1.116 + if (op != NULL)
1.117 + {
1.118 + op->WriteL(aMessageToWriteTo);
1.119 + delete op;
1.120 + }
1.121 + //
1.122 + LOGTEXT("CLogServOperationQueue::OMGetResultL() - end");
1.123 + }
1.124 +
1.125 +void CLogServOperationQueue::OMCancel(TLogOperationId aOpId, TLogServSessionId aSessionId, TBool aCompleteRequest)
1.126 +//
1.127 +// Cancel a specific operation
1.128 +//
1.129 + {
1.130 + LOGTEXT4("CLogServOperationQueue::OMCancel() - Id: %d, SessionId: %d, CompleteRequest: %d", aOpId, aSessionId, aCompleteRequest);
1.131 +
1.132 + if (iCurrentOperation && iCurrentOperation->SessionId() == aSessionId && (aOpId == KLogNullOperationId || iCurrentOperation->Id() == aOpId))
1.133 + {
1.134 + // We need to cancel the current active operation because it belongs to this session
1.135 + //
1.136 + // This should complete the request with KErrCancel causing RunL to leave
1.137 + // RunError completes the request and removes the operation from the pending queue
1.138 + iTaskInterface.TaskCancelCurrent();
1.139 +
1.140 + //
1.141 + // Do not complete the message when the operation completes
1.142 + //
1.143 + if (!aCompleteRequest)
1.144 + {
1.145 + iCurrentOperation->SetMessageCompletion(aCompleteRequest);
1.146 + }
1.147 + }
1.148 + else
1.149 + {
1.150 + // The active operation doesn't belong to this session - just remove any relevant operations from the queues
1.151 + //
1.152 + // We are taking advantage of the fact that a session will only ever have one operation outstanding
1.153 + // so a cancel request basically means - cancel everything belonging to the session
1.154 + CLogServOperationBase* op = NULL;
1.155 + while((op = FindOperation(iQueuePending, aOpId, aSessionId)) != NULL)
1.156 + {
1.157 + if (aCompleteRequest)
1.158 + {
1.159 + op->Cancel();
1.160 + }
1.161 +
1.162 + // The operation dequeues itself from the containing queue in its destructor via
1.163 + // the MLogServOperationManager abstract interface.
1.164 + delete op;
1.165 +
1.166 + // We can exit now if we were looking for a particular operation
1.167 + if (aOpId > KLogNullOperationId)
1.168 + {
1.169 + return;
1.170 + }
1.171 + }
1.172 +
1.173 + // Just delete the completed operation
1.174 + DeleteFromQueue(iQueueCompleted, aOpId, aSessionId);
1.175 + }
1.176 + //
1.177 + LOGTEXT("CLogServOperationQueue::OMCancel() - end");
1.178 + }
1.179 +
1.180 +//
1.181 +// Stop/cancel and delete all operations belonging to a particular session
1.182 +// If the session has just died we don't want to complete the request - the kernel would panic us
1.183 +//
1.184 +void CLogServOperationQueue::OMCancel(TLogServSessionId aSessionId, TBool aCompleteRequest)
1.185 + {
1.186 + OMCancel(KLogNullOperationId, aSessionId, aCompleteRequest);
1.187 + }
1.188 +
1.189 +/////////////////////////////////////////////////////////////////////////////////////////
1.190 +/////////////////////////////////////////////////////////////////////////////////////////
1.191 +/////////////////////////////////////////////////////////////////////////////////////////
1.192 +
1.193 +void CLogServOperationQueue::RunL()
1.194 +//
1.195 +// Called to indicate that the operation has completed - so complete the client request
1.196 +//
1.197 + {
1.198 + LOGTEXT2("CLogServOperationQueue::RunL(%d)", iStatus.Int());
1.199 +
1.200 + // If the queue has just been restarted there won't be an existing operation
1.201 + if (iCurrentOperation)
1.202 + {
1.203 + LOGTEXT3("CLogServOperationQueue::RunL() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id());
1.204 +
1.205 + // Handle errors in RunError
1.206 + User::LeaveIfError(iStatus.Int());
1.207 +
1.208 + // Remember the type of operation for later
1.209 + const TLogOperationType type = iCurrentOperation->Type();
1.210 +
1.211 + // Complete the operation
1.212 + if (iCurrentOperation->CompleteProcessingL(iStatus.Int()) == CLogServOperationBase::EOperationComplete)
1.213 + {
1.214 + LOGTEXT("CLogServOperationQueue::RunL() - Operation is complete, deleting it");
1.215 + delete iCurrentOperation;
1.216 + iCurrentOperation = NULL;
1.217 + }
1.218 + else
1.219 + {
1.220 + // The client is going to ask for some results.
1.221 + //
1.222 + // Move the operation to another queue until it's done
1.223 + // The session will actually delete the operation
1.224 + LOGTEXT("CLogServOperationQueue::RunL() - Operation result awaiting client fetch");
1.225 + iQueuePending.Remove(*iCurrentOperation);
1.226 + iQueueCompleted.AddLast(*iCurrentOperation);
1.227 + }
1.228 +
1.229 + // Any errors from maintenance will be ignored because the operation is null
1.230 + iCurrentOperation = NULL;
1.231 +
1.232 + LOGTEXT("CLogServOperationQueue::RunL() - Starting maintenance");
1.233 + iTaskInterface.TaskMaintenanceStartL(iStatus, type != ELogOperationEventGet);
1.234 + SetActive();
1.235 + }
1.236 + else
1.237 + {
1.238 + LOGTEXT("CLogServOperationQueue::RunL() - finding next operation");
1.239 +
1.240 + // Start the next operation
1.241 + StartNextOpL();
1.242 + }
1.243 +
1.244 + LOGTEXT("CLogServOperationQueue::RunL() - end");
1.245 + }
1.246 +
1.247 +void CLogServOperationQueue::DoCancel()
1.248 +//
1.249 +// Implements cancel policy. Only called if the maintenance is active?
1.250 +//
1.251 + {
1.252 + iTaskInterface.TaskCancelCurrent();
1.253 + }
1.254 +
1.255 +TInt CLogServOperationQueue::RunError(TInt aError)
1.256 +//
1.257 +// Handle errors
1.258 +//
1.259 + {
1.260 + LOGTEXT2("CLogServOperationQueue::RunError(%d)", aError);
1.261 +
1.262 + if (iCurrentOperation)
1.263 + {
1.264 + LOGTEXT3("CLogServOperationQueue::RunError() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id());
1.265 +
1.266 + // Fail the client request with the error
1.267 + if (iCurrentOperation->HaveMessagePointer())
1.268 + iCurrentOperation->Complete(aError);
1.269 + delete iCurrentOperation;
1.270 + iCurrentOperation = NULL;
1.271 + }
1.272 +
1.273 + // Restart by mending the database if necessary
1.274 + TRAPD(mendError, iTaskInterface.TaskMaintenanceStartL(iStatus, ETrue));
1.275 + if (mendError)
1.276 + {
1.277 + LOGTEXT2("CLogServOperationQueue::RunError() - mend error: %d)", mendError);
1.278 +
1.279 + // Just ignore the maintenance error and complete ourselves so we continue to execute operations
1.280 + CompleteRequest(KErrNone);
1.281 + }
1.282 + else
1.283 + {
1.284 + LOGTEXT("CLogServOperationQueue::RunError() - setting active again");
1.285 + SetActive();
1.286 + }
1.287 +
1.288 + LOGTEXT("CLogServOperationQueue::RunError() - end");
1.289 + return KErrNone;
1.290 + }
1.291 +
1.292 +void CLogServOperationQueue::CompleteRequest(TInt aCompletionCode)
1.293 + {
1.294 + TRequestStatus* status = &iStatus;
1.295 + User::RequestComplete(status, aCompletionCode);
1.296 + SetActive();
1.297 + }
1.298 +
1.299 +void CLogServOperationQueue::StartNextOpL()
1.300 +//
1.301 +// Start the next operation on the queue
1.302 +//
1.303 + {
1.304 + LOGTEXT("CLogServOperationQueue::StartNextOpL()");
1.305 +
1.306 + iCurrentOperation = NULL;
1.307 + if (!IsActive() && !iQueuePending.IsEmpty())
1.308 + {
1.309 + iCurrentOperation = iQueuePending.First();
1.310 +
1.311 + LOGTEXT3("CLogServOperationQueue::StartNextOpL() - New next operation, Type: %d, Id: %d", iCurrentOperation->Type(), iCurrentOperation->Id());
1.312 +
1.313 + iCurrentOperation->StartL(iStatus);
1.314 + SetActive();
1.315 + }
1.316 +
1.317 + LOGTEXT("CLogServOperationQueue::StartNextOpL() - end");
1.318 + }
1.319 +
1.320 +void CLogServOperationQueue::DeleteFromQueue(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId)
1.321 +//
1.322 +// Delete all operations belonging to a particular session from a queue
1.323 +//
1.324 + {
1.325 + LOGTEXT3("CLogServOperationQueue::DeleteFromQueue() - aId: %d, aSessionId: %d", aOperationId, aSessionId);
1.326 +
1.327 + CLogServOperationBase* op = NULL;
1.328 + while((op = FindOperation(aQueue, aOperationId, aSessionId)) != NULL)
1.329 + {
1.330 + delete op;
1.331 +
1.332 + // We can exit now if we were looking for a particular operation
1.333 + if (aOperationId > KLogNullOperationId)
1.334 + {
1.335 + LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - operation found successfully");
1.336 + return;
1.337 + }
1.338 + }
1.339 +
1.340 +#ifdef LOGGING_ENABLED
1.341 + if (aOperationId != KLogNullOperationId)
1.342 + {
1.343 + LOGTEXT2("CLogServOperationQueue::DeleteFromQueue() - operation id '%d' wasn't found!", aOperationId);
1.344 + }
1.345 +#endif
1.346 +
1.347 + LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - end");
1.348 + }
1.349 +
1.350 +TBool CLogServOperationQueue::QueueContainsOperation(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId)
1.351 +//
1.352 +// Finds an operation in a queue
1.353 +//
1.354 + {
1.355 + LOGTEXT3("CLogServOperationQueue::QueueContainsOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId);
1.356 +
1.357 + TSglQueIter<CLogServOperationBase> iter(aQueue);
1.358 + CLogServOperationBase* item = NULL;
1.359 +
1.360 + while ((item = iter++) != NULL)
1.361 + {
1.362 + if (item->Id() == aOperationId && item->SessionId() == aSessionId)
1.363 + {
1.364 + LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - operation found within queue");
1.365 + return ETrue;
1.366 + }
1.367 + }
1.368 +
1.369 + LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - queue doesn't contain operation");
1.370 + return EFalse;
1.371 + }
1.372 +
1.373 +CLogServOperationBase* CLogServOperationQueue::FindOperation(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId)
1.374 +//
1.375 +// Find the first operation in a queue belonging to a particular session
1.376 +//
1.377 + {
1.378 + LOGTEXT3("CLogServOperationQueue::FindOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId);
1.379 +
1.380 + TSglQueIter<CLogServOperationBase> iter(aQueue);
1.381 + CLogServOperationBase* item = NULL;
1.382 +
1.383 + while ((item = iter++) != NULL)
1.384 + {
1.385 + if (item->SessionId() == aSessionId && (aOperationId == KLogNullOperationId || item->Id() == aOperationId))
1.386 + {
1.387 + LOGTEXT("CLogServOperationQueue::FindOperation() - operation found successfully");
1.388 + return item;
1.389 + }
1.390 + }
1.391 +
1.392 + LOGTEXT("CLogServOperationQueue::FindOperation() - operation not found");
1.393 + return NULL;
1.394 + }