diff --git a/src/libs/qmldebug/qmldebug-lib.pri b/src/libs/qmldebug/qmldebug-lib.pri index 28c269ab350..92366373381 100644 --- a/src/libs/qmldebug/qmldebug-lib.pri +++ b/src/libs/qmldebug/qmldebug-lib.pri @@ -20,7 +20,8 @@ HEADERS += \ $$PWD/qmltoolsclient.h \ $$PWD/qmlenginecontrolclient.h \ $$PWD/qmldebugcommandlinearguments.h \ - $$PWD/qmldebugconnection.h + $$PWD/qmldebugconnection.h \ + $$PWD/qmldebugconnectionmanager.h SOURCES += \ $$PWD/qmldebugclient.cpp \ @@ -33,4 +34,5 @@ SOURCES += \ $$PWD/qmltoolsclient.cpp \ $$PWD/declarativeenginedebugclient.cpp \ $$PWD/qmlenginecontrolclient.cpp \ - $$PWD/qmldebugconnection.cpp + $$PWD/qmldebugconnection.cpp \ + $$PWD/qmldebugconnectionmanager.cpp diff --git a/src/libs/qmldebug/qmldebug.qbs b/src/libs/qmldebug/qmldebug.qbs index 2f5c30e1632..9cac1e8d7fe 100644 --- a/src/libs/qmldebug/qmldebug.qbs +++ b/src/libs/qmldebug/qmldebug.qbs @@ -29,6 +29,8 @@ Project { "qmldebugcommandlinearguments.h", "qmldebugconnection.cpp", "qmldebugconnection.h", + "qmldebugconnectionmanager.cpp", + "qmldebugconnectionmanager.h", "qmldebugconstants.h", "qmlenginecontrolclient.cpp", "qmlenginecontrolclient.h", diff --git a/src/libs/qmldebug/qmldebugconnectionmanager.cpp b/src/libs/qmldebug/qmldebugconnectionmanager.cpp new file mode 100644 index 00000000000..bb1c0ebde86 --- /dev/null +++ b/src/libs/qmldebug/qmldebugconnectionmanager.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "qmldebugconnectionmanager.h" +#include "qmldebugconnection.h" + +#include +#include + +namespace QmlDebug { + +QmlDebugConnectionManager::QmlDebugConnectionManager(QObject *parent) : QObject(parent) +{ +} + +QmlDebugConnectionManager::~QmlDebugConnectionManager() +{ + // Don't receive any signals from the dtors of child objects while our own dtor is running. + // That can lead to invalid reads. + if (m_connection) + disconnectConnectionSignals(); +} + +void QmlDebugConnectionManager::setRetryParams(int interval, int maxAttempts) +{ + m_retryInterval = interval; + m_maximumRetries = maxAttempts; +} + +void QmlDebugConnectionManager::connectToServer(const QUrl &server) +{ + if (m_server != server) { + m_server = server; + destroyConnection(); + stopConnectionTimer(); + } + if (server.scheme() == Utils::urlTcpScheme()) + connectToTcpServer(); + else if (server.scheme() == Utils::urlSocketScheme()) + startLocalServer(); + else + QTC_ASSERT(false, emit connectionFailed()); +} + +void QmlDebugConnectionManager::disconnectFromServer() +{ + m_server.clear(); + destroyConnection(); + stopConnectionTimer(); +} + +static quint16 port16(const QUrl &url) +{ + const int port32 = url.port(); + QTC_ASSERT(port32 > 0 && port32 <= std::numeric_limits::max(), return 0); + return static_cast(port32); +} + +void QmlDebugConnectionManager::connectToTcpServer() +{ + // Calling this again when we're already trying means "reset the retry timer". This is + // useful in cases where we have to parse the port from the output. We might waste retries + // on an initial guess for the port. + stopConnectionTimer(); + connect(&m_connectionTimer, &QTimer::timeout, this, [this]{ + QTC_ASSERT(!isConnected(), return); + + if (++(m_numRetries) < m_maximumRetries) { + if (m_connection.isNull()) { + // If the previous connection failed, recreate it. + createConnection(); + m_connection->connectToHost(m_server.host(), port16(m_server)); + } else if (m_numRetries < 3 + && m_connection->socketState() != QAbstractSocket::ConnectedState) { + // If we don't get connected in the first retry interval, drop the socket and try + // with a new one. On some operating systems (maxOS) the very first connection to a + // TCP server takes a very long time to get established and this helps. + // On other operating systems (windows) every connection takes forever to get + // established. So, after tearing down and rebuilding the socket twice, just + // keep trying with the same one. + m_connection->connectToHost(m_server.host(), port16(m_server)); + } // Else leave it alone and wait for hello. + } else { + // On final timeout, clear the connection. + stopConnectionTimer(); + destroyConnection(); + emit connectionFailed(); + } + }); + m_connectionTimer.start(m_retryInterval); + + if (m_connection.isNull()) { + createConnection(); + QTC_ASSERT(m_connection, emit connectionFailed(); return); + m_connection->connectToHost(m_server.host(), port16(m_server)); + } +} + +void QmlDebugConnectionManager::startLocalServer() +{ + stopConnectionTimer(); + connect(&m_connectionTimer, &QTimer::timeout, this, [this]() { + QTC_ASSERT(!isConnected(), return); + + // We leave the server running as some application might currently be trying to + // connect. Don't cut this off, or the application might hang on the hello mutex. + // qmlConnectionFailed() might drop the connection, which is fatal. We detect this + // here and signal it accordingly. + + if (!m_connection || ++(m_numRetries) >= m_maximumRetries) { + stopConnectionTimer(); + emit connectionFailed(); + } + }); + m_connectionTimer.start(m_retryInterval); + + if (m_connection.isNull()) { + // Otherwise, reuse the same one + createConnection(); + QTC_ASSERT(m_connection, emit connectionFailed(); return); + m_connection->startLocalServer(m_server.path()); + } +} + +void QmlDebugConnectionManager::retryConnect() +{ + if (m_server.scheme() == Utils::urlSocketScheme()) { + startLocalServer(); + } else if (m_server.scheme() == Utils::urlTcpScheme()) { + destroyConnection(); + connectToTcpServer(); + } else { + emit connectionFailed(); + } +} + +void QmlDebugConnectionManager::logState(const QString &message) +{ + Q_UNUSED(message); +} + +QmlDebugConnection *QmlDebugConnectionManager::connection() const +{ + return m_connection.data(); +} + +void QmlDebugConnectionManager::createConnection() +{ + QTC_ASSERT(m_connection.isNull(), destroyConnection()); + + m_connection.reset(new QmlDebug::QmlDebugConnection); + + createClients(); + connectConnectionSignals(); +} + +void QmlDebugConnectionManager::connectConnectionSignals() +{ + QTC_ASSERT(m_connection, return); + QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::connected, + this, &QmlDebugConnectionManager::qmlDebugConnectionOpened); + QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::disconnected, + this, &QmlDebugConnectionManager::qmlDebugConnectionClosed); + QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::connectionFailed, + this, &QmlDebugConnectionManager::qmlDebugConnectionFailed); + + QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::logStateChange, + this, &QmlDebugConnectionManager::logState); + QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::logError, + this, &QmlDebugConnectionManager::logState); +} + +void QmlDebugConnectionManager::disconnectConnectionSignals() +{ + QTC_ASSERT(m_connection, return); + m_connection->disconnect(); +} + +bool QmlDebugConnectionManager::isConnected() const +{ + return m_connection && m_connection->isConnected(); +} + +void QmlDebugConnectionManager::destroyConnection() +{ + // This might be called indirectly by QDebugConnectionPrivate::readyRead(). + // Therefore, allow the function to complete before deleting the object. + if (m_connection) { + // Don't receive any more signals from the connection or the client + disconnectConnectionSignals(); + destroyClients(); + m_connection.take()->deleteLater(); + } +} + +void QmlDebugConnectionManager::qmlDebugConnectionOpened() +{ + logState(tr("Debug connection opened")); + QTC_ASSERT(m_connection, return); + QTC_ASSERT(m_connection->isConnected(), return); + stopConnectionTimer(); + emit connectionOpened(); +} + +void QmlDebugConnectionManager::qmlDebugConnectionClosed() +{ + logState(tr("Debug connection closed")); + QTC_ASSERT(m_connection, return); + QTC_ASSERT(!m_connection->isConnected(), return); + destroyConnection(); + emit connectionClosed(); +} + +void QmlDebugConnectionManager::qmlDebugConnectionFailed() +{ + logState(tr("Debug connection failed")); + QTC_ASSERT(m_connection, return); + QTC_ASSERT(!m_connection->isConnected(), /**/); + + destroyConnection(); + // The retry handler, driven by m_connectionTimer should decide to retry or signal a failure. + + QTC_ASSERT(m_connectionTimer.isActive(), emit connectionFailed()); +} + +void QmlDebugConnectionManager::stopConnectionTimer() +{ + m_connectionTimer.stop(); + m_connectionTimer.disconnect(); + m_numRetries = 0; +} + +} // namespace QmlDebug diff --git a/src/libs/qmldebug/qmldebugconnectionmanager.h b/src/libs/qmldebug/qmldebugconnectionmanager.h new file mode 100644 index 00000000000..b9ff5618dbe --- /dev/null +++ b/src/libs/qmldebug/qmldebugconnectionmanager.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include + +#include +#include +#include + +namespace QmlDebug { + +class QMLDEBUG_EXPORT QmlDebugConnectionManager : public QObject +{ + Q_OBJECT +public: + explicit QmlDebugConnectionManager(QObject *parent = 0); + ~QmlDebugConnectionManager(); + + void connectToServer(const QUrl &server); + void disconnectFromServer(); + + bool isConnected() const; + + void setRetryParams(int interval, int maxAttempts); + void retryConnect(); + +signals: + void connectionOpened(); + void connectionFailed(); + void connectionClosed(); + +protected: + virtual void createClients() = 0; + virtual void destroyClients() = 0; + virtual void logState(const QString &message); + + QmlDebugConnection *connection() const; + +private: + void connectToTcpServer(); + void startLocalServer(); + + QScopedPointer m_connection; + QTimer m_connectionTimer; + QUrl m_server; + + int m_retryInterval = 200; + int m_maximumRetries = 50; + int m_numRetries = 0; + + void createConnection(); + void destroyConnection(); + + void connectConnectionSignals(); + void disconnectConnectionSignals(); + + void stopConnectionTimer(); + + void qmlDebugConnectionOpened(); + void qmlDebugConnectionClosed(); + void qmlDebugConnectionFailed(); +}; + +} // namespace QmlDebug diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index d6f3ccbe7cd..19af40c41cd 100644 --- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -28,33 +28,28 @@ #include "qmlprofilermodelmanager.h" #include "qmlprofilerstatemanager.h" -#include - #include -#include namespace QmlProfiler { namespace Internal { -QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : QObject(parent) +QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : + QmlDebug::QmlDebugConnectionManager(parent) { setObjectName(QLatin1String("QML Profiler Connections")); } -QmlProfilerClientManager::~QmlProfilerClientManager() +void QmlProfilerClientManager::setModelManager(QmlProfilerModelManager *modelManager) { - // Don't receive any signals from the dtors of child objects while our own dtor is running. - // That can lead to invalid reads. - if (m_connection) - m_connection->disconnect(); - if (m_qmlclientplugin) - m_qmlclientplugin->disconnect(); + QTC_ASSERT(!connection() && !m_clientPlugin, disconnectFromServer()); + m_modelManager = modelManager; } -void QmlProfilerClientManager::setModelManager(QmlProfilerModelManager *m) +void QmlProfilerClientManager::setProfilerStateManager(QmlProfilerStateManager *profilerState) { - QTC_ASSERT(m_connection.isNull() && m_qmlclientplugin.isNull(), disconnectClient()); - m_modelManager = m; + // Don't do this while connecting + QTC_ASSERT(!connection() && !m_clientPlugin, disconnectFromServer()); + m_profilerState = profilerState; } void QmlProfilerClientManager::setFlushInterval(quint32 flushInterval) @@ -62,274 +57,78 @@ void QmlProfilerClientManager::setFlushInterval(quint32 flushInterval) m_flushInterval = flushInterval; } -void QmlProfilerClientManager::setRetryParams(int interval, int maxAttempts) -{ - m_retryInterval = interval; - m_maximumRetries = maxAttempts; -} - -void QmlProfilerClientManager::connectToServer(const QUrl &server) -{ - if (m_server != server) { - m_server = server; - disconnectClient(); - stopConnectionTimer(); - } - if (server.scheme() == Utils::urlTcpScheme()) - connectToTcpServer(); - else if (server.scheme() == Utils::urlSocketScheme()) - startLocalServer(); - else - QTC_ASSERT(false, emit connectionFailed()); -} - -void QmlProfilerClientManager::clearConnection() -{ - m_server.clear(); - disconnectClient(); - stopConnectionTimer(); -} - void QmlProfilerClientManager::clearBufferedData() { - if (m_qmlclientplugin) - m_qmlclientplugin->clearData(); -} - -void QmlProfilerClientManager::connectToTcpServer() -{ - // Calling this again when we're already trying means "reset the retry timer". This is - // useful in cases where we have to parse the port from the output. We might waste retries - // on an initial guess for the port. - stopConnectionTimer(); - connect(&m_connectionTimer, &QTimer::timeout, this, [this]{ - QTC_ASSERT(!isConnected(), return); - - if (++(m_numRetries) < m_maximumRetries) { - if (m_connection.isNull()) { - // If the previous connection failed, recreate it. - createConnection(); - m_connection->connectToHost(m_server.host(), m_server.port()); - } else if (m_numRetries < 3 - && m_connection->socketState() != QAbstractSocket::ConnectedState) { - // If we don't get connected in the first retry interval, drop the socket and try - // with a new one. On some operating systems (maxOS) the very first connection to a - // TCP server takes a very long time to get established and this helps. - // On other operating systems (windows) every connection takes forever to get - // established. So, after tearing down and rebuilding the socket twice, just - // keep trying with the same one. - m_connection->connectToHost(m_server.host(), m_server.port()); - } // Else leave it alone and wait for hello. - } else { - // On final timeout, clear the connection. - stopConnectionTimer(); - if (m_connection) - disconnectClientSignals(); - m_qmlclientplugin.reset(); - m_connection.reset(); - emit connectionFailed(); - } - }); - m_connectionTimer.start(m_retryInterval); - - if (m_connection.isNull()) { - QTC_ASSERT(m_qmlclientplugin.isNull(), disconnectClient()); - createConnection(); - QTC_ASSERT(m_connection, emit connectionFailed(); return); - m_connection->connectToHost(m_server.host(), m_server.port()); - } -} - -void QmlProfilerClientManager::startLocalServer() -{ - stopConnectionTimer(); - connect(&m_connectionTimer, &QTimer::timeout, this, [this]() { - QTC_ASSERT(!isConnected(), return); - - // We leave the server running as some application might currently be trying to - // connect. Don't cut this off, or the application might hang on the hello mutex. - // qmlConnectionFailed() might drop the connection, which is fatal. We detect this - // here and signal it accordingly. - - if (!m_connection || ++(m_numRetries) >= m_maximumRetries) { - stopConnectionTimer(); - emit connectionFailed(); - } - }); - m_connectionTimer.start(m_retryInterval); - - if (m_connection.isNull()) { - // Otherwise, reuse the same one - QTC_ASSERT(m_qmlclientplugin.isNull(), disconnectClient()); - createConnection(); - QTC_ASSERT(m_connection, emit connectionFailed(); return); - m_connection->startLocalServer(m_server.path()); - } + if (m_clientPlugin) + m_clientPlugin->clearData(); } void QmlProfilerClientManager::stopRecording() { - QTC_ASSERT(m_qmlclientplugin, return); - m_qmlclientplugin->setRecording(false); + QTC_ASSERT(m_clientPlugin, return); + m_clientPlugin->setRecording(false); } -void QmlProfilerClientManager::retryConnect() -{ - if (m_server.scheme() == Utils::urlSocketScheme()) { - startLocalServer(); - } else if (m_server.scheme() == Utils::urlTcpScheme()) { - disconnectClient(); - connectToTcpServer(); - } else { - emit connectionFailed(); - } -} - -void QmlProfilerClientManager::createConnection() +void QmlProfilerClientManager::createClients() { QTC_ASSERT(m_profilerState, return); QTC_ASSERT(m_modelManager, return); - QTC_ASSERT(m_connection.isNull() && m_qmlclientplugin.isNull(), disconnectClient()); - - m_connection.reset(new QmlDebug::QmlDebugConnection); + QTC_ASSERT(!m_clientPlugin, return); // false by default (will be set to true when connected) m_profilerState->setServerRecording(false); m_profilerState->setRecordedFeatures(0); - m_qmlclientplugin.reset(new QmlProfilerTraceClient(m_connection.data(), m_modelManager, - m_profilerState->requestedFeatures())); - m_qmlclientplugin->setFlushInterval(m_flushInterval); - connectClientSignals(); -} + m_clientPlugin = new QmlProfilerTraceClient(connection(), m_modelManager, + m_profilerState->requestedFeatures()); + QTC_ASSERT(m_clientPlugin, return); -void QmlProfilerClientManager::connectClientSignals() -{ - QTC_ASSERT(m_connection, return); - QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::connected, - this, &QmlProfilerClientManager::qmlDebugConnectionOpened); - QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::disconnected, - this, &QmlProfilerClientManager::qmlDebugConnectionClosed); - QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::connectionFailed, - this, &QmlProfilerClientManager::qmlDebugConnectionFailed); + m_clientPlugin->setFlushInterval(m_flushInterval); - QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::logStateChange, - this, &QmlProfilerClientManager::logState); - QObject::connect(m_connection.data(), &QmlDebug::QmlDebugConnection::logError, - this, &QmlProfilerClientManager::logState); - - - QTC_ASSERT(m_qmlclientplugin, return); - QTC_ASSERT(m_modelManager, return); - QObject::connect(m_qmlclientplugin.data(), &QmlProfilerTraceClient::traceFinished, + QObject::connect(m_clientPlugin.data(), &QmlProfilerTraceClient::traceFinished, m_modelManager->traceTime(), &QmlProfilerTraceTime::increaseEndTime); - QTC_ASSERT(m_profilerState, return); QObject::connect(m_profilerState.data(), &QmlProfilerStateManager::requestedFeaturesChanged, - m_qmlclientplugin.data(), &QmlProfilerTraceClient::setRequestedFeatures); - QObject::connect(m_qmlclientplugin.data(), &QmlProfilerTraceClient::recordedFeaturesChanged, + m_clientPlugin.data(), &QmlProfilerTraceClient::setRequestedFeatures); + QObject::connect(m_clientPlugin.data(), &QmlProfilerTraceClient::recordedFeaturesChanged, m_profilerState.data(), &QmlProfilerStateManager::setRecordedFeatures); - QObject::connect(m_qmlclientplugin.data(), &QmlProfilerTraceClient::traceStarted, + QObject::connect(m_clientPlugin.data(), &QmlProfilerTraceClient::traceStarted, this, [this](qint64 time) { m_profilerState->setServerRecording(true); m_modelManager->traceTime()->decreaseStartTime(time); }); - QObject::connect(m_qmlclientplugin.data(), &QmlProfilerTraceClient::complete, - this, [this](qint64 time) { + QObject::connect(m_clientPlugin, &QmlProfilerTraceClient::complete, this, [this](qint64 time) { m_modelManager->traceTime()->increaseEndTime(time); m_profilerState->setServerRecording(false); }); QObject::connect(m_profilerState.data(), &QmlProfilerStateManager::clientRecordingChanged, - m_qmlclientplugin.data(), &QmlProfilerTraceClient::setRecording); + m_clientPlugin.data(), &QmlProfilerTraceClient::setRecording); + QObject::connect(this, &QmlDebug::QmlDebugConnectionManager::connectionOpened, + m_clientPlugin.data(), [this]() { + m_clientPlugin->setRecording(m_profilerState->clientRecording()); + }); } -void QmlProfilerClientManager::disconnectClientSignals() +void QmlProfilerClientManager::destroyClients() { - QTC_ASSERT(m_connection, return); - m_connection->disconnect(); - - QTC_ASSERT(m_qmlclientplugin, return); - m_qmlclientplugin->disconnect(); + QTC_ASSERT(m_clientPlugin, return); + m_clientPlugin->disconnect(); + m_clientPlugin->deleteLater(); QTC_ASSERT(m_profilerState, return); QObject::disconnect(m_profilerState.data(), &QmlProfilerStateManager::requestedFeaturesChanged, - m_qmlclientplugin.data(), &QmlProfilerTraceClient::setRequestedFeatures); + m_clientPlugin.data(), &QmlProfilerTraceClient::setRequestedFeatures); QObject::disconnect(m_profilerState.data(), &QmlProfilerStateManager::clientRecordingChanged, - m_qmlclientplugin.data(), &QmlProfilerTraceClient::setRecording); + m_clientPlugin.data(), &QmlProfilerTraceClient::setRecording); + m_clientPlugin.clear(); } -bool QmlProfilerClientManager::isConnected() const +void QmlProfilerClientManager::logState(const QString &message) { - return m_connection && m_connection->isConnected(); -} - -void QmlProfilerClientManager::disconnectClient() -{ - // This might be called indirectly by QDebugConnectionPrivate::readyRead(). - // Therefore, allow the function to complete before deleting the object. - if (m_connection) { - // Don't receive any more signals from the connection or the client - disconnectClientSignals(); - - QTC_ASSERT(m_connection && m_qmlclientplugin, return); - m_qmlclientplugin.take()->deleteLater(); - m_connection.take()->deleteLater(); - } -} - -void QmlProfilerClientManager::qmlDebugConnectionOpened() -{ - logState(tr("Debug connection opened")); - QTC_ASSERT(m_profilerState, return); - QTC_ASSERT(m_connection && m_qmlclientplugin, return); - QTC_ASSERT(m_connection->isConnected(), return); - stopConnectionTimer(); - m_qmlclientplugin->setRecording(m_profilerState->clientRecording()); - emit connectionOpened(); -} - -void QmlProfilerClientManager::qmlDebugConnectionClosed() -{ - logState(tr("Debug connection closed")); - QTC_ASSERT(m_connection && m_qmlclientplugin, return); - QTC_ASSERT(!m_connection->isConnected(), return); - disconnectClient(); - emit connectionClosed(); -} - -void QmlProfilerClientManager::qmlDebugConnectionFailed() -{ - logState(tr("Debug connection failed")); - QTC_ASSERT(m_connection && m_qmlclientplugin, return); - QTC_ASSERT(!m_connection->isConnected(), /**/); - - disconnectClient(); - // The retry handler, driven by m_connectionTimer should decide to retry or signal a failure. - - QTC_ASSERT(m_connectionTimer.isActive(), emit connectionFailed()); -} - -void QmlProfilerClientManager::logState(const QString &msg) -{ - QmlProfilerTool::logState(QLatin1String("QML Profiler: ") + msg); -} - -void QmlProfilerClientManager::setProfilerStateManager(QmlProfilerStateManager *profilerState) -{ - // Don't do this while connecting - QTC_ASSERT(m_connection.isNull() && m_qmlclientplugin.isNull(), disconnectClient()); - - m_profilerState = profilerState; -} - -void QmlProfilerClientManager::stopConnectionTimer() -{ - m_connectionTimer.stop(); - m_connectionTimer.disconnect(); - m_numRetries = 0; + QmlProfilerTool::logState(QLatin1String("QML Profiler: ") + message); } } // namespace Internal diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h index c64429abc70..8f3c8f668be 100644 --- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -28,6 +28,7 @@ #include "qmlprofilertraceclient.h" #include +#include #include #include @@ -39,63 +40,27 @@ class QmlProfilerStateManager; namespace Internal { -class QmlProfilerClientManager : public QObject +class QmlProfilerClientManager : public QmlDebug::QmlDebugConnectionManager { Q_OBJECT public: explicit QmlProfilerClientManager(QObject *parent = 0); - ~QmlProfilerClientManager(); - void setProfilerStateManager(QmlProfilerStateManager *profilerState); - void connectToServer(const QUrl &server); - void clearConnection(); - - void clearBufferedData(); - bool isConnected() const; - - void setModelManager(QmlProfilerModelManager *m); + void setModelManager(QmlProfilerModelManager *modelManager); void setFlushInterval(quint32 flushInterval); - - void setRetryParams(int interval, int maxAttempts); - void retryConnect(); - + void clearBufferedData(); void stopRecording(); -signals: - void connectionOpened(); - void connectionFailed(); - void connectionClosed(); +protected: + void createClients() override; + void destroyClients() override; + void logState(const QString &message) override; private: - void connectToTcpServer(); - void startLocalServer(); - + QPointer m_clientPlugin; QPointer m_profilerState; QPointer m_modelManager; - QScopedPointer m_connection; - QScopedPointer m_qmlclientplugin; - - QTimer m_connectionTimer; - - QUrl m_server; quint32 m_flushInterval = 0; - - int m_retryInterval = 200; - int m_maximumRetries = 50; - int m_numRetries = 0; - - void disconnectClient(); - void stopConnectionTimer(); - - void qmlDebugConnectionOpened(); - void qmlDebugConnectionClosed(); - void qmlDebugConnectionFailed(); - - void logState(const QString &); - - void createConnection(); - void connectClientSignals(); - void disconnectClientSignals(); }; } // namespace Internal diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp index 576039f1c48..3da45755150 100644 --- a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp +++ b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp @@ -149,7 +149,7 @@ void QmlProfilerClientManagerTest::testConnectionFailure() QCOMPARE(openedSpy.count(), 0); QVERIFY(!clientManager.isConnected()); - clientManager.clearConnection(); + clientManager.disconnectFromServer(); qputenv("QTC_FATAL_ASSERTS", fatalAsserts); } @@ -179,7 +179,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveTcp() QCOMPARE(closedSpy.count(), 0); QVERIFY(!clientManager.isConnected()); - clientManager.clearConnection(); + clientManager.disconnectFromServer(); } void QmlProfilerClientManagerTest::testUnresponsiveLocal() @@ -206,7 +206,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveLocal() QCOMPARE(closedSpy.count(), 0); QVERIFY(!clientManager.isConnected()); - clientManager.clearConnection(); + clientManager.disconnectFromServer(); } void responsiveTestData() @@ -391,7 +391,7 @@ void QmlProfilerClientManagerTest::testInvalidData() QCOMPARE(closedSpy.count(), 0); QVERIFY(!clientManager.isConnected()); - clientManager.clearConnection(); + clientManager.disconnectFromServer(); } void QmlProfilerClientManagerTest::testStopRecording()