blob: dba91ab90b29ef9068c8c57d8c1da9d861adf76a [file] [log] [blame] [raw]
/***************************************************************************
dev.cpp
-------------------
begin : Wed Aug 1 2001
copyright : (C) 2001 - 2012 by Roland Riegel
email : feedback@roland-riegel.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "device.h"
#include "devreader.h"
#include "graph.h"
#include "setting.h"
#include "settingstore.h"
#include "window.h"
#include <iomanip>
using namespace std;
Device::Device(DevReader& devReader)
: m_deviceNumber(0), m_totalNumberOfDevices(0), m_devReader(devReader)
{
}
Device::~Device()
{
}
// update the device's data
void Device::update()
{
// read current traffic
DataFrame dataFrame = m_devReader.getNewDataFrame();
if(dataFrame.isValid())
{
/* Depending on the CPU architecture and the OS interface
* used for reading the device statistics, the counts can
* overflow. We monitor the overflows and fix them.
*/
fixOverflows(dataFrame, m_dataFrameOld);
m_deviceStatistics.insertDataFrame(dataFrame);
m_deviceGraphIn.update(m_deviceStatistics.getDataInPerSecond());
m_deviceGraphOut.update(m_deviceStatistics.getDataOutPerSecond());
m_dataFrameOld = dataFrame;
}
else
{
m_deviceStatistics.reset();
m_deviceGraphIn.resetTrafficData();
m_deviceGraphOut.resetTrafficData();
}
}
// print the device's data
void Device::print(Window& window)
{
// if device does not exist
if(!m_deviceStatistics.isValid())
{
// ... print warning message ...
window.print() << "Device " << m_devReader.getDeviceName() << " (" << (m_deviceNumber + 1) << "/" << m_totalNumberOfDevices << "): does not exist" << endl;
window.print() << string(window.getWidth(), '=') << endl;
// ... and exit
return;
}
// print header
string ip4addr = m_dataFrameOld.getIpV4Address();
if(!ip4addr.empty())
window.print() << "Device " << m_devReader.getDeviceName() << " [" << ip4addr << "] (" << (m_deviceNumber + 1) << "/" << m_totalNumberOfDevices << "):" << endl;
else
window.print() << "Device " << m_devReader.getDeviceName() << " (" << (m_deviceNumber + 1) << "/" << m_totalNumberOfDevices << "):" << endl;
window.print() << string(window.getWidth(), '=');
// if graphs should be hidden ...
if(SettingStore::get("MultipleDevices"))
{
window.print() << "Incoming:";
window.print(window.getWidth() / 2) << "Outgoing:" << endl;
int statusY = window.getY();
printStatisticsIn(window, 0, statusY);
printStatisticsOut(window, window.getWidth() / 2, statusY);
window.print() << endl;
}
// ... or not
else
{
int window_width = window.getWidth();
int graph_width = window_width < 80 ? window_width * 2 / 3 : window_width - 27;
// incoming traffic
window.print() << "Incoming:" << endl;
m_deviceGraphIn.setNumOfBars(graph_width);
m_deviceGraphIn.setHeightOfBars((window.getHeight() - window.getY() - 1) / 2);
m_deviceGraphIn.setMaxDeflection((unsigned long long) SettingStore::get("BarMaxIn") * 1024 / 8);
m_deviceGraphIn.print(window, 0, window.getY());
printStatisticsIn(window, graph_width + 2, window.getY() - 5);
// outgoing traffic
window.print() << "Outgoing:" << endl;
m_deviceGraphOut.setNumOfBars(graph_width);
m_deviceGraphOut.setHeightOfBars(window.getHeight() - window.getY());
m_deviceGraphOut.setMaxDeflection((unsigned long long) SettingStore::get("BarMaxOut") * 1024 / 8);
m_deviceGraphOut.print(window, 0, window.getY());
printStatisticsOut(window, graph_width + 2, window.getY() - 4);
}
}
// set the number identifying the device (for display only)
void Device::setDeviceNumber(int deviceNumber)
{
m_deviceNumber = deviceNumber;
}
// set the total number of shown devices (for display only)
void Device::setTotalNumberOfDevices(int totalNumberOfDevices)
{
m_totalNumberOfDevices = totalNumberOfDevices;
}
void Device::fixOverflows(DataFrame& dataFrame, const DataFrame& dataFrameOld)
{
if(!dataFrame.isValid() || !dataFrameOld.isValid())
return;
dataFrame.setTotalDataIn(fixOverflow(dataFrame.getTotalDataIn(), dataFrameOld.getTotalDataIn()));
dataFrame.setTotalDataOut(fixOverflow(dataFrame.getTotalDataOut(), dataFrameOld.getTotalDataOut()));
dataFrame.setTotalPacketsIn(fixOverflow(dataFrame.getTotalPacketsIn(), dataFrameOld.getTotalPacketsIn()));
dataFrame.setTotalPacketsOut(fixOverflow(dataFrame.getTotalPacketsOut(), dataFrameOld.getTotalPacketsOut()));
dataFrame.setTotalErrorsIn(fixOverflow(dataFrame.getTotalErrorsIn(), dataFrameOld.getTotalErrorsIn()));
dataFrame.setTotalErrorsOut(fixOverflow(dataFrame.getTotalErrorsOut(), dataFrameOld.getTotalErrorsOut()));
dataFrame.setTotalDropsIn(fixOverflow(dataFrame.getTotalDropsIn(), dataFrameOld.getTotalDropsIn()));
dataFrame.setTotalDropsOut(fixOverflow(dataFrame.getTotalDropsOut(), dataFrameOld.getTotalDropsOut()));
}
unsigned long long Device::fixOverflow(unsigned long long value, unsigned long long valueOld)
{
if(value > 0xffffffffULL)
return value;
if(value < (valueOld & 0xffffffffULL))
{
// overflow happend (again)
valueOld += 0x100000000ULL;
}
// no overflow happend, keep previous ones
valueOld &= 0xffffffff00000000ULL;
value |= valueOld;
return value;
}
void Device::printTrafficValue(Window& window, int x, int y, const std::string& description, unsigned long long value)
{
Statistics::DataUnit trafficFormat = (Statistics::DataUnit) ((int) SettingStore::get("TrafficFormat"));
string unitString = Statistics::getUnitString(trafficFormat, value);
float unitFactor = Statistics::getUnitFactor(trafficFormat, value);
window.print(x, y) << fixed << setprecision(2) << description << ": " << ((float) value / unitFactor) << " " << unitString << "/s" << endl;
}
void Device::printDataValue(Window& window, int x, int y, const std::string& description, unsigned long long value)
{
Statistics::DataUnit dataFormat = (Statistics::DataUnit) ((int) SettingStore::get("DataFormat"));
string unitString = Statistics::getUnitString(dataFormat, value);
float unitFactor = Statistics::getUnitFactor(dataFormat, value);
window.print(x, y) << fixed << setprecision(2) << description << ": " << ((float) value / unitFactor) << " " << unitString << endl;
}
void Device::printStatisticsIn(Window& window, int x, int y)
{
// print current traffic
printTrafficValue(window, x, y, "Curr", m_deviceStatistics.getDataInPerSecond());
// print average traffic
printTrafficValue(window, x, y + 1, "Avg", m_deviceStatistics.getDataInAverage());
// print min traffic since nload start
printTrafficValue(window, x, y + 2, "Min", m_deviceStatistics.getDataInMin());
// print max traffic since nload start
printTrafficValue(window, x, y + 3, "Max", m_deviceStatistics.getDataInMax());
// print total traffic since last system reboot
printDataValue(window, x, y + 4, "Ttl", m_deviceStatistics.getDataInTotal());
}
void Device::printStatisticsOut(Window& window, int x, int y)
{
// print current traffic
printTrafficValue(window, x, y, "Curr", m_deviceStatistics.getDataOutPerSecond());
// print average traffic
printTrafficValue(window, x, y + 1, "Avg", m_deviceStatistics.getDataOutAverage());
// print min traffic since nload start
printTrafficValue(window, x, y + 2, "Min", m_deviceStatistics.getDataOutMin());
// print max traffic since nload start
printTrafficValue(window, x, y + 3, "Max", m_deviceStatistics.getDataOutMax());
// print total traffic since last system reboot
printDataValue(window, x, y + 4, "Ttl", m_deviceStatistics.getDataOutTotal());
}