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  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
161  for (size_t i = 0; i < cardids.size(); i++)
162  {
163  if (hosts[i] == localhostname) {
164  // No memory leak. The constructor for TVRec adds the item
165  // to the static map TVRec::s_inputs.
166  new TVRec(cardids[i]);
167  }
168  }
169 
170  for (size_t i = 0; i < cardids.size(); i++)
171  {
172  uint cardid = cardids[i];
173  QString host = hosts[i];
174  QString cidmsg = QString("Card %1").arg(cardid);
175 
176  if (!ismaster)
177  {
178  if (host == localhostname)
179  {
180  TVRec *tv = TVRec::GetTVRec(cardid);
181  if (tv && tv->Init())
182  {
183  auto *enc = new EncoderLink(cardid, tv);
184  tvList[cardid] = enc;
185  }
186  else
187  {
188  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
189  cidmsg + " failed init");
190  delete tv;
191  // The master assumes card comes up so we need to
192  // set error and exit if a non-master card fails.
193  error = true;
194  }
195  }
196  }
197  else
198  {
199  if (host == localhostname)
200  {
201  TVRec *tv = TVRec::GetTVRec(cardid);
202  if (tv && tv->Init())
203  {
204  auto *enc = new EncoderLink(cardid, tv);
205  tvList[cardid] = enc;
206  }
207  else
208  {
209  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
210  cidmsg + " failed init");
211  delete tv;
212  }
213  }
214  else
215  {
216  auto *enc = new EncoderLink(cardid, nullptr, host);
217  tvList[cardid] = enc;
218  }
219  }
220  }
221 
222  if (tvList.empty())
223  {
224  LOG(VB_GENERAL, LOG_WARNING, LOC +
225  "No valid capture cards are defined in the database.");
226  }
227 
228  return true;
229 }
230 
231 void cleanup(void)
232 {
233  if (mainServer)
234  {
235  mainServer->Stop();
236  qApp->processEvents();
237  }
238 
239  if (gCoreContext)
241 
242  delete sysEventHandler;
243  sysEventHandler = nullptr;
244 
245  delete housekeeping;
246  housekeeping = nullptr;
247 
248  if (gCoreContext)
249  {
250  delete gCoreContext->GetScheduler();
251  gCoreContext->SetScheduler(nullptr);
252  }
253 
254  delete expirer;
255  expirer = nullptr;
256 
257  delete jobqueue;
258  jobqueue = nullptr;
259 
260  delete g_pUPnp;
261  g_pUPnp = nullptr;
262 
263  if (SSDP::Instance())
264  {
266  SSDP::Instance()->wait();
267  }
268 
269  if (TaskQueue::Instance())
270  {
273  }
274 
275  while (!TVRec::s_inputs.empty())
276  {
277  TVRec *rec = *TVRec::s_inputs.begin();
278  delete rec;
279  }
280 
281 
282  delete gContext;
283  gContext = nullptr;
284 
285  delete mainServer;
286  mainServer = nullptr;
287 
288  delete gBackendContext;
289  gBackendContext = nullptr;
290 
291  if (pidfile.size())
292  {
293  unlink(pidfile.toLatin1().constData());
294  pidfile.clear();
295  }
296 
298 }
299 
301 {
302  QString eventString;
303 
304  if (cmdline.toBool("event"))
305  eventString = cmdline.toString("event");
306  else if (cmdline.toBool("systemevent"))
307  {
308  eventString = "SYSTEM_EVENT " +
309  cmdline.toString("systemevent") +
310  QString(" SENDER %1").arg(gCoreContext->GetHostName());
311  }
312 
313  if (!eventString.isEmpty())
314  {
316  {
317  gCoreContext->SendMessage(eventString);
318  return GENERIC_EXIT_OK;
319  }
321  }
322 
323  if (cmdline.toBool("setverbose"))
324  {
326  {
327  QString message = "SET_VERBOSE ";
328  message += cmdline.toString("setverbose");
329 
330  gCoreContext->SendMessage(message);
331  LOG(VB_GENERAL, LOG_INFO,
332  QString("Sent '%1' message").arg(message));
333  return GENERIC_EXIT_OK;
334  }
335  LOG(VB_GENERAL, LOG_ERR,
336  "Unable to connect to backend, verbose mask unchanged ");
338  }
339 
340  if (cmdline.toBool("setloglevel"))
341  {
343  {
344  QString message = "SET_LOG_LEVEL ";
345  message += cmdline.toString("setloglevel");
346 
347  gCoreContext->SendMessage(message);
348  LOG(VB_GENERAL, LOG_INFO,
349  QString("Sent '%1' message").arg(message));
350  return GENERIC_EXIT_OK;
351  }
352  LOG(VB_GENERAL, LOG_ERR,
353  "Unable to connect to backend, log level unchanged ");
355  }
356 
357  if (cmdline.toBool("clearcache"))
358  {
360  {
361  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
362  LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message");
363  return GENERIC_EXIT_OK;
364  }
365  LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings "
366  "cache will not be cleared.");
368  }
369 
370  if (cmdline.toBool("printsched") ||
371  cmdline.toBool("testsched"))
372  {
373  auto *sched = new Scheduler(false, &tvList);
374  if (cmdline.toBool("printsched"))
375  {
377  {
378  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master");
379  delete sched;
381  }
382  cout << "Retrieving Schedule from Master backend.\n";
384  }
385  else
386  {
387  cout << "Calculating Schedule from database.\n" <<
388  "Inputs, Card IDs, and Conflict info may be invalid "
389  "if you have multiple tuners.\n";
392  }
393 
394  verboseMask |= VB_SCHEDULE;
395  LogLevel_t oldLogLevel = logLevel;
396  logLevel = LOG_DEBUG;
397  sched->PrintList(true);
398  logLevel = oldLogLevel;
399  delete sched;
400  return GENERIC_EXIT_OK;
401  }
402 
403  if (cmdline.toBool("resched"))
404  {
405  bool ok = false;
407  {
408  LOG(VB_GENERAL, LOG_INFO, "Connected to master for reschedule");
409  ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
410  "MythBackendCommand");
411  ok = true;
412  }
413  else
414  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule");
415 
417  }
418 
419  if (cmdline.toBool("scanvideos"))
420  {
421  bool ok = false;
423  {
424  gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS");
425  LOG(VB_GENERAL, LOG_INFO, "Requested video scan");
426  ok = true;
427  }
428  else
429  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan");
430 
432  }
433 
434  if (cmdline.toBool("printexpire"))
435  {
436  expirer = new AutoExpire();
437  expirer->PrintExpireList(cmdline.toString("printexpire"));
438  return GENERIC_EXIT_OK;
439  }
440 
441  // This should never actually be reached..
442  return GENERIC_EXIT_OK;
443 }
444 using namespace MythTZ;
445 
447 {
448  auto *tempMonitorConnection = new MythSocket();
449  if (tempMonitorConnection->ConnectToHost(
452  {
453  if (!gCoreContext->CheckProtoVersion(tempMonitorConnection))
454  {
455  LOG(VB_GENERAL, LOG_ERR, "Master backend is incompatible with "
456  "this backend.\nCannot become a slave.");
457  tempMonitorConnection->DecrRef();
459  }
460 
461  QStringList tempMonitorDone("DONE");
462 
463  QStringList tempMonitorAnnounce(QString("ANN Monitor %1 0")
464  .arg(gCoreContext->GetHostName()));
465  tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
466  if (tempMonitorAnnounce.empty() ||
467  tempMonitorAnnounce[0] == "ERROR")
468  {
469  tempMonitorConnection->DecrRef();
470  tempMonitorConnection = nullptr;
471  if (tempMonitorAnnounce.empty())
472  {
473  LOG(VB_GENERAL, LOG_ERR, LOC +
474  "Failed to open event socket, timeout");
475  }
476  else
477  {
478  LOG(VB_GENERAL, LOG_ERR, LOC +
479  "Failed to open event socket" +
480  ((tempMonitorAnnounce.size() >= 2) ?
481  QString(", error was %1").arg(tempMonitorAnnounce[1]) :
482  QString(", remote error")));
483  }
484  }
485 
486  QStringList timeCheck;
487  if (tempMonitorConnection)
488  {
489  timeCheck.push_back("QUERY_TIME_ZONE");
490  tempMonitorConnection->SendReceiveStringList(timeCheck);
491  tempMonitorConnection->WriteStringList(tempMonitorDone);
492  }
493  if (timeCheck.size() < 3)
494  {
495  if (tempMonitorConnection)
496  tempMonitorConnection->DecrRef();
498  }
499 
500  QDateTime our_time = MythDate::current();
501  QDateTime master_time = MythDate::fromString(timeCheck[2]);
502  int timediff = abs(our_time.secsTo(master_time));
503 
504  if (timediff > 300)
505  {
506  LOG(VB_GENERAL, LOG_ERR,
507  QString("Current time on the master backend differs by "
508  "%1 seconds from time on this system. Exiting.")
509  .arg(timediff));
510  if (tempMonitorConnection)
511  tempMonitorConnection->DecrRef();
513  }
514 
515  if (timediff > 20)
516  {
517  LOG(VB_GENERAL, LOG_WARNING,
518  QString("Time difference between the master "
519  "backend and this system is %1 seconds.")
520  .arg(timediff));
521  }
522  }
523  if (tempMonitorConnection)
524  tempMonitorConnection->DecrRef();
525 
526  return GENERIC_EXIT_OK;
527 }
528 
529 
531 {
532  if (cmdline.toBool("nohousekeeper"))
533  {
534  LOG(VB_GENERAL, LOG_WARNING, LOC +
535  "****** The Housekeeper has been DISABLED with "
536  "the --nohousekeeper option ******");
537  }
538  if (cmdline.toBool("nosched"))
539  {
540  LOG(VB_GENERAL, LOG_WARNING, LOC +
541  "********** The Scheduler has been DISABLED with "
542  "the --nosched option **********");
543  }
544  if (cmdline.toBool("noautoexpire"))
545  {
546  LOG(VB_GENERAL, LOG_WARNING, LOC +
547  "********* Auto-Expire has been DISABLED with "
548  "the --noautoexpire option ********");
549  }
550  if (cmdline.toBool("nojobqueue"))
551  {
552  LOG(VB_GENERAL, LOG_WARNING, LOC +
553  "********* The JobQueue has been DISABLED with "
554  "the --nojobqueue option *********");
555  }
556 }
557 
559 {
561 
563  {
564  LOG(VB_GENERAL, LOG_ERR,
565  "MySQL time zone support is missing. "
566  "Please install it and try again. "
567  "See 'mysql_tzinfo_to_sql' for assistance.");
569  }
570 
571  bool ismaster = gCoreContext->IsMasterHost();
572 
573  if (!UpgradeTVDatabaseSchema(ismaster, ismaster, true))
574  {
575  LOG(VB_GENERAL, LOG_ERR,
576  QString("Couldn't upgrade database to new schema on %1 backend.")
577  .arg(ismaster ? "master" : "slave"));
579  }
580 
581  be_sd_notify("STATUS=Loading translation");
582  MythTranslation::load("mythfrontend");
583 
584  if (!ismaster)
585  {
586  be_sd_notify("STATUS=Connecting to master backend");
587  int ret = connect_to_master();
588  if (ret != GENERIC_EXIT_OK)
589  return ret;
590  }
591 
592  be_sd_notify("STATUS=Get backend server port");
593  int port = gCoreContext->GetBackendServerPort();
594  if (gCoreContext->GetBackendServerIP().isEmpty())
595  {
596  cerr << "No setting found for this machine's BackendServerIP.\n"
597  << "Please run setup on this machine and modify the first page\n"
598  << "of the general settings.\n";
600  }
601 
603 
604  if (ismaster)
605  {
606  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server.");
607  }
608  else
609  {
610  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend.");
611  }
612 
613  if (ismaster)
614  {
616  }
617 
619 
620  bool fatal_error = false;
621  bool runsched = setupTVs(ismaster, fatal_error);
622  if (fatal_error)
624 
625  Scheduler *sched = nullptr;
626  if (ismaster)
627  {
628  if (runsched)
629  {
630  be_sd_notify("STATUS=Creating scheduler");
631  sched = new Scheduler(true, &tvList);
632  int err = sched->GetError();
633  if (err)
634  {
635  delete sched;
636  return err;
637  }
638 
639  if (cmdline.toBool("nosched"))
641  }
642 
643  if (!cmdline.toBool("noautoexpire"))
644  {
645  expirer = new AutoExpire(&tvList);
646  if (sched)
648  }
650  }
651 
652  if (!cmdline.toBool("nohousekeeper"))
653  {
654  be_sd_notify("STATUS=Creating housekeeper");
655  housekeeping = new HouseKeeper();
656 
657  if (ismaster)
658  {
664 
665  // only run this task if MythMusic is installed and we have a new enough schema
666  if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) >= 1024)
668  }
669 
671 #ifdef __linux__
672  #ifdef CONFIG_BINDINGS_PYTHON
674  #endif
675 #endif
676 
677  housekeeping->Start();
678  }
679 
680  if (!cmdline.toBool("nojobqueue"))
681  jobqueue = new JobQueue(ismaster);
682 
683  // ----------------------------------------------------------------------
684  //
685  // ----------------------------------------------------------------------
686 
687  if (g_pUPnp == nullptr)
688  {
689  be_sd_notify("STATUS=Creating UPnP media server");
690  g_pUPnp = new MediaServer();
691 
692  g_pUPnp->Init(ismaster, cmdline.toBool("noupnp"));
693  }
694 
695  // ----------------------------------------------------------------------
696  // Setup status server
697  // ----------------------------------------------------------------------
698 
699  HttpStatus *httpStatus = nullptr;
700  HttpServer *pHS = g_pUPnp->GetHttpServer();
701 
702  if (pHS)
703  {
704  LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension");
705  be_sd_notify("STATUS=Registering HttpStatus Extension");
706 
707  httpStatus = new HttpStatus( &tvList, sched, expirer, ismaster );
708  pHS->RegisterExtension( httpStatus );
709  }
710 
711  be_sd_notify("STATUS=Creating main server");
712  mainServer = new MainServer(
713  ismaster, port, &tvList, sched, expirer);
714 
715  int exitCode = mainServer->GetExitCode();
716  if (exitCode != GENERIC_EXIT_OK)
717  {
718  LOG(VB_GENERAL, LOG_CRIT,
719  "Backend exiting, MainServer initialization error.");
720  cleanup();
721  return exitCode;
722  }
723 
724  if (httpStatus && mainServer)
725  httpStatus->SetMainServer(mainServer);
726 
727  be_sd_notify("STATUS=Check all storage groups");
729 
730  be_sd_notify("STATUS=Sending \"master started\" message");
732  gCoreContext->SendSystemEvent("MASTER_STARTED");
733 
734  // Provide systemd ready notification (for type=notify units)
735  be_sd_notify("READY=1");
736 
739  exitCode = qApp->exec();
742 
744  {
745  gCoreContext->SendSystemEvent("MASTER_SHUTDOWN");
746  qApp->processEvents();
747  }
748 
749  LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting");
750  be_sd_notify("STOPPING=1\nSTATUS=Exiting");
751 
752  return exitCode;
753 }
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:578
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
static TaskQueue * Instance()
Definition: taskqueue.cpp:58
static void error(const char *str,...)
Definition: vbi.cpp:42
#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
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:104
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)
MSqlQuery query(MSqlQuery::InitCon())
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:489
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:134
static SSDP * Instance()
Definition: ssdp.cpp:54
LogLevel_t logLevel
Definition: logging.cpp:92
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:791
static TVRec * GetTVRec(uint inputid)
Definition: tv_rec.cpp:4827
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
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
Definition: dbcheck.cpp:362
void Start(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
int GetError(void) const
Definition: scheduler.h:116