diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/LogServ/src/logservsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loggingservices/eventlogger/LogServ/src/logservsession.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,470 @@ +// 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 "logservsession.h" +#include "LogNotify.h" +#include "LogServServer.h" +#include "logservpanic.h" +#include "LogServView.h" +#include "LogServOperationBase.h" +#include "LogServBackupInterface.h" +#include "LogServOperationFactory.h" +#include "LogServOperationManager.h" +#include "LogServDatabaseChangeInterface.h" +#include "LogServDatabaseChangeDefinition.h" +#include "LogServSqlStrings.h" + +// Constants +const TInt KLogViewListGranuality = 5; +const TInt KLogServPendingGlobalChangesArrayGranularity = 3; + + +///////////////////////////////////////////////////////////////////////////////////////// +// -----> CLogServSession (source) +///////////////////////////////////////////////////////////////////////////////////////// + +CLogServSession::CLogServSession(TLogServSessionId aSessionId, + MLogServSessionLifetimeObserver& aObserver, + MLogServBackupInterface& aBackupInterface, + MLogServTaskInterface& aTaskInterface, + MLogServOperationManager& aOperationManager, + MLogServDatabaseChangeInterface& aChangeInterface, + MLogServDatabaseTransactionInterface& aDatabase) : + iSessionId(aSessionId), + iObserver(aObserver), + iBackupInterface(aBackupInterface), + iTaskInterface(aTaskInterface), + iOperationManager(aOperationManager), + iChangeInterface(aChangeInterface), + iDatabase(aDatabase), + iViewList(KLogViewListGranuality), + iPendingGlobalChanges(KLogServPendingGlobalChangesArrayGranularity) + { + iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventCreated); + } + +CLogServSession::~CLogServSession() + { + LOGTEXT3("CLogServSession::~CLogServSession() - client logging off: %S, %d", &iClientThreadName, iSessionId); + + iOperationManager.OMCancel(iSessionId, ETrue); + + delete iPackage; + delete iNotify; + + iChangeInterface.DCIRequestChangeNotificationsCancel(*this); + // + iViewList.ResetAndDestroy(); + iViewList.Close(); + iPendingGlobalChanges.Close(); + // + iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventDestroyed); + + LOGTEXT2("CLogServSession::~CLogServSession() - client dead %d", iSessionId); + LOGTEXT(""); + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +void CLogServSession::DCOHandleGlobalChangeEventL(const TLogServDatabaseChangeDefinition& aChange) + { + if (iExtendedNotificationRequested) + User::LeaveIfError(iPendingGlobalChanges.Append(aChange)); + ExtendedNotifyCompleteL(KErrNone); + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +void CLogServSession::CreateL() + { + iPackage = CLogPackage::NewL(); + + // Request change notifications + iChangeInterface.DCIRequestChangeNotificationsL(*this); + } + +// +// Handle a client request. +// +// Leaving is handled by CLogServ::RunError() which reports the error code to the client +// Note: operation add themselves to the server active queue in their constructor +// The server active object owns them and deletes them when necessary +// So the iffy looking code below won't actually leak memory +// +void CLogServSession::ServiceL(const RMessage2& aMessage) + { + LOGTEXT3("CLogServSession::ServiceL(%S, %d)", &iClientThreadName, aMessage.Function()); + + switch(aMessage.Function()) + { + /** + * Overall operation management + */ + case ELogOperationGetResult: + case ELogOperationCancel: + case ELogOperationInitiate: + ServiceOperationFunctionL(aMessage); + break; + + /** + * Notification related + */ + case ELogNotify: + { + if (!iNotify) + { + iNotify = CLogNotify::NewL(iBackupInterface, iChangeInterface, Server().Priority()); + + #ifdef LOGGING_ENABLED + iNotify->SetClientThreadName(iClientThreadName); + #endif + } + + if (!iNotify->IsActive()) + { + const TTimeIntervalMicroSeconds32 delayTime = reinterpret_cast(aMessage.Ptr0()); + + //Validate time value + if(delayTime.Int() < 0) + { + User::Leave(KErrArgument); + } + iNotify->Notify(delayTime, aMessage); + } + else + ::PanicClientL(aMessage, ELogAlreadyActive19); + break; + } + case ELogNotifyCancel: + { + if (iNotify) + iNotify->Cancel(); + aMessage.Complete(KErrCancel); + break; + } + case ELogNotifyExtended: + { + if (iExtendedNotificationMessage == RMessage2()) + { + iExtendedNotificationMessage = aMessage; + iExtendedNotificationRequested = ETrue; + } + else + ::PanicClientL(aMessage, ELogExtendedMessageAlreadyActive); + break; + } + case ELogNotifyExtendedCancel: + { + if (iExtendedNotificationMessage != RMessage2()) + ExtendedNotifyCompleteL(KErrCancel); + // + iExtendedNotificationRequested = EFalse; + iPendingGlobalChanges.Reset(); + iPendingGlobalChanges.GranularCompress(); + // + aMessage.Complete(KErrCancel); + break; + } + + /** + * View functionality + */ + case ELogViewCreate: + case ELogViewDelete: + case ELogViewCount: + case ELogViewOperationInitiate: + case ELogViewChangeNotificationsRequest: + case ELogViewChangeNotificationsCancel: + case ELogViewFetchChanges: + case ELogViewNotifyLockStatusChange: + case ELogViewNotifyLockStatusChangeCancel: + ServiceViewFunctionL(aMessage); + break; + + /** + * Misc. (debug) functionality + */ +#ifdef _DEBUG + case ELogMakeTransient: + { + Server().MakeTransient((TBool)aMessage.Ptr0()); + aMessage.Complete(KErrNone); + break; + } + case ELogIsServerReady: + { + const TBool serverReady = (iBackupInterface.BIErrorValueForCurrentState() == KErrNone); + aMessage.Complete(serverReady); + break; + } + case ELogSetHeapFail: + { + User::__DbgSetAllocFail(RHeap::EUser, RHeap::TAllocFail(aMessage.Int0()),aMessage.Int1()); + aMessage.Complete(KErrNone); + break; + } +#endif// _DEBUG + /** + * Unknown operations + */ + default: + ::PanicClientL(aMessage, ELogIllegalFunction); + break; + } + } + +/** +If aError is KErrBadDescriptor, then panic the client, else - default error handling. +KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad +descriptor to the server. +*/ +void CLogServSession::ServiceError(const RMessage2& aMessage,TInt aError) + { + if(aError == KErrBadDescriptor) + { + //The __LOGPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call + //from a leaving call will terminate the server. + aMessage.Panic(KLogServ, ELogBadDescriptor); + } + CSession2::ServiceError(aMessage, aError); + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +CLogServServer& CLogServSession::Server() const + { + return *static_cast(const_cast(CSession2::Server())); + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + + +CLogServViewBase& CLogServSession::ViewByIdL(TUint32 aViewId) + { + const TInt index = ViewPositionById(aViewId); + User::LeaveIfError(index); + return *iViewList[index]; + } + +TInt CLogServSession::ViewPositionById(TUint32 aViewId) const + { + const TInt count = iViewList.Count(); + for(TInt i=0; i pData(aClientServerData); + aMessage.ReadL(0, pData); + + //Validate Operation Type + if((aClientServerData.iOperationType < aMinOperation) || + (aClientServerData.iOperationType > aMaxOperation)) + { + User::Leave(KErrArgument); + } + } + +void CLogServSession::ServiceViewFunctionL(const RMessage2& aMessage) + { + switch(aMessage.Function()) + { + case ELogViewCreate: + { + iViewList.ReserveL(iViewList.Count() + 1); + // Type is first parameter, view id is second + const TLogViewId id = static_cast(aMessage.Int0()); + const TLogViewType type = static_cast(aMessage.Int1()); + + //Validate type value + if((type < ELogViewTypeEvent)||(type > ELogViewTypeDuplicate)) + { + User::Leave(KErrArgument); + } + + // Ask the factory to create it + CLogServViewBase* view = LogServFactory::NewViewL(type, id, iDatabase, iBackupInterface, *iPackage, aMessage); + TInt err = iViewList.Append(view); + __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved)); + aMessage.Complete(err); + break; + } + case ELogViewDelete: + { + const TLogViewId id = static_cast(aMessage.Int0()); + TInt indexAndError = ViewPositionById(id); + if (indexAndError >= 0) + { + delete iViewList[indexAndError]; + iViewList.Remove(indexAndError); + indexAndError = KErrNone; + } + aMessage.Complete(indexAndError); + break; + } + case ELogViewCount: + { + const TLogViewId id = static_cast(aMessage.Int0()); + CLogServViewBase& view = ViewByIdL(id); + const TInt count = view.Count(); + aMessage.Complete(count); + break; + } + case ELogViewOperationInitiate: + { + // We don't allow any operations during a backup + iBackupInterface.BIValidateStateForDatabaseOperationL(); + // + TLogClientServerData clientServerData; + ReadClientServerDataL(clientServerData,aMessage, + ELogOperationViewSetup, ELogOperationViewWindowFetch); + + // + const TLogViewId id = static_cast(aMessage.Int1()); + CLogServViewBase& view = ViewByIdL(id); + + // Create operation. Operations are owned by the operation manager (they are added to a queue) + // when the objects are created, so this does not leak any memory. + CLogServOperationBase* operation = LogServFactory::NewViewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId, view); + (void) operation; + break; + } + case ELogViewChangeNotificationsRequest: + { + const TLogViewId id = static_cast(aMessage.Int0()); + CLogServViewBase& view = ViewByIdL(id); + view.RequestChangeNotifications(aMessage); + break; + } + case ELogViewChangeNotificationsCancel: + { + const TLogViewId id = static_cast(aMessage.Int0()); + CLogServViewBase& view = ViewByIdL(id); + view.RequestChangeNotificationsCancel(); + aMessage.Complete(KErrNone); + break; + } + case ELogViewFetchChanges: + { + const TLogViewId id = static_cast(aMessage.Int0()); + CLogServViewBase& view = ViewByIdL(id); + view.RequestChangesL(aMessage); + aMessage.Complete(KErrNone); + break; + } + case ELogViewNotifyLockStatusChange: + { + const TLogViewId id = static_cast(aMessage.Int0()); + CLogServViewBase& view = ViewByIdL(id); + view.RequestLockStatusChanges(aMessage); + break; + } + case ELogViewNotifyLockStatusChangeCancel: + { + const TLogViewId id = static_cast(aMessage.Int0()); + CLogServViewBase& view = ViewByIdL(id); + view.RequestLockStatusChangesCancel(); + aMessage.Complete(KErrNone); + break; + } + } + } + +void CLogServSession::ServiceOperationFunctionL(const RMessage2& aMessage) + { + // We don't allow any operations during a backup + iBackupInterface.BIValidateStateForDatabaseOperationL(); + // + TLogClientServerData clientServerData; + ReadClientServerDataL(clientServerData,aMessage, ELogOperationEventAdd,ELogOperationMaintain); + // + const TInt function = aMessage.Function(); + // + const TLogOperationId& operationId = clientServerData.iOperationId; + #ifdef LOGGING_ENABLED + const TLogOperationType& operationType = clientServerData.iOperationType; + #endif + LOGTEXT4("CLogServSession::ServiceOperationFunctionL() - Operation function for client %S: Id: %d, Type: %d", &iClientThreadName, operationId, operationType); + // + switch(function) + { + case ELogOperationGetResult: + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - getting result"); + iOperationManager.OMGetResultL(operationId, iSessionId, aMessage); + aMessage.Complete(KErrNone); + break; + case ELogOperationCancel: + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - cancelling"); + iOperationManager.OMCancel(operationId, iSessionId, ETrue); + aMessage.Complete(KErrCancel); + break; + case ELogOperationInitiate: + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - initiating"); + // Create operation. Operations are owned by the operation manager (they are added to a queue) + // when the objects are created, so this does not leak any memory. + CLogServOperationBase* operation = LogServFactory::NewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId); + (void) operation; + break; + } + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - end"); + } + +void CLogServSession::ExtendedNotifyCompleteL(TInt aCompletionCode) + { + const TInt count = iPendingGlobalChanges.Count(); + if (iExtendedNotificationMessage != RMessage2() && (count || aCompletionCode < KErrNone)) + { + if (aCompletionCode >= KErrNone && count) + { + const TLogServDatabaseChangeDefinition& change = iPendingGlobalChanges[0]; + // + const TPckgBuf pContext(change.iChangeType.iUid); + const TPckg pParam1(change.iChangeParam1); + const TPckg pParam2(change.iChangeParam2); + const TPckg pParam3(change.iChangeParam3); + // + iExtendedNotificationMessage.WriteL(0, pContext); + iExtendedNotificationMessage.WriteL(1, pParam1); + iExtendedNotificationMessage.WriteL(2, pParam2); + iExtendedNotificationMessage.WriteL(3, pParam3); + // + iPendingGlobalChanges.Remove(0); + } + // + iExtendedNotificationMessage.Complete(aCompletionCode); + } + }