emailservices/emailservermonitor/src/emailservermonitor.cpp
branchRCL_3
changeset 64 3533d4323edc
equal deleted inserted replaced
63:d189ee25cf9d 64:3533d4323edc
       
     1 /*
       
     2 * Copyright (c) 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 * Implementation of EmailServerMonitor
       
    16 *
       
    17 */
       
    18 
       
    19 //  Include Files  
       
    20 #include <e32base.h>
       
    21 #include <e32std.h>
       
    22 #include <e32des16.h>                   // Descriptors
       
    23 #include <apacmdln.h>
       
    24 #include <apgcli.h>
       
    25 
       
    26 #include <AlwaysOnlineManagerClient.h>  // RAlwaysOnlineClientSession
       
    27 #include <CPsRequestHandler.h>          // CPSRequestHandler
       
    28 
       
    29 #include "emailtrace.h"
       
    30 #include "emailservermonitorutilities.h"
       
    31 #include "emailservermonitor.h"
       
    32 #include "emailservermonitorconst.h"
       
    33 #include "emailshutter.h"
       
    34 
       
    35 const TUint KOneSecondInMicroSeconds = 1000000;
       
    36 
       
    37 const TInt KExternalServiceRestartDelay = 5 * KOneSecondInMicroSeconds;
       
    38 const TInt KInstallatioFinishedFlagSettingDelay = 2 * KOneSecondInMicroSeconds;
       
    39 
       
    40 // ======== MEMBER FUNCTION DEFINITIONS ========
       
    41 
       
    42 /**
       
    43  * Two-phased class constructor.
       
    44  */
       
    45 CEmailServerMonitor* CEmailServerMonitor::NewL()
       
    46     {
       
    47     FUNC_LOG;
       
    48     CEmailServerMonitor* self = CEmailServerMonitor::NewLC();
       
    49     CleanupStack::Pop( self );
       
    50     return self;
       
    51     }
       
    52 
       
    53 /**
       
    54  * Two-phased class constructor.
       
    55  */
       
    56 CEmailServerMonitor* CEmailServerMonitor::NewLC()
       
    57     {
       
    58     FUNC_LOG;
       
    59     CEmailServerMonitor* self = new (ELeave) CEmailServerMonitor();
       
    60     CleanupStack::PushL( self );
       
    61     self->ConstructL();
       
    62     return self;
       
    63     }
       
    64     
       
    65 /**
       
    66  * Destructor of CEmailServerMonitor class.
       
    67  */
       
    68 CEmailServerMonitor::~CEmailServerMonitor()
       
    69     {
       
    70     FUNC_LOG;
       
    71     iApaLsSession.Close();
       
    72     iProcess.Close();
       
    73     iDelayTimer.Close();
       
    74     if( iExternalServiceRestartTimer )
       
    75         {
       
    76         delete iExternalServiceRestartTimer;
       
    77         iExternalServiceRestartTimer = NULL;
       
    78         }
       
    79     }
       
    80     
       
    81 /**
       
    82  * Default class constructor.
       
    83  * Only NewL can be called
       
    84  */
       
    85 CEmailServerMonitor::CEmailServerMonitor()
       
    86     : CActive( EPriorityStandard ),
       
    87       iState( EEsmStateIdle ),
       
    88       iRestarts( 0 ),
       
    89       iShutter( NULL ),
       
    90       iExternalServicesRestartState( EEsmEsrStateRestartNotNeeded )
       
    91     {
       
    92     FUNC_LOG;
       
    93     }
       
    94     
       
    95 /**
       
    96  * Second phase class constructor.
       
    97  */
       
    98 void CEmailServerMonitor::ConstructL()
       
    99     {
       
   100     FUNC_LOG;
       
   101     User::LeaveIfError( iApaLsSession.Connect() );
       
   102     User::LeaveIfError( iDelayTimer.CreateLocal() );
       
   103     
       
   104     CActiveScheduler::Add(this);
       
   105     }
       
   106     
       
   107 /**
       
   108  * Start email server monitoring.
       
   109  */
       
   110 void CEmailServerMonitor::Start()
       
   111     {
       
   112     FUNC_LOG;
       
   113     iLastRestartTime.UniversalTime();
       
   114     
       
   115     // Initiate delayed restart and set correct state
       
   116     InitiateDelayedRestart();
       
   117     iState = EEsmStateInitializing;
       
   118     }
       
   119 
       
   120 /**
       
   121  * Set pointer to shutter.
       
   122  */
       
   123 void CEmailServerMonitor::SetShutter( CEmailShutter* aShutter )
       
   124     {
       
   125     iShutter = aShutter;
       
   126     }
       
   127 
       
   128 /**
       
   129  * Set Restart External Services flag.
       
   130  */
       
   131 void CEmailServerMonitor::SetRestartExternalServicesFlag( TBool aRestartFlag /*= ETrue*/ )
       
   132     {
       
   133     if( aRestartFlag )
       
   134         {
       
   135         iExternalServicesRestartState = EEsmEsrStateRestartNeeded;
       
   136         }
       
   137     else
       
   138         {
       
   139         iExternalServicesRestartState = EEsmEsrStateRestartNotNeeded;
       
   140         }
       
   141     }
       
   142 
       
   143 /**
       
   144  * Called when external service restart timer has expired, so it's time to do
       
   145  * some starting
       
   146  */
       
   147 void CEmailServerMonitor::TimerEventL( CEmailServerMonitorTimer* /*aTriggeredTimer*/ )
       
   148     {
       
   149     // Shutter is used in all cases, so verify it exists at the beginning
       
   150     if( iShutter )
       
   151         {
       
   152         switch( iExternalServicesRestartState )
       
   153             {
       
   154             case EEsmEsrStateRestartInitiated:
       
   155                 {
       
   156                 // Restart external services and change state
       
   157                 iShutter->RestartServicesAfterInstallation();
       
   158                 iExternalServicesRestartState = EEsmEsrStateFirstServiceRestarted;
       
   159                 
       
   160                 // Restart the timer to set the installation finished flag
       
   161                 // with some more delay
       
   162                 iExternalServiceRestartTimer->Start( KInstallatioFinishedFlagSettingDelay );
       
   163                 }
       
   164                 break;
       
   165                 
       
   166             case EEsmEsrStateFirstServiceRestarted:
       
   167                 {
       
   168                 // Set the installation finished flag and clear state variable
       
   169                 iShutter->SetPsKeyInstallationFinished();
       
   170                 iExternalServicesRestartState = EEsmEsrStateRestartNotNeeded;
       
   171                 }
       
   172                 break;
       
   173                 
       
   174             default:
       
   175                 // Do nothing, shouldn't happen
       
   176                 break;
       
   177             }
       
   178         }
       
   179     }
       
   180 
       
   181 /**
       
   182  * Start Email Server and start monitoring it
       
   183  */
       
   184 TBool CEmailServerMonitor::StartEmailServerMonitoring()
       
   185     {
       
   186     FUNC_LOG;
       
   187     // Give iProcess as parameter for IsProcessRunning so that it will
       
   188     // be updated in case that the Email Server process is running.
       
   189     TBool running = IsProcessRunning( KEmailServerUid, &iProcess );
       
   190 	
       
   191     // Start Email Server if it's not yet running
       
   192     if( !running )
       
   193         {
       
   194         iRestarts++;
       
   195         
       
   196         TThreadId threadId;
       
   197         TRequestStatus reqStatusForRendezvous;
       
   198         TRAPD( error, StartApplicationL( KEmailServerExe(), threadId, reqStatusForRendezvous ) );
       
   199         
       
   200         // If application was started succesfully
       
   201         if( error == KErrNone )
       
   202             {
       
   203             User::WaitForRequest( reqStatusForRendezvous );
       
   204             
       
   205             // If process started succesfully, we are ready for observing
       
   206             if( reqStatusForRendezvous.Int() == KErrNone )
       
   207                 {
       
   208                 // Close previous process handle
       
   209                 iProcess.Close();
       
   210                 
       
   211                 // Get handle to newly created process using the threadId
       
   212                 RThread thread;
       
   213                 TInt error = thread.Open( threadId );
       
   214                 if( error == KErrNone )
       
   215                     {
       
   216                     error = thread.Process( iProcess );
       
   217                     thread.Close();
       
   218                     // Indicate success only if iProcess update succeeded, as it's
       
   219                     // assumed to be up-to-date if Email Server process is running
       
   220                     if( error == KErrNone )
       
   221                         {
       
   222                         running = ETrue;
       
   223                         }
       
   224                     }
       
   225                 }
       
   226             }
       
   227         }
       
   228     
       
   229     if( running )
       
   230         {
       
   231         DoStartMonitoring();
       
   232         }
       
   233     else
       
   234         {
       
   235         INFO( "Restart failed!" );
       
   236         }
       
   237     
       
   238     return running;
       
   239     }
       
   240 
       
   241 /**
       
   242  * Starts the actual monitoring. Assumes that Email Server is running
       
   243  * and Monitor's internal variables are set accordingly.
       
   244  */
       
   245 void CEmailServerMonitor::DoStartMonitoring()
       
   246     {
       
   247     FUNC_LOG;
       
   248     SetActive();
       
   249     iProcess.Logon( iStatus );
       
   250     iState = EEsmStateMonitoring;
       
   251     }
       
   252 
       
   253 /**
       
   254  * Start specified application, leaves if failed to start the application
       
   255  */
       
   256 void CEmailServerMonitor::StartApplicationL(
       
   257         const TDesC& aAppName,
       
   258         TThreadId& aThreadId,
       
   259         TRequestStatus& aReqStatusForRendezvous )
       
   260     {
       
   261     CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
       
   262     cmdLine->SetExecutableNameL( aAppName );
       
   263     // Launch Email Server in background so that it doesn't steal
       
   264     // the focus during it's construction
       
   265     cmdLine->SetCommandL( EApaCommandBackground );
       
   266     
       
   267     User::LeaveIfError( iApaLsSession.StartApp( *cmdLine, aThreadId, &aReqStatusForRendezvous ) );
       
   268     
       
   269     CleanupStack::PopAndDestroy( cmdLine );
       
   270     }
       
   271 
       
   272 /**
       
   273  * DoCancel of active object
       
   274  */
       
   275 void CEmailServerMonitor::DoCancel()
       
   276     {
       
   277     FUNC_LOG;
       
   278     iState = EEsmStateIdle;
       
   279     iProcess.LogonCancel( iStatus );
       
   280     iDelayTimer.Cancel();
       
   281     if( iExternalServiceRestartTimer )
       
   282         {
       
   283         iExternalServiceRestartTimer->Cancel();
       
   284         }
       
   285     }
       
   286 
       
   287 /**
       
   288  * RunL of active object
       
   289  */
       
   290 void CEmailServerMonitor::RunL()
       
   291     {
       
   292     FUNC_LOG;
       
   293     
       
   294     INFO_1( "iStatus: %d", iStatus.Int() );
       
   295     INFO_1( "iState: %d", iState );
       
   296 
       
   297     switch( iState )
       
   298         {
       
   299         case EEsmStateMonitoring:
       
   300             {
       
   301             // Write the process exit information to the debug log.
       
   302             INFO_1( "ExitType: %d", iProcess.ExitType() );
       
   303             INFO_1( "ExitReason: %d", iProcess.ExitReason() );
       
   304             HandleMonitorEvent();
       
   305             }
       
   306             break;
       
   307             
       
   308         case EEsmStateInitializing:
       
   309         case EEsmStateRestarting:
       
   310             {
       
   311             // Restart Email server and start monitoring it again
       
   312             if( !StartEmailServerMonitoring() )
       
   313                 {
       
   314 				// If start failed initiate new delayed restart
       
   315                 INFO( "Initiating new delayed restart" );
       
   316                 InitiateDelayedRestart();
       
   317                 }
       
   318             // If Email server is up and running and iExternalServicesRestartState
       
   319             // flag is set, initiate delayed restart of external services
       
   320             else if( iExternalServicesRestartState == EEsmEsrStateRestartNeeded )
       
   321                 {
       
   322                 // Once restart is initiated, update the state
       
   323                 iExternalServicesRestartState = EEsmEsrStateRestartInitiated;
       
   324 
       
   325                 // Create the timer and start it
       
   326                 TInt timerError = KErrNone;
       
   327                 if( !iExternalServiceRestartTimer )
       
   328                     {
       
   329                     TRAP( timerError, iExternalServiceRestartTimer = CEmailServerMonitorTimer::NewL( this ) );
       
   330                     }
       
   331                 if( timerError == KErrNone )
       
   332                     {
       
   333                     iExternalServiceRestartTimer->Start( KExternalServiceRestartDelay );
       
   334                     }
       
   335                 }
       
   336             }
       
   337             break;
       
   338             
       
   339         case EEsmStateIdle:
       
   340         default:
       
   341             {
       
   342             // Shouldn't happen
       
   343             INFO( "Unknown state or not observing!" );
       
   344             }
       
   345         }
       
   346     }
       
   347 
       
   348 /**
       
   349  * Handle email server monitoring event
       
   350  */
       
   351 void CEmailServerMonitor::HandleMonitorEvent()
       
   352     {
       
   353     FUNC_LOG;
       
   354     TExitType exitType = iProcess.ExitType(); 
       
   355     if ( exitType == EExitPanic )
       
   356         {
       
   357         INFO( "Initiating delayed restart of Email Server" );
       
   358         InitiateDelayedRestart();
       
   359         }
       
   360     else if ( exitType == EExitPending )
       
   361         {
       
   362         INFO( "Process is still alive, restarting monitoring" );
       
   363         DoStartMonitoring();
       
   364         }
       
   365     else
       
   366         {
       
   367         INFO( "Email Server terminated, not restarting!" );
       
   368         iState = EEsmStateIdle;
       
   369         }
       
   370     }
       
   371 
       
   372 /**
       
   373  * Initiate an asynchronous delayed restart
       
   374  */
       
   375 void CEmailServerMonitor::InitiateDelayedRestart()
       
   376     {
       
   377     FUNC_LOG;
       
   378     TTime now;
       
   379     now.UniversalTime();
       
   380     
       
   381     // Calculate minutes from last restart
       
   382     TTimeIntervalMinutes minutesSinceLastRestart = 0;
       
   383     now.MinutesFrom( iLastRestartTime, minutesSinceLastRestart );
       
   384     INFO_1( "Minutes since last restart=%d", minutesSinceLastRestart.Int() );
       
   385     
       
   386     iLastRestartTime = now;
       
   387     
       
   388     // If the process has been running successfully long enough then reset
       
   389     // the restart counter.
       
   390     if( minutesSinceLastRestart >= TTimeIntervalMinutes( KEsmUptimeToResetRestartCounter ) )
       
   391         {
       
   392         INFO( "Long enough uptime, reset restart counter" );
       
   393         iRestarts = 0;
       
   394         }
       
   395 
       
   396     // Initiate new delayed restart, if restart limit is not exceeded
       
   397     if( iRestarts < KEsmMaxRestarts )
       
   398         {
       
   399         iDelayTimer.After( iStatus, KEsmRestartDelayInSeconds * KOneSecondInMicroSeconds );
       
   400         SetActive();
       
   401         iState = EEsmStateRestarting;
       
   402         }
       
   403     else
       
   404         {
       
   405         INFO( "Maximum restarts exceeded!" );
       
   406         iState = EEsmStateIdle;
       
   407         }
       
   408     }