From 626f22191c3d2d7a3b05c217858408733318507b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 May 2015 14:17:02 -0700 Subject: [PATCH] add a QAbstractTableModel for domain connection steps --- .../src/ui/DomainConnectionTableModel.cpp | 82 +++++++++++++++++++ interface/src/ui/DomainConnectionTableModel.h | 41 ++++++++++ libraries/networking/src/DomainHandler.cpp | 6 +- libraries/networking/src/NodeList.cpp | 27 +++--- libraries/networking/src/NodeList.h | 46 +++++------ 5 files changed, 157 insertions(+), 45 deletions(-) create mode 100644 interface/src/ui/DomainConnectionTableModel.cpp create mode 100644 interface/src/ui/DomainConnectionTableModel.h diff --git a/interface/src/ui/DomainConnectionTableModel.cpp b/interface/src/ui/DomainConnectionTableModel.cpp new file mode 100644 index 0000000000..0f27b56434 --- /dev/null +++ b/interface/src/ui/DomainConnectionTableModel.cpp @@ -0,0 +1,82 @@ +// +// DomainConnectionTableModel.cpp +// interface/src/ui +// +// Created by Stephen Birarda on 05/26/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include + +#include "DomainConnectionTableModel.h" + +DomainConnectionTableModel::DomainConnectionTableModel(QObject* parent) : + QAbstractTableModel(parent) +{ + // ask the NodeList for the current values for connection times + QMap times = DependencyManager::get()->getLastConnectionTimes(); + + // setup our data with the returned values + + quint64 totalTime = 0; + quint64 firstStepTime = times[NodeList::ConnectionStep::LookupAddress] / USECS_PER_MSEC; + quint64 lastStepTime = firstStepTime; + + const QMetaObject &nodeListMeta = NodeList::staticMetaObject; + QMetaEnum stepEnum = nodeListMeta.enumerator(nodeListMeta.indexOfEnumerator("ConnectionStep")); + + for (int i = 0; i < stepEnum.keyCount(); i++) { + NodeList::ConnectionStep step = static_cast(i); + + if (times.contains(step)) { + // When did this step occur, how long since the last step, how long since the start? + _timestamps[_numRows] = times[step] / USECS_PER_MSEC; + _deltas[_numRows] = (_timestamps[_numRows] - lastStepTime); + _totals[_numRows] = _timestamps[_numRows] - firstStepTime; + + // increment the total time by this delta to keep track + totalTime += _deltas[_numRows]; + + lastStepTime = _timestamps[_numRows]; + + // increment our counted number of rows + ++_numRows; + } + } +} + +QVariant DomainConnectionTableModel::headerData(int section, Qt::Orientation orientation, int role) const { + switch(section) { + case 0: + return QVariant("Name"); + case 1: + return QVariant("Timestamp (ms)"); + case 2: + return QVariant("Delta (ms)"); + case 3: + return QVariant("Total Elapsed (ms)"); + default: + return QVariant(); + } +} + +QVariant DomainConnectionTableModel::data(const QModelIndex& index, int role) const { + switch(index.column()) { + case 0: + return _names[index.row()]; + case 1: + return QVariant(_timestamps[index.row()]); + case 2: + return QVariant(_deltas[index.row()]); + case 3: + return QVariant(_totals[index.row()]); + default: + return QVariant(); + } +} diff --git a/interface/src/ui/DomainConnectionTableModel.h b/interface/src/ui/DomainConnectionTableModel.h new file mode 100644 index 0000000000..9c2001dc00 --- /dev/null +++ b/interface/src/ui/DomainConnectionTableModel.h @@ -0,0 +1,41 @@ +// +// DomainConnectionTableModel.h +// interface/src/ui +// +// Created by Stephen Birarda on 05/26/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DomainConnectionTableModel_h +#define hifi_DomainConnectionTableModel_h + +#pragma once + +#include + +class DomainConnectionTableModel: public QAbstractTableModel { + Q_OBJECT +public: + DomainConnectionTableModel(QObject* parent = 0); + + const int NUM_COLUMNS = 4; // name, time, delta, since start + + int rowCount(const QModelIndex& parent = QModelIndex()) const { return _numRows; } + int columnCount(const QModelIndex& parent = QModelIndex()) const { return NUM_COLUMNS; } + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; +private: + int _numRows = 0; + + QVariantList _names; + QList _timestamps; + QList _deltas; + QList _totals; +}; + + +#endif // hifi_DomainConnectionTableModel_h diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index a5d53e8c7a..622eec6fd5 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -143,7 +143,7 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, auto nodeList = DependencyManager::get(); - nodeList->flagTimeForConnectionStep(NodeList::ConnectionStep::LookupICEHostname); + nodeList->flagTimeForConnectionStep(NodeList::ConnectionStep::SetICEServerHostname); if (_iceServerSockAddr.getAddress().isNull()) { // connect to lookup completed for ice-server socket so we can request a heartbeat once hostname is looked up @@ -157,8 +157,6 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, _iceClientID = QUuid::createUuid(); qCDebug(networking) << "ICE required to connect to domain via ice server at" << iceServerHostname; - - nodeList->flagTimeForConnectionStep(NodeList::ConnectionStep::SetICEServerInfo); } } @@ -200,7 +198,7 @@ void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) { void DomainHandler::completedIceServerHostnameLookup() { qDebug() << "ICE server socket is at" << _iceServerSockAddr; - DependencyManager::get()->flagTimeForConnectionStep(NodeList::ConnectionStep::HandleICEHostname); + DependencyManager::get()->flagTimeForConnectionStep(NodeList::ConnectionStep::SetICEServerSocket); // emit our signal so we can send a heartbeat to ice-server immediately emit iceSocketAndIDReceived(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 31e7a88e66..4bfedfd555 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +77,8 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned // clear our NodeList when logout is requested connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); + + qRegisterMetaType("NodeList::ConnectionStep"); } qint64 NodeList::sendStats(const QJsonObject& statsObject, const HifiSockAddr& destination) { @@ -202,8 +205,6 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr if (sendingNode) { sendingNode->setLastHeardMicrostamp(usecTimestampNow()); - qDebug() << "Activating socket for node" << sendingNode->getUUID() << "at" << usecTimestampNow(); - // activate the appropriate socket for this node, if not yet updated activateSocketFromNodeCommunication(packet, sendingNode); @@ -616,8 +617,6 @@ void NodeList::sendAssignment(Assignment& assignment) { } void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { - qDebug() << "Sending ping punch to node" << node->getUUID() << "at" << usecTimestampNow(); - // send the ping packet to the local and public sockets for this node QByteArray localPingPacket = constructPingPacket(PingType::Local); writeDatagram(localPingPacket, node, node->getLocalSocket()); @@ -667,21 +666,15 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con } } -void NodeList::flagTimeForConnectionStep(NodeList::ConnectionStep::Value connectionStep) { +void NodeList::flagTimeForConnectionStep(NodeList::ConnectionStep connectionStep) { QMetaObject::invokeMethod(this, "flagTimeForConnectionStep", - Q_ARG(NodeList::ConnectionStep::Value, connectionStep), - Q_ARG(quint64, usecTimestampNow())); + Q_ARG(NodeList::ConnectionStep, connectionStep), + Q_ARG(quint64, usecTimestampNow())); } -void NodeList::flagTimeForConnectionStep(NodeList::ConnectionStep::Value connectionStep, quint64 timestamp) { - if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "flagTimeForConnectionStep", - Q_ARG(NodeList::ConnectionStep::Value, connectionStep), - Q_ARG(quint64, timestamp)); - } else { - // we only add a timestamp on the first call for each NodeList::ConnectionStep - if (!_lastConnectionTimes.contains(connectionStep)) { - _lastConnectionTimes[connectionStep] = timestamp; - } +void NodeList::flagTimeForConnectionStep(NodeList::ConnectionStep connectionStep, quint64 timestamp) { + // we only add a timestamp on the first call for each NodeList::ConnectionStep + if (!_lastConnectionTimes.contains(connectionStep)) { + _lastConnectionTimes[connectionStep] = timestamp; } } diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 2ceee95f94..42356570a9 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -46,28 +46,26 @@ class NodeList : public LimitedNodeList { public: - class ConnectionStep { - public: - enum Value { - LookupAddress, - HandleAddress, - SetICEServerInfo, - LookupICEHostname, - HandleICEHostname, - SendFirstICEServerHearbeat, - ReceiveDSPeerInformation, - SendFirstPingsToDS, - SetDomainHostname, - SetDomainSocket, - SendFirstDSCheckIn, - ReceiveFirstDSList, - SendFirstAudioPing, - SetAudioMixerSocket, - SendFirstAudioPacket, - ReceiveFirstAudioPacket - }; + enum ConnectionStep { + LookupAddress, + HandleAddress, + SetICEServerHostname, + SetICEServerSocket, + SendFirstICEServerHearbeat, + ReceiveDSPeerInformation, + SendFirstPingsToDS, + SetDomainHostname, + SetDomainSocket, + SendFirstDSCheckIn, + ReceiveFirstDSList, + SendFirstAudioPing, + SetAudioMixerSocket, + SendFirstAudioPacket, + ReceiveFirstAudioPacket }; + Q_ENUMS(ConnectionStep); + NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } @@ -86,7 +84,8 @@ public: int processDomainServerList(const QByteArray& packet); - void flagTimeForConnectionStep(NodeList::ConnectionStep::Value connectionStep); + const QMap getLastConnectionTimes() const; + void flagTimeForConnectionStep(NodeList::ConnectionStep connectionStep); void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; } void sendAssignment(Assignment& assignment); @@ -102,6 +101,7 @@ signals: private slots: void sendPendingDSPathQuery(); void handleICEConnectionToDomainServer(); + void flagTimeForConnectionStep(NodeList::ConnectionStep connectionStep, quint64 timestamp); private: NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile NodeList(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); @@ -120,8 +120,6 @@ private: void sendDSPathQuery(const QString& newPath); - void flagTimeForConnectionStep(NodeList::ConnectionStep::Value connectionStep, quint64 timestamp); - NodeType_t _ownerType; NodeSet _nodeTypesOfInterest; DomainHandler _domainHandler; @@ -130,7 +128,7 @@ private: bool _hasCompletedInitialSTUNFailure; unsigned int _stunRequestsSinceSuccess; - QMap _lastConnectionTimes; + QMap _lastConnectionTimes; friend class Application; };