persistentstorage/centralrepository/cenrepsrv/obsrvr_noc.cpp
changeset 0 08ec8eefde2f
child 1 c084286672be
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15  
       
    16 #include "obsrvr_noc.h"
       
    17 #include "panic.h"
       
    18 #include "shrepos.h"
       
    19 #include "srvrepos_noc.h"
       
    20 #include "log.h"
       
    21 #include "cachemgr.h"
       
    22 
       
    23 #define TRAP_UNIFIED(_unifiedLeave, _function)	\
       
    24 	{ \
       
    25 	TInt _returnValue = 0; \
       
    26 	TRAP(_unifiedLeave, _returnValue = _function);	\
       
    27 	TInt& __rref = _unifiedLeave; \
       
    28 	__rref = _unifiedLeave | _returnValue; \
       
    29 	}
       
    30 
       
    31 CObservable::~CObservable()
       
    32 	{
       
    33 	iObservers.Close();
       
    34 	// cleanup owned objects if there's any left
       
    35 	iOpenRepositories.ResetAndDestroy();
       
    36 	iRepositoryInfo.ResetAndDestroy();
       
    37 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
       
    38 	TInt multiRofsUidCount=iMultiRofsUidList.Count();
       
    39 	for (TInt i=0;i<multiRofsUidCount;i++)
       
    40 		{
       
    41 		iMultiRofsUidList[i].iMountFlagList.Close();
       
    42 		}
       
    43 	iMultiRofsUidList.Close();
       
    44 #endif	
       
    45 	}
       
    46 
       
    47 CObservable* CObservable::NewLC()
       
    48 	{
       
    49 	CObservable* self = new(ELeave) CObservable;
       
    50 	CleanupStack::PushL(self);
       
    51 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS	
       
    52 	self->ConstructL();
       
    53 #endif	
       
    54 	return self;
       
    55 	}
       
    56 	
       
    57 void CObservable::AddObserverL(TUid aUid, CServerRepository* aRepositoryPointer)
       
    58 	{
       
    59 	TRepositoryObserverInfo info;
       
    60 
       
    61 	info.iRepositoryUid = aUid;
       
    62 	info.iRepositoryPointer = aRepositoryPointer;	
       
    63 	
       
    64 	TLinearOrder<TRepositoryObserverInfo> observerSortOrder(CObservable::ObserverSortOrder);
       
    65 	TInt err = iObservers.InsertInOrder(info, observerSortOrder);
       
    66 	if ((err != KErrNone)&&(err != KErrAlreadyExists))
       
    67 		{
       
    68 		User::Leave(err);
       
    69 		}
       
    70 	}
       
    71 
       
    72 void CObservable::RemoveObserver(TUid aUid, CServerRepository* aRepositoryPointer, TInt aInMemoryIndex)
       
    73 	{
       
    74 	TRepositoryObserverInfo info;
       
    75 
       
    76 	info.iRepositoryUid = aUid;
       
    77 	info.iRepositoryPointer = aRepositoryPointer;
       
    78 	
       
    79 	TLinearOrder<TRepositoryObserverInfo> observerSortOrder(CObservable::ObserverSortOrder);
       
    80 	
       
    81 	TInt i = iObservers.FindInOrder(info, observerSortOrder);
       
    82 	if (i!=KErrNotFound)
       
    83 		{
       
    84 		// we remove the observer we find listening on the repository
       
    85 		iObservers.Remove(i);
       
    86 		if (iObservers.SpecificFindInSignedKeyOrder(info, EArrayFindMode_Any)!=KErrNotFound)
       
    87 			{
       
    88 			//if there are more 
       
    89 			__CENTREP_TRACE1("CENTREP: Observer Removed when closing repository %x", aUid);
       
    90 			}
       
    91 		else
       
    92 			{
       
    93 			// removed the last observer with the given uid 
       
    94 			// if the repository is in memory, try evicting it
       
    95 			if (aInMemoryIndex>=0)
       
    96 				{
       
    97 				// Check cache size and carry out forced eviction if necessary			
       
    98 				// Start Eviction if the repository fits in the cache	
       
    99 				if (TServerResources::iCacheManager->Enabled()&&
       
   100 					TServerResources::iCacheManager->StartEviction(GetOpenRepository(aInMemoryIndex)))
       
   101 					{
       
   102 					// Repository added to the idle list in eviction order
       
   103 					__CENTREP_TRACE2("CENTREP: Repository Became Idle when closing repository %x size %d", aUid, GetOpenRepository(aInMemoryIndex)->Size());
       
   104 					}
       
   105 				else
       
   106 					{
       
   107 					__CENTREP_TRACE1("CENTREP: Repository Delete when closing repository %x", aUid);
       
   108 					// Remove and Delete Open Repository
       
   109 					delete iOpenRepositories[aInMemoryIndex];
       
   110 					iOpenRepositories.Remove(aInMemoryIndex);
       
   111 					}
       
   112 				}
       
   113 			// if no clients are connected on this repository, we no longer need the transaction information
       
   114 			RemoveSharedRepositoryInfo(aUid);
       
   115 			}
       
   116 		}
       
   117 	}
       
   118 
       
   119 void CObservable::Notify(TUid aUid, TUint32 aVal) const
       
   120 	{
       
   121 	TInt i = FindConnectedRepository(aUid);
       
   122 	if (i != KErrNotFound)
       
   123 		{
       
   124 		for(;(i<iObservers.Count())&&(iObservers[i].iRepositoryUid == aUid);i++)
       
   125 			{
       
   126 			iObservers[i].iRepositoryPointer->Notifier()->Notify(aVal);				
       
   127 			}
       
   128 		}
       
   129 	}
       
   130 
       
   131 TInt CObservable::FindConnectedRepository(TUid aUid) const
       
   132 	{
       
   133 	TRepositoryObserverInfo info;
       
   134 	info.iRepositoryUid = aUid;
       
   135 	
       
   136 	return iObservers.SpecificFindInSignedKeyOrder(info, EArrayFindMode_First);
       
   137 	}
       
   138 
       
   139 #ifdef CACHE_OOM_TESTABILITY
       
   140 void CObservable::Reset()
       
   141 	{
       
   142 	iObservers.Reset();
       
   143 	iOpenRepositories.Reset();
       
   144 	iRepositoryInfo.Reset();	
       
   145 	}
       
   146 	
       
   147 void CObservable::CloseiOpenRepositories() 
       
   148 	{
       
   149 	for(TInt i=iOpenRepositories.Count()-1; i>=0; i--)
       
   150 		{
       
   151 		delete iOpenRepositories[i];			
       
   152 		iOpenRepositories.Remove(i);
       
   153 		}
       
   154 	ASSERT(iOpenRepositories.Count()==0);
       
   155 	iOpenRepositories.Close();
       
   156 	}
       
   157 
       
   158 void CObservable::CloseiRepositoryInfo() 
       
   159 	{
       
   160 	for(TInt i=iRepositoryInfo.Count()-1; i>=0; i--)
       
   161 		{
       
   162 		delete iRepositoryInfo[i];			
       
   163 		iRepositoryInfo.Remove(i);
       
   164 		}
       
   165 	ASSERT(iRepositoryInfo.Count()==0);
       
   166 	iRepositoryInfo.Close();
       
   167 	}
       
   168 	
       
   169 #endif	
       
   170 
       
   171 /**
       
   172 This function compares two UID's and indicates their sorting order.  This
       
   173 implementation avoids overflow problems inherent in 'return aUid1-aUid2' 
       
   174 implementations.
       
   175 */
       
   176 TInt CObservable::CompareTUidValues(TInt aUid1, TInt aUid2)
       
   177 	{
       
   178 	if (aUid1 > aUid2)
       
   179 		return 1;
       
   180 	if (aUid1 < aUid2)
       
   181 		return -1;
       
   182 	return 0;
       
   183 	}
       
   184 
       
   185 
       
   186 TInt CObservable::ObserverSortOrder(const TRepositoryObserverInfo &aRepository1, const TRepositoryObserverInfo &aRepository2)
       
   187 	{
       
   188 	TInt result;
       
   189 	
       
   190 	result = CompareTUidValues(aRepository1.iRepositoryUid.iUid, aRepository2.iRepositoryUid.iUid);
       
   191 	if (result == 0)	
       
   192 		{
       
   193 		if (aRepository1.iRepositoryPointer > aRepository2.iRepositoryPointer)
       
   194 			return 1;
       
   195 		if (aRepository1.iRepositoryPointer < aRepository2.iRepositoryPointer)
       
   196 			return -1;		
       
   197 		}
       
   198 		
       
   199 	return result;
       
   200 	}
       
   201 
       
   202 void CObservable::RemoveOpenRepository(CSharedRepository* aRepository)
       
   203 	{
       
   204 	TInt index = iOpenRepositories.Find(aRepository);
       
   205 	
       
   206 	if (index>=0)		
       
   207 		{
       
   208 		// we don't fail any transactions here anymore, because transactions can now survive NOC repository
       
   209 		// unloads. The shared information about transactions is kept in memory seperately as long as a 
       
   210 		// client is connected. 
       
   211 		iOpenRepositories.Remove(index);
       
   212 		delete aRepository;
       
   213 		}
       
   214 	}
       
   215 
       
   216 TInt CObservable::FindOpenRepository(TUid aUid) const
       
   217 	{
       
   218 	TInt i;
       
   219 	TInt count=iOpenRepositories.Count();
       
   220 	for(i=count-1; i>=0; i--)
       
   221 		{
       
   222 		if(iOpenRepositories[i]->Uid()==aUid)
       
   223 			{
       
   224 			break;
       
   225 			}
       
   226 		}
       
   227 	return i;
       
   228 	}
       
   229 
       
   230 TInt CObservable::ReadIniFileL(CSharedRepository*& aRepository, TCentRepLocation aLocation)
       
   231 	{
       
   232 	TInt r=KErrNone;
       
   233 	CIniFileIn* inifile = 0;
       
   234 
       
   235 	HBufC* fileName(NULL);
       
   236     //allocates memory on the heap
       
   237     TServerResources::CreateRepositoryFileNameLC(fileName, aRepository->Uid(), aLocation, EIni);		
       
   238 	r = CIniFileIn::NewLC(TServerResources::iFs,inifile,*fileName);
       
   239 	if(r==KErrNone)
       
   240 		{			
       
   241 		r=ReadSettingsL(inifile, aRepository);		
       
   242 		if(r==KErrCorrupt)
       
   243 			{
       
   244 			// File is corrupt, if it's not the ROM file, delete it
       
   245 			if(fileName && aLocation != ERom)
       
   246 				User::LeaveIfError(TServerResources::iFs.Delete(*fileName));
       
   247 			// Delete any repository settings that may have been read in
       
   248 			aRepository->GetSettings().Reset();
       
   249 			}
       
   250 		}
       
   251 
       
   252 	CleanupStack::PopAndDestroy(inifile); // inifile	 
       
   253 	CleanupStack::PopAndDestroy(fileName);	// filename
       
   254 	return r;
       
   255 	}
       
   256 
       
   257 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
       
   258 
       
   259 // Function to compare two TMultiRofsList's.
       
   260 TInt CObservable::CompareUid(const TMultiRofsList& aUid1, const TMultiRofsList& aUid2)
       
   261 	{
       
   262     if (aUid1.iRepUid.iUid < aUid2.iRepUid.iUid)
       
   263         return -1 ;
       
   264     if (aUid1.iRepUid.iUid > aUid2.iRepUid.iUid)
       
   265 		return 1 ;
       
   266    	return 0 ;
       
   267 	}
       
   268 
       
   269 void CObservable::ConstructL()
       
   270 	{
       
   271 	//now search for repositories uid that might be composed of multi rofs
       
   272 #ifndef CENTREP_CONV_TOOL
       
   273 	if (TServerResources::iRomDirectory)
       
   274 		{
       
   275 		TFileName searchFileFormat;
       
   276 		searchFileFormat.Append(*(TServerResources::iRomDirectory));
       
   277 		searchFileFormat.Append(_L("????????.???[*-00]"));
       
   278 	    CDir* entryList=NULL;		
       
   279 		User::LeaveIfError(TServerResources::iFs.GetDir(searchFileFormat,KEntryAttNormal,ESortByName,entryList));
       
   280 		CleanupStack::PushL(entryList);
       
   281 		ProcessMultiRofsListL(*entryList);
       
   282 		CleanupStack::PopAndDestroy(entryList);
       
   283 		}
       
   284 #endif	
       
   285 	}
       
   286 
       
   287 void CObservable::ProcessMultiRofsListL(const CDir& aList)
       
   288 	{
       
   289 	TLex parser;
       
   290 	TUint32 uidNum;
       
   291 	TUint8 mountId;
       
   292 	TLinearOrder<TMultiRofsList> reposSortOrder(CompareUid);
       
   293 	TInt count=aList.Count();
       
   294 	iMultiRofsUidList.ReserveL(count);
       
   295 	for (TInt i=0;i<count;i++)
       
   296 		{
       
   297 		//file format as following XXXXYYYY.<cre/txt>[id-00]
       
   298 		//Extract the Uid first
       
   299 		parser.Assign(aList[i].iName.Left(8));		
       
   300 		User::LeaveIfError(parser.Val(uidNum,EHex));		
       
   301 		
       
   302 		//Extract the Mount id now, see the file format above
       
   303 		parser.Assign(aList[i].iName.Mid(13,2));
       
   304 		User::LeaveIfError(parser.Val(mountId,EHex));
       
   305 		
       
   306 		//Now find whether this uid is already in the list
       
   307 		TMultiRofsList find(TUid::Uid(uidNum));
       
   308 		//passing it the extension of the file
       
   309 		TRofsFlag newFlag(aList[i].iName.Mid(9,3),mountId);
       
   310 		
       
   311 		TInt err=iMultiRofsUidList.FindInOrder(find,reposSortOrder);
       
   312 		if (err==KErrNotFound)
       
   313 			{
       
   314 			//new entry
       
   315 			TMultiRofsList newEntry(TUid::Uid(uidNum));
       
   316 			newEntry.iMountFlagList.AppendL(newFlag);
       
   317 			iMultiRofsUidList.InsertInOrderL(newEntry,reposSortOrder);
       
   318 			}
       
   319 		else
       
   320 			{
       
   321 			//entry exist, just need to update the array inside TMultiRofsList
       
   322 			err=iMultiRofsUidList[err].iMountFlagList.InsertInOrder(newFlag,TRofsFlag::CompareFlag);
       
   323 			//ignore KErrAlreadyExists which might be the case if a txt and cre found on the same
       
   324 			//rofs but the cre is preferred.
       
   325 			if (err!=KErrNone && err!=KErrAlreadyExists)
       
   326 				{
       
   327 				User::Leave(err);
       
   328 				}
       
   329 			}
       
   330 		}		
       
   331 	}
       
   332 
       
   333 
       
   334 void CObservable::OverrideSettingL(TServerSetting& aBaseSetting,const TServerSetting& aOvSetting,CSharedRepository* aCoreRepository,TBool aNewOv,TBool aNewOvIndivPolicy)
       
   335 	{
       
   336 	TUint32 ovId=aOvSetting.Key();
       
   337 	
       
   338 	//---------------------CHECK AND SET THE META----------------------------
       
   339 	TBool indivOvMeta=aOvSetting.IsIndividualMeta()!=0;
       
   340 	//if individually specified meta override this
       
   341 	if (indivOvMeta)
       
   342 		{
       
   343 		aBaseSetting.SetMeta(aOvSetting.Meta());
       
   344 		}
       
   345 	//if not specified only when it is new we set it from the default meta
       
   346 	else
       
   347 		{
       
   348 		if (aNewOv)	
       
   349 			aCoreRepository->SetMetaDataOnRead(aBaseSetting,EFalse);		
       
   350 		}
       
   351 
       
   352 	//----------------------CHECK AND SET THE PLATSEC----------------------------	
       
   353 	TLinearOrder<TSettingsAccessPolicy> order(&CHeapRepository::CompareKeyIds);	
       
   354 	TSettingsAccessPolicy* ovTs=aOvSetting.AccessPolicy();
       
   355 	TSettingsAccessPolicy* coreTs=aCoreRepository->GetFallbackAccessPolicy(ovId,ETrue);
       
   356 	//new setting defined
       
   357 	if (aNewOv)
       
   358 		{
       
   359 		//specify own settings
       
   360 		if (aNewOvIndivPolicy)	
       
   361 			{
       
   362 			TSettingsAccessPolicy* newPol=new (ELeave)TSettingsAccessPolicy(*(const_cast<TSecurityPolicy*>
       
   363 			(aOvSetting.GetReadAccessPolicy())),*(const_cast<TSecurityPolicy*>(aOvSetting.GetWriteAccessPolicy())),ovId,ovTs->HighKey(),ovTs->KeyMask());
       
   364 			CleanupStack::PushL(newPol);
       
   365 			//for single setting policy, the highkey is used to indicate whether the setting define its own read policy or it is just a fallback
       
   366 			if (ovTs->HighKey()==0)
       
   367 				{
       
   368 				newPol->iReadAccessPolicy=*(coreTs->GetReadAccessPolicy());
       
   369 				}
       
   370 			//for single setting policy, the keymask is used to indicate whether the setting define its own write policy or it is just a fallback
       
   371 			if (ovTs->KeyMask()==0)
       
   372 				{
       
   373 				newPol->iWriteAccessPolicy=*(coreTs->GetWriteAccessPolicy());
       
   374 				}
       
   375 			//insert the new one and set the setting policy to point to this
       
   376 			aCoreRepository->iSimRep->SinglePolicyArray().InsertInOrderL(newPol,order);
       
   377 			aBaseSetting.SetAccessPolicy(newPol);				
       
   378 			CleanupStack::Pop(newPol);			
       
   379 			}
       
   380 		//no individual setting policy specified so revert to the default policy in the base	
       
   381 		else
       
   382 			{
       
   383 			aBaseSetting.SetAccessPolicy(coreTs);	
       
   384 			}
       
   385 		}
       
   386 	//old setting
       
   387 	else
       
   388 		{
       
   389 		//if no individual policy specified do nothing as this keeps what we have in the base setting
       
   390 		if (aNewOvIndivPolicy)
       
   391 			{
       
   392 			TInt baseIndividualPol=aCoreRepository->iSimRep->SinglePolicyArray().Find(aBaseSetting.AccessPolicy());	
       
   393 			if (baseIndividualPol==KErrNotFound)
       
   394 				{
       
   395 				//no base individual but overriding specify one so create one and insert into list
       
   396 				//point the old base setting to this newly defined invididual setting
       
   397 				TSettingsAccessPolicy* newPol=new (ELeave)TSettingsAccessPolicy(*(const_cast<TSecurityPolicy*>
       
   398 				(aOvSetting.GetReadAccessPolicy())),*(const_cast<TSecurityPolicy*>(aOvSetting.GetWriteAccessPolicy())),ovId,ovTs->HighKey(),ovTs->KeyMask());
       
   399 				CleanupStack::PushL(newPol);
       
   400 				//for single setting policy, the highkey is used to indicate whether the setting define its own read policy or it is just a fallback								
       
   401 				if (ovTs->HighKey()==0)
       
   402 					{
       
   403 					newPol->iReadAccessPolicy=*(coreTs->GetReadAccessPolicy());
       
   404 					}
       
   405 				//for single setting policy, the keymask is used to indicate whether the setting define its own write policy or it is just a fallback				
       
   406 				if (ovTs->KeyMask()==0)
       
   407 					{
       
   408 					newPol->iWriteAccessPolicy=*(coreTs->GetWriteAccessPolicy());
       
   409 					}
       
   410 				//insert the new one and set the setting policy to point to this
       
   411 				aCoreRepository->iSimRep->SinglePolicyArray().InsertInOrderL(newPol,order);
       
   412 				aBaseSetting.SetAccessPolicy(newPol);				
       
   413 				CleanupStack::Pop(newPol);			
       
   414 				}
       
   415 			else
       
   416 				{
       
   417 				TSettingsAccessPolicy* oldPol=aBaseSetting.AccessPolicy();				
       
   418 				//existing individual already exist, just update them
       
   419 				//for single setting policy, the highkey is used to indicate whether the setting define its own read policy or it is just a fallback
       
   420 				if (ovTs->HighKey()!=0)
       
   421 					{
       
   422 					oldPol->iReadAccessPolicy=*(aOvSetting.GetReadAccessPolicy());
       
   423 					}
       
   424 				//for single setting policy, the keymask is used to indicate whether the setting define its own write policy or it is just a fallback		
       
   425 				if (ovTs->KeyMask()!=0)
       
   426 					{
       
   427 					oldPol->iWriteAccessPolicy=*(aOvSetting.GetWriteAccessPolicy());
       
   428 					}
       
   429 				}
       
   430 			}
       
   431 		}
       
   432 
       
   433 	//---------------------SET THE VALUE---------------------------------------
       
   434 	//override the value only if it is a new setting or an old setting with value modified
       
   435 	if (aNewOv || (!aNewOv && aBaseSetting!=aOvSetting))
       
   436 		User::LeaveIfError(aBaseSetting.CopyTypeValue(aOvSetting));
       
   437 	
       
   438 	//need to set it clean as this is still ROM settings
       
   439 	aBaseSetting.SetClean();			
       
   440 	}
       
   441 
       
   442 //Function containing the rule of merging repositories to a core repository
       
   443 //such as -ignoring of the global properties(non-overriden)
       
   444 //        -type cannot be overriden
       
   445 void CObservable::MergeRepositoryL(CSharedRepository* aCoreRepository,CHeapRepository* aOverrideRepository)
       
   446 	{
       
   447 	/**
       
   448 	We may want to verify that the following global properties match
       
   449 	-OwnerUid
       
   450 	-Uid
       
   451 	We may want to give warning if they try to have global propertie section in the overriding layers
       
   452 	although this obviously now can be ignored now, just need to make sure that repository follows the format
       
   453 	and not corrupted
       
   454 	*/
       
   455 	TSettingsAccessPolicy defaultTs=aOverrideRepository->GetDefaultAccessPolicy();
       
   456 	//lets panic first on debug mode only
       
   457 	//here we panic immediately if there is any defined in the range meta/policy(we can check individually if
       
   458 	//they do override later on,we will assume any definiton of global policy is invalid here
       
   459 	if (   aOverrideRepository->Owner() != aCoreRepository->iSimRep->Owner()
       
   460 		|| (aOverrideRepository->DefaultMeta()!=0 && aOverrideRepository->DefaultMeta()!= aCoreRepository->iSimRep->DefaultMeta())
       
   461 		|| (defaultTs.HighKey()!=0 && aOverrideRepository->GetDefaultReadAccessPolicy().Package() !=	aCoreRepository->iSimRep->GetDefaultReadAccessPolicy().Package())
       
   462 		|| (defaultTs.KeyMask()!=0 && aOverrideRepository->GetDefaultWriteAccessPolicy().Package()!= aCoreRepository->iSimRep->GetDefaultWriteAccessPolicy().Package())
       
   463 		|| (aOverrideRepository->RangeMetaArray().Count()!=0 && !(aCoreRepository->iSimRep->RangeMetaArray().IsEqual(aOverrideRepository->RangeMetaArray())))
       
   464 		|| (aOverrideRepository->RangePolicyArray().Count()!=0 && !(aCoreRepository->iSimRep->RangePolicyArray().IsEqual(aOverrideRepository->RangePolicyArray())		
       
   465 		)))
       
   466 		{
       
   467 		#ifdef _DEBUG		
       
   468 			RDebug::Printf("Illegal Global Properties Overriding");
       
   469 		#endif		
       
   470 		User::Leave(KErrMultiRofsGlobalOverride);
       
   471 		}
       
   472 
       
   473 	TInt single_count=aOverrideRepository->SettingsArray().Count();
       
   474 	for (TInt i=0;i<single_count;i++)
       
   475 		{
       
   476 		//get the overriding setting
       
   477 		TServerSetting& ovTs=aOverrideRepository->SettingsArray()[i];
       
   478 		TUint32 ovId=ovTs.Key();
       
   479 				
       
   480 		//find whether it exist in the core
       
   481 		TServerSetting* coreTs=aCoreRepository->GetSettings().Find(ovId);
       
   482 		//check whether in the overriding repository,the policy is individually specified policy
       
   483 		TInt ovIndividualPol=aOverrideRepository->SinglePolicyArray().Find(ovTs.AccessPolicy());
       
   484 		if (coreTs)
       
   485 			{
       
   486 			//found in core, need to check the type is the same else Panic
       
   487 			if (coreTs->Type()!=ovTs.Type())
       
   488 				{
       
   489 				#ifdef _DEBUG			
       
   490 					RDebug::Printf("Illegal Setting Type Overriding");
       
   491 				#endif	
       
   492 				User::Leave(KErrMultiRofsTypeOverride);				
       
   493 				}
       
   494 			OverrideSettingL(*coreTs,ovTs,aCoreRepository,EFalse,ovIndividualPol!=KErrNotFound);					
       
   495 			}
       
   496 		else
       
   497 			{
       
   498 			//this is a newly defined setting
       
   499 			TServerSetting newTs(ovTs.Key());
       
   500 			OverrideSettingL(newTs,ovTs,aCoreRepository,ETrue,ovIndividualPol!=KErrNotFound);
       
   501 			//finally insert into the RSettingsArray for this new setting
       
   502 			aCoreRepository->iSimRep->SettingsArray().OrderedInsertL(newTs);	
       
   503 			}
       
   504 		}
       
   505 	
       
   506 	}	
       
   507 
       
   508 //Function on initialising a repository of multi ROFS files
       
   509 void CObservable::MergeMultiRofsL(TBool aCoreInitialized,CSharedRepository* aCoreRepository,const RArray<TRofsFlag>& aOverridingFileList)
       
   510 	{
       
   511 	//load all the files and construct an array of CHeapRepository to merge content into it
       
   512 	TInt sortedCount=aOverridingFileList.Count();
       
   513 	TFileName repFileName;
       
   514 	for (TInt i=0;i<sortedCount;i++)		
       
   515 		{
       
   516 		repFileName.Zero();
       
   517 		TRofsFlag rofsFlag=aOverridingFileList[i];
       
   518 		TPtrC extPointer(*(TServerResources::iCreExt));
       
   519 		TBool isTxt=rofsFlag.iFlag & 0x80000000;
       
   520 		if (isTxt)
       
   521 			{
       
   522 			extPointer.Set(*(TServerResources::iIniExt));
       
   523 			}
       
   524 		repFileName.Format(_L("z:\\private\\10202be9\\%08x%S[%02x-00]"),aCoreRepository->Uid().iUid,&extPointer,rofsFlag.iFlag & 0xFF);
       
   525 		//only when the core is not initialized, the first item in the list now becomes the core
       
   526 		if (!aCoreInitialized && i==0)
       
   527 			{
       
   528 			if (isTxt)
       
   529 				{
       
   530 				CIniFileIn* iniFile;
       
   531 				TInt err=CIniFileIn::NewLC(TServerResources::iFs,iniFile,repFileName);
       
   532 				User::LeaveIfError(err);
       
   533 				aCoreRepository->ReloadContentL(*iniFile,ETrue);
       
   534 				CleanupStack::PopAndDestroy(iniFile);//iniFile
       
   535 				}
       
   536 			else
       
   537 				{
       
   538 				aCoreRepository->iSimRep->CreateRepositoryFromCreFileL(TServerResources::iFs,repFileName);
       
   539 				}
       
   540 			}
       
   541 		else
       
   542 			{
       
   543 			CHeapRepository* repos=CHeapRepository::NewL(aCoreRepository->Uid());
       
   544 			CleanupStack::PushL(repos);
       
   545 		
       
   546 			if (isTxt)
       
   547 				{
       
   548 				CIniFileIn* iniFile;
       
   549 				TInt err=CIniFileIn::NewLC(TServerResources::iFs,iniFile,repFileName);
       
   550 				User::LeaveIfError(err);
       
   551 				repos->ReloadContentL(*iniFile);
       
   552 				CleanupStack::PopAndDestroy(iniFile);//iniFile
       
   553 				}
       
   554 			else
       
   555 				{
       
   556 				TUint8 creVersion;
       
   557 				repos->CreateRepositoryFromCreFileL(TServerResources::iFs,repFileName,creVersion);
       
   558 				//need to check the CRE version in the overloading layer
       
   559 				if (creVersion<KPersistFormatSupportsIndMetaIndicator)
       
   560 					{
       
   561 					#ifdef _DEBUG		
       
   562 						RDebug::Printf("Use of Cre version less than 2 in the overriding layer");
       
   563 					#endif	
       
   564 					//this macro is used for testing existing regression test with multi-rofs
       
   565 					//so we allow older cre to be used in higher rofs
       
   566 					#ifndef PDS_TEST_MULTIROFS											
       
   567 						User::Leave(KErrMultiRofsOldCreUsed);
       
   568 					#endif								
       
   569 					}
       
   570 				}
       
   571 			//Now that the repository is initialized and at this stage the repository file has been
       
   572 			//checked whether they are corrupt	
       
   573 			repos->SettingsArray().SetIsDefault(ETrue);
       
   574 			MergeRepositoryL(aCoreRepository,repos);
       
   575 
       
   576 			CleanupStack::PopAndDestroy(repos);	//repos
       
   577 			}
       
   578 		}
       
   579 	}
       
   580 #endif	
       
   581 
       
   582 TInt CObservable::CreateRepositoryL(CSharedRepository* aRepository, TCentRepLocation aLocation)
       
   583 	{
       
   584 	aRepository->GetSettings().SetIsDefault(aLocation!=EPersists);
       
   585     TInt err(KErrNotFound);
       
   586     
       
   587 	err = aRepository->CreateRepositoryFromCreFileL(aLocation);
       
   588 	if(err==KErrNotFound)
       
   589 		{
       
   590 		if (aLocation!=EPersists)
       
   591 			err = ReadIniFileL(aRepository,aLocation);
       
   592 		}
       
   593 	//for ROM might want to consider the possibility of multi rofs file
       
   594 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS		
       
   595 	if (aLocation==ERom && iMultiRofsUidList.Count()!=0)
       
   596 		{
       
   597 		//if there is error and not because of non-existant we should return error immediately
       
   598 		//and if it is fine but the uid does not match one of the multirofsuidlsit this means that
       
   599 		//repository is not composed of multi file.
       
   600 		if (err==KErrNone || err==KErrNotFound)
       
   601 			{
       
   602 			TMultiRofsList find(aRepository->Uid());
       
   603 			TLinearOrder<TMultiRofsList> sort_order(CompareUid);			
       
   604 			TInt index=iMultiRofsUidList.FindInOrder(find,sort_order);		
       
   605 			if (index==KErrNotFound)	
       
   606 				return err;
       
   607 			//if the first layer has already got the exattrib=U we should leave with KErrMultiRofsIllegalRofs
       
   608 			if (err==KErrNotFound && index!=KErrNotFound)	
       
   609 				User::Leave(KErrMultiRofsIllegalRofs);
       
   610 			//the list exist in one of the mappings stored earlier, get the name and construct them
       
   611 			TRAP(err,MergeMultiRofsL(err==KErrNone,aRepository,iMultiRofsUidList[index].iMountFlagList));
       
   612 			if (err==KErrNoMemory)	
       
   613 				User::LeaveNoMemory();
       
   614 			}
       
   615 		}
       
   616 #endif		
       
   617 	return( err);
       
   618 	}
       
   619 	
       
   620 /**
       
   621 In order to create a repository this routine looks for a .cre or .txt file. 
       
   622 Txt and cre files can co-exist in install and ROM but not in persists location.
       
   623 If a persists txt file exists, the first write to the repository will cause a
       
   624 cre file to be created and the txt file to be deleted.
       
   625 If both files exist in the same location, the .cre is picked up first. 
       
   626 If the .cre file is not found,a .txt file from the same location is tried.
       
   627 Otherwise if the .cre file is corrupted,it tries a .cre file from a next location. 
       
   628 
       
   629 Note:
       
   630 If a cre file exists at a particular location, even if the cre file is corrupt a txt 
       
   631 file will not be searched for in the same location. 
       
   632 */
       
   633 
       
   634 TInt CObservable::CreateRepositoryL(CSharedRepository*& aRepository, CIniFileIn::TIniFileOpenMode aIniFileOpenMode)
       
   635     {
       
   636     TInt err(KErrNotFound);
       
   637     
       
   638     switch (aIniFileOpenMode)
       
   639 	    {
       
   640 	    case CIniFileIn::EAuto:
       
   641 	        {
       
   642 	        // Look in persists dir	 
       
   643 	        err=CreateRepositoryL(aRepository, EPersists);		
       
   644 	        				
       
   645 			if(err==KErrNone)
       
   646 				{
       
   647 				return err;
       
   648 				}
       
   649 			 
       
   650 	        // No persists file - look in ROM dir	 
       
   651 	        // Do this before looking in the install dir, because if there is
       
   652 	        // a ROM file, an install file and no persists file then this
       
   653 	        // repository is being opened after a SW install but before the 
       
   654 	        // merge. In this case the install file shouldn't be opened
       
   655 	        // until after the merge.
       
   656 	        err=CreateRepositoryL(aRepository, ERom);		
       
   657 	        				
       
   658 			if(err==KErrNone)
       
   659 				{
       
   660 				break;
       
   661 				}
       
   662 			else if(err==KErrNotFound)
       
   663 				{				
       
   664 			     // Look in install directory only if there was no ROM or persists file	            
       
   665 				err=CreateRepositoryL(aRepository, EInstall);
       
   666 				if(err==KErrNone)
       
   667 					{
       
   668 					TTime installFileTimeStamp=TServerResources::CentrepFileTimeStampL(aRepository->Uid(), EInstall);
       
   669 					aRepository->SetInstallTime(installFileTimeStamp);
       
   670 					}
       
   671 				}
       
   672 	        break;
       
   673 	        }
       
   674 	        
       
   675 	    case CIniFileIn::EInstallOnly:
       
   676 	        {
       
   677 	    	err=CreateRepositoryL(aRepository, EInstall);		
       
   678 	        break;
       
   679 	        }
       
   680 
       
   681 	    case CIniFileIn::ERomOnly:
       
   682 	        {
       
   683 	    	err=CreateRepositoryL(aRepository, ERom);		
       
   684 	        break;
       
   685 	        }
       
   686 	    }
       
   687 
       
   688 	return err;
       
   689 	}
       
   690 	
       
   691 TInt CObservable::ReadSettingsL(CIniFileIn *aIniFile, CSharedRepository* aRep)
       
   692 	{	
       
   693 	return aRep->ReloadContentL(*aIniFile, ETrue);
       
   694 	}
       
   695 
       
   696 void CObservable::LoadRepositoryLC(TUid aUid, TBool aFailIfNotFound, CSharedRepository*& aRepository, CIniFileIn::TIniFileOpenMode aIniFileOpenMode)
       
   697 	{
       
   698 	// Calculate the amount of memory this repository will take in the heap
       
   699 	// by checking the heap size before and after the internalization
       
   700 	RHeap& myHeap = User::Heap();
       
   701 	TInt firstSize = myHeap.Size();
       
   702 	TInt biggestBlock;
       
   703 	TInt firstAvail = myHeap.Available(biggestBlock);
       
   704 	
       
   705 	aRepository = CSharedRepository::NewL(aUid);
       
   706 #ifdef CACHE_OOM_TESTABILITY
       
   707 	if ((aRepository==NULL)&&!iTrapOOMOnOpen)	
       
   708 		{
       
   709 		User::Leave(KErrNoMemory);
       
   710 		}
       
   711 #endif	
       
   712 	if ((aRepository==NULL)&&TServerResources::iCacheManager->Enabled())
       
   713 		{
       
   714 		// If cache enabled, try recovery by releasing the cache
       
   715 		TServerResources::iCacheManager->FlushCache(EFalse);
       
   716 		// retry
       
   717 		aRepository = CSharedRepository::NewL(aUid);
       
   718 		}
       
   719 	// If still no memory, return error
       
   720 	if (aRepository==NULL)
       
   721 		{
       
   722 		User::Leave(KErrNoMemory);
       
   723 		}
       
   724 	else // successfully created the object, so push it into the cleanup stack
       
   725 		{
       
   726 		CleanupStack::PushL(aRepository);
       
   727 		}
       
   728 		
       
   729 	// Now that we have enough memory for the object and constructed it properly
       
   730 	// we try to load it. We trap all errors, either from leaving functions or error code
       
   731 	// returning functions and unify them (in all cases only one of these codes will
       
   732 	// contain a valid value and the other will be 0, and for our purposes we treat
       
   733 	// all errors the same no matter if they're thrown or returned)
       
   734 
       
   735 	TInt unifiedErrorCode;
       
   736 	TRAP_UNIFIED(unifiedErrorCode, CreateRepositoryL(aRepository, aIniFileOpenMode));
       
   737 	
       
   738 	if (unifiedErrorCode!=KErrNone)
       
   739 	{
       
   740 	switch(unifiedErrorCode)
       
   741 		{
       
   742 		case KErrNoMemory:
       
   743 			{
       
   744 			if (TServerResources::iCacheManager->Enabled()) // cache enabled
       
   745 				{
       
   746 #ifdef CACHE_OOM_TESTABILITY
       
   747 				if (!iTrapOOMOnOpen)	
       
   748 					{
       
   749 					User::Leave(KErrNoMemory);
       
   750 					}
       
   751 #endif	
       
   752 				// Flush cache
       
   753 				TServerResources::iCacheManager->FlushCache(ETrue);
       
   754 
       
   755 				firstSize = myHeap.Size();
       
   756 				firstAvail = myHeap.Available(biggestBlock);
       
   757 	
       
   758 				//retry
       
   759 				TRAP_UNIFIED(unifiedErrorCode, CreateRepositoryL(aRepository, aIniFileOpenMode));
       
   760 				}
       
   761 			}
       
   762 			break;
       
   763 		case KErrNotFound:
       
   764 		case KErrPathNotFound:		
       
   765 			{
       
   766 			if (!aFailIfNotFound) // backup open
       
   767 				{
       
   768 				// override error condition and continue normally
       
   769 				unifiedErrorCode = KErrNone;
       
   770 				}
       
   771 			}
       
   772 			break;
       
   773 		}
       
   774 	}
       
   775 	// If unhandled, leave
       
   776 	User::LeaveIfError(unifiedErrorCode);
       
   777 
       
   778 	// Otherwise, finalize calulations
       
   779 	TInt lastSize = myHeap.Size();
       
   780 	TInt lastAvail = myHeap.Available(biggestBlock);
       
   781 
       
   782 	TInt calcSize = (lastSize - lastAvail) - (firstSize - firstAvail);
       
   783 	// record repository size for cache algorithm purposes
       
   784 	aRepository->SetSize(calcSize);
       
   785 	}
       
   786 
       
   787 CSharedRepository* CObservable::AccessL(TUid aUid, TBool aFailIfNotFound)
       
   788 	{
       
   789 	CSharedRepository* rep = NULL;
       
   790 	
       
   791 	TInt i = FindOpenRepository(aUid);
       
   792 	if(i!=KErrNotFound)
       
   793 		{
       
   794 		rep = GetOpenRepository(i);
       
   795 		// repository still open, can safely call RestoreConsistencyL
       
   796 		rep->RestoreConsistencyL();
       
   797 		}
       
   798 	else
       
   799 		{
       
   800 		// For memory usage testing purposes
       
   801 		RECORD_HEAP_SIZE(EMemLcnRepositoryOpen, aUid.iUid);
       
   802 		// Various error conditions are handled in this function 
       
   803 		LoadRepositoryLC(aUid, aFailIfNotFound, rep, CIniFileIn::EAuto);
       
   804 		__CENTREP_TRACE1("CENTREP: Repository Load when opening repository %x", aUid.iUid);
       
   805 		// For memory usage testing purposes
       
   806 		RECORD_HEAP_SIZE(EMemLcnRepositoryOpen, aUid.iUid);
       
   807 
       
   808 		AddOpenRepositoryL(rep);
       
   809 		
       
   810 		// We pop the rep here because if later call of TServerResources::AddOwnerIdLookupMapping fails of OOM
       
   811 		// the call of RemoveOpenRepository() will delete the repository before leave.
       
   812 		CleanupStack::Pop(rep);
       
   813 		
       
   814 		// Add owner mapping to list - Will fail if an entry already exists
       
   815 		// with this Repository UID but this doesn't matter
       
   816 		TUid owner = rep->Owner() ;
       
   817 		TInt err = TServerResources::AddOwnerIdLookupMapping(aUid.iUid, owner.iUid);	
       
   818 		if (err == KErrNoMemory)
       
   819 			{
       
   820 			RemoveOpenRepository(rep);
       
   821 			User::Leave(err);
       
   822 			}
       
   823 		
       
   824 		//Find the location of the current transaction for this repository
       
   825 		const TInt offset (FindRepositoryInfo(aUid));
       
   826 		if (offset >=0) //If there are no outstanding transactions
       
   827 			{
       
   828 			RefreshTransactorAccessPolicies(rep,offset);
       
   829 			}
       
   830 		}
       
   831 
       
   832 	// re-start the timer
       
   833 	if (TServerResources::iCacheManager->Enabled())
       
   834 		{
       
   835 		TServerResources::iCacheManager->StartEviction(rep);
       
   836 		}	
       
   837 		
       
   838 	return rep;
       
   839 	}
       
   840 
       
   841 TInt CObservable::FindRepositoryInfo(TUid aUid)
       
   842 	{
       
   843 	TSharedRepositoryInfo info(aUid);
       
   844 	TLinearOrder<TSharedRepositoryInfo> infoSortOrder(CObservable::InfoSortOrder);
       
   845 	
       
   846 	return iRepositoryInfo.FindInOrder(&info, infoSortOrder);
       
   847 	}
       
   848 	
       
   849 CObservable::TSharedRepositoryInfo* CObservable::SharedRepositoryInfo(TUid aUid)
       
   850 	{
       
   851 	TInt pos = FindRepositoryInfo(aUid);
       
   852 	return (pos!=KErrNotFound) ? iRepositoryInfo[pos] : NULL;
       
   853 	}
       
   854 
       
   855 CObservable::TSharedRepositoryInfo::TSharedRepositoryInfo(TUid aUid) : 
       
   856 	iRepositoryUid(aUid), iTransactors(_FOFF(CRepositoryTransactor, iLink)), 
       
   857 	iPessimisticTransactionLockCount(0), iNumActiveConcurrentReadWriteTransactions(0) 
       
   858 	{
       
   859 	}
       
   860 	
       
   861 TInt CObservable::InfoSortOrder(const TSharedRepositoryInfo &aRepository1, const TSharedRepositoryInfo &aRepository2)
       
   862 	{
       
   863 	return CompareTUidValues(aRepository1.iRepositoryUid.iUid, aRepository2.iRepositoryUid.iUid);
       
   864 	}
       
   865 	
       
   866 void CObservable::AddSharedRepositoryInfoL(TUid aUid)
       
   867 	{
       
   868 	TSharedRepositoryInfo* shinfo = new(ELeave) TSharedRepositoryInfo(aUid);
       
   869 
       
   870 	TLinearOrder<TSharedRepositoryInfo> infoSortOrder(CObservable::InfoSortOrder);
       
   871 	// Inserts if not already in the array, otherwise returns KErrAlreadyExists, which we handle gracefully
       
   872 	TInt err = iRepositoryInfo.InsertInOrder(shinfo, infoSortOrder);	
       
   873 	if (err==KErrAlreadyExists)
       
   874 		{
       
   875 		delete shinfo;
       
   876 		}
       
   877 	else
       
   878 		{
       
   879 		if (err!=KErrNone)
       
   880 			delete shinfo;
       
   881 		User::LeaveIfError(err);
       
   882 		}
       
   883 	}
       
   884 	
       
   885 void CObservable::RemoveSharedRepositoryInfo(TUid aUid)
       
   886 	{
       
   887 	TInt pos = FindRepositoryInfo(aUid);
       
   888 	if (pos!=KErrNotFound)
       
   889 		{
       
   890 		delete iRepositoryInfo[pos];
       
   891 		iRepositoryInfo.Remove(pos);
       
   892 		}
       
   893 	}
       
   894 
       
   895 	
       
   896 void CObservable::RefreshTransactorAccessPolicies(CSharedRepository* aRepository,const TInt offset)
       
   897 	{
       
   898 	TSglQueIter<CRepositoryTransactor> iter(iRepositoryInfo[offset]->iTransactors);
       
   899 	CRepositoryTransactor* t (iter);
       
   900 	
       
   901 	while (iter++ != NULL)
       
   902 		{
       
   903 		const TInt count = t->iTransactionSettings.Count();
       
   904 		for (TInt i=0; i<count;i++) //for the no. of changed settings in the transaction
       
   905 			{
       
   906 			TServerSetting temp = t->iTransactionSettings[i];
       
   907 			t->iTransactionSettings[i].SetAccessPolicy(aRepository->GetFallbackAccessPolicy(temp.Key()));		
       
   908 			//Correct the access policy pointer so that its pointing to the new valid location
       
   909 			}
       
   910 		t = iter;
       
   911 		}
       
   912 	}