00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <globalsearch/queueinterfaces/internal.h>
00017
00018 #include <globalsearch/macros.h>
00019 #include <globalsearch/optimizer.h>
00020 #include <globalsearch/queueinterfaces/internaldialog.h>
00021 #include <globalsearch/queuemanager.h>
00022 #include <globalsearch/structure.h>
00023
00024 #include <QtCore/QDir>
00025 #include <QtCore/QFile>
00026 #include <QtCore/QHash>
00027 #include <QtCore/QProcess>
00028 #include <QtCore/QString>
00029 #include <QtCore/QTextStream>
00030
00031 #ifdef WIN32
00032
00033 #define _WINSOCKAPI_
00034
00035 #include <windows.h>
00036 #endif
00037
00038 #include <globalsearch/queueinterfaces/internal.h>
00039
00040 namespace GlobalSearch {
00041
00042 InternalQueueInterface::InternalQueueInterface(OptBase *parent,
00043 const QString &settingsFile)
00044 : LocalQueueInterface(parent)
00045 {
00046
00047 qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
00048 qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
00049
00050 m_idString = "Internal";
00051 m_hasDialog = true;
00052 }
00053
00054 InternalQueueInterface::~InternalQueueInterface()
00055 {
00056 for (QHash<unsigned long, InternalQueueProcess*>::iterator
00057 it = m_processes.begin(),
00058 it_end = m_processes.end();
00059 it != it_end; ++it) {
00060 if ((*it) && ((*it)->state() == QProcess::Running)) {
00061
00062
00063 (*it)->terminate();
00064 (*it)->waitForFinished(5000);
00065 (*it)->kill();
00066 }
00067 }
00068 }
00069
00070 bool InternalQueueInterface::isReadyToSearch(QString *str)
00071 {
00072
00073 if (m_opt->filePath.isEmpty()) {
00074 *str = tr("Local working directory is not set. Check your Queue "
00075 "configuration.");
00076 return false;
00077 }
00078
00079
00080 QDir workingdir (m_opt->filePath);
00081 bool writable = true;
00082 if (!workingdir.exists()) {
00083 if (!workingdir.mkpath(m_opt->filePath)) {
00084 writable = false;
00085 }
00086 }
00087 else {
00088
00089 QString filename = m_opt->filePath + QString("queuetest-")
00090 + QString::number(RANDUINT());
00091 QFile file (filename);
00092 if (!file.open(QFile::ReadWrite)) {
00093 writable = false;
00094 }
00095 file.remove();
00096 }
00097 if (!writable) {
00098 *str = tr("Cannot write to working directory '%1'.\n\nPlease "
00099 "change the permissions on this directory or use "
00100 "a different one.").arg(m_opt->filePath);
00101 return false;
00102 }
00103
00104 *str = "";
00105 return true;
00106 }
00107
00108 bool InternalQueueInterface::startJob(Structure *s)
00109 {
00110 if (s->getJobID() != 0) {
00111 m_opt->warning(tr("InternalQueueInterface::startJob: Attempting to start "
00112 "job for structure %1, but a JobID is already set (%2)."
00113 ).arg(s->getIDString()).arg(s->getJobID()));
00114 return false;
00115 }
00116
00117
00118
00119 QString command = m_opt->optimizer()->localRunCommand()
00120 + " " + m_opt->optimizer()->localRunArgs().join(" ");
00121
00122 #ifdef WIN32
00123 command = "cmd.exe /C \"" + command + "\"";
00124 #endif // WIN32
00125
00126 InternalQueueProcess *proc = new InternalQueueProcess(this);
00127 proc->setWorkingDirectory(s->fileName());
00128 if (!m_opt->optimizer()->stdinFilename().isEmpty()) {
00129 proc->setStandardInputFile(s->fileName()
00130 + "/" + m_opt->optimizer()->stdinFilename());
00131 }
00132 if (!m_opt->optimizer()->stdoutFilename().isEmpty()) {
00133 proc->setStandardOutputFile(s->fileName()
00134 + "/" + m_opt->optimizer()->stdoutFilename());
00135 }
00136 if (!m_opt->optimizer()->stderrFilename().isEmpty()) {
00137 proc->setStandardErrorFile(s->fileName()
00138 + "/" + m_opt->optimizer()->stderrFilename());
00139 }
00140
00141 proc->start(command);
00142
00143 #ifdef WIN32
00144 unsigned long pid = proc->pid()->dwProcessId;
00145 #else // WIN32
00146 unsigned long pid = proc->pid();
00147 #endif // WIN32
00148
00149 s->startOptTimer();
00150 s->setJobID(pid);
00151
00152 m_processes.insert(pid, proc);
00153
00154 return true;
00155 }
00156
00157 bool InternalQueueInterface::stopJob(Structure *s)
00158 {
00159 QWriteLocker wLocker (s->lock());
00160
00161 unsigned long pid = static_cast<unsigned long>(s->getJobID());
00162
00163 if (pid == 0) {
00164
00165 return true;
00166 }
00167
00168
00169 InternalQueueProcess *proc = m_processes.value(pid, 0);
00170 if (!proc) {
00171
00172 return true;
00173 }
00174
00175
00176 proc->kill();
00177 s->setJobID(0);
00178 s->stopOptTimer();
00179 m_processes.remove(pid);
00180 return true;
00181 }
00182
00183 QueueInterface::QueueStatus
00184 InternalQueueInterface::getStatus(Structure *s) const
00185 {
00186
00187 QReadLocker wlocker (s->lock());
00188
00189
00190 unsigned long pid = static_cast<unsigned long>(s->getJobID());
00191
00192
00193 if (!pid && s->getStatus() != Structure::Submitted) {
00194 return QueueInterface::Error;
00195 }
00196
00197
00198 InternalQueueProcess *proc = m_processes.value(pid, 0);
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 if (s->getStatus() == Structure::Submitted) {
00210
00211 if (pid == 0 || proc == 0) {
00212
00213 bool exists;
00214 m_opt->optimizer()->checkIfOutputFileExists(s, &exists);
00215 if (!exists) {
00216
00217
00218 return QueueInterface::Pending;
00219 }
00220 }
00221
00222 return QueueInterface::Started;
00223 }
00224
00225
00226 if (!proc) {
00227 return QueueInterface::Error;
00228 }
00229
00230
00231
00232 switch (proc->status()) {
00233 case InternalQueueProcess::NotStarted:
00234 return QueueInterface::Pending;
00235 case InternalQueueProcess::Running:
00236 return QueueInterface::Running;
00237 case InternalQueueProcess::Error:
00238 return QueueInterface::Error;
00239 case InternalQueueProcess::Finished:
00240
00241 if (proc->exitCode() != 0) {
00242 m_opt->warning(tr("%1: Structure %2, PID=%3 failed. QProcess error "
00243 "code: %4. Process exit code: %5 errStr: %6\n"
00244 "stdout:\n%7\nstderr:\n%8")
00245 .arg(Q_FUNC_INFO).arg(s->getIDString()).arg(pid)
00246 .arg(proc->error()).arg(proc->exitCode())
00247 .arg(proc->errorString())
00248 .arg(QString(proc->readAllStandardOutput()))
00249 .arg(QString(proc->readAllStandardError())));
00250 return QueueInterface::Error;
00251 }
00252 bool success;
00253 m_opt->optimizer()->checkForSuccessfulOutput(s, &success);
00254 if (success) {
00255 return QueueInterface::Success;
00256 }
00257 else {
00258 return QueueInterface::Error;
00259 }
00260 default:
00261
00262 return QueueInterface::Unknown;
00263 }
00264 }
00265
00266 bool InternalQueueInterface::prepareForStructureUpdate(Structure *s) const
00267 {
00268
00269 return true;
00270 }
00271
00272 QDialog* InternalQueueInterface::dialog()
00273 {
00274 if (!m_dialog) {
00275 m_dialog = new InternalQueueInterfaceConfigDialog (m_opt->dialog(),
00276 m_opt,
00277 this);
00278 }
00279 InternalQueueInterfaceConfigDialog *d =
00280 qobject_cast<InternalQueueInterfaceConfigDialog*>(m_dialog);
00281 d->updateGUI();
00282
00283 return d;
00284 }
00285
00286
00287 }