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