File indexing completed on 2024-05-05 05:34:26

0001 /*
0002     KSysGuard, the KDE System Guard
0003 
0004     SPDX-FileCopyrightText: 1999-2001 Chris Schlaeger <cs@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0007 
0008 */
0009 
0010 #include "ksgrd_debug.h"
0011 #include <QCoreApplication>
0012 #include <QDebug>
0013 #include <kconfiggroup.h>
0014 #include <klocalizedstring.h>
0015 
0016 #include "SensorShellAgent.h"
0017 #include "SensorSocketAgent.h"
0018 
0019 #include "SensorManager.h"
0020 
0021 using namespace KSGRD;
0022 
0023 SensorManager::MessageEvent::MessageEvent(const QString &message)
0024     : QEvent(QEvent::User)
0025     , mMessage(message)
0026 {
0027 }
0028 
0029 QString SensorManager::MessageEvent::message() const
0030 {
0031     return mMessage;
0032 }
0033 
0034 SensorManager *KSGRD::SensorMgr;
0035 
0036 SensorManager::SensorManager(QObject *parent)
0037     : QObject(parent)
0038 {
0039     retranslate();
0040 }
0041 int SensorManager::count() const
0042 {
0043     return mAgents.count();
0044 }
0045 void SensorManager::retranslate()
0046 {
0047     // Fill the sensor description dictionary.
0048     mDict.clear();
0049     mDict.insert(QStringLiteral("Delta"), i18n("Change"));
0050     mDict.insert(QStringLiteral("Rate"), i18n("Rate"));
0051 
0052     mDict.insert(QStringLiteral("cpu"), i18n("CPU Load"));
0053     mDict.insert(QStringLiteral("idle"), i18n("Idling"));
0054     mDict.insert(QStringLiteral("nice"), i18n("Nice Load"));
0055     mDict.insert(QStringLiteral("user"), i18n("User Load"));
0056     mDict.insert(QStringLiteral("sys"), i18nc("@item sensor description", "System Load"));
0057     mDict.insert(QStringLiteral("wait"), i18n("Waiting"));
0058     mDict.insert(QStringLiteral("intr"), i18n("Interrupt Load"));
0059     mDict.insert(QStringLiteral("TotalLoad"), i18n("Total Load"));
0060 
0061     mDict.insert(QStringLiteral("mem"), i18n("Memory"));
0062     mDict.insert(QStringLiteral("physical"), i18n("Physical Memory"));
0063     mDict.insert(QStringLiteral("total"), i18n("Total Memory"));
0064     mDict.insert(QStringLiteral("swap"), i18n("Swap Memory"));
0065     mDict.insert(QStringLiteral("cached"), i18n("Cached Memory"));
0066     mDict.insert(QStringLiteral("buf"), i18n("Buffered Memory"));
0067     mDict.insert(QStringLiteral("used"), i18n("Used Memory"));
0068     mDict.insert(QStringLiteral("application"), i18n("Application Memory"));
0069     mDict.insert(QStringLiteral("allocated"), i18n("Allocated Memory"));
0070     mDict.insert(QStringLiteral("free"), i18n("Free Memory"));
0071     mDict.insert(QStringLiteral("available"), i18n("Available Memory"));
0072     mDict.insert(QStringLiteral("active"), i18n("Active Memory"));
0073     mDict.insert(QStringLiteral("inactive"), i18n("Inactive Memory"));
0074     mDict.insert(QStringLiteral("wired"), i18n("Wired Memory"));
0075     mDict.insert(QStringLiteral("execpages"), i18n("Exec Pages"));
0076     mDict.insert(QStringLiteral("filepages"), i18n("File Pages"));
0077 
0078     /* Processes */
0079     mDict.insert(QStringLiteral("processes"), i18n("Processes"));
0080     mDict.insert(QStringLiteral("ps"), i18n("Process Controller"));
0081     mDict.insert(QStringLiteral("lastpid"), i18n("Last Process ID"));
0082     mDict.insert(QStringLiteral("procspawn"), i18n("Process Spawn Count"));
0083     mDict.insert(QStringLiteral("pscount"), i18n("Process Count"));
0084     mDict.insert(QStringLiteral("psidle"), i18n("Idle Processes Count"));
0085     mDict.insert(QStringLiteral("psrun"), i18n("Running Processes Count"));
0086     mDict.insert(QStringLiteral("pssleep"), i18n("Sleeping Processes Count"));
0087     mDict.insert(QStringLiteral("psstop"), i18n("Stopped Processes Count"));
0088     mDict.insert(QStringLiteral("pszombie"), i18n("Zombie Processes Count"));
0089     mDict.insert(QStringLiteral("pswait"), i18n("Waiting Processes Count"));
0090     mDict.insert(QStringLiteral("pslock"), i18n("Locked Processes Count"));
0091 
0092     mDict.insert(QStringLiteral("disk"), i18n("Disk Throughput"));
0093     mDict.insert(QStringLiteral("load"), i18nc("CPU Load", "Load"));
0094     mDict.insert(QStringLiteral("totalio"), i18n("Total Accesses"));
0095     mDict.insert(QStringLiteral("rio"), i18n("Read Accesses"));
0096     mDict.insert(QStringLiteral("wio"), i18n("Write Accesses"));
0097     mDict.insert(QStringLiteral("rblk"), i18n("Read Data"));
0098     mDict.insert(QStringLiteral("wblk"), i18n("Written Data"));
0099     mDict.insert(QStringLiteral("rtim"), i18n("Milliseconds spent reading"));
0100     mDict.insert(QStringLiteral("wtim"), i18n("Milliseconds spent writing"));
0101     mDict.insert(QStringLiteral("ioqueue"), i18n("I/Os currently in progress"));
0102     mDict.insert(QStringLiteral("pageIn"), i18n("Pages In"));
0103     mDict.insert(QStringLiteral("pageOut"), i18n("Pages Out"));
0104     mDict.insert(QStringLiteral("context"), i18n("Context Switches"));
0105     mDict.insert(QStringLiteral("trap"), i18n("Traps"));
0106     mDict.insert(QStringLiteral("syscall"), i18n("System Calls"));
0107     mDict.insert(QStringLiteral("network"), i18n("Network"));
0108     mDict.insert(QStringLiteral("interfaces"), i18n("Interfaces"));
0109     mDict.insert(QStringLiteral("receiver"), i18n("Receiver"));
0110     mDict.insert(QStringLiteral("transmitter"), i18n("Transmitter"));
0111 
0112     mDict.insert(QStringLiteral("data"), i18n("Data Rate"));
0113     mDict.insert(QStringLiteral("compressed"), i18n("Compressed Packets Rate"));
0114     mDict.insert(QStringLiteral("drops"), i18n("Dropped Packets Rate"));
0115     mDict.insert(QStringLiteral("errors"), i18n("Error Rate"));
0116     mDict.insert(QStringLiteral("fifo"), i18n("FIFO Overruns Rate"));
0117     mDict.insert(QStringLiteral("frame"), i18n("Frame Error Rate"));
0118     mDict.insert(QStringLiteral("multicast"), i18n("Multicast Packet Rate"));
0119     mDict.insert(QStringLiteral("packets"), i18n("Packet Rate"));
0120     mDict.insert(QStringLiteral("carrier"), i18nc("@item sensor description ('carrier' is a type of network signal)", "Carrier Loss Rate"));
0121     mDict.insert(QStringLiteral("collisions"), i18n("Collisions"));
0122 
0123     mDict.insert(QStringLiteral("dataTotal"), i18n("Data"));
0124     mDict.insert(QStringLiteral("compressedTotal"), i18n("Compressed Packets"));
0125     mDict.insert(QStringLiteral("dropsTotal"), i18n("Dropped Packets"));
0126     mDict.insert(QStringLiteral("errorsTotal"), i18n("Errors"));
0127     mDict.insert(QStringLiteral("fifoTotal"), i18n("FIFO Overruns"));
0128     mDict.insert(QStringLiteral("frameTotal"), i18n("Frame Errors"));
0129     mDict.insert(QStringLiteral("multicastTotal"), i18n("Multicast Packets"));
0130     mDict.insert(QStringLiteral("packetsTotal"), i18n("Packets"));
0131     mDict.insert(QStringLiteral("carrierTotal"), i18nc("@item sensor description ('carrier' is a type of network signal)", "Carrier Losses"));
0132     mDict.insert(QStringLiteral("collisionsTotal"), i18n("Collisions"));
0133 
0134     /* Hardware monitors */
0135     mDict.insert(QStringLiteral("sockets"), i18n("Sockets"));
0136     mDict.insert(QStringLiteral("count"), i18n("Total Number"));
0137     mDict.insert(QStringLiteral("list"), i18n("Table"));
0138     mDict.insert(QStringLiteral("apm"), i18n("Advanced Power Management"));
0139     mDict.insert(QStringLiteral("acpi"), i18n("ACPI"));
0140     mDict.insert(QStringLiteral("Cooling_Device"), i18n("Cooling Device"));
0141     mDict.insert(QStringLiteral("Current_State"), i18n("Current State"));
0142     mDict.insert(QStringLiteral("thermal_zone"), i18n("Thermal Zone"));
0143     mDict.insert(QStringLiteral("Thermal_Zone"), i18n("Thermal Zone"));
0144     mDict.insert(QStringLiteral("temperature"), i18n("Temperature"));
0145     mDict.insert(QStringLiteral("Temperature"), i18n("Temperature"));
0146     mDict.insert(QStringLiteral("AverageTemperature"), i18n("Average CPU Temperature"));
0147     mDict.insert(QStringLiteral("fan"), i18n("Fan"));
0148     mDict.insert(QStringLiteral("state"), i18n("State"));
0149     mDict.insert(QStringLiteral("battery"), i18n("Battery"));
0150     mDict.insert(QStringLiteral("batterycapacity"), i18n("Battery Capacity"));
0151     mDict.insert(QStringLiteral("batterycharge"), i18n("Battery Charge"));
0152     mDict.insert(QStringLiteral("batteryusage"), i18n("Battery Usage"));
0153     mDict.insert(QStringLiteral("batteryvoltage"), i18n("Battery Voltage"));
0154     mDict.insert(QStringLiteral("batteryrate"), i18n("Battery Discharge Rate"));
0155     mDict.insert(QStringLiteral("remainingtime"), i18n("Remaining Time"));
0156     mDict.insert(QStringLiteral("interrupts"), i18n("Interrupts"));
0157     mDict.insert(QStringLiteral("loadavg1"), i18n("Load Average (1 min)"));
0158     mDict.insert(QStringLiteral("loadavg5"), i18n("Load Average (5 min)"));
0159     mDict.insert(QStringLiteral("loadavg15"), i18n("Load Average (15 min)"));
0160     mDict.insert(QStringLiteral("clock"), i18n("Clock Frequency"));
0161     mDict.insert(QStringLiteral("AverageClock"), i18n("Average Clock Frequency"));
0162     mDict.insert(QStringLiteral("lmsensors"), i18n("Hardware Sensors"));
0163     mDict.insert(QStringLiteral("partitions"), i18n("Partition Usage"));
0164     mDict.insert(QStringLiteral("usedspace"), i18n("Used Space"));
0165     mDict.insert(QStringLiteral("freespace"), i18n("Free Space"));
0166     mDict.insert(QStringLiteral("filllevel"), i18n("Fill Level"));
0167     mDict.insert(QStringLiteral("usedinode"), i18n("Used Inodes"));
0168     mDict.insert(QStringLiteral("freeinode"), i18n("Free Inodes"));
0169     mDict.insert(QStringLiteral("inodelevel"), i18n("Inode Level"));
0170     mDict.insert(QStringLiteral("system"), i18n("System"));
0171     mDict.insert(QStringLiteral("uptime"), i18n("Uptime"));
0172     mDict.insert(QStringLiteral("SoftRaid"), i18n("Linux Soft Raid (md)"));
0173     mDict.insert(QStringLiteral("processors"), i18n("Processors"));
0174     mDict.insert(QStringLiteral("cores"), i18n("Cores"));
0175     mDict.insert(QStringLiteral("NumBlocks"), i18n("Number of Blocks"));
0176     mDict.insert(QStringLiteral("TotalDevices"), i18n("Total Number of Devices"));
0177     mDict.insert(QStringLiteral("FailedDevices"), i18n("Failed Devices"));
0178     mDict.insert(QStringLiteral("SpareDevices"), i18n("Spare Devices"));
0179     mDict.insert(QStringLiteral("NumRaidDevices"), i18n("Number of Raid Devices"));
0180     mDict.insert(QStringLiteral("WorkingDevices"), i18n("Working Devices"));
0181     mDict.insert(QStringLiteral("ActiveDevices"), i18n("Active Devices"));
0182     mDict.insert(QStringLiteral("DeviceNumber"), i18n("Number of Devices"));
0183     mDict.insert(QStringLiteral("ResyncingPercent"), i18n("Resyncing Percent"));
0184     mDict.insert(QStringLiteral("DiskInfo"), i18n("Disk Information"));
0185     mDict.insert(QStringLiteral("CPUTIN"), i18n("CPU Temperature"));
0186     mDict.insert(QStringLiteral("SYSTIN"), i18n("Motherboard Temperature"));
0187     mDict.insert(QStringLiteral("AUXTIN"), i18n("Power Supply Temperature"));
0188 
0189     mDict.insert(QStringLiteral("__root__"), i18n("Filesystem Root"));
0190 
0191     for (int i = 0; i < 5; i++) {
0192         mDict.insert(QLatin1String("AUXTIN") + QString::number(i), i18n("Extra Temperature Sensor %1", i + 1));
0193     }
0194 
0195     for (int i = 0; i < 3; i++) {
0196         mDict.insert(QLatin1String("PECI Agent ") + QString::number(i), i18n("PECI Temperature Sensor %1", i + 1));
0197         mDict.insert(QLatin1String("PECI Agent %1 Calibration").arg(QString::number(i)), i18n("PECI Temperature Calibration %1", i + 1));
0198     }
0199 
0200     for (int i = 0; i < 32; i++) {
0201         mDict.insert(QLatin1String("cpu") + QString::number(i), i18n("CPU %1", i + 1));
0202         mDict.insert(QLatin1String("disk") + QString::number(i), i18n("Disk %1", i + 1));
0203     }
0204 
0205     for (int i = 1; i < 10; i++) {
0206         mDict.insert(QLatin1String("batt") + QString::number(i), i18n("Battery %1", i));
0207         mDict.insert(QLatin1String("fan") + QString::number(i), i18n("Fan %1", i));
0208         mDict.insert(QLatin1String("temp") + QString::number(i), i18n("Temperature %1", i));
0209     }
0210 
0211     mDict.insert(QStringLiteral("int00"), i18n("Total"));
0212     mDict.insert(QStringLiteral("softint"), i18n("Software Interrupts"));
0213     mDict.insert(QStringLiteral("hardint"), i18n("Hardware Interrupts"));
0214 
0215     QString num;
0216     for (int i = 1; i < 25; i++) {
0217         num = QString::asprintf("%.2d", i);
0218         mDict.insert(QLatin1String("int") + num, ki18n("Int %1").subs(i - 1, 3).toString());
0219         num = QString::asprintf("%.3d", i + 255);
0220         mDict.insert(QLatin1String("int") + num, ki18n("Int %1").subs(i + 255, 4).toString());
0221     }
0222 
0223     mDict.insert(QStringLiteral("quality"), i18n("Link Quality"));
0224     mDict.insert(QStringLiteral("signal"), i18n("Signal Level"));
0225     mDict.insert(QStringLiteral("noise"), i18n("Noise Level"));
0226     mDict.insert(QStringLiteral("nwid"), i18n("Rx Invalid Nwid Packets"));
0227     mDict.insert(QStringLiteral("nwidTotal"), i18n("Total Rx Invalid Nwid Packets"));
0228     mDict.insert(QStringLiteral("crypt"), i18n("Rx Invalid Crypt Packets"));
0229     mDict.insert(QStringLiteral("cryptTotal"), i18n("Total Rx Invalid Crypt Packets"));
0230     mDict.insert(QStringLiteral("frag"), i18n("Rx Invalid Frag Packets"));
0231     mDict.insert(QStringLiteral("fragTotal"), i18n("Total Rx Invalid Frag Packets"));
0232     mDict.insert(QStringLiteral("retry"), i18n("Tx Excessive Retries Packets"));
0233     mDict.insert(QStringLiteral("retryTotal"), i18n("Total Tx Excessive Retries Packets"));
0234     mDict.insert(QStringLiteral("misc"), i18n("Invalid Misc Packets"));
0235     mDict.insert(QStringLiteral("miscTotal"), i18n("Total Invalid Misc Packets"));
0236     mDict.insert(QStringLiteral("beacon"), i18n("Missed Beacons"));
0237     mDict.insert(QStringLiteral("beaconTotal"), i18n("Total Missed Beacons"));
0238 
0239     mDict.insert(QStringLiteral("logfiles"), i18n("Log Files"));
0240 
0241     // TODO: translated descriptions not yet implemented.
0242     mUnits.clear();
0243     mUnits.insert(QStringLiteral("1/s"), i18nc("the unit 1 per second", "1/s"));
0244     mUnits.insert(QStringLiteral("kBytes"), i18n("kBytes"));
0245     mUnits.insert(QStringLiteral("min"), i18nc("the unit minutes", "min"));
0246     mUnits.insert(QStringLiteral("MHz"), i18nc("the frequency unit", "MHz"));
0247     mUnits.insert(QStringLiteral("%"), i18nc("a percentage", "%"));
0248     mUnits.insert(QStringLiteral("mA"), i18nc("the unit milliamperes", "mA"));
0249     mUnits.insert(QStringLiteral("mAh"), i18nc("the unit milliampere hours", "mAh"));
0250     mUnits.insert(QStringLiteral("mW"), i18nc("the unit milliwatts", "mW"));
0251     mUnits.insert(QStringLiteral("mWh"), i18nc("the unit milliwatt hours", "mWh"));
0252     mUnits.insert(QStringLiteral("mV"), i18nc("the unit millivolts", "mV"));
0253 
0254     mTypes.clear();
0255     mTypes.insert(QStringLiteral("integer"), i18n("Integer Value"));
0256     mTypes.insert(QStringLiteral("float"), i18n("Floating Point Value"));
0257     mTypes.insert(QStringLiteral("table"), i18n("Process Controller"));
0258     mTypes.insert(QStringLiteral("listview"), i18n("Table"));
0259     mTypes.insert(QStringLiteral("logfile"), i18n("Log File"));
0260 
0261     mBroadcaster = nullptr;
0262 }
0263 
0264 SensorManager::~SensorManager()
0265 {
0266 }
0267 
0268 bool SensorManager::engage(const QString &hostName, const QString &shell, const QString &command, int port)
0269 {
0270     if (!mAgents.contains(hostName)) {
0271         SensorAgent *agent = nullptr;
0272 
0273         if (port == -1) {
0274             agent = new SensorShellAgent(this);
0275         } else {
0276             agent = new SensorSocketAgent(this);
0277         }
0278 
0279         if (!agent->start(hostName.toLatin1(), shell, command, port)) {
0280             delete agent;
0281             return false;
0282         }
0283 
0284         mAgents.insert(hostName, agent);
0285         connect(agent, &SensorAgent::reconfigure, this, &SensorManager::reconfigure);
0286 
0287         Q_EMIT hostAdded(agent, hostName);
0288         return true;
0289     }
0290 
0291     return false;
0292 }
0293 
0294 bool SensorManager::disengage(SensorAgent *agent)
0295 {
0296     if (!agent) {
0297         return false;
0298     }
0299     const QString key = mAgents.key(const_cast<SensorAgent *>(agent));
0300     return disengage(key);
0301 }
0302 
0303 bool SensorManager::isConnected(const QString &hostName)
0304 {
0305     return mAgents.contains(hostName);
0306 }
0307 
0308 bool SensorManager::disengage(const QString &hostName)
0309 {
0310     if (mAgents.contains(hostName)) {
0311         mAgents.take(hostName)->deleteLater();
0312 
0313         Q_EMIT hostConnectionLost(hostName);
0314         return true;
0315     }
0316 
0317     return false;
0318 }
0319 
0320 bool SensorManager::resynchronize(const QString &hostName)
0321 {
0322     const SensorAgent *agent = mAgents.value(hostName);
0323 
0324     if (!agent) {
0325         return false;
0326     }
0327 
0328     QString shell, command;
0329     int port;
0330     hostInfo(hostName, shell, command, port);
0331 
0332     mAgents.remove(hostName);
0333 
0334     qCDebug(LIBKSYSGUARD_KSGRD) << "Re-synchronizing connection to " << hostName;
0335 
0336     return engage(hostName, shell, command);
0337 }
0338 
0339 void SensorManager::notify(const QString &msg) const
0340 {
0341     /* This function relays text messages to the toplevel widget that
0342      * displays the message in a pop-up box. It must be used for objects
0343      * that might have been deleted before the pop-up box is closed. */
0344     if (mBroadcaster) {
0345         MessageEvent *event = new MessageEvent(msg);
0346         qApp->postEvent(mBroadcaster, event);
0347     }
0348 }
0349 
0350 void SensorManager::setBroadcaster(QObject *wdg)
0351 {
0352     mBroadcaster = wdg;
0353 }
0354 
0355 void SensorManager::reconfigure(const SensorAgent *)
0356 {
0357     Q_EMIT update();
0358 }
0359 
0360 bool SensorManager::sendRequest(const QString &hostName, const QString &req, SensorClient *client, int id)
0361 {
0362     SensorAgent *agent = mAgents.value(hostName);
0363     if (!agent && hostName == QLatin1String("localhost")) {
0364         // we should always be able to reconnect to localhost
0365         engage(QStringLiteral("localhost"), QLatin1String(""), QStringLiteral("ksysguardd"), -1);
0366         agent = mAgents.value(hostName);
0367     }
0368     if (agent) {
0369         agent->sendRequest(req, client, id);
0370         return true;
0371     }
0372 
0373     return false;
0374 }
0375 
0376 const QString SensorManager::hostName(const SensorAgent *agent) const
0377 {
0378     return mAgents.key(const_cast<SensorAgent *>(agent));
0379 }
0380 
0381 bool SensorManager::hostInfo(const QString &hostName, QString &shell, QString &command, int &port)
0382 {
0383     const SensorAgent *agent = mAgents.value(hostName);
0384     if (agent) {
0385         agent->hostInfo(shell, command, port);
0386         return true;
0387     }
0388 
0389     return false;
0390 }
0391 
0392 QString SensorManager::translateUnit(const QString &unit) const
0393 {
0394     if (!unit.isEmpty() && mUnits.contains(unit)) {
0395         return mUnits[unit];
0396     } else {
0397         return unit;
0398     }
0399 }
0400 
0401 QString SensorManager::translateSensorPath(const QString &path) const
0402 {
0403     if (!path.isEmpty() && mDict.contains(path)) {
0404         return mDict[path];
0405     } else {
0406         return path;
0407     }
0408 }
0409 
0410 QString SensorManager::translateSensorType(const QString &type) const
0411 {
0412     if (!type.isEmpty() && mTypes.contains(type)) {
0413         return mTypes[type];
0414     } else {
0415         return type;
0416     }
0417 }
0418 
0419 QString SensorManager::translateSensor(const QString &sensor) const
0420 {
0421     QString out;
0422     int start = 0, end = 0;
0423     for (;;) {
0424         end = sensor.indexOf(QLatin1Char('/'), start);
0425         if (end > 0) {
0426             out += translateSensorPath(sensor.mid(start, end - start)) + QLatin1Char('/');
0427         } else {
0428             out += translateSensorPath(sensor.right(sensor.length() - start));
0429             break;
0430         }
0431         start = end + 1;
0432     }
0433 
0434     return out;
0435 }
0436 
0437 void SensorManager::readProperties(const KConfigGroup &cfg)
0438 {
0439     mHostList = cfg.readEntry("HostList", QStringList());
0440     mCommandList = cfg.readEntry("CommandList", QStringList());
0441 }
0442 
0443 void SensorManager::saveProperties(KConfigGroup &cfg)
0444 {
0445     cfg.writeEntry("HostList", mHostList);
0446     cfg.writeEntry("CommandList", mCommandList);
0447 }
0448 
0449 void SensorManager::disconnectClient(SensorClient *client)
0450 {
0451     QHashIterator<QString, SensorAgent *> it(mAgents);
0452 
0453     while (it.hasNext()) {
0454         it.next().value()->disconnectClient(client);
0455     }
0456 }