source: src-qt4/pc-mounttray/fsWatcher.cpp @ 5675b55

releng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 5675b55 was 5675b55, checked in by Ken Moore <ken@…>, 6 months ago

Make sure that linsysfs is skipped by the mount tray disk watcher, and also move the nullfs skip to the actual disk watcher as well.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1#include "fsWatcher.h"
2
3FSWatcher::FSWatcher() : QObject(){
4  //setup the timer
5  timer = new QTimer();
6  timer->setSingleShot(TRUE);
7  QObject::connect(timer, SIGNAL(timeout()), this, SLOT(checkFS()));
8}
9
10FSWatcher::~FSWatcher(){
11}
12
13void FSWatcher::start(int ms){ 
14    timer->stop();
15    timer->setInterval(ms); //max time between system checks
16    timer->start(); 
17    QTimer::singleShot(2000,this,SLOT(checkFS()) ); //make sure to perform a check when it starts up
18}
19
20void FSWatcher::stop(){
21  timer->stop();
22}
23
24QStringList FSWatcher::getFSmountpoints(){
25  //output line format: name::filesystem::totalspace::usedspace::percent
26  // -- sizes all in K
27  QStringList output; 
28  //ZFS Checks
29  QStringList zpools = runCMD("zpool list -o name");
30  if(zpools.length() > 1){ 
31    //Then there are ZFS pools available
32    for(int i=1; i<zpools.length(); i++){ //skip the header line
33      QStringList tmp = runCMD("zfs list -o available,used "+zpools[i]);
34      //second line contains the data
35      QString avail = tmp[1].section(" ",0,0,QString::SectionSkipEmpty);
36      QString used = tmp[1].section(" ",1,1,QString::SectionSkipEmpty);
37      double iUsed = floor(displayToDouble(used));
38      double iTotal = floor(displayToDouble(avail)) + iUsed;
39      int percent = calculatePercentage(iUsed, iTotal);
40      //qDebug() << "Percent calc: tot:"<<iTotal<<"used"<<iUsed<<"percent"<<percent;
41      //format the output string and add it in
42      output << zpools[i]+"::zfs::"+QString::number(iTotal)+"::"+QString::number(iUsed)+"::"+QString::number(percent);
43    }
44  }
45  //Now get all the rest of the mounted filesystems
46  QStringList dfout = runCMD("df -h -T");
47  //Format: name, filesystem, size, used, available, percent, mountpoint
48  for(int i=1; i<dfout.length(); i++){
49    //ignore certain filesystems
50    if(dfout[i].startsWith("devfs")){}
51    else if(dfout[i].startsWith("procfs")){}
52    else if(dfout[i].startsWith("linprocfs")){}
53    else if(dfout[i].startsWith("linsysfs")){}
54    else{
55      //Now parse out the info 
56      dfout[i].replace("\t"," ");
57      QString fs = dfout[i].section("  ",1,1,QString::SectionSkipEmpty).simplified();
58      if(fs != "zfs" && fs!="cd9660" && fs!="nullfs"){  //ignore zfs filesystems (already taken care of)
59        QString name = dfout[i].section("  ",6,6,QString::SectionSkipEmpty).simplified();
60        QString total = dfout[i].section("  ",2,2,QString::SectionSkipEmpty).simplified();
61        QString used = dfout[i].section("  ",3,3,QString::SectionSkipEmpty).simplified();
62        //Calculate the percent
63        double iUsed = displayToDouble(used);
64        double iTotal = displayToDouble(total);
65        int percent = calculatePercentage(iUsed, iTotal);
66        //qDebug() << "df Item:" << dfout[i];
67        //qDebug() << " - Detected:" << name << fs << iTotal << iUsed << percent;
68        //format the output string and add it in
69        output << name+"::"+fs+"::"+QString::number(iTotal)+"::"+QString::number(iUsed)+"::"+QString::number(percent);
70      }
71    }
72  }
73  //Return the results
74  //qDebug() << "FS output:" << output;
75  return output;
76 
77}
78
79int FSWatcher::displayToDouble(QString entry){
80  //split the number from the size label
81  //qDebug() << "Display to Int conversion:" << entry;
82  QString units = entry.right(1); //last character
83  entry.chop(1); //remove the unit
84  double num = entry.toDouble();
85  //qDebug() << "initial number:" << num << "units:" << units;
86  QStringList unitL; unitL << "K" << "M" << "G" << "T" << "P" << "E" << "Z" << "Y";
87  bool ok = false;
88  for(int i=0; i< unitL.length(); i++){
89    if(units == unitL[i]){ num = num*pow(1024.0,i); ok = true; break;}
90  }
91  if(!ok){num=0; }
92  //qDebug() << "number:" << num;
93  return num;
94}
95
96QString FSWatcher::doubleToDisplay(double K){
97  QString num;
98  //qDebug() << "Int to Display:" << K;
99  double kdb = K; //using pure integers causes errors with large numbers
100  QStringList units; units << "K" << "M" << "G" << "T" << "P" << "E" << "Z" << "Y";
101  int i=0;
102  while( (kdb > 1000) && (i < 8) ){
103    kdb = kdb/1024;
104    i++;
105  }
106  if(i<8){
107    num = QString::number( int((kdb*100))/100.0) + units[i];
108  }else{
109    num = "??";
110  }
111  //qDebug() << "Display:" << num;
112  return num;
113         
114}
115
116//====== Public Slot =======
117void FSWatcher::checkFS(){
118  QStringList devList = getFSmountpoints();
119  QStringList badDevs;
120  for(int i=0; i<devList.length(); i++){
121    int percent = devList[i].section("::",4,4).toInt();
122    if(percent > 90){
123      //Device greater than 90% full, warn the user
124      badDevs << devList[i].section("::",0,0); //list the mountpoint
125      qDebug() << "WARNING: Device almost full:" << devList[i].section("::",0,0)+": "+QString::number(percent)+"% full: Time: "+QTime::currentTime().toString();
126    }
127  }
128  if(!badDevs.isEmpty()){
129    //check to make sure these are new "bad" devices
130    bool newFound = FALSE;
131    for(int i=0; i<badDevs.length(); i++){
132      if( oldBadDevs.indexOf(badDevs[i]) == -1){ newFound = TRUE; }         
133    }
134    if(newFound){
135      QString title = tr("Disk(s) Almost Full");
136      QString message = badDevs.join(", ");
137      emit FSWarning(title,message);
138    }
139  }
140  //Save the current badDevs as the old list
141  oldBadDevs = badDevs;
142  //Reset the timer for the next time this function is to be called
143  timer->start(); //reset the timer again
144}
145
146//===== Calculate Percentages =====
147int FSWatcher::calculatePercentage(double used, double total){
148  double U = used;
149  double T = total;
150  double result = (U/T)*100.0;
151  return result; //will remove decimel places;
152}
153//====== Run System Command Function ======
154QStringList FSWatcher::runCMD(QString command){
155   QProcess p;
156   QString outstr;
157   //Make sure we use the system environment to properly read system variables, etc.
158   QProcessEnvironment penv = QProcessEnvironment::systemEnvironment();
159   penv.insert("BLOCKSIZE","K"); //make sure we use a 1KB block size
160   p.setProcessEnvironment(penv);
161   //Merge the output channels to retrieve all output possible
162   p.setProcessChannelMode(QProcess::MergedChannels);   
163   p.start(command);
164   while(p.state()==QProcess::Starting || p.state() == QProcess::Running){
165     p.waitForFinished(200);
166     QCoreApplication::processEvents();
167   }
168   QString tmp = p.readAllStandardOutput();
169   outstr.append(tmp);
170   if(outstr.endsWith("\n")){outstr.chop(1);} //remove the newline at the end
171   QStringList out = outstr.split("\n");
172   return out;
173}
Note: See TracBrowser for help on using the repository browser.