phonebookengines/contactsmodel/cntsrv/src/CIniFileManager.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntsrv/src/CIniFileManager.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,440 @@
+// 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 "CIniFileManager.h"
+#include "CCntDbManagerController.h"
+#include "CCntBackupRestoreAgent.h"
+#include "CntCurrentItemMap.h"
+#include "CntSpeedDials.h"
+
+// uncomment this for debug logging
+//#define INIFILE_DEBUG_LOG
+
+
+
+const TUid KContactsIniUid = { 0x10009099 };
+const TUid KContactsCurrentDatabaseUid = { 0x1000909A };
+const TUid KUidContactsDefaultDatabaseLocation = { 0x1020380A };
+
+const TInt KIniFileSaveDelay = 100000;
+
+/**
+First phase constructor.
+*/
+CIniFileManager::CIniFileManager(RFs& aFs, CCntDbManagerController& aDbMgrCtrlr)
+	: CTimer(CActive::EPriorityStandard), iFs(aFs), iDbMgrCtrlr(aDbMgrCtrlr), iBackupFlag(ENoSaveRestore)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+
+/**
+Object factory method.
+*/
+CIniFileManager* CIniFileManager::NewL(RFs& aFs, CCntDbManagerController& aDbMgrCtrlr)
+	{
+	CIniFileManager* IniFileManager = new (ELeave) CIniFileManager(aFs, aDbMgrCtrlr);
+	CleanupStack::PushL(IniFileManager);
+	IniFileManager->ConstructL();
+	CleanupStack::Pop(IniFileManager);
+	return IniFileManager;
+	}
+
+
+/**
+Second phase constructor.
+*/
+void CIniFileManager::ConstructL()
+	{
+	CTimer::ConstructL();
+	iSpeedDialManager = new(ELeave) CCntServerSpeedDialManager();
+	iCurrentItemMap = new(ELeave) CCntServerCurrentItemMap();
+	iCurrentDb = KNullDesC;
+	// Restore the current database if possible. If this fails, the 
+	// current database is set to KNullDesC (i.e. zero'd)
+	RequestRestoreIniFileSettingsL();
+	}
+
+
+CIniFileManager::~CIniFileManager()
+	{
+	if (iFs.Handle()!=0)
+		{
+		TRAP_IGNORE(SaveIniFileSettingsL(ESaveAll,EFalse));
+		}
+	delete iSpeedDialManager;
+	delete iCurrentItemMap;
+	}
+
+
+/**
+Update/create a map entry for the current item associated with a database file.
+*/	
+void CIniFileManager::SetCurrentItemForDatabaseL(const TDesC& aDatabase, TContactItemId aContactId)
+	{
+	// Does the specified database contain a current item already?
+	TInt index = KErrNotFound;
+	if	(iCurrentItemMap->EntryAvailable(aDatabase, index))
+		{
+		// Yes, already exists, so update it....
+		iCurrentItemMap->UpdateEntryL(index, aContactId); 
+		}
+	else
+		{
+		// No, so create a new entry to represent this database
+		iCurrentItemMap->AddEntryL(aDatabase, aContactId);
+		}
+	}
+
+		
+void CIniFileManager::RemoveCurrentItemL(const TDesC& aDatabase)
+	{
+	SetCurrentItemForDatabaseL(aDatabase, KNullContactId);
+	}
+
+
+void CIniFileManager::SetCurrentItemL(const TDesC& aDatabase, TContactItemId aNewCurrentItem)
+	{
+	SetCurrentItemForDatabaseL(aDatabase, aNewCurrentItem);
+	}
+
+
+/**
+Returns the current item associated with the specified database.
+*/	
+TContactItemId CIniFileManager::CurrentItem(const TDesC& aDatabase) const
+	{
+	return iCurrentItemMap->CurrentItem(aDatabase);
+	}
+
+
+const TDesC& CIniFileManager::CurrentDb() const
+	{ 
+	return iCurrentDb; 
+	}
+
+	
+void CIniFileManager::SetCurrentDb(const TDesC& aDb)
+	{ 
+	iCurrentDb = aDb; 
+	}
+
+
+CCntServerSpeedDialManager& CIniFileManager::SpeedDialManager()
+	{ 
+	return *iSpeedDialManager;
+	}
+	
+
+void CIniFileManager::ScheduleSaveIniFileSettings(TInt aSaveFlags, TBool aReplace)
+	{
+	// make sure all requested writes are saved
+	iSaveType |= aSaveFlags;
+	iReplace = aReplace;
+
+	// make sure change isn't due to Internalize
+	if (iBackupFlag != EIsRestoring)
+		{
+		iBackupFlag = ERequestSave;
+		//iNumberOfAttemptedRetries = 0;
+
+		// set the time to RunL if not already set to run
+		// check that no Backup or Restore is in progress, 
+		// For Backup And Restore
+		if (!(iDbMgrCtrlr.BackupRestoreAgent().BackupInProgress()) &&
+			!(iDbMgrCtrlr.BackupRestoreAgent().RestoreInProgress()))
+			{
+			if (!IsActive())
+				{
+#ifdef INIFILE_DEBUG_LOG
+				RDebug::Print(_L("\n[CNTMODEL] CIniFileManager::ScheduleSaveIniFileSettings(aSaveFlags = %i, aReplace %i)\r\n"),aSaveFlags, aReplace);
+#endif
+				After(KIniFileSaveDelay);	
+				}
+			}
+		}
+	}
+
+
+void CIniFileManager::SaveIniFileSettingsIfRequestedL()
+	{
+	if (iBackupFlag == ERequestSave)
+		{
+		// Don't RunL
+		Cancel();
+
+		SaveIniFileSettingsL(iSaveType, iReplace);
+		iBackupFlag = ENoSaveRestore;
+		}
+	}
+
+
+void CIniFileManager::RequestRestoreIniFileSettingsL()
+	{
+	if (!(iDbMgrCtrlr.BackupRestoreAgent().RestoreInProgress()))
+		{
+		TInt ret = StartRestoreIniFileSettings();
+		switch (ret)
+			{
+		case KErrNone:
+			break;
+		// If file does not exist create ini file immediately.
+		case KErrPathNotFound:
+			SaveIniFileSettingsL(ESaveAll, EFalse);
+			break;
+		// If file is damaged replace ini file.
+		case KErrEof:
+			SaveIniFileSettingsL(ESaveAll, ETrue);
+			break;
+		default:
+#if	defined(_DEBUG)
+			User::Leave(KErrNotSupported);
+#endif
+			break;  //Would not build in UREL without it
+			}
+		}
+	}
+
+	
+TInt CIniFileManager::StartRestoreIniFileSettings()
+	{
+	iBackupFlag = EIsRestoring;
+	TInt err;
+	TRAP(err,RestoreIniFileSettingsL());
+	iBackupFlag = ENoSaveRestore;
+	return err ;
+	}
+
+
+void CIniFileManager::GetIniFileNameL(TDes& aFileName, TBool aIncPrivatePath)
+	{
+	if (aIncPrivatePath)
+		{
+		User::LeaveIfError(iFs.PrivatePath(aFileName));
+		}
+	// Drive name goes before the path.
+	aFileName.Insert(0,TDriveUnit(EDriveC).Name());
+	// Filename goes after the path.
+	aFileName.Append(KContactsIniFileName);
+	}
+
+
+/**
+Restore server-wide settings from the contacts ini file.
+*/
+void CIniFileManager::RestoreIniFileSettingsL()
+	{
+	// Initial location for Default database
+	SetDefaultDatabaseDrive(TDriveUnit(EDriveC),EFalse);
+
+	TFileName iniFile;
+	GetIniFileNameL(iniFile);
+	CDictionaryFileStore* iniStore = IniFileStoreLC(iniFile);
+	
+	// Load settings
+	iCurrentItemMap->RestoreL(*iniStore);
+	iSpeedDialManager->RestoreL(*iniStore);
+
+	// Current database
+	RestoreCurrentDatabaseL(*iniStore);
+
+	// Default database location
+	RestoreDefaultDbDriveL(*iniStore);
+
+	// Tidy up
+	CleanupStack::PopAndDestroy(iniStore);
+	}
+
+	
+void CIniFileManager::SetDefaultDatabaseDrive(TDriveUnit aDriveUnit, TBool aDriveSet)
+	{
+	iDefaultDriveUnit = aDriveUnit;
+	iDatabaseDriveSet = aDriveSet;
+	}
+
+	
+/**
+Restore the current database filename from the ini file.
+*/
+void CIniFileManager::RestoreCurrentDatabaseL(CDictionaryFileStore& aStore)
+	{
+	if	(aStore.IsPresentL(KContactsCurrentDatabaseUid))
+		{
+		RDictionaryReadStream stream;
+		stream.OpenLC(aStore, KContactsCurrentDatabaseUid);
+		stream >> iCurrentDb;
+		CleanupStack::PopAndDestroy(); // stream
+		}
+	}
+
+	
+/**
+Restore the current database filename from the ini file.
+*/
+void CIniFileManager::RestoreDefaultDbDriveL(CDictionaryFileStore& aStore)
+	{
+	if	(aStore.IsPresentL(KUidContactsDefaultDatabaseLocation))
+		{
+		TDriveUnit driveUnit;
+		RDictionaryReadStream stream;
+
+		stream.OpenLC(aStore, KUidContactsDefaultDatabaseLocation);
+		driveUnit = stream.ReadInt32L();
+		CleanupStack::PopAndDestroy(); // stream
+
+		SetDefaultDatabaseDrive(driveUnit);
+		iDbMgrCtrlr.RestoreDatabaseDrive(driveUnit); // restore drive setting in DBManagerController
+		}
+	}
+
+
+void CIniFileManager::RetryStoreOperation()
+	{
+	if (iBackupFlag == ERequestSave && !IsActive())
+		{
+		// can RunL now
+		After(0);
+		}
+	}
+
+
+void CIniFileManager::RunL()
+	{
+	const TInt error = iStatus.Int();
+
+#ifdef INIFILE_DEBUG_LOG
+	RDebug::Print(_L("[CNTMODEL] CIniFileManager::RunL() - error %i, iBackupFlag %i\r\n"), error, iBackupFlag);
+#endif
+
+	// operation isn't cancelled
+	if	(error == KErrNone && iBackupFlag == ERequestSave)
+		{
+		SaveIniFileSettingsL(iSaveType, iReplace);
+		iBackupFlag = ENoSaveRestore;
+		}
+	}
+
+
+TInt CIniFileManager::RunError(TInt aError)
+   	{
+#ifdef INIFILE_DEBUG_LOG
+	RDebug::Print(_L("[CNTMODEL] CIniFileManager::RunError(aError = %i)\r\n"), aError);
+#else
+	aError = aError; // remove compiler warning for unreferenced parameter
+#endif
+	// cannot do anything about the error
+	// - unless it occurred during a Backup, when it will already be retried
+
+	return KErrNone;
+	}
+
+	
+/**
+Save server-wide settings to the contacts model ini file.
+*/
+void CIniFileManager::SaveIniFileSettingsL(TInt aSaveFlags, TBool aReplace)
+	{
+	TFileName	iniFile;
+	GetIniFileNameL(iniFile);
+	iFs.MkDirAll(iniFile);
+
+	if (aReplace)
+		{
+		iFs.Delete(iniFile);
+		}
+	
+	// Get the ini store
+	CDictionaryFileStore* iniStore = IniFileStoreLC(iniFile);
+
+	// Save settings
+	if ((aSaveFlags & ESaveCurrentItem) && iCurrentItemMap)
+		{
+		iCurrentItemMap->StoreL(*iniStore);
+		}
+
+	if ((aSaveFlags & ESaveSpeedDials) && iSpeedDialManager)
+		{
+		iSpeedDialManager->StoreL(*iniStore);
+		}
+
+	// Current database
+	if (aSaveFlags & ESaveCurrentDatabase)
+		{
+		StoreCurrentDatabaseL(*iniStore);
+		}
+
+	// Default database location
+	if (aSaveFlags & ESaveDefaultDbDrive)
+		{
+		StoreDefaultDbDriveL(*iniStore);
+		}
+
+	// Commit
+	iniStore->CommitL();
+
+	// Tidy up
+	CleanupStack::PopAndDestroy(); // iniStore
+	}
+
+
+/**
+Return a pointer to the contacts ini file.
+*/
+CDictionaryFileStore* CIniFileManager::IniFileStoreLC(TFileName& aIniFile)
+	{
+	return CDictionaryFileStore::OpenLC(iFs, aIniFile, KContactsIniUid);
+	}
+
+	
+/**
+Save the current database filename to the ini file.
+*/
+void CIniFileManager::StoreCurrentDatabaseL(CDictionaryFileStore& aStore)
+	{
+	RDictionaryWriteStream stream;
+	stream.AssignLC(aStore, KContactsCurrentDatabaseUid);
+	stream << iCurrentDb;
+	stream.CommitL();
+	CleanupStack::PopAndDestroy(); // stream
+	}
+
+
+/**
+Save the default database drive to the ini file.
+*/
+void CIniFileManager::StoreDefaultDbDriveL(CDictionaryFileStore& aStore)
+	{
+	if (iDatabaseDriveSet)
+		{
+		RDictionaryWriteStream stream;
+		stream.AssignLC(aStore, KUidContactsDefaultDatabaseLocation);
+		stream.WriteInt32L(iDefaultDriveUnit);
+		stream.CommitL();
+		CleanupStack::PopAndDestroy(); // stream
+		}
+	}
+
+
+TBool& CIniFileManager::DatabaseDriveSet()
+	{
+	return iDatabaseDriveSet;
+	}