MythTV  master
backendhousekeeper.cpp
Go to the documentation of this file.
1 // POSIX headers
2 #include <unistd.h>
3 #include <sys/types.h>
4 
5 // ANSI C headers
6 #include <cstdlib>
7 
8 // Qt headers
9 #include <QStringList>
10 #include <QDateTime>
11 #include <QDir>
12 #include <QFileInfo>
13 
14 // MythTV headers
15 #include "backendhousekeeper.h"
16 #include "mythdb.h"
17 #include "mythdirs.h"
18 #include "jobqueue.h"
19 #include "exitcodes.h"
20 #include "mythsystemlegacy.h"
21 #include "mythversion.h"
22 #include "mythcoreutil.h"
23 #include "programtypes.h"
24 #include "recordingtypes.h"
25 #include "mythcorecontext.h"
26 #include "mythdownloadmanager.h"
27 #include "musicmetadata.h"
28 
29 #include "enums/recStatus.h"
30 
32 {
33  int numdays = 14;
34  uint64_t maxrows = 10000 * numdays; // likely high enough to keep numdays
35  bool res = true;
36 
38  if (query.isConnected())
39  {
40  // Remove less-important logging after 1/2 * numdays days
41  QDateTime days = MythDate::current();
42  days = days.addDays(0 - (numdays / 2));
43  QString sql = "DELETE FROM logging "
44  " WHERE application NOT IN (:MYTHBACKEND, :MYTHFRONTEND) "
45  " AND msgtime < :DAYS ;";
46  query.prepare(sql);
47  query.bindValue(":MYTHBACKEND", MYTH_APPNAME_MYTHBACKEND);
48  query.bindValue(":MYTHFRONTEND", MYTH_APPNAME_MYTHFRONTEND);
49  query.bindValue(":DAYS", days);
50  LOG(VB_GENERAL, LOG_DEBUG,
51  QString("Deleting helper application database log entries "
52  "from before %1.") .arg(days.toString(Qt::ISODate)));
53  if (!query.exec())
54  {
55  MythDB::DBError("Delete helper application log entries", query);
56  res = false;
57  }
58 
59  // Remove backend/frontend logging after numdays days
60  days = MythDate::current();
61  days = days.addDays(0 - numdays);
62  sql = "DELETE FROM logging WHERE msgtime < :DAYS ;";
63  query.prepare(sql);
64  query.bindValue(":DAYS", days);
65  LOG(VB_GENERAL, LOG_DEBUG,
66  QString("Deleting database log entries from before %1.")
67  .arg(days.toString(Qt::ISODate)));
68  if (!query.exec())
69  {
70  MythDB::DBError("Delete old log entries", query);
71  res = false;
72  }
73 
74  sql = "SELECT COUNT(id) FROM logging;";
75  query.prepare(sql);
76  if (query.exec())
77  {
78  uint64_t totalrows = 0;
79  while (query.next())
80  {
81  totalrows = query.value(0).toLongLong();
82  LOG(VB_GENERAL, LOG_DEBUG,
83  QString("Database has %1 log entries.").arg(totalrows));
84  }
85  if (totalrows > maxrows)
86  {
87  sql = "DELETE FROM logging ORDER BY msgtime LIMIT :ROWS;";
88  query.prepare(sql);
89  quint64 extrarows = totalrows - maxrows;
90  query.bindValue(":ROWS", extrarows);
91  LOG(VB_GENERAL, LOG_DEBUG,
92  QString("Deleting oldest %1 database log entries.")
93  .arg(extrarows));
94  if (!query.exec())
95  {
96  MythDB::DBError("Delete excess log entries", query);
97  res = false;
98  }
99  }
100  }
101  else
102  {
103  MythDB::DBError("Query logging table size", query);
104  res = false;
105  }
106  }
107 
108  return res;
109 }
110 
112 {
119  return true;
120 }
121 
123 {
124  MSqlQuery query(MSqlQuery::InitCon());
125 
126  query.prepare("DELETE FROM inuseprograms "
127  "WHERE hostname = :HOSTNAME AND "
128  "( recusage = 'recorder' OR recusage LIKE 'Unknown %' );");
129  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
130  if (!query.exec())
131  MythDB::DBError("CleanupTask::CleanupOldRecordings", query);
132 }
133 
135 {
136  QDateTime fourHoursAgo = MythDate::current().addSecs(-4 * 60 * 60);
137  MSqlQuery query(MSqlQuery::InitCon());
138 
139  query.prepare("DELETE FROM inuseprograms "
140  "WHERE lastupdatetime < :FOURHOURSAGO ;");
141  query.bindValue(":FOURHOURSAGO", fourHoursAgo);
142  if (!query.exec())
143  MythDB::DBError("CleanupTask::CleanupInUsePrograms", query);
144 }
145 
147 {
148  QDateTime fourHoursAgo = MythDate::current().addSecs(-4 * 60 * 60);
149  MSqlQuery query(MSqlQuery::InitCon());
150  MSqlQuery deleteQuery(MSqlQuery::InitCon());
151 
152  // Keep these tvchains, they may be in use.
153  query.prepare("SELECT DISTINCT chainid FROM tvchain "
154  "WHERE endtime > :FOURHOURSAGO ;");
155  query.bindValue(":FOURHOURSAGO", fourHoursAgo);
156 
157  if (!query.exec() || !query.isActive())
158  {
159  MythDB::DBError("HouseKeeper Cleaning TVChain Table", query);
160  return;
161  }
162 
163  QString msg, keepChains;
164  while (query.next())
165  if (keepChains.isEmpty())
166  keepChains = "'" + query.value(0).toString() + "'";
167  else
168  keepChains += ", '" + query.value(0).toString() + "'";
169 
170  if (keepChains.isEmpty())
171  msg = "DELETE FROM tvchain WHERE endtime < now();";
172  else
173  {
174  msg = QString("DELETE FROM tvchain "
175  "WHERE chainid NOT IN ( %1 ) AND endtime < now();")
176  .arg(keepChains);
177  }
178  deleteQuery.prepare(msg);
179  if (!deleteQuery.exec())
180  MythDB::DBError("CleanupTask::CleanupOrphanedLiveTV", deleteQuery);
181 }
182 
184 {
185  MSqlQuery query(MSqlQuery::InitCon());
186  MSqlQuery deleteQuery(MSqlQuery::InitCon());
187  int tableIndex = 0;
188  // tables[tableIndex][0] is the table name
189  // tables[tableIndex][1] is the name of the column on which the join is
190  // performed
191  QString tables[][2] = {
192  { "recordedprogram", "progstart" },
193  { "recordedrating", "progstart" },
194  { "recordedcredits", "progstart" },
195  { "recordedmarkup", "starttime" },
196  { "recordedseek", "starttime" },
197  { "", "" } }; // This blank entry must exist, do not remove.
198  QString table = tables[tableIndex][0];
199  QString column = tables[tableIndex][1];
200 
201  // Because recordedseek can have millions of rows, we don't want to JOIN it
202  // with recorded. Instead, pull out DISTINCT chanid and starttime into a
203  // temporary table (resulting in tens, hundreds, or--at most--a few
204  // thousand rows) for the JOIN
205  QString querystr;
206  querystr = "CREATE TEMPORARY TABLE IF NOT EXISTS temprecordedcleanup ( "
207  "chanid int(10) unsigned NOT NULL default '0', "
208  "starttime datetime NOT NULL default '0000-00-00 00:00:00' "
209  ");";
210 
211  if (!query.exec(querystr))
212  {
213  MythDB::DBError("CleanupTask::CleanupRecordedTables"
214  "(creating temporary table)", query);
215  return;
216  }
217 
218  while (!table.isEmpty())
219  {
220  query.prepare(QString("TRUNCATE TABLE temprecordedcleanup;"));
221  if (!query.exec() || !query.isActive())
222  {
223  MythDB::DBError("CleanupTask::CleanupRecordedTables"
224  "(truncating temporary table)", query);
225  return;
226  }
227 
228  query.prepare(QString("INSERT INTO temprecordedcleanup "
229  "( chanid, starttime ) "
230  "SELECT DISTINCT chanid, starttime "
231  "FROM %1;")
232  .arg(table));
233 
234  if (!query.exec() || !query.isActive())
235  {
236  MythDB::DBError("CleanupTask::CleanupRecordedTables"
237  "(cleaning recorded tables)", query);
238  return;
239  }
240 
241  query.prepare(QString("SELECT DISTINCT p.chanid, p.starttime "
242  "FROM temprecordedcleanup p "
243  "LEFT JOIN recorded r "
244  "ON p.chanid = r.chanid "
245  "AND p.starttime = r.%1 "
246  "WHERE r.chanid IS NULL;").arg(column));
247  if (!query.exec() || !query.isActive())
248  {
249  MythDB::DBError("CleanupTask::CleanupRecordedTables"
250  "(cleaning recorded tables)", query);
251  return;
252  }
253 
254  deleteQuery.prepare(QString("DELETE FROM %1 "
255  "WHERE chanid = :CHANID "
256  "AND starttime = :STARTTIME;")
257  .arg(table));
258  while (query.next())
259  {
260  deleteQuery.bindValue(":CHANID", query.value(0).toString());
261  deleteQuery.bindValue(":STARTTIME", query.value(1));
262  if (!deleteQuery.exec())
263  {
264  MythDB::DBError("CleanupTask::CleanupRecordedTables"
265  "(cleaning recorded tables)", deleteQuery);
266  return;
267  }
268  }
269 
270  tableIndex++;
271  table = tables[tableIndex][0];
272  column = tables[tableIndex][1];
273  }
274 
275  if (!query.exec("DROP TABLE temprecordedcleanup;"))
276  MythDB::DBError("CleanupTask::CleanupRecordedTables"
277  "(deleting temporary table)", query);
278 }
279 
281 {
282  MSqlQuery query(MSqlQuery::InitCon());
283  QString querystr;
284  // Keep as many days of listings data as we keep matching, non-recorded
285  // oldrecorded entries to allow for easier post-mortem analysis
286  int offset = gCoreContext->GetNumSetting( "CleanOldRecorded", 10);
287  // Also make sure to keep enough data so that we can flag the original
288  // airdate, for when that isn't included in guide data
289  int newEpiWindow = gCoreContext->GetNumSetting( "NewEpisodeWindow", 14);
290  if (newEpiWindow > offset)
291  offset = newEpiWindow;
292 
293  query.prepare("DELETE FROM oldprogram WHERE airdate < "
294  "DATE_SUB(CURRENT_DATE, INTERVAL 320 DAY);");
295  if (!query.exec())
296  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
297 
298  query.prepare("REPLACE INTO oldprogram (oldtitle,airdate) "
299  "SELECT title,starttime FROM program "
300  "WHERE starttime < NOW() AND manualid = 0 "
301  "GROUP BY title;");
302  if (!query.exec())
303  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
304 
305  query.prepare("DELETE FROM program WHERE starttime <= "
306  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
307  query.bindValue(":OFFSET", offset);
308  if (!query.exec())
309  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
310 
311  query.prepare("DELETE FROM programrating WHERE starttime <= "
312  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
313  query.bindValue(":OFFSET", offset);
314  if (!query.exec())
315  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
316 
317  query.prepare("DELETE FROM programgenres WHERE starttime <= "
318  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
319  query.bindValue(":OFFSET", offset);
320  if (!query.exec())
321  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
322 
323  query.prepare("DELETE FROM credits WHERE starttime <= "
324  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
325  query.bindValue(":OFFSET", offset);
326  if (!query.exec())
327  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
328 
329  query.prepare("DELETE FROM record WHERE (type = :SINGLE "
330  "OR type = :OVERRIDE OR type = :DONTRECORD) "
331  "AND enddate < CURDATE();");
332  query.bindValue(":SINGLE", kSingleRecord);
333  query.bindValue(":OVERRIDE", kOverrideRecord);
334  query.bindValue(":DONTRECORD", kDontRecord);
335  if (!query.exec())
336  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
337 
338  MSqlQuery findq(MSqlQuery::InitCon());
339  findq.prepare("SELECT record.recordid FROM record "
340  "LEFT JOIN oldfind ON oldfind.recordid = record.recordid "
341  "WHERE type = :FINDONE AND oldfind.findid IS NOT NULL;");
342  findq.bindValue(":FINDONE", kOneRecord);
343 
344  if (findq.exec())
345  {
346  query.prepare("DELETE FROM record WHERE recordid = :RECORDID;");
347  while (findq.next())
348  {
349  query.bindValue(":RECORDID", findq.value(0).toInt());
350  if (!query.exec())
351  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
352  }
353  }
354  query.prepare("DELETE FROM oldfind WHERE findid < TO_DAYS(NOW()) - 14;");
355  if (!query.exec())
356  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
357 
358  query.prepare("DELETE FROM oldrecorded WHERE "
359  "recstatus <> :RECORDED AND duplicate = 0 AND "
360  "endtime < DATE_SUB(CURRENT_DATE, INTERVAL :CLEAN DAY);");
361  query.bindValue(":RECORDED", RecStatus::Recorded);
362  query.bindValue(":CLEAN", offset);
363  if (!query.exec())
364  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
365 }
366 
367 bool ThemeUpdateTask::DoCheckRun(QDateTime now)
368 {
369  return gCoreContext->GetBoolSetting("ThemeUpdateNofications", true) &&
371 }
372 
374 {
375  bool result = false;
376  QString MythVersion = MYTH_SOURCE_PATH;
377 
378  // Treat devel branches as master
379  if (!MythVersion.isEmpty() && !MythVersion.startsWith("fixes/"))
380  {
381  // FIXME: For now, treat git master the same as svn trunk
382  MythVersion = "trunk";
383 
384  result |= LoadVersion(MythVersion, LOG_ERR);
385  LOG(VB_GENERAL, LOG_INFO,
386  QString("Loading themes for %1").arg(MythVersion));
387  }
388  else
389  {
390 
391  MythVersion = MYTH_BINARY_VERSION; // Example: 29.20161017-1
392  MythVersion.replace(QRegExp("\\.[0-9]{8,}.*"), "");
393  LOG(VB_GENERAL, LOG_INFO,
394  QString("Loading themes for %1").arg(MythVersion));
395  result |= LoadVersion(MythVersion, LOG_ERR);
396 
397  // If a version of the theme for this tag exists, use it...
398  QRegExp subexp("v[0-9]+\\.([0-9]+)-*");
399  int pos = subexp.indexIn(MYTH_SOURCE_VERSION);
400  if (pos > -1)
401  {
402  QString subversion;
403  int idx = subexp.cap(1).toInt();
404  for ( ; idx > 0; --idx)
405  {
406  subversion = MythVersion + "." + QString::number(idx);
407  LOG(VB_GENERAL, LOG_INFO,
408  QString("Loading themes for %1").arg(subversion));
409  result |= LoadVersion(subversion, LOG_INFO);
410  }
411  }
412  }
413  return result;
414 }
415 
416 bool ThemeUpdateTask::LoadVersion(const QString &version, int download_log_level)
417 {
418  QString remoteThemesDir = GetConfDir();
419  remoteThemesDir.append("/tmp/remotethemes");
420 
421  QDir dir(remoteThemesDir);
422  if (!dir.exists() && !dir.mkpath(remoteThemesDir))
423  {
424  LOG(VB_GENERAL, LOG_ERR,
425  QString("HouseKeeper: Error creating %1 "
426  "directory for remote themes info cache.")
427  .arg(remoteThemesDir));
428  return false;
429  }
430 
431  QString remoteThemesFile = remoteThemesDir;
432  remoteThemesFile.append("/themes.zip");
433 
434  m_url = QString("%1/%2/themes.zip")
435  .arg(gCoreContext->GetSetting("ThemeRepositoryURL",
436  "http://themes.mythtv.org/themes/repository"))
437  .arg(version);
438 
439  m_running = true;
440  bool result = GetMythDownloadManager()->download(m_url, remoteThemesFile);
441  m_running = false;
442 
443  if (!result)
444  {
445  LOG(VB_GENERAL, (LogLevel_t)download_log_level,
446  QString("HouseKeeper: Failed to download %1 "
447  "remote themes info package.").arg(m_url));
448  return false;
449  }
450 
451  if (!extractZIP(remoteThemesFile, remoteThemesDir))
452  {
453  LOG(VB_GENERAL, LOG_ERR,
454  QString("HouseKeeper: Error extracting %1 "
455  "remote themes info package.").arg(remoteThemesFile));
456  QFile::remove(remoteThemesFile);
457  return false;
458  }
459 
460  return true;
461 }
462 
464 {
465  if (m_running)
467  m_running = false;
468 }
469 
472  m_msMU(nullptr)
473 {
474 }
475 
477 {
478  if (m_msMU)
479  {
480  // this should never be defined, but terminate it anyway
482  m_msMU->Term(true);
483  delete m_msMU;
484  m_msMU = nullptr;
485  }
486 
487  QString command = GetAppBinDir() + "mythutil";
488  QStringList args;
489  args << "--updateradiostreams";
491 
492  LOG(VB_GENERAL, LOG_INFO, QString("Performing Radio Streams Update: %1 %2")
493  .arg(command).arg(args.join(" ")));
494 
496 
497  m_msMU->Run();
498  uint result = m_msMU->Wait();
499 
500  delete m_msMU;
501  m_msMU = nullptr;
502 
503  if (result != GENERIC_EXIT_OK)
504  {
505  LOG(VB_GENERAL, LOG_ERR, QString("Update Radio Streams command '%1' failed")
506  .arg(command));
507  return false;
508  }
509 
510  LOG(VB_GENERAL, LOG_INFO, QString("Radio Stream Update Complete"));
511  return true;
512 }
513 
515 {
516  delete m_msMU;
517  m_msMU = nullptr;
518 }
519 
521 {
522  // we are only interested in the global setting so remove any local host setting just in case
523  GetMythDB()->ClearSetting("MusicStreamListModified");
524 
525  // check we are not already running a radio stream update
526  return gCoreContext->GetSetting("MusicStreamListModified") == "Updating" &&
528 }
529 
531 {
533  // just kill it, the runner thread will handle any necessary cleanup
534  m_msMU->Term(true);
535 }
536 
537 ArtworkTask::ArtworkTask(void) : DailyHouseKeeperTask("RecordedArtworkUpdate",
539  m_msMML(nullptr)
540 {
541 }
542 
544 {
545  if (m_msMML)
546  {
547  // this should never be defined, but terminate it anyway
549  m_msMML->Term(true);
550  delete m_msMML;
551  m_msMML = nullptr;
552  }
553 
554  QString command = GetAppBinDir() + "mythmetadatalookup";
555  QStringList args;
556  args << "--refresh-all-artwork";
558 
559  LOG(VB_GENERAL, LOG_INFO, QString("Performing Artwork Refresh: %1 %2")
560  .arg(command).arg(args.join(" ")));
561 
563 
564  m_msMML->Run();
565  uint result = m_msMML->Wait();
566 
567  delete m_msMML;
568  m_msMML = nullptr;
569 
570  if (result != GENERIC_EXIT_OK)
571  {
572  LOG(VB_GENERAL, LOG_ERR, QString("Artwork command '%1' failed")
573  .arg(command));
574  return false;
575  }
576  LOG(VB_GENERAL, LOG_INFO, QString("Artwork Refresh Complete"));
577  return true;
578 }
579 
581 {
582  delete m_msMML;
583  m_msMML = nullptr;
584 }
585 
586 bool ArtworkTask::DoCheckRun(QDateTime now)
587 {
588  return gCoreContext->GetBoolSetting("DailyArtworkUpdates", false) &&
590 }
591 
593 {
595  // just kill it, the runner thread will handle any necessary cleanup
596  m_msMML->Term(true);
597 }
598 
600 {
602  return true;
603 }
604 
606  DailyHouseKeeperTask("MythFillDB"), m_msMFD(nullptr)
607 {
609 }
610 
612 {
613  // we need to set the time window from database settings, so we cannot
614  // initialize these values in. grab them and set them afterwards
615  int min = gCoreContext->GetNumSetting("MythFillMinHour", -1);
616  int max = gCoreContext->GetNumSetting("MythFillMaxHour", 23);
617 
618  if (min == -1)
619  {
620  min = 0;
621  max = 23;
622  }
623  else
624  {
625  // make sure they fall within the range of 0-23
626  min %= 24;
627  max %= 24;
628  }
629 
631 }
632 
634 {
635 // if (!gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", true))
636 // // this feature is disabled, so don't bother with a deeper check
637 // return false;
638 //
639 // MSqlQuery result(MSqlQuery::InitCon());
640 // if (result.isConnected())
641 // {
642 // // check to see if we have any of a list of supported grabbers in use
643 // // TODO: this is really cludgy. there has to be a better way to test
644 // result.prepare("SELECT COUNT(*) FROM videosource"
645 // " WHERE xmltvgrabber IN"
646 // " ( 'technovera' );");
647 // if ((result.exec()) &&
648 // (result.next()) &&
649 // (result.value(0).toInt() > 0))
650 // return true;
651 // }
652 
653  return gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", true);
654 }
655 
657 {
658  if (!gCoreContext->GetBoolSetting("MythFillEnabled", true))
659  {
660  // we don't want to run this manually, so abort early
661  LOG(VB_GENERAL, LOG_DEBUG, "MythFillDatabase is disabled. Cannot run.");
662  return false;
663  }
664 
665 // if (m_running)
666 // // we're still running from the previous pass, so abort early
667 // return false;
668 
669  if (UseSuggestedTime())
670  {
671  QDateTime nextRun = MythDate::fromString(
672  gCoreContext->GetSetting("MythFillSuggestedRunTime",
673  "1970-01-01T00:00:00"));
674  LOG(VB_GENERAL, LOG_DEBUG,
675  QString("MythFillDatabase scheduled to run at %1.")
676  .arg(nextRun.toString()));
677  // is it yet time
678  return nextRun <= now;
679  }
680  if (InWindow(now))
681  // we're inside our permitted window
682  return true;
683 
684  // just let DailyHouseKeeperTask handle things
685  LOG(VB_GENERAL, LOG_DEBUG, "Performing daily run check.");
687 }
688 
690 {
691  if (m_msMFD)
692  {
693  // this should never be defined, but terminate it anyway
695  m_msMFD->Term(true);
696  delete m_msMFD;
697  m_msMFD = nullptr;
698  }
699 
700  QString mfpath = gCoreContext->GetSetting("MythFillDatabasePath",
701  "mythfilldatabase");
702  QString mfarg = gCoreContext->GetSetting("MythFillDatabaseArgs", "");
703 
705  if (mfpath == "mythfilldatabase")
706  {
708  mfpath = GetAppBinDir() + "mythfilldatabase";
709  }
710 
711  QString cmd = QString("%1 %2").arg(mfpath).arg(mfarg);
712 
713  m_msMFD = new MythSystemLegacy(cmd, opts);
714 
715  m_msMFD->Run();
716  uint result = m_msMFD->Wait();
717 
718  delete m_msMFD;
719  m_msMFD = nullptr;
720 
721  if (result != GENERIC_EXIT_OK)
722  {
723  LOG(VB_GENERAL, LOG_ERR, QString("MythFillDatabase command '%1' failed")
724  .arg(cmd));
725  return false;
726  }
727 
728  return true;
729 }
730 
732 {
733  delete m_msMFD;
734  m_msMFD = nullptr;
735 }
736 
738 {
740  // just kill it, the runner thread will handle any necessary cleanup
741  m_msMFD->Term(true);
742 }
void CleanupInUsePrograms(void)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
bool DoCheckRun(QDateTime now) override
void Terminate(void) override
automatically delete if backgrounded
Definition: mythsystem.h:43
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
bool DoRun(void) override
MythSystemLegacy * m_msMFD
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
bool DoCheckRun(QDateTime now) override
QString logPropagateArgs
Definition: logging.cpp:89
bool isConnected(void)
Only updated once during object creation.
Definition: mythdbcon.h:135
bool DoRun(void) override
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void CleanupOrphanedLiveTV(void)
bool DoRun(void) override
bool DoCheckRun(QDateTime now) override
void Terminate(void) override
bool DoRun(void) override
virtual ~ArtworkTask(void)
bool extractZIP(const QString &zipFile, const QString &outDir)
MythSystemLegacy * m_msMML
bool DoCheckRun(QDateTime now) override
add arguments for MythTV log propagation
Definition: mythsystem.h:50
QString GetConfDir(void)
Definition: mythdirs.cpp:224
QVariant value(int i) const
Definition: mythdbcon.h:198
task should only run once per cluster e.g.
Definition: housekeeper.h:25
bool DoCheckRun(QDateTime now) override
bool InWindow(QDateTime now) override
MythSystemLegacy * m_msMU
void Term(bool force=false)
task is queued when HouseKeeper is started
Definition: housekeeper.h:35
QString GetAppBinDir(void)
Definition: mythdirs.cpp:221
run process through shell
Definition: mythsystem.h:41
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
void Terminate(void) override
void CleanupOldRecordings(void)
bool isActive(void) const
Definition: mythdbcon.h:204
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
bool download(const QString &url, const QString &dest, const bool reload=false)
Downloads a URL to a file in blocking mode.
#define GENERIC_EXIT_RUNNING
Process is running.
Definition: exitcodes.h:25
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
void CleanupRecordedTables(void)
uint Wait(time_t timeout=0)
static void RecoverOldJobsInQueue()
Definition: jobqueue.h:212
Modified PeriodicHouseKeeperTask for tasks to be run once daily.
Definition: housekeeper.h:107
virtual void SetHourWindow(int min, int max)
int GetNumSetting(const QString &key, int defaultval=0)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define MYTH_APPNAME_MYTHFRONTEND
#define MYTH_APPNAME_MYTHBACKEND
bool GetBoolSetting(const QString &key, bool defaultval=false)
static void CleanupOldJobsInQueue()
Definition: jobqueue.cpp:1632
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:16
bool DoRun(void) override
virtual ~MythFillDatabaseTask(void)
void CleanupProgramListings(void)
void cancelDownload(const QString &url, bool block=true)
Cancel a queued or current download.
bool DoRun(void) override
bool LoadVersion(const QString &version, int download_log_level)
virtual ~RadioStreamUpdateTask(void)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
static bool UseSuggestedTime(void)
bool DoRun(void) override
QString GetHostName(void)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
Default UTC.
Definition: mythdate.h:14
void Terminate(void) override