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