persistentstorage/centralrepository/cenrepsrv/shrepos.cpp
changeset 0 08ec8eefde2f
child 1 c084286672be
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/centralrepository/cenrepsrv/shrepos.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,980 @@
+// Copyright (c) 2004-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:
+//
+
+#include "srvdefs.h"
+#include "srvres.h"
+#include "shrepos.h"
+#include "srvrepos_noc.h"
+#include "obsrvr_noc.h"
+#include "srvparams.h"
+
+CSharedRepository* CSharedRepository::NewL(TUid aUid)
+	{
+	CSharedRepository* self = new(ELeave) CSharedRepository();
+	CleanupStack::PushL(self);
+	self->ConstructL(aUid);
+	CleanupStack::Pop(self);
+	
+	// debug check that CRepository::TTransactionMode modes match those used internally
+	// from CRepositoryTransactor: internal state logic relies on this
+	// there should be a better location for these checks...
+	ASSERT(CRepository::EReadTransaction == static_cast<CRepository::TTransactionMode>(EReadTransaction));
+	ASSERT(CRepository::EConcurrentReadWriteTransaction == static_cast<CRepository::TTransactionMode>(EConcurrentReadWriteTransaction));
+	ASSERT(CRepository::EReadWriteTransaction == static_cast<CRepository::TTransactionMode>(EReadWriteTransaction));
+	
+	return self;
+	}
+	
+void CSharedRepository::ConstructL(TUid aUid)
+	{
+	iSimRep = CHeapRepository::NewL(aUid);
+	}
+
+CSharedRepository::CSharedRepository() : iNotificationState(ETrue)
+	{
+	}
+	
+CSharedRepository::~CSharedRepository()
+	{
+	if (iSimRep)
+		{
+		delete iSimRep;
+		}
+	}
+
+TUid CSharedRepository::Uid() const
+	{
+	return iSimRep->Uid();
+	}
+
+/**
+Stores the repository in-memory content to the related repository file on drive C.
+If the operation fails, the in-memory content won't match the content of 
+the repository file (which will be kept as it was before the CommitChangesL() call).
+In order to keep the consistency, the in-memory repository content is deleted now
+and restored later, on the next repository operation.
+*/
+TInt CSharedRepository::CommitChanges(TCentRepLocation aLocation)
+	{
+	iInconsistentData=ETrue;
+	
+	HBufC* filePath(NULL);	   
+	TRAPD(err,TServerResources::CreateRepositoryFileNameL(filePath,iSimRep->Uid(),aLocation,ECre));	
+	if (err!=KErrNone)
+		{
+		iSimRep->ResetContent();
+		return err;		
+		}
+	
+	// should not be committing while transactions are still active
+	ASSERT(!IsTransactionActive());
+	TInt ret=iSimRep->CommitChanges(TServerResources::iFs,TServerResources::iPersistsVersion,*filePath);
+	if (ret==KErrNone)
+		{
+		iInconsistentData=EFalse;	
+		}
+	delete filePath;
+	return ret;
+	}
+
+// merge transaction settings (which may include entries flagged as deleted), persist and notify
+// private method relies on calling code to ensure it is permitted to make changes here.
+// if this method is committing any changes, it cancels all other sessions' transactions
+TInt CSharedRepository::DoCommitTransactionSettings(CRepositoryTransactor& aTransactor, TUint32& aKeyInfo)
+	{
+	aKeyInfo = KUnspecifiedKey;
+	if (0 == aTransactor.iTransactionSettings.Count())
+		{
+		aKeyInfo = 0; // == number of settings modified
+		return KErrNone; // nothing to do
+		}
+	TInt error = iSimRep->SettingsArray().MergeArray(aTransactor.iTransactionSettings, iSimRep->DeletedSettingsArray(), ETransactionMerge);
+	TInt numChanges = aTransactor.iTransactionSettings.Count();
+	if (numChanges == 0)
+		{
+		if (error == KErrNone)
+			{
+			aKeyInfo = 0; // no changes
+			}
+		// no changes were made, so the internal cache is still valid.
+		// This could be because there were no changes: empty list, only deletes on
+		// non-existent items (a setting created and deleted in the transaction),
+		// or because of error, such as failure of an initial realloc failure.
+		return error;
+		}
+	if (error != KErrNone)
+		{
+		// the repository is corrupted. Dump it for lazy loading later
+		ResetContent();
+		
+		// mark cache as inconsistent so it is reloaded.
+		iInconsistentData = ETrue;	
+		return error;	
+		}
+	if (error == KErrNone)
+		{
+		// changes have been made: fail all other sessions' transactions so we can commit
+		FailAllTransactions(/*aExcludeTransactor=*/&aTransactor);
+		error = CommitChanges(); // this already calls ResetContent() in case of failure
+		}
+	if (error == KErrNone)
+		{
+		// settings are now persistent on disk: we can now notify about the changes
+		// following will notify about objects that are created and deleted in the transaction
+		// this could be made faster by having a multiple Notify method.
+		// That would also allow Notify messages to be more descriptive - ranges of Keys
+		for (TInt i = 0; i < numChanges; i++)
+			{
+			Notify(aTransactor.iTransactionSettings[i].Key());
+			}
+		aKeyInfo = /*reinterpret_cast<TUint32>*/numChanges;
+		}
+	return error;
+	}
+
+void CSharedRepository::SetMetaDataOnRead(TServerSetting& aSetting, TBool aSingleMetaFound)
+	{
+	iSimRep->SetMetaDataOnRead(aSetting, aSingleMetaFound);
+	}
+
+void CSharedRepository::SetMetaDataOnCreate(TServerSetting& aNewSetting, TUint32* aMeta)
+	{
+	if(aMeta)
+		{
+		aNewSetting.SetMeta(*aMeta);
+		}
+	else
+		{
+		// No metadata specified. First check for a matching "range" default
+		// metadata setting
+		TSettingsDefaultMeta* defaultMeta = iSimRep->RangeMetaArray().Find(aNewSetting.Key());
+		if (defaultMeta)
+			{
+			aNewSetting.SetMeta(defaultMeta->GetDefaultMetadata());
+			}
+		else
+			{
+			// Range value not found, try for a repository default
+			aNewSetting.SetMeta(iSimRep->DefaultMeta());
+			}
+		}	
+	}
+
+void CSharedRepository::CreateL(TServerSetting& aSetting, TSettingsAccessPolicy*& aPolicy, TBool aFirstLoad, TBool aSingleMetaFound)
+	{
+	User::LeaveIfError(iSimRep->Create(aSetting, aPolicy, aSingleMetaFound));
+	if (!aFirstLoad)
+		{
+		Notify(aSetting.Key());
+		}
+	}
+
+// deletes an individual setting in the shared repository and makes it persistent
+// if changes are made, all sessions' transactions are failed
+TInt CSharedRepository::DeleteAndPersist(TUint32 aId)
+	{
+	TServerSetting* s = iSimRep->SettingsArray().Find(aId);
+	if(!s)
+		return KErrNotFound;
+	iSimRep->SettingsArray().Remove(aId);
+	
+	// removed a setting, so must fail all sessions' transactions before commit possible
+	FailAllTransactions(/*aExcludeTransactor=*/NULL);
+	TInt error = CommitChanges();
+	if (error == KErrNone)
+		{
+		Notify(aId);
+		}
+	return error;
+	}
+
+// deletes an individual setting without making it persistent
+// must not be called while any sessions are in transactions
+TInt CSharedRepository::DeleteNoPersist(TUint32 aId)
+	{
+	// should only be calling this if no transactions are active
+	ASSERT(!IsTransactionActive());
+	TServerSetting* s = iSimRep->SettingsArray().Find(aId);
+	if(!s)
+		return KErrNotFound;
+
+	iSimRep->SettingsArray().Remove(aId);
+	return KErrNone;	
+	}
+
+TInt CSharedRepository::ResetNoPersistL(TServerSetting& aSetting)
+	{
+	TServerSetting* s = iSimRep->SettingsArray().Find(aSetting.Key());
+	if ((!s) || (*s != aSetting))
+		{
+		if (s)
+			{
+			// save access policy of setting
+			TSettingsAccessPolicy* policy=s->AccessPolicy();
+			s->Transfer(aSetting);
+			// restore access policy of setting
+			s->SetAccessPolicy(policy);
+			}
+		else
+			{
+			TServerSetting setting;
+			setting.Transfer(aSetting);
+			setting.SetAccessPolicy(GetFallbackAccessPolicy(setting.Key()));
+			setting.PushL();
+			iSimRep->SettingsArray().OrderedInsertL(setting);
+			
+			TInt index = iSimRep->DeletedSettingsArray().FindInUnsignedKeyOrder(aSetting.Key());
+			if (index != KErrNotFound)
+				iSimRep->DeletedSettingsArray().Remove(index);
+	
+			setting.Pop();
+			}
+		}
+	else
+		{
+		return KErrGeneral;
+		}
+	return KErrNone;
+	}
+
+// if changes are made, all sessions' transactions are failed
+void CSharedRepository::ResetAndPersistL(TServerSetting& aSetting)
+	{
+	if (ResetNoPersistL(aSetting) == KErrNone)
+		{
+		// changed a setting, so must fail all sessions' transactions
+		// before commit possible
+		FailAllTransactions(/*aExcludeTransactor=*/NULL);
+		CommitChangesL();
+		Notify(aSetting.Key());
+		}
+	}
+
+TInt CSharedRepository::ResetAllNoPersistL(CSharedRepository& aNewContent)
+	{
+	// mark cache as inconsistent in case Reset fails, so it is reloaded.
+	iInconsistentData=ETrue;
+
+	// should not change repository while transactions in progress: should fail them first
+	ASSERT(!IsTransactionActive());
+	TInt newCount = (aNewContent.iSimRep)->SettingsArray().Count();
+	TInt count = iSimRep->SettingsArray().Count();
+
+	TInt newIndex = 0;
+	TInt index = 0;
+
+	while(newIndex<newCount && index<count)
+		{
+		const TServerSetting& newSetting = (aNewContent.iSimRep)->SettingsArray()[newIndex];
+		const TServerSetting& setting = iSimRep->SettingsArray()[index];
+
+		TUint32 newKey = newSetting.Key();
+		TUint32 key = setting.Key();
+
+		if(newKey<key)
+			{
+			Notify(newKey);
+			newIndex++;
+			}
+		else if(newKey==key)
+			{
+			if(newSetting!=setting)
+				{
+				Notify(key);
+				}
+			newIndex++;
+			index++;
+			}
+		else if(newKey>key)
+			{
+			Notify(key);
+			index++;
+			}
+		}
+
+	while(newIndex<newCount)
+		{
+		Notify((aNewContent.iSimRep)->SettingsArray()[newIndex++].Key());
+		}
+		
+	while(index<count)
+		{
+		Notify(iSimRep->SettingsArray()[index++].Key());
+		}
+
+	// Replace current settings with settings read from ROM, this 
+	// will leave settings pointing to new single policies
+	iSimRep->SettingsArray().AdoptL((aNewContent.iSimRep)->SettingsArray());
+
+	// Reset policy pointers to point at this repositories policies
+	newCount=iSimRep->SettingsArray().Count();
+	for(TInt i=0; i<newCount;i++)
+		{
+		(iSimRep->SettingsArray())[i].SetAccessPolicy(NULL);
+		TUint32 key = (iSimRep->SettingsArray())[i].Key();
+		(iSimRep->SettingsArray())[i].SetAccessPolicy(GetFallbackAccessPolicy(key));
+		}	
+	
+	iSimRep->DeletedSettingsArray().Reset();
+
+	iInconsistentData=EFalse;
+	return KErrNone;
+	}
+	
+// returns the read security policy used if there is no per-setting policy at aId
+const TSecurityPolicy& CSharedRepository::GetFallbackReadAccessPolicy(TUint32 aId)
+	{
+	return iSimRep->GetFallbackReadAccessPolicy(aId);
+	}
+
+// returns the write security policy used if there is no per-setting policy at aId
+const TSecurityPolicy& CSharedRepository::GetFallbackWriteAccessPolicy(TUint32 aId)
+	{
+	return iSimRep->GetFallbackWriteAccessPolicy(aId);
+	}
+
+// Get pointer to security policy that applies to a given setting
+TSettingsAccessPolicy* CSharedRepository::GetFallbackAccessPolicy(TUint32 aId
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+	,TBool aSkipSingle
+#endif	
+	)
+	{
+	return iSimRep->GetFallbackAccessPolicy(aId
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+	,aSkipSingle
+#endif	
+	);
+	}
+
+
+TInt CSharedRepository::ReadSettingSavePolicyL(CIniFileIn& aFile,TServerSetting& aSetting, TSettingsAccessPolicy*& aPolicy, TBool& aSingleMetaFound)
+	{
+	return iSimRep->ReadSettingSavePolicyL(aFile, aSetting, aPolicy, aSingleMetaFound);
+	}	
+
+// Merge settings in this->iSettings with the iSettings of aMergeRep
+// During an intsall/upgrade event aMergeRep will be created from the installed file
+// During an upinstall event aMergeRep will be created from the ROM file
+void CSharedRepository::MergeL(CSharedRepository& aMergeRep, TMergeType aMergeType)
+	{
+	// Process settings from main section - this updates values only
+	User::LeaveIfError(GetSettings().MergeArray(aMergeRep.GetSettings(), iSimRep->DeletedSettingsArray(), aMergeType));
+
+	//if the merging is due to a ROM Flash, we need to copy over both the NEW ROM keypsace global properties
+	//(default access policies/metadata and range policies/metadata), individual policies, we then need to ensure
+	//that the settings point at the correct individual policies and metadata.
+	if (aMergeType==ERomFlash)
+		{
+		//copy the default/range/individual policy
+		iSimRep->SetDefaultPolicy(aMergeRep.iSimRep->GetDefaultAccessPolicy());
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+		iSimRep->GetDefaultAccessPolicy().iHighKey=aMergeRep.iSimRep->GetDefaultAccessPolicy().iHighKey;
+		iSimRep->GetDefaultAccessPolicy().iKeyMask=aMergeRep.iSimRep->GetDefaultAccessPolicy().iKeyMask;		
+#endif		
+		iSimRep->RangePolicyArray().Reset();
+		TInt count=aMergeRep.iSimRep->RangePolicyArray().Count();
+		iSimRep->RangePolicyArray().ReserveL(count);
+		for (TInt i=0;i<count;i++)
+			{
+			iSimRep->RangePolicyArray().AppendL(aMergeRep.iSimRep->RangePolicyArray()[i]);
+			}
+		iSimRep->SinglePolicyArray().ResetAndDestroy();
+		count=aMergeRep.iSimRep->SinglePolicyArray().Count();
+		iSimRep->SinglePolicyArray().ReserveL(count);
+		for (TInt i=0;i<count;i++)
+			{
+			iSimRep->SinglePolicyArray().AppendL(aMergeRep.iSimRep->SinglePolicyArray()[i]);
+			}
+		//now need to reset the aMergeRep single policies so it is not going to destroy the
+		//individual policies as ownership has been transferred
+		aMergeRep.iSimRep->SinglePolicyArray().Reset();
+		
+		//copy the default/range metadata
+		iSimRep->SetDefaultMeta(aMergeRep.iSimRep->DefaultMeta());
+		iSimRep->RangeMetaArray().Reset();
+		count=aMergeRep.iSimRep->RangeMetaArray().Count();
+		iSimRep->RangeMetaArray().ReserveL(count);		
+		for (TInt i=0;i<count;i++)
+			{
+			iSimRep->RangeMetaArray().AppendL(aMergeRep.iSimRep->RangeMetaArray()[i]);
+			}
+		
+		//set the timestamp,owner etc
+		iSimRep->SetTimeStamp(aMergeRep.iSimRep->TimeStamp());
+		iSimRep->SetOwner(aMergeRep.iSimRep->Owner());
+		}
+
+	// Update all access policies and meta
+	for(TInt i=0; i<iSimRep->SettingsArray().Count();i++)
+		{
+		TServerSetting& setting= iSimRep->SettingsArray()[i];
+		setting.SetAccessPolicy(GetFallbackAccessPolicy(setting.Key()));
+		}	
+	}
+	
+// Save timestamp of installed file 
+void CSharedRepository::SetInstallTime(TTime aInstallTime)
+	{
+	iSimRep->SetTimeStamp(aInstallTime);
+	}
+	
+// Handle creation or upgrade of file in install directory
+void CSharedRepository::HandleUpdateMergeL(TTime aInstallFileTimeStamp, CSharedRepository& aInstallRep)
+	{			
+	MergeL(aInstallRep, ESWIUpgradeMerge);
+	
+	SetInstallTime(aInstallFileTimeStamp);	// Set merge timestamp		
+	CommitChangesL();						// Commit changes to write system drive file
+
+	// settings are now persistent on disk: we can now notify about the changes
+	for (TInt i = 0; i < (aInstallRep.iSimRep)->SettingsArray().Count(); i++)
+		{
+		Notify((aInstallRep.iSimRep)->SettingsArray()[i].Key());
+		}
+	}
+	
+// Handle merge activity due to an uninstall
+void CSharedRepository::HandleDeleteMergeL(CSharedRepository& aRomRep)
+	{
+	MergeL(aRomRep, ESWIDowngradeMerge);
+	
+	SetInstallTime(0);						// Reset timestamp			
+	CommitChangesL();						// Commit changes to write system drive file
+	
+	// settings are now persistent on disk: we can now notify about the changes
+	for (TInt i = 0; i < (aRomRep.iSimRep)->SettingsArray().Count(); i++)
+		{
+		Notify((aRomRep.iSimRep)->SettingsArray()[i].Key());
+		}
+	}
+	
+
+#ifdef CENTREP_CONV_TOOL
+/**
+Statement "iInconsistentData = ETrue;" must be the first statement in the method,
+"iInconsistentData = EFalse;" must be the last. It is used for lasy-load implementation
+for the repository and solves the problem that if CommitChangesL() fails the in-memory
+repository data won't match the repository data, stored in the file.
+This routine is being retained for testing purposes
+*/
+void CSharedRepository::DoCommitChangesToIniFileL(const TDesC& aOutFileName
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+	,TUint32 aCreVersion
+#endif
+	)
+	{
+	iInconsistentData=ETrue;
+
+	// should not be committing while transactions are still active
+	ASSERT(!IsTransactionActive());
+
+	iSimRep->DoCommitChangesToIniFileL(TServerResources::iFs,aOutFileName
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+	,aCreVersion
+#endif	
+	);
+	
+	iInconsistentData = EFalse;
+	}
+#endif //CENTREP_CONV_TOOL
+	
+/**
+The method reloads the repository content from a repository file.
+The current repository must be emptied (or must be empty already) before the call is made.
+@param aIniFile A reference to CIniFileIn object, which will be used to load
+				the repository content.
+@return KErrCorrupt Corrupted repository file.
+		KErrNone	The repository content was seccessfully loaded into memory.
+		KErrNotFound Setting not found in the file.
+@leave System-wide error codes.
+@leave KErrGeneral It's probably a programmer's error - current CSharedRepository 
+				   object is partially initialised.
+*/
+TInt CSharedRepository::ReloadContentL(CIniFileIn& aIniFile, TBool aFirstLoad)
+	{
+	// Preconditions - CHeapRepository object should be an empty one.
+	if(!iSimRep->IsEmpty())
+		{
+		User::Leave(KErrGeneral);
+		}
+	TInt err = iSimRep->ReloadContentExceptSettingsL(aIniFile);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+	CleanupClosePushL(iSimRep->RangeMetaArray());
+	CleanupClosePushL(iSimRep->RangePolicyArray());
+	
+	// Settings
+	TServerSetting setting;
+	TSettingsAccessPolicy* policy;
+	TBool singleMetaFound;
+	TCleanupItem tc(CHeapRepository::SinglePoliciesCleanup, &(iSimRep->SinglePolicyArray()));
+	CleanupStack::PushL(tc);	
+	CleanupClosePushL(iSimRep->SettingsArray());	
+	while((err = ReadSettingSavePolicyL(aIniFile, setting, policy, singleMetaFound)) == KErrNone)
+		{
+		setting.PushL();
+		if(iSimRep->SettingsArray().IsDefault())
+			{
+			setting.SetClean();			
+			}
+		CreateL(setting, policy, aFirstLoad, singleMetaFound);
+		setting.Pop();
+		}
+	if(err == KErrNotFound)			
+		{
+		err = KErrNone;
+		}
+	if (err == KErrNone)
+		{
+		CleanupStack::Pop(4,&(iSimRep->RangeMetaArray()));		
+		}
+	else
+		{
+		CleanupStack::PopAndDestroy(4,&(iSimRep->RangeMetaArray()));		
+		}
+	return err;
+	}
+
+/**
+Resets current repository data - actually all of them, which may be loaded from
+the related ini file.
+The iUid data member value is kept as it was at the moment of creation of 
+CSharedRepository object.
+*/
+void CSharedRepository::ResetContent()
+	{
+	iSimRep->ResetContent();
+	}
+
+/**
+This function is used to restore the notification, which was temporary disabled
+when making RestoreConsistencyL() call.
+@param aNotificationState It points to CObservable::iNotificationState data member, which 
+						 controls the notification state - active or disabled.
+@internalComponent
+*/
+static void RestoreNotification(void* aNotificationState)
+	{
+	TBool* notificationState = static_cast <TBool*> (aNotificationState);
+	*notificationState = ETrue;
+	}
+
+/**
+The method reloads the repository content from the related ini file if previous
+CommitChangesL() has not completed successfully.
+*/
+void CSharedRepository::RestoreConsistencyL()
+	{
+	//Do nothing if previous CommitChangesL() completed successfully.
+	if (!iInconsistentData)
+		{
+		return;
+		}
+	//Reset current repository data	
+	ResetContent();
+	//Disable notifications
+	TCleanupItem restoreNotification(&RestoreNotification, &iNotificationState);
+	CleanupStack::PushL(restoreNotification);
+	iNotificationState = EFalse;
+	//Reload the repository content from the related ini file
+	DoRestoreConsistencyL();
+	//Activate notifications
+	CleanupStack::PopAndDestroy();//restoreNotification
+	
+	TCentRepLocation location = EPersists;
+	HBufC* persistsTmpFilePath(NULL);
+    //allocates memory on the heap
+    TServerResources::CreateRepositoryFileNameLC(persistsTmpFilePath,iSimRep->Uid(),location,ETmp);
+	// Remove any .tmp file
+	// If a debug build - record error
+	TInt fileDeleteErr=TServerResources::iFs.Delete(*persistsTmpFilePath);
+	if ((fileDeleteErr != KErrNone) && (fileDeleteErr != KErrNotFound))
+		{
+		#ifdef _DEBUG
+		RDebug::Print(_L("CHeapRepository::RestoreConsistencyL - Failed to delete file. Error = %d"), fileDeleteErr);
+		#endif
+		}
+
+	CleanupStack::PopAndDestroy(persistsTmpFilePath);
+	
+	iInconsistentData=EFalse;
+	}
+
+/**
+The method reloads the repository content from the related cre or ini file.
+@leave System-wide error codes
+*/	
+void CSharedRepository::DoRestoreConsistencyL()
+	{
+#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
+	//note that the function below already handles the deletion of any corrupt file
+	//in  non-rom location
+	TInt ret=TServerResources::iObserver->CreateRepositoryL(this,EPersists);
+	if (ret==KErrNotFound)
+		{
+		ret=TServerResources::iObserver->CreateRepositoryL(this,EInstall);
+		if (ret==KErrNotFound)
+			{	
+			ret=TServerResources::iObserver->CreateRepositoryL(this,ERom);
+			User::LeaveIfError(ret);
+			}
+		}
+#else
+	TCentRepLocation location;
+	
+	TInt err = FindLocationForFileL(location,iSimRep->Uid(),ECre);
+	if (err != KErrNotFound)
+		{
+		User::LeaveIfError(CreateRepositoryFromCreFileL(location));
+		return;
+		}
+		
+	User::LeaveIfError(FindLocationForFileL(location,iSimRep->Uid(),EIni));
+	
+	HBufC* fileName(NULL);
+    TServerResources::CreateRepositoryFileNameLC(fileName,iSimRep->Uid(),location,EIni);	
+ 
+	CIniFileIn* iniFile = NULL;
+	err = CIniFileIn::NewLC(TServerResources::iFs,iniFile,*fileName);
+	if (err==KErrCorrupt && location!=ERom)
+		{
+		User::LeaveIfError(TServerResources::iFs.Delete(*fileName));
+		}
+	User::LeaveIfError(err);
+	
+
+	err = ReloadContentL(*iniFile);
+	User::LeaveIfError(err);
+	
+	CleanupStack::PopAndDestroy(iniFile); //iniFile 
+	CleanupStack::PopAndDestroy(fileName);	//fileName
+#endif
+	}
+
+
+/**
+This method looks for and sets a location for a given repository.
+It is based on EAuto mode thus it goes through all locations in the
+same order (EPersists - EInstall - ERom)  
+
+@param aLocation - returns a location for a repository
+@param aUid - id of a repository which location should be found
+@param aType - repository file type (.txt or .cre) 
+@return KErrNone if aLocation succesfully set for a given repository,
+		KErrNotFound if a repository was not found in any locations.
+
+@internalTechnology
+*/
+#ifndef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+TInt CSharedRepository::FindLocationForFileL(TCentRepLocation& aLocation,TUid aUid,const TCentRepFileType aType) const
+    { 		
+	if(TServerResources::CentrepFileExistsL(aUid, EPersists, aType))
+	    {
+	     aLocation = EPersists;
+		 return KErrNone;
+	    }
+	    
+	if(TServerResources::CentrepFileExistsL(aUid, EInstall, aType))
+		{
+	     aLocation = EInstall;
+		 return KErrNone;
+	    }
+	    
+	if(TServerResources::CentrepFileExistsL(aUid, ERom, aType))
+		{
+		aLocation = ERom;
+		return KErrNone;
+		}
+
+	return KErrNotFound;
+    }
+#endif
+
+TInt CSharedRepository::CreateRepositoryFromCreFileL( TCentRepLocation aLocation)
+	{
+	// Get file path name from location
+    HBufC* filePath(NULL);
+    TServerResources::CreateRepositoryFileNameLC(filePath,iSimRep->Uid(), aLocation,ECre);
+    // Trap errors from repository creation so we can delete corrupt repositories
+	TRAPD(error, iSimRep->CreateRepositoryFromCreFileL(TServerResources::iFs,*filePath));
+	if(error!=KErrNone && error!=KErrNotFound && error!=KErrNoMemory)
+		{
+		error=KErrCorrupt;
+		// store wasn't quite what we were expecting - can't return an error, can't leave
+		// so all we can do is close the file, tidy up as best we can, and return corrupt 
+		if (aLocation != ERom)
+			{
+			// If a debug build - record error
+			TInt fileDeleteErr=TServerResources::iFs.Delete(*filePath);
+			if (fileDeleteErr != KErrNone)
+				{
+				#ifdef _DEBUG
+				RDebug::Print(_L("CSharedRepository::CreateRepositoryFromCreFileL - Failed to delete file. Error = %d"), fileDeleteErr);
+				#endif
+				}
+
+			}
+		}
+	else if( error==KErrNoMemory)
+		{
+		User::Leave(KErrNoMemory);
+		}
+	CleanupStack::PopAndDestroy(filePath);
+	return error;
+	}
+
+/** Attempts to start a transaction.
+Guaranteed to succeed (return KErrNone) for EConcurrentReadWriteTransaction mode only.
+@param aTransactor transactor attempting to start transaction
+@param aMode type of transaction to be started
+@pre transactor is not in a transaction
+@return KErrNone if the transaction is started, KErrLocked if read/write locks prevented that
+type of transaction from starting now, and KErrArgument for invalid aMode.
+@post On returning KErrNone, transaction is started and read/write locks are obtained for it
+in the shared repository. Any other return: transaction has not started.
+*/
+TInt CSharedRepository::StartTransaction(CRepositoryTransactor& aTransactor, TInt aMode)
+	{
+	// session can only be in one transaction
+	ASSERT(!aTransactor.IsInTransaction());
+	
+  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+  	ASSERT(shrepinfo);
+	switch (aMode)
+		{
+		case EConcurrentReadWriteTransaction:
+			// can always start this type of transaction
+			shrepinfo->iNumActiveConcurrentReadWriteTransactions++;
+			break;
+		case EReadTransaction:
+			// negative lock means there is an active EReadWriteTransaction
+			if (shrepinfo->iPessimisticTransactionLockCount < 0)
+				{
+				ASSERT(shrepinfo->iPessimisticTransactionLockCount == -1); // sanity check
+				return KErrLocked;
+				}
+			// when non-negative lock equals number of active EReadTransactions.
+			shrepinfo->iPessimisticTransactionLockCount++;
+			break;
+		case EReadWriteTransaction:
+			// lock is zero if there are no active pessimistic transactions
+			if (shrepinfo->iPessimisticTransactionLockCount != 0)
+				{
+				return KErrLocked;
+				}
+			// lock value of -1 means the exclusive EReadWriteTransaction is active
+			shrepinfo->iPessimisticTransactionLockCount = -1;
+			break;
+		default:
+			// not a valid transaction mode
+			return KErrArgument;
+		}
+	aTransactor.AddToQueue(shrepinfo->iTransactors, aMode);
+	return KErrNone;
+	}
+
+/**	Commit transaction
+@return KErrNone on success, or error code.
+@param aKeyInfo 
+	on success (return KErrNone): aKeyInfo returns number of modified settings;
+	on failure (other error code): KUnspecifiedKey
+@pre transactor is in a transaction.
+@post transactor is not in a transaction
+*/
+TInt CSharedRepository::CommitTransaction(CRepositoryTransactor& aTransactor, TUint32& aKeyInfo)
+	{
+	// calling code should have panicked the client if not in a transaction
+	ASSERT(aTransactor.IsInTransaction());
+	TInt result = aTransactor.iTransactionResult;
+	if (aTransactor.IsInFailedTransaction())
+		{
+		ASSERT(result != KErrNone);
+		aKeyInfo = aTransactor.iTransactionErrorKey;
+		}
+	else
+		{
+		ASSERT(result == KErrNone);
+		ASSERT(aTransactor.iTransactionErrorKey == KUnspecifiedKey);
+		aKeyInfo = 0;
+		// must release locks otherwise shared repository will not commit changes
+		// failed transactions have already released their locks
+		ReleaseTransactionLock(aTransactor);
+		}
+	
+	// transactions that haven't made any changes can be closed at any time
+	if (aTransactor.IsInActiveReadWriteTransaction() &&
+		(aTransactor.iTransactionSettings.Count() > 0))
+		{
+		result = DoCommitTransactionSettings(aTransactor, aKeyInfo);
+		}
+
+	// transaction is complete - remove from queue
+  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+  	ASSERT(shrepinfo);
+	shrepinfo->iTransactors.Remove(aTransactor);
+	//Remove the link to the next transaction
+	aTransactor.iLink.iNext = NULL;
+	aTransactor.Deque();
+
+	return result;
+	}
+
+/**	Cancels the transaction, discarding changes.
+@post Not in a transaction
+*/
+void CSharedRepository::CancelTransaction(CRepositoryTransactor& aTransactor)
+	{
+	if (aTransactor.IsInTransaction())
+		{
+		ReleaseTransactionLock(aTransactor);
+	  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+	  	ASSERT(shrepinfo);
+		shrepinfo->iTransactors.Remove(aTransactor);
+		//Remove the link to the next transaction
+		aTransactor.iLink.iNext = NULL;
+		aTransactor.Deque();
+		}
+	}
+
+TInt CSharedRepository::FailTransaction(CRepositoryTransactor& aTransactor, TInt aError, TUint32 aErrorKey)
+	{
+	ASSERT(aError != KErrNone); // must fail for a reason
+	if (aTransactor.IsInActiveTransaction())
+		{
+		// locks cannot be removed from a failed transaction, so release before failing
+		ReleaseTransactionLock(aTransactor);
+		aTransactor.SetFailed(aError, aErrorKey);
+		}
+	return aError; // to allow "return FailTransaction(error, errorKey);" - error written once
+	}
+
+/** Fails all active transactions - except for the optional aExcludeTransactor, releasing locks.
+All transactions are failed with reason "KErrLocked" meaning they are "locked out".
+This should only be done to allow another agent to change values in the repository.
+Beware that all concurrent read/write transactions that are failed with KErrLocked are
+expected to retry the transactions straight afterwards - must be careful to allow their
+retry strategy to be successful.
+*/
+void CSharedRepository::FailAllTransactions(const CRepositoryTransactor* aExcludeTransactor)
+	{
+  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+  	ASSERT(shrepinfo);
+	TSglQueIter<CRepositoryTransactor> transIter(shrepinfo->iTransactors);  	
+	CRepositoryTransactor* transactor;
+	while ((transactor = transIter++) != NULL)
+		{
+		if (transactor != aExcludeTransactor)
+			{
+			FailTransaction(*transactor, KErrLocked, KUnspecifiedKey);
+			}
+		}
+	}
+
+/** must currently be in active Read transaction. Does not fail
+transaction here if promotion to read/write failed.
+@return KErrNone if promoted, KErrLocked if not
+*/
+TInt CSharedRepository::AttemptPromoteTransactionToReadWrite(CRepositoryTransactor& aTransactor)
+	{
+	// transactor should currently be in an active read transaction
+	ASSERT(aTransactor.IsInActiveReadTransaction());
+
+  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+  	ASSERT(shrepinfo);
+	// sanity check: must only be pessimistic reads active
+	ASSERT(shrepinfo->iPessimisticTransactionLockCount > 0);
+	// can promote only if there are no other active read transactions:
+	if (1 == shrepinfo->iPessimisticTransactionLockCount)
+		{
+		// may only promote to exclusive read/write as it has the same commit semantics
+		// as Read transaction: concurrent R/W must wait for reads to finish first.
+		aTransactor.PromoteToExclusiveReadWrite();
+		// lock value of -1 means the exclusive EReadWriteTransaction is active
+		shrepinfo->iPessimisticTransactionLockCount = -1;
+		return KErrNone;
+		}
+	return KErrLocked;
+	}
+
+/** Private helper method which releases any read/write locks held in the shared repository
+by this transactor. Caller must set transactor's state or remove from queue as appropriate.
+@param aTransactor transactor whose read/write locks are to be released.
+@post Any read/write locks held by transactor are released.
+*/
+void CSharedRepository::ReleaseTransactionLock(CRepositoryTransactor& aTransactor)
+	{
+  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+  	ASSERT(shrepinfo);
+	if (aTransactor.IsInActiveConcurrentReadWriteTransaction())
+		{
+		shrepinfo->iNumActiveConcurrentReadWriteTransactions--;
+		ASSERT(shrepinfo->iNumActiveConcurrentReadWriteTransactions >= 0); // sanity check
+		}
+	else if (aTransactor.IsInActiveReadTransaction())
+		{
+		shrepinfo->iPessimisticTransactionLockCount--;
+		ASSERT(shrepinfo->iPessimisticTransactionLockCount >= 0); // sanity check
+		}
+	else if (aTransactor.IsInActiveExclusiveReadWriteTransaction())
+		{
+		// can only be one exclusive read/write transaction active (lock value -1)
+		ASSERT(shrepinfo->iPessimisticTransactionLockCount == -1);
+		shrepinfo->iPessimisticTransactionLockCount = 0;
+		}
+	}
+	
+void CSharedRepository::ExternalizeCre(RWriteStream& aStream) const
+	{
+	iSimRep->ExternalizeCre(TServerResources::iPersistsVersion,aStream);
+	}
+
+void CSharedRepository::InternalizeCreL(RReadStream& aStream)
+	{
+	iSimRep->InternalizeCreL(aStream);
+	}
+	
+#ifdef	SYMBIAN_CENTREP_SUPPORT_MULTIROFS
+void CSharedRepository::InternalizeCreL(RReadStream& aStream,TUint8& aCreVersion)
+	{
+	iSimRep->InternalizeCreL(aStream,aCreVersion);
+	}
+#endif	
+
+void CSharedRepository::Notify(TUint32 aVal) const
+	{
+	if(iNotificationState)
+		{
+		TServerResources::iObserver->Notify(iSimRep->Uid(), aVal);
+		}
+	}
+
+TBool CSharedRepository::IsTransactionActive()
+	{
+  	CObservable::TSharedRepositoryInfo* shrepinfo = TServerResources::iObserver->SharedRepositoryInfo(iSimRep->Uid());
+  	if (shrepinfo)
+  		{
+		return (shrepinfo->iPessimisticTransactionLockCount != 0) ||
+			(shrepinfo->iNumActiveConcurrentReadWriteTransactions > 0);
+  		}
+  	return EFalse;  		
+	}
+
+RSettingsArray& CSharedRepository::GetSettings()
+	{
+	return iSimRep->SettingsArray();
+	}