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 {
120  return true;
121 }
122 
124 {
125  MSqlQuery query(MSqlQuery::InitCon());
126 
127  query.prepare("DELETE FROM inuseprograms "
128  "WHERE hostname = :HOSTNAME AND "
129  "( recusage = 'recorder' OR recusage LIKE 'Unknown %' );");
130  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
131  if (!query.exec())
132  MythDB::DBError("CleanupTask::CleanupOldRecordings", query);
133 }
134 
136 {
137  QDateTime fourHoursAgo = MythDate::current().addSecs(-4 * 60 * 60);
138  MSqlQuery query(MSqlQuery::InitCon());
139 
140  query.prepare("DELETE FROM inuseprograms "
141  "WHERE lastupdatetime < :FOURHOURSAGO ;");
142  query.bindValue(":FOURHOURSAGO", fourHoursAgo);
143  if (!query.exec())
144  MythDB::DBError("CleanupTask::CleanupInUsePrograms", query);
145 }
146 
148 {
149  QDateTime fourHoursAgo = MythDate::current().addSecs(-4 * 60 * 60);
150  MSqlQuery query(MSqlQuery::InitCon());
151  MSqlQuery deleteQuery(MSqlQuery::InitCon());
152 
153  // Keep these tvchains, they may be in use.
154  query.prepare("SELECT DISTINCT chainid FROM tvchain "
155  "WHERE endtime > :FOURHOURSAGO ;");
156  query.bindValue(":FOURHOURSAGO", fourHoursAgo);
157 
158  if (!query.exec() || !query.isActive())
159  {
160  MythDB::DBError("HouseKeeper Cleaning TVChain Table", query);
161  return;
162  }
163 
164  QString msg, keepChains;
165  while (query.next())
166  if (keepChains.isEmpty())
167  keepChains = "'" + query.value(0).toString() + "'";
168  else
169  keepChains += ", '" + query.value(0).toString() + "'";
170 
171  if (keepChains.isEmpty())
172  msg = "DELETE FROM tvchain WHERE endtime < now();";
173  else
174  {
175  msg = QString("DELETE FROM tvchain "
176  "WHERE chainid NOT IN ( %1 ) AND endtime < now();")
177  .arg(keepChains);
178  }
179  deleteQuery.prepare(msg);
180  if (!deleteQuery.exec())
181  MythDB::DBError("CleanupTask::CleanupOrphanedLiveTV", deleteQuery);
182 }
183 
185 {
186  MSqlQuery query(MSqlQuery::InitCon());
187  MSqlQuery deleteQuery(MSqlQuery::InitCon());
188  int tableIndex = 0;
189  // tables[tableIndex][0] is the table name
190  // tables[tableIndex][1] is the name of the column on which the join is
191  // performed
192  QString tables[][2] = {
193  { "recordedprogram", "progstart" },
194  { "recordedrating", "progstart" },
195  { "recordedcredits", "progstart" },
196  { "recordedmarkup", "starttime" },
197  { "recordedseek", "starttime" },
198  { "", "" } }; // This blank entry must exist, do not remove.
199  QString table = tables[tableIndex][0];
200  QString column = tables[tableIndex][1];
201 
202  // Because recordedseek can have millions of rows, we don't want to JOIN it
203  // with recorded. Instead, pull out DISTINCT chanid and starttime into a
204  // temporary table (resulting in tens, hundreds, or--at most--a few
205  // thousand rows) for the JOIN
206  QString querystr;
207  querystr = "CREATE TEMPORARY TABLE IF NOT EXISTS temprecordedcleanup ( "
208  "chanid int(10) unsigned NOT NULL default '0', "
209  "starttime datetime NOT NULL default '0000-00-00 00:00:00' "
210  ");";
211 
212  if (!query.exec(querystr))
213  {
214  MythDB::DBError("CleanupTask::CleanupRecordedTables"
215  "(creating temporary table)", query);
216  return;
217  }
218 
219  while (!table.isEmpty())
220  {
221  query.prepare(QString("TRUNCATE TABLE temprecordedcleanup;"));
222  if (!query.exec() || !query.isActive())
223  {
224  MythDB::DBError("CleanupTask::CleanupRecordedTables"
225  "(truncating temporary table)", query);
226  return;
227  }
228 
229  query.prepare(QString("INSERT INTO temprecordedcleanup "
230  "( chanid, starttime ) "
231  "SELECT DISTINCT chanid, starttime "
232  "FROM %1;")
233  .arg(table));
234 
235  if (!query.exec() || !query.isActive())
236  {
237  MythDB::DBError("CleanupTask::CleanupRecordedTables"
238  "(cleaning recorded tables)", query);
239  return;
240  }
241 
242  query.prepare(QString("SELECT DISTINCT p.chanid, p.starttime "
243  "FROM temprecordedcleanup p "
244  "LEFT JOIN recorded r "
245  "ON p.chanid = r.chanid "
246  "AND p.starttime = r.%1 "
247  "WHERE r.chanid IS NULL;").arg(column));
248  if (!query.exec() || !query.isActive())
249  {
250  MythDB::DBError("CleanupTask::CleanupRecordedTables"
251  "(cleaning recorded tables)", query);
252  return;
253  }
254 
255  deleteQuery.prepare(QString("DELETE FROM %1 "
256  "WHERE chanid = :CHANID "
257  "AND starttime = :STARTTIME;")
258  .arg(table));
259  while (query.next())
260  {
261  deleteQuery.bindValue(":CHANID", query.value(0).toString());
262  deleteQuery.bindValue(":STARTTIME", query.value(1));
263  if (!deleteQuery.exec())
264  {
265  MythDB::DBError("CleanupTask::CleanupRecordedTables"
266  "(cleaning recorded tables)", deleteQuery);
267  return;
268  }
269  }
270 
271  tableIndex++;
272  table = tables[tableIndex][0];
273  column = tables[tableIndex][1];
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  QString querystr;
315  // Keep as many days of listings data as we keep matching, non-recorded
316  // oldrecorded entries to allow for easier post-mortem analysis
317  int offset = gCoreContext->GetNumSetting( "CleanOldRecorded", 10);
318  // Also make sure to keep enough data so that we can flag the original
319  // airdate, for when that isn't included in guide data
320  int newEpiWindow = gCoreContext->GetNumSetting( "NewEpisodeWindow", 14);
321  if (newEpiWindow > offset)
322  offset = newEpiWindow;
323 
324  query.prepare("DELETE FROM oldprogram WHERE airdate < "
325  "DATE_SUB(CURRENT_DATE, INTERVAL 320 DAY);");
326  if (!query.exec())
327  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
328 
329  query.prepare("REPLACE INTO oldprogram (oldtitle,airdate) "
330  "SELECT title,starttime FROM program "
331  "WHERE starttime < NOW() AND manualid = 0 "
332  "GROUP BY title;");
333  if (!query.exec())
334  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
335 
336  query.prepare("DELETE FROM program WHERE starttime <= "
337  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
338  query.bindValue(":OFFSET", offset);
339  if (!query.exec())
340  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
341 
342  query.prepare("DELETE FROM programrating WHERE starttime <= "
343  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
344  query.bindValue(":OFFSET", offset);
345  if (!query.exec())
346  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
347 
348  query.prepare("DELETE FROM programgenres WHERE starttime <= "
349  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
350  query.bindValue(":OFFSET", offset);
351  if (!query.exec())
352  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
353 
354  query.prepare("DELETE FROM credits WHERE starttime <= "
355  "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
356  query.bindValue(":OFFSET", offset);
357  if (!query.exec())
358  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
359 
360  query.prepare("DELETE FROM record WHERE (type = :SINGLE "
361  "OR type = :OVERRIDE OR type = :DONTRECORD) "
362  "AND enddate < CURDATE();");
363  query.bindValue(":SINGLE", kSingleRecord);
364  query.bindValue(":OVERRIDE", kOverrideRecord);
365  query.bindValue(":DONTRECORD", kDontRecord);
366  if (!query.exec())
367  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
368 
369  MSqlQuery findq(MSqlQuery::InitCon());
370  findq.prepare("SELECT record.recordid FROM record "
371  "LEFT JOIN oldfind ON oldfind.recordid = record.recordid "
372  "WHERE type = :FINDONE AND oldfind.findid IS NOT NULL;");
373  findq.bindValue(":FINDONE", kOneRecord);
374 
375  if (findq.exec())
376  {
377  query.prepare("DELETE FROM record WHERE recordid = :RECORDID;");
378  while (findq.next())
379  {
380  query.bindValue(":RECORDID", findq.value(0).toInt());
381  if (!query.exec())
382  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
383  }
384  }
385  query.prepare("DELETE FROM oldfind WHERE findid < TO_DAYS(NOW()) - 14;");
386  if (!query.exec())
387  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
388 
389  query.prepare("DELETE FROM oldrecorded WHERE "
390  "recstatus <> :RECORDED AND duplicate = 0 AND "
391  "endtime < DATE_SUB(CURRENT_DATE, INTERVAL :CLEAN DAY);");
392  query.bindValue(":RECORDED", RecStatus::Recorded);
393  query.bindValue(":CLEAN", offset);
394  if (!query.exec())
395  MythDB::DBError("HouseKeeper Cleaning Program Listings", query);
396 }
397 
398 bool ThemeUpdateTask::DoCheckRun(QDateTime now)
399 {
400  return gCoreContext->GetBoolSetting("ThemeUpdateNofications", true) &&
402 }
403 
405 {
406  bool result = false;
407  QString MythVersion = MYTH_SOURCE_PATH;
408 
409  // Treat devel branches as master
410  if (!MythVersion.isEmpty() && !MythVersion.startsWith("fixes/"))
411  {
412  // FIXME: For now, treat git master the same as svn trunk
413  MythVersion = "trunk";
414 
415  result |= LoadVersion(MythVersion, LOG_ERR);
416  LOG(VB_GENERAL, LOG_INFO,
417  QString("Loading themes for %1").arg(MythVersion));
418  }
419  else
420  {
421 
422  MythVersion = MYTH_BINARY_VERSION; // Example: 29.20161017-1
423  MythVersion.replace(QRegExp("\\.[0-9]{8,}.*"), "");
424  LOG(VB_GENERAL, LOG_INFO,
425  QString("Loading themes for %1").arg(MythVersion));
426  result |= LoadVersion(MythVersion, LOG_ERR);
427 
428  // If a version of the theme for this tag exists, use it...
429  QRegExp subexp("v[0-9]+\\.([0-9]+)-*");
430  int pos = subexp.indexIn(MYTH_SOURCE_VERSION);
431  if (pos > -1)
432  {
433  QString subversion;
434  int idx = subexp.cap(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  .arg(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 
503  m_msMU(nullptr)
504 {
505 }
506 
508 {
509  if (m_msMU)
510  {
511  // this should never be defined, but terminate it anyway
513  m_msMU->Term(true);
514  delete m_msMU;
515  m_msMU = nullptr;
516  }
517 
518  QString command = GetAppBinDir() + "mythutil";
519  QStringList args;
520  args << "--updateradiostreams";
522 
523  LOG(VB_GENERAL, LOG_INFO, QString("Performing Radio Streams Update: %1 %2")
524  .arg(command).arg(args.join(" ")));
525 
527 
528  m_msMU->Run();
529  uint result = m_msMU->Wait();
530 
531  delete m_msMU;
532  m_msMU = nullptr;
533 
534  if (result != GENERIC_EXIT_OK)
535  {
536  LOG(VB_GENERAL, LOG_ERR, QString("Update Radio Streams command '%1' failed")
537  .arg(command));
538  return false;
539  }
540 
541  LOG(VB_GENERAL, LOG_INFO, QString("Radio Stream Update Complete"));
542  return true;
543 }
544 
546 {
547  delete m_msMU;
548  m_msMU = nullptr;
549 }
550 
552 {
553  // we are only interested in the global setting so remove any local host setting just in case
554  GetMythDB()->ClearSetting("MusicStreamListModified");
555 
556  // check we are not already running a radio stream update
557  return gCoreContext->GetSetting("MusicStreamListModified") == "Updating" &&
559 }
560 
562 {
564  // just kill it, the runner thread will handle any necessary cleanup
565  m_msMU->Term(true);
566 }
567 
568 ArtworkTask::ArtworkTask(void) : DailyHouseKeeperTask("RecordedArtworkUpdate",
570  m_msMML(nullptr)
571 {
572 }
573 
575 {
576  if (m_msMML)
577  {
578  // this should never be defined, but terminate it anyway
580  m_msMML->Term(true);
581  delete m_msMML;
582  m_msMML = nullptr;
583  }
584 
585  QString command = GetAppBinDir() + "mythmetadatalookup";
586  QStringList args;
587  args << "--refresh-all-artwork";
589 
590  LOG(VB_GENERAL, LOG_INFO, QString("Performing Artwork Refresh: %1 %2")
591  .arg(command).arg(args.join(" ")));
592 
594 
595  m_msMML->Run();
596  uint result = m_msMML->Wait();
597 
598  delete m_msMML;
599  m_msMML = nullptr;
600 
601  if (result != GENERIC_EXIT_OK)
602  {
603  LOG(VB_GENERAL, LOG_ERR, QString("Artwork command '%1' failed")
604  .arg(command));
605  return false;
606  }
607  LOG(VB_GENERAL, LOG_INFO, QString("Artwork Refresh Complete"));
608  return true;
609 }
610 
612 {
613  delete m_msMML;
614  m_msMML = nullptr;
615 }
616 
617 bool ArtworkTask::DoCheckRun(QDateTime now)
618 {
619  return gCoreContext->GetBoolSetting("DailyArtworkUpdates", false) &&
621 }
622 
624 {
626  // just kill it, the runner thread will handle any necessary cleanup
627  m_msMML->Term(true);
628 }
629 
631 {
633  return true;
634 }
635 
637  DailyHouseKeeperTask("MythFillDB"), m_msMFD(nullptr)
638 {
640 }
641 
643 {
644  // we need to set the time window from database settings, so we cannot
645  // initialize these values in. grab them and set them afterwards
646  int min = gCoreContext->GetNumSetting("MythFillMinHour", -1);
647  int max = gCoreContext->GetNumSetting("MythFillMaxHour", 23);
648 
649  if (min == -1)
650  {
651  min = 0;
652  max = 23;
653  }
654  else
655  {
656  // make sure they fall within the range of 0-23
657  min %= 24;
658  max %= 24;
659  }
660 
662 }
663 
665 {
666 // if (!gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", true))
667 // // this feature is disabled, so don't bother with a deeper check
668 // return false;
669 //
670 // MSqlQuery result(MSqlQuery::InitCon());
671 // if (result.isConnected())
672 // {
673 // // check to see if we have any of a list of supported grabbers in use
674 // // TODO: this is really cludgy. there has to be a better way to test
675 // result.prepare("SELECT COUNT(*) FROM videosource"
676 // " WHERE xmltvgrabber IN"
677 // " ( 'technovera' );");
678 // if ((result.exec()) &&
679 // (result.next()) &&
680 // (result.value(0).toInt() > 0))
681 // return true;
682 // }
683 
684  return gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", true);
685 }
686 
688 {
689  if (!gCoreContext->GetBoolSetting("MythFillEnabled", true))
690  {
691  // we don't want to run this manually, so abort early
692  LOG(VB_GENERAL, LOG_DEBUG, "MythFillDatabase is disabled. Cannot run.");
693  return false;
694  }
695 
696 // if (m_running)
697 // // we're still running from the previous pass, so abort early
698 // return false;
699 
700  if (UseSuggestedTime())
701  {
702  QDateTime nextRun = MythDate::fromString(
703  gCoreContext->GetSetting("MythFillSuggestedRunTime",
704  "1970-01-01T00:00:00"));
705  LOG(VB_GENERAL, LOG_DEBUG,
706  QString("MythFillDatabase scheduled to run at %1.")
707  .arg(nextRun.toString()));
708  // is it yet time
709  return nextRun <= now;
710  }
711  if (InWindow(now))
712  // we're inside our permitted window
713  return true;
714 
715  // just let DailyHouseKeeperTask handle things
716  LOG(VB_GENERAL, LOG_DEBUG, "Performing daily run check.");
718 }
719 
721 {
722  if (m_msMFD)
723  {
724  // this should never be defined, but terminate it anyway
726  m_msMFD->Term(true);
727  delete m_msMFD;
728  m_msMFD = nullptr;
729  }
730 
731  QString mfpath = gCoreContext->GetSetting("MythFillDatabasePath",
732  "mythfilldatabase");
733  QString mfarg = gCoreContext->GetSetting("MythFillDatabaseArgs", "");
734 
736  if (mfpath == "mythfilldatabase")
737  {
739  mfpath = GetAppBinDir() + "mythfilldatabase";
740  }
741 
742  QString cmd = QString("%1 %2").arg(mfpath).arg(mfarg);
743 
744  m_msMFD = new MythSystemLegacy(cmd, opts);
745 
746  m_msMFD->Run();
747  uint result = m_msMFD->Wait();
748 
749  delete m_msMFD;
750  m_msMFD = nullptr;
751 
752  if (result != GENERIC_EXIT_OK)
753  {
754  LOG(VB_GENERAL, LOG_ERR, QString("MythFillDatabase command '%1' failed")
755  .arg(cmd));
756  return false;
757  }
758 
759  return true;
760 }
761 
763 {
764  delete m_msMFD;
765  m_msMFD = nullptr;
766 }
767 
769 {
771  // just kill it, the runner thread will handle any necessary cleanup
772  m_msMFD->Term(true);
773 }
static void CleanupInUsePrograms(void)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:781
static void CleanupChannelTables(void)
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:862
bool DoCheckRun(QDateTime now) override
void Terminate(void) override
#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
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static 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
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
MythSystemLegacy * m_msMU
add arguments for MythTV log propagation
Definition: mythsystem.h:50
void Term(bool force=false)
task is queued when HouseKeeper is started
Definition: housekeeper.h:35
bool InWindow(const QDateTime &now) override
QString GetAppBinDir(void)
Definition: mythdirs.cpp:221
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
static 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
unsigned int uint
Definition: compat.h:140
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:534
static 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)
run process through shell
Definition: mythsystem.h:41
int GetNumSetting(const QString &key, int defaultval=0)
automatically delete if backgrounded
Definition: mythsystem.h:43
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:806
#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:1634
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:16
bool DoRun(void) override
virtual ~MythFillDatabaseTask(void)
static 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)
Default UTC.
Definition: mythdate.h:14
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:602
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
void Terminate(void) override