sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "LogServOperationQueue.h" sl@0: sl@0: // User includes sl@0: #include "logservpanic.h" sl@0: #include "LogServOperationBase.h" sl@0: #include "LogServTaskInterface.h" sl@0: sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: // -----> CLogServOperationQueue (source) sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: CLogServOperationQueue::CLogServOperationQueue(MLogServTaskInterface& aTaskInterface, TInt aPriority) sl@0: : CActive(aPriority), sl@0: iTaskInterface(aTaskInterface), sl@0: iQueuePending(CLogServOperationBase::QueueOffset()), sl@0: iQueueCompleted(CLogServOperationBase::QueueOffset()) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: CLogServOperationQueue::~CLogServOperationQueue() sl@0: { sl@0: Cancel(); sl@0: // sl@0: CLogServOperationBase* item = NULL; sl@0: // sl@0: TSglQueIter pendingIterator(iQueuePending); sl@0: while ((item = pendingIterator++) != NULL) sl@0: { sl@0: delete item; sl@0: } sl@0: // sl@0: TSglQueIter completedIterator(iQueueCompleted); sl@0: while ((item = completedIterator++) != NULL) sl@0: { sl@0: delete item; sl@0: } sl@0: } sl@0: sl@0: CLogServOperationQueue* CLogServOperationQueue::NewL(MLogServTaskInterface& aTaskInterface, TInt aPriority) sl@0: { sl@0: CLogServOperationQueue* self = new(ELeave) CLogServOperationQueue(aTaskInterface, aPriority); sl@0: return self; sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogServOperationQueue::OMOperationQueueAdd(CLogServOperationBase& aOp) sl@0: // sl@0: // Add a new event to the queue and restart processing if necessary sl@0: // sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::OMOperationQueueAdd() - Type: %d, Id: %d", aOp.Type(), aOp.Id()); sl@0: // sl@0: iQueuePending.AddLast(aOp); sl@0: if (!IsActive()) sl@0: CompleteRequest(); sl@0: // sl@0: LOGTEXT("CLogServOperationQueue::OMOperationQueueAdd() - end"); sl@0: } sl@0: sl@0: // sl@0: // Removes an operation from the relevant server queue sl@0: // sl@0: void CLogServOperationQueue::OMOperationQueueRemove(CLogServOperationBase& aOperation) sl@0: { sl@0: const TLogOperationId operationId = aOperation.Id(); sl@0: const TLogServSessionId sessionId = aOperation.SessionId(); sl@0: // sl@0: LOGTEXT3("CLogServOperationQueue::OMOperationQueueRemove() - Id: %d, SessionId: %d", operationId, sessionId); sl@0: // sl@0: if(QueueContainsOperation(iQueuePending, operationId, sessionId)) sl@0: { sl@0: iQueuePending.Remove(aOperation); sl@0: } sl@0: else sl@0: { sl@0: iQueueCompleted.Remove(aOperation); sl@0: } sl@0: // sl@0: LOGTEXT("CLogServOperationQueue::OMOperationQueueRemove() - end"); sl@0: } sl@0: sl@0: void CLogServOperationQueue::OMGetResultL(TLogOperationId aId, TLogServSessionId aSessionId, const RMessage2& aMessageToWriteTo) sl@0: // sl@0: // Get the result of a specific operation sl@0: // sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::OMGetResultL() - Id: %d, SessionId: %d", aId, aSessionId); sl@0: sl@0: // Look for the op sl@0: CLogServOperationBase* op = FindOperation(iQueueCompleted, aId, aSessionId); sl@0: sl@0: // If we found it, then return the result sl@0: if (op != NULL) sl@0: { sl@0: op->WriteL(aMessageToWriteTo); sl@0: delete op; sl@0: } sl@0: // sl@0: LOGTEXT("CLogServOperationQueue::OMGetResultL() - end"); sl@0: } sl@0: sl@0: void CLogServOperationQueue::OMCancel(TLogOperationId aOpId, TLogServSessionId aSessionId, TBool aCompleteRequest) sl@0: // sl@0: // Cancel a specific operation sl@0: // sl@0: { sl@0: LOGTEXT4("CLogServOperationQueue::OMCancel() - Id: %d, SessionId: %d, CompleteRequest: %d", aOpId, aSessionId, aCompleteRequest); sl@0: sl@0: if (iCurrentOperation && iCurrentOperation->SessionId() == aSessionId && (aOpId == KLogNullOperationId || iCurrentOperation->Id() == aOpId)) sl@0: { sl@0: // We need to cancel the current active operation because it belongs to this session sl@0: // sl@0: // This should complete the request with KErrCancel causing RunL to leave sl@0: // RunError completes the request and removes the operation from the pending queue sl@0: iTaskInterface.TaskCancelCurrent(); sl@0: sl@0: // sl@0: // Do not complete the message when the operation completes sl@0: // sl@0: if (!aCompleteRequest) sl@0: { sl@0: iCurrentOperation->SetMessageCompletion(aCompleteRequest); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // The active operation doesn't belong to this session - just remove any relevant operations from the queues sl@0: // sl@0: // We are taking advantage of the fact that a session will only ever have one operation outstanding sl@0: // so a cancel request basically means - cancel everything belonging to the session sl@0: CLogServOperationBase* op = NULL; sl@0: while((op = FindOperation(iQueuePending, aOpId, aSessionId)) != NULL) sl@0: { sl@0: if (aCompleteRequest) sl@0: { sl@0: op->Cancel(); sl@0: } sl@0: sl@0: // The operation dequeues itself from the containing queue in its destructor via sl@0: // the MLogServOperationManager abstract interface. sl@0: delete op; sl@0: sl@0: // We can exit now if we were looking for a particular operation sl@0: if (aOpId > KLogNullOperationId) sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: // Just delete the completed operation sl@0: DeleteFromQueue(iQueueCompleted, aOpId, aSessionId); sl@0: } sl@0: // sl@0: LOGTEXT("CLogServOperationQueue::OMCancel() - end"); sl@0: } sl@0: sl@0: // sl@0: // Stop/cancel and delete all operations belonging to a particular session sl@0: // If the session has just died we don't want to complete the request - the kernel would panic us sl@0: // sl@0: void CLogServOperationQueue::OMCancel(TLogServSessionId aSessionId, TBool aCompleteRequest) sl@0: { sl@0: OMCancel(KLogNullOperationId, aSessionId, aCompleteRequest); sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: ///////////////////////////////////////////////////////////////////////////////////////// sl@0: sl@0: void CLogServOperationQueue::RunL() sl@0: // sl@0: // Called to indicate that the operation has completed - so complete the client request sl@0: // sl@0: { sl@0: LOGTEXT2("CLogServOperationQueue::RunL(%d)", iStatus.Int()); sl@0: sl@0: // If the queue has just been restarted there won't be an existing operation sl@0: if (iCurrentOperation) sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::RunL() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id()); sl@0: sl@0: // Handle errors in RunError sl@0: User::LeaveIfError(iStatus.Int()); sl@0: sl@0: // Remember the type of operation for later sl@0: const TLogOperationType type = iCurrentOperation->Type(); sl@0: sl@0: // Complete the operation sl@0: if (iCurrentOperation->CompleteProcessingL(iStatus.Int()) == CLogServOperationBase::EOperationComplete) sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::RunL() - Operation is complete, deleting it"); sl@0: delete iCurrentOperation; sl@0: iCurrentOperation = NULL; sl@0: } sl@0: else sl@0: { sl@0: // The client is going to ask for some results. sl@0: // sl@0: // Move the operation to another queue until it's done sl@0: // The session will actually delete the operation sl@0: LOGTEXT("CLogServOperationQueue::RunL() - Operation result awaiting client fetch"); sl@0: iQueuePending.Remove(*iCurrentOperation); sl@0: iQueueCompleted.AddLast(*iCurrentOperation); sl@0: } sl@0: sl@0: // Any errors from maintenance will be ignored because the operation is null sl@0: iCurrentOperation = NULL; sl@0: sl@0: LOGTEXT("CLogServOperationQueue::RunL() - Starting maintenance"); sl@0: iTaskInterface.TaskMaintenanceStartL(iStatus, type != ELogOperationEventGet); sl@0: SetActive(); sl@0: } sl@0: else sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::RunL() - finding next operation"); sl@0: sl@0: // Start the next operation sl@0: StartNextOpL(); sl@0: } sl@0: sl@0: LOGTEXT("CLogServOperationQueue::RunL() - end"); sl@0: } sl@0: sl@0: void CLogServOperationQueue::DoCancel() sl@0: // sl@0: // Implements cancel policy. Only called if the maintenance is active? sl@0: // sl@0: { sl@0: iTaskInterface.TaskCancelCurrent(); sl@0: } sl@0: sl@0: TInt CLogServOperationQueue::RunError(TInt aError) sl@0: // sl@0: // Handle errors sl@0: // sl@0: { sl@0: LOGTEXT2("CLogServOperationQueue::RunError(%d)", aError); sl@0: sl@0: if (iCurrentOperation) sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::RunError() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id()); sl@0: sl@0: // Fail the client request with the error sl@0: if (iCurrentOperation->HaveMessagePointer()) sl@0: iCurrentOperation->Complete(aError); sl@0: delete iCurrentOperation; sl@0: iCurrentOperation = NULL; sl@0: } sl@0: sl@0: // Restart by mending the database if necessary sl@0: TRAPD(mendError, iTaskInterface.TaskMaintenanceStartL(iStatus, ETrue)); sl@0: if (mendError) sl@0: { sl@0: LOGTEXT2("CLogServOperationQueue::RunError() - mend error: %d)", mendError); sl@0: sl@0: // Just ignore the maintenance error and complete ourselves so we continue to execute operations sl@0: CompleteRequest(KErrNone); sl@0: } sl@0: else sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::RunError() - setting active again"); sl@0: SetActive(); sl@0: } sl@0: sl@0: LOGTEXT("CLogServOperationQueue::RunError() - end"); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CLogServOperationQueue::CompleteRequest(TInt aCompletionCode) sl@0: { sl@0: TRequestStatus* status = &iStatus; sl@0: User::RequestComplete(status, aCompletionCode); sl@0: SetActive(); sl@0: } sl@0: sl@0: void CLogServOperationQueue::StartNextOpL() sl@0: // sl@0: // Start the next operation on the queue sl@0: // sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::StartNextOpL()"); sl@0: sl@0: iCurrentOperation = NULL; sl@0: if (!IsActive() && !iQueuePending.IsEmpty()) sl@0: { sl@0: iCurrentOperation = iQueuePending.First(); sl@0: sl@0: LOGTEXT3("CLogServOperationQueue::StartNextOpL() - New next operation, Type: %d, Id: %d", iCurrentOperation->Type(), iCurrentOperation->Id()); sl@0: sl@0: iCurrentOperation->StartL(iStatus); sl@0: SetActive(); sl@0: } sl@0: sl@0: LOGTEXT("CLogServOperationQueue::StartNextOpL() - end"); sl@0: } sl@0: sl@0: void CLogServOperationQueue::DeleteFromQueue(TSglQue& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId) sl@0: // sl@0: // Delete all operations belonging to a particular session from a queue sl@0: // sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::DeleteFromQueue() - aId: %d, aSessionId: %d", aOperationId, aSessionId); sl@0: sl@0: CLogServOperationBase* op = NULL; sl@0: while((op = FindOperation(aQueue, aOperationId, aSessionId)) != NULL) sl@0: { sl@0: delete op; sl@0: sl@0: // We can exit now if we were looking for a particular operation sl@0: if (aOperationId > KLogNullOperationId) sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - operation found successfully"); sl@0: return; sl@0: } sl@0: } sl@0: sl@0: #ifdef LOGGING_ENABLED sl@0: if (aOperationId != KLogNullOperationId) sl@0: { sl@0: LOGTEXT2("CLogServOperationQueue::DeleteFromQueue() - operation id '%d' wasn't found!", aOperationId); sl@0: } sl@0: #endif sl@0: sl@0: LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - end"); sl@0: } sl@0: sl@0: TBool CLogServOperationQueue::QueueContainsOperation(TSglQue& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId) sl@0: // sl@0: // Finds an operation in a queue sl@0: // sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::QueueContainsOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId); sl@0: sl@0: TSglQueIter iter(aQueue); sl@0: CLogServOperationBase* item = NULL; sl@0: sl@0: while ((item = iter++) != NULL) sl@0: { sl@0: if (item->Id() == aOperationId && item->SessionId() == aSessionId) sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - operation found within queue"); sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - queue doesn't contain operation"); sl@0: return EFalse; sl@0: } sl@0: sl@0: CLogServOperationBase* CLogServOperationQueue::FindOperation(TSglQue& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId) sl@0: // sl@0: // Find the first operation in a queue belonging to a particular session sl@0: // sl@0: { sl@0: LOGTEXT3("CLogServOperationQueue::FindOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId); sl@0: sl@0: TSglQueIter iter(aQueue); sl@0: CLogServOperationBase* item = NULL; sl@0: sl@0: while ((item = iter++) != NULL) sl@0: { sl@0: if (item->SessionId() == aSessionId && (aOperationId == KLogNullOperationId || item->Id() == aOperationId)) sl@0: { sl@0: LOGTEXT("CLogServOperationQueue::FindOperation() - operation found successfully"); sl@0: return item; sl@0: } sl@0: } sl@0: sl@0: LOGTEXT("CLogServOperationQueue::FindOperation() - operation not found"); sl@0: return NULL; sl@0: }