| /*************************************************************************** |
| 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> |
| #include <sstream> |
| |
| 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 ip4 = m_dataFrameOld.getIpV4(); |
| if(!ip4.empty()) |
| window.print() << "Device " << m_devReader.getDeviceName() << " [" << ip4 << "] (" << (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 |
| { |
| unsigned long long maxDeflectionIn = (unsigned long long) SettingStore::get("BarMaxIn") * 1024 / 8; |
| unsigned long long maxDeflectionOut = (unsigned long long) SettingStore::get("BarMaxOut") * 1024 / 8; |
| |
| if(maxDeflectionIn < 1) |
| maxDeflectionIn = roundUpMaxDeflection(m_deviceGraphIn.calcMaxDeflection()); |
| if(maxDeflectionOut < 1) |
| maxDeflectionOut = roundUpMaxDeflection(m_deviceGraphOut.calcMaxDeflection()); |
| |
| // incoming traffic |
| window.print() << "Incoming (100% @ " << formatTrafficValue(maxDeflectionIn, 0) << "):" << endl; |
| |
| m_deviceGraphIn.setNumOfBars(window.getWidth() * 2 / 3); |
| m_deviceGraphIn.setHeightOfBars((window.getHeight() - window.getY() - 1) / 2); |
| m_deviceGraphIn.setMaxDeflection(maxDeflectionIn); |
| m_deviceGraphIn.print(window, 0, window.getY()); |
| |
| printStatisticsIn(window, window.getWidth() * 2 / 3 + 2, window.getY() - 5); |
| |
| // outgoing traffic |
| window.print() << "Outgoing (100% @ " << formatTrafficValue(maxDeflectionOut, 0) << "):" << endl; |
| |
| m_deviceGraphOut.setNumOfBars(window.getWidth() * 2 / 3); |
| m_deviceGraphOut.setHeightOfBars(window.getHeight() - window.getY()); |
| m_deviceGraphOut.setMaxDeflection(maxDeflectionOut); |
| m_deviceGraphOut.print(window, 0, window.getY()); |
| |
| printStatisticsOut(window, window.getWidth() * 2 / 3 + 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; |
| } |
| |
| unsigned long long Device::roundUpMaxDeflection(unsigned long long value) |
| { |
| unsigned long long rounded = 2 * 1024; // 2 kByte/s |
| while (rounded < value) |
| { |
| if((rounded << 1) < rounded) |
| return value; |
| |
| rounded <<= 1; |
| } |
| |
| return rounded; |
| } |
| |
| void Device::printTrafficValue(Window& window, int x, int y, const std::string& description, unsigned long long value) |
| { |
| window.print(x, y) << description << ": " << formatTrafficValue(value, 2) << endl; |
| } |
| |
| void Device::printDataValue(Window& window, int x, int y, const std::string& description, unsigned long long value) |
| { |
| window.print(x, y) << description << ": " << formatDataValue(value, 2) << endl; |
| } |
| |
| string Device::formatTrafficValue(unsigned long value, int precision) |
| { |
| Statistics::dataUnit trafficFormat = (Statistics::dataUnit) ((int) SettingStore::get("TrafficFormat")); |
| |
| string unitString = Statistics::getUnitString(trafficFormat, value); |
| float unitFactor = Statistics::getUnitFactor(trafficFormat, value); |
| |
| ostringstream oss; |
| oss << fixed << setprecision(precision) << ((float) value / unitFactor) << " " << unitString << "/s"; |
| |
| return oss.str(); |
| } |
| |
| string Device::formatDataValue(unsigned long long value, int precision) |
| { |
| Statistics::dataUnit dataFormat = (Statistics::dataUnit) ((int) SettingStore::get("DataFormat")); |
| |
| string unitString = Statistics::getUnitString(dataFormat, value); |
| float unitFactor = Statistics::getUnitFactor(dataFormat, value); |
| |
| ostringstream oss; |
| oss << fixed << setprecision(precision) << ((float) value / unitFactor) << " " << unitString << endl; |
| |
| return oss.str(); |
| } |
| |
| 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()); |
| } |
| |