15 #include <QCoreApplication>
17 #include "mythconfig.h"
44 #define LOC QString("JobQueue: ")
51 runningJobsLock(new QMutex(QMutex::Recursive)),
53 queueThread(new
MThread(
"JobQueue", this)),
58 #ifndef USING_VALGRIND
63 LOG(VB_GENERAL, LOG_ERR,
LOC +
64 "The JobQueue has been disabled because "
65 "you compiled with the --enable-valgrind option.");
66 #endif // USING_VALGRIND
92 QString message = me->
Message();
94 if (message.startsWith(
"LOCAL_JOB"))
99 message = message.simplified();
100 QStringList tokens = message.split(
" ", QString::SkipEmptyParts);
101 QString
action = tokens[1];
104 if (tokens[2] ==
"ID")
105 jobID = tokens[3].toInt();
117 msg = QString(
"Unable to determine jobID for message: "
118 "%1. Program will not be flagged.")
120 LOG(VB_GENERAL, LOG_ERR,
LOC + msg);
126 msg = QString(
"Received message '%1'").arg(message);
127 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + msg);
129 if ((action ==
"STOP") ||
130 (action ==
"PAUSE") ||
131 (action ==
"RESTART") ||
132 (action ==
"RESUME" ))
136 if (action ==
"STOP")
138 else if (action ==
"PAUSE")
140 else if (action ==
"RESUME")
142 else if (action ==
"RESTART")
168 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
"ProcessQueue() started");
178 QMap<int, int> jobStatus;
181 QMap<int, JobQueueEntry> jobs;
183 bool inTimeWindow =
true;
184 bool startedJobAlready =
false;
185 QMap<int, RunningJobInfo>::Iterator rjiter;
192 startedJobAlready =
false;
195 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
196 QString(
"Currently set to run up to %1 job(s) max.")
205 if ((*rjiter).pginfo)
206 (*rjiter).pginfo->UpdateInUseMark();
216 for (
int x = 0;
x < jobs.size();
x++)
218 status = jobs[
x].status;
219 hostname = jobs[
x].hostname;
221 if (((status == JOB_RUNNING) ||
222 (status == JOB_STARTING) ||
223 (status == JOB_PAUSED)) &&
228 message = QString(
"Currently Running %1 jobs.")
232 message += QString(
" Jobs in Queue, but we are outside of the "
233 "Job Queue time window, no new jobs can be "
235 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
239 message +=
" (At Maximum, no new jobs can be started until "
240 "a running job completes)";
243 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
249 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
260 status = jobs[
x].status;
261 hostname = jobs[
x].hostname;
264 logInfo = QString(
"jobID #%1").arg(jobID);
266 logInfo = QString(
"chanid %1 @ %2").arg(jobs[
x].chanid)
267 .arg(jobs[
x].startts);
270 if ((inTimeWindow) &&
271 (!hostname.isEmpty()) &&
277 jobStatus[
jobID] = status;
279 message = QString(
"Skipping '%1' job for %2, "
280 "should run on '%3' instead")
283 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
292 if (otherJobID && (jobStatus.contains(otherJobID)) &&
293 (!(jobStatus[otherJobID] & JOB_DONE)))
296 QString(
"Skipping '%1' job for %2, "
297 "Job ID %3 is already running for "
298 "this recording with a status of '%4'")
302 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
307 jobStatus[
jobID] = status;
312 message = QString(
"Skipping '%1' job for %2, "
313 "not allowed to run on this backend.")
315 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
322 message = QString(
"Skipping '%1' job for %2, this job is "
323 "not scheduled to run until %3.")
325 .arg(jobs[x].schedruntime
327 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
335 if (status != JOB_QUEUED) {
336 message = QString(
"Stopping '%1' job for %2")
339 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
353 message = QString(
"Cancelling '%1' job for %2")
356 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
364 message = QString(
"Unable to claim '%1' job for %2")
367 LOG(VB_JOBQUEUE, LOG_ERR,
LOC + message);
377 if ((cmds &
JOB_PAUSE) && (status != JOB_QUEUED))
379 message = QString(
"Pausing '%1' job for %2")
381 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
392 if ((cmds &
JOB_RESTART) && (status != JOB_QUEUED))
394 message = QString(
"Restart '%1' job for %2")
396 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
407 if (status != JOB_QUEUED)
410 if (hostname.isEmpty())
412 message = QString(
"Resetting '%1' job for %2 to %3 "
413 "status, because no hostname is set.")
417 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
422 else if (inTimeWindow)
424 message = QString(
"Skipping '%1' job for %2, "
425 "current job status is '%3'")
429 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
435 if (startedJobAlready)
438 if ((inTimeWindow) &&
439 (hostname.isEmpty()) &&
442 message = QString(
"Unable to claim '%1' job for %2")
444 LOG(VB_JOBQUEUE, LOG_ERR,
LOC + message);
450 message = QString(
"Skipping '%1' job for %2, "
451 "current time is outside of the "
452 "Job Queue processing window.")
454 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
458 message = QString(
"Processing '%1' job for %2, "
459 "current status is '%3'")
462 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
466 startedJobAlready =
true;
470 if (QCoreApplication::applicationName() == MYTH_APPNAME_MYTHJOBQUEUE)
477 LOG(VB_JOBQUEUE, LOG_INFO, QString(
"%1 jobs running. "
486 LOG(VB_JOBQUEUE, LOG_INFO,
"No jobs running. "
487 "Allowing shutdown.");
496 int st = (startedJobAlready) ? (5 * 1000) : (sleepTime * 1000);
513 QString jobHost = QString(
"");
529 QString args, QString comment, QString host,
530 int flags,
int status, QDateTime schedruntime)
532 int tmpStatus = JOB_UNKNOWN;
533 int tmpCmd = JOB_UNKNOWN;
537 if(!schedruntime.isValid())
545 query.
prepare(
"SELECT status, id, cmds FROM jobqueue "
546 "WHERE chanid = :CHANID AND starttime = :STARTTIME "
547 "AND type = :JOBTYPE;");
549 query.
bindValue(
":STARTTIME", recstartts);
561 tmpStatus = query.
value(0).toInt();
562 jobID = query.
value(1).toInt();
563 tmpCmd = query.
value(2).toInt();
581 if (! (tmpStatus & JOB_DONE) && (tmpCmd &
JOB_STOP))
590 query.
prepare(
"INSERT INTO jobqueue (chanid, starttime, inserttime, type, "
591 "status, statustime, schedruntime, hostname, args, comment, "
593 "VALUES (:CHANID, :STARTTIME, now(), :JOBTYPE, :STATUS, "
594 "now(), :SCHEDRUNTIME, :HOST, :ARGS, :COMMENT, :FLAGS);");
597 query.
bindValue(
":STARTTIME", recstartts);
600 query.
bindValue(
":SCHEDRUNTIME", schedruntime);
616 QString args, QString comment, QString host)
621 QueueJob(JOB_METADATA, chanid, recstartts, args, comment, host);
623 QueueJob(JOB_TRANSCODE, chanid, recstartts, args, comment, host);
625 QueueJob(JOB_COMMFLAG, chanid, recstartts, args, comment, host);
630 QueueJob(JOB_METADATA, chanid, recstartts, args, comment, host);
632 QueueJob(JOB_COMMFLAG, chanid, recstartts, args, comment, host);
640 schedruntime = QDateTime(schedruntime.addDays(defer).date(),
641 QTime(0,0,0), Qt::UTC);
644 QueueJob(JOB_TRANSCODE, chanid, recstartts, args, comment, host,
645 0, JOB_QUEUED, schedruntime);
650 QueueJob(JOB_USERJOB1, chanid, recstartts, args, comment, host);
652 QueueJob(JOB_USERJOB2, chanid, recstartts, args, comment, host);
654 QueueJob(JOB_USERJOB3, chanid, recstartts, args, comment, host);
656 QueueJob(JOB_USERJOB4, chanid, recstartts, args, comment, host);
665 query.
prepare(
"SELECT id FROM jobqueue "
666 "WHERE chanid = :CHANID AND starttime = :STARTTIME "
667 "AND type = :JOBTYPE;");
669 query.
bindValue(
":STARTTIME", recstartts);
680 return query.
value(0).toInt();
687 int jobID,
int &jobType,
uint &chanid, QDateTime &recstartts)
691 query.
prepare(
"SELECT type, chanid, starttime FROM jobqueue "
705 jobType = query.
value(0).toInt();
706 chanid = query.
value(1).toUInt();
716 int jobID,
int &jobType,
uint &chanid, QString &recstartts)
718 QDateTime tmpStarttime;
721 jobID, jobType, chanid, tmpStarttime);
731 QString message = QString(
"GLOBAL_JOB PAUSE ID %1").arg(jobID);
740 QString message = QString(
"GLOBAL_JOB RESUME ID %1").arg(jobID);
749 QString message = QString(
"GLOBAL_JOB RESTART ID %1").arg(jobID);
758 QString message = QString(
"GLOBAL_JOB STOP ID %1").arg(jobID);
770 query.
prepare(
"UPDATE jobqueue SET status = :CANCELLED "
771 "WHERE chanid = :CHANID AND starttime = :STARTTIME "
772 "AND status = :QUEUED;");
774 query.
bindValue(
":CANCELLED", JOB_CANCELLED);
776 query.
bindValue(
":STARTTIME", recstartts);
782 query.
prepare(
"UPDATE jobqueue SET cmds = :CMD "
783 "WHERE chanid = :CHANID AND starttime = :STARTTIME "
784 "AND status <> :CANCELLED;");
787 query.
bindValue(
":STARTTIME", recstartts);
788 query.
bindValue(
":CANCELLED", JOB_CANCELLED);
797 bool jobsAreRunning =
true;
800 while (jobsAreRunning && totalSlept < maxSleep)
803 query.
prepare(
"SELECT id FROM jobqueue "
804 "WHERE chanid = :CHANID and starttime = :STARTTIME "
806 "(:FINISHED,:ABORTED,:ERRORED,:CANCELLED);");
808 query.
bindValue(
":STARTTIME", recstartts);
809 query.
bindValue(
":FINISHED", JOB_FINISHED);
810 query.
bindValue(
":ABORTED", JOB_ABORTED);
811 query.
bindValue(
":ERRORED", JOB_ERRORED);
812 query.
bindValue(
":CANCELLED", JOB_CANCELLED);
820 if (query.
size() == 0)
822 jobsAreRunning =
false;
825 else if ((totalSlept % 5) == 0)
827 message = QString(
"Waiting on %1 jobs still running for "
828 "chanid %2 @ %3").arg(query.
size())
829 .arg(chanid).arg(recstartts.toString(
Qt::ISODate));
830 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + message);
837 if (totalSlept <= maxSleep)
839 query.
prepare(
"DELETE FROM jobqueue "
840 "WHERE chanid = :CHANID AND starttime = :STARTTIME;");
842 query.
bindValue(
":STARTTIME", recstartts);
849 query.
prepare(
"SELECT id, type, status, comment FROM jobqueue "
850 "WHERE chanid = :CHANID AND starttime = :STARTTIME "
851 "AND status <> :CANCELLED ORDER BY id;");
854 query.
bindValue(
":STARTTIME", recstartts);
855 query.
bindValue(
":CANCELLED", JOB_CANCELLED);
860 "to query list of Jobs left in Queue.", query);
864 LOG(VB_GENERAL, LOG_ERR,
LOC +
865 QString(
"In DeleteAllJobs: There are Jobs "
866 "left in the JobQueue that are still running for "
867 "chanid %1 @ %2.").arg(chanid)
872 LOG(VB_GENERAL, LOG_ERR,
LOC +
873 QString(
"Job ID %1: '%2' with status '%3' and comment '%4'")
874 .arg(query.
value(0).toInt())
877 .arg(query.
value(3).toString()));
893 query.
prepare(
"DELETE FROM jobqueue WHERE id = :ID;");
913 query.
prepare(
"UPDATE jobqueue SET cmds = :CMDS WHERE id = :ID;");
928 const QDateTime &recstartts,
int newCmds)
932 query.
prepare(
"UPDATE jobqueue SET cmds = :CMDS WHERE type = :TYPE "
933 "AND chanid = :CHANID AND starttime = :STARTTIME;");
938 query.
bindValue(
":STARTTIME", recstartts);
956 query.
prepare(
"UPDATE jobqueue SET flags = :FLAGS WHERE id = :ID;");
975 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + QString(
"ChangeJobStatus(%1, %2, '%3')")
976 .arg(jobID).arg(
StatusText(newStatus)).arg(comment));
980 query.
prepare(
"UPDATE jobqueue SET status = :STATUS, comment = :COMMENT "
981 "WHERE id = :ID AND status <> :NEWSTATUS;");
986 query.
bindValue(
":NEWSTATUS", newStatus);
1002 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + QString(
"ChangeJobComment(%1, '%2')")
1003 .arg(jobID).arg(comment));
1007 query.
prepare(
"UPDATE jobqueue SET comment = :COMMENT "
1029 query.
prepare(
"UPDATE jobqueue SET args = :ARGS "
1047 QMap<int, RunningJobInfo>::iterator it =
runningJobs.begin();
1066 uint chanid,
const QDateTime &recstartts)
1068 int tmpStatus =
GetJobStatus(jobType, chanid, recstartts);
1070 if ((tmpStatus != JOB_UNKNOWN) && (tmpStatus != JOB_QUEUED) &&
1071 (!(tmpStatus & JOB_DONE)))
1084 int jobType,
uint chanid,
const QDateTime &recstartts)
1086 int tmpStatus =
GetJobStatus(jobType, chanid, recstartts);
1088 if ((tmpStatus != JOB_UNKNOWN) && (!(tmpStatus & JOB_DONE)))
1095 int jobType,
uint chanid,
const QDateTime &recstartts)
1097 int tmpStatus =
GetJobStatus(jobType, chanid, recstartts);
1099 if (tmpStatus & JOB_QUEUED)
1116 QString settingName =
1121 return tr(
"Unknown Job");
1128 #define JOBSTATUS_STATUSTEXT(A,B,C) case A: return C;
1132 return tr(
"Undefined");
1137 QString queueStartTimeStr;
1138 QString queueEndTimeStr;
1139 QTime queueStartTime;
1141 QTime curTime = QTime::currentTime();
1142 bool inTimeWindow =
false;
1143 orStartsWithinMins = orStartsWithinMins < 0 ? 0 : orStartsWithinMins;
1149 if (!queueStartTime.isValid())
1151 LOG(VB_GENERAL, LOG_ERR,
1152 QString(
"Invalid JobQueueWindowStart time '%1', using 00:00")
1153 .arg(queueStartTimeStr));
1154 queueStartTime = QTime(0, 0);
1158 if (!queueEndTime.isValid())
1160 LOG(VB_GENERAL, LOG_ERR,
1161 QString(
"Invalid JobQueueWindowEnd time '%1', using 23:59")
1162 .arg(queueEndTimeStr));
1163 queueEndTime = QTime(23, 59);
1166 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1167 QString(
"Currently set to run new jobs from %1 to %2")
1168 .arg(queueStartTimeStr).arg(queueEndTimeStr));
1170 if ((queueStartTime <= curTime) && (curTime < queueEndTime))
1172 inTimeWindow =
true;
1174 else if ((queueStartTime > queueEndTime) &&
1175 ((curTime < queueEndTime) || (queueStartTime <= curTime)))
1177 inTimeWindow =
true;
1179 else if (orStartsWithinMins > 0)
1182 if (curTime <= queueStartTime)
1185 if (queueStartTime.secsTo(curTime) <= (orStartsWithinMins * 60))
1187 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1188 QString(
"Job run window will start within %1 minutes")
1189 .arg(orStartsWithinMins));
1190 inTimeWindow =
true;
1197 QDateTime startDateTime = QDateTime(
1198 curDateTime.date(), queueStartTime, Qt::UTC).addDays(1);
1200 if (curDateTime.secsTo(startDateTime) <= (orStartsWithinMins * 60))
1202 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1203 QString(
"Job run window will start "
1204 "within %1 minutes (tomorrow)")
1205 .arg(orStartsWithinMins));
1206 inTimeWindow =
true;
1211 return inTimeWindow;
1218 QMap<int, JobQueueEntry> jobs;
1219 QMap<int, JobQueueEntry>::Iterator it;
1222 bool checkForQueuedJobs = (startingWithinMins <= 0
1225 if (checkForQueuedJobs && startingWithinMins > 0) {
1226 maxSchedRunTime = maxSchedRunTime.addSecs(startingWithinMins * 60);
1227 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1228 QString(
"HasRunningOrPendingJobs: checking for jobs "
1229 "starting before: %1")
1236 for (it = jobs.begin(); it != jobs.end(); ++it)
1238 tmpStatus = (*it).status;
1239 if (tmpStatus == JOB_RUNNING) {
1240 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1241 QString(
"HasRunningOrPendingJobs: found running job"));
1245 if (checkForQueuedJobs) {
1246 if ((tmpStatus != JOB_UNKNOWN) && (!(tmpStatus & JOB_DONE))) {
1247 if (startingWithinMins <= 0) {
1248 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1249 "HasRunningOrPendingJobs: found pending job");
1252 else if ((*it).schedruntime <= maxSchedRunTime) {
1253 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1254 QString(
"HasRunningOrPendingJobs: found pending "
1255 "job scheduled to start at: %1")
1274 bool commflagWhileRecording =
1279 query.
prepare(
"SELECT j.id, j.chanid, j.starttime, j.inserttime, j.type, "
1280 "j.cmds, j.flags, j.status, j.statustime, j.hostname, "
1281 "j.args, j.comment, r.endtime, j.schedruntime "
1283 "LEFT JOIN recorded r "
1284 " ON j.chanid = r.chanid AND j.starttime = r.starttime "
1285 "ORDER BY j.schedruntime, j.id;");
1290 "query list of Jobs in Queue.", query);
1294 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1295 QString(
"GetJobsInQueue: findJobs search bitmask %1, "
1296 "found %2 total jobs")
1297 .arg(findJobs).arg(query.
size()));
1299 while (query.
next())
1301 bool wantThisJob =
false;
1303 thisJob.
id = query.
value(0).toInt();
1313 if (query.
value(1).toInt() == -1)
1316 logInfo = QString(
"jobID #%1").arg(thisJob.
id);
1321 logInfo = QString(
"chanid %1 @ %2").arg(thisJob.
chanid)
1326 ((!commflagWhileRecording) ||
1330 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1331 QString(
"GetJobsInQueue: Ignoring '%1' Job "
1332 "for %2 in %3 state. Endtime in future.")
1340 (thisJob.
status & JOB_DONE)) ||
1342 (!(thisJob.
status & JOB_DONE))) ||
1344 (thisJob.
status == JOB_ERRORED)) ||
1351 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1352 QString(
"GetJobsInQueue: Ignore '%1' Job for %2 in %3 state.")
1358 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1359 QString(
"GetJobsInQueue: Found '%1' Job for %2 in %3 state.")
1367 thisJob.
args = query.
value(10).toString();
1374 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
1375 QString(
"GetJobsInQueue: Unknown Job Type: %1")
1376 .arg(thisJob.
type));
1380 jobs[jobCount++] = thisJob;
1390 if (!newHostname.isEmpty())
1392 query.
prepare(
"UPDATE jobqueue SET hostname = :NEWHOSTNAME "
1393 "WHERE hostname = :EMPTY AND id = :ID;");
1394 query.
bindValue(
":NEWHOSTNAME", newHostname);
1400 query.
prepare(
"UPDATE jobqueue SET hostname = :EMPTY "
1409 "Unable to set hostname to '%1' for "
1410 "job %2.").arg(newHostname).arg(jobID),
1423 QString allowSetting;
1444 default:
return false;
1458 query.
prepare(
"SELECT cmds FROM jobqueue WHERE id = :ID;");
1479 query.
prepare(
"SELECT args FROM jobqueue WHERE id = :ID;");
1486 return query.
value(0).toString();
1500 query.
prepare(
"SELECT flags FROM jobqueue WHERE id = :ID;");
1521 query.
prepare(
"SELECT status FROM jobqueue WHERE id = :ID;");
1538 int jobType,
uint chanid,
const QDateTime &recstartts)
1542 query.
prepare(
"SELECT status FROM jobqueue WHERE type = :TYPE "
1543 "AND chanid = :CHANID AND starttime = :STARTTIME;");
1547 query.
bindValue(
":STARTTIME", recstartts);
1563 QMap<int, JobQueueEntry> jobs;
1567 msg = QString(
"RecoverQueue: Checking for unfinished jobs to "
1569 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + msg);
1575 QMap<int, JobQueueEntry>::Iterator it;
1581 for (it = jobs.begin(); it != jobs.end(); ++it)
1583 tmpCmds = (*it).cmds;
1584 tmpStatus = (*it).status;
1587 logInfo = QString(
"jobID #%1").arg((*it).id);
1589 logInfo = QString(
"chanid %1 @ %2").arg((*it).chanid)
1590 .arg((*it).startts);
1592 if (((tmpStatus == JOB_STARTING) ||
1593 (tmpStatus == JOB_RUNNING) ||
1594 (tmpStatus == JOB_PAUSED) ||
1596 (tmpStatus == JOB_STOPPING)) &&
1598 ((*it).hostname == hostname)) ||
1599 ((*it).statustime < oldDate)))
1601 msg = QString(
"RecoverQueue: Recovering '%1' for %2 "
1605 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + msg);
1615 msg = QString(
"RecoverQueue: Ignoring '%1' for %2 "
1619 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + msg);
1632 delquery.
prepare(
"DELETE FROM jobqueue "
1633 "WHERE (status in (:FINISHED, :ABORTED, :CANCELLED) "
1634 "AND statustime < :DONEPURGEDATE) "
1635 "OR (status in (:ERRORED) "
1636 "AND statustime < :ERRORSPURGEDATE) ");
1637 delquery.
bindValue(
":FINISHED", JOB_FINISHED);
1638 delquery.
bindValue(
":ABORTED", JOB_ABORTED);
1639 delquery.
bindValue(
":CANCELLED", JOB_CANCELLED);
1640 delquery.
bindValue(
":ERRORED", JOB_ERRORED);
1641 delquery.
bindValue(
":DONEPURGEDATE", donePurgeDate);
1642 delquery.
bindValue(
":ERRORSPURGEDATE", errorsPurgeDate);
1644 if (!delquery.
exec())
1647 "old finished jobs.", delquery);
1654 QString
name = QString(
"jobqueue%1%2").arg(jobID).arg(
random());
1658 LOG(VB_JOBQUEUE, LOG_ERR,
LOC +
1659 "ProcessJob(): Unable to open database connection");
1672 LOG(VB_JOBQUEUE, LOG_ERR,
LOC +
1673 QString(
"Unable to retrieve program info for chanid %1 @ %2")
1678 tr(
"Unable to retrieve program info from database"));
1708 tr(
"Program has been deleted"));
1722 (
runningJobs[jobID].command ==
"mythmetadatalookup"))
1733 tr(
"UNKNOWN JobType, unable to process!"));
1746 pthread_t childThread;
1747 pthread_attr_t attr;
1748 pthread_attr_init(&attr);
1749 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1750 pthread_create(&childThread, &attr, ChildThreadRoutine, jts);
1751 pthread_attr_destroy(&attr);
1759 return "Commercial Detection";
1761 return "Unknown Job";
1763 QString descSetting =
1777 if (command.trimmed().isEmpty())
1778 command =
"mythtranscode";
1780 if (command ==
"mythtranscode")
1786 if (command.trimmed().isEmpty())
1787 command =
"mythcommflag";
1789 if (command ==
"mythcommflag")
1798 if (!command.isEmpty())
1800 command.replace(
"%JOBID%", QString(
"%1").arg(
id));
1803 if (!command.isEmpty() && tmpInfo)
1807 command.replace(
"%VERBOSELEVEL%", QString(
"%1").arg(
verboseMask));
1811 command.replace(
"%TRANSPROFILE%",
1813 "autodetect" : QString::number(transcoder));
1842 static const struct {
1847 {
"bytes", 9999, 0 },
1858 float fbytes = bytes;
1861 while (pptab[ii].max && fbytes > pptab[ii].max) {
1866 return QString(
"%1 %2")
1867 .arg(fbytes, 0,
'f', pptab[ii].precision)
1868 .arg(pptab[ii].suffix);
1891 LOG(VB_JOBQUEUE, LOG_ERR,
LOC +
1892 "The JobQueue cannot currently transcode files that do not "
1893 "have a chanid/starttime in the recorded table.");
1908 bool useCutlist = program_info->
HasCutlist() &&
1912 QString profilearg =
1914 "autodetect" : QString::number(transcoder);
1920 if (
runningJobs[jobID].command ==
"mythtranscode")
1923 command = QString(
"%1 -j %2 --profile %3")
1924 .arg(path).arg(jobID).arg(profilearg);
1926 command +=
" --honorcutlist";
1933 QStringList tokens = command.split(
" ", QString::SkipEmptyParts);
1934 if (!tokens.empty())
1945 QString transcoderName;
1948 transcoderName =
"Autodetect";
1953 query.
prepare(
"SELECT name FROM recordingprofiles WHERE id = :ID;");
1957 transcoderName = query.
value(0).toString();
1962 transcoderName = QString(
"Autodetect(%1)").arg(transcoder);
1978 long long filesize = 0;
1979 long long origfilesize = QFileInfo(filename).size();
1981 QString msg = QString(
"Transcode %1")
1984 QString detailstr = QString(
"%1: %2 (%3)")
1986 .arg(transcoderName)
1988 QByteArray details = detailstr.toLocal8Bit();
1990 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"%1 for %2")
1991 .arg(msg).arg(details.constData()));
1993 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + QString(
"Running command: '%1'")
1996 GetMythDB()->GetDBManager()->CloseDatabases();
2000 if ((result == GENERIC_EXIT_DAEMONIZING_ERROR) ||
2001 (result == GENERIC_EXIT_CMD_NOT_FOUND))
2004 tr(
"ERROR: Unable to find mythtranscode, check backend logs."));
2008 detailstr = QString(
"%1: %2 does not exist or is not executable")
2011 details = detailstr.toLocal8Bit();
2013 LOG(VB_GENERAL, LOG_ERR,
LOC +
2014 QString(
"%1 for %2").arg(msg).arg(details.constData()));
2016 else if (result == GENERIC_EXIT_RESTART && retrylimit > 0)
2018 LOG(VB_JOBQUEUE, LOG_INFO,
LOC +
"Transcode command restarting");
2026 if (status == JOB_FINISHED)
2032 QFileInfo st(filename);
2036 filesize = st.size();
2039 QString comment = tr(
"%1: %2 => %3")
2040 .arg(transcoderName)
2048 details = (QString(
"%1: %2 (%3)")
2051 .arg(transcoderName)
2057 QString(
"could not stat '%1'").arg(filename);
2061 details = (QString(
"%1: %2")
2064 .arg(comment)).toLocal8Bit();
2073 QString comment = tr(
"exit status %1, job status was \"%2\"")
2079 details = (QString(
"%1: %2 (%3)")
2082 .arg(transcoderName)
2083 .arg(comment)).toLocal8Bit().constData();
2087 LOG(VB_GENERAL, LOG_INFO,
LOC + msg +
": " + details);
2091 if (retrylimit == 0)
2093 LOG(VB_JOBQUEUE, LOG_ERR,
LOC +
"Retry limit exceeded for transcoder, "
2094 "setting job status to errored.");
2121 LOG(VB_JOBQUEUE, LOG_ERR,
LOC +
2122 "The JobQueue cannot currently perform lookups for items which do "
2123 "not have a chanid/starttime in the recorded table.");
2133 QString detailstr = QString(
"%1 recorded from channel %3")
2136 QByteArray details = detailstr.toLocal8Bit();
2140 QString msg = QString(
"Metadata Lookup failed. Could not open "
2141 "new database connection for %1. "
2142 "Program cannot be looked up.")
2143 .arg(details.constData());
2144 LOG(VB_GENERAL, LOG_ERR,
LOC + msg);
2147 tr(
"Could not open new database connection for "
2148 "metadata lookup."));
2150 delete program_info;
2154 QString msg = tr(
"Metadata Lookup Starting");
2155 LOG(VB_GENERAL, LOG_INFO,
2156 LOC +
"Metadata Lookup Starting for " + detailstr);
2163 command = QString(
"%1 -j %2")
2164 .arg(path).arg(jobID);
2167 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + QString(
"Running command: '%1'")
2170 GetMythDB()->GetDBManager()->CloseDatabases();
2172 int priority = LOG_NOTICE;
2177 if ((retVal == GENERIC_EXIT_DAEMONIZING_ERROR) ||
2178 (retVal == GENERIC_EXIT_CMD_NOT_FOUND))
2180 comment = tr(
"Unable to find mythmetadatalookup");
2182 priority = LOG_WARNING;
2186 comment = tr(
"Aborted by user");
2188 priority = LOG_WARNING;
2190 else if (retVal == GENERIC_EXIT_NO_RECORDING_DATA)
2192 comment = tr(
"Unable to open file or init decoder");
2194 priority = LOG_WARNING;
2196 else if (retVal >= GENERIC_EXIT_NOT_OK)
2198 comment = tr(
"Failed with exit status %1").arg(retVal);
2200 priority = LOG_WARNING;
2204 comment = tr(
"Metadata Lookup Complete.");
2210 msg = tr(
"Metadata Lookup %1",
"Job ID")
2213 if (!comment.isEmpty())
2215 detailstr += QString(
" (%1)").arg(comment);
2216 details = detailstr.toLocal8Bit();
2219 if (priority <= LOG_WARNING)
2220 LOG(VB_GENERAL, LOG_ERR,
LOC + msg +
": " + details.constData());
2246 LOG(VB_JOBQUEUE, LOG_ERR,
LOC +
2247 "The JobQueue cannot currently commflag files that do not "
2248 "have a chanid/starttime in the recorded table.");
2258 QString detailstr = QString(
"%1 recorded from channel %3")
2261 QByteArray details = detailstr.toLocal8Bit();
2265 QString msg = QString(
"Commercial Detection failed. Could not open "
2266 "new database connection for %1. "
2267 "Program cannot be flagged.")
2268 .arg(details.constData());
2269 LOG(VB_GENERAL, LOG_ERR,
LOC + msg);
2272 tr(
"Could not open new database connection for "
2273 "commercial detector."));
2275 delete program_info;
2279 QString msg = tr(
"Commercial Detection Starting");
2280 LOG(VB_GENERAL, LOG_INFO,
2281 LOC +
"Commercial Detection Starting for " + detailstr);
2283 uint breaksFound = 0;
2291 command = QString(
"%1 -j %2 --noprogress")
2292 .arg(path).arg(jobID);
2298 QStringList tokens = command.split(
" ", QString::SkipEmptyParts);
2299 if (!tokens.empty())
2304 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + QString(
"Running command: '%1'")
2307 GetMythDB()->GetDBManager()->CloseDatabases();
2309 int priority = LOG_NOTICE;
2314 if ((breaksFound == GENERIC_EXIT_DAEMONIZING_ERROR) ||
2315 (breaksFound == GENERIC_EXIT_CMD_NOT_FOUND))
2317 comment = tr(
"Unable to find mythcommflag");
2319 priority = LOG_WARNING;
2323 comment = tr(
"Aborted by user");
2325 priority = LOG_WARNING;
2327 else if (breaksFound == GENERIC_EXIT_NO_RECORDING_DATA)
2329 comment = tr(
"Unable to open file or init decoder");
2331 priority = LOG_WARNING;
2333 else if (breaksFound >= GENERIC_EXIT_NOT_OK)
2335 comment = tr(
"Failed with exit status %1").arg(breaksFound);
2337 priority = LOG_WARNING;
2341 comment = tr(
"%n commercial break(s)",
"", breaksFound);
2357 msg = tr(
"Commercial Detection %1",
"Job ID")
2360 if (!comment.isEmpty())
2362 detailstr += QString(
" (%1)").arg(comment);
2363 details = detailstr.toLocal8Bit();
2366 if (priority <= LOG_WARNING)
2367 LOG(VB_GENERAL, LOG_ERR,
LOC + msg +
": " + details.constData());
2401 msg = QString(
"Started %1 for %2 recorded from channel %3")
2407 msg = QString(
"Started %1 for jobID %2").arg(jobDesc).arg(jobID);
2409 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(msg.toLocal8Bit().constData()));
2423 LOG(VB_JOBQUEUE, LOG_INFO,
LOC + QString(
"Running command: '%1'")
2425 GetMythDB()->GetDBManager()->CloseDatabases();
2428 if ((result == GENERIC_EXIT_DAEMONIZING_ERROR) ||
2429 (result == GENERIC_EXIT_CMD_NOT_FOUND))
2431 msg = QString(
"User Job '%1' failed, unable to find "
2432 "executable, check your PATH and backend logs.")
2434 LOG(VB_GENERAL, LOG_ERR,
LOC + msg);
2435 LOG(VB_GENERAL, LOG_NOTICE,
LOC + QString(
"Current PATH: '%1'")
2436 .arg(getenv(
"PATH")));
2439 tr(
"ERROR: Unable to find executable, check backend logs."));
2441 else if (result != 0)
2443 msg = QString(
"User Job '%1' failed.").arg(command);
2444 LOG(VB_GENERAL, LOG_ERR,
LOC + msg);
2447 tr(
"ERROR: User Job returned non-zero, check logs."));
2453 msg = QString(
"Finished %1 for %2 recorded from channel %3")
2459 msg = QString(
"Finished %1 for jobID %2").arg(jobDesc).arg(jobID);
2461 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(msg.toLocal8Bit().constData()));
2478 while ((x != 0) && ((x & 0x01) == 0))