diff -r 000000000000 -r dfb7c4ff071f commsconfig/commsdatabaseshim/commdbshim/Notifier/src/NotifierServ.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsconfig/commsdatabaseshim/commdbshim/Notifier/src/NotifierServ.CPP Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,546 @@ +// Copyright (c) 2006-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: +// + +/** + @file + @deprecated since v9.1. Functionality is replaced with commsdat. +*/ + +#include +#include + +#include +#include "NotifierServ.H" + +const TInt noPendingEvents = -1; + +void InitL() + { + RProcess().SetPriority(EPriorityHigh); + CCommsdatNotifierScheduler* pA = new(ELeave) CCommsdatNotifierScheduler(); + CActiveScheduler::Install(pA); + pA->iServer = CCommsdatNotifierServer::NewL(); + } + +/** +CCommsdatNotifier server process entry point +*/ +TInt E32Main() + { + __UHEAP_MARK; + TInt ret = KErrNone; + + CTrapCleanup* cleanup=CTrapCleanup::New(); + if (cleanup==NULL) + { + ret=KErrNoMemory; + } + + if (ret==KErrNone) + { + TRAP(ret,InitL()); + } + + RProcess::Rendezvous(ret); + + if (ret==KErrNone) + { + CActiveScheduler::Start(); + } + + + delete CActiveScheduler::Current(); + delete cleanup; + + __UHEAP_MARKEND; + + return ret; + } + + + +//********************************** +//CCommsdatNotifierServer +//********************************** + +CCommsdatNotifierServer::CCommsdatNotifierServer() + : CServer2(EPriorityHigh, EGlobalSharableSessions) + { + } + +CCommsdatNotifierServer* CCommsdatNotifierServer::NewL() +// Create and start a new count server + { + CCommsdatNotifierServer* self = new(ELeave) CCommsdatNotifierServer; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CCommsdatNotifierServer::ConstructL() + { + iShutdownWatchDog = CShutdownWatchDog::NewL(*this); + StartL(COMMSDATNOTIFIER_SERVER_NAME); + } + +CCommsdatNotifierServer::~CCommsdatNotifierServer() + { + delete iShutdownWatchDog; + } + +void CCommsdatNotifierServer::IncrementSessionCount() + { + iSessionCount++; + } + +void CCommsdatNotifierServer::DecrementSessionCount() + { + iSessionCount--; + if (iSessionCount<=0) + { + iShutdownWatchDog->Cancel(); //Cancel any outstanding request and start again + iShutdownWatchDog->StartShutdown(); + } + } + +void CCommsdatNotifierServer::MaybeShutDown() + { + if (iSessionCount<=0) + { + CActiveScheduler::Stop(); + } + } + +CSession2* CCommsdatNotifierServer::NewSessionL(const TVersion &aVersion, const RMessage2& /*aMessage*/) const +// Create a new server session - check we're the right version and make session + { + TVersion v(KCommsdatNotifierMajorVersionNumber,KCommsdatNotifierMinorVersionNumber,KCommsdatNotifierBuildVersionNumber); + + TBool r=User::QueryVersionSupported(v,aVersion); + if (r==EFalse) + { + User::Leave(KErrNotSupported); + } + + TBool clientSpecialVersion = (aVersion.iBuild==KCommsdatNotifierSpecialBuildVersionNumber); + + return CCommsdatNotifierSession::NewL((CCommsdatNotifierServer*)this, clientSpecialVersion); + } + + +//********************************** +//CCommsdatNotifierSession +//********************************** + +CCommsdatNotifierSession* CCommsdatNotifierSession::NewL(CCommsdatNotifierServer* aServer, TBool aClientSpecialVersion) + { + CCommsdatNotifierSession* thisptr = new(ELeave) CCommsdatNotifierSession(aServer); + CleanupStack::PushL(thisptr); + thisptr->ConstructL(aClientSpecialVersion); + CleanupStack::Pop(thisptr); + return thisptr; + } + +void CCommsdatNotifierSession::ConstructL(TBool aClientSpecialVersion) + { + if (aClientSpecialVersion) + iNotifierHandler = CCommsdatNotifierSessionHandler2::NewL(); + else + iNotifierHandler = CCommsdatNotifierSessionHandler::NewL(); + } + +CCommsdatNotifierSession::CCommsdatNotifierSession(CCommsdatNotifierServer* aServer) + : iNotifierSvr(aServer) + { + iNotifierSvr->IncrementSessionCount(); + } + +CCommsdatNotifierSession::~CCommsdatNotifierSession() + { + iNotifierSvr->DecrementSessionCount(); + iNotifierHandler->Cancel(); + delete iNotifierHandler; + } + +void CCommsdatNotifierSession::ServiceL(const RMessage2& aMessage) + { + switch (aMessage.Function()) + { + case ERequestNotify: + iNotifierHandler->RegisterNotifyL(aMessage); + break; + case ECancelNotify: + iNotifierHandler->CancelNotify(aMessage); + break; + case ECancelAllNotify: + iNotifierHandler->CancelAllNotify(aMessage); + break; + default: + PanicClient(KErrArgument,aMessage); + break; + } + } +void CCommsdatNotifierSession::PanicClient(TInt aPanic,const RMessage2& aMessage) const +// Panic the client + { + _LIT(KClientFault,"Commdb Shim Notifier Server"); + aMessage.Panic(KClientFault,aPanic); + } + +//********************************** +//CCommsdatNotifierSessionHandlerBase +//********************************** + +void CCommsdatNotifierSessionHandlerBase::ConstructL() + { + TInt err = iProperty.Attach(KUidSystemCategory, KUidCommsDatNotificationEvent.iUid); + User::LeaveIfError(err); + } + +CCommsdatNotifierSessionHandlerBase::CCommsdatNotifierSessionHandlerBase() + : CActive(EPriorityHigh) + { + CActiveScheduler::Add(this); + } + +CCommsdatNotifierSessionHandlerBase::~CCommsdatNotifierSessionHandlerBase() + { + iProperty.Close(); + } + +void CCommsdatNotifierSessionHandlerBase::DoCancel() + { + iProperty.Cancel(); + } + +void CCommsdatNotifierSessionHandlerBase::CompleteMessage(const RMessage2& aMessage,TInt aVal) + { + if(!aMessage.IsNull()) + { + aMessage.Complete(aVal); + } + } + +//********************************** +//CCommsdbNotifierSessionHandler +//********************************** + +CCommsdatNotifierSessionHandler* CCommsdatNotifierSessionHandler::NewL() + { + CCommsdatNotifierSessionHandler* self = new(ELeave) CCommsdatNotifierSessionHandler; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CCommsdatNotifierSessionHandler::ConstructL() + { + CCommsdatNotifierSessionHandlerBase::ConstructL(); + } + +void CCommsdatNotifierSessionHandler::RegisterNotifyL(const RMessage2& aMessage) + { + // if there is already an outstanding request, complete + // immediately with an error + + if (! iMessage.IsNull()) + { + aMessage.Complete(KErrServerBusy); + return; + } + + // there are no outstanding requests + + // if there is already a pending event, complete immediately + if (iPendingEvent > noPendingEvents) + { + aMessage.Complete(iPendingEvent); + // reset iPendingEvent + iPendingEvent = noPendingEvents; + return; + } + + // there are no outstanding events (iPendingEvent == noPendingEvents) + + iMessage = aMessage; + + if (!IsActive()) + { + iProperty.Subscribe(iStatus); + SetActive(); + } + } + +CCommsdatNotifierSessionHandler::CCommsdatNotifierSessionHandler() + : CCommsdatNotifierSessionHandlerBase(), iPendingEvent(noPendingEvents) + { + } + +CCommsdatNotifierSessionHandler::~CCommsdatNotifierSessionHandler() + { + } + +void CCommsdatNotifierSessionHandler::CancelNotify(const RMessage2& aMessage) + { + Cancel(); + iPendingEvent = noPendingEvents; + + // Complete outstanding async request for notification + CompleteMessage(iMessage, KErrCancel); + + // Complete the cancel message + CompleteMessage(aMessage, KErrNone); + } + +void CCommsdatNotifierSessionHandler::CancelAllNotify(const RMessage2& aMessage) + { + CancelNotify(aMessage); + } + +void CCommsdatNotifierSessionHandler::RunL() + { + TInt stat = iStatus.Int(); +// according to the present Symbian Publish and Subscribe API +// documentation and implementation, the following code should ensure +// that further events are not missed during RunL + iProperty.Subscribe(iStatus); + SetActive(); + + if (stat == KErrNone) + { + // use stat for storing the new event + User::LeaveIfError(iProperty.Get(KUidSystemCategory, KUidCommsDatNotificationEvent.iUid, stat)); + + if (iMessage.IsNull()) + { + // if the client is not ready to receive notifications, + // store the new event in iPendingEvent, + //but check first if it is more important than the current + //pending event (if there is one) + if (stat > iPendingEvent) + { + iPendingEvent = stat; + } + } + else + { + // if the client is ready to receive notifications, complete + + if (iPendingEvent > noPendingEvents) + { + // if there is a pending event + + // complete with the new event, if it is more + // important than the pending event + if (stat > iPendingEvent) + { + iMessage.Complete(stat); + iPendingEvent = stat; + } + // otherwise complete with the pending event + else + { + iMessage.Complete(iPendingEvent); + } + } + else + { + iMessage.Complete(stat); + iPendingEvent = stat; + } + } + } + else + { + if (!iMessage.IsNull()) + { + // if there is a pending event, complete immediately + if (iPendingEvent > noPendingEvents) + { + iMessage.Complete(iPendingEvent); + } + else + { + // otherwise, complete with error + iMessage.Complete(stat); + } + } + } + } + +TInt CCommsdatNotifierSessionHandler::RunError(TInt aError) + { + CompleteMessage(iMessage,aError); + return KErrNone; + } + +//********************************** +//CCommsdatNotifierSessionHandler2 +//********************************** + +CCommsdatNotifierSessionHandler2* CCommsdatNotifierSessionHandler2::NewL() + { + CCommsdatNotifierSessionHandler2* self = new(ELeave) CCommsdatNotifierSessionHandler2; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CCommsdatNotifierSessionHandler2::ConstructL() + { + CCommsdatNotifierSessionHandlerBase::ConstructL(); + + iMessagePool = new(ELeave)CArrayFixFlat(5); + } + +void CCommsdatNotifierSessionHandler2::CompleteRequests(TInt aErrorCode) + { + for (TInt i = iMessagePool->Count() ; i > 0 ; i--) + { + CompleteMessage(iMessagePool->At(i - 1), aErrorCode); + } + iMessagePool->Reset(); + } + + +void CCommsdatNotifierSessionHandler2::ResetRequestVector() + { + iMessagePool->Reset(); + } + + +void CCommsdatNotifierSessionHandler2::RegisterNotifyL(const RMessage2& aMessage) + { + for (TInt i = iMessagePool->Count() ; i > 0 ; i--) + { + if (iMessagePool->At(i - 1).ClientStatus()==aMessage.ClientStatus()) + { + // do nothing we already have this outstanding request + return; + } + } + + iMessagePool->AppendL(aMessage); + + if (!IsActive()) + { + iProperty.Subscribe(iStatus); + SetActive(); + } + } + +CCommsdatNotifierSessionHandler2::CCommsdatNotifierSessionHandler2() + : CCommsdatNotifierSessionHandlerBase() + { + } + +CCommsdatNotifierSessionHandler2::~CCommsdatNotifierSessionHandler2() + { + ResetRequestVector(); + delete iMessagePool; + } + +void CCommsdatNotifierSessionHandler2::CancelNotify(const RMessage2& aMessage) +/** +Cancel a previously registered notification. + +@param aMessage the cancel notification request. Ptr0() identifies the notification to +cancel and contains the address of its TRequestStatus. +*/ + + { + for (TInt i = iMessagePool->Count() ; i > 0 ; i--) + { + if (iMessagePool->At(i - 1).ClientStatus() == aMessage.Ptr0()) + { + CompleteMessage(iMessagePool->At(i - 1), KErrCancel); // complete the registered notification + iMessagePool->Delete(i - 1); + break; + } + } + + aMessage.Complete(KErrNone); // complete the cancel notification + } + +void CCommsdatNotifierSessionHandler2::CancelAllNotify(const RMessage2& aMessage) + { + iProperty.Cancel(); + CompleteRequests(KErrCancel); + aMessage.Complete(KErrCancel); + } + +void CCommsdatNotifierSessionHandler2::RunL() + { + TInt stat = iStatus.Int(); + iProperty.Subscribe(iStatus); + SetActive(); + + CompleteRequests(stat); + } + +TInt CCommsdatNotifierSessionHandler2::RunError(TInt aError) + { + CompleteRequests(aError); + return KErrNone; + } + +//********************************** +//CShutdownWatchDog +//********************************** +const TInt KNotifierServerShutdownLatencyMicroSeconds = 30 * 1000 * 1000; + +CShutdownWatchDog::CShutdownWatchDog(CCommsdatNotifierServer& aNotifierServer) + :CTimer(EPriorityStandard),iNotifierServer(aNotifierServer) + { + } + +void CShutdownWatchDog::StartShutdown() +/** +Queue ourselves to shut this server down after a suitable delay. +*/ + { + if (!IsAdded()) + { + CActiveScheduler::Add(this); + } + if(!IsActive()) + { + After(KNotifierServerShutdownLatencyMicroSeconds); + } + } + +void CShutdownWatchDog::RunL() +/** +Call the server to shut itself down - this will do nothing if there are active sessions. +*/ + { + iNotifierServer.MaybeShutDown(); + } + +CShutdownWatchDog* CShutdownWatchDog::NewL(CCommsdatNotifierServer& aNotifierServer) + { + CShutdownWatchDog* self=new CShutdownWatchDog(aNotifierServer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + + +