--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntsrv/inc/CCntStateMachine.h Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,461 @@
+/**
+* Copyright (c) 2006-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
+ @internalComponent
+ @released
+*/
+
+
+#ifndef __CCNTSTATEMACHINE_H__
+#define __CCNTSTATEMACHINE_H__
+
+#include "CActiveLoop.h" // For MActiveLoopCallBack.
+#include <cntdef.h> // for tcontactitemid.
+#include "CCntRequest.h"
+
+namespace nsState
+ {
+ const TInt KLastStep = 0;
+ const TInt KNoSessionId = 0;
+
+ enum TStates
+ {
+ EStateClosed = 0,
+ EStateTablesClosed,
+ EStateWritable,
+ EStateOpening,
+ EStateTransaction,
+ EStateBackupRestore
+ };
+ }
+
+
+// Forward class references.
+class CCntStateMachine;
+class CTransactionTimer;
+class CCntRequest;
+class CPersistenceLayer;
+class CCntDbManager;
+class MLplContactsFile;
+
+
+/**
+This class is the base class for each State object held in the State Machine.
+*/
+class CState : public CBase, public MContactDbObserver
+ {
+public:
+ ~CState();
+
+ virtual TAccept AcceptRequestL(CReqAsyncOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqUpdateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCommitCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqReadCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqOpenCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDeleteCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCloseCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCreateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCancelAsyncOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCloseTables* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqReOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbBeginTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbCommitTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbRollbackTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqBackupRestoreBegin* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqBackupRestoreEnd* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDiskSpaceLow* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDiskSpaceNormal* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqAsyncActivity* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqNoAsyncActivity* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqSetSpeedDial* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqSetOwnCard* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqInternalSessionUnlock* aRequest); //visitor pattern
+
+ // Implementation of the MContactDbObserver interface
+ void HandleDatabaseEventL(TContactDbObserverEvent aEvent);
+
+protected:
+ CState(CCntStateMachine& aStateMachine, CPersistenceLayer& iPersistenceLayer);
+
+ void TransactionStartLC(TUint aSessionId);
+ void TransactionCommitLP();
+ virtual void RollbackTransAndRecoverL(const TBool aNotification);
+
+ TAccept DeferRequest(CCntRequest* aRequest);
+ TAccept DeferWithTimeOutError(CCntRequest* aRequest);
+
+ // derived state classes use different error codes and implement a derived TimeOutErrorCode()
+ virtual TInt TimeOutErrorCode();
+
+private:
+ static void CleanupTransactionRollback(TAny* aState);
+
+protected:
+ CCntStateMachine& iStateMachine;
+ CPersistenceLayer& iPersistenceLayer;
+ TUint iCurrentTransactionSessionId;
+ };
+
+
+class CStateClosed : public CState
+ {
+public:
+ static CStateClosed* NewL(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ ~CStateClosed();
+
+ virtual TAccept AcceptRequestL(CReqAsyncOpen* aRequest);
+ virtual TAccept AcceptRequestL(CReqReOpen* aRequest);
+
+ // Overridden read-only operations from base class: can't read from the
+ // database while in the Closed state so defer these requests.
+ virtual TAccept AcceptRequestL(CReqReadCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqOpenCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDeleteCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqUpdateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCommitCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCreateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCloseTables* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbBeginTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbCommitTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbRollbackTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqSetSpeedDial* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqSetOwnCard* aRequest); //visitor pattern
+
+ // Overridden Backup/Restore operations from base class.
+ virtual TAccept AcceptRequestL(CReqBackupRestoreBegin* aRequest); //visitor pattern
+
+protected:
+ CStateClosed(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ };
+
+
+
+/**
+CStateTablesClosed is a special case of the CStateClosed. It allows requests
+that don't use the tables, such as compression.
+*/
+
+class CStateTablesClosed : public CStateClosed
+ {
+public:
+ static CStateTablesClosed* NewL(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ ~CStateTablesClosed();
+
+ // Do not allow AsyncOpen requests - return deferred.
+ // The CStateClosed parent class processes CReqAsyncOpen requests.
+ virtual TAccept AcceptRequestL(CReqAsyncOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqReOpen* aRequest); //visitor pattern
+
+private:
+ CStateTablesClosed(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ };
+
+
+class CStateBackupRestore : public CStateClosed
+ {
+public:
+ static CStateBackupRestore* NewL(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ ~CStateBackupRestore();
+
+ // Do not allow AsyncOpen requests
+ virtual TAccept AcceptRequestL(CReqAsyncOpen* aRequest); //visitor pattern
+
+ virtual TAccept AcceptRequestL(CReqBackupRestoreBegin* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqBackupRestoreEnd* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqNoAsyncActivity* aRequest); //visitor pattern
+
+ // Does not use the CStateClosed Timeout error code
+ virtual TInt TimeOutErrorCode();
+
+private:
+ CStateBackupRestore(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ };
+
+
+/**
+The CStateOpening state is where the opening and possibly recovery and upgrade
+of the Contacts database takes place.
+*/
+class CStateOpening : public CState, public MActiveLoopCallBack
+ {
+public:
+ static CStateOpening* NewL(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ ~CStateOpening();
+
+ virtual TAccept AcceptRequestL(CReqAsyncOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCancelAsyncOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqReOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqBackupRestoreEnd* aRequest); //visitor pattern
+
+ // Overridden read-only operations from base class: can't read from the
+ // database while in the Opening state so defer these requests.
+ virtual TAccept AcceptRequestL(CReqReadCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqOpenCnt* aRequest); //visitor pattern
+
+ TBool DoStepL();
+ void DoError(TInt aError);
+
+private:
+ CStateOpening(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ void SetFileNameL (const TDes& aFileName);
+ void ConstructL ();
+ void InitialStep();
+ TAccept OpenDatabaseFileL(CCntRequest* aRequest, TBool aNoftify = EFalse);
+ void DoCompletion(TInt aError);
+private:
+ CActiveLoop* iActive;
+ MLplContactsFile* iCntFile;
+ HBufC* iFileName;
+ RPointerArray<CCntRequest> iOpenReqsStore;
+ // When opening the database a notification event is propogated for some requests
+ // however, the Persistence layer knows nothing of requests, so this flag is set for
+ // those requests that require notification to be propagated to the client.
+ TBool iNotify;
+ };
+
+
+/**
+The CStateWritable state is the "normal" state for a Contacts database. In this
+state CRUD operations can be carried out.
+*/
+class CStateWritable : public CState
+ {
+public:
+ static CStateWritable* NewL(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ ~CStateWritable();
+
+ // Locking methods.
+ virtual TAccept AcceptRequestL(CReqUpdateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCommitCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDeleteCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCreateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCancelAsyncOpen* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbBeginTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqBackupRestoreBegin* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqSetSpeedDial* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqSetOwnCard* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCloseTables* aRequest); //visitor pattern
+
+ virtual TInt TimeOutErrorCode();
+
+private:
+ CStateWritable(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ };
+
+
+/**
+The CStateTransaction state prevents all other sessions performing changes to
+the Contacts database.
+
+This state contains a CTransactionTimer which is reset after all requests are
+processed when the CStateTransaction is the current active state. If the
+CTransactionTimer timer object times out, the session is deemed to have died
+since it has not been in touch, and the transaction is rolled back.
+*/
+class CStateTransaction : public CState
+ {
+public:
+ static CStateTransaction* NewL(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ ~CStateTransaction();
+
+ // Overloaded Visitor Pattern methods
+ virtual TAccept AcceptRequestL(CReqDbBeginTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbCommitTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDbRollbackTrans* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCreateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqReadCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqUpdateCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqDeleteCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCommitCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqOpenCnt* aRequest); //visitor pattern
+ virtual TAccept AcceptRequestL(CReqCloseCnt* aRequest); //visitor pattern
+
+ virtual void CancelTransactionL();
+
+ void HandleDatabaseEventL(TContactDbObserverEvent aEvent);
+private:
+ CStateTransaction(CCntStateMachine& aStateMachine, CPersistenceLayer& aPersistenceLayer);
+ void ConstructL();
+ void StrayRequestL(CCntRequest* aRequest);
+ void PropagateDatabaseEventsL();
+ TBool CheckInternalCompressL();
+
+protected:
+ virtual TInt TimeOutErrorCode();
+
+private:
+ // Only one session is allowed to perform a transaction
+ TUint iSessionId;
+ CTransactionTimer* iTimeOut;
+ // Holds all events until the a commit transaction has been called
+ RArray<TContactDbObserverEvent> iEventQ;
+ };
+
+
+class CTransactionTimer : public CTimer
+ {
+public:
+ static CTransactionTimer* NewL(CStateTransaction& aTransState);
+ ~CTransactionTimer();
+ void Start();
+ void Stop ();
+ void Reset();
+
+private:
+ CTransactionTimer(CStateTransaction& aTransState);
+ void RunL();
+ void ConstructL();
+
+private:
+ CStateTransaction& iTransState;
+ };
+
+
+/**
+The transaction lock is NOT directly related to the CStateTransaction state.
+The CTransactionLock holds all the IDs of locked contact items - locked by a
+session for updating. No other session can perform a write operation on a
+locked contact item. There is one instance of the transaction lock owned by the
+CStateMachine class.
+*/
+class CTransactionLock : public CBase
+ {
+public:
+ static CTransactionLock* NewL(CCntStateMachine& aStateMachine);
+ inline ~CTransactionLock(){ iLockedIds.Close();}
+
+ TInt LockLX (const TUint aSessionId, const TContactItemId aCntId);
+ TInt UnLockL (const TUint aSessionId, const TContactItemId aCntId);
+
+ // Used with TCleanupItem when a method leaves & cleanup stack pop by the client
+ void UnlockLastLockedContactL(TUint aSessionId = nsState::KNoSessionId);
+ static void CleanupUnlockRecord(TAny* aTransLock);
+
+ // Used for the session close - removes all contact items that remain locked by the session
+ void UnLockAllL(const TUint aSessionId);
+ TBool IsLocked (const TUint aSessionId, const TContactItemId aCntId) const;
+
+ // Overridden IsLocked is used by CStateWritable::AcceptRequestL()
+ // which ignore the session id when checking for locked contact ids - original implementation
+ TBool IsLocked(const TContactItemId aCntId) const;
+
+ TBool AnyLocked() const;
+
+private:
+ inline CTransactionLock(CCntStateMachine& aStateMachine) : iStateMachine(aStateMachine){};
+ void ProcessLockedContactsL();
+
+private:
+ struct TLockData
+ {
+ TContactItemId iCntItemId;
+ const TUint iSessionId;
+ TLockData (TContactItemId aCntId, const TUint aSessionId);
+ };
+
+ // The iLockIds array works like a stack. On the client side, the lock
+ // can be popped via the CleanUpStack, this generates an IPC close request
+ // which pops the last LockID
+ RArray<TLockData> iLockedIds;
+ CCntStateMachine& iStateMachine;
+ };
+
+
+
+/**
+The CCntStateMachine class contains all states, sets the current state and is
+the point of entry for processing requests. It does none of the request
+processing, this is done within the state objects.
+
+It also contains all generic helper objects used by more than one state such as
+the request store where all deferred requests (requests that can not be
+processed) by the current active state are queued until the state changed.
+
+Another helper object is the transaction lock which holds the IDds of locked
+contact item. No state can modify a locked contact item. The states call into
+the state machine to ascertain if a contact item has been locked before
+modifying it.
+
+The CCntStateMachine class also implements the MContactDbObserver interface
+which propagates events back to the client session. All events originating in
+the Persistence Layer are routed through the State Machine. The reason for this
+is that within the Transaction State, the operations which trigger these events
+are only committed via an explicit commit request and therefore these events
+should only be propagated to the sessions after the operations have been
+committed to the Contacts database.
+
+Finally, each CCntStateMachine instance is owned by an associated CCntDbManager
+instance. This means one State Machine exists for each open Contacts database
+file which is shared among many sessions - hence the need for states.
+*/
+class CCntStateMachine : public CBase, public MContactDbObserver
+ {
+public:
+ static CCntStateMachine* NewL(CPersistenceLayer& aPersistenceLayer, CCntDbManager& aDbManager);
+ virtual ~CCntStateMachine();
+
+ CState& CurrentState();
+ void SetCurrentStateL (CState& aState);
+
+ void ProcessRequestL (CCntRequest* aRequest);
+ inline TBool DatabaseReady() { return iState == &StateWritable(); };
+
+ // Implementation of the MContactDbObserver interface
+ void HandleDatabaseEventL(TContactDbObserverEvent aEvent);
+
+ CTransactionLock& TransactionLockL();
+
+ CCntDbManager& DbManager();
+ CRequestStore& ReqStoreL();
+
+ inline void SetLowDisk(TBool aLowDisk) { iLowDisk = aLowDisk; };
+ inline TBool LowDisk() { return iLowDisk; };
+
+ inline void SetAsyncActivity(TBool aAsyncActivity) { iAsyncActivity = aAsyncActivity; };
+ inline TBool AsyncActivity() { return iAsyncActivity; };
+
+ inline CStateClosed& StateClosed() { return static_cast<CStateClosed&> (*iStateArray[nsState::EStateClosed]);};
+ inline CStateTablesClosed& StateTablesClosed() { return static_cast<CStateTablesClosed&> (*iStateArray[nsState::EStateTablesClosed]);};
+ inline CStateWritable& StateWritable() { return static_cast<CStateWritable&> (*iStateArray[nsState::EStateWritable]);};
+ inline CStateOpening& StateOpening() { return static_cast<CStateOpening&> (*iStateArray[nsState::EStateOpening]);};
+ inline CStateTransaction& StateTransaction() { return static_cast<CStateTransaction&> (*iStateArray[nsState::EStateTransaction]);};
+ inline CStateBackupRestore& StateBackupRestore(){ return static_cast<CStateBackupRestore&>(*iStateArray[nsState::EStateBackupRestore]);};
+
+private:
+ CCntStateMachine(CCntDbManager& aDbManager);
+ void ConstructL(CPersistenceLayer& aPersistenceLayer);
+
+#ifdef __STATE_MACHINE_DEBUG__
+ const TDesC& StateName(CState& aState);
+#endif
+
+private:
+ CState* iState;
+ RPointerArray <CState> iStateArray;
+ CRequestStore* iReqStore;
+ CTransactionLock* iTransLock;
+ CCntDbManager& iDbManager;
+ TBool iLowDisk;
+ TBool iAsyncActivity;
+ };
+
+
+#endif