sysstatemgmt/systemstatemgr/ssm/src/ssmswptransitionscheduler.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstatemgr/ssm/src/ssmswptransitionscheduler.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,223 @@
+// Copyright (c) 2007-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 <ssm/ssmswppolicy.h>
+
+#include "ssmdebug.h"
+#include "ssmswptransitionengine.h"
+#include "ssmswptransitionscheduler.h"
+#include "ssmswpindividualtransitionscheduler.h"
+
+//
+//Construction/Destruction
+//
+
+
+/**
+Create a scheduler
+*/
+CSsmSwpTransitionScheduler* CSsmSwpTransitionScheduler::NewL()
+	{
+	CSsmSwpTransitionScheduler* self = NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CSsmSwpTransitionScheduler* CSsmSwpTransitionScheduler::NewLC()
+	{
+	CSsmSwpTransitionScheduler* self = new (ELeave) CSsmSwpTransitionScheduler();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+void CSsmSwpTransitionScheduler::ConstructL()
+	{
+	CTimer::ConstructL();
+	CActiveScheduler::Add(this);
+	}
+
+LOCAL_C TInt OrderingFunction(const CSsmSwpIndividualTransitionScheduler& aLhs, const CSsmSwpIndividualTransitionScheduler& aRhs)
+	{
+	return aLhs.SwpKey() - aRhs.SwpKey();
+	}
+
+LOCAL_C TInt SearchingFunction(const TUint* aUint, const CSsmSwpIndividualTransitionScheduler& aObject)
+	{
+	return *aUint - aObject.SwpKey();
+	}
+
+CSsmSwpTransitionScheduler::CSsmSwpTransitionScheduler()
+: CTimer(CActive::EPriorityStandard),
+  iLinearOrder(&OrderingFunction)
+	{
+	
+	}
+
+/**
+Deactivate
+Destroy queue
+*/
+CSsmSwpTransitionScheduler::~CSsmSwpTransitionScheduler()
+	{
+	CTimer::Cancel();
+	iIndividualTransitionSchedulers.ResetAndDestroy();
+	}
+
+/**
+Take ownership of the transition engine and prepare it to run
+@param aEngine - the engine to run
+*/
+void CSsmSwpTransitionScheduler::SubmitL(CSsmSwpTransitionEngine* aEngine)
+	{
+	if(!aEngine)
+		{
+		SSMLOGLEAVE(KErrArgument); //lint !e527 Suppress Unreachable. Lint is just confused by macro, warning goes away when code in macro gets expanded
+		}
+	CSsmSwpIndividualTransitionScheduler* scheduler = FindScheduler(aEngine);
+	if(scheduler == NULL)
+		{
+		// No scheduler already for this SwP, need to create one
+		scheduler = CSsmSwpIndividualTransitionScheduler::NewLC(aEngine->TransitionValue().Key(), aEngine->CleSessionProxy(), *this);
+		iIndividualTransitionSchedulers.InsertInOrderL(scheduler, iLinearOrder);
+		CleanupStack::Pop(scheduler);
+		// Submit the request
+		scheduler->SubmitL(aEngine);
+		}
+	else
+		{
+		// Already have a scheduler for this session so submit it
+		scheduler->SubmitL(aEngine);
+		}
+	}
+
+void CSsmSwpTransitionScheduler::Cancel(CSession2* aSession)
+	{
+	// Iterate through the array informing all schedulers of the cancel
+	TInt count = iIndividualTransitionSchedulers.Count();
+	for(TInt i = 0; i < count; ++i)
+		{
+		iIndividualTransitionSchedulers[i]->Cancel(aSession);
+		}
+	}
+
+CSsmSwpIndividualTransitionScheduler* CSsmSwpTransitionScheduler::FindScheduler(CSsmSwpTransitionEngine* aEngine)
+	{
+	TInt offset = iIndividualTransitionSchedulers.FindInOrder(aEngine->TransitionValue().Key(), &SearchingFunction);
+	if(offset != KErrNotFound)
+		{
+		return iIndividualTransitionSchedulers[offset];
+		}
+	return NULL;
+	}
+
+/**
+Notify the monitor (if set) that one of the transition events has occured
+*/
+void CSsmSwpTransitionScheduler::NotifyTransitionQueued()
+	{
+	if(iTransactionMonitor != NULL)
+		{
+		iTransactionMonitor->SwpTransitionQueued();
+		}
+	}
+
+void CSsmSwpTransitionScheduler::NotifyTransitionStarted()
+	{
+	if(iTransactionMonitor != NULL)
+		{
+		iTransactionMonitor->SwpTransitionStarted();
+		}
+	}
+
+// Time to wait after completion before starting lazy cleanup
+const TInt KLazyCleanupTimeOut = 5000000;
+
+void CSsmSwpTransitionScheduler::NotifyTransitionCompleted()
+	{
+	DEBUGPRINT1(_L("ERequestSwpChange Completed"));
+	if(iTransactionMonitor != NULL)
+		{
+		iTransactionMonitor->SwpTransitionCompleted(++iNumberOfCompletedTransitions);
+		}
+	if(!IsActive())
+		{
+		After(KLazyCleanupTimeOut);
+		}
+	}
+
+void CSsmSwpTransitionScheduler::RunL()
+	{
+	// ignore any error in iStatus as clean-up is a safe operations to perform anytime
+	
+	// iterate through schedulers, removing them if they're not doing anything
+	TInt top = iIndividualTransitionSchedulers.Count() - 1;
+	for(TInt i = top; i >= 0; --i)
+		{
+		if (iIndividualTransitionSchedulers[i]->IsIdle())
+			{
+			delete iIndividualTransitionSchedulers[i];
+			iIndividualTransitionSchedulers[i] = NULL;
+			iIndividualTransitionSchedulers.Remove(i);
+			}
+		}
+	// If there are now none left, free the memory
+	if(iIndividualTransitionSchedulers.Count() == 0)
+		{
+		iIndividualTransitionSchedulers.GranularCompress();
+		}
+	}
+
+TInt CSsmSwpTransitionScheduler::RunError(TInt __DEBUG_ONLY(aError))
+	{
+	DEBUGPRINT2A("CSsmSwpTransitionScheduler::RunError() run with error %d, ignoring", aError);
+	// Ignore any errors with the timer as it is only used for clean up 
+	return KErrNone;
+	}
+
+void CSsmSwpTransitionScheduler::NotifyTransitionFailed()
+	{
+	DEBUGPRINT1(_L("Error: ERequestSwpChange Failed"));
+	if(iTransactionMonitor != NULL)
+		{
+		iTransactionMonitor->SwpTransitionFailed(++iNumberOfFailedTransitions);
+		}
+	}
+
+/**
+ * Used for testing purposes
+ * Delete all the individual Transition Schedulers stored in the array
+ * and free the memory
+ */
+#ifdef _DEBUG
+void CSsmSwpTransitionScheduler::CleanupIndividualSchedulerArray()
+	{
+	TInt top = iIndividualTransitionSchedulers.Count() - 1;
+	for(TInt i = top; i >= 0; --i)
+		{
+		if (iIndividualTransitionSchedulers[i]->IsIdle())
+			{
+			delete iIndividualTransitionSchedulers[i];
+			iIndividualTransitionSchedulers[i] = NULL;
+			iIndividualTransitionSchedulers.Remove(i);
+			}
+		}
+	// If there are now none left, free the memory
+	if(iIndividualTransitionSchedulers.Count() == 0)
+		{
+		iIndividualTransitionSchedulers.GranularCompress();
+		}
+	}
+#endif