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