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