File: queue.h

package info (click to toggle)
molequeue 0.9.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,924 kB
  • sloc: cpp: 22,039; python: 478; xml: 364; sh: 59; makefile: 14
file content (434 lines) | stat: -rw-r--r-- 14,271 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
/******************************************************************************

  This source file is part of the MoleQueue project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#ifndef MOLEQUEUE_QUEUE_H
#define MOLEQUEUE_QUEUE_H

#include <QtCore/QObject>

#include "job.h"

#include "idtypeutils.h"

#include <QtCore/QMap>
#include <QtCore/QList>
#include <QtCore/QMetaType>
#include <QtCore/QPointer>
#include <QtCore/QStringList>

class QJsonObject;

namespace MoleQueue
{
class AbstractQueueSettingsWidget;
class Job;
class Program;
class QueueManager;
class Server;

/**
 * @class Queue queue.h <molequeue/queue.h>
 * @brief Abstract interface for queuing systems.
 * @author Marcus D. Hanwell, David C. Lonie
 *
 * The Queue interface defines interactions with a distributed resource
 * management system, such as job submission and job status updates. Each
 * Queue object manages a set of Program instances, which contain information
 * about the related task of actually running an executable to do work.
 */
class Queue : public QObject
{
  Q_OBJECT
protected:
  /**
   * Protected constructor. Use QueueManager:::addQueue() method to create new
   * Queue objects.
   */
  explicit Queue(const QString &queueName = "Undefined",
                 QueueManager *parentManager = 0);

public:
  ~Queue();

  /// @return The parent Server
  Server *server() { return m_server; }
  /// @return The parent Server
  const Server *server() const { return m_server; }

  /// @return The parent QueueManager
  QueueManager *queueManager() { return m_queueManager; }
  /// @return The parent Server
  const QueueManager *queueManager() const { return m_queueManager; }

  /**
   * Set the name of the queue. This should be unique, and will be used in the
   * GUI to refer to this queue.
   */
  virtual void setName(const QString &newName)
  {
    if (newName != m_name) {
      QString oldName = m_name;
      m_name = newName;
      emit nameChanged(newName, oldName);
    }
  }

  /** Get the name of the queue. */
  QString name() const { return m_name; }

  /**
   * Returns the type of the queue as a string.
   */
  virtual QString typeName() const { return "Unknown"; }

  /**
   * Read settings for the queue, done early on at startup.
   * @param filePath Path to the .mqq file with the queue settings.
   *
   * This method calls readJsonSettings to perform the actual setting of
   * state information. Subclasses should reimplement that method.
   */
  bool readSettings(const QString &filePath);

  /**
   * Write settings for the queue, done just before closing the server.
   * The settings are written to
   * [server's local working directory]/config/queues/[queuename].mqq
   *
   * This method calls writeJsonSettings to perform the actual collection of
   * state information. Subclasses should reimplement that method.
   */
  bool writeSettings() const;

  /**
   * Write this Queue's configuration to the .mqq file @a fileName.
   * Sensitive data (such as usernames, etc) and mutatable state data (like
   * current jobs) are not written, see writeSettings() if these are needed.
   * @param includePrograms Export this queue's programs as well. Default: true
   *
   * This method calls writeJsonSettings to perform the actual collection of
   * state information. Subclasses should reimplement that method.
   */
  bool exportSettings(const QString &fileName,
                      bool includePrograms = true) const;

  /**
   * Set this Queue's configuration using the the .mqq file @a fileName.
   * Sensitive data (such as usernames, etc) and mutatable state data (like
   * current jobs) are not read, see readSettings() if these are needed.
   * @param includePrograms Import any programs contained in the importer.
   * Default: true
   *
   * This method calls readJsonSettings to perform the actual setting of
   * state information. Subclasses should reimplement that method.
   */
  bool importSettings(const QString &fileName, bool includePrograms = true);

  /**
   * @param mqqFile Filename of the mqq (MoleQueue Queue) file.
   * @return Return the type of queue that is stored in the .mqq file.
   */
  static QString queueTypeFromFile(const QString &mqqFile);

  /**
   * @return The name of the persistant state file used to store this Queue's
   * configuration.
   */
  QString stateFileName() const;

