os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServOperationQueue.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 		//
   138 		// Do not complete the message when the operation completes
   139 		//
   140 		if (!aCompleteRequest)
   141 			{
   142 			iCurrentOperation->SetMessageCompletion(aCompleteRequest);
   143 			}
   144 		}
   145 	else
   146 		{
   147 		// The active operation doesn't belong to this session - just remove any relevant operations from the queues
   148 		//
   149 		// We are taking advantage of the fact that a session will only ever have one operation outstanding
   150 		// so a cancel request basically means - cancel everything belonging to the session
   151 		CLogServOperationBase* op = NULL;
   152 		while((op = FindOperation(iQueuePending, aOpId, aSessionId)) != NULL)
   153 			{
   154 			if	(aCompleteRequest)
   155 				{
   156 				op->Cancel();
   157 				}
   158 
   159 			// The operation dequeues itself from the containing queue in its destructor via
   160 			// the MLogServOperationManager abstract interface.
   161 			delete op;
   162 
   163 			// We can exit now if we were looking for a particular operation
   164 			if	(aOpId > KLogNullOperationId)
   165 				{
   166 				return;
   167 				}
   168 			}
   169 
   170 		// Just delete the completed operation
   171 		DeleteFromQueue(iQueueCompleted, aOpId, aSessionId);
   172 		}
   173 	//
   174 	LOGTEXT("CLogServOperationQueue::OMCancel() - end");
   175 	}
   176 
   177 //
   178 //	Stop/cancel and delete all operations belonging to a particular session
   179 //	If the session has just died we don't want to complete the request - the kernel would panic us
   180 //
   181 void CLogServOperationQueue::OMCancel(TLogServSessionId aSessionId, TBool aCompleteRequest)
   182 	{
   183 	OMCancel(KLogNullOperationId, aSessionId, aCompleteRequest);
   184 	}
   185 
   186 /////////////////////////////////////////////////////////////////////////////////////////
   187 /////////////////////////////////////////////////////////////////////////////////////////
   188 /////////////////////////////////////////////////////////////////////////////////////////
   189 
   190 void CLogServOperationQueue::RunL()
   191 //
   192 //	Called to indicate that the operation has completed - so complete the client request
   193 //
   194 	{
   195 	LOGTEXT2("CLogServOperationQueue::RunL(%d)", iStatus.Int());
   196 
   197 	// If the queue has just been restarted there won't be an existing operation
   198 	if (iCurrentOperation)
   199 		{
   200 		LOGTEXT3("CLogServOperationQueue::RunL() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id());
   201 
   202 		// Handle errors in RunError
   203 		User::LeaveIfError(iStatus.Int());
   204 
   205 		// Remember the type of operation for later
   206 		const TLogOperationType type = iCurrentOperation->Type();
   207 
   208 		// Complete the operation
   209 		if	(iCurrentOperation->CompleteProcessingL(iStatus.Int()) == CLogServOperationBase::EOperationComplete)
   210 			{
   211 			LOGTEXT("CLogServOperationQueue::RunL() - Operation is complete, deleting it");
   212 			delete iCurrentOperation;
   213 			iCurrentOperation = NULL;
   214 			}
   215 		else
   216 			{
   217 			// The client is going to ask for some results.
   218 			//
   219 			// Move the operation to another queue until it's done
   220 			// The session will actually delete the operation
   221 			LOGTEXT("CLogServOperationQueue::RunL() - Operation result awaiting client fetch");
   222 			iQueuePending.Remove(*iCurrentOperation);
   223 			iQueueCompleted.AddLast(*iCurrentOperation);
   224 			}
   225 
   226 		// Any errors from maintenance will be ignored because the operation is null
   227 		iCurrentOperation = NULL;
   228 
   229 		LOGTEXT("CLogServOperationQueue::RunL() - Starting maintenance");
   230 		iTaskInterface.TaskMaintenanceStartL(iStatus, type != ELogOperationEventGet);
   231 		SetActive();
   232 		}
   233 	else
   234 		{
   235 		LOGTEXT("CLogServOperationQueue::RunL() - finding next operation");
   236 
   237 		// Start the next operation
   238 		StartNextOpL();
   239 		}
   240 
   241 	LOGTEXT("CLogServOperationQueue::RunL() - end");
   242 	}
   243 
   244 void CLogServOperationQueue::DoCancel()
   245 //
   246 //	Implements cancel policy. Only called if the maintenance is active?
   247 //
   248 	{
   249 	iTaskInterface.TaskCancelCurrent();
   250 	}
   251 
   252 TInt CLogServOperationQueue::RunError(TInt aError)
   253 //
   254 //	Handle errors
   255 //
   256 	{
   257 	LOGTEXT2("CLogServOperationQueue::RunError(%d)", aError);
   258 
   259 	if	(iCurrentOperation)
   260 		{
   261 		LOGTEXT3("CLogServOperationQueue::RunError() - Current operation Type: %d, Id: %d,", iCurrentOperation->Type(), iCurrentOperation->Id());
   262 
   263 		// Fail the client request with the error
   264 		if	(iCurrentOperation->HaveMessagePointer())
   265 			iCurrentOperation->Complete(aError);
   266 		delete iCurrentOperation;
   267 		iCurrentOperation = NULL;
   268 		}
   269 
   270 	// Restart by mending the database if necessary
   271 	TRAPD(mendError, iTaskInterface.TaskMaintenanceStartL(iStatus, ETrue));
   272 	if	(mendError)
   273 		{
   274 		LOGTEXT2("CLogServOperationQueue::RunError() - mend error: %d)", mendError);
   275 
   276 		// Just ignore the maintenance error and complete ourselves so we continue to execute operations
   277 		CompleteRequest(KErrNone);
   278 		}
   279 	else
   280 		{
   281 		LOGTEXT("CLogServOperationQueue::RunError() - setting active again");
   282 		SetActive();
   283 		}
   284 
   285 	LOGTEXT("CLogServOperationQueue::RunError() - end");
   286 	return KErrNone;
   287 	}
   288 
   289 void CLogServOperationQueue::CompleteRequest(TInt aCompletionCode)
   290 	{
   291 	TRequestStatus* status = &iStatus;
   292 	User::RequestComplete(status, aCompletionCode);
   293 	SetActive();
   294 	}
   295 
   296 void CLogServOperationQueue::StartNextOpL()
   297 //
   298 //	Start the next operation on the queue
   299 //
   300 	{
   301 	LOGTEXT("CLogServOperationQueue::StartNextOpL()");
   302 
   303 	iCurrentOperation = NULL;
   304 	if (!IsActive() && !iQueuePending.IsEmpty())
   305 		{
   306 		iCurrentOperation = iQueuePending.First();
   307 
   308 		LOGTEXT3("CLogServOperationQueue::StartNextOpL() - New next operation, Type: %d, Id: %d", iCurrentOperation->Type(), iCurrentOperation->Id());
   309 
   310 		iCurrentOperation->StartL(iStatus);
   311 		SetActive();
   312 		}
   313 
   314 	LOGTEXT("CLogServOperationQueue::StartNextOpL() - end");
   315 	}
   316 
   317 void CLogServOperationQueue::DeleteFromQueue(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId)
   318 //
   319 //	Delete all operations belonging to a particular session from a queue
   320 //
   321 	{
   322 	LOGTEXT3("CLogServOperationQueue::DeleteFromQueue() - aId: %d, aSessionId: %d", aOperationId, aSessionId);
   323 
   324 	CLogServOperationBase* op = NULL;
   325 	while((op = FindOperation(aQueue, aOperationId, aSessionId)) != NULL)
   326 		{
   327 		delete op;
   328 
   329 		// We can exit now if we were looking for a particular operation
   330 		if	(aOperationId > KLogNullOperationId)
   331 			{
   332 			LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - operation found successfully");
   333 			return;
   334 			}
   335 		}
   336 
   337 #ifdef LOGGING_ENABLED
   338 	if	(aOperationId != KLogNullOperationId)
   339 		{
   340 		LOGTEXT2("CLogServOperationQueue::DeleteFromQueue() - operation id '%d' wasn't found!", aOperationId);
   341 		}
   342 #endif
   343 
   344 	LOGTEXT("CLogServOperationQueue::DeleteFromQueue() - end");
   345 	}
   346 
   347 TBool CLogServOperationQueue::QueueContainsOperation(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId)
   348 //
   349 //	Finds an operation in a queue
   350 //
   351 	{
   352 	LOGTEXT3("CLogServOperationQueue::QueueContainsOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId);
   353 
   354 	TSglQueIter<CLogServOperationBase> iter(aQueue);
   355 	CLogServOperationBase* item = NULL;
   356 	
   357 	while ((item = iter++) != NULL)
   358 		{
   359 		if	(item->Id() == aOperationId && item->SessionId() == aSessionId)
   360 			{
   361 			LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - operation found within queue");
   362 			return ETrue;
   363 			}
   364 		}
   365 	
   366 	LOGTEXT("CLogServOperationQueue::QueueContainsOperation() - queue doesn't contain operation");
   367 	return EFalse;
   368 	}
   369 
   370 CLogServOperationBase* CLogServOperationQueue::FindOperation(TSglQue<CLogServOperationBase>& aQueue, TLogOperationId aOperationId, TLogServSessionId aSessionId)
   371 //
   372 //	Find the first operation in a queue belonging to a particular session
   373 //
   374 	{
   375 	LOGTEXT3("CLogServOperationQueue::FindOperation() - aId: %d, aSessionId: %d", aOperationId, aSessionId);
   376 
   377 	TSglQueIter<CLogServOperationBase> iter(aQueue);
   378 	CLogServOperationBase* item = NULL;
   379 	
   380 	while ((item = iter++) != NULL)
   381 		{
   382 		if	(item->SessionId() == aSessionId && (aOperationId == KLogNullOperationId || item->Id() == aOperationId))
   383 			{
   384 			LOGTEXT("CLogServOperationQueue::FindOperation() - operation found successfully");
   385 			return item;
   386 			}
   387 		}
   388 
   389 	LOGTEXT("CLogServOperationQueue::FindOperation() - operation not found");
   390 	return NULL;	
   391 	}