commsconfig/commsdatabaseshim/commdbshim/Notifier/src/NotifierServ.CPP
changeset 0 dfb7c4ff071f
--- /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 <c32comm.h>
+#include <e32svr.h>
+
+#include <commsdat.h>
+#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<RMessage2>(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;
+	}
+        
+        
+        	
+