  /**
   * @brief writeJsonSettings Write the queue's internal state into a JSON
   * object.
   * @param value Target JSON object.
   * @param exportOnly If true, instance specific information (e.g. currently
   * running jobs, login details, etc) is omitted.
   * @param includePrograms Whether or not to include the Queue's program
   * configurations.
   * @return True on success, false on failure.
   */
  virtual bool writeJsonSettings(QJsonObject &value, bool exportOnly,
                                 bool includePrograms) const;

  /**
   * @brief readJsonSettings Initialize the queue's internal state from a JSON
   * object.
   * @param value Source JSON object.
   * @param importOnly If true, instance specific information (e.g. currently
   * running jobs, login details, etc) is ignored.
   * @param includePrograms Whether or not to include the Queue's program
   * configurations.
   * @return True on success, false on failure.
   *
   * @note When reimplementing this method, verify and parse the Json object
   * into temporary variables, then call the base class implementation and only
   * modify the queue if the call returns true.
   */
  virtual bool readJsonSettings(const QJsonObject &value, bool importOnly,
                                bool includePrograms);


  /**
   * Returns a widget that can be used to configure the settings for the
   * queue.
   */
  virtual AbstractQueueSettingsWidget* settingsWidget();

  /**
   * Add a new program to the queue. Program names must be unique in each
   * queue, as they are used to specify which program will be used.
   * @note This Queue instance will take ownership and reparent @a newProgram.
   * @param program The program to be added to the queue.
   * @param replace Defaults to false, if true replace any program with the
   * same name in this queue.
   * @return True on success, false on failure.
   */
  bool addProgram(Program *newProgram, bool replace = false);

  /**
   * Attempt to remove a program from the queue. The program name is used
   * as the criteria to decice which object to remove.
   * @param program The program to be removed from the queue.
   * @return True on success, false on failure.
   */
  bool removeProgram(Program *programToRemove);

  /**
   * Attempt to remove a program from the queue. The program name is used
   * as the criteria to decide which object to remove.
   * @param name The name of the program to be removed from the queue.
   * @return True on success, false on failure.
   */
  bool removeProgram(const QString &programName);

  /**
   * Retrieve the program object associated with the supplied name.
   * @param name The name of the program.
   * @return The Program object, a null pointer is returned if the
   * requested program is not in this queue.
   */
  Program* lookupProgram(const QString &programName) const
  {
    return m_programs.value(programName, NULL);
  }

  /**
   * @return A list of program names available through this queue.
   */
  QStringList programNames() const
  {
    return m_programs.keys();
  }

  /**
   * @return A list of the available Program objects.
   */
  QList<Program *> programs() const
  {
    return m_programs.values();
  }

  /**
   * @return The number of programs belonging to this Queue.
   */
  int numPrograms() const
  {
    return m_programs.size();
  }

  /**
   * @return A string containing a template for the launcher script. For remote
   * queues, this will be a batch script for the queuing system, for local
   * queues this will be a shell script (unix) or batch script (windows).
   *
   * It should contain the token "$$programExecution$$", which will be replaced
   * with program-specific launch details.
   */
  virtual QString launchTemplate() const { return m_launchTemplate; }

  /**
   * @return The filename for the launcher script. For remote
   * queues, this will be a batch script for the queuing system, for local
   * queues this will be a shell script (unix) or batch script (windows).
   */
  QString launchScriptName() const { return m_launchScriptName; }

  /**
   * @param moleQueueId MoleQueue id of Job of interest.
   * @return The number of time the job has failed if it has encountered an
   * error and is being retried. 0 if the job has not encountered an error, or
   * has exceeded three retries.
   */
  int jobFailureCount(IdType moleQueueId) const
  {
    return m_failureTracker.value(moleQueueId, 0);
  }

  /**
   * @brief replaceKeywords Replace $$keywords$$ in @a launchScript
   * with queue/job specific values.
   * @param launchScript Launch script to complete.
   * @param job Job data to use.
   */
  virtual void replaceKeywords(QString & launchScript,
                               const Job &job,
                               bool addNewline = true);

  /// For queue creation
  friend class MoleQueue::QueueManager;

signals:
  /**
   * Emitted when a new program is added to the Queue.
   * @param name Name of the program.
   * @param program Pointer to the newly added Program object.
   */
  void programAdded(const QString &name, MoleQueue::Program *program);

