// Copyright (c) 2005-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:
// The Implementation of the CServerStartupMgr class which
// connects to the Domain manager to keep aware of the current start-up
// state and distributes the state changes to the interested MStartupStateObserver
// objects.
//
//
/**
@internalComponent
@file
*/
#include "ServerStartupManager.h"
#include "EComServer.h"
#include "EComDebug.h"
#include "EComPerformance.h"
/**
constructor of CServerStartupMgr
@param aHierarchyId The Id of the domain hierarchy to connect to.
@param aDomainId The Id of the domain to connect to.
@param aFs A reference to a connected file server session.
*/
CServerStartupMgr::CServerStartupMgr(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId, RFs& aFs):
#ifdef __ECOM_SERVER_TESTABILITY__
CDmDomainTestHarness(aHierarchyId,aDomainId),
#else
CDmDomain(aHierarchyId,aDomainId),
#endif
EKFinalStartupState(EStartupStateNonCritical),
iCurrentStartupState(EStartupStateUndefined),
iFs(aFs)
{
// does nothing.
}
/**
destructor
@internalComponent
*/
CServerStartupMgr::~CServerStartupMgr()
{
Cancel();
iObserverList.Reset();
}
/**
Accessor to the current startup state
@internalComponent
@return the current startup state
*/
TStartupStateIdentifier CServerStartupMgr::CurrentStartupState()
{
return iCurrentStartupState;
}
/**
updates the MStartupStateObserver objects.
@internalComponent
@param aKnownState the startup state passed into the MStartupStateObserver objects.
*/
void CServerStartupMgr::UpdateStateAwareObjectsL(TStartupStateIdentifier aKnownState)
{
RECORD_STARTUP_STATE_TIMER_RESULT(aKnownState)
RECORD_STARTUP_STATE_HEAP_RESULT(aKnownState)
TInt observerCount=iObserverList.Count();
for (TInt i = 0; i < observerCount; i++)
{
iObserverList[i]->ProcessSSAEventL(aKnownState);
}
RECORD_STARTUP_STATE_HEAP_RESULT(aKnownState)
RECORD_STARTUP_STATE_TIMER_RESULT(aKnownState)
}
/**
This method takes a a startup state which can be KSS or USS as a parameter,
and returns a ECOM Known Startup State
@internalComponent
@param aStartupState a startup state which can be KSS or USS.
@return an ECOM known startup state
*/
TStartupStateIdentifier CServerStartupMgr::GetKnownStartupState(TDmDomainState aStartupState)
{
if(aStartupState >= EStartupStateNonCritical)
{
return EStartupStateNonCritical;
}
else if(aStartupState >= EStartupStateCriticalDynamic)
{
return EStartupStateCriticalDynamic;
}
else if(aStartupState >= EStartupStateCriticalStatic)
{
return EStartupStateCriticalStatic;
}
else
{
return EStartupStateUndefined;
}
}
/**
Register the MStartupStateObserver object with the CServerStartupMgr.
@internalComponent
@param aObs the pointer to the MStartupStateObserver object to be registered with CServerStartupMgr.
*/
void CServerStartupMgr::RegisterObserverL(const MStartupStateObserver* aObs)
{
User::LeaveIfError(iObserverList.Append(aObs));
}
/**
Handle the error if RunL leaves. Panic with the error code
@internalComponent
@param aError error code generated by the RunL(), not used here.
@return KErrNone to avoid CActiveScheduler to panic.
*/
TInt CServerStartupMgr::RunError(TInt aError)
{
__ECOM_LOG1("ECOM: PANIC in CServerStartupMgr::RunError(), error= %d", aError);
User::Panic(KEComServerPanicCategory, EEComPanic_CServerStartupMgr_RunError);
return KErrNone; // dummy return to stop compiler warnings
}
/**
This method indicates how the CServerStartupMgr interacts with the Domain
manager to keep aware of the startup state change, and distribute it to the
MStartupStateObserver objects inside ECOM.
@internalComponent
@pre CServerStartupMgr is fully constructed.
*/
void CServerStartupMgr::InitialiseL(TBool aSsaEnabled)
{
if(!aSsaEnabled)
{
// it is not SSA, do a full discovery.
__ECOM_TRACE("ECOM: CServerStartupMgr::InitialiseL(): It is not SSA, do a full discovery");
UpdateStateAwareObjectsL(EKFinalStartupState);
iCurrentStartupState = EKFinalStartupState;
return;
}
// it is SSA.
else
{
__ECOM_TRACE("---------------------------------------------------");
__ECOM_TRACE("ECOM: CServerStartupMgr::InitialiseL(): SSA is on.");
#ifdef __ECOM_SERVER_TESTABILITY__
TRAPD(err, CDmDomainTestHarness::ConstructL());
#else
TRAPD(err, CDmDomain::ConstructL());
#endif
if(err!=KErrNone)
{
// the ConstructL leaves, then do a full discovery.
__ECOM_TRACE("ECOM: CServerStartupMgr::InitialiseL(): Can not connect to the Domain Manager, do a full discovery.");
UpdateStateAwareObjectsL(EKFinalStartupState);
iCurrentStartupState = EKFinalStartupState;
return;
}
//get the state from Domain Manager in case missing any.
#ifdef __ECOM_SERVER_TESTABILITY__
RequestTransitionNotificationL();
#else
RequestTransitionNotification();
#endif
// get the start up state from the Domain Manager.
TDmDomainState state = GetState();
// either something wrong with the Domain Manager or final state is reached.
if(state <= EStartupStateUndefined || state >= EStartupStateNonCritical)
{
// do a full discovery. Cancel outstanding request.
UpdateStateAwareObjectsL(EKFinalStartupState);
iCurrentStartupState = EKFinalStartupState;
Cancel();
return;
}
// get the ECom Known state.
TStartupStateIdentifier nextKnownState = GetKnownStartupState(state);
//for EStartupStateCriticalStatic or EStartupStateCriticalDynamic.
if(nextKnownState != EStartupStateUndefined)
{
// catch up to the ECOM interested state.
UpdateStateAwareObjectsL(EStartupStateCriticalStatic);
}
iCurrentStartupState = nextKnownState;
}
}
/**
Executed when the startup state change is done, it does the same thing
as the method InitialiseL() does when SSA is on and the CurrentStartupState is not EStartupStateNonCritical.
@internalComponent
*/
void CServerStartupMgr::RunL()
{
// Leave if something wrong with the RequestTransitionNotification().
User::LeaveIfError(iStatus.Int()); //RunError will handle this.
//do request transition notification in case missing any.
#ifdef __ECOM_SERVER_TESTABILITY__
RequestTransitionNotificationL();
#else
RequestTransitionNotification();
#endif
// get the start up state from Domain Manager.
TDmDomainState state = GetState();
//If the state is EStartupStateUndefined there must be sth wrong.
if(state == EStartupStateUndefined)
{
#ifdef __ECOM_SERVER_TESTABILITY__
AcknowledgeLastStateL(KErrBadHandle);
#else
AcknowledgeLastState(KErrBadHandle);
#endif
Cancel();
User::Leave(KErrBadHandle); //RunError will handle this.
}
//get the known state
TStartupStateIdentifier nextKnownState = GetKnownStartupState(state);
//If the nextKnownState is a state that we are ready to switch to
//update all the state aware objects and change the state.
//This way if we receive a state that is same as our current state
//we do not process it. Or the new state is less than our current
//state, we just ignore it.
if((iCurrentStartupState < EStartupStateCriticalStatic && nextKnownState == EStartupStateCriticalStatic)
|| (iCurrentStartupState < EStartupStateCriticalDynamic && nextKnownState == EStartupStateCriticalDynamic)
|| (iCurrentStartupState < EStartupStateNonCritical && nextKnownState == EStartupStateNonCritical))
{
UpdateStateAwareObjectsL(nextKnownState);
iCurrentStartupState = nextKnownState;
}
//Tell domain manager that we have processed the last state change.
#ifdef __ECOM_SERVER_TESTABILITY__
AcknowledgeLastStateL(KErrNone);
#else
AcknowledgeLastState(KErrNone);
#endif
//do not request transition notification if we have reached the last state
if(nextKnownState == EStartupStateNonCritical)
{
Cancel();
}
}