diff -r fd64c38c277d -r b46a585f6909 phonebookengines_old/contactsmodel/cntsrv/src/CCntDbManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines_old/contactsmodel/cntsrv/src/CCntDbManager.cpp Fri Jun 11 13:29:23 2010 +0300 @@ -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* 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(); + }