Changeset View
Changeset View
Standalone View
Standalone View
src/qt/peertablemodel.cpp
// Copyright (c) 2011-2016 The Bitcoin Core developers | // Copyright (c) 2011-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include "peertablemodel.h" | #include <qt/peertablemodel.h> | ||||
#include "clientmodel.h" | #include <qt/clientmodel.h> | ||||
#include "guiconstants.h" | #include <qt/guiconstants.h> | ||||
#include "guiutil.h" | #include <qt/guiutil.h> | ||||
#include "sync.h" | #include <interfaces/node.h> | ||||
#include "validation.h" // for cs_main | #include <sync.h> | ||||
#include <validation.h> // for cs_main | |||||
#include <QDebug> | #include <QDebug> | ||||
#include <QList> | #include <QList> | ||||
#include <QTimer> | #include <QTimer> | ||||
bool NodeLessThan::operator()(const CNodeCombinedStats &left, | bool NodeLessThan::operator()(const CNodeCombinedStats &left, | ||||
const CNodeCombinedStats &right) const { | const CNodeCombinedStats &right) const { | ||||
const CNodeStats *pLeft = &(left.nodeStats); | const CNodeStats *pLeft = &(left.nodeStats); | ||||
Show All 27 Lines | public: | ||||
/** Column to sort nodes by */ | /** Column to sort nodes by */ | ||||
int sortColumn; | int sortColumn; | ||||
/** Order (ascending or descending) to sort nodes by */ | /** Order (ascending or descending) to sort nodes by */ | ||||
Qt::SortOrder sortOrder; | Qt::SortOrder sortOrder; | ||||
/** Index of rows by node ID */ | /** Index of rows by node ID */ | ||||
std::map<NodeId, int> mapNodeRows; | std::map<NodeId, int> mapNodeRows; | ||||
/** Pull a full list of peers from vNodes into our cache */ | /** Pull a full list of peers from vNodes into our cache */ | ||||
void refreshPeers() { | void refreshPeers(interfaces::Node &node) { | ||||
{ | { | ||||
cachedNodeStats.clear(); | cachedNodeStats.clear(); | ||||
std::vector<CNodeStats> vstats; | |||||
if (g_connman) g_connman->GetNodeStats(vstats); | interfaces::Node::NodesStats nodes_stats; | ||||
cachedNodeStats.reserve(vstats.size()); | node.getNodesStats(nodes_stats); | ||||
for (const CNodeStats &nodestats : vstats) { | cachedNodeStats.reserve(nodes_stats.size()); | ||||
for (auto &node_stats : nodes_stats) { | |||||
CNodeCombinedStats stats; | CNodeCombinedStats stats; | ||||
stats.nodeStateStats.nMisbehavior = 0; | stats.nodeStats = std::get<0>(node_stats); | ||||
stats.nodeStateStats.nSyncHeight = -1; | stats.fNodeStateStatsAvailable = std::get<1>(node_stats); | ||||
stats.nodeStateStats.nCommonHeight = -1; | stats.nodeStateStats = std::get<2>(node_stats); | ||||
stats.fNodeStateStatsAvailable = false; | |||||
stats.nodeStats = nodestats; | |||||
cachedNodeStats.append(stats); | cachedNodeStats.append(stats); | ||||
} | } | ||||
} | } | ||||
// Try to retrieve the CNodeStateStats for each node. | if (sortColumn >= 0) { | ||||
{ | |||||
TRY_LOCK(cs_main, lockMain); | |||||
if (lockMain) { | |||||
for (CNodeCombinedStats &stats : cachedNodeStats) { | |||||
stats.fNodeStateStatsAvailable = GetNodeStateStats( | |||||
stats.nodeStats.nodeid, stats.nodeStateStats); | |||||
} | |||||
} | |||||
} | |||||
if (sortColumn >= 0) | |||||
// sort cacheNodeStats (use stable sort to prevent rows jumping | // sort cacheNodeStats (use stable sort to prevent rows jumping | ||||
// around unnecessarily) | // around unnecessarily) | ||||
qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), | qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), | ||||
NodeLessThan(sortColumn, sortOrder)); | NodeLessThan(sortColumn, sortOrder)); | ||||
} | |||||
// build index map | // build index map | ||||
mapNodeRows.clear(); | mapNodeRows.clear(); | ||||
int row = 0; | int row = 0; | ||||
for (const CNodeCombinedStats &stats : cachedNodeStats) { | for (const CNodeCombinedStats &stats : cachedNodeStats) { | ||||
mapNodeRows.insert( | mapNodeRows.insert( | ||||
std::pair<NodeId, int>(stats.nodeStats.nodeid, row++)); | std::pair<NodeId, int>(stats.nodeStats.nodeid, row++)); | ||||
} | } | ||||
} | } | ||||
int size() const { return cachedNodeStats.size(); } | int size() const { return cachedNodeStats.size(); } | ||||
CNodeCombinedStats *index(int idx) { | CNodeCombinedStats *index(int idx) { | ||||
if (idx >= 0 && idx < cachedNodeStats.size()) | if (idx >= 0 && idx < cachedNodeStats.size()) | ||||
return &cachedNodeStats[idx]; | return &cachedNodeStats[idx]; | ||||
return 0; | return 0; | ||||
} | } | ||||
}; | }; | ||||
PeerTableModel::PeerTableModel(ClientModel *parent) | PeerTableModel::PeerTableModel(interfaces::Node &node, ClientModel *parent) | ||||
: QAbstractTableModel(parent), clientModel(parent), timer(0) { | : QAbstractTableModel(parent), m_node(node), clientModel(parent), timer(0) { | ||||
columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") | columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") | ||||
<< tr("Received") << tr("User Agent"); | << tr("Received") << tr("User Agent"); | ||||
priv.reset(new PeerTablePriv()); | priv.reset(new PeerTablePriv()); | ||||
// default to unsorted | // default to unsorted | ||||
priv->sortColumn = -1; | priv->sortColumn = -1; | ||||
// set up timer for auto refresh | // set up timer for auto refresh | ||||
timer = new QTimer(this); | timer = new QTimer(this); | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) { | const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) { | ||||
return priv->index(idx); | return priv->index(idx); | ||||
} | } | ||||
void PeerTableModel::refresh() { | void PeerTableModel::refresh() { | ||||
Q_EMIT layoutAboutToBeChanged(); | Q_EMIT layoutAboutToBeChanged(); | ||||
priv->refreshPeers(); | priv->refreshPeers(m_node); | ||||
Q_EMIT layoutChanged(); | Q_EMIT layoutChanged(); | ||||
} | } | ||||
int PeerTableModel::getRowByNodeId(NodeId nodeid) { | int PeerTableModel::getRowByNodeId(NodeId nodeid) { | ||||
std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid); | std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid); | ||||
if (it == priv->mapNodeRows.end()) return -1; | if (it == priv->mapNodeRows.end()) return -1; | ||||
return it->second; | return it->second; | ||||
} | } | ||||
void PeerTableModel::sort(int column, Qt::SortOrder order) { | void PeerTableModel::sort(int column, Qt::SortOrder order) { | ||||
priv->sortColumn = column; | priv->sortColumn = column; | ||||
priv->sortOrder = order; | priv->sortOrder = order; | ||||
refresh(); | refresh(); | ||||
} | } |