source: src-qt4/pc-softwaremanager/processManager.cpp @ 52fa6eb

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 52fa6eb was 52fa6eb, checked in by Ken Moore <ken@…>, 11 months ago

Fix a bug with the level of error reporting in the remove channel. Now it should only have a high level of error checking it is running the pbi_delete command. Other commands (like the occasional mime type removal) should no longer cause an error when removing a PBI.

  • Property mode set to 100644
File size: 11.4 KB
Line 
1/***************************************************************************
2 *   Copyright (C) 2011 - iXsystems                                       *
3 *   kris@pcbsd.org  *
4 *   tim@pcbsd.org   *
5 *   ken@pcbsd.org   *
6 *                                                                         *
7 *   Permission is hereby granted, free of charge, to any person obtaining *
8 *   a copy of this software and associated documentation files (the       *
9 *   "Software"), to deal in the Software without restriction, including   *
10 *   without limitation the rights to use, copy, modify, merge, publish,   *
11 *   distribute, sublicense, and/or sell copies of the Software, and to    *
12 *   permit persons to whom the Software is furnished to do so, subject to *
13 *   the following conditions:                                             *
14 *                                                                         *
15 *   The above copyright notice and this permission notice shall be        *
16 *   included in all copies or substantial portions of the Software.       *
17 *                                                                         *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
19 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
20 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
22 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
23 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
24 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
25 ***************************************************************************/
26 #include "processManager.h"
27
28ProcessManager::ProcessManager(){
29  //Get the system environment for all the processes
30  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
31    env.insert("PBI_FETCH_PARSING","YES"); //For readable download notifications
32    //Initialize the UPDATE Process
33    upProc = new QProcess; upProc->setProcessEnvironment(env);
34    upProc->setProcessChannelMode(QProcess::MergedChannels);
35    connect(upProc, SIGNAL(readyRead()),this,SLOT(slotUpProcMessage()) );
36    connect(upProc, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotUpProcFinished()) );
37    //Initialize the REMOVE Process
38    remProc = new QProcess; remProc->setProcessEnvironment(env);
39    remProc->setProcessChannelMode(QProcess::MergedChannels);
40    connect(remProc, SIGNAL(readyRead()),this,SLOT(slotRemProcMessage()) );
41    connect(remProc, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotRemProcFinished()) );
42    //Initialize the DOWNLOAD Process
43    dlProc = new QProcess; dlProc->setProcessEnvironment(env);
44    dlProc->setProcessChannelMode(QProcess::MergedChannels);
45    connect(dlProc, SIGNAL(readyRead()),this,SLOT(slotDlProcMessage()) );
46    connect(dlProc, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotDlProcFinished()) );
47    //Initialize the INSTALL Process
48    inProc = new QProcess; inProc->setProcessEnvironment(env);
49    inProc->setProcessChannelMode(QProcess::MergedChannels);
50    connect(inProc, SIGNAL(readyRead()),this,SLOT(slotInProcMessage()) );
51    connect(inProc, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotInProcFinished()) );
52    //Initialize the OTHER Process
53    otProc = new QProcess; otProc->setProcessEnvironment(env);
54    connect(otProc, SIGNAL(readyReadStandardOutput()),this,SLOT(slotOtProcMessage()) );
55    connect(otProc, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotOtProcFinished()) );
56}
57
58ProcessManager::~ProcessManager(){
59}
60
61void ProcessManager::goToDirectory(ProcessID ID, QString dir){
62  if( ID == UPDATE ){
63    upProc->setWorkingDirectory(dir);     
64  }else if( ID == REMOVE ){
65    remProc->setWorkingDirectory(dir);           
66  }else if( ID == DOWNLOAD ){
67    dlProc->setWorkingDirectory(dir);     
68  }else if( ID == INSTALL ){
69    inProc->setWorkingDirectory(dir);             
70  }else if( ID == OTHER ){
71    otProc->setWorkingDirectory(dir);             
72  }     
73}
74
75// =========================
76// ===== PUBLIC ACCESS =====
77// =========================
78void ProcessManager::startProcess(ProcessID ID, QString cmd){
79  if( ID == UPDATE ){
80    qDebug() << "Update Process Started:" << cmd;
81    upLog.clear(); //clear the log for action
82    upProc->start(cmd);   
83  }else if( ID == REMOVE ){
84    qDebug() << "Removal Process Started:" << cmd;
85    remLog.clear();
86    if( cmd.contains("pbi_delete") ){ remStrictErrChecking = true; }
87    else{ remStrictErrChecking=false; }
88    remProc->start(cmd);                 
89  }else if( ID == DOWNLOAD ){
90    qDebug() << "Download Process Started:" << cmd;
91    dlLog.clear();
92    dlProc->start(cmd);           
93  }else if( ID == INSTALL ){
94    qDebug() << "Install Process Started:" << cmd;
95    inLog.clear();
96    inProc->start(cmd);           
97  }else if( ID == OTHER ){
98    qDebug() << "Other Process Started:" << cmd;
99    otProc->start(cmd);           
100  }
101       
102}
103
104void ProcessManager::stopProcess(ProcessID ID){
105  if((ID == ALL) || (ID == UPDATE)){
106    upProc->terminate();         
107  }
108  if((ID == ALL) || (ID == REMOVE)){
109    remProc->terminate();         
110  }
111  if((ID == ALL) || (ID == DOWNLOAD)){
112    dlProc->terminate();         
113  }
114  if((ID == ALL) || (ID == INSTALL)){
115    inProc->terminate();         
116  }
117  if((ID == ALL) || (ID == OTHER)){
118    otProc->terminate();         
119  }     
120}
121
122QStringList ProcessManager::getProcessLog(ProcessID ID){
123  if( ID == UPDATE ){ return upLog; }
124  else if( ID == REMOVE ){ return remLog; }
125  else if( ID == DOWNLOAD ){ return dlLog; }
126  else if( ID == INSTALL ){ return inLog; }
127  else{ return QStringList(); }
128}
129
130// =========================
131// ===== PRIVATE SLOTS =====
132// =========================
133QString ProcessManager::parseDlLine(QString line){
134  /*DOWNLOAD NOTIFICATION CODES:
135  Download complete: "DLDONE"
136  Download running: "DLSTAT::<percent>::<total size>::<download speed>"
137        -- A value of "??" means that it is unknown
138  Download starting: "DLSTART"
139  */
140  QString out;
141  if( line.startsWith("FETCH:") ){ return "DLSTART"; }
142  else if( line == "FETCHDONE"){ return "DLDONE"; }
143  else if(!line.startsWith("SIZE:")){ return out; }
144  //qDebug() << "parse Download Line:" << line;
145  //Line format: SIZE:  <KB> DOWNLOADED:  <KB> SPEED:  <KB/s> KB/s
146  line = line.simplified();
147  line.replace("SIZE: ","");
148  line.replace("DOWNLOADED: ", "");
149  line.replace("SPEED: ","");
150  line.replace("KB/s","");
151  bool totok, curok, spdok;
152  double tot, cur, spd;
153  tot = line.section(" ",0,0).toDouble(&totok);
154  cur = line.section(" ",1,1).toDouble(&curok);
155  spd = line.section(" ",2,2).toDouble(&spdok);
156  //qDebug() << " - DownloadStats:" << tot << cur << spd;
157  if(totok && tot==0){totok=FALSE;}
158  if(curok && cur==0){curok=FALSE;}
159  if(spdok && spd==0){spdok=FALSE;}
160  //Now format the output string
161  QString stats;
162  out = "DLSTAT::";
163  //Get percent and totals
164  if(totok && curok){
165    bool totErr = (tot==cur); //catch for a display error where the cur is always identical to the tot
166    if(!totErr){         
167      //Calculate the percentage
168      double percent = (cur/tot)*100;
169      percent = int(percent*10)/10.0;
170      out.append(QString::number(percent)+"::");
171      //Now list the total
172      out.append( Extras::sizeKToDisplay(QString::number(tot)) +"::" );
173    }else{
174      //Only Total/Current is known (unknown percentage since not complete yet)
175      out.append("??::"+Extras::sizeKToDisplay(QString::number(tot))+"::");
176    }       
177  }else if(curok){
178    //Only Total/Current is known (unknown percentage since not complete yet)
179    out.append("??::"+Extras::sizeKToDisplay(QString::number(cur))+"::");
180  }else if(totok){
181    //Only Total/Current is known (unknown percentage since not complete yet)
182    out.append("??::"+Extras::sizeKToDisplay(QString::number(tot))+"::");
183  }else{
184    //Unknown Total and Current
185    out.append("??::??::");
186  }
187  //Now get the speed
188  if(spdok){
189    out.append( Extras::sizeKToDisplay(QString::number(spd))+"/s" );
190  }else{
191    out.append("??");
192  }
193  return out;
194}
195
196// == UPDATE PROCESS ==
197void ProcessManager::slotUpProcMessage(){
198  while( upProc->canReadLine() ){
199    QString line = upProc->readLine().simplified();
200    if(line.isEmpty()){ continue; }
201    QString dl = parseDlLine(line);
202    if(!dl.isEmpty()){ 
203      emit ProcessMessage(UPDATE,dl); //Download status
204      if( !dl.startsWith("DLSTAT::") ){
205        upLog << line; //not just a status update - add to the log (log download start/stop)   
206      }
207    }else{ 
208      emit ProcessMessage(UPDATE,line); 
209      upLog << line; //not a download line - add to the log
210    }
211  }
212}
213
214void ProcessManager::slotUpProcFinished(){
215  if(upProc->exitStatus() != QProcess::NormalExit || upProc->exitCode() != 0){
216    //Emit the command log
217    qDebug() << "Update Process Error Log:\n"<<upLog.join("\n");
218    emit ProcessError(UPDATE, upLog);
219  }else{
220    qDebug() << "Update Process Finished";
221    emit ProcessFinished(UPDATE);         
222  }
223}
224
225// == REMOVE PROCESS ==
226void ProcessManager::slotRemProcMessage(){
227  while( remProc->canReadLine() ){
228    QString line = remProc->readLine().simplified();
229    if(!line.isEmpty()){ 
230      remLog << line; 
231      emit ProcessMessage(REMOVE,line);
232    }
233  }
234}
235
236void ProcessManager::slotRemProcFinished(){
237  if(remProc->exitStatus() != QProcess::NormalExit || (remProc->exitCode() != 0 && remStrictErrChecking) ){
238    qDebug() << "Removal Process Error Log:\n"<<remLog.join("\n");
239    emit ProcessError(REMOVE, remLog);
240  }else{
241    qDebug() << "Removal Process Finished";
242    emit ProcessFinished(REMOVE);         
243  }
244}
245
246// == DOWNLOAD PROCESS ==
247void ProcessManager::slotDlProcMessage(){
248  while( dlProc->canReadLine() ){
249    QString line = dlProc->readLine().simplified();
250    if(line.isEmpty()){ continue; }
251    QString dl = parseDlLine(line);
252    if(!dl.isEmpty()){ 
253      emit ProcessMessage(DOWNLOAD,dl); //Download status
254      if( !dl.startsWith("DLSTAT::") ){
255        dlLog << line; //not just a status update - add to the log (log download start/stop)   
256      }
257    }else{ 
258      emit ProcessMessage(DOWNLOAD,line); 
259      dlLog << line; //not a download line - add to the log
260    }
261  }
262}
263
264void ProcessManager::slotDlProcFinished(){
265  if(dlProc->exitStatus() != QProcess::NormalExit || dlProc->exitCode() != 0){
266    qDebug() << "Download Process Error Log:\n"<<dlLog.join("\n");
267    emit ProcessError(DOWNLOAD, dlLog);
268  }else{
269    qDebug() << "Download Process Finished";
270    emit ProcessFinished(DOWNLOAD);       
271  }
272}
273
274// == INSTALL PROCESS ==
275void ProcessManager::slotInProcMessage(){
276  while( inProc->canReadLine() ){
277    QString line = inProc->readLine().simplified();
278    if(!line.isEmpty()){ 
279      inLog << line; 
280      emit ProcessMessage(INSTALL,line);
281    }
282  }
283}
284
285void ProcessManager::slotInProcFinished(){
286  if(inProc->exitStatus() != QProcess::NormalExit || inProc->exitCode() != 0){
287    qDebug() << "Install Process Error Log:\n"<<inLog.join("\n");
288    emit ProcessError(INSTALL, inLog);
289  }else{
290    qDebug() << "Install Process Finished";
291    emit ProcessFinished(INSTALL);       
292  }
293}
294
295// == OTHER PROCESS ==
296void ProcessManager::slotOtProcMessage(){
297  QString msg = otProc->readAllStandardOutput();
298  emit ProcessMessage(OTHER,msg);
299}
300
301void ProcessManager::slotOtProcFinished(){
302  if(otProc->exitStatus() != QProcess::NormalExit){
303    QString msg = otProc->readAllStandardError();
304    if(msg.isEmpty()){ msg = otProc->readAllStandardOutput(); }
305    if(msg.isEmpty()){ msg = tr("Unknown Error"); }
306    qDebug() << "Other Process Error:"<<msg;
307    emit ProcessError(OTHER, QStringList(msg));
308  }else{
309    qDebug() << "Other Process Finished";
310    emit ProcessFinished(OTHER);         
311  }
312}
313
Note: See TracBrowser for help on using the repository browser.