brandingserver/bsclient/bsprocessstarter.cpp
changeset 0 e6b17d312c8b
child 21 cfd5c2994f10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brandingserver/bsclient/bsprocessstarter.cpp	Thu Dec 17 08:54:49 2009 +0200
@@ -0,0 +1,405 @@
+/*
+* Copyright (c) 2009 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: bsprocessstarter.cpp
+*
+*/
+//  INCLUDE FILES
+#include "bsprocessstarter.h"
+#include <e32std.h>
+#include <f32file.h>
+
+
+// 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 ========================
+// ==============================================================
+
+
+// --------------------------------------------------------------
+// BSProcessStarter::FullExePathForClienLocation()
+// --------------------------------------------------------------
+//
+void BSProcessStarter::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 );
+    }
+
+
+
+// --------------------------------------------------------------
+// BSProcessStarter::StartInstance()
+// --------------------------------------------------------------
+//
+TInt BSProcessStarter::StartInstance(
+    const TDesC& aFullExePath,
+    const TDesC& aCommand,
+    const TArray< TProcessStartupParam >* 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 = BSProcessStarter::DoStartInstance( aFullExePath,
+                                             aCommand,
+                                             aParams );
+
+    launchMutex.Signal();
+    launchMutex.Close();
+
+    return error;
+    }
+
+
+
+// --------------------------------------------------------------
+// BSProcessStarter::ConnectToServer()
+// --------------------------------------------------------------
+//
+TInt BSProcessStarter::ConnectToServer(
+    const TDesC& aFullExePath,
+    const TDesC& aCommand,
+    const TArray< TProcessStartupParam >* 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 = BSProcessStarter::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 )
+                {
+                // 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;
+            }
+        }
+
+    return err;
+    }
+
+
+
+// --------------------------------------------------------------
+// BSProcessStarter::DoStartServerInstance()
+// --------------------------------------------------------------
+//
+TInt BSProcessStarter::DoStartInstance(
+    const TDesC& aFullExePath,
+    const TDesC& aCommand,
+    const TArray< TProcessStartupParam >* 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();
+            // 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();
+
+    return error;
+    }
+
+
+
+// --------------------------------------------------------------
+// BSProcessStarter::ApplyParameters()
+// --------------------------------------------------------------
+//
+TInt BSProcessStarter::ApplyParameters(
+    const TArray< TProcessStartupParam >* 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 ======================
+// ==============================================================
+
+// --------------------------------------------------------------
+// TProcessStartupParam::TProcessStartupParam()
+// --------------------------------------------------------------
+//
+TProcessStartupParam::TProcessStartupParam()
+    : iType( EUnknown ),
+      iSlot( KErrNotFound )
+    {
+    }
+
+
+// --------------------------------------------------------------
+// TProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TProcessStartupParam::Set( TInt aSlot,
+                                const RHandleBase& aHandle )
+    {
+    iType = EHandle;
+    iSlot = aSlot;
+    iHandle = &aHandle;
+    }
+
+
+// --------------------------------------------------------------
+// TProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TProcessStartupParam::Set( TInt aSlot,
+                                const RSubSessionBase& aSubSession )
+    {
+    iType = ESubSession;
+    iSlot = aSlot;
+    iSubSession = &aSubSession;
+    }
+
+
+// --------------------------------------------------------------
+// TProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TProcessStartupParam::Set( TInt aSlot,
+                                const TDesC16& aDes )
+    {
+    iType = EDes16;
+    iSlot = aSlot;
+    iDes16.Set( aDes );
+    }
+
+
+// --------------------------------------------------------------
+// TProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TProcessStartupParam::Set( TInt aSlot,
+                                const TDesC8& aDes )
+    {
+    iType = EDes8;
+    iSlot = aSlot;
+    iDes8.Set( aDes );
+    }
+
+
+// --------------------------------------------------------------
+// TProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TProcessStartupParam::Set( TInt aSlot,
+                                TInt aInt )
+    {
+    iType = EInt;
+    iSlot = aSlot;
+    iInt = aInt;
+    }
+
+
+// --------------------------------------------------------------
+// TProcessStartupParam::ApplyParam()
+// --------------------------------------------------------------
+//
+TInt TProcessStartupParam::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
+
+
+