email/imap4mtm/imapprotocolcontroller/src/cimapopbackgroundsync.cpp
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32base.h>
       
    17 #include <mentact.h>
       
    18 
       
    19 #include "cimapopbackgroundsync.h"
       
    20 #include "cimapfolder.h"
       
    21 #include "cimapprotocolcontroller.h"
       
    22 #include "cimapmailstore.h" 
       
    23 #include "cimapsyncmanager.h"
       
    24 #include "cimapcompoundsyncservice.h"
       
    25 #include "cimapsessionconsts.h"
       
    26 #include "cimaplogger.h"
       
    27 
       
    28 CImapOpBackgroundSync::CImapOpBackgroundSync( MImapOpBackgroundSyncObserver& aBackgroundSyncObserver,
       
    29 											  CMsvServerEntry& aServerEntry, 
       
    30 										      CImapSyncManager& aSyncMan,
       
    31 											  CImapSettings& aImapSettings,
       
    32 											  CImapMailStore& aImapMailStore,
       
    33 											  CImapOfflineControl& aImapOfflineControl ) :
       
    34 	CActive(EPriorityStandard),
       
    35 	iBackgroundSyncObserver(aBackgroundSyncObserver),
       
    36 	iEntry(aServerEntry),
       
    37 	iSyncMan(aSyncMan),
       
    38 	iImapSettings(aImapSettings),
       
    39 	iImapMailStore(aImapMailStore),
       
    40 	iImapOfflineControl(aImapOfflineControl),
       
    41 	iMigrateState(ENotMigrating)
       
    42 	{
       
    43 	
       
    44 	}
       
    45 						   
       
    46 CImapOpBackgroundSync::~CImapOpBackgroundSync()
       
    47 	{
       
    48 	Cancel();
       
    49 	delete iCompoundSync;
       
    50 	iCompoundSync = NULL;
       
    51 	}
       
    52 
       
    53 /**
       
    54 Returns a CImapOpBackgroundSync. The background synchronise operation is started 
       
    55 by calling StartSync().
       
    56 
       
    57 @param aBackgroundSyncObserver Owning observer that is notified when the operation is completed.
       
    58 @param aSyncMan IMAP Sync Manager used to perform the full synchronise
       
    59 @return the newly created CImapOpBackgroundSync object. The caller is responsible for deleting
       
    60 the object. Usually this is done after the caller is notified by the CImapOpBackgroundSync
       
    61 object through the MImapOpBackgroundSyncObserver API.
       
    62 */
       
    63 CImapOpBackgroundSync* CImapOpBackgroundSync::NewL( MImapOpBackgroundSyncObserver& aBackgroundSyncObserver,
       
    64 													CMsvServerEntry& aServerEntry,
       
    65 													CImapSyncManager& aSyncMan,
       
    66 													CImapSettings& aImapSettings,
       
    67 													CImapMailStore& aImapMailStore,
       
    68 													CImapOfflineControl& aImapOfflineControl  )
       
    69 	{
       
    70 	CImapOpBackgroundSync* self = new (ELeave) CImapOpBackgroundSync( aBackgroundSyncObserver,
       
    71 																	  aServerEntry,
       
    72 																	  aSyncMan,
       
    73 																	  aImapSettings,
       
    74 																	  aImapMailStore,
       
    75 																	  aImapOfflineControl );
       
    76 	CleanupStack::PushL(self);
       
    77 	self->ConstructL();
       
    78 	CleanupStack::Pop(self);
       
    79 	return self;
       
    80 	}
       
    81 
       
    82 void CImapOpBackgroundSync::ConstructL()
       
    83 	{
       
    84 	iCompoundSync = CImapCompoundSyncService::NewL( iSyncMan, 
       
    85 											    	iEntry, 
       
    86 											    	iImapSettings,
       
    87 											    	iImapMailStore,
       
    88 											    	iImapOfflineControl,
       
    89 											    	EFalse);
       
    90 	CActiveScheduler::Add(this);
       
    91 	}
       
    92 
       
    93 /**
       
    94 Starts the asynchronous background synchronisation. When the operation is completed, the
       
    95 observer iBackgroundSyncObserver is notified.
       
    96 */	
       
    97 void CImapOpBackgroundSync::StartSync(CImapSession& aSession)
       
    98 	{
       
    99 	iSession = &aSession;
       
   100 	iState = EStartingSync;
       
   101 
       
   102 	__LOG_TEXT(iSession->LogId(), "CImapOpBackgroundSync::StartSync()");
       
   103 	
       
   104 	// Complete self
       
   105 	TRequestStatus* status = &iStatus;
       
   106 	User::RequestComplete(status, KErrNone);
       
   107 	SetActive();
       
   108 	}
       
   109 
       
   110 void CImapOpBackgroundSync::RunL()
       
   111 	{
       
   112 	__ASSERT_DEBUG(iSession!=NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EBackgroundSyncSessionIsNull));
       
   113 	
       
   114 	if (iMigrateState==EStoppingForMigrate)
       
   115 		{
       
   116 		// has the sync finished? if so, process normally as we do not need to resume.
       
   117 		// Otherwise mark the background sync as suspended
       
   118 		TImap4CompoundProgress compoundProgress;
       
   119 		iCompoundSync->Progress(compoundProgress);
       
   120 		if (compoundProgress.iGenericProgress.iState != TImap4GenericProgress::EIdle)
       
   121 			{
       
   122 			// the sync op has completed prematurely to allow the migration to occur
       
   123 			iMigrateState=ESuspendedForMigrate;
       
   124 			iBackgroundSyncObserver.BackgroundSyncComplete(iStatus.Int());
       
   125 			iSession = NULL;
       
   126 			return;
       
   127 			}
       
   128 		}
       
   129 
       
   130 	// Normal behaviour follows:
       
   131 	switch (iState)
       
   132 		{
       
   133 		case EStartingSync:
       
   134 			{
       
   135 			iCompoundSync->StartOperation(iStatus, *iSession);
       
   136 			iState = ESynchronising;
       
   137 			SetActive();
       
   138 			break;
       
   139 			}
       
   140 		case ESynchronising:
       
   141 			{
       
   142 			// call backgroundsynccomplete
       
   143 			iState = EFinished;
       
   144 			iBackgroundSyncObserver.BackgroundSyncComplete(iStatus.Int());
       
   145 			break;
       
   146 			}
       
   147 		case ECancelRecoveringSession:
       
   148 			{
       
   149 			// Call syncmanager api to clean up after cancel
       
   150 			iState = ECancelRefreshingSyncManager;
       
   151 			// break; fall through
       
   152 			}
       
   153 		case ECancelRefreshingSyncManager:
       
   154 			{
       
   155 			iState = EFinished;
       
   156 			if(iStatus.Int() != KErrNone)
       
   157 				{
       
   158 				// An error has occured during the flushing of the session.
       
   159 				// Pass the error code to the observer for processing.
       
   160 				iBackgroundSyncObserver.BackgroundSyncComplete(iStatus.Int());	
       
   161 				}
       
   162 			else
       
   163 				{
       
   164 				iBackgroundSyncObserver.BackgroundSyncComplete(KErrCancel);	
       
   165 				}
       
   166 			break;
       
   167 			}
       
   168 		default:
       
   169 			{
       
   170 			__ASSERT_DEBUG(iSession!=NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EBackgroundSyncUnexpectedState));
       
   171 			break;
       
   172 			}
       
   173 		} // end of switch (iState)
       
   174 	}
       
   175 	
       
   176 TInt CImapOpBackgroundSync::RunError(TInt aError)
       
   177 	{
       
   178 	// Complete with error
       
   179 	iBackgroundSyncObserver.BackgroundSyncComplete(aError);
       
   180 	return KErrNone;
       
   181 	}
       
   182 
       
   183 void CImapOpBackgroundSync::DoCancel()
       
   184 	{
       
   185 	switch(iState)
       
   186 		{
       
   187 		case ESynchronising:
       
   188 			{
       
   189 			// Do not change state - cleanup needs it.
       
   190 			// Do not delete as the status needs to be checked later.
       
   191 			if (iMigrateState==ECancellingForMigrate)
       
   192 				{
       
   193 				iCompoundSync->CancelForMigrate();
       
   194 				}
       
   195 			else
       
   196 				{
       
   197 				iCompoundSync->Cancel();
       
   198 				}
       
   199 			break;
       
   200 			}
       
   201 
       
   202 		case ECancelRecoveringSession:
       
   203 			{
       
   204 			iSession->Cancel();
       
   205 			break;
       
   206 			}
       
   207 
       
   208 		case EStartingSync:
       
   209 		case ECancelRefreshingSyncManager:
       
   210 			{
       
   211 			// self-completed or no outstanding request.
       
   212 			break;
       
   213 			}
       
   214 
       
   215 		default:
       
   216 			{
       
   217 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EBackgroundSyncCancelUnexpectedState));
       
   218 			break;
       
   219 			}
       
   220 		}
       
   221 	}
       
   222 
       
   223 /**
       
   224 Calls Cancel() to cancel any outstanding asynchronous service requests,
       
   225 then cleans up the sync manager and issues the appropriate command to 
       
   226 flushes the imap session if necessary.
       
   227 */
       
   228 void CImapOpBackgroundSync::CancelAndCleanup()
       
   229 	{
       
   230 	__LOG_TEXT(iSession->LogId(), "CImapOpBackgroundSync::CancelAndCleanup()");
       
   231 	if (iMigrateState==ESuspendedForMigrate)
       
   232 		{
       
   233 		// already suspended.
       
   234 		iState = EFinished;
       
   235 		iBackgroundSyncObserver.BackgroundSyncComplete(KErrCancel);
       
   236 		}
       
   237 	else
       
   238 		{
       
   239 		Cancel();
       
   240 		if (iState==ESynchronising)
       
   241 			{
       
   242 			iSession->FlushCancelledCommand(iStatus);
       
   243 			iState=ECancelRecoveringSession;
       
   244 			SetActive();
       
   245 			}
       
   246 		else
       
   247 			{
       
   248 			iState = EFinished;
       
   249 			iBackgroundSyncObserver.BackgroundSyncComplete(KErrCancel);
       
   250 			}
       
   251 		}
       
   252 	}
       
   253 
       
   254 
       
   255 void CImapOpBackgroundSync::Progress(TImap4CompoundProgress& aCompoundProgress)
       
   256 	{
       
   257 	iCompoundSync->Progress(aCompoundProgress);	
       
   258 	}
       
   259 
       
   260 /**
       
   261 Returns ETrue if the background sync operation has been suspended to allow
       
   262 a bearer migration to occur.
       
   263 */
       
   264 TBool CImapOpBackgroundSync::IsSuspendedForMigrate()
       
   265 	{
       
   266 	return (iMigrateState==ESuspendedForMigrate?ETrue:EFalse);
       
   267 	}
       
   268 
       
   269 /**
       
   270 Immediately cancels outstanding operation, and recovers the compound operation
       
   271 object to a state in which the operation may be restarted following migration
       
   272 to a new carrier.
       
   273 The operation will be restarted by a call to StartOperation()
       
   274 */
       
   275 void CImapOpBackgroundSync::CancelForMigrate()
       
   276 	{
       
   277 	iMigrateState=ECancellingForMigrate;
       
   278 	Cancel();
       
   279 	iMigrateState=ESuspendedForMigrate;
       
   280 	iSession=NULL;
       
   281 	}
       
   282 
       
   283 /**
       
   284 Indicates that the compound operation should complete as soon as it is possible
       
   285 for the operation to be re-started without requiring large amounts of communication
       
   286 that has already been performed to be repeated to complete the operation.
       
   287 The operation will be restarted by a call to StartOperation()
       
   288 */
       
   289 void CImapOpBackgroundSync::StopForMigrate()
       
   290 	{
       
   291 	iMigrateState=EStoppingForMigrate;
       
   292 	iCompoundSync->StopForMigrate();
       
   293 	}
       
   294 
       
   295 /**
       
   296 Resumes the background sync operation (following bearer migration).
       
   297 @param aSession the connected IMAP session 
       
   298 */
       
   299 void CImapOpBackgroundSync::ResumeOperationL(CImapSession& aSession)
       
   300 	{
       
   301 	iSession = &aSession;
       
   302 	__ASSERT_DEBUG(iMigrateState==ESuspendedForMigrate, TImapServerPanic::ImapPanic(TImapServerPanic::EBackgroundSyncUnexpectedState));
       
   303 	iMigrateState=ENotMigrating;
       
   304 	
       
   305 	switch (iState)
       
   306 		{
       
   307 		case ENotInUse:
       
   308 		case EStartingSync:
       
   309 			{
       
   310 			// the sync operation has not yet been started.
       
   311 			iCompoundSync->StartOperation(iStatus, *iSession);
       
   312 			iState = ESynchronising;
       
   313 			SetActive();
       
   314 			break;
       
   315 			}
       
   316 		case ESynchronising:
       
   317 			{
       
   318 			iCompoundSync->ResumeOperationL(iStatus, *iSession);
       
   319 			SetActive();
       
   320 			break;
       
   321 			}	
       
   322 		case ECancelRecoveringSession:
       
   323 		case ECancelRefreshingSyncManager:
       
   324 		case EFinished:
       
   325 		default:
       
   326 			{
       
   327 			// just auto-complete to force the background sync op to complete.
       
   328 			iState = ESynchronising;
       
   329 			TRequestStatus* status = &iStatus;
       
   330 			User::RequestComplete(status, KErrNone);
       
   331 			SetActive();
       
   332 			}
       
   333 		}
       
   334 	}
       
   335 
       
   336 /**
       
   337 Allows the protocol to specify an array of messages that should not be fetched
       
   338 using the download rules during background sync. This is called in the case that
       
   339 a copy to local or populate operation is requested while the background sync op
       
   340 is still in progress.
       
   341 
       
   342 @param aSelection - the selection of messages that should not be autofetched
       
   343 */
       
   344 void CImapOpBackgroundSync::RemoveFromSelectionL(CMsvEntrySelection& aDeleteSel)
       
   345 	{
       
   346 	if (iCompoundSync)
       
   347 		{
       
   348 		iCompoundSync->RemoveFromSelectionL(aDeleteSel);
       
   349 		}
       
   350 	}
       
   351