phonebookengines/contactsmodel/cntsrv/src/CCntPermanentData.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 <e32base.h>
       
    24 
       
    25 #include "CCntRequest.h"
       
    26 #include "CCntDbManager.h"
       
    27 #include "CCntDbManagerController.h"
       
    28 #include "CCntStateMachine.h"
       
    29 #include "cntviewprivate.h"
       
    30 #include "CViewSubSessions.h"
       
    31 #include <cntviewstore.h>
       
    32 #include "CCntPermanentData.h"
       
    33 #include "CCntLogger.h"
       
    34 
       
    35 /**
       
    36 Object factory method.
       
    37 */
       
    38 CCntPermanentData* CCntPermanentData::NewL(CCntDbManagerController& aController)
       
    39 	{
       
    40 	CCntPermanentData* self = new (ELeave) CCntPermanentData(aController);
       
    41 	CleanupStack::PushL(self);
       
    42 	self->ConstructL();
       
    43 	CleanupStack::Pop(self);
       
    44 	return self;
       
    45 	}
       
    46 
       
    47 
       
    48 /**
       
    49 First phase constructor.
       
    50 */
       
    51 CCntPermanentData::CCntPermanentData(CCntDbManagerController& aController) 
       
    52 : CActive(CActive::EPriorityLow), iState(EStateInitial), iController(aController)
       
    53 	{
       
    54 	CActiveScheduler::Add(this);
       
    55 	}
       
    56 
       
    57 
       
    58 /**
       
    59 Second phase constructor.
       
    60 */
       
    61 void CCntPermanentData::ConstructL()
       
    62 	{
       
    63 	}
       
    64 
       
    65 	
       
    66 /**
       
    67 Object destructor.
       
    68 */	
       
    69 CCntPermanentData::~CCntPermanentData()
       
    70 	{
       
    71 	Cancel();
       
    72 	Close();
       
    73 	}
       
    74 
       
    75 	
       
    76 /*
       
    77 */
       
    78 void CCntPermanentData::Close()
       
    79 	{
       
    80 	iViewDefs.ResetAndDestroy();
       
    81 	for (TInt i = 0; i < iViews.Count(); i++)
       
    82 		{
       
    83 		iViews[i]->Close(*this);
       
    84 		}
       
    85 	iViews.Close();
       
    86 	if (iManager)
       
    87 		{
       
    88 		iController.CloseDatabase(*iManager);
       
    89 		iManager = NULL;
       
    90 		}	
       
    91 	}
       
    92 
       
    93 
       
    94 /**
       
    95 The permanent data is created in a number of asynchronous steps. The AO uses
       
    96 a simple state machine to control the steps:
       
    97 
       
    98 1. Open the default database - EStateOpeningDb.
       
    99 2. Open each default view one at a time - EStateOpeningView.
       
   100    (Views are created one at a time to avoid thrashing the dbms/file server
       
   101    with multiple requests for data that is not contiguous.)
       
   102 3. Once all views are opened, or if there is an error, or the AO is cancelled -
       
   103    EStateFinished.
       
   104 */	
       
   105 void CCntPermanentData::RunL()
       
   106 	{
       
   107 	if (iStatus.Int() == KErrNone)
       
   108 		{
       
   109 		switch (iState)
       
   110 			{
       
   111 			case EStateOpeningDb:
       
   112 				{
       
   113 				if (OpenNextViewL())
       
   114 					{
       
   115 					iState = EStateOpeningView;
       
   116 					iStatus = KRequestPending;
       
   117 					SetActive();
       
   118 					}
       
   119 				else
       
   120 					{
       
   121 					iState = EStateFinished;
       
   122 					}
       
   123 				break;
       
   124 				}
       
   125 			case EStateOpeningView:
       
   126 				{
       
   127 				if (OpenNextViewL())
       
   128 					{
       
   129 					iState = EStateOpeningView;
       
   130 					iStatus = KRequestPending;
       
   131 					SetActive();
       
   132 					}
       
   133 				else
       
   134 					{
       
   135 					iState = EStateFinished;
       
   136 					}		
       
   137 				break;
       
   138 				}
       
   139 			case EStateFinished:
       
   140 				{
       
   141 				// Nothing left to do
       
   142 				break;
       
   143 				}
       
   144 			default:
       
   145 				{
       
   146 				__ASSERT_DEBUG(0, User::Invariant());
       
   147 				break;
       
   148 				}
       
   149 			}
       
   150 		}
       
   151 	else if (iStatus.Int() == KErrNotFound)
       
   152 		{
       
   153 		// File could not be found to open.
       
   154 		iState = EStateFinished;
       
   155 		}		
       
   156 	}
       
   157 
       
   158 
       
   159 /**
       
   160 Only need to cancel requests in certain states, otherwise there is nothing to
       
   161 do.
       
   162 */	
       
   163 void CCntPermanentData::DoCancel()
       
   164 	{
       
   165 	if (IsActive())
       
   166 		{
       
   167 		switch (iState)
       
   168 			{
       
   169 			case EStateOpeningDb:
       
   170 				{
       
   171 				// Cancel the asynchronous open to stop this from recieving any notifications.
       
   172 				CReqCancelInternalAsyncOpen* req = NULL;
       
   173 
       
   174 				TRAP_IGNORE(
       
   175 				    {
       
   176     				// req is Pop'd from the cleanup stack to keep cleanup stack balanced
       
   177     				// before and after the TRAP.
       
   178 				    req = CReqCancelInternalAsyncOpen::NewLC(0);
       
   179 				    CleanupStack::Pop(req);
       
   180                     iManager->StateMachineL().ProcessRequestL(req);  // ownership transferred
       
   181 
       
   182 	                // ProcessRequestL received ownership of the request, req can be set to 
       
   183 	                // NULL
       
   184                     req = NULL;
       
   185 					});
       
   186 
       
   187                 // if request is not being cleaned up within TRAP, clean it up now!
       
   188                 if (req)
       
   189                     {
       
   190                     req->Complete();
       
   191                     delete req;
       
   192                     }
       
   193 
       
   194 				break;
       
   195 				}
       
   196 			case EStateOpeningView: // intentional fall-through.
       
   197 			default:
       
   198 				{
       
   199 				// Self-complete the currently active request.
       
   200 				CompleteSelf(KErrCancel);
       
   201 				break;
       
   202 				}
       
   203 			}
       
   204 		iState = EStateFinished;
       
   205 		}
       
   206 	}
       
   207 
       
   208 
       
   209 /**
       
   210 Any errors will have come from OpenNextViewL() leaving.  This is not a fatal
       
   211 error for this class so do not pass it on to the scheduler.
       
   212 */
       
   213 TInt CCntPermanentData::RunError(TInt /*aError*/)
       
   214 	{
       
   215 	iState = EStateFinished;
       
   216 	return KErrNone;
       
   217 	}
       
   218 
       
   219 	
       
   220 void CCntPermanentData::CompleteSelf(TInt aReason)
       
   221 	{
       
   222 	TRequestStatus* pStat = &iStatus;
       
   223   	User::RequestComplete(pStat, aReason);
       
   224 	}
       
   225 
       
   226 
       
   227 /**
       
   228 Kicks off the creation of the default data. This means:
       
   229 
       
   230 1. Opening the default database.
       
   231 2. Opening any views that are specified in the default view 'store' (a CenRep
       
   232    repository).
       
   233 */	
       
   234 void CCntPermanentData::StartDataCreationL()
       
   235 	{
       
   236 	__ASSERT_ALWAYS(!IsActive(), User::Leave(KErrInUse));
       
   237 	
       
   238 	TContactViewStore::GetDefaultViewsL(iViewDefs);
       
   239 	
       
   240 	if (iViewDefs.Count() == 0)
       
   241 		{
       
   242 		// No views; no need to open the default database.
       
   243 		iState = EStateFinished;
       
   244 		}
       
   245 	else
       
   246 		{
       
   247 		// Only attempt to open the default file if it exists.
       
   248 		if (iController.DatabaseExistsL(KNullDesC))
       
   249 			{
       
   250 			// Open the default database (this is asynchronous).
       
   251 			CReqInternalAsyncOpen* openReq = CReqInternalAsyncOpen::NewLC(0, KNullDesC, iStatus);
       
   252 			// Get an instance of the database manager for this file. One db manager is 
       
   253 			// created per file and shared amoung sessions working on that file.
       
   254 			iManager = iController.GetDbManagerL(openReq->FileName(), ECntFileOpen);
       
   255 			// Process the open request via the state machine
       
   256 			// The state machine ensures the file - owned by the manager - is in a valid
       
   257 			// state to process the request.
       
   258 			iManager->StateMachineL().ProcessRequestL(openReq);  // ownership transferred
       
   259 
       
   260 	        // ProcessRequestL received ownership of the request, the request only need
       
   261 	        // to be popped from CleanupStack.
       
   262 			CleanupStack::Pop(openReq);
       
   263 
       
   264 			iState = EStateOpeningDb;
       
   265 			SetActive();
       
   266 			}
       
   267 		else
       
   268 			{
       
   269 			iState = EStateFinished;
       
   270 			}
       
   271 		}
       
   272 	}
       
   273 
       
   274 
       
   275 /**
       
   276 Checks to see if the given CCntDbManager is being held open by this object AND
       
   277 that it has a reference count of 1, i.e. this is the only object holding a
       
   278 reference to it.
       
   279   
       
   280 @return ETrue if this is the only object with a reference to the CCntDbManager,
       
   281 EFalse otherwise.
       
   282 */
       
   283 TBool CCntPermanentData::IsOnlyClientOfDbManager(CCntDbManager* manager) const
       
   284 	{
       
   285 	if (iManager == manager && manager->SessionCount() == 1)
       
   286 		{
       
   287 		return ETrue;
       
   288 		}
       
   289 	return EFalse;
       
   290 	}
       
   291 
       
   292 
       
   293 /**
       
   294 Destroy any views and the manager being held by this object
       
   295 */	
       
   296 void CCntPermanentData::ReleaseDbManagerL(CCntDbManager* manager)
       
   297 	{
       
   298 	__ASSERT_ALWAYS(manager == iManager, User::Leave(KErrArgument));
       
   299 	Close();
       
   300 	}
       
   301 
       
   302 
       
   303 /**
       
   304 Creates the next view from the list of view definitions.  The actual
       
   305 construction of the view is done asynchronously.  When it has finished this
       
   306 object is notified by a call to HandleContactViewEvent().
       
   307   
       
   308 @return EFalse if no view was created, ETrue otherwise.
       
   309 */
       
   310 TBool CCntPermanentData::OpenNextViewL()
       
   311 	{
       
   312 	if (iViewDefs.Count() == 0)
       
   313 		{
       
   314 		return EFalse;
       
   315 		}
       
   316 
       
   317 	TBool viewCreated(EFalse);
       
   318 	do 
       
   319 		{		
       
   320 		CContactDefaultViewDefinition* viewDef = iViewDefs[0];
       
   321 		CleanupStack::PushL(viewDef);
       
   322 		iViewDefs.Remove(0);
       
   323 		
       
   324 		// Attempt to create a view from the definition.
       
   325 		// If this leaves, the do..while ensures that
       
   326 		// an attempt to create the next view will happen.
       
   327 		CContactViewBase* view = NULL;
       
   328 		TRAPD(err, view = OpenViewFromDefinitionL(*viewDef));
       
   329 		if (err == KErrNone)
       
   330 			{
       
   331 			iViews.AppendL(view);
       
   332 			viewCreated = ETrue;
       
   333 			}
       
   334 		else
       
   335 			{
       
   336   
       
   337 
       
   338 //		 Log the details of the view that failed to be created.
       
   339             DEBUG_PRINTF1(__VERBOSE_DEBUG__,"[CNTMODEL] CCntPermanentData::OpenNextViewL(): Failed to create a view:\n");
       
   340             DEBUG_PRINTF2(__VERBOSE_DEBUG__,"[CNTMODEL] View type: %d\n", viewDef->ViewType());
       
   341             DEBUG_PRINTF2(__VERBOSE_DEBUG__,"[CNTMODEL] View preferences: %d\n", viewDef->ViewPreferences());
       
   342 			DEBUG_PRINT2(__VERBOSE_DEBUG__,_L("[CNTMODEL] View name: %S\n"), &viewDef->ViewNameL());
       
   343 			DEBUG_PRINT2(__VERBOSE_DEBUG__,_L("[CNTMODEL] Sort plugin name: %S\n"), &viewDef->SortPluginNameL());
       
   344 			DEBUG_PRINTF1(__VERBOSE_DEBUG__,"[CNTMODEL] View field sort order: ");
       
   345 			RContactViewSortOrder sortOrder = viewDef->SortOrder();
       
   346 			for (TInt i = 0; i < sortOrder.Count(); i++)
       
   347 				{
       
   348 				DEBUG_PRINTF2(__VERBOSE_DEBUG__,"[CNTMODEL] 0x%x, ", sortOrder[i].iUid);
       
   349 				}
       
   350 			RDebug::Printf("\n");
       
   351 
       
   352 			}
       
   353 		
       
   354 		CleanupStack::PopAndDestroy(viewDef);
       
   355 		}
       
   356 	while (!viewCreated && (iViewDefs.Count() > 0));
       
   357 	return viewCreated;
       
   358 	}
       
   359 
       
   360 	
       
   361 CContactViewBase* CCntPermanentData::OpenViewFromDefinitionL(const CContactDefaultViewDefinition& aViewDef)
       
   362 	{
       
   363 	CContactViewBase* view = NULL;
       
   364 	switch (aViewDef.ViewType())
       
   365 		{
       
   366 		case CContactDefaultViewDefinition::ERemoteView:
       
   367 			{
       
   368 			view = &iManager->ViewManagerL().OpenViewL(aViewDef.SortOrder(), *this, 
       
   369 														aViewDef.ViewPreferences(), 
       
   370 														KNullUid, aViewDef.SortPluginNameL());
       
   371 			break;
       
   372 			}
       
   373 		case CContactDefaultViewDefinition::ENamedRemoteView:
       
   374 			{
       
   375 			view = &iManager->ViewManagerL().OpenNamedViewL(aViewDef.ViewNameL(), 
       
   376 															aViewDef.SortOrder(), *this, 
       
   377 															aViewDef.ViewPreferences(), 
       
   378 															KNullUid, aViewDef.SortPluginNameL());
       
   379 			break;
       
   380 			}
       
   381 		default:
       
   382 			{
       
   383 			User::Leave(KErrArgument);
       
   384 			}
       
   385 		}
       
   386 	return view;	
       
   387 	}
       
   388 
       
   389 
       
   390 void CCntPermanentData::HandleContactViewEvent(const CContactViewBase& /*aView*/, const TContactViewEvent& /*aEvent*/)
       
   391 	{
       
   392 	// Complete the active object regardless of whether the view was 
       
   393 	// created successfully or not. This class is only trying to pre-create 
       
   394 	// the view(s) for the main Contacts application. If there are errors 
       
   395 	// creating the view then the application should deal with them 
       
   396 	// (as it would if this class didn't exist).
       
   397 	if (iState == EStateOpeningView)
       
   398 		{
       
   399 		CompleteSelf(KErrNone);
       
   400 		}
       
   401 	}