os/persistentdata/persistentstorage/centralrepository/cenrepsrv/obsrvr_noc.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-2010 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 			find.iMountFlagList.AppendL(newFlag);
   316 			iMultiRofsUidList.InsertInOrderL(find,reposSortOrder);
   317 			}
   318 		else
   319 			{
   320 			//entry exist, just need to update the array inside TMultiRofsList
   321 			err=iMultiRofsUidList[err].iMountFlagList.InsertInOrder(newFlag,TRofsFlag::CompareFlag);
   322 			//ignore KErrAlreadyExists which might be the case if a txt and cre found on the same
   323 			//rofs but the cre is preferred.
   324 			if (err!=KErrNone && err!=KErrAlreadyExists)
   325 				{
   326 				User::Leave(err);
   327 				}
   328 			}
   329 		}		
   330 	}
   331 
   332 
   333 void CObservable::OverrideSettingL(TServerSetting& aBaseSetting,const TServerSetting& aOvSetting,CSharedRepository* aCoreRepository,TBool aNewOv,TBool aNewOvIndivPolicy)
   334 	{
   335 	TUint32 ovId=aOvSetting.Key();
   336 	
   337 	//---------------------CHECK AND SET THE META----------------------------
   338 	TBool indivOvMeta=aOvSetting.IsIndividualMeta()!=0;
   339 	//if individually specified meta override this
   340 	if (indivOvMeta)
   341 		{
   342 		aBaseSetting.SetMeta(aOvSetting.Meta());
   343 		}
   344 	//if not specified only when it is new we set it from the default meta
   345 	else
   346 		{
   347 		if (aNewOv)	
   348 			aCoreRepository->SetMetaDataOnRead(aBaseSetting,EFalse);		
   349 		}
   350 
   351 	//----------------------CHECK AND SET THE PLATSEC----------------------------	
   352 	TLinearOrder<TSettingsAccessPolicy> order(&CHeapRepository::CompareKeyIds);	
   353 	TSettingsAccessPolicy* ovTs=aOvSetting.AccessPolicy();
   354 	TSettingsAccessPolicy* coreTs=aCoreRepository->GetFallbackAccessPolicy(ovId,ETrue);
   355 	//new setting defined
   356 	if (aNewOv)
   357 		{
   358 		//specify own settings
   359 		if (aNewOvIndivPolicy)	
   360 			{
   361 			TSettingsAccessPolicy* newPol=new (ELeave)TSettingsAccessPolicy(*(const_cast<TSecurityPolicy*>
   362 			(aOvSetting.GetReadAccessPolicy())),*(const_cast<TSecurityPolicy*>(aOvSetting.GetWriteAccessPolicy())),ovId,ovTs->HighKey(),ovTs->KeyMask());
   363 			CleanupStack::PushL(newPol);
   364 			//for single setting policy, the highkey is used to indicate whether the setting define its own read policy or it is just a fallback
   365 			if (ovTs->HighKey()==0)
   366 				{
   367 				newPol->iReadAccessPolicy=*(coreTs->GetReadAccessPolicy());
   368 				}
   369 			//for single setting policy, the keymask is used to indicate whether the setting define its own write policy or it is just a fallback
   370 			if (ovTs->KeyMask()==0)
   371 				{
   372 				newPol->iWriteAccessPolicy=*(coreTs->GetWriteAccessPolicy());
   373 				}
   374 			//insert the new one and set the setting policy to point to this
   375 			aCoreRepository->iSimRep->SinglePolicyArray().InsertInOrderL(newPol,order);
   376 			aBaseSetting.SetAccessPolicy(newPol);				
   377 			CleanupStack::Pop(newPol);			
   378 			}
   379 		//no individual setting policy specified so revert to the default policy in the base	
   380 		else
   381 			{
   382 			aBaseSetting.SetAccessPolicy(coreTs);	
   383 			}
   384 		}
   385 	//old setting
   386 	else
   387 		{
   388 		//if no individual policy specified do nothing as this keeps what we have in the base setting
   389 		if (aNewOvIndivPolicy)
   390 			{
   391 			TInt baseIndividualPol=aCoreRepository->iSimRep->SinglePolicyArray().Find(aBaseSetting.AccessPolicy());	
   392 			if (baseIndividualPol==KErrNotFound)
   393 				{
   394 				//no base individual but overriding specify one so create one and insert into list
   395 				//point the old base setting to this newly defined invididual setting
   396 				TSettingsAccessPolicy* newPol=new (ELeave)TSettingsAccessPolicy(*(const_cast<TSecurityPolicy*>
   397 				(aOvSetting.GetReadAccessPolicy())),*(const_cast<TSecurityPolicy*>(aOvSetting.GetWriteAccessPolicy())),ovId,ovTs->HighKey(),ovTs->KeyMask());
   398 				CleanupStack::PushL(newPol);
   399 				//for single setting policy, the highkey is used to indicate whether the setting define its own read policy or it is just a fallback								
   400 				if (ovTs->HighKey()==0)
   401 					{
   402 					newPol->iReadAccessPolicy=*(coreTs->GetReadAccessPolicy());
   403 					}
   404 				//for single setting policy, the keymask is used to indicate whether the setting define its own write policy or it is just a fallback				
   405 				if (ovTs->KeyMask()==0)
   406 					{
   407 					newPol->iWriteAccessPolicy=*(coreTs->GetWriteAccessPolicy());
   408 					}
   409 				//insert the new one and set the setting policy to point to this
   410 				aCoreRepository->iSimRep->SinglePolicyArray().InsertInOrderL(newPol,order);
   411 				aBaseSetting.SetAccessPolicy(newPol);				
   412 				CleanupStack::Pop(newPol);			
   413 				}
   414 			else
   415 				{
   416 				TSettingsAccessPolicy* oldPol=aBaseSetting.AccessPolicy();				
   417 				//existing individual already exist, just update them
   418 				//for single setting policy, the highkey is used to indicate whether the setting define its own read policy or it is just a fallback
   419 				if (ovTs->HighKey()!=0)
   420 					{
   421 					oldPol->iReadAccessPolicy=*(aOvSetting.GetReadAccessPolicy());
   422 					}
   423 				//for single setting policy, the keymask is used to indicate whether the setting define its own write policy or it is just a fallback		
   424 				if (ovTs->KeyMask()!=0)
   425 					{
   426 					oldPol->iWriteAccessPolicy=*(aOvSetting.GetWriteAccessPolicy());
   427 					}
   428 				}
   429 			}
   430 		}
   431 
   432 	//---------------------SET THE VALUE---------------------------------------
   433 	//override the value only if it is a new setting or an old setting with value modified
   434 	if (aNewOv || (!aNewOv && aBaseSetting!=aOvSetting))
   435 		User::LeaveIfError(aBaseSetting.CopyTypeValue(aOvSetting));
   436 	
   437 	//need to set it clean as this is still ROM settings
   438 	aBaseSetting.SetClean();			
   439 	}
   440 
   441 //Function containing the rule of merging repositories to a core repository
   442 //such as -ignoring of the global properties(non-overriden)
   443 //        -type cannot be overriden
   444 void CObservable::MergeRepositoryL(CSharedRepository* aCoreRepository,CHeapRepository* aOverrideRepository)
   445 	{
   446 	/**
   447 	We may want to verify that the following global properties match
   448 	-OwnerUid
   449 	-Uid
   450 	We may want to give warning if they try to have global propertie section in the overriding layers
   451 	although this obviously now can be ignored now, just need to make sure that repository follows the format
   452 	and not corrupted
   453 	*/
   454 	TSettingsAccessPolicy defaultTs=aOverrideRepository->GetDefaultAccessPolicy();
   455 	//here we panic immediately if there is any defined in the range meta/policy(we can check individually if
   456 	//they do override later on,we will assume any definiton of global policy is invalid here
   457 	if (   aOverrideRepository->Owner() != aCoreRepository->iSimRep->Owner()
   458 		|| (aOverrideRepository->DefaultMeta()!=0 && aOverrideRepository->DefaultMeta()!= aCoreRepository->iSimRep->DefaultMeta())
   459 		|| (defaultTs.HighKey()!=0 && aOverrideRepository->GetDefaultReadAccessPolicy().Package() !=	aCoreRepository->iSimRep->GetDefaultReadAccessPolicy().Package())
   460 		|| (defaultTs.KeyMask()!=0 && aOverrideRepository->GetDefaultWriteAccessPolicy().Package()!= aCoreRepository->iSimRep->GetDefaultWriteAccessPolicy().Package())
   461 		|| (aOverrideRepository->RangeMetaArray().Count()!=0 && !(aCoreRepository->iSimRep->RangeMetaArray().IsEqual(aOverrideRepository->RangeMetaArray())))
   462 		|| (aOverrideRepository->RangePolicyArray().Count()!=0 && !(aCoreRepository->iSimRep->RangePolicyArray().IsEqual(aOverrideRepository->RangePolicyArray())		
   463 		)))
   464 		{
   465 		#ifdef _DEBUG		
   466 			RDebug::Printf("Illegal Global Properties Overriding");
   467 		#endif		
   468 		User::Leave(KErrMultiRofsGlobalOverride);
   469 		}
   470 
   471 	TInt single_count=aOverrideRepository->SettingsArray().Count();
   472 	for (TInt i=0;i<single_count;i++)
   473 		{
   474 		//get the overriding setting
   475 		TServerSetting& ovTs=aOverrideRepository->SettingsArray()[i];
   476 		TUint32 ovId=ovTs.Key();
   477 				
   478 		//find whether it exist in the core
   479 		TServerSetting* coreTs=aCoreRepository->GetSettings().Find(ovId);
   480 		//check whether in the overriding repository,the policy is individually specified policy
   481 		TInt ovIndividualPol=aOverrideRepository->SinglePolicyArray().Find(ovTs.AccessPolicy());
   482 		if (coreTs)
   483 			{
   484 			//found in core, need to check the type is the same else Panic
   485 			if (coreTs->Type()!=ovTs.Type())
   486 				{
   487 				#ifdef _DEBUG			
   488 					RDebug::Printf("Illegal Setting Type Overriding");
   489 				#endif	
   490 				User::Leave(KErrMultiRofsTypeOverride);				
   491 				}
   492 			OverrideSettingL(*coreTs,ovTs,aCoreRepository,EFalse,ovIndividualPol!=KErrNotFound);					
   493 			}
   494 		else
   495 			{
   496 			//this is a newly defined setting
   497 			TServerSetting newTs(ovTs.Key());
   498 			OverrideSettingL(newTs,ovTs,aCoreRepository,ETrue,ovIndividualPol!=KErrNotFound);
   499 			//finally insert into the RSettingsArray for this new setting
   500 			aCoreRepository->iSimRep->SettingsArray().OrderedInsertL(newTs);	
   501 			}
   502 		}
   503 	
   504 	}	
   505 
   506 /**Function on initialising a repository of multi ROFS files
   507 aCoreInitialized indicate whether there is already existing keyspace file in the core layer
   508 otherwise the first one in the rofs layer will be the core repository
   509 */ 
   510 void CObservable::MergeMultiRofsL(TBool aCoreInitialized,CSharedRepository* aCoreRepository,const RArray<TRofsFlag>& aOverridingFileList)
   511 	{
   512 	//load all the files and construct an array of CHeapRepository to merge content into it
   513 	TInt sortedCount=aOverridingFileList.Count();
   514 	TFileName repFileName;
   515 	for (TInt i=0;i<sortedCount;i++)		
   516 		{
   517 		repFileName.Zero();
   518 		TRofsFlag rofsFlag=aOverridingFileList[i];
   519 		TPtrC extPointer(*(TServerResources::iCreExt));
   520 		TBool isTxt=rofsFlag.iFlag & 0x80000000;
   521 		if (isTxt)
   522 			{
   523 			extPointer.Set(*(TServerResources::iIniExt));
   524 			}
   525 		repFileName.Format(_L("z:\\private\\10202be9\\%08x%S[%02x-00]"),aCoreRepository->Uid().iUid,&extPointer,rofsFlag.iFlag & 0xFF);
   526 		//only when the core is not initialized, the first item in the list now becomes the core
   527 		if (!aCoreInitialized && i==0)
   528 			{
   529 			if (isTxt)
   530 				{
   531 				CIniFileIn* iniFile;
   532 				TInt err=CIniFileIn::NewLC(TServerResources::iFs,iniFile,repFileName);
   533 				User::LeaveIfError(err);
   534 				err=aCoreRepository->ReloadContentL(*iniFile,ETrue);
   535 				User::LeaveIfError(err);
   536 				CleanupStack::PopAndDestroy(iniFile);//iniFile
   537 				}
   538 			else
   539 				{
   540 				aCoreRepository->iSimRep->CreateRepositoryFromCreFileL(TServerResources::iFs,repFileName);
   541 				}
   542 			}
   543 		else
   544 			{
   545 			CHeapRepository* repos=CHeapRepository::NewL(aCoreRepository->Uid());
   546 			CleanupStack::PushL(repos);
   547 		
   548 			if (isTxt)
   549 				{
   550 				CIniFileIn* iniFile;
   551 				TInt err=CIniFileIn::NewLC(TServerResources::iFs,iniFile,repFileName);
   552 				User::LeaveIfError(err);
   553 				repos->ReloadContentL(*iniFile);
   554 				CleanupStack::PopAndDestroy(iniFile);//iniFile
   555 				}
   556 			else
   557 				{
   558 				TUint8 creVersion;
   559 				repos->CreateRepositoryFromCreFileL(TServerResources::iFs,repFileName,creVersion);
   560 				//need to check the CRE version in the overloading layer
   561 				if (creVersion<KPersistFormatSupportsIndMetaIndicator)
   562 					{
   563 					#ifdef _DEBUG		
   564 						RDebug::Printf("Use of Cre version less than 2 in the overriding layer");
   565 					#endif	
   566 					//this macro is used for testing existing regression test with multi-rofs
   567 					//so we allow older cre to be used in higher rofs
   568 					#ifndef PDS_TEST_MULTIROFS											
   569 						User::Leave(KErrMultiRofsOldCreUsed);
   570 					#endif								
   571 					}
   572 				}
   573 			//Now that the repository is initialized and at this stage the repository file has been
   574 			//checked whether they are corrupt	
   575 			repos->SettingsArray().SetIsDefault(ETrue);
   576 			MergeRepositoryL(aCoreRepository,repos);
   577 
   578 			CleanupStack::PopAndDestroy(repos);	//repos
   579 			}
   580 		}
   581 	}
   582 #endif	
   583 
   584 TInt CObservable::CreateRepositoryL(CSharedRepository* aRepository, TCentRepLocation aLocation)
   585 	{
   586 	aRepository->GetSettings().SetIsDefault(aLocation!=EPersists);
   587     TInt err(KErrNotFound);
   588     
   589 	err = aRepository->CreateRepositoryFromCreFileL(aLocation);
   590 	if(err==KErrNotFound)
   591 		{
   592 		if (aLocation!=EPersists)
   593 			err = ReadIniFileL(aRepository,aLocation);
   594 		}
   595 	//for ROM might want to consider the possibility of multi rofs file
   596 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS		
   597 	if (aLocation==ERom && iMultiRofsUidList.Count()!=0)
   598 		{
   599 		//if there is error and not because of non-existant we should return error immediately
   600 		//and if it is fine but the uid does not match one of the multirofsuidlsit this means that
   601 		//repository is not composed of multi file.
   602 		if (err==KErrNone || err==KErrNotFound)
   603 			{
   604 			TMultiRofsList find(aRepository->Uid());
   605 			TLinearOrder<TMultiRofsList> sort_order(CompareUid);			
   606 			TInt index=iMultiRofsUidList.FindInOrder(find,sort_order);		
   607 			if (index==KErrNotFound)	
   608 				return err;
   609 			//if the first layer has already got the exattrib=U we should leave with KErrMultiRofsIllegalRofs
   610 			if (err==KErrNotFound && index!=KErrNotFound)	
   611 				User::Leave(KErrMultiRofsIllegalRofs);
   612 			//the list exist in one of the mappings stored earlier, get the name and construct them
   613 			TRAP(err,MergeMultiRofsL(err==KErrNone,aRepository,iMultiRofsUidList[index].iMountFlagList));
   614 			if (err==KErrNoMemory)	
   615 				User::LeaveNoMemory();
   616 			}
   617 		}
   618 #endif		
   619 	return( err);
   620 	}
   621 	
   622 /**
   623 In order to create a repository this routine looks for a .cre or .txt file. 
   624 Txt and cre files can co-exist in install and ROM but not in persists location.
   625 If a persists txt file exists, the first write to the repository will cause a
   626 cre file to be created and the txt file to be deleted.
   627 If both files exist in the same location, the .cre is picked up first. 
   628 If the .cre file is not found,a .txt file from the same location is tried.
   629 Otherwise if the .cre file is corrupted,it tries a .cre file from a next location. 
   630 
   631 Note:
   632 If a cre file exists at a particular location, even if the cre file is corrupt a txt 
   633 file will not be searched for in the same location. 
   634 */
   635 
   636 TInt CObservable::CreateRepositoryL(CSharedRepository*& aRepository, CIniFileIn::TIniFileOpenMode aIniFileOpenMode)
   637     {
   638     TInt err(KErrNotFound);
   639     
   640     switch (aIniFileOpenMode)
   641 	    {
   642 	    case CIniFileIn::EAuto:
   643 	        {
   644 	        // Look in persists dir	 
   645 	        err=CreateRepositoryL(aRepository, EPersists);		
   646 	        				
   647 			if(err==KErrNone)
   648 				{
   649 				return err;
   650 				}
   651 			 
   652 	        // No persists file - look in ROM dir	 
   653 	        // Do this before looking in the install dir, because if there is
   654 	        // a ROM file, an install file and no persists file then this
   655 	        // repository is being opened after a SW install but before the 
   656 	        // merge. In this case the install file shouldn't be opened
   657 	        // until after the merge.
   658 	        err=CreateRepositoryL(aRepository, ERom);		
   659 	        				
   660 			if(err==KErrNone)
   661 				{
   662 				break;
   663 				}
   664 			else if(err==KErrNotFound)
   665 				{				
   666 			     // Look in install directory only if there was no ROM or persists file	            
   667 				err=CreateRepositoryL(aRepository, EInstall);
   668 				if(err==KErrNone)
   669 					{
   670 					TTime installFileTimeStamp=TServerResources::CentrepFileTimeStampL(aRepository->Uid(), EInstall);
   671 					aRepository->SetInstallTime(installFileTimeStamp);
   672 					}
   673 				}
   674 	        break;
   675 	        }
   676 	        
   677 	    case CIniFileIn::EInstallOnly:
   678 	        {
   679 	    	err=CreateRepositoryL(aRepository, EInstall);		
   680 	        break;
   681 	        }
   682 
   683 	    case CIniFileIn::ERomOnly:
   684 	        {
   685 	    	err=CreateRepositoryL(aRepository, ERom);		
   686 	        break;
   687 	        }
   688 	    }
   689 
   690 	return err;
   691 	}
   692 	
   693 TInt CObservable::ReadSettingsL(CIniFileIn *aIniFile, CSharedRepository* aRep)
   694 	{	
   695 	return aRep->ReloadContentL(*aIniFile, ETrue);
   696 	}
   697 
   698 void CObservable::LoadRepositoryLC(TUid aUid, TBool aFailIfNotFound, CSharedRepository*& aRepository, CIniFileIn::TIniFileOpenMode aIniFileOpenMode)
   699 	{
   700 	// Calculate the amount of memory this repository will take in the heap
   701 	// by checking the heap size before and after the internalization
   702 	RHeap& myHeap = User::Heap();
   703 	TInt firstSize = myHeap.Size();
   704 	TInt biggestBlock;
   705 	TInt firstAvail = myHeap.Available(biggestBlock);
   706 	
   707 	TRAPD(err, aRepository = CSharedRepository::NewL(aUid));
   708 #ifdef CACHE_OOM_TESTABILITY
   709 	if ((err!=KErrNone)&&!iTrapOOMOnOpen)	
   710 		{
   711 		User::Leave(err);
   712 		}
   713 #endif	
   714 	if ((err!=KErrNone)&&TServerResources::iCacheManager->Enabled())
   715 		{
   716 		// If cache enabled, try recovery by releasing the cache
   717 		TServerResources::iCacheManager->FlushCache(EFalse);
   718 		// retry
   719 		aRepository = CSharedRepository::NewL(aUid);
   720 		err = KErrNone;
   721 		}
   722 	User::LeaveIfError(err);
   723 		
   724 	// Now that we have enough memory for the object and constructed it properly
   725 	// we try to load it. We trap all errors, either from leaving functions or error code
   726 	// returning functions and unify them (in all cases only one of these codes will
   727 	// contain a valid value and the other will be 0, and for our purposes we treat
   728 	// all errors the same no matter if they're thrown or returned)
   729 
   730 	TInt unifiedErrorCode;
   731 	TRAP_UNIFIED(unifiedErrorCode, CreateRepositoryL(aRepository, aIniFileOpenMode));
   732 	
   733 	if (unifiedErrorCode!=KErrNone)
   734 	{
   735 	switch(unifiedErrorCode)
   736 		{
   737 		case KErrNoMemory:
   738 			{
   739 			if (TServerResources::iCacheManager->Enabled()) // cache enabled
   740 				{
   741 #ifdef CACHE_OOM_TESTABILITY
   742 				if (!iTrapOOMOnOpen)	
   743 					{
   744 					delete aRepository;
   745 					aRepository = NULL;
   746 					User::Leave(KErrNoMemory);
   747 					}
   748 #endif	
   749 				// Flush cache
   750 				TServerResources::iCacheManager->FlushCache(ETrue);
   751 
   752 				firstSize = myHeap.Size();
   753 				firstAvail = myHeap.Available(biggestBlock);
   754 	
   755 				//retry
   756 				TRAP_UNIFIED(unifiedErrorCode, CreateRepositoryL(aRepository, aIniFileOpenMode));
   757 				}
   758 			}
   759 			break;
   760 		case KErrNotFound:
   761 		case KErrPathNotFound:		
   762 			{
   763 			if (!aFailIfNotFound) // backup open
   764 				{
   765 				// override error condition and continue normally
   766 				unifiedErrorCode = KErrNone;
   767 				}
   768 			}
   769 			break;
   770 		}
   771 	}
   772 	// If unhandled, leave
   773 	if(unifiedErrorCode != KErrNone)
   774 		{
   775 		delete aRepository;
   776 		aRepository = NULL;
   777 		}
   778 	User::LeaveIfError(unifiedErrorCode);
   779 	CleanupStack::PushL(aRepository);
   780 
   781 	// Otherwise, finalize calulations
   782 	TInt lastSize = myHeap.Size();
   783 	TInt lastAvail = myHeap.Available(biggestBlock);
   784 
   785 	TInt calcSize = (lastSize - lastAvail) - (firstSize - firstAvail);
   786 	// record repository size for cache algorithm purposes
   787 	aRepository->SetSize(calcSize);
   788 	}
   789 
   790 CSharedRepository* CObservable::AccessL(TUid aUid, TBool aFailIfNotFound)
   791 	{
   792 	CSharedRepository* rep = NULL;
   793 	
   794 	TInt i = FindOpenRepository(aUid);
   795 	if(i!=KErrNotFound)
   796 		{
   797 		rep = GetOpenRepository(i);
   798 		// repository still open, can safely call RestoreConsistencyL
   799 		rep->RestoreConsistencyL();
   800 		}
   801 	else
   802 		{
   803 		// For memory usage testing purposes
   804 		RECORD_HEAP_SIZE(EMemLcnRepositoryOpen, aUid.iUid);
   805 		// Various error conditions are handled in this function 
   806 		LoadRepositoryLC(aUid, aFailIfNotFound, rep, CIniFileIn::EAuto);
   807 		__CENTREP_TRACE1("CENTREP: Repository Load when opening repository %x", aUid.iUid);
   808 		// For memory usage testing purposes
   809 		RECORD_HEAP_SIZE(EMemLcnRepositoryOpen, aUid.iUid);
   810 
   811 		AddOpenRepositoryL(rep);
   812 		
   813 		// We pop the rep here because if later call of TServerResources::AddOwnerIdLookupMapping fails of OOM
   814 		// the call of RemoveOpenRepository() will delete the repository before leave.
   815 		CleanupStack::Pop(rep);
   816 		
   817 		// Add owner mapping to list - Will fail if an entry already exists
   818 		// with this Repository UID but this doesn't matter
   819 		TUid owner = rep->Owner() ;
   820 		TInt err = TServerResources::AddOwnerIdLookupMapping(aUid.iUid, owner.iUid);	
   821 		if (err == KErrNoMemory)
   822 			{
   823 			RemoveOpenRepository(rep);
   824 			User::Leave(err);
   825 			}
   826 		
   827 		//Find the location of the current transaction for this repository
   828 		const TInt offset (FindRepositoryInfo(aUid));
   829 		if (offset >=0) //If there are no outstanding transactions
   830 			{
   831 			RefreshTransactorAccessPolicies(rep,offset);
   832 			}
   833 		}
   834 
   835 	// re-start the timer
   836 	if (TServerResources::iCacheManager->Enabled())
   837 		{
   838 		TServerResources::iCacheManager->StartEviction(rep);
   839 		}	
   840 		
   841 	return rep;
   842 	}
   843 
   844 TInt CObservable::FindRepositoryInfo(TUid aUid)
   845 	{
   846 	TSharedRepositoryInfo info(aUid);
   847 	TLinearOrder<TSharedRepositoryInfo> infoSortOrder(CObservable::InfoSortOrder);
   848 	
   849 	return iRepositoryInfo.FindInOrder(&info, infoSortOrder);
   850 	}
   851 	
   852 CObservable::TSharedRepositoryInfo* CObservable::SharedRepositoryInfo(TUid aUid)
   853 	{
   854 	TInt pos = FindRepositoryInfo(aUid);
   855 	return (pos!=KErrNotFound) ? iRepositoryInfo[pos] : NULL;
   856 	}
   857 
   858 void CObservable::CancelTransaction(CRepositoryTransactor& aTransactor,TUid aRepositoryUid)
   859     {
   860     if (aTransactor.IsInTransaction())
   861         {
   862         ReleaseTransactionLock(aTransactor,aRepositoryUid);
   863         CObservable::TSharedRepositoryInfo* shrepinfo =SharedRepositoryInfo(aRepositoryUid);
   864         ASSERT(shrepinfo);
   865         shrepinfo->iTransactors.Remove(aTransactor);
   866         //Remove the link to the next transaction
   867         aTransactor.iLink.iNext = NULL;
   868         aTransactor.Deque();
   869         }
   870     }
   871 
   872 /** Private helper method which releases any read/write locks held in the shared repository
   873 by this transactor. Caller must set transactor's state or remove from queue as appropriate.
   874 @param aTransactor transactor whose read/write locks are to be released.
   875 @post Any read/write locks held by transactor are released.
   876 */
   877 void CObservable::ReleaseTransactionLock(CRepositoryTransactor& aTransactor,TUid aRepositoryUid)
   878     {
   879     CObservable::TSharedRepositoryInfo* shrepinfo = SharedRepositoryInfo(aRepositoryUid);
   880     ASSERT(shrepinfo);
   881     if (aTransactor.IsInActiveConcurrentReadWriteTransaction())
   882         {
   883         shrepinfo->iNumActiveConcurrentReadWriteTransactions--;
   884         ASSERT(shrepinfo->iNumActiveConcurrentReadWriteTransactions >= 0); // sanity check
   885         }
   886     else if (aTransactor.IsInActiveReadTransaction())
   887         {
   888         shrepinfo->iPessimisticTransactionLockCount--;
   889         ASSERT(shrepinfo->iPessimisticTransactionLockCount >= 0); // sanity check
   890         }
   891     else if (aTransactor.IsInActiveExclusiveReadWriteTransaction())
   892         {
   893         // can only be one exclusive read/write transaction active (lock value -1)
   894         ASSERT(shrepinfo->iPessimisticTransactionLockCount == -1);
   895         shrepinfo->iPessimisticTransactionLockCount = 0;
   896         }
   897     }
   898 CObservable::TSharedRepositoryInfo::TSharedRepositoryInfo(TUid aUid) : 
   899 	iRepositoryUid(aUid), iTransactors(_FOFF(CRepositoryTransactor, iLink)), 
   900 	iPessimisticTransactionLockCount(0), iNumActiveConcurrentReadWriteTransactions(0) 
   901 	{
   902 	}
   903 	
   904 TInt CObservable::InfoSortOrder(const TSharedRepositoryInfo &aRepository1, const TSharedRepositoryInfo &aRepository2)
   905 	{
   906 	return CompareTUidValues(aRepository1.iRepositoryUid.iUid, aRepository2.iRepositoryUid.iUid);
   907 	}
   908 	
   909 void CObservable::AddSharedRepositoryInfoL(TUid aUid)
   910 	{
   911 	TSharedRepositoryInfo* shinfo = new(ELeave) TSharedRepositoryInfo(aUid);
   912 
   913 	TLinearOrder<TSharedRepositoryInfo> infoSortOrder(CObservable::InfoSortOrder);
   914 	// Inserts if not already in the array, otherwise returns KErrAlreadyExists, which we handle gracefully
   915 	TInt err = iRepositoryInfo.InsertInOrder(shinfo, infoSortOrder);	
   916 	if (err==KErrAlreadyExists)
   917 		{
   918 		delete shinfo;
   919 		}
   920 	else
   921 		{
   922 		if (err!=KErrNone)
   923 			delete shinfo;
   924 		User::LeaveIfError(err);
   925 		}
   926 	}
   927 	
   928 void CObservable::RemoveSharedRepositoryInfo(TUid aUid)
   929 	{
   930 	TInt pos = FindRepositoryInfo(aUid);
   931 	if (pos!=KErrNotFound)
   932 		{
   933 		delete iRepositoryInfo[pos];
   934 		iRepositoryInfo.Remove(pos);
   935 		}
   936 	}
   937 
   938 	
   939 void CObservable::RefreshTransactorAccessPolicies(CSharedRepository* aRepository,const TInt offset)
   940 	{
   941 	TSglQueIter<CRepositoryTransactor> iter(iRepositoryInfo[offset]->iTransactors);
   942 	CRepositoryTransactor* t (iter);
   943 	
   944 	while (iter++ != NULL)
   945 		{
   946 		const TInt count = t->iTransactionSettings.Count();
   947 		for (TInt i=0; i<count;i++) //for the no. of changed settings in the transaction
   948 			{
   949 			TServerSetting temp = t->iTransactionSettings[i];
   950 			t->iTransactionSettings[i].SetAccessPolicy(aRepository->GetFallbackAccessPolicy(temp.Key()));		
   951 			//Correct the access policy pointer so that its pointing to the new valid location
   952 			}
   953 		t = iter;
   954 		}
   955 	}