--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/featuremgmt/featuremgr/src/serverexe/burstate.cpp Fri Jan 22 11:06:30 2010 +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 <babackup.h>
+#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;
+ }
+