Go to the documentation of this file.
55 #include <QMutexLocker>
121 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1 Running? %2/In window? %3.")
144 LOG(VB_GENERAL, LOG_INFO, QString(
"Running HouseKeeperTask '%1'.")
149 LOG(VB_GENERAL, LOG_WARNING, QString(
"HouseKeeperTask '%1' already "
150 "running. Refusing to run concurrently").arg(
m_dbTag));
159 LOG(VB_GENERAL, LOG_INFO, QString(
"HouseKeeperTask '%1' Failed.")
164 LOG(VB_GENERAL, LOG_INFO,
165 QString(
"HouseKeeperTask '%1' Finished Successfully.")
198 query.
prepare(
"SELECT lastrun,lastsuccess FROM housekeeping"
200 " AND hostname IS NULL");
204 query.
prepare(
"SELECT lastrun,lastsuccess FROM housekeeping"
206 " AND hostname = :HOST");
237 query.
prepare(
"UPDATE `housekeeping` SET `lastrun`=:TIME,"
238 " `lastsuccess`=:STIME"
239 " WHERE `tag` = :TAG"
240 " AND `hostname` IS NULL");
244 query.
prepare(
"UPDATE `housekeeping` SET `lastrun`=:TIME,"
245 " `lastsuccess`=:STIME"
246 " WHERE `tag` = :TAG"
247 " AND `hostname` = :HOST");
262 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: UPDATEd %2 run time.")
270 query.
prepare(
"INSERT INTO `housekeeping`"
271 " (`tag`, `lastrun`, `lastsuccess`)"
272 " VALUES (:TAG, :TIME, :STIME)");
276 query.
prepare(
"INSERT INTO `housekeeping`"
277 " (`tag`, `hostname`, `lastrun`, `lastsuccess`)"
278 " VALUES (:TAG, :HOST, :TIME, :STIME)");
290 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: INSERTed %2 run time.")
297 msg = QString(
"HOUSE_KEEPER_SUCCESSFUL %1 %2 %3");
299 msg = QString(
"HOUSE_KEEPER_RUNNING %1 %2 %3");
332 std::chrono::seconds period,
float min,
float max, std::chrono::seconds retry,
335 m_windowPercent(min, max)
344 std::chrono::seconds period =
m_period;
381 auto elapsed = std::chrono::seconds(
GetLastRun().secsTo(now));
396 double prob = 1.0 - (duration_cast<floatsecs>(elapsed -
m_windowElapsed.first) /
412 bool res = (rand() > (int)(prob2 *
static_cast<double>(RAND_MAX)));
425 auto elapsed = std::chrono::seconds(
GetLastRun().secsTo(now));
456 m_windowHour(0h, 23h)
462 std::chrono::hours minhour, std::chrono::hours maxhour,
465 m_windowHour(minhour, maxhour)
485 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1 Run window between %2 - %3.")
502 auto hour = std::chrono::hours(now.time().hour());
611 for (
auto *it : std::as_const(
m_taskMap))
633 QMap<QString,HouseKeeperTask*>::iterator it =
m_taskMap.begin();
645 QString tag = task->
GetTag();
649 LOG(VB_GENERAL, LOG_ERR,
650 QString(
"HouseKeeperTask '%1' already registered. "
651 "Rejecting duplicate.").arg(tag));
655 LOG(VB_GENERAL, LOG_INFO,
656 QString(
"Registering HouseKeeperTask '%1'.").arg(tag));
686 query.
prepare(
"SELECT `tag`,`lastrun`"
687 " FROM `housekeeping`"
688 " WHERE `hostname` = :HOST"
689 " OR `hostname` IS NULL");
699 QString tag = query.
value(0).toString();
711 if ((*it)->CheckImmediate())
714 (*it)->UpdateLastRun();
717 else if ((*it)->CheckStartup())
720 LOG(VB_GENERAL, LOG_INFO,
721 QString(
"Queueing HouseKeeperTask '%1'.").arg(it.key()));
728 LOG(VB_GENERAL, LOG_INFO,
"Starting HouseKeeper.");
735 LOG(VB_GENERAL, LOG_DEBUG,
"Running HouseKeeper.");
742 if ((*it)->CheckRun(now))
745 LOG(VB_GENERAL, LOG_INFO,
746 QString(
"Queueing HouseKeeperTask '%1'.").arg(it.key()));
767 if ((*it)->isRunning())
779 LOG(VB_GENERAL, LOG_DEBUG,
780 QString(
"Discarded HouseKeepingThreads have completed and "
781 "been deleted. Current count %1 -> %2.")
782 .arg(count1).arg(count2));
808 LOG(VB_GENERAL, LOG_DEBUG,
"Running initial HouseKeepingThread.");
819 LOG(VB_GENERAL, LOG_DEBUG,
820 QString(
"Current HouseKeepingThread is delayed on task, "
821 "spawning replacement. Current count %1.")
832 LOG(VB_GENERAL, LOG_DEBUG,
"Waking HouseKeepingThread.");
844 if ((me->Message().left(20) ==
"HOUSE_KEEPER_RUNNING") ||
845 (me->Message().left(23) ==
"HOUSE_KEEPER_SUCCESSFUL"))
847 QStringList tokens = me->
Message()
848 .split(
" ", Qt::SkipEmptyParts);
849 if (tokens.size() != 4)
853 QString tag = tokens[2];
855 bool successful = me->Message().contains(
"SUCCESSFUL");
867 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.