--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntsrv/src/CCntDbManager.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,516 @@
+// 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:
+//
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+
+#include "persistencelayer.h"
+#include "CCntDbManager.h"
+#include "CCntRequest.h"
+#include "CCntStateMachine.h"
+#include "CCntBackupRestoreAgent.h"
+#include "CIniFileManager.h"
+#include "CntSpeedDials.h"
+#include "CCntLowDiskManager.h"
+#include "CViewSubSessions.h"
+
+CCntDbManager::CCntDbManager(RFs& aFs, const TDesC& aCntFile, CCntBackupRestoreAgent& aBackupRestoreAgent, CIniFileManager& aIniManager)
+: iFs(aFs), iCntFile(aCntFile), iBackupRestoreAgent(aBackupRestoreAgent), iIniManager(aIniManager)
+ {
+ }
+
+CCntDbManager::~CCntDbManager()
+ {
+ iObserverArray.Close();
+ delete iViewManager;
+ delete iPersistenceLayer;
+ delete iStateMachine;
+ delete iLowDiskManager;
+ }
+
+
+const TDesC& CCntDbManager::CntFile()
+ {
+ return iCntFile;
+ }
+
+/**
+Object factory method.
+
+@param aFs File Server session.
+@param aCntFile Filename of the Contacts database.
+@param aFileMode Indicates whether to open, create or replace the Contacts
+database. If open is indicated then the actual open takes place within the
+State Machine and is initiated by the CCntDbManagerController singleton.
+@param aBackupRestoreAgent The Backup/Restore Agent used to monitor inform this
+database of Backup/Restore events originating from the SBEngine component.
+@param aIniManager The Initialisation File Manager used to manage this
+database's data within cntmodel.ini.
+
+@return CCntDbManager instance.
+*/
+CCntDbManager* CCntDbManager::NewLC(RFs& aFs, const TDesC& aCntFile, TCntFileMode aFileMode, CCntBackupRestoreAgent& aBackupRestoreAgent, CIniFileManager& aIniManager)
+ {
+ CCntDbManager* manager = new (ELeave) CCntDbManager(aFs, aCntFile, aBackupRestoreAgent, aIniManager);
+ CleanupStack::PushL(manager);
+ manager->ConstructL(aFileMode);
+ return manager;
+ }
+
+
+/**
+Second phase constructor.
+
+@param aFileMode Indicates whether to open, create or replace the Contacts
+database. If open is indicated then the actual open takes place within the
+State Machine and is initiated by the CCntDbManagerController singleton.
+*/
+void CCntDbManager::ConstructL(TCntFileMode aFileMode)
+ {
+ iPersistenceLayer = CPersistenceLayer::NewLC(iFs, this, NULL);
+ CleanupStack::Pop(iPersistenceLayer);
+
+ // The State Machine is passed into the Persistence Layer as
+ // MContactDbObserver since it is the first observer to recieve (and deal
+ // with) database events outside the Persistence Layer.
+ iPersistenceLayer->RegisterDbObserver(StateMachineL());
+
+ // Create and replace use the same call just the overwrite is different.
+ // Once created, the database has to be opened. The open operation is
+ // initiated in the State Machine by the CCntDbManagerController singleton
+ // that creates this CCntDbManager instance.
+ if (aFileMode == ECntFileCreate)
+ {
+ iPersistenceLayer->ContactsFileL().CreateL(iCntFile, MLplContactsFile::EPlLeaveIfExist);
+ }
+ else if (aFileMode == ECntFileReplace)
+ {
+ iPersistenceLayer->ContactsFileL().CreateL(iCntFile, MLplContactsFile::EPlOverwrite);
+ }
+
+ if (aFileMode == ECntFileCreate || aFileMode == ECntFileReplace)
+ {
+ // creating a backup registration file for the newly created or replaced database file.
+ TRAPD(createErr, BackupRestoreAgent().CreateBackupRegistrationFileL(iCntFile));
+
+ if (createErr != KErrNone)
+ {
+ //An error has occured while creating backupregistration file,
+ //therefore we should delete the newly created database file.
+ TRAP_IGNORE(iPersistenceLayer->ContactsFileL().DeleteL(iCntFile));
+
+ //return the error recieved while creating BackupRegistration File
+ User::Leave(createErr);
+ }
+ }
+
+ // Start Low Disk Space Manager. Uses the database file name in iCntFile to
+ // determine the drive to observe for low disk space.
+ LowDiskManagerL().Start();
+ }
+
+
+/**
+Get the State Machine instance owned by this CCntDbManager. This instance is
+used to call CCntStateMachine::ProcessRequestL() which implements the Visitor
+Pattern. If the instance does not yet exist then create it (lazy
+initialisation).
+
+@return CCntStateMachine instance owned by this CCntDbManager.
+
+@leave KErrNoMemory Out of memory.
+*/
+CCntStateMachine& CCntDbManager::StateMachineL()
+ {
+ if (!iStateMachine)
+ {
+ iStateMachine = CCntStateMachine::NewL(*iPersistenceLayer, *this);
+ }
+ return *iStateMachine;
+ }
+
+
+/**
+Get the Persistence Layer instance owned by this CCntDbManager.
+
+@return CPersistenceLayer instance owned by this CCntDbManager.
+*/
+CPersistenceLayer& CCntDbManager::GetPersistenceLayer()
+ {
+ return *iPersistenceLayer;
+ }
+
+
+/**
+Get the Backup/Restore Agent instance owned by this CCntDbManager.
+
+@return CCntBackupRestoreAgent instance owned by this CCntDbManager.
+*/
+CCntBackupRestoreAgent& CCntDbManager::BackupRestoreAgent()
+ {
+ return iBackupRestoreAgent;
+ }
+
+
+/**
+Get the Initialisation File Manager instance owned by this CCntDbManager.
+
+@return CIniFileManager instance owned by this CCntDbManager.
+*/
+CIniFileManager& CCntDbManager::IniFileManager()
+ {
+ return iIniManager;
+ }
+
+
+/**
+Get the View Manager instance owned by this CCntDbManager. If the instance does
+not yet exist then create it (lazy initialisation).
+
+@return CCntStateMachine instance owned by this CCntDbManager.
+*/
+CViewManager& CCntDbManager::ViewManagerL()
+ {
+ if (!iViewManager)
+ {
+ iViewManager = CViewManager::NewL(GetPersistenceLayer().FactoryL(), *this);
+ }
+ return *iViewManager;
+ }
+
+
+/**
+Create and start Active Object which observes disk threshold notifications.
+
+@return CCntLowDiskManager instance owned by this CCntDbManager.
+*/
+CCntLowDiskManager& CCntDbManager::LowDiskManagerL()
+ {
+ if (!iLowDiskManager)
+ {
+ // Find out the drive held in iCntFile. If a drive letter is not
+ // present then the method leaves.
+ TParsePtrC parseFileName(iCntFile);
+ if (!parseFileName.DrivePresent())
+ {
+ User::Leave(KErrBadName);
+ }
+ TDriveUnit drive(parseFileName.Drive());
+
+ iLowDiskManager = CCntLowDiskManager::NewL(*this, KLowDiskThreshold, drive, iFs);
+ //
+ // FUTURE: In later implementation we will call RFs::ReserveDriveSpace()
+ // either here or via Persistence Layer. There is no method to un-
+ // reserve this space - it is automatically cleaned up when the RFs
+ // object used to reserve the space is closed.
+ //
+ }
+ return *iLowDiskManager;
+ }
+
+
+
+TInt CCntDbManager::FileSizeL()
+ {
+ return iPersistenceLayer->ContactsFileL().FileSize();
+ }
+
+
+/**
+Add a session (increase the number of clients accessing this database).
+*/
+void CCntDbManager::AddSession()
+ {
+ iSessionCount++;
+ }
+
+
+/**
+Remove a session (decrease the number of clients accessing this database).
+*/
+void CCntDbManager::RemoveSession()
+ {
+ iSessionCount--;
+ }
+
+
+/**
+Return the session count. When the session count reaches zero this instance of
+CCntDbManager can be destroyed.
+
+@return Session count.
+*/
+TInt CCntDbManager::SessionCount() const
+ {
+ return iSessionCount;
+ }
+
+
+/**
+Add a database event observer for this database.
+
+@param aObserver Database event observer to add.
+*/
+void CCntDbManager::RegisterDatabaseEventObserverL(MContactDbObserver& aObserver)
+ {
+ User::LeaveIfError(iObserverArray.InsertInAddressOrder(&aObserver));
+ }
+
+
+/**
+Remove a database event observer for this database.
+
+@param aObserver Database event observer to remove.
+*/
+void CCntDbManager::UnRegisterDatabaseEventObserver(MContactDbObserver& aObserver)
+ {
+ TInt index = KErrNotFound;
+ const TInt error = iObserverArray.FindInAddressOrder(&aObserver, index);
+ if (error != KErrNotFound)
+ {
+ iObserverArray.Remove(index);
+ }
+ }
+
+
+/**
+Process a database event (typically generated in the Persistence Layer).
+
+@param aEvent Database event.
+*/
+void CCntDbManager::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
+ {
+ // Notify all registered observers of the event.
+ NotifyObserversL(aEvent);
+ }
+
+
+/**
+Process a Backup/Restore event (typically generated by the Database Manager
+Controller via the Backup/Restore Agent).
+
+@param aEvent Database event (limited to Backup/Restore database events).
+*/
+void CCntDbManager::HandleBackupRestoreEventL(TContactDbObserverEvent aEvent)
+ {
+ // Create and then process appropriate request using state machine.
+ CCntRequest* request = NULL;
+
+ switch(aEvent.iType)
+ {
+ case EContactDbObserverEventBackupBeginning :
+ case EContactDbObserverEventRestoreBeginning :
+ {
+ request = CReqBackupRestoreBegin::NewLC();
+ }
+ break;
+
+ case EContactDbObserverEventBackupRestoreCompleted :
+ // Bad database recovery is automatically carried out in the
+ // Persistence Layer as part of the opening process.
+ case EContactDbObserverEventRestoreBadDatabase :
+ {
+ request = CReqBackupRestoreEnd::NewLC();
+ }
+ break;
+
+ default :
+ {
+ // Misuse of API (unexpected event).
+ User::Leave(KErrArgument);
+ }
+ }
+
+ StateMachineL().ProcessRequestL(request); // ownership transferred
+
+ // ProcessRequestL received ownership of the request, the request only need
+ // to be popped from CleanupStack.
+ CleanupStack::Pop(request);
+
+ // Notify all registered observers of Backup/Restore event.
+ NotifyObserversL(aEvent);
+ }
+
+
+/**
+Process a low/not low disk condition.
+
+@param aLowDisk ETrue if low disk condition, EFalse otherwise.
+*/
+void CCntDbManager::HandleLowDiskL(TBool aLowDisk)
+ {
+ // Create and then process appropriate request using state machine.
+ CCntRequest* request = NULL;
+
+ if (aLowDisk)
+ {
+ request = CReqDiskSpaceLow::NewLC();
+ }
+ else
+ {
+ request = CReqDiskSpaceNormal::NewLC();
+ }
+
+ StateMachineL().ProcessRequestL(request); // ownership transferred
+
+ // ProcessRequestL received ownership of the request, the request only need
+ // to be popped from CleanupStack.
+ CleanupStack::Pop(request);
+ }
+
+
+/**
+Notify all registered observers (typically a client session) of a database
+event. Each registered observer implements the MContactDbObserver interface
+which is comprised of the HandleDatabaseEventL() method.
+
+@param aEvent Database event to send to registered observers.
+*/
+void CCntDbManager::NotifyObserversL(const TContactDbObserverEvent aEvent)
+ {
+ for(TInt i = iObserverArray.Count()-1; i>=0; --i)
+ {
+ iObserverArray[i]->HandleDatabaseEventL(aEvent);
+ }
+ }
+
+
+void CCntDbManager::SetCurrentItemL(TContactItemId aContactId, TUint aConnectionId)
+ {
+ iIniManager.SetCurrentItemL(iCntFile, aContactId);
+ TContactDbObserverEvent event;
+ event.iType = EContactDbObserverEventCurrentItemChanged;
+ event.iContactId = aContactId;
+ event.iConnectionId = aConnectionId;
+ // Save the changes to the contacts model ini file
+ iIniManager.ScheduleSaveIniFileSettings(CIniFileManager::ESaveCurrentItem);
+ NotifyObserversL(event);
+ }
+
+
+void CCntDbManager::RemoveCurrentItemL(TUint aConnectionId)
+ {
+ iIniManager.RemoveCurrentItemL(iCntFile);
+ TContactDbObserverEvent event;
+ event.iType = EContactDbObserverEventCurrentItemDeleted;
+ event.iContactId = KNullContactId;
+ event.iConnectionId = aConnectionId;
+ // Save the changes to the contacts model ini file
+ iIniManager.ScheduleSaveIniFileSettings(CIniFileManager::ESaveCurrentItem);
+ NotifyObserversL(event);
+ }
+
+
+TContactItemId CCntDbManager::CurrentItem() const
+ {
+ return iIniManager.CurrentItem(iCntFile);
+ }
+
+
+void CCntDbManager::DeleteNotifyL(TContactItemId aContactId)
+ {
+ if (aContactId == CurrentItem())
+ {
+ // Tell the server that the current item has just been deleted.
+ RemoveCurrentItemL(0);
+ }
+ }
+
+
+/**
+Return the speed dial phone number at the specified speed dial table index.
+*/
+void CCntDbManager::GetSpeedDialContactIdAndPhoneNumberL(const TInt aSpeedDialIndex, TSpeedDialPhoneNumber& aPhoneNumber, TContactItemId& aContactId)
+ {
+ const CCntServerSpeedDialTable& table = iIniManager.SpeedDialManager().TableL(iCntFile);
+ aContactId = table.SpeedDialContactItem(aSpeedDialIndex, aPhoneNumber);
+ }
+
+
+/**
+Set the phone number and Contact ID for the specified speed dial table index.
+*/
+TContactItemId CCntDbManager::SetSpeedDialIdForPositionL(const TInt aSpeedDialIndex, const TContactItemId aContactId, const TSpeedDialPhoneNumber& aPhoneNumber, TUint aConnectionId, TBool aSendNotification)
+ {
+ // Get the speed dial table
+ CCntServerSpeedDialTable& table = iIniManager.SpeedDialManager().TableL(iCntFile);
+ // Grab data from the speed dial table
+ TContactItemId contactIdToBroadcast;
+ if ( aContactId == KNullContactId )
+ {
+ TSpeedDialPhoneNumber phoneNumberFromSpeedDialTable;
+ contactIdToBroadcast = table.SpeedDialContactItem(aSpeedDialIndex, phoneNumberFromSpeedDialTable);
+ }
+ else
+ {
+ contactIdToBroadcast = aContactId;
+ }
+
+ // Update speed dial array
+ table.SetSpeedDialL(aSpeedDialIndex, aContactId, aPhoneNumber);
+ // Save the changes to the contacts model ini file
+ iIniManager.ScheduleSaveIniFileSettings(CIniFileManager::ESaveSpeedDials);
+ if (aSendNotification)
+ {
+ //BroadCast the SpeedDialsChanged event
+ TContactDbObserverEvent event;
+ event.iType = EContactDbObserverEventSpeedDialsChanged;
+ event.iContactId = contactIdToBroadcast;
+ event.iConnectionId = aConnectionId;
+ NotifyObserversL(event);
+ }
+ return contactIdToBroadcast;
+ }
+
+
+CArrayFix<TInt>* CCntDbManager::SpeedDialIndicesForContactIdLC(TContactItemId aContactId)
+ {
+ CCntServerSpeedDialTable& table = iIniManager.SpeedDialManager().TableL(iCntFile);
+ return table.SpeedDialIndicesForContactIdLC(aContactId);
+ }
+
+
+void CCntDbManager::SetCardTemplatePrefIdL(TContactItemId aCardTemplatePrefId, TInt aConnectionId)
+ {
+ // This is effectively a Write operation which should not be allowed in low
+ // disk condition.
+ if (LowDiskManagerL().LowDiskL())
+ {
+ User::Leave(KErrDiskFull);
+ }
+ iPersistenceLayer->ContactProperties().SetCardTemplatePrefIdL(aCardTemplatePrefId);
+ //Notify clients here
+ TContactDbObserverEvent event;
+ event.iType = EContactDbObserverEventPreferredTemplateChanged;
+ event.iContactId = aCardTemplatePrefId;
+ event.iConnectionId = aConnectionId;
+ NotifyObserversL(event);
+ }
+
+
+void CCntDbManager::RecreateSystemTemplateL()
+ {
+ // This is effectively a Write operation which should not be allowed in low
+ // disk condition.
+ if (LowDiskManagerL().LowDiskL())
+ {
+ User::Leave(KErrDiskFull);
+ }
+ iPersistenceLayer->ContactProperties().RecreateSystemTemplateL();
+ }