diff -r 000000000000 -r bde4ae8d615e os/persistentdata/featuremgmt/featuremgr/src/serverexe/burstate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/featuremgmt/featuremgr/src/serverexe/burstate.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,417 @@ +// 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: +// + +/** + @file +*/ + +#include "burstate.h" +#include +#include "featmgrdebug.h" +#include "featmgrserver.h" + +CBurState::CBurState() + { + return; + } + +/** + * The Backup and Restore state machine. + * This state machine has two state tables. The first table defines the correct modes of operation + * and the second describe the pathways arrising from error conditions. By seperating the normal + * pathways from the error pathways we can simplify the state machine into two parts. The function + * SetUpBurStruct() will define the pathways for both these tables. + * Each table has three items per row: a current state, an ending state, and a pointer to a function + * that transforms between these two states safely. + * Given that we already know where we are, and where we are told to goto, the state machine + * function BUR_StateMachine() will search the normal operation table for a match, and then apply + * the function through the pointer. If no match is found, then the goto state is set to Error, and + * the error table is searched and applied. Because all the state are covered within the error table + * we can always return to a normal more of operation through the application of the error + * functions. + */ +CBurState::CBurState(CFeatMgrServer* aServer) : iCurrentBURStatus( EFeatMgrBURState_None ), iServer( aServer ) + { + SetUpBurStruct(); + return; + } + +CBurState::~CBurState() + { + return; + } + +CBurState* CBurState::NewLC() + { + CBurState* self = new (ELeave)CBurState(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CBurState* CBurState::NewL() + { + CBurState* self=CBurState::NewLC(); + CleanupStack::Pop(); // self; + return self; + } + +void CBurState::ConstructL() + { + return; + } + +/** + * This function checks the arguments that are passed into HandleBackupOperationEventL. + * The TBackupOperationAttributes are checked against known values and an error is returned if + * the Feature Manager doesn't recognise the events. + */ +TInt CBurState::CheckBURArguments( const TBackupOperationAttributes& aBackupOperationAttributes ) + { + TInt error( KErrNone ); + iBURLockFlag = aBackupOperationAttributes.iFileFlag; + iBUROpType = aBackupOperationAttributes.iOperation; + + // determine the operation type (backup or restore) + switch( iBURLockFlag ) + { + case MBackupObserver::EReleaseLockReadOnly: + INFO_LOG( "MBackupObserver::EReleaseLockReadOnly" ); + break; + case MBackupObserver::EReleaseLockNoAccess: + INFO_LOG( "MBackupObserver::EReleaseLockNoAccess" ); + break; + case MBackupObserver::ETakeLock: + INFO_LOG( "MBackupObserver::ETakeLock" ); + break; + default: + INFO_LOG( "CheckBURArguments iBURLockFlag default" ); + error = KErrNotFound; + break; + } + + // determine the operation status (e.g. starting, ending) + switch( iBUROpType ) + { + case MBackupOperationObserver::ENone: + INFO_LOG( "ENone" ); + break; + case MBackupOperationObserver::EStart: + INFO_LOG( "EStart" ); + break; + case MBackupOperationObserver::EEnd: + INFO_LOG( "EEnd" ); + break; + case MBackupOperationObserver::EAbort: + INFO_LOG( "EAbort" ); + break; + default: + INFO_LOG( "CheckBURArguments iOperation default" ); + error = KErrNotFound; + break; + } + + return error; + } + +/** + * Sets up the array entries for the possible backup/restore state vectors. + * from -> to : function + * State vector: None -> BackupStarted : Goto_StartBackupState + * State vector: BackupStarted -> BackupEnded : EndBackupState + * State vector: BackupEnded -> None : Goto_NormalState + * State vector: None -> RestoreStarted : Goto_StartRestoreState + * State vector: RestoreStarted -> RestoreEnded : Goto_EndRestoreState + * State vector: RestoreEnded -> None : Goto_NormalState + */ +void CBurState::SetUpBurStruct() + { + BURStruct bStruct; + + // Backup states + + // State vector: None -> BackupStarted : Goto_StartBackupState + bStruct.iCurrent = EFeatMgrBURState_None; + bStruct.iGoto = EFeatMgrBURState_BackupStarted; + bStruct.iFunc = &CFeatMgrServer::Goto_StartBackupState; + iBURStructArray[0] = bStruct; + + // State vector: BackupStarted -> BackupEnded : EndBackupState + bStruct.iCurrent = EFeatMgrBURState_BackupStarted; + bStruct.iGoto = EFeatMgrBURState_BackupEnded; + bStruct.iFunc = &CFeatMgrServer::Goto_EndBackupState; + iBURStructArray[1] = bStruct; + + // State vector: BackupEnded -> None : Goto_NormalState + bStruct.iCurrent = EFeatMgrBURState_BackupEnded; + bStruct.iGoto = EFeatMgrBURState_None; + bStruct.iFunc = &CFeatMgrServer::Goto_NormalState; + iBURStructArray[2] = bStruct; + + // Valid restore states + + // State vector: None -> RestoreStarted : Goto_StartRestoreState + bStruct.iCurrent = EFeatMgrBURState_None; + bStruct.iGoto = EFeatMgrBURState_RestoreStarted; + bStruct.iFunc = &CFeatMgrServer::Goto_StartRestoreState; + iBURStructArray[3] = bStruct; + + // State vector: RestoreStarted -> RestoreEnded : Goto_EndRestoreState + bStruct.iCurrent = EFeatMgrBURState_RestoreStarted; + bStruct.iGoto = EFeatMgrBURState_RestoreEnded; + bStruct.iFunc = &CFeatMgrServer::Goto_EndRestoreState; + iBURStructArray[4] = bStruct; + + // State vector: RestoreEnded -> None : Goto_NormalState + bStruct.iCurrent = EFeatMgrBURState_RestoreEnded; + bStruct.iGoto = EFeatMgrBURState_None; + bStruct.iFunc = &CFeatMgrServer::Goto_NormalState; + iBURStructArray[6] = bStruct; + + // State vector: None -> None : Goto_NormalState + bStruct.iCurrent = EFeatMgrBURState_None; + bStruct.iGoto = EFeatMgrBURState_None; + bStruct.iFunc = &CFeatMgrServer::Goto_NormalState; + iBURStructArray[5] = bStruct; + + + // + // Error states + + // State vector: RestoreStarted -> Error : Goto_ErrorState + bStruct.iCurrent = EFeatMgrBURState_RestoreStarted; + bStruct.iGoto = EFeatMgrBURState_Error; + bStruct.iFunc = &CFeatMgrServer::Goto_ErrorState; + iBURStructErrorArray[0] = bStruct; + + // State vector: RestoreEnded -> Error : Goto_ErrorState + bStruct.iCurrent = EFeatMgrBURState_RestoreEnded; + bStruct.iGoto = EFeatMgrBURState_Error; + bStruct.iFunc = &CFeatMgrServer::Goto_ErrorState; + iBURStructErrorArray[1] = bStruct; + + // State vector: BackupStarted -> None : Goto_ErrorState + bStruct.iCurrent = EFeatMgrBURState_BackupStarted; + bStruct.iGoto = EFeatMgrBURState_Error; + bStruct.iFunc = &CFeatMgrServer::Goto_ErrorState; + iBURStructErrorArray[2] = bStruct; + + // State vector: BackupEnded -> None : Goto_ErrorState + bStruct.iCurrent = EFeatMgrBURState_BackupEnded; + bStruct.iGoto = EFeatMgrBURState_Error; + bStruct.iFunc = &CFeatMgrServer::Goto_ErrorState; + iBURStructErrorArray[3] = bStruct; + + // State vector: Error -> None : Goto_NormalState + bStruct.iCurrent = EFeatMgrBURState_Error; + bStruct.iGoto = EFeatMgrBURState_None; + bStruct.iFunc = &CFeatMgrServer::Goto_NormalState; + iBURStructErrorArray[4] = bStruct; + + return; + } + +/** + * Convert from the type provided in TBackupOperationAttributes into more sensible BUR types that + * can be handles by the BUR_StateMachine. This step is necessary for two reasons, the first is + * simplification and the second is a lexical check for invalid type MBackupObserver::TFileLockFlags. + */ +BURStatus CBurState::ConvertToBURState( const TBackupOperationAttributes& aBackupOperationAttributes ) + { + BURStatus status = EFeatMgrBURState_Error; + iBURLockFlag = aBackupOperationAttributes.iFileFlag; + iBUROpType = aBackupOperationAttributes.iOperation; + // we ignore the iOperation state + + if( iBURLockFlag == MBackupObserver::ETakeLock ) + { + // ending (this doesn't define whether it was a backup + // or a restore ending, just that file writing can now start + // again). + INFO_LOG("ChangeFileLockL() BUR ending"); + switch( iCurrentBURStatus ) + { + case( EFeatMgrBURState_BackupStarted ): + status = EFeatMgrBURState_BackupEnded; + break; + case( EFeatMgrBURState_RestoreStarted ): + status = EFeatMgrBURState_RestoreEnded; + break; + case( EFeatMgrBURState_None ): + status = EFeatMgrBURState_None; + break; + default: + status = EFeatMgrBURState_Error; + break; + } + } + else if( (iBURLockFlag & MBackupObserver::EReleaseLockReadOnly) && + (iBURLockFlag & ~MBackupObserver::EReleaseLockNoAccess) ) + { + // starting (making the file read-only is a sign that we are + // in "backup" mode). + INFO_LOG("ChangeFileLockL() backup starting"); + status = EFeatMgrBURState_BackupStarted; + } + else if( iBURLockFlag & MBackupObserver::EReleaseLockNoAccess ) + { + // starting (now read/write access is used to signify that a + // restore has been started). + INFO_LOG("ChangeFileLockL() restore starting"); + status = EFeatMgrBURState_RestoreStarted; + } + else + { + // unhandled flag states + INFO_LOG("ChangeFileLockL() error state"); + status = EFeatMgrBURState_Error; + } + + return status; + } + +/** + * This function is called from within featmgr server when a backup event occurs + * There are two state variables coming into Feature Manager as types MBackupObserver::TFileLockFlags + * and TOperationType. Only certain combinations of these two state variables are valid for Feature + * Manager and if the combination is not valid (because there is no way of returning an error) + * it will just set the internal state machine into an "error" state. + * Given our current state and our goto state (i.e. where we are at the moment and where we want to goto) + * the state machine checks that this is a valid path in our state machine and then perform the correct + * operations to get us to the next valid state. + */ +void CBurState::BUROperationL( const TBackupOperationAttributes& aBackupOperationAttributes ) + { + BURStatus gotoState = EFeatMgrBURState_Error; // fail safe + BURStatus currentState = iCurrentBURStatus; // where in the state machine we are at the moment + + // Check that the arguments are within valid limits + if( KErrNone == CheckBURArguments( aBackupOperationAttributes ) ) + { + // Now convert into states that the Feature Manager understands. + gotoState = ConvertToBURState( aBackupOperationAttributes ); + } + + // Check that this is a valid path and then perform the correct operations to get to the next valid state + iCurrentBURStatus = BUR_StateMachine( currentState, gotoState ); + + return; + } + +/** + * The state machine for the backup and restore of the featmgr + * The logic that goes into changing states in the state machine. + */ +BURStatus CBurState::BUR_StateMachine( BURStatus aCurrent, BURStatus aGoto ) + { + TInt count = 0; + TBool found = EFalse; + + // Fail safe default state values + BURStatus newState = EFeatMgrBURState_Error; + BURStatus stateTableGoto = EFeatMgrBURState_Error; + BURStatus stateTableCurrent = EFeatMgrBURState_Error; + + // Normal operation + // + do + { + // Get the n-th state table [current,goto] state vector + stateTableCurrent = iBURStructArray[count].iCurrent; + stateTableGoto = iBURStructArray[count].iGoto; + + // if the state table matches what we are given + if( (aCurrent == stateTableCurrent) && + (aGoto == stateTableGoto) ) + { + // process the relevant state function + if( NULL != iBURStructArray[count].iFunc ) + { + newState = (iServer->*iBURStructArray[count].iFunc)( aCurrent ); + + // check result: when from the state machine is not what we expected from the state table + if( newState != stateTableGoto ) + { + // put state machine into an error state and break "normal" loop + aCurrent = newState; + aGoto = EFeatMgrBURState_Error; + break; + } + else + { + found = ETrue; + } + } + + // self-perpetuate in certain cases + if( (EFeatMgrBURState_BackupEnded == newState) || + (EFeatMgrBURState_RestoreEnded == newState) ) + { + aCurrent = newState; + aGoto = EFeatMgrBURState_None; + found = EFalse; + count = 0; + } + } + count++; + } + while( (!found) && count < KBURArrayLength ); + + + // Error recovery + // + if( EFeatMgrBURState_Error == aGoto || + EFalse == found ) + { + // reset + aGoto = EFeatMgrBURState_Error; + count = 0; + found = EFalse; + + do + { + // Get the n-th state table [current,goto] state vector in the error array + stateTableCurrent = iBURStructErrorArray[count].iCurrent; + stateTableGoto = iBURStructErrorArray[count].iGoto; + + // if the state table matches what we are given + if( ((aCurrent == stateTableCurrent) && (aGoto == stateTableGoto)) ) + { + // process the relevant state function + if( NULL != iBURStructErrorArray[count].iFunc ) + { + newState = (iServer->*iBURStructErrorArray[count].iFunc)( aCurrent ); + // there is no error recovery from error recovery. + found = ETrue; + } + + // self-perpetuate in certain cases + if( EFeatMgrBURState_Error == newState ) + { + aCurrent = newState; + aGoto = EFeatMgrBURState_None; + found = EFalse; + count = 0; + } + } + count++; + } + while( (!found) && count < KBURErrorArrayLength ); + + } + + return newState; + } +