00001 #ifndef JOBQUEUE_H_
00002 #define JOBQUEUE_H_
00003
00004 #include <sys/types.h>
00005
00006 #include <QWaitCondition>
00007 #include <QDateTime>
00008 #include <QRunnable>
00009 #include <QObject>
00010 #include <QEvent>
00011 #include <QMutex>
00012 #include <QMap>
00013
00014 #include "mythtvexp.h"
00015
00016 class MThread;
00017 class ProgramInfo;
00018 class RecordingInfo;
00019
00020 using namespace std;
00021
00022
00023 #define JOBSTATUS_MAP(F) \
00024 F(JOB_UNKNOWN, 0x0000, QObject::tr("Unknown")) \
00025 F(JOB_QUEUED, 0x0001, QObject::tr("Queued")) \
00026 F(JOB_PENDING, 0x0002, QObject::tr("Pending")) \
00027 F(JOB_STARTING, 0x0003, QObject::tr("Starting")) \
00028 F(JOB_RUNNING, 0x0004, QObject::tr("Running")) \
00029 F(JOB_STOPPING, 0x0005, QObject::tr("Stopping")) \
00030 F(JOB_PAUSED, 0x0006, QObject::tr("Paused")) \
00031 F(JOB_RETRY, 0x0007, QObject::tr("Retrying")) \
00032 F(JOB_ERRORING, 0x0008, QObject::tr("Erroring")) \
00033 F(JOB_ABORTING, 0x0009, QObject::tr("Aborting")) \
00034
00035
00036
00037 \
00038 F(JOB_DONE, 0x0100, QObject::tr("Done (Invalid status!)")) \
00039 F(JOB_FINISHED, 0x0110, QObject::tr("Finished")) \
00040 F(JOB_ABORTED, 0x0120, QObject::tr("Aborted")) \
00041 F(JOB_ERRORED, 0x0130, QObject::tr("Errored")) \
00042 F(JOB_CANCELLED, 0x0140, QObject::tr("Cancelled")) \
00043
00044 enum JobStatus {
00045 #define JOBSTATUS_ENUM(A,B,C) A = B ,
00046 JOBSTATUS_MAP(JOBSTATUS_ENUM)
00047 };
00048
00049 enum JobCmds {
00050 JOB_RUN = 0x0000,
00051 JOB_PAUSE = 0x0001,
00052 JOB_RESUME = 0x0002,
00053 JOB_STOP = 0x0004,
00054 JOB_RESTART = 0x0008
00055 };
00056
00057 enum JobFlags {
00058 JOB_NO_FLAGS = 0x0000,
00059 JOB_USE_CUTLIST = 0x0001,
00060 JOB_LIVE_REC = 0x0002,
00061 JOB_EXTERNAL = 0x0004,
00062 JOB_REBUILD = 0x0008
00063 };
00064
00065 enum JobLists {
00066 JOB_LIST_ALL = 0x0001,
00067 JOB_LIST_DONE = 0x0002,
00068 JOB_LIST_NOT_DONE = 0x0004,
00069 JOB_LIST_ERROR = 0x0008,
00070 JOB_LIST_RECENT = 0x0010
00071 };
00072
00073 enum JobTypes {
00074 JOB_NONE = 0x0000,
00075
00076 JOB_SYSTEMJOB = 0x00ff,
00077 JOB_TRANSCODE = 0x0001,
00078 JOB_COMMFLAG = 0x0002,
00079 JOB_METADATA = 0x0004,
00080
00081 JOB_USERJOB = 0xff00,
00082 JOB_USERJOB1 = 0x0100,
00083 JOB_USERJOB2 = 0x0200,
00084 JOB_USERJOB3 = 0x0400,
00085 JOB_USERJOB4 = 0x0800
00086 };
00087
00088 typedef struct jobqueueentry {
00089 int id;
00090 uint chanid;
00091 QDateTime recstartts;
00092 QDateTime schedruntime;
00093 QString startts;
00094 QDateTime inserttime;
00095 int type;
00096 int cmds;
00097 int flags;
00098 int status;
00099 QDateTime statustime;
00100 QString hostname;
00101 QString args;
00102 QString comment;
00103 } JobQueueEntry;
00104
00105 typedef struct runningjobinfo {
00106 int id;
00107 int type;
00108 int flag;
00109 QString desc;
00110 QString command;
00111 ProgramInfo *pginfo;
00112 } RunningJobInfo;
00113
00114 class JobQueue;
00115
00116 class MTV_PUBLIC JobQueue : public QObject, public QRunnable
00117 {
00118 Q_OBJECT
00119
00120 friend class QueueProcessorThread;
00121 public:
00122 JobQueue(bool master);
00123 ~JobQueue(void);
00124 void customEvent(QEvent *e);
00125
00126 static bool QueueRecordingJobs(
00127 const RecordingInfo&, int jobTypes = JOB_NONE);
00128 static bool QueueJob(int jobType, uint chanid,
00129 const QDateTime &recstartts, QString args = "",
00130 QString comment = "", QString host = "",
00131 int flags = 0, int status = JOB_QUEUED,
00132 QDateTime schedruntime = QDateTime());
00133
00134 static bool QueueJobs(int jobTypes, uint chanid,
00135 const QDateTime &recstartts, QString args = "",
00136 QString comment = "", QString host = "");
00137
00138 static int GetJobID(int jobType, uint chanid,
00139 const QDateTime &recstartts);
00140 static bool GetJobInfoFromID(int jobID, int &jobType,
00141 uint &chanid, QDateTime &recstartts);
00142 static bool GetJobInfoFromID(int jobID, int &jobType,
00143 uint &chanid, QString &recstartts);
00144
00145 static bool ChangeJobCmds(int jobID, int newCmds);
00146 static bool ChangeJobCmds(int jobType, uint chanid,
00147 const QDateTime &recstartts, int newCmds);
00148 static bool ChangeJobFlags(int jobID, int newFlags);
00149 static bool ChangeJobStatus(int jobID, int newStatus,
00150 QString comment = "");
00151 static bool ChangeJobHost(int jobID, QString newHostname);
00152 static bool ChangeJobComment(int jobID,
00153 QString comment = "");
00154 static bool ChangeJobArgs(int jobID,
00155 QString args = "");
00156 static bool IsJobQueuedOrRunning(int jobType, uint chanid,
00157 const QDateTime &recstartts);
00158 int GetRunningJobID(uint chanid, const QDateTime &recstartts);
00159 static bool IsJobRunning(int jobType, uint chanid,
00160 const QDateTime &recstartts);
00161 static bool IsJobRunning(int jobType, const ProgramInfo &pginfo);
00162 static bool IsJobQueued(int jobType,
00163 uint chanid, const QDateTime &recstartts);
00164 static bool PauseJob(int jobID);
00165 static bool ResumeJob(int jobID);
00166 static bool RestartJob(int jobID);
00167 static bool StopJob(int jobID);
00168 static bool DeleteJob(int jobID);
00169
00170 static enum JobCmds GetJobCmd(int jobID);
00171 static enum JobFlags GetJobFlags(int jobID);
00172 static enum JobStatus GetJobStatus(int jobID);
00173 static enum JobStatus GetJobStatus(int jobType, uint chanid,
00174 const QDateTime &recstartts);
00175 static QString GetJobArgs(int jobID);
00176 static int UserJobTypeToIndex(int JobType);
00177
00178 static bool DeleteAllJobs(uint chanid, const QDateTime &recstartts);
00179
00180 static void ClearJobMask(int &mask) { mask = JOB_NONE; }
00181 static bool JobIsInMask(int job, int mask) { return (bool)(job & mask); }
00182 static bool JobIsNotInMask(int job, int mask)
00183 { return ! JobIsInMask(job, mask); }
00184 static void AddJobsToMask(int jobs, int &mask) { mask |= jobs; }
00185 static void RemoveJobsFromMask(int jobs, int &mask) { mask &= ~jobs; }
00186
00187 static QString JobText(int jobType);
00188 static QString StatusText(int status);
00189
00190 static bool HasRunningOrPendingJobs(int startingWithinMins = 0);
00191
00192 static int GetJobsInQueue(QMap<int, JobQueueEntry> &jobs,
00193 int findJobs = JOB_LIST_NOT_DONE);
00194
00195 static void RecoverQueue(bool justOld = false);
00196 static void RecoverOldJobsInQueue()
00197 { RecoverQueue(true); }
00198 static void CleanupOldJobsInQueue();
00199
00200 private:
00201 typedef struct jobthreadstruct
00202 {
00203 JobQueue *jq;
00204 int jobID;
00205 } JobThreadStruct;
00206
00207 void run(void);
00208 void ProcessQueue(void);
00209
00210 void ProcessJob(JobQueueEntry job);
00211
00212 bool AllowedToRun(JobQueueEntry job);
00213
00214 static bool InJobRunWindow(int orStartingWithinMins = 0);
00215
00216 void StartChildJob(void *(*start_routine)(void *), int jobID);
00217
00218 QString GetJobDescription(int jobType);
00219 QString GetJobCommand(int id, int jobType, ProgramInfo *tmpInfo);
00220 void RemoveRunningJob(int id);
00221
00222 static QString PrettyPrint(off_t bytes);
00223
00224 static void *TranscodeThread(void *param);
00225 void DoTranscodeThread(int jobID);
00226
00227 static void *MetadataLookupThread(void *param);
00228 void DoMetadataLookupThread(int jobID);
00229
00230 static void *FlagCommercialsThread(void *param);
00231 void DoFlagCommercialsThread(int jobID);
00232
00233 static void *UserJobThread(void *param);
00234 void DoUserJobThread(int jobID);
00235
00236 QString m_hostname;
00237
00238 int jobsRunning;
00239 int jobQueueCPU;
00240
00241 ProgramInfo *m_pginfo;
00242
00243 QMutex controlFlagsLock;
00244 QMap<QString, int *> jobControlFlags;
00245
00246 QMutex *runningJobsLock;
00247 QMap<int, RunningJobInfo> runningJobs;
00248
00249 bool isMaster;
00250
00251 MThread *queueThread;
00252 QWaitCondition queueThreadCond;
00253 QMutex queueThreadCondLock;
00254 bool processQueue;
00255 };
00256
00257 #endif
00258
00259