Go to the documentation of this file.
55 #include <QMutexLocker>
117 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1 Running? %2/In window? %3.")
140 LOG(VB_GENERAL, LOG_INFO, QString(
"Running HouseKeeperTask '%1'.")
145 LOG(VB_GENERAL, LOG_WARNING, QString(
"HouseKeeperTask '%1' already "
146 "running. Refusing to run concurrently").arg(
m_dbTag));
155 LOG(VB_GENERAL, LOG_INFO, QString(
"HouseKeeperTask '%1' Failed.")
160 LOG(VB_GENERAL, LOG_INFO,
161 QString(
"HouseKeeperTask '%1' Finished Successfully.")
194 query.
prepare(
"SELECT lastrun,lastsuccess FROM housekeeping"
196 " AND hostname IS NULL");
200 query.
prepare(
"SELECT lastrun,lastsuccess FROM housekeeping"
202 " AND hostname = :HOST");
233 query.
prepare(
"UPDATE `housekeeping` SET `lastrun`=:TIME,"
234 " `lastsuccess`=:STIME"
235 " WHERE `tag` = :TAG"
236 " AND `hostname` IS NULL");
240 query.
prepare(
"UPDATE `housekeeping` SET `lastrun`=:TIME,"
241 " `lastsuccess`=:STIME"
242 " WHERE `tag` = :TAG"
243 " AND `hostname` = :HOST");
258 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: UPDATEd %2 run time.")
266 query.
prepare(
"INSERT INTO `housekeeping`"
267 " (`tag`, `lastrun`, `lastsuccess`)"
268 " VALUES (:TAG, :TIME, :STIME)");
272 query.
prepare(
"INSERT INTO `housekeeping`"
273 " (`tag`, `hostname`, `lastrun`, `lastsuccess`)"
274 " VALUES (:TAG, :HOST, :TIME, :STIME)");
286 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: INSERTed %2 run time.")
293 msg = QString(
"HOUSE_KEEPER_SUCCESSFUL %1 %2 %3");
295 msg = QString(
"HOUSE_KEEPER_RUNNING %1 %2 %3");
328 std::chrono::seconds period,
float min,
float max, std::chrono::seconds retry,
331 m_windowPercent(min, max)
340 std::chrono::seconds period =
m_period;
377 auto elapsed = std::chrono::seconds(
GetLastRun().secsTo(now));
392 double prob = 1.0 - (duration_cast<floatsecs>(elapsed -
m_windowElapsed.first) /
408 bool res = (rand() > (int)(prob2 *
static_cast<double>(RAND_MAX)));
421 auto elapsed = std::chrono::seconds(
GetLastRun().secsTo(now));
452 m_windowHour(0h, 23h)
458 std::chrono::hours minhour, std::chrono::hours maxhour,
461 m_windowHour(minhour, maxhour)
481 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1 Run window between %2 - %3.")
498 auto hour = std::chrono::hours(now.time().hour());
629 QMap<QString,HouseKeeperTask*>::iterator it =
m_taskMap.begin();
641 QString tag = task->
GetTag();
645 LOG(VB_GENERAL, LOG_ERR,
646 QString(
"HouseKeeperTask '%1' already registered. "
647 "Rejecting duplicate.").arg(tag));
651 LOG(VB_GENERAL, LOG_INFO,
652 QString(
"Registering HouseKeeperTask '%1'.").arg(tag));
682 query.
prepare(
"SELECT `tag`,`lastrun`"
683 " FROM `housekeeping`"
684 " WHERE `hostname` = :HOST"
685 " OR `hostname` IS NULL");
695 QString tag = query.
value(0).toString();
707 if ((*it)->CheckImmediate())
710 (*it)->UpdateLastRun();
713 else if ((*it)->CheckStartup())
716 LOG(VB_GENERAL, LOG_INFO,
717 QString(
"Queueing HouseKeeperTask '%1'.").arg(it.key()));
724 LOG(VB_GENERAL, LOG_INFO,
"Starting HouseKeeper.");
731 LOG(VB_GENERAL, LOG_DEBUG,
"Running HouseKeeper.");
738 if ((*it)->CheckRun(now))
741 LOG(VB_GENERAL, LOG_INFO,
742 QString(
"Queueing HouseKeeperTask '%1'.").arg(it.key()));
763 if ((*it)->isRunning())
775 LOG(VB_GENERAL, LOG_DEBUG,
776 QString(
"Discarded HouseKeepingThreads have completed and "
777 "been deleted. Current count %1 -> %2.")
778 .arg(count1).arg(count2));
804 LOG(VB_GENERAL, LOG_DEBUG,
"Running initial HouseKeepingThread.");
815 LOG(VB_GENERAL, LOG_DEBUG,
816 QString(
"Current HouseKeepingThread is delayed on task, "
817 "spawning replacement. Current count %1.")
828 LOG(VB_GENERAL, LOG_DEBUG,
"Waking HouseKeepingThread.");
840 if ((me->Message().left(20) ==
"HOUSE_KEEPER_RUNNING") ||
841 (me->Message().left(23) ==
"HOUSE_KEEPER_SUCCESSFUL"))
843 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
844 QStringList tokens = me->
Message()
845 .split(
" ", QString::SkipEmptyParts);
847 QStringList tokens = me->Message()
848 .split(
" ", Qt::SkipEmptyParts);
850 if (tokens.size() != 4)
854 QString tag = tokens[2];
856 bool successful = me->Message().contains(
"SUCCESSFUL");
868 m_taskMap[tag]->SetLastRun(last, successful);
This decrements the reference on destruction.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
static const Type kMythEventMessage
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
HouseKeeperStartup m_startup
std::chrono::seconds m_retry
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
QList< HouseKeepingThread * > m_threadList
void SetLastRun(const QDateTime &last, bool successful=true) override
virtual bool InWindow(const QDateTime &now)
bool CheckImmediate(void)
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
virtual bool DoCheckRun(const QDateTime &)
QDateTime QueryLastRun(void)
This class is used as a container for messages.
static constexpr T chronomult(T duration, double f)
Multiply a duration by a float, returning a duration.
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
QVariant value(int i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
bool DoCheckRun(const QDateTime &now) override
QQueue< HouseKeeperTask * > m_taskQueue
void customEvent(QEvent *e) override
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
void RegisterTask(HouseKeeperTask *task)
QDateTime UpdateLastRun(bool successful=true)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
const QString & Message() const
bool InWindow(const QDateTime &now) override
void addListener(QObject *listener)
Add a listener to the observable.
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
PeriodicHouseKeeperTask(const QString &dbTag, std::chrono::seconds period, float min=0.5, float max=1.1, std::chrono::seconds retry=0s, HouseKeeperScope scope=kHKGlobal, HouseKeeperStartup startup=kHKNormal)
virtual void SetLastRun(const QDateTime &last, bool successful=true)
virtual void CalculateWindow(void)
void SendEvent(const MythEvent &event)
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 CalculateWindow(void) override
QDateTime GetLastRun(void)
HouseKeeperTask(const QString &dbTag, HouseKeeperScope scope=kHKGlobal, HouseKeeperStartup startup=kHKNormal)
Modified HouseKeeperTask for tasks to be run at a regular interval.
Thread used to perform queued HouseKeeper tasks.
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
@ kHKRunImmediateOnStartup
task is run during HouseKeeper startup
bool isConnected(void) const
Only updated once during object creation.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QDateTime UpdateLastRun(const QDateTime &last, bool successful=true) override
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
QPair< std::chrono::seconds, std::chrono::seconds > m_windowElapsed
QMap< QString, HouseKeeperTask * > m_taskMap
QPair< std::chrono::hours, std::chrono::hours > m_windowHour
QDateTime QueryLastSuccess(void)
virtual void SetWindow(float min, float max)
virtual bool PastWindow(const QDateTime &now)
void StartThread(void)
Wake the primary run thread, or create a new one.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
std::chrono::seconds m_period
@ kHKInst
task should run on every process e.g.
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
@ kHKRunOnStartup
task is queued when HouseKeeper is started
int numRowsAffected() const
QString GetHostName(void)
QPair< float, float > m_windowPercent
QDateTime GetLastSuccess(void)
QWaitCondition m_waitCondition
Definition for a single task to be run by the HouseKeeper.
bool CheckRun(const QDateTime &now)
DailyHouseKeeperTask(const QString &dbTag, HouseKeeperScope scope=kHKGlobal, HouseKeeperStartup startup=kHKNormal)
@ kHKLocal
task should only run once per machine e.g.
void removeListener(QObject *listener)
Remove a listener to the observable.
HouseKeeperTask * GetQueuedTask(void)
General purpose reference counter.
bool ConfirmRun(void) const
@ kHKGlobal
task should only run once per cluster e.g.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.