applayerpluginsandutils/bookmarksupport/test/cenrepsrv/shrepos.cpp
changeset 0 b16258d2340f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerpluginsandutils/bookmarksupport/test/cenrepsrv/shrepos.cpp	Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,1476 @@
+// 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 "panic.h"
+#include "srvdefs.h"
+#include "srvres.h"
+#include "shrepos.h"
+#include "srvrepos.h"
+#include "srvparams.h"
+
+#ifdef SYMBIAN_CENTRALREPOSITORY_PARANOID_CHECKING
+
+/** Validates that the required invariants hold: (1) ordered by ascending key value (2) key uniqueness.
+Panics upon violation.
+*/
+void RSettingsArray::ValidateInvariantProperties() const
+	{
+	if (Count() > 0)
+		{
+		const TServerSetting* prev = &( operator[](0) );
+		const TServerSetting* curr = prev + 1;
+		const TServerSetting* upperBound = prev + Count() - 1;
+		while(curr <= upperBound)
+			{
+			// future: should replace with diagnostic panic code
+			ASSERT(curr->Key() > prev->Key());
+			prev = curr;
+			++curr;
+			}
+		}
+	}
+
+/** Validates that the required invariants hold for the given setting pointer array: 
+(1) ordered by ascending key value (2) key uniqueness. Panics upon violation.
+*/
+void RSettingsArray::ValidateInvariantProperties(const RSettingPointerArray& aPtrArray)
+	{
+	if (aPtrArray.Count() > 0)
+		{
+		const TServerSetting** prev = const_cast<const TServerSetting**>( &(aPtrArray[0]) );
+		const TServerSetting** curr = prev + 1;
+		const TServerSetting** upperBound = prev + aPtrArray.Count() - 1;
+		while(curr <= upperBound)
+			{
+			// future: should replace with diagnostic panic code
+			ASSERT((*curr)->Key() > (*prev)->Key());
+			prev = curr;
+			++curr;
+			}
+		}
+	}
+
+#endif
+
+/** Returns pointers to all settings whose key matches all bits of the target id also included
+in the bitwise mask.
+
+@param	aTargetKey Bit pattern to match
+@param	aMask Bitwise mask. Where bits are set the corresponding bit in aTargetKey is significant, ie
+		AND behaviour conventional with masking
+@param	aMatches Returns pointers to all settings with keys matching the mask, in ascending key order. The
+		caller should ensure it is appropriately constructed for the likely growth pattern.
+@return	Error code. aMatches may be modified even upon error return but the contents must not be relied upon.
+*/
+TInt RSettingsArray::Find(TUint32 aTargetKey, TUint32 aMask, RSettingPointerArray& aMatches) const
+	{
+#ifdef SYMBIAN_CENTRALREPOSITORY_PARANOID_CHECKING
+	ValidateInvariantProperties();
+#endif
+
+	aMatches.Reset();
+	// Find the first setting with key >= the lowest possible match
+	const TInt upperIdx = Count() - 1;
+	const TUint32 maskedTarget = aTargetKey & aMask;
+	TInt lowerIdx;
+	FindInUnsignedKeyOrder(TServerSetting(maskedTarget), lowerIdx);
+	if(lowerIdx > upperIdx)
+		{
+		return KErrNone;
+		}
+	
+	// this simply traverses the settings from the first possible match to the last. For masks with
+	// only with higher bits this would be wasteful - in principle could jump to next possible match start
+	// with another Find...() call. However logic more complex and counterproductive in some cases; would
+	// need some heuristic such as probing N settings ahead of current point and only invoking the refind
+	// if that still falls below the next range start, where N would allow for the cost of the binsearch
+	// and other book-keeping (for real smartness construct a new RArray from the current point onwards,
+	// so binsearch excludes the already known infertile preceding settings). Only worth pursuing after
+	// profiling.
+	const TUint32 upperMatchingKey = aTargetKey | ~aMask;
+	const TServerSetting* setting = &( operator[](lowerIdx) );
+	const TServerSetting* upperBound = setting + (upperIdx - lowerIdx);
+	while(setting <= upperBound && setting->Key() <= upperMatchingKey)
+		{
+		if((setting->Key() & aMask) == maskedTarget)
+			{
+			TInt err = aMatches.Append(setting);
+			// Small optimisation of not testing err in while() condition, presuming
+			// that Append() far less common than key tests, ie repeatedly testing err
+			// is wasteful. However (arguably) makes code more complex
+			if(err != KErrNone)
+				{
+				aMatches.Reset();
+				return err;
+				}
+			}
+		++setting;
+		}
+	return KErrNone;
+	}
+
+/** Given source and destination arrays of settings, replaces the destination with the union of the
+arrays. The properties of ascending key order and key uniqueness are preserved: where a key is common
+to both arrays the source setting is kept, excepting where the source setting is flagged as deleted, which
+simply deletes the destination
+
+@param	aDst destination settings array
+@param	aSrc source settings array
+@return Error code. If not KErrNone then the contents of aDst are may have been modified and must be
+		disregarded
+@post	aDst contains the union and matches the setting array invariant
+*/
+TInt RSettingsArray::Merge(RSettingPointerArray& aDst, const RSettingPointerArray& aSrc)
+	{
+	const TServerSetting** srcBound;
+	const TServerSetting** srcPtr;
+	TInt count = aSrc.Count();
+	if(count > 0)
+		{
+		srcPtr = const_cast<const TServerSetting**>( &(aSrc[0]) );
+		srcBound = srcPtr + count;
+		}
+	else
+		{
+		srcPtr = NULL;
+		srcBound = NULL;
+		}
+
+	TInt dstIdx = 0;
+	const TServerSetting** dstPtr=NULL;
+	const TServerSetting** dstBound=NULL;
+
+	// The approach taken here of inserting entries one at a time is necessarily inefficient
+	// given the RPointerArray interface, but may be adequate for the projected (small) use. For 
+	// greater efficiency the ability to insert ranges is required, ie probably custom array code
+	while(srcPtr < srcBound)
+		{
+		if (aDst.Count() > 0)
+			{
+			dstBound = const_cast<const TServerSetting**>( &(aDst[0]) ) + aDst.Count();
+			dstPtr=const_cast<const TServerSetting**>( &(aDst[0]) )+ dstIdx;
+			}
+		const TUint32 srcKey = (*srcPtr)->Key();
+		while(dstPtr < dstBound && srcKey > (*dstPtr)->Key())
+			{
+			++dstPtr;
+			++dstIdx;
+			}
+		// Three possibilities: end of dst reached (append src), src and dst match (replace dst), 
+		// and dst now greater than src (insert src)
+		if((dstPtr == dstBound || (*dstPtr)->Key() > srcKey))
+			{
+			if(!(*srcPtr)->IsDeleted())	// drop deleted records
+				{
+				TInt ret = aDst.Insert(*srcPtr, dstIdx);	// presumes insert at end == append
+				if(ret != KErrNone)
+					{
+					return ret;
+					}
+				++dstIdx;
+				}
+			}
+		else
+			{
+			// Src key matches dst, replace or delete dst
+			if(!(*srcPtr)->IsDeleted())
+				{
+				*dstPtr= *srcPtr;
+				++dstIdx;
+				}
+			else
+				{
+				// may be more efficient ways of handling remove
+				aDst.Remove(dstIdx);
+				--dstBound;
+				}
+			}
+		++srcPtr;
+		}
+#ifdef SYMBIAN_CENTRALREPOSITORY_PARANOID_CHECKING
+	RSettingsArray::ValidateInvariantProperties(aDst);
+#endif
+	return KErrNone;
+	}
+
+CSharedRepository::CSharedRepository(TUid aUid) :
+	iSettings(), iUid(aUid),
+	iSinglePolicies(KGranularity),
+	iTransactors(_FOFF(CRepositoryTransactor, iLink))
+	{
+	iPersistsIniFileExists = ETrue;
+	
+	// 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 == EReadTransaction);
+	ASSERT(CRepository::EConcurrentReadWriteTransaction == EConcurrentReadWriteTransaction);
+	ASSERT(CRepository::EReadWriteTransaction == EReadWriteTransaction);
+	}
+	
+CSharedRepository::~CSharedRepository()
+	{
+	// sanity check that no transactions are active
+	ASSERT(!IsTransactionActive());
+	// check transactor queue is empty - note this includes failed transactions
+	ASSERT(NULL == (CRepositoryTransactor*)TDblQueIter<CRepositoryTransactor>(iTransactors));
+
+	iSinglePolicies.ResetAndDestroy();
+	iDeletedSettings.Close();
+	}
+
+TUid CSharedRepository::Uid() const
+	{
+	return iUid;
+	}
+
+/**
+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()
+	{
+	TRAPD(error, DoCommitChangesL());
+	if (error != KErrNone)
+		{
+		ResetContent();
+		}
+	return error;
+	}
+
+/** Merges the aChanges settings into array. Is used for
+	Transaction merges
+	Restore merges
+	SWI merges
+
+	Works as follows:
+(a) EDeleted settings in aChanges destroy the corresponding setting in this array (if any)
+(b) Where matching settings exist in both arrays, data from aChanges replaces originals. 
+    Matching depends on aKeyOnly parameter's value. If true, matching is only
+    based on key. If false, settings values will be compared
+    For SWI merges this replacement is also dependent on whether the setting has been modified
+(c)	aMergeType is the merge type
+Future: All descriptors are deeply copied; must change to use shallow copy for greater efficiency.
+@post Following a requirement that notifications are only made if values have changed:
+1. Settings flagged as deleted without a counterpart in the persistent array are removed from aChanges.
+2. Where the new value and the existing value are the same, the setting is removed from aChanges.
+*/
+TInt RSettingsArray::MergeArray(RSettingsArray& aChanges, RArray<TUint32> & aDeletedSettings, TMergeType aMergeType, TBool aKeyOnly)
+	{
+	TInt error = KErrNone;
+	TInt numChanges;
+	TInt i;
+		
+	// For downgrade remove SWI only keys
+	if(aMergeType==ESWIDowngradeMerge)
+		{
+		numChanges = Count();
+		i = 0;
+		while ((i < numChanges) && (KErrNone == error))
+			{
+			TServerSetting source = operator[](i);
+			// find index of item in array matching the index of this change
+			TInt targetIndex = aChanges.FindIndex(source);
+			if (targetIndex == KErrNotFound)
+				{
+				// If key is default and wasn't in the ROM, it was an install key
+				// so remove it
+				if(source.IsClean())
+					{
+					DeleteElement(i);
+					--numChanges;
+					--i;
+					}
+				}
+			++i;
+			}
+		}
+
+	numChanges = aChanges.Count();
+	i=0;
+	
+	while ((i < numChanges) && (KErrNone == error))
+		{
+		const TServerSetting& source = aChanges[i];
+		// find index of item in array matching the index of this change
+		TInt targetIndex = FindIndex(source);
+		if (targetIndex == KErrNotFound)
+			{
+			if (source.IsDeleted())
+				{
+				// remove setting that is flagged as deleted to prevent notification
+				aChanges.DeleteElement(i);
+				i--;
+				numChanges--;
+				}
+			else
+				{
+				// add the new setting
+				TServerSetting newSetting(source.Key());
+				error = newSetting.Replace(source);
+				if (error == KErrNone)
+					{
+					error = OrderedInsert(newSetting);
+					TInt deletedSetting = aDeletedSettings.FindInUnsignedKeyOrder(source.Key());
+					if (KErrNotFound != deletedSetting)
+						{
+						aDeletedSettings.Remove(deletedSetting) ;
+						}
+					if (error != KErrNone)
+						{
+						newSetting.Reset();
+						}
+					}
+				}
+			}
+		else
+			{
+			if (source.IsDeleted())
+				{
+				// Retain "deleted element" state for settings marked for backup so that
+				// we can persist state correctly across a backup/restore cycle.
+				if (operator[](targetIndex).Meta() & KMetaBackup)
+					{
+						aDeletedSettings.InsertInUnsignedKeyOrder(source.Key()) ;
+					}
+				DeleteElement(targetIndex);
+				}
+			else
+				{
+				TServerSetting& target = operator[](targetIndex);
+				if ((target == source) && (aKeyOnly==EFalse))
+					{
+					// value not changing: remove setting to prevent notification
+					// Note that for SWI merges, settings are not deleted from 
+					// aChanges unless they are marked with EDeleted.
+					aChanges.DeleteElement(i);
+					i--;
+					numChanges--;
+					}
+				else
+					{						
+					if( (aMergeType==ESWIUpgradeMerge) || (aMergeType==ESWIDowngradeMerge))
+						{
+						if(target.IsClean())
+							{
+							error = target.Replace(source);
+							}
+						else
+							{
+							// value not changing: remove setting to prevent notification
+							aChanges.DeleteElement(i);
+							i--;
+							numChanges--;
+							}
+						}
+					else
+						{
+						error = target.Replace(source);
+						}
+					}
+				}
+			}
+		i++;
+		}
+	aDeletedSettings.Compress();
+	return error;
+	}
+
+// 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 = iSettings.MergeArray(aTransactor.iTransactionSettings, iDeletedSettings, ETransactionMerge, EFalse);
+	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();
+		}
+	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)
+	{
+	TInt isMetaFlagSet = aSetting.Meta() & KMetaDefaultValue;
+	
+	if(!aSingleMetaFound)
+		// No single metadata set for this key
+		{
+		// First check for a matching "range" default metadata
+		// setting
+		TSettingsDefaultMeta *defaultMeta = iRangeMeta.Find(aSetting.Key());
+		if (defaultMeta)
+			{
+			if (isMetaFlagSet)
+				//sets a default meta data
+				//also sets the flag back to indicate that it is a default setting from ROM 
+				//or previous install so it can be replaced later with a new one. 
+				aSetting.SetMeta(defaultMeta->GetDefaultMetadata() | KMetaDefaultValue);
+			else
+				aSetting.SetMeta(defaultMeta->GetDefaultMetadata());
+			}
+		else
+			{
+			// Range value not found, try for a repository default
+			if (isMetaFlagSet)	
+				aSetting.SetMeta(iDefaultMeta | KMetaDefaultValue) ;
+			else
+				aSetting.SetMeta(iDefaultMeta) ;
+			}
+		}
+	}
+
+TInt CSharedRepository::CreateL(TServerSetting& aSetting, TSettingsAccessPolicy* &aPolicy, TBool aSingleMetaFound)
+	{
+	if(iSettings.Find(aSetting.Key()))
+		return KErrAlreadyExists;
+	
+	SetMetaDataOnRead( aSetting, aSingleMetaFound);
+		
+	TUint32 key = aSetting.Key();
+	aSetting.SetAccessPolicy(aPolicy);
+
+	iSettings.OrderedInsertL(aSetting);
+	Notify(aSetting.Key());
+	return KErrNone;
+	}
+
+// 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 = iSettings.Find(aId);
+	if(!s)
+		return KErrNotFound;
+
+	iSettings.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 = iSettings.Find(aId);
+	if(!s)
+		return KErrNotFound;
+
+	iSettings.Remove(aId);
+	Notify(aId);
+	return KErrNone;
+	}
+
+TInt CSharedRepository::ResetNoPersistL(TServerSetting& aSetting)
+	{
+	TServerSetting* s = iSettings.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();
+			iSettings.OrderedInsertL(setting);
+			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.iSettings.Count();
+	TInt count = iSettings.Count();
+
+	TInt newIndex = 0;
+	TInt index = 0;
+
+	while(newIndex<newCount && index<count)
+		{
+		const TServerSetting& newSetting = aNewContent.iSettings[newIndex];
+		const TServerSetting& setting = iSettings[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.iSettings[newIndex++].Key());
+
+	while(index<count)
+		Notify(iSettings[index++].Key());
+
+	// Replace current settings with settings read from ROM, this 
+	// will leave settings pointing to new single policies
+	iSettings.AdoptL(aNewContent.iSettings);
+
+	// Reset policy pointers to point at this repositories policies
+	newCount=iSettings.Count();
+	for(TInt i=0; i<newCount;i++)
+		{
+		iSettings[i].SetAccessPolicy(NULL);
+		TUint32 key = iSettings[i].Key();
+		iSettings[i].SetAccessPolicy(GetFallbackAccessPolicy(key));
+		}	
+
+	iInconsistentData = EFalse;
+	return KErrNone;
+	}
+	
+// Comparison relation to allow single policies to be inserted in order
+TBool CSharedRepository::CompareKeyIds(TSettingsAccessPolicy const &aSinglePolicy, TSettingsAccessPolicy const &aSinglePolicyIndexItem)
+	{
+	if(aSinglePolicy.iLowKey==aSinglePolicyIndexItem.iLowKey)
+		return 0;
+	return (aSinglePolicy.iLowKey < aSinglePolicyIndexItem.iLowKey)?-1:1;
+	}
+
+// Identity relation to allow single policy for a given key to be found
+TBool CSharedRepository::SinglePolicyMatchOnKey(TSettingsAccessPolicy const &aSinglePolicy, TSettingsAccessPolicy const &aSinglePolicyIndexItem)
+	{
+	return aSinglePolicy.iLowKey==aSinglePolicyIndexItem.iLowKey;
+	}
+
+// returns the read security policy used if there is no per-setting policy at aId
+const TSecurityPolicy& CSharedRepository::GetFallbackReadAccessPolicy(TUint32 aId)
+	{
+	return *(GetFallbackAccessPolicy(aId)->GetReadAccessPolicy());
+	}
+
+// returns the write security policy used if there is no per-setting policy at aId
+const TSecurityPolicy& CSharedRepository::GetFallbackWriteAccessPolicy(TUint32 aId)
+	{
+	return *(GetFallbackAccessPolicy(aId)->GetWriteAccessPolicy());
+	}
+
+// Get pointer to security policy that applies to a given setting
+TSettingsAccessPolicy* CSharedRepository::GetFallbackAccessPolicy(TUint32 aId)
+	{
+	// Check for single policy
+	TSettingsAccessPolicy policy(aId);
+	TIdentityRelation<TSettingsAccessPolicy> identity(SinglePolicyMatchOnKey);
+	TInt index = iSinglePolicies.Find(&policy, identity);
+	if(KErrNotFound != index)
+		return iSinglePolicies[index];
+	
+	// check if the aId falls into any range specified in the ini file
+	TSettingsAccessPolicy* rangePolicy = iRangePolicies.Find(aId);
+	if(rangePolicy)
+		return rangePolicy;
+	
+	// If no single policy or range policy, return default policy
+	return &iDefaultPolicy;
+	}
+
+
+TInt CSharedRepository::ReadSettingSavePolicyL(CIniFileIn& aFile,TServerSetting& aSetting, TSettingsAccessPolicy* &aPolicy, TBool& aSingleMetaFound)
+	{
+	TBool singleReadPolicyFound;
+	TBool singleWritePolicyFound;
+	TSecurityPolicy singleReadPolicy;
+	TSecurityPolicy singleWritePolicy;
+
+	TInt err=aFile.ReadSettingL(aSetting,singleReadPolicy, singleWritePolicy, singleReadPolicyFound, singleWritePolicyFound, aSingleMetaFound);
+	if(err!=KErrNone)
+		return err;
+	
+	// Set up single policies
+	if(!singleReadPolicyFound)
+		singleReadPolicy=GetDefaultReadAccessPolicy();
+	if(!singleWritePolicyFound)
+		singleWritePolicy=GetDefaultWriteAccessPolicy();
+
+	aSetting.PushL();
+	if(singleReadPolicyFound || singleWritePolicyFound)
+		{
+		aPolicy=new (ELeave) TSettingsAccessPolicy(singleReadPolicy,singleWritePolicy,aSetting.Key());
+		CleanupStack::PushL(aPolicy);
+		TLinearOrder<TSettingsAccessPolicy> order(&CSharedRepository::CompareKeyIds);
+		SinglePolicyArray().InsertInOrderL(aPolicy, order);
+		CleanupStack::Pop(aPolicy);
+		}
+	else
+		{
+		// check if the aId falls into any range specified in the ini file
+		// otherwise set policy to default policy
+		TSettingsAccessPolicy* rangePolicy = iRangePolicies.Find(aSetting.Key());
+		if(rangePolicy)
+			aPolicy=rangePolicy;
+		else
+			aPolicy=&iDefaultPolicy;
+		}
+		
+	aSetting.Pop();
+	return err;
+	}	
+
+// 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(iSettings.MergeArray(aMergeRep.iSettings, iDeletedSettings, aMergeType));
+		
+	// Update all access policies and meta
+	for(TInt i=0; i<iSettings.Count();i++)
+		{
+		TServerSetting& setting= iSettings[i];
+		setting.SetAccessPolicy(GetFallbackAccessPolicy(setting.Key()));
+		}
+	}
+
+// Get timestamp of installed file
+TTime CSharedRepository::InstallTime()
+	{
+	return iTimeStamp;
+	}
+	
+// Save timestamp of installed file 
+void CSharedRepository::SetInstallTime(TTime aInstallTime)
+	{
+	iTimeStamp = aInstallTime;
+	}
+    
+// Return if this repository's installed file exists and if it does
+// return the file time stamp as well
+TInt CSharedRepository::InstallFileTimeStampL(TTime& aModified)
+	{
+	// Ensure that there is an install directory
+	if( !TServerResources::iInstallDirectory)
+		{
+		return KErrNotFound;
+		}
+	
+	// Get name for open repository
+	// Look for .cre file first
+	HBufC* fullPath(NULL);
+	TCentRepLocation location=EInstall;
+    TServerResources::CreateRepositoryFileNameLC(fullPath, iUid, location, ECre);
+		
+	// Look in install directory to see if this repository has been hit
+	TEntry entry;
+	TInt r=TServerResources::iFs.Entry(fullPath->Des(),entry);
+	if( r == KErrNone)
+		{
+		aModified=entry.iModified;
+		}
+	else if( r== KErrNotFound)
+		{
+		// Look for txt file
+    	TServerResources::CreateRepositoryFileNameLC(fullPath, iUid, location, EIni);
+		r=TServerResources::iFs.Entry(fullPath->Des(),entry);
+		if( r == KErrNone)
+			{
+			aModified=entry.iModified;
+			}	
+		}
+	return r;
+	}
+	
+// 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 C: file
+
+	// settings are now persistent on disk: we can now notify about the changes
+	for (TInt i = 0; i < aInstallRep.iSettings.Count(); i++)
+		{
+		Notify(aInstallRep.iSettings[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 C: file
+	
+	// settings are now persistent on disk: we can now notify about the changes
+	for (TInt i = 0; i < aRomRep.iSettings.Count(); i++)
+		{
+		Notify(aRomRep.iSettings[i].Key());
+		}
+	}
+	
+
+/**
+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)
+	{
+	iInconsistentData = ETrue;
+
+	// should not be committing while transactions are still active
+	ASSERT(!IsTransactionActive());
+
+	CIniFileOut* out = CIniFileOut::NewLC();
+
+	out->WriteHeaderL();
+	out->WriteOwnerSectionL(iOwner);
+	out->WriteTimeStampL(iTimeStamp);
+	out->WriteMetaDataL(iDefaultMeta, iRangeMeta);
+	out->WritePlatSecL(iDefaultReadPolicy, iDefaultWritePolicy, iRangePolicies);
+
+	out->WriteMainSectionHeaderL();
+	for(TInt i=0; i<iSettings.Count(); i++)
+		{
+		const TServerSetting& setting = iSettings[i];
+		if (setting.HasAccessPolicy() && (iSinglePolicies.Find(setting.AccessPolicy()) != KErrNotFound))
+			{
+			out->WriteSettingL(setting, *setting.AccessPolicy());
+			}
+		else
+			{
+			out->WriteSettingL(setting);
+			}
+		}
+
+	out->CommitL(aOutFileName);
+	CleanupStack::PopAndDestroy(out);//out
+	iInconsistentData = EFalse;
+	}
+
+
+/**
+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.
+*/
+void CSharedRepository::DoCommitChangesL() 
+	{
+	iInconsistentData = ETrue;
+	
+	// should not be committing while transactions are still active
+	ASSERT(!IsTransactionActive());
+	
+	TCentRepLocation location = EPersists;
+	HBufC* persistsTrnsFilePath(NULL);
+    //allocates memory on the heap
+    TServerResources::CreateRepositoryFileNameLC(persistsTrnsFilePath,iUid,location,ETmp);
+	// Create file store
+	CDirectFileStore* store = CDirectFileStore::ReplaceLC(TServerResources::iFs, *persistsTrnsFilePath,
+															  (EFileWrite | EFileShareExclusive));
+	const TUid uid2	 = KNullUid ;														 
+	store->SetTypeL(TUidType(KDirectFileStoreLayoutUid, uid2, KServerUid3)) ; 
+
+	// Write the stream index/dictionary as root stream within the store
+	// so we can access it when we do a restore later on
+	RStoreWriteStream rootStream ;
+	TStreamId rootStreamId = rootStream.CreateLC(*store) ;
+	ExternalizeCre(rootStream) ;
+	rootStream.CommitL() ;
+		
+	CleanupStack::PopAndDestroy(&rootStream) ;
+	store->SetRootL(rootStreamId);
+	store->CommitL();
+	CleanupStack::PopAndDestroy(store) ;	
+	
+	HBufC* persistsFilePath(NULL);	   
+	TServerResources::CreateRepositoryFileNameLC(persistsFilePath,iUid,location,ECre);
+	TEntry entry;
+	if(TServerResources::iFs.Entry(*persistsFilePath,entry)==KErrNone)
+		{
+		User::LeaveIfError(TServerResources::iFs.Replace(*persistsTrnsFilePath, *persistsFilePath));
+		}
+	else
+		{
+		User::LeaveIfError(TServerResources::iFs.Rename(*persistsTrnsFilePath, *persistsFilePath));
+		}
+	
+	CleanupStack::PopAndDestroy(persistsFilePath);
+	CleanupStack::PopAndDestroy(persistsTrnsFilePath);		
+	iInconsistentData = EFalse;		
+	
+	// Delete any exitsing ini file on 1st sucessful externalizing of repository
+	if(iPersistsIniFileExists)
+		{
+		HBufC* iniFileName(NULL);	   
+	    TServerResources::CreateRepositoryFileNameLC(iniFileName,iUid,location,EIni);	
+		TServerResources::iFs.Delete(*iniFileName);
+		CleanupStack::PopAndDestroy(iniFileName);
+		iPersistsIniFileExists=EFalse;
+		}
+	}
+
+/**
+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 mistake - current CSharedRepository 
+				   object is partially initialised.
+*/
+TInt CSharedRepository::ReloadContentL(CIniFileIn& aIniFile)
+	{
+	// Preconditions - CSharedRepository object should be an empty one.
+	if(iSettings.Count() != 0 || iRangeMeta.Count() != 0 ||
+	   iSinglePolicies.Count() != 0 || iRangePolicies.Count() != 0)
+		{
+		User::Leave(KErrGeneral);
+		}
+	// Look for an "owner" section
+	TUint32 uidValue(KNullUid.iUid);
+	TInt err = aIniFile.ReadOwnerSectionL(uidValue);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+	iOwner.iUid = uidValue;
+	// Timestamp
+	TTime timeStamp (0);
+	err = aIniFile.ReadTimeStampSectionL(timeStamp);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+	if(timeStamp.Int64() != 0)
+		{
+		iTimeStamp = timeStamp;
+		}
+
+	// Metadata
+	err = aIniFile.ReadDefaultMetaSecSectionL(iDefaultMeta, iRangeMeta);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+	// Default read/write policies
+	TBool gotDefaultReadPolicy;
+	TBool gotDefaultWritePolicy;
+	err = aIniFile.ReadPlatSecSectionL(iDefaultReadPolicy, gotDefaultReadPolicy,
+									   iDefaultWritePolicy, gotDefaultWritePolicy,
+									   iRangePolicies);
+	if(err == KErrCorrupt)
+		{
+		return err;
+		}
+		
+	iDefaultPolicy=TSettingsAccessPolicy(iDefaultReadPolicy,iDefaultWritePolicy, KUnspecifiedKey);
+
+	// Settings
+	TServerSetting setting;
+	TSettingsAccessPolicy* policy;
+	TBool singleMetaFound;
+	while((err = ReadSettingSavePolicyL(aIniFile, setting, policy, singleMetaFound)) == KErrNone)
+		{
+		setting.PushL();
+		if(iSettings.IsDefault())
+			{
+			setting.SetClean();			
+			}
+		User::LeaveIfError(CreateL(setting, policy, singleMetaFound));
+		setting.Pop();
+		}
+	if(err == KErrNotFound)			
+		{
+		return KErrNone;
+		}
+	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()
+	{
+	iSettings.Reset();
+	iOwner = KNullUid;
+	iTimeStamp = TTime(0);
+
+	for (TInt i=0;i<iSinglePolicies.Count();i++)
+		{
+		delete iSinglePolicies[i];
+		}
+	iSinglePolicies.Reset();
+	iRangePolicies.Reset();
+	iDefaultReadPolicy = TSecurityPolicy();
+	iDefaultWritePolicy = TSecurityPolicy();
+	iDefaultPolicy=TSettingsAccessPolicy(iDefaultReadPolicy,iDefaultWritePolicy, KUnspecifiedKey);
+	iDefaultMeta = 0;
+	iRangeMeta.Reset();
+	}
+
+/**
+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,iUid,location,ETmp);
+	// Remove any .tmp file
+	TServerResources::iFs.Delete(*persistsTmpFilePath);
+	CleanupStack::PopAndDestroy(persistsTmpFilePath);
+	
+	iInconsistentData = EFalse;	
+	}
+
+/**
+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
+*/
+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;
+    }
+    
+/**
+The method reloads the repository content from the related cre or ini file.
+@leave System-wide error codes
+*/	
+void CSharedRepository::DoRestoreConsistencyL()
+	{
+	 TCentRepLocation location;
+	
+	TInt err = FindLocationForFileL(location,iUid,ECre);
+	if (err != KErrNotFound)
+		{
+		User::LeaveIfError(CreateRepositoryFromCreFileL(location));
+		return;
+		}
+		
+	User::LeaveIfError(FindLocationForFileL(location,iUid,EIni));
+	
+	HBufC* fileName(NULL);
+    TServerResources::CreateRepositoryFileNameLC(fileName,iUid,location,EIni);	
+ 
+	CIniFileIn* iniFile = NULL;
+	err = CIniFileIn::NewLC(iniFile,fileName,location);
+	User::LeaveIfError(err);
+	
+
+	err = ReloadContentL(*iniFile);
+	User::LeaveIfError(err);
+	
+	CleanupStack::PopAndDestroy(iniFile); //iniFile 
+	CleanupStack::PopAndDestroy(fileName);	//fileName
+	fileName=0;
+	}
+    
+TInt CSharedRepository::CreateRepositoryFromCreFileL( TCentRepLocation aLocation)
+	{
+	// Get file path name from location
+    HBufC* filePath(NULL);
+    TServerResources::CreateRepositoryFileNameLC(filePath,iUid, aLocation,ECre);
+    // Trap errors from repository creation so we can delete corrupt repositories
+	TRAPD(error, CreateRepositoryFromCreFileL(*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)
+			{
+			TServerResources::iFs.Delete(*filePath) ;
+			}
+		}
+	else if( error==KErrNoMemory)
+		{
+		User::Leave(KErrNoMemory);
+		}
+	CleanupStack::PopAndDestroy(filePath);
+	return error;
+	}
+    
+void CSharedRepository::CreateRepositoryFromCreFileL(TDesC& aFilePath )
+	{	
+
+	TEntry entry;
+	TInt e = TServerResources::iFs.Entry(aFilePath, entry);	
+	if(e==KErrNotFound || e==KErrPathNotFound)
+		{
+		User::Leave( KErrNotFound);
+		}
+
+	CDirectFileStore* store = 
+	    CDirectFileStore::OpenLC (TServerResources::iFs,aFilePath, EFileRead|EFileShareReadersOnly);
+	if(store->Type()[0] != KDirectFileStoreLayoutUid)
+		{
+		User::Leave(KErrCorrupt);
+		}
+
+	// Get the root stream and attempt to read the index from it
+	TStreamId rootStreamId = store->Root() ;
+	RStoreReadStream rootStream ;
+	rootStream.OpenLC(*store, rootStreamId);
+	// Internalize the repository
+	InternalizeCreL(rootStream);
+	CleanupStack::PopAndDestroy(&rootStream);
+	CleanupStack::PopAndDestroy(store);
+	}
+
+/** 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());
+	switch (aMode)
+		{
+		case EConcurrentReadWriteTransaction:
+			// can always start this type of transaction
+			iNumActiveConcurrentReadWriteTransactions++;
+			break;
+		case EReadTransaction:
+			// negative lock means there is an active EReadWriteTransaction
+			if (iPessimisticTransactionLockCount < 0)
+				{
+				ASSERT(iPessimisticTransactionLockCount == -1); // sanity check
+				return KErrLocked;
+				}
+			// when non-negative lock equals number of active EReadTransactions.
+			iPessimisticTransactionLockCount++;
+			break;
+		case EReadWriteTransaction:
+			// lock is zero if there are no active pessimistic transactions
+			if (iPessimisticTransactionLockCount != 0)
+				{
+				return KErrLocked;
+				}
+			// lock value of -1 means the exclusive EReadWriteTransaction is active
+			iPessimisticTransactionLockCount = -1;
+			break;
+		default:
+			// not a valid transaction mode
+			return KErrArgument;
+		}
+	aTransactor.AddToQueue(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
+	aTransactor.Deque();
+
+	return result;
+	}
+
+/**	Cancels the transaction, discarding changes.
+@post Not in a transaction
+*/
+void CSharedRepository::CancelTransaction(CRepositoryTransactor& aTransactor)
+	{
+	if (aTransactor.IsInTransaction())
+		{
+		ReleaseTransactionLock(aTransactor);
+		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)
+	{
+		TDblQueIter<CRepositoryTransactor> transIter(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());
+	// sanity check: must only be pessimistic reads active
+	ASSERT(iPessimisticTransactionLockCount > 0);
+	// can promote only if there are no other active read transactions:
+	if (1 == 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
+		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)
+	{
+	if (aTransactor.IsInActiveConcurrentReadWriteTransaction())
+		{
+		iNumActiveConcurrentReadWriteTransactions--;
+		ASSERT(iNumActiveConcurrentReadWriteTransactions >= 0); // sanity check
+		}
+	else if (aTransactor.IsInActiveReadTransaction())
+		{
+		iPessimisticTransactionLockCount--;
+		ASSERT(iPessimisticTransactionLockCount >= 0); // sanity check
+		}
+	else if (aTransactor.IsInActiveExclusiveReadWriteTransaction())
+		{
+		// can only be one exclusive read/write transaction active (lock value -1)
+		ASSERT(iPessimisticTransactionLockCount == -1);
+		iPessimisticTransactionLockCount = 0;
+		}
+	}
+	
+void CSharedRepository::ExternalizeCre(RWriteStream& aStream) const
+	{
+	aStream << TServerResources::iPersistsVersion;
+	aStream << iUid ;
+	aStream << iOwner ;
+	
+	TUint32 count=iSinglePolicies.Count();
+	aStream << count;
+	for(TInt i=0; i<count;i++)
+		{
+		aStream << *iSinglePolicies[i];
+		}
+	
+	aStream << iRangePolicies ;
+	aStream << iDefaultReadPolicy.Package() ;
+	aStream << iDefaultWritePolicy.Package() ;
+	
+	aStream << iDefaultMeta ;
+	aStream << iRangeMeta ;
+	aStream << iTimeStamp.Int64() ;
+
+	aStream << iSettings ;
+	
+	// Deleted settings
+	count = iDeletedSettings.Count() ;
+	aStream << count ;
+	for (TInt i=0; i<count; i++)
+		{
+		aStream << iDeletedSettings[i];
+		}
+	}
+
+void CSharedRepository::InternalizeCreL(RReadStream& aStream)
+	{
+	TUint8 version;
+	aStream >> version;
+	aStream >> iUid ;
+	aStream >> iOwner ;
+	
+	TUint32 count;
+	aStream >> count;
+	for(TInt i=0; i<count;i++)
+		{
+		TSettingsAccessPolicy* singlePolicy = new(ELeave) TSettingsAccessPolicy;
+		CleanupStack::PushL(singlePolicy);
+		aStream >> *singlePolicy;
+		iSinglePolicies.AppendL(singlePolicy);
+		CleanupStack::Pop(singlePolicy);
+		}
+	
+	iRangePolicies.Reset();		
+	aStream >> iRangePolicies ;
+	
+	HBufC8* securityPolicyPackage ;
+	securityPolicyPackage = HBufC8::NewLC(aStream, 10000) ;
+	iDefaultReadPolicy.Set(securityPolicyPackage->Des()) ;
+	CleanupStack::PopAndDestroy(securityPolicyPackage) ;
+	securityPolicyPackage = HBufC8::NewLC(aStream, 10000) ;
+	iDefaultWritePolicy.Set(securityPolicyPackage->Des()) ;
+	CleanupStack::PopAndDestroy(securityPolicyPackage) ;
+	
+	iDefaultPolicy=TSettingsAccessPolicy(iDefaultReadPolicy,iDefaultWritePolicy, KUnspecifiedKey);
+	
+	aStream >> iDefaultMeta ;
+	
+	iRangeMeta.Reset();
+	aStream >> iRangeMeta ;
+	
+	TInt64 timeStampInt ;
+	aStream >> timeStampInt ;
+	iTimeStamp = timeStampInt ;
+
+	iSettings.Reset() ;
+	aStream >> iSettings ;
+	
+	if (version >= KPersistFormatSupportsDeletedSettings)
+		{
+		// Deleted Settings 
+		// Deleted settings
+		aStream >> count  ;
+		for (TInt i=0; i<count; i++)
+			{
+			TUint32 keyValue ;
+			aStream >> keyValue ;
+			iDeletedSettings.InsertInUnsignedKeyOrder(keyValue);
+			}
+		}
+	// Set up access policies
+	TInt32 numElements = iSettings.Count();
+	for (TInt32 count = 0; count < numElements; count++)
+		{
+		TServerSetting* setting= &iSettings[count];
+		TUint32 key=setting->Key();
+		setting->SetAccessPolicy(GetFallbackAccessPolicy(key));
+		}
+	}
+	
+void CSharedRepository::SetAllDefaultMetaFlags()	
+    {
+    TInt y = iSettings.Count();
+    for (TInt i=0; i < iSettings.Count(); i++)
+        {
+        TUint32 meta = iSettings.operator[](i).Meta();
+        meta |= KMetaDefaultValue;
+        iSettings.operator[](i).SetMeta(meta);
+        }
+    }