harvester/common/src/harvestereventmanager.cpp
changeset 0 c53acadfccc6
child 8 6752808b2036
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harvester/common/src/harvestereventmanager.cpp	Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,460 @@
+/*
+* 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:  
+ *
+*/
+#include <e32svr.h>
+
+#include "harvestereventmanager.h"
+#include "harvesterlog.h"
+
+const TInt KHarvesterEventManagerTLSKey = 0x200104D9;
+
+CHarvesterEventManager::CHarvesterEventManager()
+	{
+	}
+
+void CHarvesterEventManager::ConstructL()
+	{
+	}
+
+CHarvesterEventManager::~CHarvesterEventManager()
+	{
+	for ( TInt i = 0; i < iEventQueues.Count(); i++)
+		{
+		iEventQueues[i]->Close();
+		}
+	iEventQueues.ResetAndDestroy();
+	iEventQueues.Close();
+	
+	iRegisteredObservers.ResetAndDestroy();
+	iRegisteredObservers.Close();
+	
+	iEventStatuses.Close();
+	}
+
+EXPORT_C CHarvesterEventManager* CHarvesterEventManager::GetInstanceL()
+	{
+	WRITELOG( "CHarvesterEventManager::GetInstanceL" );
+
+	CHarvesterEventManagerStaticData* data = 
+		static_cast<CHarvesterEventManagerStaticData*>( 
+				UserSvr::DllTls( KHarvesterEventManagerTLSKey ) );
+
+	CHarvesterEventManager* instance = NULL;
+
+	if ( !data )
+        {
+        instance = new (ELeave) CHarvesterEventManager();
+        CleanupStack::PushL( instance );
+        instance->ConstructL();
+        UserSvr::DllSetTls( KHarvesterEventManagerTLSKey,
+        	new (ELeave) CHarvesterEventManagerStaticData(instance) );
+        CleanupStack::Pop( instance );
+        }
+    else
+        {
+        instance = data->iHEM;
+        data->iRefCount++;
+        }
+
+    return instance;
+	}
+
+EXPORT_C void CHarvesterEventManager::ReleaseInstance()
+    {
+    WRITELOG( "CHarvesterEventManager::ReleaseInstance" );
+    CHarvesterEventManagerStaticData* data =
+        static_cast<CHarvesterEventManagerStaticData*>( 
+        		UserSvr::DllTls( KHarvesterEventManagerTLSKey ) );
+    if ( data )
+        {
+        data->iRefCount--;
+        if ( data->iRefCount <= 0 )
+            {
+            // destroy the singleton and free TLS
+            delete data;
+            UserSvr::DllFreeTls( KHarvesterEventManagerTLSKey );
+            }
+        }
+    }
+
+EXPORT_C void CHarvesterEventManager::IncreaseItemCount( 
+		HarvesterEventObserverType aHEObserverType, TUint aCount )
+	{
+	TEventStatus* eventStatus = GetEventStatus( aHEObserverType );
+	WRITELOG2( "CHarvesterEventManager::IncreaseItemCount(%d) type = %d", aCount, aHEObserverType); 
+	
+#ifdef _DEBUG
+	switch(aHEObserverType)
+	    {
+	    case EHEObserverTypePlaceholder:
+	        WRITELOG( "CHarvesterEventManager::IncreaseItemCount() EHEObserverTypePlaceholder");
+	        break;
+	    case EHEObserverTypeMMC:
+	        WRITELOG( "CHarvesterEventManager::IncreaseItemCount() EHEObserverTypeMMC");
+	        break;
+	    case EHEObserverTypeOverall:
+	        WRITELOG( "CHarvesterEventManager::IncreaseItemCount() EHEObserverTypeOverall");
+	        break;
+	    default:
+	        WRITELOG( "CHarvesterEventManager::IncreaseItemCount() Unknown type!");
+	    };
+#endif
+	
+	if( eventStatus )
+		{
+		WRITELOG1( "CHarvesterEventManager::IncreaseItemCount() itemsleft = %d old ", eventStatus->iItemsLeft);
+		eventStatus->iItemsLeft += aCount;
+		WRITELOG1( "CHarvesterEventManager::IncreaseItemCount() itemsleft = %d ", eventStatus->iItemsLeft);
+		}
+	else
+		{
+		TEventStatus eventStatus;
+		eventStatus.iCurrentState = EHEStateStarted;
+		WRITELOG1( "CHarvesterEventManager::IncreaseItemCount() itemsleft = %d old", aCount);
+		eventStatus.iItemsLeft = aCount;
+		WRITELOG1( "CHarvesterEventManager::IncreaseItemCount() itemsleft = %d ", aCount);
+		eventStatus.iObserverType = aHEObserverType;
+		iEventStatuses.Append( eventStatus );
+		}
+	}
+
+EXPORT_C TBool CHarvesterEventManager::DecreaseItemCountL( 
+		HarvesterEventObserverType aHEObserverType, TUint aCount )
+	{
+	TEventStatus* eventStatus = GetEventStatus( aHEObserverType );
+	WRITELOG2( "CHarvesterEventManager::DecreaseItemCountL(%d) type = %d ", aCount, aHEObserverType);
+	
+#ifdef _DEBUG
+    switch(aHEObserverType)
+        {
+        case EHEObserverTypePlaceholder:
+            WRITELOG( "CHarvesterEventManager::DecreaseItemCountL() EHEObserverTypePlaceholder");
+            break;
+        case EHEObserverTypeMMC:
+            WRITELOG( "CHarvesterEventManager::DecreaseItemCountL() EHEObserverTypeMMC");
+            break;
+        case EHEObserverTypeOverall:
+            WRITELOG( "CHarvesterEventManager::DecreaseItemCountL() EHEObserverTypeOverall");
+            break;
+        default:
+            WRITELOG( "CHarvesterEventManager::DecreaseItemCountL() Unknown type!");
+        };
+#endif
+	
+	if( eventStatus )
+		{
+		WRITELOG1( "CHarvesterEventManager::DecreaseItemCountL() iItemsLeft = %d old", eventStatus->iItemsLeft);
+		TUint newCount = eventStatus->iItemsLeft - aCount;
+
+		// check for wrap
+		if( newCount > eventStatus->iItemsLeft )
+			{
+			newCount = 0;
+			}
+
+		// event doesn't need to be sent, if count hasn't changed 
+		if( newCount == eventStatus->iItemsLeft )
+			{
+			return EFalse;
+			}
+
+		eventStatus->iItemsLeft = newCount;
+		}
+	else
+		{
+		return EFalse;
+		}
+
+	WRITELOG1( "CHarvesterEventManager::DecreaseItemCountL() iItemsLeft = %d", eventStatus->iItemsLeft );
+	
+	// send finished event to all matching observers
+	if ( eventStatus->iItemsLeft <= 0 )
+		{
+		eventStatus->iItemsLeft = 0;
+		eventStatus->iCurrentState = EHEStateFinished;
+
+		// EHEObserverTypeOverall state is handled directly in harvesterao during harvesting
+        if( aHEObserverType != EHEObserverTypeOverall )
+		    {
+		    const TInt err = SendEventL( aHEObserverType, eventStatus->iCurrentState, eventStatus->iItemsLeft );
+		    return err == KErrNone;
+		    }
+		}
+
+	// still harvesting
+	eventStatus->iCurrentState = EHEStateHarvesting;
+	
+	// send harvesting event to all matching observers
+	TBool wasSent = EFalse;
+	TInt count = iRegisteredObservers.Count();
+	for ( TInt i = count; --i >= 0; )
+		{
+		THarvesterEventObserverInfo& observer = *(iRegisteredObservers[i]);
+
+		if( CheckObserverType( observer.iObserverType, aHEObserverType ) )
+			{
+			observer.iDelta += aCount;
+
+			// observers interval full
+			if ( observer.iDelta >= observer.iNotificationInterval )
+				{
+				TInt err = SendSingleEvent( observer, aHEObserverType, 
+						eventStatus->iCurrentState, eventStatus->iItemsLeft );
+				if ( err == KErrNone )
+					{
+					wasSent = ETrue;
+					}
+				}
+			}
+		}
+
+	return wasSent;
+	}
+
+TInt CHarvesterEventManager::SendSingleEvent( 
+		THarvesterEventObserverInfo& aEventObserverInfo, 
+		HarvesterEventObserverType aObserverType, 
+		HarvesterEventState aEventState, TUint aItemsLeft )
+	{
+	aEventObserverInfo.iDelta = 0;
+
+	THarvesterEventNotification notification;
+	notification.iObserverId = aEventObserverInfo.iObserverId;
+	notification.iObserverType = aObserverType;
+	notification.iCurrentState = aEventState;
+	notification.iItemsLeft = aItemsLeft;
+
+	THarvesterEventQueue& eventQueue = *(aEventObserverInfo.iQueuePtr);
+	TInt err = eventQueue.Send( notification );
+	return err;
+	}
+
+EXPORT_C TUint CHarvesterEventManager::ItemCount( 
+		HarvesterEventObserverType aHEObserverType )
+	{
+	TEventStatus* eventStatus = GetEventStatus( aHEObserverType );
+	if( eventStatus )
+		{
+		return eventStatus->iItemsLeft;
+		}
+	
+	return 0;
+	}
+
+EXPORT_C TInt CHarvesterEventManager::SendEventL( 
+		HarvesterEventObserverType aHEObserverType,
+		HarvesterEventState aHEState, TUint aItemsLeft )
+	{
+	TEventStatus* eventStatus = GetEventStatus( aHEObserverType );
+	if( eventStatus )
+		{
+		eventStatus->iCurrentState = aHEState;
+		}
+
+	THarvesterEventNotification notification;
+	notification.iObserverType = aHEObserverType;
+	notification.iCurrentState = aHEState;
+	notification.iItemsLeft = aItemsLeft;
+
+	TInt err = KErrNone;
+	TInt count = iRegisteredObservers.Count();
+	for ( TInt i = count; --i >= 0; )
+		{
+		THarvesterEventObserverInfo& observer = *(iRegisteredObservers[i]);
+
+		if( CheckObserverType( observer.iObserverType, aHEObserverType ) )
+			{
+			notification.iObserverId = observer.iObserverId;
+
+			THarvesterEventQueue& eventQueue = *(observer.iQueuePtr);
+			TInt sendErr = eventQueue.Send( notification );
+			// Take first error
+			if( err == KErrNone )
+				{
+				err = sendErr;
+				}
+			}
+		}
+	return err;
+	}
+
+EXPORT_C void CHarvesterEventManager::RegisterEventObserverL( const RMessage2& aMessage )
+	{
+	THarvesterEventObserverInfo* observerInfo = new (ELeave) THarvesterEventObserverInfo;
+	CleanupStack::PushL( observerInfo );
+
+    TPckg<THarvesterEventObserverInfo> pckgObserverInfo( *observerInfo );
+    TInt err = aMessage.Read( 0, pckgObserverInfo );
+
+    // Init server side values
+    observerInfo->iQueuePtr = NULL;
+    observerInfo->iDelta = 0;
+    observerInfo->iProcessUid = aMessage.Identity().iUid;
+
+    // Check if observer ID is not yet used
+    // and if event queue already exists
+    TBool found = EFalse;
+	for(TInt i = iRegisteredObservers.Count(); --i >= 0;)
+		{
+		THarvesterEventObserverInfo* info = iRegisteredObservers[i];
+		if( info->iProcessUid == observerInfo->iProcessUid && 
+			info->iQueueHandle == observerInfo->iQueueHandle )
+			{
+			if( info->iObserverId == observerInfo->iObserverId )
+				{
+				User::Leave( KErrAlreadyExists );
+				}
+
+			observerInfo->iQueuePtr = info->iQueuePtr;
+			found = ETrue;
+			}
+		}
+
+	// create new event queue if no match was found 
+	if ( !found )
+		{
+		THarvesterEventQueue* msgQueue = new (ELeave) THarvesterEventQueue;
+		CleanupStack::PushL( msgQueue );
+
+		TInt err = msgQueue->Open( aMessage, 1 );
+
+		User::LeaveIfError( err );
+
+		iEventQueues.AppendL( msgQueue );
+		observerInfo->iQueuePtr = msgQueue;
+		
+		CleanupStack::Pop( msgQueue );
+		}	
+
+	iRegisteredObservers.AppendL( observerInfo );
+
+	CleanupStack::Pop( observerInfo );
+	
+	// send event if register is coming in the middle of harvesting
+	for( TInt i = iEventStatuses.Count(); --i >= 0; )
+		{
+		TEventStatus& eventStatus = iEventStatuses[i];
+		if( CheckObserverType( observerInfo->iObserverType, 
+				eventStatus.iObserverType) )
+			{
+			if( eventStatus.iItemsLeft > 0 )
+				{
+				TRAP_IGNORE( SendEventL( eventStatus.iObserverType, 
+						eventStatus.iCurrentState, eventStatus.iItemsLeft ) );
+				}
+			}
+		}
+	}
+
+EXPORT_C TInt CHarvesterEventManager::UnregisterEventObserver( const RMessage2& aMessage )
+	{
+	TUint observerId = (TUint)aMessage.Int0();
+	TInt queueHandle = aMessage.Int1();
+
+	TInt serverQueueHandle = KNullHandle;
+	TUint processUid = aMessage.Identity().iUid;
+	
+	TBool otherObserverFound = EFalse;
+	for(TInt i = iRegisteredObservers.Count(); --i >= 0;)
+		{
+		THarvesterEventObserverInfo* observer = iRegisteredObservers[i];
+		if( observer->iProcessUid == processUid && 
+			observer->iQueueHandle == queueHandle )
+			{
+			// Remove registered observer
+			if( observer->iObserverId == observerId )
+				{
+				serverQueueHandle = observer->iQueuePtr->Handle();
+				
+				iRegisteredObservers.Remove( i );
+				delete observer;
+				}
+			// Find if any other observer is using the same queue
+			else
+				{
+				otherObserverFound = ETrue;
+				}
+			}
+		}
+
+	if( serverQueueHandle )
+		{
+		// Remove the queue if removed observer 
+		// was the last observer which used it
+		if( !otherObserverFound )
+			{
+			for(TInt i = iEventQueues.Count(); --i >= 0;)
+				{
+				THarvesterEventQueue* queue = iEventQueues[i];
+				if( queue->Handle() == serverQueueHandle )
+					{
+					iEventQueues.Remove( i );
+					queue->Close();
+					delete queue;
+					break;
+					}
+				}
+			}
+
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+EXPORT_C HarvesterEventState CHarvesterEventManager::CurrentState( 
+		HarvesterEventObserverType aHEObserverType )
+	{
+	TInt count = iEventStatuses.Count();
+	for( TInt i = count; --i >= 0; )
+		{
+		TEventStatus& eventStatus = iEventStatuses[i];
+		if( eventStatus.iObserverType == aHEObserverType )
+			{
+			return eventStatus.iCurrentState;
+			}
+		}
+	return EHEStateUninitialized;
+	}
+
+TBool CHarvesterEventManager::CheckObserverType( TInt aObserverType, TInt aEventType )
+	{
+	return aObserverType & aEventType;
+	}
+
+CHarvesterEventManager::TEventStatus* CHarvesterEventManager::GetEventStatus( 
+		HarvesterEventObserverType aHEObserverType )
+	{
+	TInt count = iEventStatuses.Count();
+	for(TInt i = count; --i >= 0; )
+		{
+		TEventStatus& eventStatus = iEventStatuses[i];
+		if( eventStatus.iObserverType == aHEObserverType )
+			{
+			return &eventStatus;
+			}
+		}
+
+	return NULL;
+	}
+
+EXPORT_C TUint CHarvesterEventManager::GetLastClientId()
+	{
+	// deprecated method, just return something
+	return 0;
+	}