1 /******************************************************************************
2 
3   This source file is part of the MoleQueue project.
4 
5   Copyright 2012 Kitware, Inc.
6 
7   This source code is released under the New BSD License, (the "License").
8 
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14 
15 ******************************************************************************/
16 
17 #ifndef MOLEQUEUE_JOBDATA_H
18 #define MOLEQUEUE_JOBDATA_H
19 
20 #include "molequeueglobal.h"
21 
22 #include "filespecification.h"
23 
24 #include <qjsonobject.h>
25 
26 #include <QtCore/QMetaType>
27 #include <QtCore/QString>
28 
29 class ClientTest;
30 class JobManagerTest;
31 class ServerConnectionTest;
32 
33 namespace MoleQueue
34 {
35 class Client;
36 class JobManager;
37 class Server;
38 
39 /**
40  * @class JobData jobdata.h <molequeue/jobdata.h>
41  * @brief Internal container for job details.
42  * @author David C. Lonie
43  *
44  * Each JobData instance stores information about a specific job. All JobData
45  * objects are owned by a JobManager, which dispenses JobReferenceBase
46  * subclasses (Job and JobRequest) that are used to interact with the JobData
47  * members.
48  *
49  */
50 class JobData
51 {
52 public:
53 
54   JobData(JobManager *parentManager);
55   JobData(const JobData &);
56 
57   /// @return The parent JobManager
jobManager()58   JobManager *jobManager() const { return m_jobManager; }
59 
60   /// @param newQueue name of the queue.
setQueue(const QString & newQueue)61   void setQueue(const QString &newQueue)
62   {
63     if (m_queue != newQueue) {
64       m_queue = newQueue;
65       modified();
66     }
67   }
68 
69   /// @return Name of queue to use.
queue()70   QString queue() const { return m_queue; }
71 
72   /// @param newProgram Name of the program.
setProgram(const QString & newProgram)73   void setProgram(const QString &newProgram)
74   {
75     if (m_program != newProgram) {
76       m_program = newProgram;
77       modified();
78     }
79   }
80 
81   /// @return Name of program to run.
program()82   QString program() const { return m_program; }
83 
84   /// @param state Status of job
setJobState(JobState state)85   void setJobState(JobState state)
86   {
87     if (m_jobState != state) {
88       m_jobState = state;
89       modified();
90     }
91   }
92 
93   /// @return Status of job
jobState()94   JobState jobState() const { return m_jobState; }
95 
96   /// @param newDesc Description of job
setDescription(const QString & newDesc)97   void setDescription(const QString &newDesc)
98   {
99     if (m_description != newDesc) {
100       m_description = newDesc;
101       modified();
102     }
103   }
104 
105   /// @return newDesc Description of job
description()106   QString description() const { return m_description; }
107 
108   /// @param filespec FileSpecification describing the main input file (called
109   /// by the executable)
setInputFile(const FileSpecification & filespec)110   void setInputFile(const FileSpecification &filespec)
111   {
112     m_inputFile = filespec;
113     modified();
114   }
115 
116   /// @return FileSpecification describing the main input file (called by the
117   /// executable)
inputFile()118   FileSpecification inputFile() const { return m_inputFile; }
119 
120   /// @param files FileSpecification objects describing additional input files
121   /// to be placed in the working directory of the job prior to execution.
setAdditionalInputFiles(const QList<FileSpecification> & files)122   void setAdditionalInputFiles(const QList<FileSpecification> & files)
123   {
124     m_additionalInputFiles = files;
125     modified();
126   }
127 
128   /// @return FileSpecification objects describing additional input files to be
129   /// placed in the working directory of the job prior to execution.
additionalInputFiles()130   QList<FileSpecification> additionalInputFiles() const
131   {
132     return m_additionalInputFiles;
133   }
134 
135   /// @return A reference to the additional input files list.
additionalInputFilesRef()136   QList<FileSpecification> & additionalInputFilesRef()
137   {
138     return m_additionalInputFiles;
139   }
140 
141   /// @param path String containing a location to copy the output files to after
142   /// the job completes. Ignored if empty.
setOutputDirectory(const QString & path)143   void setOutputDirectory(const QString &path)
144   {
145     if (m_outputDirectory != path) {
146       m_outputDirectory = path;
147       modified();
148     }
149   }
150 
151   /// @return String containing a location to copy the output files to after
152   /// the job completes. Ignored if empty.
outputDirectory()153   QString outputDirectory() const { return m_outputDirectory; }
154 
155   /// @param path Temporary working directory where files are stored during job
156   /// execution.
setLocalWorkingDirectory(const QString & path)157   void setLocalWorkingDirectory(const QString &path)
158   {
159     if (m_localWorkingDirectory != path) {
160       m_localWorkingDirectory = path;
161       modified();
162     }
163   }
164 
165   /// @return Temporary working directory where files are stored during job
166   /// execution.
localWorkingDirectory()167   QString localWorkingDirectory() const { return m_localWorkingDirectory; }
168 
169   /// @param clean If true, delete any working files on the remote server.
170   /// Default: false.
setCleanRemoteFiles(bool clean)171   void setCleanRemoteFiles(bool clean)
172   {
173     if (m_cleanRemoteFiles != clean) {
174       m_cleanRemoteFiles = clean;
175       modified();
176     }
177   }
178 
179   /// @return If true, delete any working files on the remote server.
180   /// Default: false.
cleanRemoteFiles()181   bool cleanRemoteFiles() const { return m_cleanRemoteFiles; }
182 
183   /// @param b If true, copies files back from remote server. Default: true
setRetrieveOutput(bool b)184   void setRetrieveOutput(bool b)
185   {
186     if (m_retrieveOutput != b) {
187       m_retrieveOutput = b;
188       modified();
189     }
190   }
191 
192   /// @return If true, copies files back from remote server. Default: true
retrieveOutput()193   bool retrieveOutput() const { return m_retrieveOutput; }
194 
195   /// @param b If true, the local working files are removed after job is
196   /// complete. Should be used with setOutputDirectory. Default: false
setCleanLocalWorkingDirectory(bool b)197   void setCleanLocalWorkingDirectory(bool b)
198   {
199     if (m_cleanLocalWorkingDirectory != b) {
200       m_cleanLocalWorkingDirectory = b;
201       modified();
202     }
203   }
204 
205   /// @return If true, the local working files are removed after job is
206   /// complete. Should be used with setOutputDirectory. Default: false
cleanLocalWorkingDirectory()207   bool cleanLocalWorkingDirectory() const
208   {
209     return m_cleanLocalWorkingDirectory;
210   }
211 
212   /// @param b If true, the job will not appear in the queue. Default: false
setHideFromGui(bool b)213   void setHideFromGui(bool b)
214   {
215     if (m_hideFromGui != b) {
216       m_hideFromGui = b;
217       modified();
218     }
219   }
220 
221   /// @return If true, the job will not appear in the queue. Default: false
hideFromGui()222   bool hideFromGui() const { return m_hideFromGui; }
223 
224   /// @param b If true, changes in the job state will trigger a popup
225   /// notification from the MoleQueue system tray icon. Default: false
setPopupOnStateChange(bool b)226   void setPopupOnStateChange(bool b)
227   {
228     if (m_popupOnStateChange != b) {
229       m_popupOnStateChange = b;
230       modified();
231     }
232   }
233 
234   /// @return If true, changes in the job state will trigger a popup
235   /// notification from the MoleQueue system tray icon. Default: false
popupOnStateChange()236   bool popupOnStateChange() const { return m_popupOnStateChange; }
237 
238   /// @param num The total number of processor cores to use (if applicable).
239   /// Default: 1
setNumberOfCores(int num)240   void setNumberOfCores(int num)
241   {
242     if (m_numberOfCores != num) {
243       m_numberOfCores = num;
244       modified();
245     }
246   }
247 
248   /// @return The total number of processor cores to use (if applicable).
249   /// Default: 1
numberOfCores()250   int numberOfCores() const { return m_numberOfCores; }
251 
252   /// @param minutes The maximum walltime for this job in minutes. Setting this
253   /// to a value <= 0 will use the queue-specific default max walltime. Only
254   /// available for remote queues. Default is -1.
setMaxWallTime(int minutes)255   void setMaxWallTime(int minutes)
256   {
257     if (m_maxWallTime != minutes) {
258       m_maxWallTime = minutes;
259       modified();
260     }
261   }
262 
263   /// @return The maximum walltime for this job in minutes. Setting this to a
264   /// value <= 0 will use the queue-specific default max walltime. Only
265   /// available for remote queues. Default is -1.
maxWallTime()266   int maxWallTime() const { return m_maxWallTime; }
267 
268   /// @param id Internal MoleQueue identifier
setMoleQueueId(IdType id)269   void setMoleQueueId(IdType id)
270   {
271     if (m_moleQueueId != id) {
272       m_moleQueueId = id;
273       modified();
274     }
275   }
276 
277   /// @return Internal MoleQueue identifier
moleQueueId()278   IdType moleQueueId() const { return m_moleQueueId; }
279 
280   /// @param id Queue Job ID
setQueueId(IdType id)281   void setQueueId(IdType id)
282   {
283     if (m_queueId != id) {
284       m_queueId = id;
285       modified();
286     }
287   }
288 
289   /// @return Queue Job ID
queueId()290   IdType queueId() const { return m_queueId; }
291 
292   /// @return A reference to the job's keyword hash
keywordsRef()293   QHash<QString, QString> & keywordsRef() { return m_keywords; }
294 
295   /// @param keyrep The keyword replacement hash
setKeywords(const QHash<QString,QString> & keyrep)296   void setKeywords(const QHash<QString, QString> &keyrep)
297   {
298     if (m_keywords != keyrep) {
299       m_keywords = keyrep;
300       modified();
301     }
302   }
303 
304   /// @return The keyword replacement hash
keywords()305   QHash<QString, QString> keywords() const { return m_keywords; }
306 
307   /// @return The Job's internal state as a QJsonObject
308   QJsonObject toJsonObject() const;
309 
310   /// Update the Job's internal state from a QJsonObject
311   void setFromJson(const QJsonObject &state);
312 
313   /// Initialize the JobData from the state in JSON file @a stateFileName
314   bool load(const QString& stateFilename);
315 
316   /// Write a mqjobinfo.json file to the JobData's local working directory with
317   /// the job state.
318   bool save();
319 
320   /// @return true if the JobData has changed since load() or save() was called.
needsSync()321   bool needsSync() const { return m_needsSync; }
322 
323   /// Called when the JobData is modified.
modified()324   void modified() { m_needsSync = true; }
325 
326 protected:
327   /// Parent JobManager
328   JobManager *m_jobManager;
329   /// Name of queue to use
330   QString m_queue;
331   /// Name of program to run
332   QString m_program;
333   /// Current state of job
334   JobState m_jobState;
335   /// Description of job
336   QString m_description;
337   /// FileSpecification describing the main input file (called by the executable)
338   FileSpecification m_inputFile;
339   /// FileSpecification objects describing additional input files, to be placed
340   /// in the working directory of the job prior to execution.
341   QList<FileSpecification> m_additionalInputFiles;
342   /// String containing a location to copy the output files to after the job
343   /// completes. Ignored if empty.
344   QString m_outputDirectory;
345   /// Temporary working directory where files are stored during job execution.
346   QString m_localWorkingDirectory;
347   /// If true, delete any working files on the remote server. Default: false.
348   bool m_cleanRemoteFiles;
349   /// If true, copies files back from remote server. Default: true
350   bool m_retrieveOutput;
351   /// If true, the local working files are removed after job is complete. Should
352   /// be used with setOutputDirectory. Default: false
353   bool m_cleanLocalWorkingDirectory;
354   /// If true, the job will not appear in the queue. Default: false
355   bool m_hideFromGui;
356   /// If true, changes in the job state will trigger a popup notification from
357   /// the MoleQueue system tray icon. Default: true
358   bool m_popupOnStateChange;
359   /// The total number of processor cores to use (if applicable).
360   /// Default: 1
361   int m_numberOfCores;
362   /// The maximum walltime for this job in minutes. Setting this
363   /// to a value <= 0 will use the queue-specific default max walltime. Only
364   /// available for remote queues. Default is -1.
365   int m_maxWallTime;
366   /// Internal MoleQueue identifier
367   IdType m_moleQueueId;
368   /// Queue Job ID
369   IdType m_queueId;
370   /// List of custom keyword replacements for the job's launch script
371   QHash<QString, QString> m_keywords;
372 
373   /// True if the JobData has changed since load() or save() was called.
374   bool m_needsSync;
375 };
376 
377 } // end namespace MoleQueue
378 
379 Q_DECLARE_METATYPE(MoleQueue::JobData*)
380 Q_DECLARE_METATYPE(const MoleQueue::JobData*)
381 
382 #endif // JOB_H
383