MythTV  master
housekeeper.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2 *
3 * Class HouseKeeperTask
4 * Class HouseKeeperThread
5 * Class HouseKeeper
6 *
7 * Copyright (C) Raymond Wagner 2013
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23 
24 
25 
52 #include <chrono>
53 #include <utility>
54 
55 #include <QMutexLocker>
56 
57 #include "mythevent.h"
58 #include "mythdbcon.h"
59 #include "housekeeper.h"
60 #include "mythcorecontext.h"
61 
100  ReferenceCounter(dbTag), m_dbTag(dbTag), m_scope(scope),
101  m_startup(startup),
102  m_lastRun(MythDate::fromSecsSinceEpoch(0)),
103  m_lastSuccess(MythDate::fromSecsSinceEpoch(0)),
104  m_lastUpdate(MythDate::fromSecsSinceEpoch(0))
105 {
106 }
107 
108 bool HouseKeeperTask::CheckRun(const QDateTime& now)
109 {
110  LOG(VB_GENERAL, LOG_DEBUG, QString("Checking to run %1").arg(GetTag()));
111  bool check = false;
112  if (!m_confirm && !m_running && (check = DoCheckRun(now)))
113  {
114  // if m_confirm is already set, the task is already in the queue
115  // and should not be queued a second time
116  m_confirm = true;
117  }
118  return check;
119 }
120 
122 {
123  return ((m_startup == kHKRunImmediateOnStartup) &&
125 }
126 
128 {
130  {
131  m_confirm = true;
132  return true;
133  }
134  return false;
135 }
136 
138 {
139  LOG(VB_GENERAL, LOG_INFO, QString("Running HouseKeeperTask '%1'.")
140  .arg(m_dbTag));
141  if (m_running)
142  {
143  // something else is already running me, bail out
144  LOG(VB_GENERAL, LOG_WARNING, QString("HouseKeeperTask '%1' already "
145  "running. Refusing to run concurrently").arg(m_dbTag));
146  return false;
147  }
148 
149  m_running = true;
150  bool res = DoRun();
151  m_running = false;
152  if (!res)
153  {
154  LOG(VB_GENERAL, LOG_INFO, QString("HouseKeeperTask '%1' Failed.")
155  .arg(m_dbTag));
156  }
157  else
158  {
159  LOG(VB_GENERAL, LOG_INFO,
160  QString("HouseKeeperTask '%1' Finished Successfully.")
161  .arg(m_dbTag));
162  }
163  return res;
164 }
165 
167 {
168  QueryLast();
169  return m_lastRun;
170 }
171 
173 {
174  QueryLast();
175  return m_lastRun;
176 }
177 
179 {
180  if (m_scope != kHKInst)
181  {
182  if (m_lastUpdate.addSecs(30) > MythDate::current())
183  // just to cut down on unnecessary queries
184  return;
185 
186  MSqlQuery query(MSqlQuery::InitCon());
187 
190 
191  if (m_scope == kHKGlobal)
192  {
193  query.prepare("SELECT lastrun,lastsuccess FROM housekeeping"
194  " WHERE tag = :TAG"
195  " AND hostname IS NULL");
196  }
197  else
198  {
199  query.prepare("SELECT lastrun,lastsuccess FROM housekeeping"
200  " WHERE tag = :TAG"
201  " AND hostname = :HOST");
202  query.bindValue(":HOST", gCoreContext->GetHostName());
203  }
204 
205  query.bindValue(":TAG", m_dbTag);
206 
207  if (query.exec() && query.next())
208  {
209  m_lastRun = MythDate::as_utc(query.value(0).toDateTime());
210  m_lastSuccess = MythDate::as_utc(query.value(1).toDateTime());
211  }
212  }
213 
215 }
216 
217 QDateTime HouseKeeperTask::UpdateLastRun(const QDateTime& last, bool successful)
218 {
219  m_lastRun = last;
220  if (successful)
221  m_lastSuccess = last;
222  m_confirm = false;
223 
224  if (m_scope != kHKInst)
225  {
226  MSqlQuery query(MSqlQuery::InitCon());
227  if (!query.isConnected())
228  return last;
229 
231  {
232  // not previously set, perform insert
233 
234  if (m_scope == kHKGlobal)
235  {
236  query.prepare("INSERT INTO housekeeping"
237  " (tag, lastrun, lastsuccess)"
238  " VALUES (:TAG, :TIME, :STIME)");
239  }
240  else
241  {
242  query.prepare("INSERT INTO housekeeping"
243  " (tag, hostname, lastrun, lastsuccess)"
244  " VALUES (:TAG, :HOST, :TIME, :STIME)");
245  }
246  }
247  else
248  {
249  // previously set, perform update
250 
251  if (m_scope == kHKGlobal)
252  {
253  query.prepare("UPDATE housekeeping SET lastrun=:TIME,"
254  " lastsuccess=:STIME"
255  " WHERE tag = :TAG"
256  " AND hostname IS NULL");
257  }
258  else
259  {
260  query.prepare("UPDATE housekeeping SET lastrun=:TIME,"
261  " lastsuccess=:STIME"
262  " WHERE tag = :TAG"
263  " AND hostname = :HOST");
264  }
265  }
266 
267  if (m_scope == kHKGlobal)
268  {
269  LOG(VB_GENERAL, LOG_DEBUG,
270  QString("Updating global run time for %1").arg(m_dbTag));
271  }
272  else
273  {
274  LOG(VB_GENERAL, LOG_DEBUG,
275  QString("Updating local run time for %1").arg(m_dbTag));
276  }
277 
278  if (m_scope == kHKLocal)
279  query.bindValue(":HOST", gCoreContext->GetHostName());
280  query.bindValue(":TAG", m_dbTag);
281  query.bindValue(":TIME", MythDate::as_utc(m_lastRun));
282  query.bindValue(":STIME", MythDate::as_utc(m_lastSuccess));
283 
284  if (!query.exec())
285  MythDB::DBError("HouseKeeperTask::updateLastRun", query);
286  }
287 
288  QString msg;
289  if (successful)
290  msg = QString("HOUSE_KEEPER_SUCCESSFUL %1 %2 %3");
291  else
292  msg = QString("HOUSE_KEEPER_RUNNING %1 %2 %3");
293  msg = msg.arg(gCoreContext->GetHostName(),
294  m_dbTag,
298 
299  return last;
300 }
301 
302 void HouseKeeperTask::SetLastRun(const QDateTime &last, bool successful)
303 {
304  m_lastRun = last;
305  if (successful)
306  m_lastSuccess = last;
307 
309 }
310 
325  std::chrono::seconds period, float min, float max, std::chrono::seconds retry,
327  HouseKeeperTask(dbTag, scope, startup), m_period(period), m_retry(retry),
328  m_windowPercent(min, max), m_currentProb(1.0)
329 {
331  if (m_retry == 0s)
332  m_retry = m_period;
333 }
334 
336 {
337  std::chrono::seconds period = m_period;
338  if (GetLastRun() > GetLastSuccess())
339  {
340  // last attempt was not successful
341  // try shortened period
342  period = m_retry;
343  }
344 
345  m_windowElapsed.first = chronomult(period, m_windowPercent.first);
346  m_windowElapsed.second = chronomult(period, m_windowPercent.second);
347 }
348 
349 void PeriodicHouseKeeperTask::SetWindow(float min, float max)
350 {
351  m_windowPercent.first = min;
352  m_windowPercent.second = max;
353  CalculateWindow();
354 }
355 
356 QDateTime PeriodicHouseKeeperTask::UpdateLastRun(const QDateTime& last,
357  bool successful)
358 {
359  QDateTime res = HouseKeeperTask::UpdateLastRun(last, successful);
360  CalculateWindow();
361  m_currentProb = 1.0;
362  return res;
363 }
364 
365 void PeriodicHouseKeeperTask::SetLastRun(const QDateTime& last, bool successful)
366 {
367  HouseKeeperTask::SetLastRun(last, successful);
368  CalculateWindow();
369  m_currentProb = 1.0;
370 }
371 
372 bool PeriodicHouseKeeperTask::DoCheckRun(const QDateTime& now)
373 {
374  auto elapsed = std::chrono::seconds(GetLastRun().secsTo(now));
375 
376  if (elapsed < 0s)
377  // something bad has happened. let's just move along
378  return false;
379 
380  if (elapsed < m_windowElapsed.first)
381  // insufficient time elapsed to test
382  return false;
383  if (elapsed > m_windowElapsed.second)
384  // too much time has passed. force run
385  return true;
386 
387  // calculate probability that task should not have yet run
388  // it's backwards, but it makes the math simplier
389  double prob = 1.0 - (duration_cast<floatsecs>(elapsed - m_windowElapsed.first) /
390  duration_cast<floatsecs>(m_windowElapsed.second - m_windowElapsed.first));
391  if (m_currentProb < prob)
392  // more bad stuff
393  return false;
394 
395  // calculate current probability to achieve overall probability
396  // this should be nearly one
397  double prob2 = prob/m_currentProb;
398  // so rand() should have to return nearly RAND_MAX to get a positive
399  // remember, this is computing the probability that up to this point, one
400  // of these tests has returned positive, so each individual test has
401  // a necessarily low probability
402  //
403  // Pseudo-random is good enough. Don't need a true random.
404  // NOLINTNEXTLINE(cert-msc30-c,cert-msc50-cpp)
405  bool res = (rand() > (int)(prob2 * static_cast<double>(RAND_MAX)));
406  m_currentProb = prob;
407 // if (res)
408 // LOG(VB_GENERAL, LOG_DEBUG, QString("%1 will run: this=%2; total=%3")
409 // .arg(GetTag()).arg(1-prob2).arg(1-prob));
410 // else
411 // LOG(VB_GENERAL, LOG_DEBUG, QString("%1 will not run: this=%2; total=%3")
412 // .arg(GetTag()).arg(1-prob2).arg(1-prob));
413  return res;
414 }
415 
416 bool PeriodicHouseKeeperTask::InWindow(const QDateTime& now)
417 {
418  auto elapsed = std::chrono::seconds(GetLastRun().secsTo(now));
419 
420  if (elapsed < 0s)
421  // something bad has happened. let's just move along
422  return false;
423 
424  return (elapsed > m_windowElapsed.first) &&
425  (elapsed < m_windowElapsed.second);
426 }
427 
428 bool PeriodicHouseKeeperTask::PastWindow(const QDateTime &now)
429 {
430  return std::chrono::seconds(GetLastRun().secsTo(now)) > m_windowElapsed.second;
431 }
432 
448  PeriodicHouseKeeperTask(dbTag, 24h, .5, 1.5, 0s, scope, startup),
449  m_windowHour(0h, 23h)
450 {
452 }
453 
455  std::chrono::hours minhour, std::chrono::hours maxhour,
457  PeriodicHouseKeeperTask(dbTag, 24h, .5, 1.5, 0s, scope, startup),
458  m_windowHour(minhour, maxhour)
459 {
461 }
462 
464 {
466  QDate date = GetLastRun().addDays(1).date();
467 
468  QDateTime tmp = QDateTime(date, QTime(m_windowHour.first.count(), 0));
469  if (GetLastRun().addSecs(m_windowElapsed.first.count()) < tmp)
470  m_windowElapsed.first = std::chrono::seconds(GetLastRun().secsTo(tmp));
471 
472  tmp = QDateTime(date, QTime(m_windowHour.second.count(), 30));
473  // we want to make sure this gets run before the end of the day
474  // so add a 30 minute buffer prior to the end of the window
475  if (GetLastRun().addSecs(m_windowElapsed.second.count()) > tmp)
476  m_windowElapsed.second = std::chrono::seconds(GetLastRun().secsTo(tmp));
477 
478  LOG(VB_GENERAL, LOG_DEBUG, QString("%1 Run window between %2 - %3.")
479  .arg(GetTag()).arg(m_windowElapsed.first.count()).arg(m_windowElapsed.second.count()));
480 }
481 
482 void DailyHouseKeeperTask::SetHourWindow(std::chrono::hours min, std::chrono::hours max)
483 {
484  m_windowHour.first = min;
485  m_windowHour.second = max;
486  CalculateWindow();
487 }
488 
489 bool DailyHouseKeeperTask::InWindow(const QDateTime& now)
490 {
492  // parent says we're in the window
493  return true;
494 
495  auto hour = std::chrono::hours(now.time().hour());
496  // true if we've missed the window, but we're within our time constraints
497  return PastWindow(now) && (m_windowHour.first <= hour)
498  && (m_windowHour.second > hour);
499 }
500 
512 {
513  RunProlog();
514  m_waitMutex.lock();
515  HouseKeeperTask *task = nullptr;
516 
517  while (m_keepRunning)
518  {
519  m_idle = false;
520 
521  while ((task = m_parent->GetQueuedTask()))
522  {
523  // pull task from housekeeper and process it
524  ReferenceLocker rlock(task);
525 
526  if (!task->ConfirmRun())
527  {
528  // something else has caused the lastrun time to
529  // change since this was requested to run. abort.
530  task = nullptr;
531  continue;
532  }
533 
534  task->UpdateLastRun(false);
535  if (task->Run())
536  task->UpdateLastRun(task->GetLastRun(), true);
537  task = nullptr;
538 
539  if (!m_keepRunning)
540  // thread has been discarded, don't try to start another task
541  break;
542  }
543 
544  m_idle = true;
545 
546  if (!m_keepRunning)
547  // short out rather than potentially hitting another sleep cycle
548  break;
549 
551  }
552 
553  m_waitMutex.unlock();
554  RunEpilog();
555 }
556 
574 {
575  m_timer = new QTimer(this);
576  connect(m_timer, &QTimer::timeout, this, &HouseKeeper::Run);
577  m_timer->setInterval(1min);
578  m_timer->setSingleShot(false);
579 }
580 
582 {
584 
585  if (m_timer)
586  {
587  m_timer->stop();
588  disconnect(m_timer);
589  delete m_timer;
590  m_timer = nullptr;
591  }
592 
593  {
594  // remove anything from the queue first, so it does not start
595  QMutexLocker queueLock(&m_queueLock);
596  while (!m_taskQueue.isEmpty())
597  m_taskQueue.takeFirst()->DecrRef();
598  }
599 
600  {
601  // issue a terminate call to any long-running tasks
602  // this is just a noop unless overwritten by a subclass
603  QMutexLocker mapLock(&m_mapLock);
604  for (auto *it : qAsConst(m_taskMap))
605  it->Terminate();
606  }
607 
608  if (!m_threadList.isEmpty())
609  {
610  QMutexLocker threadLock(&m_threadLock);
611  // tell primary thread to self-terminate and wake it
612  m_threadList.first()->Discard();
613  m_threadList.first()->Wake();
614  // wait for any remaining threads to self-terminate and close
615  while (!m_threadList.isEmpty())
616  {
617  HouseKeepingThread *thread = m_threadList.takeFirst();
618  thread->wait();
619  delete thread;
620  }
621  }
622 
623  {
624  // unload any registered tasks
625  QMutexLocker mapLock(&m_mapLock);
626  QMap<QString,HouseKeeperTask*>::iterator it = m_taskMap.begin();
627  while (it != m_taskMap.end())
628  {
629  (*it)->DecrRef();
630  it = m_taskMap.erase(it);
631  }
632  }
633 }
634 
636 {
637  QMutexLocker mapLock(&m_mapLock);
638  QString tag = task->GetTag();
639  if (m_taskMap.contains(tag))
640  {
641  task->DecrRef();
642  LOG(VB_GENERAL, LOG_ERR,
643  QString("HouseKeeperTask '%1' already registered. "
644  "Rejecting duplicate.").arg(tag));
645  }
646  else
647  {
648  LOG(VB_GENERAL, LOG_INFO,
649  QString("Registering HouseKeeperTask '%1'.").arg(tag));
650  m_taskMap.insert(tag, task);
651  }
652 }
653 
655 {
656  QMutexLocker queueLock(&m_queueLock);
657  HouseKeeperTask *task = nullptr;
658 
659  if (!m_taskQueue.isEmpty())
660  {
661  task = m_taskQueue.dequeue();
662  }
663 
664  // returning nullptr tells the thread that the queue is empty and
665  // to go into standby
666  return task;
667 }
668 
670 {
671  // no need to be fine grained, nothing else should be accessing this map
672  QMutexLocker mapLock(&m_mapLock);
673 
674  if (m_timer->isActive())
675  // Start() should only be called once
676  return;
677 
678  MSqlQuery query(MSqlQuery::InitCon());
679  query.prepare("SELECT tag,lastrun"
680  " FROM housekeeping"
681  " WHERE hostname = :HOST"
682  " OR hostname IS NULL");
683  query.bindValue(":HOST", gCoreContext->GetHostName());
684 
685  if (!query.exec())
686  MythDB::DBError("HouseKeeper::Run", query);
687  else
688  {
689  while (query.next())
690  {
691  // loop through housekeeping table and load last run timestamps
692  QString tag = query.value(0).toString();
693  QDateTime lastrun = MythDate::as_utc(query.value(1).toDateTime());
694 
695  if (m_taskMap.contains(tag))
696  m_taskMap[tag]->SetLastRun(lastrun);
697  }
698  }
699 
700  gCoreContext->addListener(this);
701 
702  for (auto it = m_taskMap.cbegin(); it != m_taskMap.cend(); ++it)
703  {
704  if ((*it)->CheckImmediate())
705  {
706  // run any tasks marked for immediate operation in-thread
707  (*it)->UpdateLastRun();
708  (*it)->Run();
709  }
710  else if ((*it)->CheckStartup())
711  {
712  // queue any tasks marked for startup
713  LOG(VB_GENERAL, LOG_INFO,
714  QString("Queueing HouseKeeperTask '%1'.").arg(it.key()));
715  QMutexLocker queueLock(&m_queueLock);
716  (*it)->IncrRef();
717  m_taskQueue.enqueue(*it);
718  }
719  }
720 
721  LOG(VB_GENERAL, LOG_INFO, "Starting HouseKeeper.");
722 
723  m_timer->start();
724 }
725 
727 {
728  LOG(VB_GENERAL, LOG_DEBUG, "Running HouseKeeper.");
729 
730  QDateTime now = MythDate::current();
731 
732  QMutexLocker mapLock(&m_mapLock);
733  for (auto it = m_taskMap.begin(); it != m_taskMap.end(); ++it)
734  {
735  if ((*it)->CheckRun(now))
736  {
737  // check if any tasks are ready to run, and add to queue
738  LOG(VB_GENERAL, LOG_INFO,
739  QString("Queueing HouseKeeperTask '%1'.").arg(it.key()));
740  QMutexLocker queueLock(&m_queueLock);
741  (*it)->IncrRef();
742  m_taskQueue.enqueue(*it);
743  }
744  }
745 
746  if (!m_taskQueue.isEmpty())
747  StartThread();
748 
749  if (m_threadList.size() > 1)
750  {
751  // spent threads exist in the thread list
752  // check to see if any have finished up their task and terminated
753  QMutexLocker threadLock(&m_threadLock);
754  int count1 = m_threadList.size();
755 
756  auto it = m_threadList.begin();
757  ++it; // skip the primary thread
758  while (it != m_threadList.end())
759  {
760  if ((*it)->isRunning())
761  ++it;
762  else
763  {
764  delete *it;
765  it = m_threadList.erase(it);
766  }
767  }
768 
769  int count2 = m_threadList.size();
770  if (count1 > count2)
771  {
772  LOG(VB_GENERAL, LOG_DEBUG,
773  QString("Discarded HouseKeepingThreads have completed and "
774  "been deleted. Current count %1 -> %2.")
775  .arg(count1).arg(count2));
776  }
777  }
778 }
779 
794 {
795  QMutexLocker threadLock(&m_threadLock);
796 
797  if (m_threadList.isEmpty())
798  {
799  // we're running for the first time
800  // start up a new thread
801  LOG(VB_GENERAL, LOG_DEBUG, "Running initial HouseKeepingThread.");
802  auto *thread = new HouseKeepingThread(this);
803  m_threadList.append(thread);
804  thread->start();
805  }
806 
807  else if (!m_threadList.first()->isIdle())
808  {
809  // the old thread is still off processing something
810  // discard it and start a new one because we have more stuff
811  // that wants to run
812  LOG(VB_GENERAL, LOG_DEBUG,
813  QString("Current HouseKeepingThread is delayed on task, "
814  "spawning replacement. Current count %1.")
815  .arg(m_threadList.size()));
816  m_threadList.first()->Discard();
817  auto *thread = new HouseKeepingThread(this);
818  m_threadList.prepend(thread);
819  thread->start();
820  }
821 
822  else
823  {
824  // the old thread is idle, so just wake it for processing
825  LOG(VB_GENERAL, LOG_DEBUG, "Waking HouseKeepingThread.");
826  m_threadList.first()->Wake();
827  }
828 }
829 
831 {
832  if (e->type() == MythEvent::MythEventMessage)
833  {
834  auto *me = dynamic_cast<MythEvent*>(e);
835  if (me == nullptr)
836  return;
837  if ((me->Message().left(20) == "HOUSE_KEEPER_RUNNING") ||
838  (me->Message().left(23) == "HOUSE_KEEPER_SUCCESSFUL"))
839  {
840 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
841  QStringList tokens = me->Message()
842  .split(" ", QString::SkipEmptyParts);
843 #else
844  QStringList tokens = me->Message()
845  .split(" ", Qt::SkipEmptyParts);
846 #endif
847  if (tokens.size() != 4)
848  return;
849 
850  QString hostname = tokens[1];
851  QString tag = tokens[2];
852  QDateTime last = MythDate::fromString(tokens[3]);
853  bool successful = me->Message().contains("SUCCESSFUL");
854 
855  QMutexLocker mapLock(&m_mapLock);
856  if (m_taskMap.contains(tag))
857  {
858  if ((m_taskMap[tag]->GetScope() == kHKGlobal) ||
859  ((m_taskMap[tag]->GetScope() == kHKLocal) &&
861  {
862  // task being run in the same scope as us.
863  // update the run time so we don't attempt to run
864  // it ourselves
865  m_taskMap[tag]->SetLastRun(last, successful);
866  }
867  }
868  }
869  }
870 }
ReferenceLocker
This decrements the reference on destruction.
Definition: referencecounter.h:66
HouseKeeperTask::QueryLast
void QueryLast(void)
Definition: housekeeper.cpp:178
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:802
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:124
mythevent.h
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:80
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:78
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
HouseKeepingThread::m_waitMutex
QMutex m_waitMutex
Definition: housekeeper.h:146
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
HouseKeeperTask::m_startup
HouseKeeperStartup m_startup
Definition: housekeeper.h:77
HouseKeepingThread::m_keepRunning
bool m_keepRunning
Definition: housekeeper.h:144
PeriodicHouseKeeperTask::m_retry
std::chrono::seconds m_retry
Definition: housekeeper.h:102
MythDate::as_utc
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:23
HouseKeeper::m_threadList
QList< HouseKeepingThread * > m_threadList
Definition: housekeeper.h:177
PeriodicHouseKeeperTask::SetLastRun
void SetLastRun(const QDateTime &last, bool successful=true) override
Definition: housekeeper.cpp:365
housekeeper.h
PeriodicHouseKeeperTask::InWindow
virtual bool InWindow(const QDateTime &now)
Definition: housekeeper.cpp:416
HouseKeeperTask::CheckImmediate
bool CheckImmediate(void)
Definition: housekeeper.cpp:121
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:303
HouseKeeper::m_threadLock
QMutex m_threadLock
Definition: housekeeper.h:178
HouseKeeperTask::DoCheckRun
virtual bool DoCheckRun(const QDateTime &)
Definition: housekeeper.h:66
HouseKeeperTask::QueryLastRun
QDateTime QueryLastRun(void)
Definition: housekeeper.cpp:166
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
chronomult
static constexpr T chronomult(T duration, double f)
Multiply a duration by a float, returning a duration.
Definition: mythchrono.h:199
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:201
mythdbcon.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
PeriodicHouseKeeperTask::DoCheckRun
bool DoCheckRun(const QDateTime &now) override
Definition: housekeeper.cpp:372
HouseKeeper::m_taskQueue
QQueue< HouseKeeperTask * > m_taskQueue
Definition: housekeeper.h:171
HouseKeeper::customEvent
void customEvent(QEvent *e) override
Definition: housekeeper.cpp:830
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
HouseKeeper::RegisterTask
void RegisterTask(HouseKeeperTask *task)
Definition: housekeeper.cpp:635
startup
static int startup()
Definition: mythtv/programs/mythshutdown/main.cpp:771
HouseKeeperTask::m_lastUpdate
QDateTime m_lastUpdate
Definition: housekeeper.h:82
HouseKeeper::Run
void Run(void)
Definition: housekeeper.cpp:726
HouseKeeperTask::UpdateLastRun
QDateTime UpdateLastRun(bool successful=true)
Definition: housekeeper.h:61
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
DailyHouseKeeperTask::InWindow
bool InWindow(const QDateTime &now) override
Definition: housekeeper.cpp:489
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
HouseKeeperTask::Run
bool Run(void)
Definition: housekeeper.cpp:137
MythDate::fromSecsSinceEpoch
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(uint seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
Definition: mythdate.cpp:68
PeriodicHouseKeeperTask::PeriodicHouseKeeperTask
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)
Definition: housekeeper.cpp:324
HouseKeeperTask::SetLastRun
virtual void SetLastRun(const QDateTime &last, bool successful=true)
Definition: housekeeper.cpp:302
PeriodicHouseKeeperTask::CalculateWindow
virtual void CalculateWindow(void)
Definition: housekeeper.cpp:335
MythCoreContext::SendEvent
void SendEvent(const MythEvent &event)
Definition: mythcorecontext.cpp:1542
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:200
DailyHouseKeeperTask::SetHourWindow
virtual void SetHourWindow(std::chrono::hours min, std::chrono::hours max)
Definition: housekeeper.cpp:482
DailyHouseKeeperTask::CalculateWindow
void CalculateWindow(void) override
Definition: housekeeper.cpp:463
HouseKeeperTask::GetLastRun
QDateTime GetLastRun(void)
Definition: housekeeper.h:56
HouseKeeper::m_queueLock
QMutex m_queueLock
Definition: housekeeper.h:172
HouseKeeperTask::HouseKeeperTask
HouseKeeperTask(const QString &dbTag, HouseKeeperScope scope=kHKGlobal, HouseKeeperStartup startup=kHKNormal)
Definition: housekeeper.cpp:98
PeriodicHouseKeeperTask
Modified HouseKeeperTask for tasks to be run at a regular interval.
Definition: housekeeper.h:85
HouseKeepingThread
Thread used to perform queued HouseKeeper tasks.
Definition: housekeeper.h:128
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
kHKRunImmediateOnStartup
@ kHKRunImmediateOnStartup
task is run during HouseKeeper startup
Definition: housekeeper.h:37
HouseKeeper::m_timer
QTimer * m_timer
Definition: housekeeper.h:169
MSqlQuery::isConnected
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:134
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
PeriodicHouseKeeperTask::UpdateLastRun
QDateTime UpdateLastRun(const QDateTime &last, bool successful=true) override
Definition: housekeeper.cpp:356
HouseKeeperTask::GetTag
QString GetTag(void)
Definition: housekeeper.h:55
HouseKeeperScope
HouseKeeperScope
Definition: housekeeper.h:25
HouseKeeperTask::CheckStartup
bool CheckStartup(void)
Definition: housekeeper.cpp:127
HouseKeeperStartup
HouseKeeperStartup
Definition: housekeeper.h:34
HouseKeeper::~HouseKeeper
~HouseKeeper() override
Definition: housekeeper.cpp:581
HouseKeeperTask::m_lastSuccess
QDateTime m_lastSuccess
Definition: housekeeper.h:81
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
HouseKeepingThread::m_idle
bool m_idle
Definition: housekeeper.h:143
HouseKeeperTask::m_running
bool m_running
Definition: housekeeper.h:78
HouseKeepingThread::m_parent
HouseKeeper * m_parent
Definition: housekeeper.h:145
PeriodicHouseKeeperTask::m_windowElapsed
QPair< std::chrono::seconds, std::chrono::seconds > m_windowElapsed
Definition: housekeeper.h:104
HouseKeeper::m_taskMap
QMap< QString, HouseKeeperTask * > m_taskMap
Definition: housekeeper.h:174
DailyHouseKeeperTask::m_windowHour
QPair< std::chrono::hours, std::chrono::hours > m_windowHour
Definition: housekeeper.h:125
HouseKeeperTask::QueryLastSuccess
QDateTime QueryLastSuccess(void)
Definition: housekeeper.cpp:172
PeriodicHouseKeeperTask::SetWindow
virtual void SetWindow(float min, float max)
Definition: housekeeper.cpp:349
PeriodicHouseKeeperTask::PastWindow
virtual bool PastWindow(const QDateTime &now)
Definition: housekeeper.cpp:428
HouseKeeper::StartThread
void StartThread(void)
Wake the primary run thread, or create a new one.
Definition: housekeeper.cpp:793
mythcorecontext.h
MythDate
Definition: mythdate.cpp:7
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:878
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
HouseKeeper::HouseKeeper
HouseKeeper(void)
Definition: housekeeper.cpp:573
PeriodicHouseKeeperTask::m_period
std::chrono::seconds m_period
Definition: housekeeper.h:101
kHKInst
@ kHKInst
task should run on every process e.g.
Definition: housekeeper.h:30
HouseKeepingThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: housekeeper.cpp:511
kHKRunOnStartup
@ kHKRunOnStartup
task is queued when HouseKeeper is started
Definition: housekeeper.h:36
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:862
PeriodicHouseKeeperTask::m_windowPercent
QPair< float, float > m_windowPercent
Definition: housekeeper.h:103
HouseKeeperTask::GetLastSuccess
QDateTime GetLastSuccess(void)
Definition: housekeeper.h:57
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
HouseKeepingThread::m_waitCondition
QWaitCondition m_waitCondition
Definition: housekeeper.h:147
HouseKeeperTask
Definition for a single task to be run by the HouseKeeper.
Definition: housekeeper.h:40
HouseKeeperTask::DoRun
virtual bool DoRun(void)
Definition: housekeeper.h:67
HouseKeeperTask::CheckRun
bool CheckRun(const QDateTime &now)
Definition: housekeeper.cpp:108
DailyHouseKeeperTask::DailyHouseKeeperTask
DailyHouseKeeperTask(const QString &dbTag, HouseKeeperScope scope=kHKGlobal, HouseKeeperStartup startup=kHKNormal)
Definition: housekeeper.cpp:446
HouseKeeperTask::m_confirm
bool m_confirm
Definition: housekeeper.h:75
kHKLocal
@ kHKLocal
task should only run once per machine e.g.
Definition: housekeeper.h:28
HouseKeeperTask::m_scope
HouseKeeperScope m_scope
Definition: housekeeper.h:76
HouseKeeper::m_mapLock
QMutex m_mapLock
Definition: housekeeper.h:175
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
HouseKeeper::GetQueuedTask
HouseKeeperTask * GetQueuedTask(void)
Definition: housekeeper.cpp:654
HouseKeeper::Start
void Start(void)
Definition: housekeeper.cpp:669
HouseKeeperTask::m_dbTag
QString m_dbTag
Definition: housekeeper.h:74
HouseKeeperTask::m_lastRun
QDateTime m_lastRun
Definition: housekeeper.h:80
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
HouseKeeperTask::ConfirmRun
bool ConfirmRun(void) const
Definition: housekeeper.h:49
PeriodicHouseKeeperTask::m_currentProb
double m_currentProb
Definition: housekeeper.h:105
kHKGlobal
@ kHKGlobal
task should only run once per cluster e.g.
Definition: housekeeper.h:26
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:827