--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstatemgr/ssm/src/ssmswpindividualtransitionscheduler.cpp Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,313 @@
+// Copyright (c) 2008-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 "ssmserverpanic.h"
+#include "clesessionproxy.h"
+#include "ssmswptransitionengine.h"
+#include "ssmswptransitionscheduler.h"
+#include "ssmswpindividualtransitionscheduler.h"
+
+
+//
+//Construction/Destruction
+//
+
+
+/**
+Create a scheduler
+*/
+CSsmSwpIndividualTransitionScheduler* CSsmSwpIndividualTransitionScheduler::NewLC(TUint aSwpKey, MCleSessionProxy* aCleSession, CSsmSwpTransitionScheduler& aParent)
+ {
+ CSsmSwpIndividualTransitionScheduler* self = new (ELeave) CSsmSwpIndividualTransitionScheduler(aSwpKey, aParent);
+ CleanupStack::PushL(self);
+ self->ConstructL(aCleSession);
+ return self;
+ }
+
+void CSsmSwpIndividualTransitionScheduler::ConstructL(MCleSessionProxy* aCleSession)
+ {
+ // Need to create an individual CLE session proxy for each transition scheduler
+ iCleSession = aCleSession->CreateNewProxyL();
+
+ // Need to create an individual swppolicy session for each transition scheduler
+ iSsmSwpPolicySession = CSsmSwpPolicyCliSession::NewL();
+ }
+
+CSsmSwpIndividualTransitionScheduler::CSsmSwpIndividualTransitionScheduler(TUint aSwpKey, CSsmSwpTransitionScheduler& aParent)
+ : CActive(CActive::EPriorityStandard),
+ iSchedulerState(EIdle),
+ iSwpKey(aSwpKey),
+ iParent(aParent)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/**
+Deactivate
+Destroy queue
+*/
+CSsmSwpIndividualTransitionScheduler::~CSsmSwpIndividualTransitionScheduler()
+ {
+ CActive::Cancel();
+ __ASSERT_DEBUG(iTransitionQueue.Count() == 0, PanicNow(KPanicSysStateMgr,ESwpTransitionSchedulerError1));
+ DestroyTransitionQueue();
+ if(iCleSession)
+ {
+ iCleSession->Close();
+ iCleSession->ReleaseCle();
+ iCleSession = NULL;
+ }
+ if(iSsmSwpPolicySession)
+ {
+ delete iSsmSwpPolicySession;
+ }
+ }
+
+/**
+Take ownership of the transition engine and prepare to run it
+@param aEngine - the engine to run
+*/
+void CSsmSwpIndividualTransitionScheduler::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
+ }
+ // Change aEngine to having the cle proxy from this scheduler
+ // This allows multiple SwP transitions
+ aEngine->SetCleSessionProxy(iCleSession);
+
+ // Change aEngine to have the SsmSwpPolicySession from this scheduler. i.e, same SsmSwpPolicySession
+ // instance will be used for the all the individual Swp transitions.(the same swp policy session would be used).
+ // This allows multiple SwP transitions
+ aEngine->SetSsmSwpPolicySession(iSsmSwpPolicySession);
+ DoSubmitL(aEngine);
+ }
+
+void CSsmSwpIndividualTransitionScheduler::Cancel(CSession2* aSession)
+ {
+ //Cancel all queued requests that originates from aSession
+ CancelTransitionQueue(aSession);
+
+ // Cancel iCurrentTransition if it originates from aSession && still possible to Cancel (i.e. not started)
+ if(CurrentTransitionOriginatesFrom(aSession) && !iCurrentTransition->InTransition())
+ {
+ iCancellingSession = aSession;
+ CActive::Cancel();
+ iCancellingSession = NULL;
+
+ //We cancelled the currently running engine, see if there is anything left in the queue
+ iCurrentTransition = GetNextFromQueue();
+ if(iCurrentTransition != NULL) // we have more
+ {
+ ScheduleTransition();
+ }
+ }
+ }
+
+TBool CSsmSwpIndividualTransitionScheduler::CurrentTransitionOriginatesFrom(CSession2* aSession)
+ {
+ return (iCurrentTransition != NULL) && (iCurrentTransition->OriginatingSesssion() == aSession);
+ }
+
+TUint CSsmSwpIndividualTransitionScheduler::SwpKey() const
+ {
+ return iSwpKey;
+ }
+
+TBool CSsmSwpIndividualTransitionScheduler::IsIdle() const
+ {
+ return iTransitionQueue.Count() == 0 && iCurrentTransition == NULL;
+ }
+
+//
+// from CActive
+//
+
+/**
+Cancel running transition if any and destroy any transition in the queue that originates from the cancelling session
+*/
+void CSsmSwpIndividualTransitionScheduler::DoCancel()
+ {
+ // Cancel the running transition if it originates from the calling session
+ if(CurrentTransitionOriginatesFrom(iCancellingSession))
+ {
+ iCurrentTransition->Cancel();
+ delete iCurrentTransition;
+ iCurrentTransition = NULL;
+ }
+ }
+
+/**
+The only valid event at the moment is completion of engine for any reason.
+Except few errors (for example, when a transition is not allowed),
+most of the unexpected transition errors are identified and dealt in the engine.
+Notes: Tries to start the next engine even if there was an error.
+*/
+void CSsmSwpIndividualTransitionScheduler::RunL()
+ {
+ if(KErrNone == iStatus.Int())
+ {
+ NotifyTransitionCompleted();
+ }
+ else
+ {
+ NotifyTransitionFailed();
+ }
+
+ // try to start the next transition
+ delete iCurrentTransition;
+ iCurrentTransition = NULL;
+ iCurrentTransition = GetNextFromQueue();
+ if(iCurrentTransition != NULL) // we have more
+ {
+ ScheduleTransition();
+ }
+ }
+
+/**
+Log an error occured
+
+@param aError the error
+
+*/
+TInt CSsmSwpIndividualTransitionScheduler::RunError(TInt aError)
+ {
+ (void)aError;
+ DEBUGPRINT2(_L("CSsmSwpIndividualTransitionScheduler leave detected in RunL, error: %d"), aError);
+ PanicNow(KPanicSysStateMgr,ESwpTransitionSchedulerError5);
+ return KErrNone;
+ }
+
+//
+// private: methods
+//
+
+/**
+Start a transition if none is running, otherwise put it into the queue
+
+@param aEngine the transition engine to submit
+@leave one of the system wide error codes if insert fails
+
+*/
+void CSsmSwpIndividualTransitionScheduler::DoSubmitL(CSsmSwpTransitionEngine* aEngine)
+ {
+ if(IsActive())
+ {
+ // add to Queue
+ iTransitionQueue.InsertL(aEngine, 0);
+ NotifyTransitionQueued();
+ }
+ else
+ {
+ // start immediately
+ __ASSERT_DEBUG(iCurrentTransition == NULL, PanicNow(KPanicSysStateMgr,ESwpTransitionSchedulerError2));
+ iCurrentTransition = aEngine;
+ ScheduleTransition();
+ }
+ }
+
+/**
+Start the transition running and make it current
+
+@param aEngine the transition engine to submit
+@leave one of the system wide error codes
+*/
+void CSsmSwpIndividualTransitionScheduler::ScheduleTransition()
+ {
+ __ASSERT_DEBUG(!IsActive() && IsAdded(), PanicNow(KPanicSysStateMgr,ESwpTransitionSchedulerError3));
+ __ASSERT_DEBUG(iCurrentTransition != NULL, PanicNow(KPanicSysStateMgr,ESwpTransitionSchedulerError4));
+
+ iCurrentTransition->Submit(iStatus);
+ NotifyTransitionStarted();
+ SetActive();
+ }
+
+/**
+Retrieve the next transition engine from the queue
+return NULL if the queue is empty
+
+@return - the next transition engine or NULL
+*/
+CSsmSwpTransitionEngine* CSsmSwpIndividualTransitionScheduler::GetNextFromQueue()
+ {
+ TInt nextPos = iTransitionQueue.Count() - 1;
+ if(nextPos < 0) // Q empty
+ {
+ return NULL;
+ }
+ CSsmSwpTransitionEngine* ret = iTransitionQueue[nextPos];
+ iTransitionQueue.Remove(nextPos);
+ return ret;
+ }
+
+/**
+Remove and delete all queue entries, cancel any pending entries
+*/
+void CSsmSwpIndividualTransitionScheduler::DestroyTransitionQueue()
+ {
+ const TInt count = iTransitionQueue.Count();
+ for(TInt i=0; i<count; i++)
+ {
+ iTransitionQueue[i]->CompleteClientMessage(KErrCancel);
+ }
+ iTransitionQueue.ResetAndDestroy();
+ }
+
+/**
+Cancel, remove and delete all queue entries originating from aSession
+*/
+void CSsmSwpIndividualTransitionScheduler::CancelTransitionQueue(CSession2* aSession)
+ {
+ TInt count = iTransitionQueue.Count();
+ while(count--)
+ {
+ CSsmSwpTransitionEngine* engine = iTransitionQueue[count];
+ if( engine && (engine->OriginatingSesssion() == aSession) )
+ {
+ engine->CompleteClientMessage(KErrCancel);
+ iTransitionQueue.Remove(count);
+ delete engine;
+ }
+ }
+ }
+
+/**
+Notify the monitor (if set) that one of the transition events has occured
+*/
+void CSsmSwpIndividualTransitionScheduler::NotifyTransitionQueued()
+ {
+ iParent.NotifyTransitionQueued();
+ }
+
+void CSsmSwpIndividualTransitionScheduler::NotifyTransitionStarted()
+ {
+ iParent.NotifyTransitionStarted();
+ }
+
+void CSsmSwpIndividualTransitionScheduler::NotifyTransitionCompleted()
+ {
+ DEBUGPRINT1(_L("ERequestSwpChange Completed"));
+ iParent.NotifyTransitionCompleted();
+ }
+
+void CSsmSwpIndividualTransitionScheduler::NotifyTransitionFailed()
+ {
+ DEBUGPRINT1(_L("Error: ERequestSwpChange Failed"));
+ iParent.NotifyTransitionFailed();
+ }