qthighway/xqserviceutil/src/xqservicemanager.cpp
changeset 24 9d760f716ca8
parent 19 46686fb6258c
child 26 3d09643def13
--- a/qthighway/xqserviceutil/src/xqservicemanager.cpp	Wed Aug 18 10:38:12 2010 +0300
+++ b/qthighway/xqserviceutil/src/xqservicemanager.cpp	Thu Sep 02 21:20:48 2010 +0300
@@ -33,6 +33,7 @@
 #include <QBuffer>
 #include <QString>
 #include <QCoreApplication>
+#include <QHash>
 
 #include "xqservicelog.h"
 #include <xqserviceglobal.h>
@@ -45,7 +46,127 @@
 #include "xqconversions.h"
 
 
+#define TIMER_DELAY 3000
 
+class CProcessInfo : public CActive
+    {
+    public:
+        static void AddProcessL(const TUid& appUid, RProcess& appProcess);
+        static void EnsureProcessCanStartL(const TUid& appUid);
+        
+    protected:
+        CProcessInfo(const TUid& appUid);
+        ~CProcessInfo();
+        void ConstructL(RProcess& appProcess);
+        void DoCancel();
+        void RunL();
+        
+    protected:
+        class ProcessInfoMap
+        {
+        public:
+            ~ProcessInfoMap()
+            {
+                foreach (CProcessInfo* info, map.values())
+                    delete info;
+            }
+            QHash<TInt32, CProcessInfo*> map;
+        };
+        
+        static ProcessInfoMap iProcessInfoMap;
+        const TUid iAppUid;
+    };
+
+
+
+CProcessInfo::ProcessInfoMap CProcessInfo::iProcessInfoMap;
+
+CProcessInfo::CProcessInfo(const TUid& appUid):
+        CActive(CActive::EPriorityStandard), 
+        iAppUid(appUid)
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::CProcessInfo");
+    
+    CActiveScheduler::Add(this);
+}
+
+CProcessInfo::~CProcessInfo()
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::~CProcessInfo");
+    
+    // Cancel asynch request, normally it should be done in DoCancel() 
+    // but we dont wont to cancel request when we cancel active object
+    User::CancelMiscNotifier(iStatus);
+    
+    Cancel();
+}
+
+void CProcessInfo::AddProcessL(const TUid& appUid, RProcess& appProcess)
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::AddProcessL");
+    
+    CProcessInfo* self = new(ELeave) CProcessInfo(appUid);
+    CleanupStack::PushL(self);
+    self->ConstructL(appProcess);
+    CleanupStack::Pop(self);
+}
+
+void CProcessInfo::EnsureProcessCanStartL(const TUid& appUid)
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::EnsureProcessCanStartL");
+    
+    CProcessInfo* previousProcess = iProcessInfoMap.map[appUid.iUid];
+    if (previousProcess) {
+        previousProcess->Cancel();
+        
+        // Timer is for ensure that wait will end. 
+        // Maybe there is possibility that destroing process notification could be lost.
+        RTimer securityTimer;
+        securityTimer.CreateLocal();
+        CleanupClosePushL(securityTimer);
+        
+        TRequestStatus timerStatus;
+        securityTimer.After(timerStatus, TIMER_DELAY);
+        User::WaitForRequest(previousProcess->iStatus, timerStatus);
+        
+        CleanupStack::PopAndDestroy();
+        delete previousProcess;
+        iProcessInfoMap.map.remove(appUid.iUid);
+    }
+}
+
+void CProcessInfo::RunL()
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::RunL");
+    
+    iProcessInfoMap.map.remove(iAppUid.iUid);
+    delete this;
+}
+
+void CProcessInfo::ConstructL(RProcess& appProcess)
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::ConstructL");
+    
+    SetActive();
+    
+    EnsureProcessCanStartL(iAppUid);
+    iProcessInfoMap.map.insert(iAppUid.iUid, this);
+    appProcess.NotifyDestruction(iStatus);
+}
+
+void CProcessInfo::DoCancel()
+{
+    XQSERVICE_DEBUG_PRINT("CProcessInfo::DoCancel");
+    
+    // Cancel asynch request, normally it should be done in DoCancel() 
+    // but we dont wont to cancel request when we cancel active object.
+    // Cancel asynch request is in ~CProcessInfo().
+}
+
+/*!
+    \class XQServiceManagerPrivate
+    \brief Private implementation of the XQServiceManager.
+*/
 class XQServiceManagerPrivate 
     {
     public:
@@ -85,12 +206,23 @@
         XQAiwInterfaceDescriptor iImplDescriptor; 
     };
 
