--- /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 <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 ========================
+// ==============================================================
+
+// --------------------------------------------------------------
+// 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
+
+
+