C++ / fmt (pull_request) Failing after 4s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 10s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 9s
Python / static (pull_request) Successful in 33s
Rust / build (pull_request) Successful in 48s
Python / verify (pull_request) Successful in 1m42s
Rust / fmt (pull_request) Successful in 26s
Rust / clippy (pull_request) Successful in 45s
154 lines
3.5 KiB
C++
154 lines
3.5 KiB
C++
#include "networkusage.hpp"
|
|
|
|
#include <qbytearrayview.h>
|
|
#include <qfile.h>
|
|
#include <qtypes.h>
|
|
|
|
#include <array>
|
|
#include <charconv>
|
|
#include <system_error>
|
|
|
|
#include "config/rootnodes.hpp"
|
|
#include "config/dashboard.hpp"
|
|
|
|
namespace ZShell::services {
|
|
|
|
using Qt::StringLiterals::operator""_s;
|
|
|
|
NetworkUsage::NetworkUsage(QObject* parent)
|
|
: TickingService(parent)
|
|
, m_downloadBuffer(new internal::CircularBuffer(this))
|
|
, m_uploadBuffer(new internal::CircularBuffer(this)) {
|
|
m_downloadBuffer->setSmoothingRadius(2);
|
|
m_uploadBuffer->setSmoothingRadius(2);
|
|
|
|
auto* resources =
|
|
config::ConfigSingleton::instance()->dashboard()->performance();
|
|
setHistoryLength(resources->showVram() ? 70 : 30);
|
|
QObject::connect(
|
|
resources,
|
|
&ZShell::config::Performance::showVramChanged,
|
|
this,
|
|
[this, resources] {
|
|
setHistoryLength(resources->showVram() ? 70 : 30);
|
|
});
|
|
}
|
|
|
|
qreal NetworkUsage::downloadSpeed() const {
|
|
return m_downloadSpeed;
|
|
}
|
|
|
|
qreal NetworkUsage::uploadSpeed() const {
|
|
return m_uploadSpeed;
|
|
}
|
|
|
|
qreal NetworkUsage::downloadTotal() const {
|
|
return m_downloadTotal;
|
|
}
|
|
|
|
qreal NetworkUsage::uploadTotal() const {
|
|
return m_uploadTotal;
|
|
}
|
|
|
|
int NetworkUsage::historyLength() const {
|
|
return m_historyLength;
|
|
}
|
|
|
|
void NetworkUsage::setHistoryLength(int length) {
|
|
if (length <= 0 || length == m_historyLength) {
|
|
return;
|
|
}
|
|
m_historyLength = length;
|
|
m_downloadBuffer->setCapacity(m_historyLength + 1);
|
|
m_uploadBuffer->setCapacity(m_historyLength + 1);
|
|
Q_EMIT historyLengthChanged();
|
|
}
|
|
|
|
internal::CircularBuffer* NetworkUsage::downloadBuffer() const {
|
|
return m_downloadBuffer;
|
|
}
|
|
|
|
internal::CircularBuffer* NetworkUsage::uploadBuffer() const {
|
|
return m_uploadBuffer;
|
|
}
|
|
|
|
void NetworkUsage::tick() {
|
|
QFile f(u"/proc/net/dev"_s);
|
|
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
return;
|
|
}
|
|
// Skip headers
|
|
f.readLine();
|
|
f.readLine();
|
|
|
|
quint64 totalRx = 0;
|
|
quint64 totalTx = 0;
|
|
|
|
while (!f.atEnd()) {
|
|
const QByteArray line = f.readLine();
|
|
const qsizetype splitIdx = line.indexOf(':');
|
|
if (splitIdx == -1) {
|
|
continue;
|
|
}
|
|
const QByteArray iface = line.left(splitIdx).trimmed();
|
|
if (iface == QByteArrayView("lo")) {
|
|
continue; // Skip loopback interface
|
|
}
|
|
|
|
// Parse every counter through tx bytes to validate the row
|
|
const char* pos = line.constData() + splitIdx + 1;
|
|
const char* const end = line.constData() + line.size();
|
|
|
|
std::array<unsigned long long, 9> fields{};
|
|
bool valid = true;
|
|
for (unsigned long long& field : fields) {
|
|
while (pos < end && (*pos == ' ' || *pos == '\t'))
|
|
++pos;
|
|
|
|
const auto [next, ec] = std::from_chars(pos, end, field);
|
|
if (ec != std::errc{}) {
|
|
valid = false;
|
|
break;
|
|
}
|
|
pos = next;
|
|
}
|
|
|
|
if (!valid) continue;
|
|
|
|
totalRx += static_cast<quint64>(fields[0]);
|
|
totalTx += static_cast<quint64>(fields[8]);
|
|
}
|
|
f.close();
|
|
|
|
if (!m_initialized) {
|
|
m_prevRx = totalRx;
|
|
m_prevTx = totalTx;
|
|
m_timer.start();
|
|
m_initialized = true;
|
|
return;
|
|
}
|
|
|
|
const qreal elapsed = static_cast<qreal>(m_timer.restart()) / 1000.0;
|
|
const quint64 rxDelta = totalRx >= m_prevRx ? totalRx - m_prevRx : 0;
|
|
const quint64 txDelta = totalTx >= m_prevTx ? totalTx - m_prevTx : 0;
|
|
|
|
m_downloadTotal += static_cast<qreal>(rxDelta);
|
|
m_uploadTotal += static_cast<qreal>(txDelta);
|
|
|
|
if (elapsed > 0.0) {
|
|
// Calculate speeds
|
|
m_downloadSpeed = static_cast<qreal>(rxDelta) / elapsed;
|
|
m_uploadSpeed = static_cast<qreal>(txDelta) / elapsed;
|
|
|
|
m_downloadBuffer->push(m_downloadSpeed);
|
|
m_uploadBuffer->push(m_uploadSpeed);
|
|
}
|
|
|
|
m_prevRx = totalRx;
|
|
m_prevTx = totalTx;
|
|
|
|
emit changed();
|
|
}
|
|
|
|
} // namespace ZShell::services
|