os/persistentdata/loggingservices/eventlogger/LogServ/src/logservsession.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 "logservsession.h"
    17 #include "LogNotify.h"
    18 #include "LogServServer.h"
    19 #include "logservpanic.h"
    20 #include "LogServView.h"
    21 #include "LogServOperationBase.h"
    22 #include "LogServBackupInterface.h"
    23 #include "LogServOperationFactory.h"
    24 #include "LogServOperationManager.h"
    25 #include "LogServDatabaseChangeInterface.h"
    26 #include "LogServDatabaseChangeDefinition.h"
    27 #include "LogServSqlStrings.h"
    28 
    29 // Constants
    30 const TInt KLogViewListGranuality = 5;
    31 const TInt KLogServPendingGlobalChangesArrayGranularity = 3;
    32 
    33 
    34 /////////////////////////////////////////////////////////////////////////////////////////
    35 // -----> CLogServSession (source)
    36 /////////////////////////////////////////////////////////////////////////////////////////
    37 
    38 CLogServSession::CLogServSession(TLogServSessionId aSessionId, 
    39                                  MLogServSessionLifetimeObserver& aObserver, 
    40                                  MLogServBackupInterface& aBackupInterface, 
    41                                  MLogServTaskInterface& aTaskInterface, 
    42                                  MLogServOperationManager& aOperationManager, 
    43                                  MLogServDatabaseChangeInterface& aChangeInterface, 
    44                                  MLogServDatabaseTransactionInterface& aDatabase) :
    45     iSessionId(aSessionId), 
    46     iObserver(aObserver), 
    47     iBackupInterface(aBackupInterface), 
    48     iTaskInterface(aTaskInterface), 
    49     iOperationManager(aOperationManager), 
    50     iChangeInterface(aChangeInterface), 
    51     iDatabase(aDatabase), 
    52     iViewList(KLogViewListGranuality), 
    53     iPendingGlobalChanges(KLogServPendingGlobalChangesArrayGranularity)
    54 	{
    55 	iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventCreated); 
    56 	}
    57 
    58 CLogServSession::~CLogServSession()
    59 	{
    60 	LOGTEXT3("CLogServSession::~CLogServSession() - client logging off: %S, %d", &iClientThreadName, iSessionId);
    61 
    62 	// Set second parameter to not complete the message, otherwise if the client has died a KERN-EXEC 44 will be generated.
    63 	iOperationManager.OMCancel(iSessionId, EFalse);
    64 	
    65 	delete iPackage;
    66 	delete iNotify;
    67 
    68 	iChangeInterface.DCIRequestChangeNotificationsCancel(*this);
    69 	//
    70 	iViewList.ResetAndDestroy();
    71 	iViewList.Close();
    72 	iPendingGlobalChanges.Close();
    73 	//
    74 	iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventDestroyed); 
    75 
    76 	LOGTEXT2("CLogServSession::~CLogServSession() - client dead %d", iSessionId);
    77 	LOGTEXT("");
    78 	}
    79 
    80 /////////////////////////////////////////////////////////////////////////////////////////
    81 /////////////////////////////////////////////////////////////////////////////////////////
    82 /////////////////////////////////////////////////////////////////////////////////////////
    83 
    84 void CLogServSession::DCOHandleGlobalChangeEventL(const TLogServDatabaseChangeDefinition& aChange)
    85 	{
    86 	if	(iExtendedNotificationRequested)
    87 		User::LeaveIfError(iPendingGlobalChanges.Append(aChange));
    88 	ExtendedNotifyCompleteL(KErrNone);
    89 	}
    90 
    91 /////////////////////////////////////////////////////////////////////////////////////////
    92 /////////////////////////////////////////////////////////////////////////////////////////
    93 /////////////////////////////////////////////////////////////////////////////////////////
    94 void CLogServSession::CreateL()
    95 	{
    96 	iPackage = CLogPackage::NewL();
    97 
    98 	// Request change notifications
    99 	iChangeInterface.DCIRequestChangeNotificationsL(*this);
   100 	}
   101 
   102 //
   103 //  Handle a client request.
   104 //
   105 //  Leaving is handled by CLogServ::RunError() which reports the error code to the client
   106 //  Note: operation add themselves to the server active queue in their constructor
   107 //  The server active object owns them and deletes them when necessary
   108 //  So the iffy looking code below won't actually leak memory
   109 //
   110 void CLogServSession::ServiceL(const RMessage2& aMessage)
   111 	{
   112 	LOGTEXT3("CLogServSession::ServiceL(%S, %d)", &iClientThreadName, aMessage.Function());
   113 
   114 	switch(aMessage.Function())
   115 		{
   116 	/**
   117 	 * Overall operation management
   118 	 */
   119 	case ELogOperationGetResult:
   120 	case ELogOperationCancel:
   121 	case ELogOperationInitiate:
   122 		ServiceOperationFunctionL(aMessage);
   123 		break;
   124 
   125 	/**
   126 	 * Notification related
   127 	 */
   128 	case ELogNotify:
   129 		{
   130 		if	(!iNotify)
   131 			{
   132 			iNotify = CLogNotify::NewL(iBackupInterface, iChangeInterface, Server().Priority());
   133 
   134 		#ifdef LOGGING_ENABLED
   135 			iNotify->SetClientThreadName(iClientThreadName);
   136 		#endif
   137 			}
   138 		
   139 		if	(!iNotify->IsActive())
   140 			{
   141 			const TTimeIntervalMicroSeconds32 delayTime = reinterpret_cast<TInt>(aMessage.Ptr0());
   142 			
   143 			//Validate time value
   144 			if(delayTime.Int() < 0)
   145 				{
   146 				User::Leave(KErrArgument);
   147 				}
   148 			iNotify->Notify(delayTime, aMessage);
   149 			}
   150 		else
   151 			::PanicClientL(aMessage, ELogAlreadyActive19);
   152 		break;
   153 		}
   154 	case ELogNotifyCancel:
   155 		{
   156 		if	(iNotify)
   157 			iNotify->Cancel();
   158 		aMessage.Complete(KErrCancel);
   159 		break;
   160 		}
   161 	case ELogNotifyExtended:
   162 		{
   163 		if	(iExtendedNotificationMessage == RMessage2())
   164 			{
   165 			iExtendedNotificationMessage = aMessage;
   166 			iExtendedNotificationRequested = ETrue;
   167 			}
   168 		else
   169 			::PanicClientL(aMessage, ELogExtendedMessageAlreadyActive);
   170 		break;
   171 		}
   172 	case ELogNotifyExtendedCancel:
   173 		{
   174         if	(iExtendedNotificationMessage != RMessage2())
   175 			ExtendedNotifyCompleteL(KErrCancel);
   176 		//
   177 		iExtendedNotificationRequested = EFalse;
   178 		iPendingGlobalChanges.Reset();
   179 		iPendingGlobalChanges.GranularCompress();
   180 		//
   181 		aMessage.Complete(KErrCancel);
   182 		break;
   183 		}
   184 
   185 	/**
   186 	 * View functionality
   187 	 */
   188 	case ELogViewCreate:
   189 	case ELogViewDelete:
   190 	case ELogViewCount:
   191 	case ELogViewOperationInitiate:
   192 	case ELogViewChangeNotificationsRequest:
   193 	case ELogViewChangeNotificationsCancel:
   194 	case ELogViewFetchChanges:
   195 	case ELogViewNotifyLockStatusChange:
   196 	case ELogViewNotifyLockStatusChangeCancel:
   197 		ServiceViewFunctionL(aMessage);
   198 		break;
   199 
   200 	/** 
   201 	 * Misc. (debug) functionality
   202 	 */
   203 #ifdef _DEBUG
   204 	case ELogMakeTransient:
   205 		{
   206 		Server().MakeTransient((TBool)aMessage.Ptr0());
   207 		aMessage.Complete(KErrNone);
   208 		break;
   209 		}
   210 	case ELogIsServerReady:
   211 		{
   212 		const TBool serverReady = (iBackupInterface.BIErrorValueForCurrentState() == KErrNone);
   213 		aMessage.Complete(serverReady);
   214 		break;
   215 		}
   216 	case ELogSetHeapFail:
   217 		{
   218 		User::__DbgSetAllocFail(RHeap::EUser, RHeap::TAllocFail(aMessage.Int0()),aMessage.Int1());
   219 		aMessage.Complete(KErrNone);
   220 		break;
   221 		}
   222 #endif// _DEBUG
   223 	/**
   224 	 * Unknown operations
   225 	 */
   226 	default:
   227 		::PanicClientL(aMessage, ELogIllegalFunction);
   228 		break;
   229 		}
   230 	}
   231 
   232 /**
   233 If aError is KErrBadDescriptor, then panic the client, else - default error handling.
   234 KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad
   235 descriptor to the server.
   236 */
   237 void CLogServSession::ServiceError(const RMessage2& aMessage,TInt aError)
   238 	{
   239 	if(aError == KErrBadDescriptor)
   240 		{
   241 		//The __LOGPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call
   242 		//from a leaving call will terminate the server.
   243 		aMessage.Panic(KLogServ, ELogBadDescriptor);
   244 		}
   245 	CSession2::ServiceError(aMessage, aError);
   246 	}
   247 	
   248 /////////////////////////////////////////////////////////////////////////////////////////
   249 /////////////////////////////////////////////////////////////////////////////////////////
   250 /////////////////////////////////////////////////////////////////////////////////////////
   251 
   252 CLogServServer& CLogServSession::Server() const
   253 	{
   254 	return *static_cast<CLogServServer*>(const_cast<CServer2*>(CSession2::Server()));
   255 	}
   256 
   257 /////////////////////////////////////////////////////////////////////////////////////////
   258 /////////////////////////////////////////////////////////////////////////////////////////
   259 /////////////////////////////////////////////////////////////////////////////////////////
   260 
   261 
   262 CLogServViewBase& CLogServSession::ViewByIdL(TUint32 aViewId)
   263 	{
   264 	const TInt index = ViewPositionById(aViewId);
   265 	User::LeaveIfError(index);
   266 	return *iViewList[index];
   267 	}
   268 
   269 TInt CLogServSession::ViewPositionById(TUint32 aViewId) const
   270 	{
   271 	const TInt count = iViewList.Count();
   272 	for(TInt i=0; i<count; i++)
   273 		{
   274 		const CLogServViewBase& view = *iViewList[i];
   275 		if	(view.ViewId() == aViewId)
   276 			return i;
   277 		}
   278 	return KErrNotFound;
   279 	}
   280 
   281 
   282 void CLogServSession::ReadClientServerDataL(TLogClientServerData& aClientServerData,
   283 		const RMessage2 &aMessage, TInt aMinOperation, TInt aMaxOperation)
   284 	{
   285 
   286 	TInt length = aMessage.GetDesLengthL(0);
   287 	if(length != sizeof(TLogClientServerData))
   288 		{
   289 		User::Leave(KErrBadDescriptor);
   290 		}
   291 	
   292 	TPckg<TLogClientServerData> pData(aClientServerData);
   293 	aMessage.ReadL(0, pData);
   294 	
   295 	//Validate Operation Type
   296 	if((aClientServerData.iOperationType < aMinOperation) ||
   297 			(aClientServerData.iOperationType > aMaxOperation))
   298 		{
   299 		User::Leave(KErrArgument);
   300 		}
   301 	}
   302 
   303 void CLogServSession::ServiceViewFunctionL(const RMessage2& aMessage)
   304 	{
   305 	switch(aMessage.Function())
   306 		{
   307 	case ELogViewCreate:
   308 		{
   309 		iViewList.ReserveL(iViewList.Count() + 1);
   310 		// Type is first parameter, view id is second
   311 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   312 		const TLogViewType type = static_cast<TLogViewType>(aMessage.Int1());
   313 		
   314 		//Validate type value
   315 		if((type < ELogViewTypeEvent)||(type > ELogViewTypeDuplicate))
   316 			{
   317 			User::Leave(KErrArgument);
   318 			}
   319 		
   320 		// Ask the factory to create it
   321 		CLogServViewBase* view = LogServFactory::NewViewL(type, id, iDatabase, iBackupInterface, *iPackage, aMessage);
   322 		TInt err = iViewList.Append(view);
   323         __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
   324 		aMessage.Complete(err);
   325 		break;
   326 		}
   327 	case ELogViewDelete:
   328 		{
   329 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   330 		TInt indexAndError = ViewPositionById(id);
   331 		if	(indexAndError >= 0)
   332 			{
   333 			delete iViewList[indexAndError];
   334 			iViewList.Remove(indexAndError);
   335 			indexAndError = KErrNone;
   336 			}
   337 		aMessage.Complete(indexAndError);
   338 		break;
   339 		}
   340 	case ELogViewCount:
   341 		{
   342 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   343 		CLogServViewBase& view = ViewByIdL(id);
   344 		const TInt count = view.Count();
   345 		aMessage.Complete(count);
   346 		break;
   347 		}
   348 	case ELogViewOperationInitiate:
   349 		{
   350 		// We don't allow any operations during a backup
   351 		iBackupInterface.BIValidateStateForDatabaseOperationL();
   352 		//
   353 		TLogClientServerData clientServerData;
   354 		ReadClientServerDataL(clientServerData,aMessage, 
   355 				ELogOperationViewSetup, ELogOperationViewWindowFetch);
   356 
   357 		//
   358 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int1());
   359 		CLogServViewBase& view = ViewByIdL(id);
   360 
   361 		// Create operation. Operations are owned by the operation manager (they are added to a queue)
   362 		// when the objects are created, so this does not leak any memory.
   363 		CLogServOperationBase* operation = LogServFactory::NewViewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId, view);
   364 		(void) operation;
   365 		break;
   366 		}
   367 	case ELogViewChangeNotificationsRequest:
   368 		{
   369 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   370 		CLogServViewBase& view = ViewByIdL(id);
   371 		view.RequestChangeNotifications(aMessage);
   372 		break;
   373 		}
   374 	case ELogViewChangeNotificationsCancel:
   375 		{
   376 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   377 		CLogServViewBase& view = ViewByIdL(id);
   378 		view.RequestChangeNotificationsCancel();
   379 		aMessage.Complete(KErrNone);
   380 		break;
   381 		}
   382 	case ELogViewFetchChanges:
   383 		{
   384 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   385 		CLogServViewBase& view = ViewByIdL(id);
   386 		view.RequestChangesL(aMessage);
   387 		aMessage.Complete(KErrNone);
   388 		break;
   389 		}
   390 	case ELogViewNotifyLockStatusChange:
   391 		{
   392 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   393 		CLogServViewBase& view = ViewByIdL(id);
   394 		view.RequestLockStatusChanges(aMessage);
   395 		break;
   396 		}
   397 	case ELogViewNotifyLockStatusChangeCancel:
   398 		{
   399 		const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
   400 		CLogServViewBase& view = ViewByIdL(id);
   401 		view.RequestLockStatusChangesCancel();
   402 		aMessage.Complete(KErrNone);
   403 		break;
   404 		}
   405 		}
   406 	}
   407 
   408 void CLogServSession::ServiceOperationFunctionL(const RMessage2& aMessage)
   409 	{
   410 	// We don't allow any operations during a backup
   411 	iBackupInterface.BIValidateStateForDatabaseOperationL();
   412 	//
   413 	TLogClientServerData clientServerData;
   414 	ReadClientServerDataL(clientServerData,aMessage, ELogOperationEventAdd,ELogOperationMaintain);
   415 	//
   416 	const TInt function = aMessage.Function();
   417 	//
   418 	const TLogOperationId& operationId = clientServerData.iOperationId;
   419 	#ifdef LOGGING_ENABLED
   420 	const TLogOperationType& operationType = clientServerData.iOperationType;
   421 	#endif
   422 	LOGTEXT4("CLogServSession::ServiceOperationFunctionL() - Operation function for client %S: Id: %d, Type: %d", &iClientThreadName, operationId, operationType);
   423 	//
   424 	switch(function)
   425 		{
   426 	case ELogOperationGetResult:
   427 		LOGTEXT("CLogServSession::ServiceOperationFunctionL() - getting result");
   428 		iOperationManager.OMGetResultL(operationId, iSessionId, aMessage);
   429 		aMessage.Complete(KErrNone);
   430 		break;
   431 	case ELogOperationCancel:
   432 		LOGTEXT("CLogServSession::ServiceOperationFunctionL() - cancelling");
   433 		iOperationManager.OMCancel(operationId, iSessionId, ETrue);
   434 		aMessage.Complete(KErrCancel);
   435 		break;
   436 	case ELogOperationInitiate:
   437 		LOGTEXT("CLogServSession::ServiceOperationFunctionL() - initiating");
   438 		// Create operation. Operations are owned by the operation manager (they are added to a queue)
   439 		// when the objects are created, so this does not leak any memory.
   440 		CLogServOperationBase* operation = LogServFactory::NewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId);
   441 		(void) operation;
   442 		break;
   443 		}
   444 	LOGTEXT("CLogServSession::ServiceOperationFunctionL() - end");
   445 	}
   446 
   447 void CLogServSession::ExtendedNotifyCompleteL(TInt aCompletionCode)
   448 	{
   449 	const TInt count = iPendingGlobalChanges.Count();
   450     if	(iExtendedNotificationMessage != RMessage2() && (count || aCompletionCode < KErrNone))
   451 		{
   452 		if	(aCompletionCode >= KErrNone && count)
   453 			{
   454 			const TLogServDatabaseChangeDefinition& change = iPendingGlobalChanges[0];
   455 			//
   456 			const TPckgBuf<TInt> pContext(change.iChangeType.iUid);
   457 			const TPckg<TInt> pParam1(change.iChangeParam1);
   458 			const TPckg<TInt> pParam2(change.iChangeParam2);
   459 			const TPckg<TInt> pParam3(change.iChangeParam3);
   460 			//
   461 			iExtendedNotificationMessage.WriteL(0, pContext);
   462 			iExtendedNotificationMessage.WriteL(1, pParam1);
   463 			iExtendedNotificationMessage.WriteL(2, pParam2);
   464 			iExtendedNotificationMessage.WriteL(3, pParam3);
   465 			//
   466 			iPendingGlobalChanges.Remove(0);
   467 			}
   468 		//
   469 		iExtendedNotificationMessage.Complete(aCompletionCode);
   470 		}
   471 	}