phonebookengines/contactsmodel/cntsrv/src/CCntDbManager.cpp
changeset 0 e686773b3f54
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2005-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 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 
       
    22 
       
    23 #include "persistencelayer.h"
       
    24 #include "CCntDbManager.h"
       
    25 #include "CCntRequest.h"
       
    26 #include "CCntStateMachine.h"
       
    27 #include "CCntBackupRestoreAgent.h"
       
    28 #include "CIniFileManager.h"
       
    29 #include "CntSpeedDials.h"
       
    30 #include "CCntLowDiskManager.h"
       
    31 #include "CViewSubSessions.h"
       
    32 
       
    33 CCntDbManager::CCntDbManager(RFs& aFs, const TDesC& aCntFile, CCntBackupRestoreAgent& aBackupRestoreAgent, CIniFileManager& aIniManager) 
       
    34 : iFs(aFs), iCntFile(aCntFile), iBackupRestoreAgent(aBackupRestoreAgent), iIniManager(aIniManager)
       
    35 	{
       
    36 	}
       
    37 
       
    38 CCntDbManager::~CCntDbManager()
       
    39 	{
       
    40 	iObserverArray.Close();
       
    41 	delete iViewManager;
       
    42  	delete iPersistenceLayer;
       
    43  	delete iStateMachine;
       
    44  	delete iLowDiskManager;
       
    45 	}
       
    46 
       
    47 
       
    48 const TDesC& CCntDbManager::CntFile()
       
    49 	{
       
    50 	return iCntFile;
       
    51 	}
       
    52 
       
    53 /**
       
    54 Object factory method.
       
    55 
       
    56 @param aFs File Server session.
       
    57 @param aCntFile Filename of the Contacts database.
       
    58 @param aFileMode Indicates whether to open, create or replace the Contacts
       
    59 database.  If open is indicated then the actual open takes place within the
       
    60 State Machine and is initiated by the CCntDbManagerController singleton.
       
    61 @param aBackupRestoreAgent The Backup/Restore Agent used to monitor inform this
       
    62 database of Backup/Restore events originating from the SBEngine component.
       
    63 @param aIniManager The Initialisation File Manager used to manage this
       
    64 database's data within cntmodel.ini.
       
    65 
       
    66 @return CCntDbManager instance.
       
    67 */
       
    68 CCntDbManager* CCntDbManager::NewLC(RFs& aFs, const TDesC& aCntFile, TCntFileMode aFileMode, CCntBackupRestoreAgent& aBackupRestoreAgent, CIniFileManager& aIniManager)
       
    69  	{
       
    70 	CCntDbManager* manager = new (ELeave) CCntDbManager(aFs, aCntFile, aBackupRestoreAgent, aIniManager);
       
    71 	CleanupStack::PushL(manager);
       
    72 	manager->ConstructL(aFileMode);
       
    73 	return manager;
       
    74 	}
       
    75 
       
    76 
       
    77 /**
       
    78 Second phase constructor.
       
    79 
       
    80 @param aFileMode Indicates whether to open, create or replace the Contacts
       
    81 database.  If open is indicated then the actual open takes place within the
       
    82 State Machine and is initiated by the CCntDbManagerController singleton.
       
    83 */
       
    84 void CCntDbManager::ConstructL(TCntFileMode aFileMode)
       
    85  	{
       
    86 	iPersistenceLayer = CPersistenceLayer::NewLC(iFs, this, NULL);
       
    87 	CleanupStack::Pop(iPersistenceLayer);
       
    88 
       
    89  	// The State Machine is passed into the Persistence Layer as
       
    90  	// MContactDbObserver since it is the first observer to recieve (and deal
       
    91  	// with) database events outside the Persistence Layer. 
       
    92 	iPersistenceLayer->RegisterDbObserver(StateMachineL());
       
    93 
       
    94 	// Create and replace use the same call just the overwrite is different.
       
    95 	// Once created, the database has to be opened.  The open operation is
       
    96 	// initiated in the State Machine by the CCntDbManagerController singleton
       
    97 	// that creates this CCntDbManager instance.
       
    98 	if (aFileMode == ECntFileCreate)
       
    99 		{
       
   100 		iPersistenceLayer->ContactsFileL().CreateL(iCntFile, MLplContactsFile::EPlLeaveIfExist);
       
   101 		}
       
   102 	else if (aFileMode == ECntFileReplace)
       
   103 		{
       
   104 		iPersistenceLayer->ContactsFileL().CreateL(iCntFile, MLplContactsFile::EPlOverwrite);
       
   105 		}
       
   106 
       
   107 	if (aFileMode == ECntFileCreate || aFileMode == ECntFileReplace)
       
   108 		{
       
   109 		// creating a backup registration file for the newly created or replaced database file.
       
   110 		TRAPD(createErr, BackupRestoreAgent().CreateBackupRegistrationFileL(iCntFile));
       
   111 		
       
   112 		if (createErr != KErrNone)
       
   113 			{
       
   114 			//An error has occured while creating backupregistration file,
       
   115 			//therefore we should delete the newly created database file.
       
   116 			TRAP_IGNORE(iPersistenceLayer->ContactsFileL().DeleteL(iCntFile));
       
   117 			
       
   118 			//return the error recieved while creating BackupRegistration File
       
   119 			User::Leave(createErr);
       
   120 			}	
       
   121 		}
       
   122 
       
   123 	// Start Low Disk Space Manager.  Uses the database file name in iCntFile to
       
   124 	// determine the drive to observe for low disk space.
       
   125 	LowDiskManagerL().Start();
       
   126 	}
       
   127 
       
   128 
       
   129 /**
       
   130 Get the State Machine instance owned by this CCntDbManager.  This instance is
       
   131 used to call CCntStateMachine::ProcessRequestL() which implements the Visitor
       
   132 Pattern.  If the instance does not yet exist then create it (lazy
       
   133 initialisation).
       
   134 
       
   135 @return CCntStateMachine instance owned by this CCntDbManager.
       
   136 
       
   137 @leave KErrNoMemory Out of memory.
       
   138 */
       
   139 CCntStateMachine& CCntDbManager::StateMachineL()
       
   140 	{
       
   141 	if (!iStateMachine)
       
   142 		{
       
   143 		iStateMachine = CCntStateMachine::NewL(*iPersistenceLayer, *this);
       
   144 		}
       
   145 	return *iStateMachine;
       
   146 	}
       
   147 
       
   148 	
       
   149 /**
       
   150 Get the Persistence Layer instance owned by this CCntDbManager.
       
   151 
       
   152 @return CPersistenceLayer instance owned by this CCntDbManager.
       
   153 */
       
   154 CPersistenceLayer& CCntDbManager::GetPersistenceLayer()
       
   155 	{
       
   156 	return *iPersistenceLayer;
       
   157 	}
       
   158 
       
   159 
       
   160 /**
       
   161 Get the Backup/Restore Agent instance owned by this CCntDbManager.
       
   162 
       
   163 @return CCntBackupRestoreAgent instance owned by this CCntDbManager.
       
   164 */
       
   165 CCntBackupRestoreAgent& CCntDbManager::BackupRestoreAgent()
       
   166 	{
       
   167 	return iBackupRestoreAgent;
       
   168 	}
       
   169 
       
   170 
       
   171 /**
       
   172 Get the Initialisation File Manager instance owned by this CCntDbManager.
       
   173 
       
   174 @return CIniFileManager instance owned by this CCntDbManager.
       
   175 */
       
   176 CIniFileManager& CCntDbManager::IniFileManager()
       
   177 	{
       
   178 	return iIniManager;
       
   179 	}
       
   180 
       
   181 
       
   182 /**
       
   183 Get the View Manager instance owned by this CCntDbManager.  If the instance does
       
   184 not yet exist then create it (lazy initialisation).
       
   185 
       
   186 @return CCntStateMachine instance owned by this CCntDbManager.
       
   187 */
       
   188 CViewManager& CCntDbManager::ViewManagerL()
       
   189 	{
       
   190 	if (!iViewManager)
       
   191 		{
       
   192 		iViewManager = CViewManager::NewL(GetPersistenceLayer().FactoryL(), *this);
       
   193 		}	
       
   194 	return *iViewManager;
       
   195 	}
       
   196 
       
   197 
       
   198 /**
       
   199 Create and start Active Object which observes disk threshold notifications.
       
   200 
       
   201 @return CCntLowDiskManager instance owned by this CCntDbManager.
       
   202 */
       
   203 CCntLowDiskManager& CCntDbManager::LowDiskManagerL()
       
   204 	{
       
   205 	if (!iLowDiskManager)
       
   206 		{
       
   207 		// Find out the drive held in iCntFile.  If a drive letter is not
       
   208 		// present then the method leaves.
       
   209 		TParsePtrC parseFileName(iCntFile);
       
   210 		if (!parseFileName.DrivePresent())
       
   211 		{
       
   212 			User::Leave(KErrBadName);
       
   213 		}
       
   214 		TDriveUnit drive(parseFileName.Drive());
       
   215 
       
   216 		iLowDiskManager = CCntLowDiskManager::NewL(*this, KLowDiskThreshold, drive, iFs);	
       
   217 		//
       
   218 		// FUTURE: In later implementation we will call RFs::ReserveDriveSpace()
       
   219 		// either here or via Persistence Layer.  There is no method to un-
       
   220 		// reserve this space - it is automatically cleaned up when the RFs
       
   221 		// object used to reserve the space is closed.
       
   222 		//
       
   223 		}
       
   224 	return *iLowDiskManager;
       
   225 	}
       
   226 
       
   227 
       
   228 	
       
   229 TInt CCntDbManager::FileSizeL()
       
   230 	{
       
   231 	return iPersistenceLayer->ContactsFileL().FileSize();  
       
   232 	}	
       
   233 	
       
   234 
       
   235 /**
       
   236 Add a session (increase the number of clients accessing this database).
       
   237 */
       
   238 void CCntDbManager::AddSession()
       
   239 	{
       
   240 	iSessionCount++;
       
   241 	}
       
   242 
       
   243 
       
   244 /**
       
   245 Remove a session (decrease the number of clients accessing this database).
       
   246 */
       
   247 void CCntDbManager::RemoveSession()
       
   248 	{
       
   249 	iSessionCount--;
       
   250 	}
       
   251 
       
   252 
       
   253 /**
       
   254 Return the session count.  When the session count reaches zero this instance of
       
   255 CCntDbManager can be destroyed.
       
   256 
       
   257 @return Session count.
       
   258 */
       
   259 TInt CCntDbManager::SessionCount() const
       
   260 	{
       
   261 	return iSessionCount;
       
   262 	}
       
   263 
       
   264 
       
   265 /**
       
   266 Add a database event observer for this database.
       
   267 
       
   268 @param aObserver Database event observer to add.
       
   269 */
       
   270 void CCntDbManager::RegisterDatabaseEventObserverL(MContactDbObserver& aObserver)
       
   271 	{
       
   272 	User::LeaveIfError(iObserverArray.InsertInAddressOrder(&aObserver));
       
   273 	}
       
   274 
       
   275 
       
   276 /**
       
   277 Remove a database event observer for this database.
       
   278 
       
   279 @param aObserver Database event observer to remove.
       
   280 */
       
   281 void CCntDbManager::UnRegisterDatabaseEventObserver(MContactDbObserver& aObserver)
       
   282 	{
       
   283 	TInt index = KErrNotFound;
       
   284 	const TInt error = iObserverArray.FindInAddressOrder(&aObserver, index);
       
   285 	if	(error != KErrNotFound)
       
   286 		{
       
   287 		iObserverArray.Remove(index);
       
   288 		}
       
   289 	}
       
   290 
       
   291 
       
   292 /**
       
   293 Process a database event (typically generated in the Persistence Layer).
       
   294 
       
   295 @param aEvent Database event.
       
   296 */
       
   297 void CCntDbManager::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
       
   298 	{
       
   299 	// Notify all registered observers of the event.
       
   300 	NotifyObserversL(aEvent);	
       
   301 	}
       
   302 
       
   303 
       
   304 /**
       
   305 Process a Backup/Restore event (typically generated by the Database Manager 
       
   306 Controller via the Backup/Restore Agent).
       
   307 
       
   308 @param aEvent Database event (limited to Backup/Restore database events).
       
   309 */
       
   310 void CCntDbManager::HandleBackupRestoreEventL(TContactDbObserverEvent aEvent)
       
   311 	{
       
   312 	// Create and then process appropriate request using state machine.
       
   313 	CCntRequest* request = NULL;
       
   314 
       
   315 	switch(aEvent.iType)
       
   316 		{
       
   317 		case EContactDbObserverEventBackupBeginning :
       
   318 		case EContactDbObserverEventRestoreBeginning :
       
   319 			{
       
   320 			request = CReqBackupRestoreBegin::NewLC();
       
   321 			}
       
   322 			break;
       
   323 
       
   324 		case EContactDbObserverEventBackupRestoreCompleted :
       
   325 		// Bad database recovery is automatically carried out in the
       
   326 		// Persistence Layer as part of the opening process.
       
   327 		case EContactDbObserverEventRestoreBadDatabase :
       
   328 			{
       
   329 			request = CReqBackupRestoreEnd::NewLC();
       
   330 			}
       
   331 			break;
       
   332 
       
   333 		default :
       
   334 			{
       
   335 			// Misuse of API (unexpected event).
       
   336 			User::Leave(KErrArgument);
       
   337 			}
       
   338 		}
       
   339 
       
   340 	StateMachineL().ProcessRequestL(request);    // ownership transferred
       
   341 
       
   342 	// ProcessRequestL received ownership of the request, the request only need
       
   343 	// to be popped from CleanupStack.
       
   344 	CleanupStack::Pop(request); 
       
   345 
       
   346 	// Notify all registered observers of Backup/Restore event.
       
   347 	NotifyObserversL(aEvent);
       
   348 	}
       
   349 
       
   350 
       
   351 /**
       
   352 Process a low/not low disk condition.
       
   353 
       
   354 @param aLowDisk ETrue if low disk condition, EFalse otherwise.
       
   355 */
       
   356 void CCntDbManager::HandleLowDiskL(TBool aLowDisk)
       
   357 	{
       
   358 	// Create and then process appropriate request using state machine.
       
   359 	CCntRequest* request = NULL;
       
   360 
       
   361 	if (aLowDisk)
       
   362 		{
       
   363 		request = CReqDiskSpaceLow::NewLC();
       
   364 		}
       
   365 	else
       
   366 		{
       
   367 		request = CReqDiskSpaceNormal::NewLC();
       
   368 		}
       
   369 
       
   370 	StateMachineL().ProcessRequestL(request);    // ownership transferred
       
   371 	
       
   372 	// ProcessRequestL received ownership of the request, the request only need
       
   373 	// to be popped from CleanupStack.
       
   374     CleanupStack::Pop(request);
       
   375 	}
       
   376 
       
   377 
       
   378 /**
       
   379 Notify all registered observers (typically a client session) of a database
       
   380 event.  Each registered observer implements the MContactDbObserver interface
       
   381 which is comprised of the HandleDatabaseEventL() method.
       
   382 
       
   383 @param aEvent Database event to send to registered observers.
       
   384 */
       
   385 void CCntDbManager::NotifyObserversL(const TContactDbObserverEvent aEvent)
       
   386 	{
       
   387 	for(TInt i = iObserverArray.Count()-1; i>=0; --i)
       
   388 		{
       
   389 		iObserverArray[i]->HandleDatabaseEventL(aEvent);
       
   390 		}
       
   391 	}
       
   392 
       
   393 
       
   394 void CCntDbManager::SetCurrentItemL(TContactItemId aContactId, TUint aConnectionId)
       
   395 	{
       
   396 	iIniManager.SetCurrentItemL(iCntFile, aContactId);
       
   397 	TContactDbObserverEvent event;
       
   398 	event.iType = EContactDbObserverEventCurrentItemChanged;
       
   399 	event.iContactId = aContactId;
       
   400 	event.iConnectionId = aConnectionId;
       
   401 	// Save the changes to the contacts model ini file
       
   402 	iIniManager.ScheduleSaveIniFileSettings(CIniFileManager::ESaveCurrentItem);
       
   403 	NotifyObserversL(event);
       
   404 	}
       
   405 
       
   406 
       
   407 void CCntDbManager::RemoveCurrentItemL(TUint aConnectionId)
       
   408 	{
       
   409 	iIniManager.RemoveCurrentItemL(iCntFile);
       
   410 	TContactDbObserverEvent event;
       
   411 	event.iType = EContactDbObserverEventCurrentItemDeleted;
       
   412 	event.iContactId = KNullContactId;
       
   413 	event.iConnectionId = aConnectionId;
       
   414 	// Save the changes to the contacts model ini file
       
   415 	iIniManager.ScheduleSaveIniFileSettings(CIniFileManager::ESaveCurrentItem);
       
   416 	NotifyObserversL(event);
       
   417 	}
       
   418 
       
   419 	
       
   420 TContactItemId CCntDbManager::CurrentItem() const
       
   421 	{
       
   422 	return iIniManager.CurrentItem(iCntFile);
       
   423 	}
       
   424 
       
   425 
       
   426 void CCntDbManager::DeleteNotifyL(TContactItemId aContactId)
       
   427 	{
       
   428 	if (aContactId == CurrentItem())
       
   429 		{
       
   430 		// Tell the server that the current item has just been deleted.
       
   431 		RemoveCurrentItemL(0);
       
   432 		}
       
   433 	}
       
   434 
       
   435 
       
   436 /**
       
   437 Return the speed dial phone number at the specified speed dial table index.
       
   438 */
       
   439 void CCntDbManager::GetSpeedDialContactIdAndPhoneNumberL(const TInt aSpeedDialIndex, TSpeedDialPhoneNumber& aPhoneNumber, TContactItemId& aContactId)
       
   440 	{
       
   441 	const CCntServerSpeedDialTable& table = iIniManager.SpeedDialManager().TableL(iCntFile);
       
   442 	aContactId = table.SpeedDialContactItem(aSpeedDialIndex, aPhoneNumber);
       
   443 	}
       
   444 
       
   445 
       
   446 /**
       
   447 Set the phone number and Contact ID for the specified speed dial table index.
       
   448 */
       
   449 TContactItemId CCntDbManager::SetSpeedDialIdForPositionL(const TInt aSpeedDialIndex, const TContactItemId aContactId,  const TSpeedDialPhoneNumber& aPhoneNumber, TUint aConnectionId, TBool aSendNotification)
       
   450 	{
       
   451 	// Get the speed dial table
       
   452 	CCntServerSpeedDialTable& table = iIniManager.SpeedDialManager().TableL(iCntFile);
       
   453 	// Grab data from the speed dial table
       
   454 	TContactItemId contactIdToBroadcast;
       
   455 	if ( aContactId == KNullContactId )
       
   456 		 {
       
   457 		 TSpeedDialPhoneNumber phoneNumberFromSpeedDialTable;
       
   458 		 contactIdToBroadcast = table.SpeedDialContactItem(aSpeedDialIndex, phoneNumberFromSpeedDialTable);
       
   459 		 }
       
   460 	else
       
   461 		 {
       
   462  		 contactIdToBroadcast = aContactId;
       
   463  		 }
       
   464 
       
   465 	// Update speed dial array
       
   466 	table.SetSpeedDialL(aSpeedDialIndex, aContactId, aPhoneNumber);	
       
   467 	// Save the changes to the contacts model ini file
       
   468 	iIniManager.ScheduleSaveIniFileSettings(CIniFileManager::ESaveSpeedDials);
       
   469 	if (aSendNotification)
       
   470 		{	
       
   471 		//BroadCast the SpeedDialsChanged event
       
   472 		TContactDbObserverEvent event;
       
   473 		event.iType = EContactDbObserverEventSpeedDialsChanged;
       
   474 		event.iContactId = contactIdToBroadcast;
       
   475 		event.iConnectionId = aConnectionId;
       
   476 		NotifyObserversL(event);
       
   477 		}
       
   478 	return contactIdToBroadcast;	
       
   479 	}
       
   480 
       
   481 	
       
   482 CArrayFix<TInt>* CCntDbManager::SpeedDialIndicesForContactIdLC(TContactItemId aContactId)
       
   483 	{
       
   484 	CCntServerSpeedDialTable& table = iIniManager.SpeedDialManager().TableL(iCntFile);	
       
   485 	return table.SpeedDialIndicesForContactIdLC(aContactId);
       
   486 	}
       
   487 
       
   488 	
       
   489 void CCntDbManager::SetCardTemplatePrefIdL(TContactItemId aCardTemplatePrefId, TInt aConnectionId)
       
   490 	{
       
   491 	// This is effectively a Write operation which should not be allowed in low
       
   492 	// disk condition.
       
   493 	if (LowDiskManagerL().LowDiskL())
       
   494 		{
       
   495 		User::Leave(KErrDiskFull);
       
   496 		}
       
   497 	iPersistenceLayer->ContactProperties().SetCardTemplatePrefIdL(aCardTemplatePrefId);
       
   498 	//Notify clients here
       
   499 	TContactDbObserverEvent event;
       
   500 	event.iType = EContactDbObserverEventPreferredTemplateChanged;
       
   501 	event.iContactId = aCardTemplatePrefId;
       
   502 	event.iConnectionId = aConnectionId;
       
   503 	NotifyObserversL(event);	
       
   504 	}
       
   505 
       
   506 
       
   507 void CCntDbManager::RecreateSystemTemplateL()
       
   508 	{
       
   509 	// This is effectively a Write operation which should not be allowed in low
       
   510 	// disk condition.
       
   511 	if (LowDiskManagerL().LowDiskL())
       
   512 		{
       
   513 		User::Leave(KErrDiskFull);
       
   514 		}
       
   515 	iPersistenceLayer->ContactProperties().RecreateSystemTemplateL();
       
   516 	}