diff -r 000000000000 -r e6b17d312c8b imservices/instantmessagingcache/imcacheclient/src/imcacheprocessstarter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imservices/instantmessagingcache/imcacheclient/src/imcacheprocessstarter.cpp Thu Dec 17 08:54:49 2009 +0200 @@ -0,0 +1,266 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: start the server +* +*/ + + +#include "imcacheprocessstarter.h" +// logs +#include "imcachedebugtrace.h" +// system includes +#include +#include + + +// CONSTANTS +_LIT( KEka2ExeDir,"\\sys\\bin\\"); +_LIT( KEka2LaunchMutexExt, "[lMtx]" ); +const TInt KEka2SrvConnTries = 7; +const TInt KEka2SrvConnInitialRetryWait = 500; //MicroSeconds => 0.0005s + + +// ============================================================== +// ====================== HELPER CLASS ========================== +// ============================================================== + +/** + * RSessionBase accessor to give to the ProcessStarter + * access to RSessionBase::CreateSession(). + */ +class REka2SessionBaseAccessor : public RSessionBase + { + public: // Constructor + inline REka2SessionBaseAccessor() + { + } + + public: // New functions + + /** + * Public access to RSessionBase::CreateSession(). + */ + inline TInt CreateSession( const TDesC& aServer, + const TVersion& aVersion, + TInt aAsyncMessageSlots ) + { + return RSessionBase::CreateSession( aServer, + aVersion, + aAsyncMessageSlots ); + } + }; + + +// ============================================================== +// ====================== PROCESSSTARTER ======================== +// ============================================================== + +// -------------------------------------------------------------- +// IMCacheProcessStarter::FullExePathForClientLocation() +// -------------------------------------------------------------- +// +void IMCacheProcessStarter::FullExePathForClientLocation( + const TDesC& aExeName, + TFileName& aFullExePath ) + { + TRACE( T_LIT("IMCacheProcessStarter::FullExePathForClientLocation begin") ); + //Get drive (C:) where this client code is installed + { + TFileName tmp; + Dll::FileName( tmp ); + aFullExePath.Copy( TParsePtrC( tmp ).Drive() ); + } + + //Build the rest from the exe path + aFullExePath.Append( KEka2ExeDir ); + aFullExePath.Append( aExeName ); + TRACE( T_LIT("IMCacheProcessStarter::FullExePathForClientLocation end") ); + } + +// -------------------------------------------------------------- +// IMCacheProcessStarter::StartInstance() +// -------------------------------------------------------------- +// +TInt IMCacheProcessStarter::StartInstance( + const TDesC& aFullExePath, + const TDesC& aCommand ) + { + TRACE( T_LIT("IMCacheProcessStarter::StartInstance begin") ); + RMutex launchMutex; + TInt error = KErrNotFound; + + { + // Dynamic mutex name used to allow code share + TName launchMutexName( TParsePtrC( aFullExePath ).Name() ); + launchMutexName.Append( KEka2LaunchMutexExt ); + + // Open or Create mutex to serialize to access to server startup code. + // (race condition safe way) + while( error == KErrNotFound ) + { + error = launchMutex.CreateGlobal( launchMutexName ); + if( error != KErrAlreadyExists ) + { + break; + } + error = launchMutex.OpenGlobal( launchMutexName ); + } + + if( error != KErrNone ) + { + TRACE( T_LIT("IMCacheProcessStarter::StartInstance end") ); + return error; + } + } + + + launchMutex.Wait(); + + //Serialized access + error = IMCacheProcessStarter::DoStartInstance( aFullExePath, + aCommand ); + + launchMutex.Signal(); + launchMutex.Close(); + TRACE( T_LIT("IMCacheProcessStarter::StartInstance end") ); + return error; + } + +// -------------------------------------------------------------- +// IMCacheProcessStarter::ConnectToServer() +// -------------------------------------------------------------- +// +TInt IMCacheProcessStarter::ConnectToServer( + const TDesC& aFullExePath, + const TDesC& aCommand, + RSessionBase& aSessionToConnect, + const TDesC& aServerName, + const TVersion& aClientVersion, + TInt aAsyncMessageSlots ) + { + TRACE( T_LIT("IMCacheProcessStarter::ConnectToServer begin") ); + if( aSessionToConnect.Handle() != KNullHandle ) + { + return KErrInUse; + } + + TInt err = KErrNone; + TInt startupWait = KEka2SrvConnInitialRetryWait; + + //Server connect and launch loop + for( TInt trie = 0 ; trie < KEka2SrvConnTries ; trie++ ) + { + REka2SessionBaseAccessor acc; + err = acc.CreateSession( aServerName, + aClientVersion, + aAsyncMessageSlots ); + + if( err == KErrNone ) + { + //session ownership is now on client + aSessionToConnect = acc; + return KErrNone; + } + + else if( ( err == KErrNotFound ) || + ( err == KErrServerTerminated ) ) + { + //Server missing or died when connecting + //Start a new server + err = IMCacheProcessStarter::StartInstance( aFullExePath, + aCommand ); + + //If process exist already, then all is fine + //(some other process started it between the origical connect and launch trie) + if( err == KErrAlreadyExists ) + { + err = KErrNone; + } + + //If server process start failed, bail out. + if( err != KErrNone ) + { + return err; + } + + //If this is 2nd or subsequent try, + //give some time for server to startup + if( trie > 0 ) + { + // Code scanner warning : Use of User::After (id:92) + // it is required to be used here + User::After( startupWait ); // CSI: 92 # See above + startupWait = 2 * startupWait; + } + } + + else + { + //Server process start failed. Bail out. + return err; + } + } + TRACE( T_LIT("IMCacheProcessStarter::ConnectToServer end") ); + return err; + } + +// -------------------------------------------------------------- +// IMCacheProcessStarter::DoStartServerInstance() +// -------------------------------------------------------------- +// +TInt IMCacheProcessStarter::DoStartInstance( + const TDesC& aFullExePath, + const TDesC& aCommand ) + { + TRACE( T_LIT("IMCacheProcessStarter::DoStartInstance begin") ); + TInt error = KErrNone; + + //Create process + RProcess process; + error = process.Create( aFullExePath, aCommand ); + + if( error == KErrNone ) + { + + TRequestStatus rendezvousStatus; + process.Rendezvous( rendezvousStatus ); + + process.Resume(); + // Codescanner warning: user of User::WaitForRequest (Id:94) + // it is required to use at server startup + User::WaitForRequest( rendezvousStatus ); // CSI: 94 # See above + error = rendezvousStatus.Int(); + + if( process.ExitType() != EExitPending ) + { + //Something failed in server startup + //Force the error code to be always something + //else than KErrNone + if( error == KErrNone ) + { + error = KErrServerTerminated; + } + } + + } + + process.Close(); + TRACE( T_LIT("IMCacheProcessStarter::DoStartInstance end") ); + return error; + } + +// END OF FILE + + +