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