add a QAbstractTableModel for domain connection steps

This commit is contained in:
Stephen Birarda 2015-05-26 14:17:02 -07:00
parent f9251471da
commit 626f22191c
5 changed files with 157 additions and 45 deletions

View file

@ -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 <QtCore/QMetaEnum>
#include <NodeList.h>
#include <NumericalConstants.h>
#include "DomainConnectionTableModel.h"
DomainConnectionTableModel::DomainConnectionTableModel(QObject* parent) :
QAbstractTableModel(parent)
{
// ask the NodeList for the current values for connection times
QMap<NodeList::ConnectionStep, quint64> times = DependencyManager::get<NodeList>()->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<NodeList::ConnectionStep>(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();
}
}

View file

@ -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 <QtCore/QAbstractTableModel>
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<quint64> _timestamps;
QList<quint64> _deltas;
QList<quint64> _totals;
};
#endif // hifi_DomainConnectionTableModel_h

View file

@ -143,7 +143,7 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname,
auto nodeList = DependencyManager::get<NodeList>();
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<NodeList>()->flagTimeForConnectionStep(NodeList::ConnectionStep::HandleICEHostname);
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(NodeList::ConnectionStep::SetICEServerSocket);
// emit our signal so we can send a heartbeat to ice-server immediately
emit iceSocketAndIDReceived();

View file

@ -12,6 +12,7 @@
#include <QtCore/QDataStream>
#include <QtCore/QDebug>
#include <QtCore/QJsonDocument>
#include <QtCore/QMetaEnum>
#include <QtCore/QUrl>
#include <QtCore/QThread>
#include <QtNetwork/QHostInfo>
@ -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>("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;
}
}

View file

@ -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<ConnectionStep, quint64> 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<ConnectionStep::Value, quint64> _lastConnectionTimes;
QMap<ConnectionStep, quint64> _lastConnectionTimes;
friend class Application;
};