  /**
   * Emitted when a program is removed from the queue.
   * @param name Name of the program
   * @param program Pointer to the removed Program object.
   * @warning The @program pointer should not be dereferenced, as this signal
   * is often associated with program deletion.
   */
  void programRemoved(const QString &name, MoleQueue::Program *program);

  /**
   * @brief programRenamed Emitted when a program is renamed.
   */
  void programRenamed(const QString &newName, Program *prog,
                      const QString &oldName);

  /**
   * Emitted when the name of the queue is changed.
   */
  void nameChanged(const QString &newName, const QString &oldName);

public slots:
  /**
   * Writes input files and submits a new job to the queue.
   * @param job Job to submit.
   * @return True on success, false on failure.
   * @sa jobSubmitted
   */
  virtual bool submitJob(MoleQueue::Job job) = 0;

  /**
   * @brief killJob Stop the job and remove from the queue. Set the JobState to
   * Canceled.
   * @param job Job to kill.
   */
  virtual void killJob(MoleQueue::Job job) = 0;

  /**
   * Update the launch script template.
   * @param script The new launch template.
   * @sa launchTemplate
   */
  virtual void setLaunchTemplate(const QString &script)
  {
    m_launchTemplate = script;
  }

  /**
   * Update the launch script name.
   * @param scriptName The new launch script name.
   * @sa launchTemplate
   * @sa launchScript
   */
  virtual void setLaunchScriptName(const QString &scriptName)
  {
    m_launchScriptName = scriptName;
  }

protected slots:
  /**
   * Called when the JobManager::jobAboutToBeRemoved signal is emitted to
   * remove any internal references to the job. Subclasses should reimplement
   * if they hold any state about owned jobs.
   */
  virtual void jobAboutToBeRemoved(const MoleQueue::Job &job);

  /**
   * Update internal data structures when the name of a program changes.
   */
  void programNameChanged(const QString &newName, const QString &oldName);

  /**
   * Delete the local working directory of @a Job.
   */
  void cleanLocalDirectory(const MoleQueue::Job &job);

protected:
  /// Write the input files for @a job to the local working directory.
  bool writeInputFiles(const Job &job);

  /**
   * @brief addJobFailure Call this when a job encounters a problem but will be
   * retried (e.g. a possible networking failure). The failure will be recorded
   * and the return value will indicate whether to retry the job or not. If this
   * function returns true, the job has failed less than 3 times and an attempt
   * should be made to retry. If it returns false, the job has exceeded the
   * maximum number of retries and should be aborted. The failure count will be
   * reset and an error will be logged if the maximum retries are exceeded.
   * @param moleQueueId
   * @return True if the job should be retried, false otherwise.
   * @see jobFailureCount
   * @see clearJobFailures
   */
  bool addJobFailure(IdType moleQueueId);

  /**
   * @brief clearJobFailures Remove all recorded job failures for a job. This
   * does not necessarily mean that the job is successful, but that it is no
   * longer being retried.
   * @param moleQueueId MoleQueue id of job
   * @see addJobFailure
   * @see jobFailureCount
   */
  void clearJobFailures(IdType moleQueueId)
  {
    m_failureTracker.remove(moleQueueId);
  }

  QueueManager *m_queueManager;
  Server *m_server;

  QString m_name;
  QString m_launchTemplate;
  QString m_launchScriptName;
  QMap<QString, Program *> m_programs;
  /// Lookup table for jobs that are using this Queue. Maps JobId to MoleQueueId.
  QMap<IdType, IdType> m_jobs;
  /// Keeps track of the number of times a job has failed (MoleQueueId to
  /// #failures). Once a job fails three times, it will no longer retry.
  QMap<IdType, int> m_failureTracker;

private:
  /// Private helper function
  bool writeJsonSettingsToFile(const QString &filename, bool exportOnly,
                               bool includePrograms) const;
  /// Private helper function
  bool readJsonSettingsFromFile(const QString &filename, bool importOnly,
                                bool includePrograms);
};

} // End namespace

Q_DECLARE_METATYPE(MoleQueue::Queue*)
Q_DECLARE_METATYPE(const MoleQueue::Queue*)

#endif // MOLEQUEUE_QUEUE_H