Go to the documentation of this file. 1 #include "mythconfig.h"
5 #if CONFIG_SYSTEMD_NOTIFY
6 #include <systemd/sd-daemon.h>
7 #define be_sd_notify(x) \
10 #define be_sd_notify(x)
20 #include <sys/types.h>
23 #include <QCoreApplication>
64 #define LOC QString("MythBackend: ")
65 #define LOC_WARN QString("MythBackend, Warning: ")
66 #define LOC_ERR QString("MythBackend, Error: ")
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 = '';"))
91 if (!
query.
exec(
"UPDATE channel SET callsign=chanid "
92 "WHERE callsign IS NULL OR callsign='';"))
95 if (
query.
exec(
"SELECT MIN(chanid) FROM channel;"))
99 if (!
query.
exec(QString(
"UPDATE record SET chanid = %1 "
100 "WHERE chanid IS NULL;").
arg(min_chanid)))
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())
113 update_record.
prepare(
"UPDATE record SET station = :CALLSIGN"
114 " WHERE chanid = :CHANID;");
118 records_without_station.
value(1));
120 records_without_station.
value(0));
121 if (!update_record.
exec())
125 }
while (records_without_station.
next());
130 "SELECT cardid, parentid, videodevice, hostname, sourceid "
138 vector<uint> cardids;
139 vector<QString> hosts;
144 QString videodevice =
query.
value(2).toString();
147 QString cidmsg = QString(
"Card[%1](%2)").arg(cardid).arg(videodevice);
151 LOG(VB_GENERAL, LOG_ERR, cidmsg +
152 " does not have a hostname defined.\n"
153 "Please run setup and confirm all of the capture cards.\n");
162 LOG(VB_GENERAL, LOG_WARNING, cidmsg +
163 " does not have a video source");
168 cardids.push_back(cardid);
175 for (
size_t i = 0; i < cardids.size(); i++)
177 if (hosts[i] == localhostname) {
180 new TVRec(cardids[i]);
184 for (
size_t i = 0; i < cardids.size(); i++)
186 uint cardid = cardids[i];
187 QString host = hosts[i];
188 QString cidmsg = QString(
"Card %1").arg(cardid);
192 if (host == localhostname)
195 if (tv && tv->
Init())
202 LOG(VB_GENERAL, LOG_ERR,
"Problem with capture cards. " +
203 cidmsg +
" failed init");
213 if (host == localhostname)
216 if (tv && tv->
Init())
223 LOG(VB_GENERAL, LOG_ERR,
"Problem with capture cards. " +
224 cidmsg +
" failed init");
230 auto *enc =
new EncoderLink(cardid,
nullptr, host);
238 LOG(VB_GENERAL, LOG_WARNING,
LOC +
239 "No valid capture cards are defined in the database.");
250 qApp->processEvents();
307 unlink(
pidfile.toLatin1().constData());
322 eventString =
"SYSTEM_EVENT " +
327 if (!eventString.isEmpty())
341 QString message =
"SET_VERBOSE ";
345 LOG(VB_GENERAL, LOG_INFO,
346 QString(
"Sent '%1' message").
arg(message));
349 LOG(VB_GENERAL, LOG_ERR,
350 "Unable to connect to backend, verbose mask unchanged ");
358 QString message =
"SET_LOG_LEVEL ";
362 LOG(VB_GENERAL, LOG_INFO,
363 QString(
"Sent '%1' message").
arg(message));
366 LOG(VB_GENERAL, LOG_ERR,
367 "Unable to connect to backend, log level unchanged ");
376 LOG(VB_GENERAL, LOG_INFO,
"Sent CLEAR_SETTINGS_CACHE message");
379 LOG(VB_GENERAL, LOG_ERR,
"Unable to connect to backend, settings "
380 "cache will not be cleared.");
392 LOG(VB_GENERAL, LOG_ERR,
"Cannot connect to master");
396 std::cout <<
"Retrieving Schedule from Master backend.\n";
401 std::cout <<
"Calculating Schedule from database.\n" <<
402 "Inputs, Card IDs, and Conflict info may be invalid "
403 "if you have multiple tuners.\n";
422 LOG(VB_GENERAL, LOG_INFO,
"Connected to master for reschedule");
424 "MythBackendCommand");
428 LOG(VB_GENERAL, LOG_ERR,
"Cannot connect to master for reschedule");
439 LOG(VB_GENERAL, LOG_INFO,
"Requested video scan");
443 LOG(VB_GENERAL, LOG_ERR,
"Cannot connect to master for video scan");
462 auto *tempMonitorConnection =
new MythSocket();
463 if (tempMonitorConnection->ConnectToHost(
469 LOG(VB_GENERAL, LOG_ERR,
"Master backend is incompatible with "
470 "this backend.\nCannot become a slave.");
471 tempMonitorConnection->DecrRef();
475 QStringList tempMonitorDone(
"DONE");
477 QStringList tempMonitorAnnounce(QString(
"ANN Monitor %1 0")
479 tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
480 if (tempMonitorAnnounce.empty() ||
481 tempMonitorAnnounce[0] ==
"ERROR")
483 tempMonitorConnection->DecrRef();
484 tempMonitorConnection =
nullptr;
485 if (tempMonitorAnnounce.empty())
487 LOG(VB_GENERAL, LOG_ERR,
LOC +
488 "Failed to open event socket, timeout");
492 LOG(VB_GENERAL, LOG_ERR,
LOC +
493 "Failed to open event socket" +
494 ((tempMonitorAnnounce.size() >= 2) ?
495 QString(
", error was %1").
arg(tempMonitorAnnounce[1]) :
496 QString(
", remote error")));
500 QStringList timeCheck;
501 if (tempMonitorConnection)
503 timeCheck.push_back(
"QUERY_TIME_ZONE");
504 tempMonitorConnection->SendReceiveStringList(timeCheck);
505 tempMonitorConnection->WriteStringList(tempMonitorDone);
507 if (timeCheck.size() < 3)
509 if (tempMonitorConnection)
510 tempMonitorConnection->DecrRef();
516 int timediff = abs(our_time.secsTo(master_time));
520 LOG(VB_GENERAL, LOG_ERR,
521 QString(
"Current time on the master backend differs by "
522 "%1 seconds from time on this system. Exiting.")
524 if (tempMonitorConnection)
525 tempMonitorConnection->DecrRef();
531 LOG(VB_GENERAL, LOG_WARNING,
532 QString(
"Time difference between the master "
533 "backend and this system is %1 seconds.")
537 if (tempMonitorConnection)
538 tempMonitorConnection->DecrRef();
548 LOG(VB_GENERAL, LOG_WARNING,
LOC +
549 "****** The Housekeeper has been DISABLED with "
550 "the --nohousekeeper option ******");
554 LOG(VB_GENERAL, LOG_WARNING,
LOC +
555 "********** The Scheduler has been DISABLED with "
556 "the --nosched option **********");
560 LOG(VB_GENERAL, LOG_WARNING,
LOC +
561 "********* Auto-Expire has been DISABLED with "
562 "the --noautoexpire option ********");
566 LOG(VB_GENERAL, LOG_WARNING,
LOC +
567 "********* The JobQueue has been DISABLED with "
568 "the --nojobqueue option *********");
578 LOG(VB_GENERAL, LOG_ERR,
579 "MySQL time zone support is missing. "
580 "Please install it and try again. "
581 "See 'mysql_tzinfo_to_sql' for assistance.");
589 LOG(VB_GENERAL, LOG_ERR,
590 QString(
"Couldn't upgrade database to new schema on %1 backend.")
591 .
arg(ismaster ?
"master" :
"slave"));
610 std::cerr <<
"No setting found for this machine's BackendServerIP.\n"
611 <<
"Please run setup on this machine and modify the first page\n"
612 <<
"of the general settings.\n";
620 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
"Starting up as the master server.");
624 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
"Running as a slave backend.");
634 bool fatal_error =
false;
635 bool runsched =
setupTVs(ismaster, fatal_error);
686 #ifdef CONFIG_BINDINGS_PYTHON
711 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Use legacy DVBv3 API");
724 LOG(VB_GENERAL, LOG_INFO,
"Main::Registering HttpStatus Extension");
725 be_sd_notify(
"STATUS=Registering HttpStatus Extension");
738 LOG(VB_GENERAL, LOG_CRIT,
739 "Backend exiting, MainServer initialization error.");
750 be_sd_notify(
"STATUS=Sending \"master started\" message");
759 exitCode = qApp->exec();
766 qApp->processEvents();
769 LOG(VB_GENERAL, LOG_NOTICE,
"MythBackend exiting");
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Manages registered HouseKeeperTasks and queues tasks for operation.
void SendMessage(const QString &message)
void PrintExpireList(const QString &expHost="ALL")
Prints a summary of the files that can be deleted.
#define GENERIC_EXIT_OK
Exited with no error.
static MTV_PUBLIC void ClearChannelLocks(void)
Removes old channel locks, use it only at master backend start.
MythSystemEventHandler * sysEventHandler
Provides an interface to both local and remote TVRec's for the mythbackend.
static void error(const char *str,...)
MythScheduler * GetScheduler(void)
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
int connect_to_master(void)
bool Init(void)
Performs instance initialization, returns true on success.
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
QMap< int, EncoderLink * > tvList
void RegisterExtension(HttpServerExtension *pExtension)
void SetScheduler(MythScheduler *sched)
void FillRecordListFromDB(uint recordid=0)
#define GENERIC_EXIT_DB_NOTIMEZONE
Missing DB time zone support.
QVariant value(int i) const
arg(title).arg(filename).arg(doDelete))
Used to expire recordings to make space for new recordings.
void DisableScheduling(void)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
HttpServer * GetHttpServer()
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
void print_warnings(const MythBackendCommandLineParser &cmdline)
void RegisterTask(HouseKeeperTask *task)
BackendContext * gBackendContext
void SetMainServer(MainServer *mainServer)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Class for communcating between myth backends and frontends.
int run_backend(MythBackendCommandLineParser &cmdline)
bool IsMasterBackend(void)
is this the actual MBE process
int handle_command(const MythBackendCommandLineParser &cmdline)
int GetBackendServerPort(void)
Returns the locally defined backend control port.
void SendSystemEvent(const QString &msg)
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
static TaskQueue * Instance()
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
void SetDVBv3(bool dvbv3)
static void DBError(const QString &where, const MSqlQuery &query)
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
void SetExpirer(AutoExpire *autoExpirer)
bool setupTVs(bool ismaster, bool &error)
static bool CheckTimeZoneSupport(void)
Check if MySQL has working timz zone support.
void PrintList(bool onlyFutureRecordings=false)
static QReadWriteLock s_inputsLock
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
int GetNumSetting(const QString &key, int defaultval=0)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
HouseKeeper * housekeeping
static int GetMasterServerPort(void)
Returns the Master Backend control port If no master server port has been defined in the database,...
MythCommFlagCommandLineParser cmdline
bool CheckProtoVersion(MythSocket *socket, uint timeout_ms=kMythSocketLongTimeout, bool error_dialog_desired=false)
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
#define GENERIC_EXIT_SOCKET_ERROR
Socket error.
This is the coordinating class of the Recorder Subsystem.
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
QString GetHostName(void)
static MainServer * mainServer
bool IsMasterHost(void)
is this the same host as the master
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
#define GENERIC_EXIT_CONNECT_ERROR
Can't connect to master backend.
static void CheckProgramIDAuthorities(void)
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
Handles incoming MythSystemEvent messages.
void FillRecordListFromMaster(void)
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
MSqlQuery query(MSqlQuery::InitCon())
static void CheckAllStorageGroupDirs(void)
MythContext * gContext
This global variable contains the MythContext instance for the application.
void SetExiting(bool exiting=true)
static TVRec * GetTVRec(uint inputid)
void RequestTerminate(void)
#define GENERIC_EXIT_INVALID_TIME
Invalid time.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
static QMap< uint, TVRec * > s_inputs
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.