MythTV  master
main_helpers.cpp
Go to the documentation of this file.
1 #include "mythconfig.h"
2 #if CONFIG_DARWIN
3  #include <sys/aio.h> // O_SYNC
4 #endif
5 #if CONFIG_SYSTEMD_NOTIFY
6  #include <systemd/sd-daemon.h>
7  #define be_sd_notify(x) \
8  (void)sd_notify(0, x);
9 #else
10  #define be_sd_notify(x)
11 #endif
12 
13 // C++ headers
14 #include <cerrno>
15 #include <csignal>
16 #include <cstdlib>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <sys/time.h> // for setpriority
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <QCoreApplication>
24 #include <QFileInfo>
25 #include <QRegExp>
26 #include <QFile>
27 #include <QDir>
28 #include <QMap>
29 
30 #include "tv_rec.h"
31 #include "scheduledrecording.h"
32 #include "autoexpire.h"
33 #include "scheduler.h"
34 #include "mainserver.h"
35 #include "encoderlink.h"
36 #include "remoteutil.h"
37 #include "backendhousekeeper.h"
38 
39 #include "mythcontext.h"
40 #include "mythversion.h"
41 #include "mythdb.h"
42 #include "dbutil.h"
43 #include "exitcodes.h"
44 #include "compat.h"
45 #include "storagegroup.h"
46 #include "programinfo.h"
47 #include "dbcheck.h"
48 #include "jobqueue.h"
49 #include "previewgenerator.h"
50 #include "commandlineparser.h"
51 #include "mythsystemevent.h"
52 #include "main_helpers.h"
53 #include "backendcontext.h"
54 #include "mythtranslation.h"
55 #include "mythtimezone.h"
56 #include "signalhandling.h"
57 #include "hardwareprofile.h"
58 #include "eitcache.h"
59 
60 #include "mediaserver.h"
61 #include "httpstatus.h"
62 #include "mythlogging.h"
63 
64 #define LOC QString("MythBackend: ")
65 #define LOC_WARN QString("MythBackend, Warning: ")
66 #define LOC_ERR QString("MythBackend, Error: ")
67 
68 static MainServer *mainServer = nullptr;
69 
70 bool setupTVs(bool ismaster, bool &error)
71 {
72  error = false;
73  QString localhostname = gCoreContext->GetHostName();
74 
76 
77  if (ismaster)
78  {
79  // Hack to make sure recorded.basename gets set if the user
80  // downgrades to a prior version and creates new entries
81  // without it.
82  if (!query.exec("UPDATE recorded SET basename = CONCAT(chanid, '_', "
83  "DATE_FORMAT(starttime, '%Y%m%d%H%i00'), '_', "
84  "DATE_FORMAT(endtime, '%Y%m%d%H%i00'), '.nuv') "
85  "WHERE basename = '';"))
86  MythDB::DBError("Updating record basename", query);
87 
88  // Hack to make sure record.station gets set if the user
89  // downgrades to a prior version and creates new entries
90  // without it.
91  if (!query.exec("UPDATE channel SET callsign=chanid "
92  "WHERE callsign IS NULL OR callsign='';"))
93  MythDB::DBError("Updating channel callsign", query);
94 
95  if (query.exec("SELECT MIN(chanid) FROM channel;"))
96  {
97  query.first();
98  int min_chanid = query.value(0).toInt();
99  if (!query.exec(QString("UPDATE record SET chanid = %1 "
100  "WHERE chanid IS NULL;").arg(min_chanid)))
101  MythDB::DBError("Updating record chanid", query);
102  }
103  else
104  MythDB::DBError("Querying minimum chanid", query);
105 
106  MSqlQuery records_without_station(MSqlQuery::InitCon());
107  records_without_station.prepare("SELECT record.chanid,"
108  " channel.callsign FROM record LEFT JOIN channel"
109  " ON record.chanid = channel.chanid WHERE record.station='';");
110  if (records_without_station.exec() && records_without_station.next())
111  {
112  MSqlQuery update_record(MSqlQuery::InitCon());
113  update_record.prepare("UPDATE record SET station = :CALLSIGN"
114  " WHERE chanid = :CHANID;");
115  do
116  {
117  update_record.bindValue(":CALLSIGN",
118  records_without_station.value(1));
119  update_record.bindValue(":CHANID",
120  records_without_station.value(0));
121  if (!update_record.exec())
122  {
123  MythDB::DBError("Updating record station", update_record);
124  }
125  } while (records_without_station.next());
126  }
127  }
128 
129  if (!query.exec(
130  "SELECT cardid, hostname "
131  "FROM capturecard "
132  "ORDER BY cardid"))
133  {
134  MythDB::DBError("Querying Recorders", query);
135  return false;
136  }
137 
138  vector<uint> cardids;
139  vector<QString> hosts;
140  while (query.next())
141  {
142  uint cardid = query.value(0).toUInt();
143  QString host = query.value(1).toString();
144  QString cidmsg = QString("Card %1").arg(cardid);
145 
146  if (host.isEmpty())
147  {
148  LOG(VB_GENERAL, LOG_ERR, cidmsg +
149  " does not have a hostname defined.\n"
150  "Please run setup and confirm all of the capture cards.\n");
151  continue;
152  }
153 
154  cardids.push_back(cardid);
155  hosts.push_back(host);
156  }
157 
158  QWriteLocker tvlocker(&TVRec::s_inputsLock);
159 
160  for (size_t i = 0; i < cardids.size(); i++)
161  {
162  if (hosts[i] == localhostname) {
163  // No memory leak. The constructor for TVRec adds the item
164  // to the static map TVRec::s_inputs.
165  new TVRec(cardids[i]);
166  }
167  }
168 
169  for (size_t i = 0; i < cardids.size(); i++)
170  {
171  uint cardid = cardids[i];
172  QString host = hosts[i];
173  QString cidmsg = QString("Card %1").arg(cardid);
174 
175  if (!ismaster)
176  {
177  if (host == localhostname)
178  {
179  TVRec *tv = TVRec::GetTVRec(cardid);
180  if (tv && tv->Init())
181  {
182  auto *enc = new EncoderLink(cardid, tv);
183  tvList[cardid] = enc;
184  }
185  else
186  {
187  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
188  cidmsg + " failed init");
189  delete tv;
190  // The master assumes card comes up so we need to
191  // set error and exit if a non-master card fails.
192  error = true;
193  }
194  }
195  }
196  else
197  {
198  if (host == localhostname)
199  {
200  TVRec *tv = TVRec::GetTVRec(cardid);
201  if (tv && tv->Init())
202  {
203  auto *enc = new EncoderLink(cardid, tv);
204  tvList[cardid] = enc;
205  }
206  else
207  {
208  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
209  cidmsg + " failed init");
210  delete tv;
211  }
212  }
213  else
214  {
215  auto *enc = new EncoderLink(cardid, nullptr, host);
216  tvList[cardid] = enc;
217  }
218  }
219  }
220 
221  if (tvList.empty())
222  {
223  LOG(VB_GENERAL, LOG_WARNING, LOC +
224  "No valid capture cards are defined in the database.");
225  }
226 
227  return true;
228 }
229 
230 void cleanup(void)
231 {
232  if (mainServer)
233  {
234  mainServer->Stop();
235  qApp->processEvents();
236  }
237 
238  if (gCoreContext)
240 
241  delete sysEventHandler;
242  sysEventHandler = nullptr;
243 
244  delete housekeeping;
245  housekeeping = nullptr;
246 
247  if (gCoreContext)
248  {
249  delete gCoreContext->GetScheduler();
250  gCoreContext->SetScheduler(nullptr);
251  }
252 
253  delete expirer;
254  expirer = nullptr;
255 
256  delete jobqueue;
257  jobqueue = nullptr;
258 
259  delete g_pUPnp;
260  g_pUPnp = nullptr;
261 
262  if (SSDP::Instance())
263  {
265  SSDP::Instance()->wait();
266  }
267 
268  if (TaskQueue::Instance())
269  {
272  }
273 
274  while (!TVRec::s_inputs.empty())
275  {
276  TVRec *rec = *TVRec::s_inputs.begin();
277  delete rec;
278  }
279 
280 
281  delete gContext;
282  gContext = nullptr;
283 
284  delete mainServer;
285  mainServer = nullptr;
286 
287  delete gBackendContext;
288  gBackendContext = nullptr;
289 
290  if (pidfile.size())
291  {
292  unlink(pidfile.toLatin1().constData());
293  pidfile.clear();
294  }
295 
297 }
298 
300 {
301  QString eventString;
302 
303  if (cmdline.toBool("event"))
304  eventString = cmdline.toString("event");
305  else if (cmdline.toBool("systemevent"))
306  {
307  eventString = "SYSTEM_EVENT " +
308  cmdline.toString("systemevent") +
309  QString(" SENDER %1").arg(gCoreContext->GetHostName());
310  }
311 
312  if (!eventString.isEmpty())
313  {
315  {
316  gCoreContext->SendMessage(eventString);
317  return GENERIC_EXIT_OK;
318  }
320  }
321 
322  if (cmdline.toBool("setverbose"))
323  {
325  {
326  QString message = "SET_VERBOSE ";
327  message += cmdline.toString("setverbose");
328 
329  gCoreContext->SendMessage(message);
330  LOG(VB_GENERAL, LOG_INFO,
331  QString("Sent '%1' message").arg(message));
332  return GENERIC_EXIT_OK;
333  }
334  LOG(VB_GENERAL, LOG_ERR,
335  "Unable to connect to backend, verbose mask unchanged ");
337  }
338 
339  if (cmdline.toBool("setloglevel"))
340  {
342  {
343  QString message = "SET_LOG_LEVEL ";
344  message += cmdline.toString("setloglevel");
345 
346  gCoreContext->SendMessage(message);
347  LOG(VB_GENERAL, LOG_INFO,
348  QString("Sent '%1' message").arg(message));
349  return GENERIC_EXIT_OK;
350  }
351  LOG(VB_GENERAL, LOG_ERR,
352  "Unable to connect to backend, log level unchanged ");
354  }
355 
356  if (cmdline.toBool("clearcache"))
357  {
359  {
360  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
361  LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message");
362  return GENERIC_EXIT_OK;
363  }
364  LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings "
365  "cache will not be cleared.");
367  }
368 
369  if (cmdline.toBool("printsched") ||
370  cmdline.toBool("testsched"))
371  {
372  auto *sched = new Scheduler(false, &tvList);
373  if (cmdline.toBool("printsched"))
374  {
376  {
377  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master");
378  delete sched;
380  }
381  cout << "Retrieving Schedule from Master backend.\n";
383  }
384  else
385  {
386  cout << "Calculating Schedule from database.\n" <<
387  "Inputs, Card IDs, and Conflict info may be invalid "
388  "if you have multiple tuners.\n";
391  }
392 
393  verboseMask |= VB_SCHEDULE;
394  LogLevel_t oldLogLevel = logLevel;
395  logLevel = LOG_DEBUG;
396  sched->PrintList(true);
397  logLevel = oldLogLevel;
398  delete sched;
399  return GENERIC_EXIT_OK;
400  }
401 
402  if (cmdline.toBool("resched"))
403  {
404  bool ok = false;
406  {
407  LOG(VB_GENERAL, LOG_INFO, "Connected to master for reschedule");
408  ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
409  "MythBackendCommand");
410  ok = true;
411  }
412  else
413  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule");
414 
416  }
417 
418  if (cmdline.toBool("scanvideos"))
419  {
420  bool ok = false;
422  {
423  gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS");
424  LOG(VB_GENERAL, LOG_INFO, "Requested video scan");
425  ok = true;
426  }
427  else
428  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan");
429 
431  }
432 
433  if (cmdline.toBool("printexpire"))
434  {
435  expirer = new AutoExpire();
436  expirer->PrintExpireList(cmdline.toString("printexpire"));
437  return GENERIC_EXIT_OK;
438  }
439 
440  // This should never actually be reached..
441  return GENERIC_EXIT_OK;
442 }
443 using namespace MythTZ;
444 
446 {
447  auto *tempMonitorConnection = new MythSocket();
448  if (tempMonitorConnection->ConnectToHost(
451  {
452  if (!gCoreContext->CheckProtoVersion(tempMonitorConnection))
453  {
454  LOG(VB_GENERAL, LOG_ERR, "Master backend is incompatible with "
455  "this backend.\nCannot become a slave.");
456  tempMonitorConnection->DecrRef();
458  }
459 
460  QStringList tempMonitorDone("DONE");
461 
462  QStringList tempMonitorAnnounce(QString("ANN Monitor %1 0")
463  .arg(gCoreContext->GetHostName()));
464  tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
465  if (tempMonitorAnnounce.empty() ||
466  tempMonitorAnnounce[0] == "ERROR")
467  {
468  tempMonitorConnection->DecrRef();
469  tempMonitorConnection = nullptr;
470  if (tempMonitorAnnounce.empty())
471  {
472  LOG(VB_GENERAL, LOG_ERR, LOC +
473  "Failed to open event socket, timeout");
474  }
475  else
476  {
477  LOG(VB_GENERAL, LOG_ERR, LOC +
478  "Failed to open event socket" +
479  ((tempMonitorAnnounce.size() >= 2) ?
480  QString(", error was %1").arg(tempMonitorAnnounce[1]) :
481  QString(", remote error")));
482  }
483  }
484 
485  QStringList timeCheck;
486  if (tempMonitorConnection)
487  {
488  timeCheck.push_back("QUERY_TIME_ZONE");
489  tempMonitorConnection->SendReceiveStringList(timeCheck);
490  tempMonitorConnection->WriteStringList(tempMonitorDone);
491  }
492  if (timeCheck.size() < 3)
493  {
494  if (tempMonitorConnection)
495  tempMonitorConnection->DecrRef();
497  }
498 
499  QDateTime our_time = MythDate::current();
500  QDateTime master_time = MythDate::fromString(timeCheck[2]);
501  int timediff = abs(our_time.secsTo(master_time));
502 
503  if (timediff > 300)
504  {
505  LOG(VB_GENERAL, LOG_ERR,
506  QString("Current time on the master backend differs by "
507  "%1 seconds from time on this system. Exiting.")
508  .arg(timediff));
509  if (tempMonitorConnection)
510  tempMonitorConnection->DecrRef();
512  }
513 
514  if (timediff > 20)
515  {
516  LOG(VB_GENERAL, LOG_WARNING,
517  QString("Time difference between the master "
518  "backend and this system is %1 seconds.")
519  .arg(timediff));
520  }
521  }
522  if (tempMonitorConnection)
523  tempMonitorConnection->DecrRef();
524 
525  return GENERIC_EXIT_OK;
526 }
527 
528 
530 {
531  if (cmdline.toBool("nohousekeeper"))
532  {
533  LOG(VB_GENERAL, LOG_WARNING, LOC +
534  "****** The Housekeeper has been DISABLED with "
535  "the --nohousekeeper option ******");
536  }
537  if (cmdline.toBool("nosched"))
538  {
539  LOG(VB_GENERAL, LOG_WARNING, LOC +
540  "********** The Scheduler has been DISABLED with "
541  "the --nosched option **********");
542  }
543  if (cmdline.toBool("noautoexpire"))
544  {
545  LOG(VB_GENERAL, LOG_WARNING, LOC +
546  "********* Auto-Expire has been DISABLED with "
547  "the --noautoexpire option ********");
548  }
549  if (cmdline.toBool("nojobqueue"))
550  {
551  LOG(VB_GENERAL, LOG_WARNING, LOC +
552  "********* The JobQueue has been DISABLED with "
553  "the --nojobqueue option *********");
554  }
555 }
556 
558 {
560 
562  {
563  LOG(VB_GENERAL, LOG_ERR,
564  "MySQL time zone support is missing. "
565  "Please install it and try again. "
566  "See 'mysql_tzinfo_to_sql' for assistance.");
568  }
569 
570  bool ismaster = gCoreContext->IsMasterHost();
571 
572  if (!UpgradeTVDatabaseSchema(ismaster, ismaster, true))
573  {
574  LOG(VB_GENERAL, LOG_ERR,
575  QString("Couldn't upgrade database to new schema on %1 backend.")
576  .arg(ismaster ? "master" : "slave"));
578  }
579 
580  be_sd_notify("STATUS=Loading translation");
581  MythTranslation::load("mythfrontend");
582 
583  if (!ismaster)
584  {
585  be_sd_notify("STATUS=Connecting to master backend");
586  int ret = connect_to_master();
587  if (ret != GENERIC_EXIT_OK)
588  return ret;
589  }
590 
591  be_sd_notify("STATUS=Get backend server port");
592  int port = gCoreContext->GetBackendServerPort();
593  if (gCoreContext->GetBackendServerIP().isEmpty())
594  {
595  cerr << "No setting found for this machine's BackendServerIP.\n"
596  << "Please run setup on this machine and modify the first page\n"
597  << "of the general settings.\n";
599  }
600 
602 
603  if (ismaster)
604  {
605  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server.");
606  }
607  else
608  {
609  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend.");
610  }
611 
612  if (ismaster)
613  {
615  }
616 
618 
619  bool fatal_error = false;
620  bool runsched = setupTVs(ismaster, fatal_error);
621  if (fatal_error)
623 
624  Scheduler *sched = nullptr;
625  if (ismaster)
626  {
627  if (runsched)
628  {
629  be_sd_notify("STATUS=Creating scheduler");
630  sched = new Scheduler(true, &tvList);
631  int err = sched->GetError();
632  if (err)
633  return err;
634 
635  if (cmdline.toBool("nosched"))
637  }
638 
639  if (!cmdline.toBool("noautoexpire"))
640  {
641  expirer = new AutoExpire(&tvList);
642  if (sched)
644  }
646  }
647 
648  if (!cmdline.toBool("nohousekeeper"))
649  {
650  be_sd_notify("STATUS=Creating housekeeper");
651  housekeeping = new HouseKeeper();
652 
653  if (ismaster)
654  {
660 
661  // only run this task if MythMusic is installed and we have a new enough schema
662  if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) >= 1024)
664  }
665 
667 #ifdef __linux__
668  #ifdef CONFIG_BINDINGS_PYTHON
670  #endif
671 #endif
672 
673  housekeeping->Start();
674  }
675 
676  if (!cmdline.toBool("nojobqueue"))
677  jobqueue = new JobQueue(ismaster);
678 
679  // ----------------------------------------------------------------------
680  //
681  // ----------------------------------------------------------------------
682 
683  if (g_pUPnp == nullptr)
684  {
685  be_sd_notify("STATUS=Creating UPnP media server");
686  g_pUPnp = new MediaServer();
687 
688  g_pUPnp->Init(ismaster, cmdline.toBool("noupnp"));
689  }
690 
691  // ----------------------------------------------------------------------
692  // Setup status server
693  // ----------------------------------------------------------------------
694 
695  HttpStatus *httpStatus = nullptr;
696  HttpServer *pHS = g_pUPnp->GetHttpServer();
697 
698  if (pHS)
699  {
700  LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension");
701  be_sd_notify("STATUS=Registering HttpStatus Extension");
702 
703  httpStatus = new HttpStatus( &tvList, sched, expirer, ismaster );
704  pHS->RegisterExtension( httpStatus );
705  }
706 
707  be_sd_notify("STATUS=Creating main server");
708  mainServer = new MainServer(
709  ismaster, port, &tvList, sched, expirer);
710 
711  int exitCode = mainServer->GetExitCode();
712  if (exitCode != GENERIC_EXIT_OK)
713  {
714  LOG(VB_GENERAL, LOG_CRIT,
715  "Backend exiting, MainServer initialization error.");
716  cleanup();
717  return exitCode;
718  }
719 
720  if (httpStatus && mainServer)
721  httpStatus->SetMainServer(mainServer);
722 
723  be_sd_notify("STATUS=Check all storage groups");
725 
726  be_sd_notify("STATUS=Sending \"master started\" message");
728  gCoreContext->SendSystemEvent("MASTER_STARTED");
729 
730  // Provide systemd ready notification (for type=notify units)
731  be_sd_notify("READY=1");
732 
735  exitCode = qApp->exec();
738 
740  {
741  gCoreContext->SendSystemEvent("MASTER_SHUTDOWN");
742  qApp->processEvents();
743  }
744 
745  LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting");
746  be_sd_notify("STOPPING=1\nSTATUS=Exiting");
747 
748  return exitCode;
749 }
void RegisterExtension(HttpServerExtension *pExtension)
Definition: httpserver.cpp:321
static void CheckProgramIDAuthorities(void)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MythScheduler * GetScheduler(void)
void FillRecordListFromMaster(void)
Definition: scheduler.cpp:568
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
static TaskQueue * Instance()
Definition: taskqueue.cpp:58
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
#define GENERIC_EXIT_CONNECT_ERROR
Can't connect to master backend.
Definition: exitcodes.h:20
void RegisterTask(HouseKeeperTask *task)
QString pidfile
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
static MTV_PUBLIC void ClearChannelLocks(void)
removes old channel locks, use it only at master backend start
Definition: eitcache.cpp:445
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
static void error(const char *str,...)
Definition: vbi.c:42
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
#define LOC
static int GetMasterServerPort(void)
Returns the Master Backend control port If no master server port has been defined in the database,...
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
A simple wrapper containing details about a UPnP Media Server.
Definition: mediaserver.h:32
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:311
MediaServer * g_pUPnp
HouseKeeper * housekeeping
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
MythSystemEventHandler * sysEventHandler
void SetScheduler(MythScheduler *sched)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
uint64_t verboseMask
Definition: logging.cpp:107
void DisableScheduling(void)
Definition: scheduler.h:107
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:62
bool Init(void)
Performs instance initialization, returns true on success.
Definition: tv_rec.cpp:139
void SendMessage(const QString &message)
int GetBackendServerPort(void)
Returns the locally defined backend control port.
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
int connect_to_master(void)
QVariant value(int i) const
Definition: mythdbcon.h:198
void Stop(void)
Definition: mainserver.cpp:359
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
static QReadWriteLock s_inputsLock
Definition: tv_rec.h:426
int run_backend(MythBackendCommandLineParser &cmdline)
#define GENERIC_EXIT_DB_NOTIMEZONE
Missing DB time zone support.
Definition: exitcodes.h:36
static void CheckAllStorageGroupDirs(void)
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
void SetMainServer(MainServer *mainServer)
Definition: httpstatus.h:88
void SetExiting(bool exiting=true)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
void PrintList(bool onlyFutureRecordings=false)
Definition: scheduler.h:97
#define GENERIC_EXIT_SOCKET_ERROR
Socket error.
Definition: exitcodes.h:18
void RequestTerminate(void)
Definition: ssdp.cpp:136
Manages registered HouseKeeperTasks and queues tasks for operation.
Definition: housekeeper.h:148
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
void cleanup(void)
void FillRecordListFromDB(uint recordid=0)
Definition: scheduler.cpp:479
BackendContext * gBackendContext
static void Done(void)
#define GENERIC_EXIT_INVALID_TIME
Invalid time.
Definition: exitcodes.h:22
unsigned int uint
Definition: compat.h:140
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythCommFlagCommandLineParser cmdline
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
bool IsMasterHost(void)
is this the same host as the master
void SetExpirer(AutoExpire *autoExpirer)
Definition: scheduler.h:56
int GetExitCode() const
Definition: mainserver.h:153
void RequestTerminate()
Definition: taskqueue.cpp:101
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:793
int GetNumSetting(const QString &key, int defaultval=0)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
HttpServer * GetHttpServer()
Definition: upnp.h:128
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static SSDP * Instance()
Definition: ssdp.cpp:54
LogLevel_t logLevel
Definition: logging.cpp:95
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:61
AutoExpire * expirer
bool CheckProtoVersion(MythSocket *socket, uint timeout_ms=kMythSocketLongTimeout, bool error_dialog_desired=false)
void Init(bool bIsMaster, bool bDisableUPnp=false)
Definition: mediaserver.cpp:69
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
Definition: exitcodes.h:21
void PrintExpireList(const QString &expHost="ALL")
Prints a summary of the files that can be deleted.
Definition: autoexpire.cpp:792
static TVRec * GetTVRec(uint inputid)
Definition: tv_rec.cpp:4828
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:26
static MainServer * mainServer
Scheduler * sched
Handles incoming MythSystemEvent messages.
void print_warnings(const MythBackendCommandLineParser &cmdline)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
bool IsMasterBackend(void)
is this the actual MBE process
#define be_sd_notify(x)
JobQueue * jobqueue
QString GetHostName(void)
void SendSystemEvent(const QString &msg)
QMap< int, EncoderLink * > tvList
static QMap< uint, TVRec * > s_inputs
Definition: tv_rec.h:427
int handle_command(const MythBackendCommandLineParser &cmdline)
bool setupTVs(bool ismaster, bool &error)
static bool CheckTimeZoneSupport(void)
Check if MySQL has working timz zone support.
Definition: dbutil.cpp:869
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
void Start(void)
int GetError(void) const
Definition: scheduler.h:116