summaryrefslogtreecommitdiffstats
path: root/src/processmanager/qprelaunchprocessbackendfactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/processmanager/qprelaunchprocessbackendfactory.cpp')
-rw-r--r--src/processmanager/qprelaunchprocessbackendfactory.cpp313
1 files changed, 313 insertions, 0 deletions
diff --git a/src/processmanager/qprelaunchprocessbackendfactory.cpp b/src/processmanager/qprelaunchprocessbackendfactory.cpp
new file mode 100644
index 0000000..201aa0d
--- /dev/null
+++ b/src/processmanager/qprelaunchprocessbackendfactory.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+
+#include "qprelaunchprocessbackendfactory.h"
+#include "qprelaunchprocessbackend.h"
+#include "qprocessinfo.h"
+
+QT_BEGIN_NAMESPACE_PROCESSMANAGER
+
+/*!
+ \class QPrelaunchProcessBackendFactory
+ \brief The QPrelaunchProcessBackendFactory class creates QPrelaunchProcessBackend objects
+ \inmodule QtProcessManager
+
+ The QPrelaunchProcessBackendFactory starts up a QPrelaunchProcessBackend using
+ information passed in the constructor.
+*/
+
+/*!
+ \property QPrelaunchProcessBackendFactory::processInfo
+ \brief QProcessInfo record used to create the prelaunched process
+ */
+
+/*!
+ \property QPrelaunchProcessBackendFactory::prelaunchEnabled
+ \brief Controls whether or not a prelaunched process is created.
+
+ If this property is true, a prelaunched process will be created
+ after a suitable time interval. If it is set to false and a
+ prelaunched process exists, that process will be terminated.
+ */
+
+/*!
+ Construct a QPrelaunchProcessBackendFactory with optional \a parent.
+ To be able to use the QPrelaunchProcessBackendFactory, you also need to set
+ a QProcessInfo object to it that specifies which process is prelaunched.
+*/
+QPrelaunchProcessBackendFactory::QPrelaunchProcessBackendFactory(QObject *parent)
+ : QProcessBackendFactory(parent)
+ , m_prelaunch(NULL)
+ , m_info(NULL)
+ , m_prelaunchEnabled(true)
+{
+}
+
+/*!
+ Destroy this and child objects.
+*/
+
+QPrelaunchProcessBackendFactory::~QPrelaunchProcessBackendFactory()
+{
+}
+
+/*!
+ Return true if the QPrelaunchProcessBackendFactory can create
+ a process that matches \a info. The default implementation only checks that
+ a valid info object has been previously set in the factory, and then
+ passes the decision on to the default implementation, which should probably
+ have some kind of QMatchDelegate installed.
+*/
+
+bool QPrelaunchProcessBackendFactory::canCreate(const QProcessInfo &info) const
+{
+ if (!m_info)
+ return false;
+
+ return QProcessBackendFactory::canCreate(info);
+}
+
+/*!
+ Construct a PrelaunchProcessBackend from a QProcessInfo \a info record with \a parent.
+*/
+
+QProcessBackend * QPrelaunchProcessBackendFactory::create(const QProcessInfo &info, QObject *parent)
+{
+ Q_ASSERT(m_info);
+ QPrelaunchProcessBackend *prelaunch = m_prelaunch;
+
+ if (hasPrelaunchedProcess()) {
+ // qDebug() << "Using existing prelaunch";
+ m_prelaunch = NULL;
+ prelaunch->setInfo(info);
+ prelaunch->setParent(parent);
+ prelaunch->disconnect(this);
+ updateState();
+ } else {
+ // qDebug() << "Creating prelaunch from scratch";
+ prelaunch = new QPrelaunchProcessBackend(*m_info, parent);
+ prelaunch->prestart();
+ prelaunch->setInfo(info);
+ }
+ return prelaunch;
+}
+
+/*!
+ Return the prelaunched process information
+ */
+
+QProcessInfo *QPrelaunchProcessBackendFactory::processInfo() const
+{
+ return m_info;
+}
+
+/*!
+ Returns whether prelaunching is enabled for this factory.
+*/
+bool QPrelaunchProcessBackendFactory::prelaunchEnabled() const
+{
+ return m_prelaunchEnabled;
+}
+
+void QPrelaunchProcessBackendFactory::setPrelaunchEnabled(bool value)
+{
+ if (m_prelaunchEnabled != value) {
+ m_prelaunchEnabled = value;
+ updateState();
+ emit prelaunchEnabledChanged();
+ }
+}
+
+/*!
+ Returns whether there is a prelaunched process which is ready to be consumed.
+*/
+bool QPrelaunchProcessBackendFactory::hasPrelaunchedProcess() const
+{
+ return (m_prelaunch && m_prelaunch->isReady());
+}
+
+/*!
+ Under memory restriction, terminate the prelaunch process.
+*/
+void QPrelaunchProcessBackendFactory::handleMemoryRestrictionChange()
+{
+ if (m_memoryRestricted) {
+ if (m_prelaunch) {
+ delete m_prelaunch; // This will kill the child process as well
+ m_prelaunch = NULL;
+ }
+ }
+ updateState();
+}
+
+/*!
+ Returns the prelaunched process backend, or null if none is created.
+ */
+QPrelaunchProcessBackend *QPrelaunchProcessBackendFactory::prelaunchProcessBackend() const
+{
+ return m_prelaunch;
+}
+
+/*!
+ Launch a new prelaunched process backend.
+ */
+
+void QPrelaunchProcessBackendFactory::idleCpuAvailable()
+{
+ // qDebug() << Q_FUNC_INFO;
+ if (m_prelaunchEnabled && !m_prelaunch && !m_memoryRestricted && m_info) {
+ // qDebug() << Q_FUNC_INFO << "...launching";
+ m_prelaunch = new QPrelaunchProcessBackend(*m_info, this);
+ connect(m_prelaunch, SIGNAL(finished(int,QProcess::ExitStatus)),
+ SLOT(prelaunchFinished(int,QProcess::ExitStatus)));
+ connect(m_prelaunch, SIGNAL(error(QProcess::ProcessError)),
+ SLOT(prelaunchError(QProcess::ProcessError)));
+ connect(m_prelaunch, SIGNAL(stateChanged(QProcess::ProcessState)),
+ SLOT(updateState()));
+ m_prelaunch->prestart();
+ emit processPrelaunched();
+ }
+ updateState();
+}
+
+/*!
+ Handle a surprise termination condition - the prelaunched process died
+ unexpectedly.
+ */
+
+void QPrelaunchProcessBackendFactory::prelaunchFinished(int exitCode, QProcess::ExitStatus status)
+{
+ qWarning() << Q_FUNC_INFO << "died unexpectedly" << exitCode << status;
+ if (m_prelaunch) {
+ m_prelaunch->deleteLater();
+ m_prelaunch = NULL;
+ }
+ updateState();
+}
+
+/*!
+ Handle surprise error conditions on the prelaunched process.
+ */
+
+void QPrelaunchProcessBackendFactory::prelaunchError(QProcess::ProcessError err)
+{
+ qWarning() << Q_FUNC_INFO << "unexpected error" << err;
+ if (m_prelaunch) {
+ m_prelaunch->deleteLater();
+ m_prelaunch = NULL;
+ }
+
+ if (err == QProcess::FailedToStart) {
+ qWarning() << Q_FUNC_INFO << "disabling prelaunch because of process errors";
+ m_prelaunchEnabled = false;
+ }
+
+ updateState();
+ emit internalProcessError(err);
+}
+
+/*!
+ Update our presented state, consisting of whether or not we need
+ idle CPU resources and how many internal processes we are running.
+*/
+void QPrelaunchProcessBackendFactory::updateState()
+{
+ Q_ASSERT(!m_prelaunch || !m_memoryRestricted); // If memory is restricted, we must not have a prelaunch process
+
+ setIdleCpuRequest(!m_memoryRestricted && m_prelaunchEnabled && !m_prelaunch && m_info);
+
+ QPidList list;
+ if (m_prelaunch && m_prelaunch->isReady())
+ list << m_prelaunch->pid();
+ setInternalProcesses(list);
+}
+
+/*!
+ Sets the QProcessInfo that is used to determine the prelaunched runtime to \a processInfo.
+ An internal copy is made of the \a processInfo object.
+ */
+void QPrelaunchProcessBackendFactory::setProcessInfo(QProcessInfo *processInfo)
+{
+ if (m_info != processInfo) {
+ if (m_info) {
+ delete m_info;
+ m_info = NULL;
+ }
+
+ if (processInfo) {
+ m_info = new QProcessInfo(*processInfo);
+ m_info->setParent(this);
+ if (m_prelaunch) {
+ m_prelaunch->deleteLater();
+ m_prelaunch = NULL;
+ }
+ }
+ updateState();
+ emit processInfoChanged();
+ }
+}
+
+/*!
+ Sets the QProcessInfo that is used to determine the prelaunched runtime to \a processInfo.
+ */
+void QPrelaunchProcessBackendFactory::setProcessInfo(QProcessInfo& processInfo)
+{
+ setProcessInfo(&processInfo);
+}
+
+
+/*!
+ \fn void QPrelaunchProcessBackendFactory::processInfoChanged()
+ This signal is emitted when the internal QProcessInfo record is
+ changed.
+ */
+/*!
+ \fn void QPrelaunchProcessBackendFactory::prelaunchEnabledChanged()
+ This signal is emitted when the prelaunchEnabled property is changed.
+ */
+/*!
+ \fn void QPrelaunchProcessBackendFactory::processPrelaunched()
+ This signal is emitted when the prelaunched process is first created.
+ */
+
+#include "moc_qprelaunchprocessbackendfactory.cpp"
+
+QT_END_NAMESPACE_PROCESSMANAGER