Go to the documentation of this file.
12 #include <QStringList>
21 #include "libmythbase/mythversion.h"
34 #if QT_VERSION < QT_VERSION_CHECK(5,15,2)
35 #define capturedView capturedRef
41 uint64_t maxrows = 10000ULL * numdays;
49 days =
days.addDays(0 - (numdays / 2));
50 QString sql =
"DELETE FROM logging "
51 " WHERE application NOT IN (:MYTHBACKEND, :MYTHFRONTEND) "
52 " AND msgtime < :DAYS ;";
57 LOG(VB_GENERAL, LOG_DEBUG,
58 QString(
"Deleting helper application database log entries "
69 sql =
"DELETE FROM logging WHERE msgtime < :DAYS ;";
72 LOG(VB_GENERAL, LOG_DEBUG,
73 QString(
"Deleting database log entries from before %1.")
81 sql =
"SELECT COUNT(id) FROM logging;";
85 uint64_t totalrows = 0;
88 totalrows = query.
value(0).toLongLong();
89 LOG(VB_GENERAL, LOG_DEBUG,
90 QString(
"Database has %1 log entries.").arg(totalrows));
92 if (totalrows > maxrows)
94 sql =
"DELETE FROM logging ORDER BY msgtime LIMIT :ROWS;";
96 quint64 extrarows = totalrows - maxrows;
98 LOG(VB_GENERAL, LOG_DEBUG,
99 QString(
"Deleting oldest %1 database log entries.")
134 query.
prepare(
"DELETE FROM inuseprograms "
135 "WHERE hostname = :HOSTNAME AND "
136 "( recusage = 'recorder' OR recusage LIKE 'Unknown %' );");
147 query.
prepare(
"DELETE FROM inuseprograms "
148 "WHERE lastupdatetime < :FOURHOURSAGO ;");
149 query.
bindValue(
":FOURHOURSAGO", fourHoursAgo);
161 query.
prepare(
"SELECT DISTINCT chainid FROM tvchain "
162 "WHERE endtime > :FOURHOURSAGO ;");
163 query.
bindValue(
":FOURHOURSAGO", fourHoursAgo);
175 if (keepChains.isEmpty())
176 keepChains =
"'" + query.
value(0).toString() +
"'";
178 keepChains +=
", '" + query.
value(0).toString() +
"'";
181 if (keepChains.isEmpty())
182 msg =
"DELETE FROM tvchain WHERE endtime < now();";
185 msg = QString(
"DELETE FROM tvchain "
186 "WHERE chainid NOT IN ( %1 ) AND endtime < now();")
190 if (!deleteQuery.
exec())
201 std::array<std::array<QString,2>,5> tables {{
202 {
"recordedprogram",
"progstart" },
203 {
"recordedrating",
"progstart" },
204 {
"recordedcredits",
"progstart" },
205 {
"recordedmarkup",
"starttime" },
206 {
"recordedseek",
"starttime" },
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' "
219 if (!query.
exec(querystr))
222 "(creating temporary table)", query);
226 for (
const auto & [table,column] : tables)
228 query.
prepare(QString(
"TRUNCATE TABLE temprecordedcleanup;"));
232 "(truncating temporary table)", query);
236 query.
prepare(QString(
"INSERT INTO temprecordedcleanup "
237 "( chanid, starttime ) "
238 "SELECT DISTINCT chanid, starttime "
245 "(cleaning recorded tables)", query);
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));
258 "(cleaning recorded tables)", query);
262 deleteQuery.
prepare(QString(
"DELETE FROM %1 "
263 "WHERE chanid = :CHANID "
264 "AND starttime = :STARTTIME;")
270 if (!deleteQuery.
exec())
273 "(cleaning recorded tables)", deleteQuery);
279 if (!query.
exec(
"DROP TABLE temprecordedcleanup;"))
281 "(deleting temporary table)", query);
289 query.
prepare(QString(
"DELETE 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"));
302 "(channel table)", query);
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"));
311 "(dtv_multiplex table)", query);
323 if (newEpiWindow > offset)
324 offset = newEpiWindow;
326 query.
prepare(
"DELETE FROM oldprogram WHERE airdate < "
327 "DATE_SUB(CURRENT_DATE, INTERVAL 320 DAY);");
331 query.
prepare(
"REPLACE INTO oldprogram (oldtitle,airdate) "
332 "SELECT title,starttime FROM program "
333 "WHERE starttime < NOW() AND manualid = 0 "
338 query.
prepare(
"DELETE FROM program WHERE starttime <= "
339 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
344 query.
prepare(
"DELETE FROM programrating WHERE starttime <= "
345 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
350 query.
prepare(
"DELETE FROM programgenres WHERE starttime <= "
351 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
356 query.
prepare(
"DELETE FROM credits WHERE starttime <= "
357 "DATE_SUB(CURRENT_DATE, INTERVAL :OFFSET DAY);");
362 query.
prepare(
"DELETE FROM record WHERE (type = :SINGLE "
363 "OR type = :OVERRIDE OR type = :DONTRECORD) "
364 "AND enddate < CURDATE();");
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;");
379 query.
prepare(
"DELETE FROM record WHERE recordid = :RECORDID;");
387 query.
prepare(
"DELETE FROM oldfind WHERE findid < TO_DAYS(NOW()) - 14;");
391 query.
prepare(
"DELETE FROM oldrecorded WHERE "
392 "recstatus <> :RECORDED AND duplicate = 0 AND "
393 "endtime < DATE_SUB(CURRENT_DATE, INTERVAL :CLEAN DAY);");
412 if (!MythVersion.isEmpty() && !MythVersion.startsWith(
"fixes/"))
415 MythVersion =
"trunk";
418 LOG(VB_GENERAL, LOG_INFO,
419 QString(
"Loading themes for %1").arg(MythVersion));
423 static const QRegularExpression
kVersionDateRE {
"\\.[0-9]{8,}.*" };
424 MythVersion = MYTH_BINARY_VERSION;
426 LOG(VB_GENERAL, LOG_INFO,
427 QString(
"Loading themes for %1").arg(MythVersion));
431 static const QRegularExpression subexp
432 {
"v[0-9]+\\.([0-9]+)-*", QRegularExpression::CaseInsensitiveOption };
434 if (match.hasMatch())
437 int idx = match.capturedView(1).toInt();
438 for ( ; idx > 0; --idx)
440 subversion = MythVersion +
"." + QString::number(idx);
441 LOG(VB_GENERAL, LOG_INFO,
442 QString(
"Loading themes for %1").arg(subversion));
453 remoteThemesDir.append(
"/tmp/remotethemes");
455 QDir dir(remoteThemesDir);
456 if (!dir.exists() && !dir.mkpath(remoteThemesDir))
458 LOG(VB_GENERAL, LOG_ERR,
459 QString(
"HouseKeeper: Error creating %1 "
460 "directory for remote themes info cache.")
461 .arg(remoteThemesDir));
465 QString remoteThemesFile = remoteThemesDir;
466 remoteThemesFile.append(
"/themes.zip");
468 m_url = QString(
"%1/%2/themes.zip")
470 "http://themes.mythtv.org/themes/repository"),
479 LOG(VB_GENERAL, (LogLevel_t)download_log_level,
480 QString(
"HouseKeeper: Failed to download %1 "
481 "remote themes info package.").arg(
m_url));
485 if (!
extractZIP(remoteThemesFile, remoteThemesDir))
487 LOG(VB_GENERAL, LOG_ERR,
488 QString(
"HouseKeeper: Error extracting %1 "
489 "remote themes info package.").arg(remoteThemesFile));
490 QFile::remove(remoteThemesFile);
522 args <<
"--updateradiostreams";
525 LOG(VB_GENERAL, LOG_INFO, QString(
"Performing Radio Streams Update: %1 %2")
526 .arg(command,
args.join(
" ")));
538 LOG(VB_GENERAL, LOG_ERR, QString(
"Update Radio Streams command '%1' failed")
543 LOG(VB_GENERAL, LOG_INFO, QString(
"Radio Streams Update Complete"));
557 if (!setting.isEmpty())
559 GetMythDB()->ClearSetting(
"MusicStreamListModified");
590 QString command =
GetAppBinDir() +
"mythmetadatalookup";
592 args <<
"--refresh-all-artwork";
595 LOG(VB_GENERAL, LOG_INFO, QString(
"Performing Artwork Refresh: %1 %2")
596 .arg(command,
args.join(
" ")));
608 LOG(VB_GENERAL, LOG_ERR, QString(
"Artwork command '%1' failed")
612 LOG(VB_GENERAL, LOG_INFO, QString(
"Artwork Refresh Complete"));
697 LOG(VB_GENERAL, LOG_DEBUG,
"MythFillDatabase is disabled. Cannot run.");
709 "1970-01-01T00:00:00"));
710 LOG(VB_GENERAL, LOG_DEBUG,
711 QString(
"MythFillDatabase scheduled to run at %1.")
712 .arg(nextRun.toString()));
714 return nextRun <= now;
721 LOG(VB_GENERAL, LOG_DEBUG,
"Performing daily run check.");
741 if (mfpath ==
"mythfilldatabase")
747 QString cmd = QString(
"%1 %2").arg(mfpath, mfarg);
759 LOG(VB_GENERAL, LOG_ERR, QString(
"MythFillDatabase command '%1' failed")
bool isActive(void) const
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool DoRun(void) override
bool extractZIP(QString zipFile, const QString &outDir)
bool DoRun(void) override
static const QRegularExpression kVersionDateRE
void Term(bool force=false)
void SetHourWindowFromDB(void)
uint GetStatus(void) const
bool DoRun(void) override
void Terminate(void) override
bool DoCheckRun(const QDateTime &now) override
static void CleanupInUsePrograms(void)
MythSystemLegacy * m_msMFD
const char * GetMythSourceVersion()
bool DoCheckRun(const QDateTime &now) override
QVariant value(int i) const
~RadioStreamUpdateTask(void) override
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void Terminate(void) override
bool DoCheckRun(const QDateTime &now) override
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
bool DoRun(void) override
static void CleanupOldRecordings(void)
@ GENERIC_EXIT_OK
Exited with no error.
MythSystemLegacy * m_msMU
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
bool InWindow(const QDateTime &now) override
RadioStreamUpdateTask(void)
MythFillDatabaseTask(void)
static constexpr const char * MYTH_APPNAME_MYTHBACKEND
static void CleanupRecordedTables(void)
~ArtworkTask(void) override
~MythFillDatabaseTask(void) override
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
static void DBError(const QString &where, const MSqlQuery &query)
virtual void SetHourWindow(std::chrono::hours min, std::chrono::hours max)
void Terminate(void) override
static void CleanupOldJobsInQueue()
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
bool LoadVersion(const QString &version, int download_log_level)
static void CleanupOrphanedLiveTV(void)
static constexpr int64_t kFourHours
uint Wait(std::chrono::seconds timeout=0s)
bool download(const QString &url, const QString &dest, bool reload=false)
Downloads a URL to a file in blocking mode.
void cancelDownload(const QString &url, bool block=true)
Cancel a queued or current download.
bool isConnected(void) const
Only updated once during object creation.
@ kMSPropagateLogs
add arguments for MythTV log propagation
static void CleanupProgramListings(void)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
int GetNumSetting(const QString &key, int defaultval=0)
bool DoRun(void) override
@ kMSRunShell
run process through shell
@ kMSAutoCleanup
automatically delete if backgrounded
const char * GetMythSourcePath()
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
bool GetBoolSetting(const QString &key, bool defaultval=false)
void Terminate(void) override
MythSystemLegacy * m_msMML
duration< CHRONO_TYPE, ratio< 86400 > > days
static constexpr const char * MYTH_APPNAME_MYTHFRONTEND
static bool UseSuggestedTime(void)
bool DoRun(void) override
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
static void CleanupChannelTables(void)
QString GetAppBinDir(void)
@ kHKRunOnStartup
task is queued when HouseKeeper is started
QString GetHostName(void)
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
bool DoCheckRun(const QDateTime &now) override
bool DoRun(void) override
@ GENERIC_EXIT_RUNNING
Process is running.
Modified PeriodicHouseKeeperTask for tasks to be run once daily.
static void RecoverOldJobsInQueue()
@ kHKGlobal
task should only run once per cluster e.g.
QString GetSetting(const QString &key, const QString &defaultval="")
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
bool DoCheckRun(const QDateTime &now) override