diff -r 000000000000 -r e6b17d312c8b ximpfw/core/srcclient/ximpprocessstarter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ximpfw/core/srcclient/ximpprocessstarter.cpp Thu Dec 17 08:54:49 2009 +0200 @@ -0,0 +1,396 @@ +/* +* Copyright (c) 2006 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: XIMP Framework process starter implementation. +* +*/ + + +// INCLUDE FILES +#include "ximpprocessstarter.h" +#include +#include + + +// CONSTANTS +_LIT( KEka2ExeDir,"\\sys\\bin\\"); +_LIT( KEka2LaunchMutexExt, "[lMtx]" ); +const TInt KEka2SrvConnTries = 7; // Try to start 7 times + // before giving up +const TInt KEka2SrvConnInitialRetryWait = 500; // MicroSeconds => 0.0005s + + + +// ============================================================== +// ====================== HELPER CLASS ========================== +// ============================================================== + +/** + * RSessionBase accessor to give to the XIMPProcessStarter + * 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 ======================== +// ============================================================== + + +// -------------------------------------------------------------- +// XIMPProcessStarter::FullExePathForClienLocation() +// -------------------------------------------------------------- +// +EXPORT_C void XIMPProcessStarter::FullExePathForClienLocation( + const TDesC& aExeName, + TFileName& aFullExePath ) + { + //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 ); + } + + +// -------------------------------------------------------------- +// XIMPProcessStarter::StartInstance() +// -------------------------------------------------------------- +// +EXPORT_C TInt XIMPProcessStarter::StartInstance( + const TDesC& aFullExePath, + const TDesC& aCommand, + const TArray< TXIMPProcessStartupParam >* aParams ) + { + 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 ) + { + return error; + } + } + + + launchMutex.Wait(); + + //Serialized access + error = XIMPProcessStarter::DoStartInstance( aFullExePath, + aCommand, + aParams ); + + launchMutex.Signal(); + launchMutex.Close(); + + return error; + } + + +// -------------------------------------------------------------- +// XIMPProcessStarter::ConnectToServer() +// -------------------------------------------------------------- +// +EXPORT_C TInt XIMPProcessStarter::ConnectToServer( + const TDesC& aFullExePath, + const TDesC& aCommand, + const TArray< TXIMPProcessStartupParam >* aParams, + RSessionBase& aSessionToConnect, + const TDesC& aServerName, + const TVersion& aClientVersion, + TInt aAsyncMessageSlots ) + { + 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 = XIMPProcessStarter::StartInstance( aFullExePath, + aCommand, + aParams ); + + //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 ) + { + User::After( startupWait ); // CSI: 92 # + startupWait = 2 * startupWait; + } + } + + else + { + //Server process start failed. Bail out. + return err; + } + } + + return err; + } + + +// -------------------------------------------------------------- +// XIMPProcessStarter::DoStartServerInstance() +// -------------------------------------------------------------- +// +TInt XIMPProcessStarter::DoStartInstance( + const TDesC& aFullExePath, + const TDesC& aCommand, + const TArray< TXIMPProcessStartupParam >* aParams ) + { + TInt error = KErrNone; + + //Create process + RProcess process; + error = process.Create( aFullExePath, aCommand ); + + if( error == KErrNone ) + { + //Set process startup parameters + error = ApplyParameters( aParams, process ); + + //And execute the process and wait it's startup + if( error == KErrNone ) + { + TRequestStatus rendezvousStatus; + process.Rendezvous( rendezvousStatus ); + + process.Resume(); + User::WaitForRequest( rendezvousStatus ); // CSI: 94 # + 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(); + + return error; + } + + +// -------------------------------------------------------------- +// XIMPProcessStarter::ApplyParameters() +// -------------------------------------------------------------- +// +TInt XIMPProcessStarter::ApplyParameters( + const TArray< TXIMPProcessStartupParam >* aParams, + RProcess& aProcess ) + { + TInt error = KErrNone; + if( aParams ) + { + const TInt paramCount = aParams->Count(); + for( TInt ix = 0; ix < paramCount; ix++ ) + { + error = (*aParams)[ ix ].ApplyParam( aProcess ); + if( error != KErrNone ) + { + break; + } + } + } + + return error; + } + + +// ============================================================== +// ================== TPROCESSSTARTUPPARAM ====================== +// ============================================================== + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::TXIMPProcessStartupParam() +// -------------------------------------------------------------- +// +EXPORT_C TXIMPProcessStartupParam::TXIMPProcessStartupParam() + : iType( EUnknown ), + iSlot( KErrNotFound ) + { + } + + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::Set() +// -------------------------------------------------------------- +// +void TXIMPProcessStartupParam::Set( TInt aSlot, + const RHandleBase& aHandle ) + { + iType = EHandle; + iSlot = aSlot; + iHandle = &aHandle; + } + + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::Set() +// -------------------------------------------------------------- +// +void TXIMPProcessStartupParam::Set( TInt aSlot, + const RSubSessionBase& aSubSession ) + { + iType = ESubSession; + iSlot = aSlot; + iSubSession = &aSubSession; + } + + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::Set() +// -------------------------------------------------------------- +// +void TXIMPProcessStartupParam::Set( TInt aSlot, + const TDesC16& aDes ) + { + iType = EDes16; + iSlot = aSlot; + iDes16.Set( aDes ); + } + + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::Set() +// -------------------------------------------------------------- +// +void TXIMPProcessStartupParam::Set( TInt aSlot, + const TDesC8& aDes ) + { + iType = EDes8; + iSlot = aSlot; + iDes8.Set( aDes ); + } + + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::Set() +// -------------------------------------------------------------- +// +EXPORT_C void TXIMPProcessStartupParam::Set( TInt aSlot, + TInt aInt ) + { + iType = EInt; + iSlot = aSlot; + iInt = aInt; + } + + +// -------------------------------------------------------------- +// TXIMPProcessStartupParam::ApplyParam() +// -------------------------------------------------------------- +// +TInt TXIMPProcessStartupParam::ApplyParam( RProcess& aProcess ) const + { + switch( iType ) + { + case EHandle: return aProcess.SetParameter( iSlot, *iHandle ); + case ESubSession: return aProcess.SetParameter( iSlot, *iSubSession ); + case EDes16: return aProcess.SetParameter( iSlot, iDes16 ); + case EDes8: return aProcess.SetParameter( iSlot, iDes8 ); + case EInt: return aProcess.SetParameter( iSlot, iInt ); + } + + return KErrUnknown; + } + + +// END OF FILE + + +