+/*!
+    \class XQServiceManager
+    \brief Discovery and service startup. 
+*/
+
+/*!
+    Constructor.
+*/
 XQServiceManager::XQServiceManager()
 {
     XQSERVICE_DEBUG_PRINT("XQServiceManager::XQServiceManager");
     d = new XQServiceManagerPrivate();
 }
 
+/*!
+    Destructor.
+*/
 XQServiceManager::~XQServiceManager()
 {
     XQSERVICE_DEBUG_PRINT("XQServiceManager::~XQServiceManager");
@@ -99,10 +231,11 @@
 
 /*!
     Starts service
-    \param service The full name of service (servicename + interfacename)
-    \param embedded Start in embedded mode
-    \param applicationUid Returned applicatiion
-    \return List of implementations
+    \param service The full name of service (servicename + interfacename).
+    \param embedded Start in embedded mode.
+    \param applicationUid Returned applicatiion.
+    \param threadId Returned process id of the application.
+    \return Error code if error occured, 0 otherwise.
 */
 int XQServiceManager::startServer(const QString& service, bool embedded, int& applicationUid, quint64& threadId)
 {
@@ -110,6 +243,15 @@
     return startServer(service,embedded,applicationUid,threadId,NULL);
 }
 
+/*!
+    Starts service
+    \param service The full name of service (servicename + interfacename).
+    \param embedded Start in embedded mode.
+    \param applicationUid Returned applicatiion.
+    \param threadId Returned process id of the application.
+    \param userData Additional user data.
+    \return Error code if error occured, 0 otherwise.
+*/
 int XQServiceManager::startServer(const QString& service, bool embedded, int& applicationUid, quint64& threadId,
                                  const void *userData)
 {
@@ -130,9 +272,9 @@
 
 
 /*!
-    Finds implementations for the given interface
-    \param interfaceName Interfacename to match
-    \return List of implementations
+    Finds implementations for the given interface.
+    \param interfaceName Interfacename to match.
+    \return List of implementations.
 */
 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findInterfaces ( const QString &interfaceName ) const
     {
@@ -145,10 +287,10 @@
     }
 
 /*!
-    Finds implementations for the given interface implemented by given service
-    \param serviceName Service name
-    \param interfaceName Interfacename to match
-    \return List of implementations
+    Finds implementations for the given interface implemented by given service.
+    \param serviceName Service name.
+    \param interfaceName Interfacename to match.
+    \return List of implementations.
 */
 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findInterfaces ( const QString &serviceName, const QString &interfaceName ) const
 {
@@ -164,8 +306,8 @@
 
 /*!
     Finds the first implementation for the given interface name.
-    \param interfaceName Interfacename to match
-    \return List of implementations
+    \param interfaceName Interfacename to match.
+    \return List of implementations.
 */
 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findFirstInterface ( const QString &interfaceName ) const
 {
@@ -178,10 +320,10 @@
 }
 
 /*!
-    Finds the first implementation for the given service + interface names
-    \param serviceName Service name
-    \param interfaceName Interfacename to match
-    \return List of implementations
+    Finds the first implementation for the given service + interface names.
+    \param serviceName Service name.
+    \param interfaceName Interfacename to match.
+    \return List of implementations.
 */
 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findFirstInterface ( const QString &serviceName, const QString &interfaceName ) const
 {
@@ -197,7 +339,8 @@
 
 
 /*!
-    Returns the latest error occured
+    Gets the latest error occured.
+    \return Latest error code as integer value.
 */
 int XQServiceManager::latestError() const
 {
@@ -205,7 +348,9 @@
 }
 
 /*!
-    Returns the latest error occured
+    Checks if the given \a implmentation is running.
+    \param implementation Implementation to be checked.
+    \return true if given \a implementation is running, false otherwise.
 */
 bool XQServiceManager::isRunning(const XQAiwInterfaceDescriptor& implementation) const
 {
@@ -347,7 +492,9 @@
                 embed = false;
             }
         }
-         
+        else {
+            CProcessInfo::EnsureProcessCanStartL(uid);
+        }
         TRequestStatus requestStatusForRendezvous;
         
         // start application with command line parameters
@@ -389,6 +536,10 @@
         User::WaitForRequest( requestStatusForRendezvous ); // Make the  rendezvouz
         XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Rendezvous done %d", requestStatusForRendezvous.Int());
 
+        if (!embed) {
+            CProcessInfo::AddProcessL(uid, newApp);
+        }
+        
         User::LeaveIfError( requestStatusForRendezvous.Int()); 
         CleanupStack::PopAndDestroy(2,cmdLine); // newApp, cmdLine