Isis 3 Programmer Reference
ProgramLauncher.cpp
Go to the documentation of this file.
1 
23 #include "ProgramLauncher.h"
24 
25 #include <iostream>
26 #include <sstream>
27 #include <sys/wait.h>
28 
29 #include <QLocalServer>
30 #include <QLocalSocket>
31 #include <QProcess>
32 
33 #include "Application.h"
34 #include "FileName.h"
35 #include "IException.h"
36 #include "IString.h"
37 
38 using namespace std;
39 
40 namespace Isis {
53  void ProgramLauncher::RunIsisProgram(QString programName,
54  QString parameters) {
55  FileName program(programName);
56  FileName isisExecutableFileName("$ISISROOT/bin/" + program.name());
57  bool isIsisProgram = false;
58 
59  if(isisExecutableFileName.fileExists()) {
60  isIsisProgram = true;
61  program = isisExecutableFileName;
62  }
63 
64  QString command = program.expanded() + " " + parameters +
65  " -pid=" + toString(getpid());
66 
67  if(!isIsisProgram) {
68  QString msg = "Program [" + programName + "] does not appear to be a "
69  "valid Isis 3 program";
70  throw IException(IException::Unknown, msg, _FILEINFO_);
71  }
72 
73  QString serverName = "isis_" + Application::UserName() +
74  "_" + toString(getpid());
75 
76  QLocalServer server;
77  server.listen(serverName);
78 
79  QProcess childProcess;
80  childProcess.setProcessChannelMode(QProcess::ForwardedChannels);
81  childProcess.start(command);
82  childProcess.waitForStarted();
83 
84  bool connected = false;
85 
86  while(!connected && childProcess.state() != QProcess::NotRunning) {
87  // Give time for the process to connect to us or for it to finish
88  // wait 30s for the new connection....
89  connected = server.waitForNewConnection(30000);
90  childProcess.waitForFinished(100);
91  }
92 
93  if(!connected) {
94  QString msg = "Isis child process failed to communicate with parent";
95  throw IException(IException::Programmer, msg, _FILEINFO_);
96  }
97 
98  QLocalSocket *childSocket = server.nextPendingConnection();
99  IException errors;
100 
101  // Don't return until we're done running this program
102  while(childSocket->state() != QLocalSocket::UnconnectedState) {
103  bool insideCode = true;
104  bool messageDone = false;
105 
106  QString code;
107  QString message;
108  QByteArray lineData;
109 
110  if(childSocket->waitForReadyRead(1000)) {
111  lineData = childSocket->read(childSocket->bytesAvailable());
112 
113  for(int i = 0; i < lineData.size(); i++) {
114  if(insideCode) {
115  if(lineData[i] != (char)27) {
116  code += lineData[i];
117  }
118  else {
119  insideCode = false;
120  }
121  }
122  else {
123  if(lineData[i] != (char)27) {
124  message += lineData[i];
125  }
126  else {
127  messageDone = true;
128  insideCode = true;
129  i ++; // skip \n that should always exist here
130  }
131  }
132 
133  if(messageDone) {
134  errors.append(
135  ProcessIsisMessageFromChild(code, message));
136  code = "";
137  message = "";
138  messageDone = false;
139  }
140  }
141  }
142  }
143 
144  childProcess.waitForFinished();
145 
146  if(childProcess.exitCode() != 0) {
147  QString msg = "Running Isis program [" + programName + "] failed with "
148  "return status [" + toString(childProcess.exitCode()) + "]";
149  throw IException(errors, IException::Unknown, msg, _FILEINFO_);
150  }
151  }
152 
153 
164  IException
165  ProgramLauncher::ProcessIsisMessageFromChild(QString code, QString msg) {
166  IException errors;
167 
168  if(code == "PROGRESSTEXT" && iApp) {
169  iApp->UpdateProgress(msg, true);
170  }
171  else if(code == "PROGRESS" && iApp) {
172  iApp->UpdateProgress(toInt(msg), true);
173  }
174  else if(code == "LOG" && iApp) {
175  stringstream msgStream;
176  msgStream << msg;
177  Pvl logPvl;
178  msgStream >> logPvl;
179 
180  if(logPvl.groups() == 1 &&
181  logPvl.keywords() == 0 &&
182  logPvl.objects() == 0) {
183  iApp->Log(logPvl.group(0));
184  }
185  }
186  else if(code == "GUILOG" && iApp) {
187  iApp->GuiLog(msg);
188  }
189  else if(code == "ERROR") {
190  stringstream msgStream;
191  msgStream << msg;
192  Pvl errorPvl;
193  msgStream >> errorPvl;
194 
195  for(int i = 0; i < errorPvl.groups(); i++) {
196  PvlGroup &g = errorPvl.group(i);
197  QString eclass = g["Class"];
198  QString emsg = g["Message"];
199  int ecode = g["Code"];
200  QString efile = g["File"];
201  int eline = g["Line"];
202 
203  errors.append(
204  IException((IException::ErrorType)ecode, emsg, efile.toLatin1().data(), eline));
205  }
206  }
207 
208  return errors;
209  }
210 
211 
223  void ProgramLauncher::RunSystemCommand(QString fullCommand) {
224  int status = system(fullCommand.toLatin1().data());
225 
226  if(status != 0) {
227  QString msg = "Executing command [" + fullCommand +
228  "] failed with return status [" + toString(status) + "]";
229  throw IException(IException::Programmer, msg, _FILEINFO_);
230  }
231  }
232 } //end namespace isis
File name manipulation and expansion.
Definition: FileName.h:116
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:108
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception&#39;s causational exc...
Definition: IException.cpp:425
Namespace for the standard library.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
static void GuiLog(const Pvl &results)
Writes the Pvl results to the sessionlog, but not to the printfile.
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
static void Log(PvlGroup &results)
Writes Pvl results to sessionlog and printfile.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
Container for cube-like labels.
Definition: Pvl.h:135
ErrorType
Contains a set of exception error types.
Definition: IException.h:127
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
void UpdateProgress(const QString &text, bool print)
Updates the progress bar in the gui.