[mythtv] [Patch] Database logging, etc - version 3

Matt White whitem at arts.usask.ca
Mon Mar 1 18:16:49 EST 2004


Attached is my latest database logging patch (see my earlier messages
for details), with changes based on comments from the list. The changes
in this patch are:

 From Joseph A. Caputo:

* filters repeat messages (ie. "Last message repeated 213 times")
* put an optional limit on total number of messages kept per module

 From Mark Edwards:

* added an option in General settings to output messages at or above
   a set priority to STDOUT as well as sending them to the database -
   that way, you don't need to have both a VERBOSE() and a LogEntry()
   call (VERBOSE is a bit more granular, though).  It also takes
   advantage of the repeat message filtering from above.

Note that the patch bumps the database version up to 1034, and adds
the necessary tables automatically.

The UI module for viewing the logs is available here:

http://borris.usask.ca/mythtv/mythlog-0.2.tar.gz

PS - I've had to split my time between working on this patch and
playing with my new modded XBox.  Unfortunately, it's a new one with
a Focus chip, so I'll have to wait until the HDTV support comes out
since I've got a component video cable :-(

-- 
Matt White                          whitem at arts.usask.ca
Arts and Science Computer Labs      University of Saskatchewan
-------------- next part --------------
Index: contrib/mythmaillog.pl
===================================================================
RCS file: contrib/mythmaillog.pl
diff -N contrib/mythmaillog.pl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ contrib/mythmaillog.pl	1 Mar 2004 06:04:28 -0000
@@ -0,0 +1,133 @@
+#!/usr/bin/perl
+##
+## Script to email database log entries.
+##
+## 21 Feb 04	1.0	Initial version
+##
+## written by Matt White (whitem at arts.usask.ca)
+## 
+## Remember to edit the settings below to your taste
+##
+
+use DBI;
+
+## 
+## User Configurable Settings
+##
+
+# The email address to send the logs to
+# ** REMEMBER TO ESCAPE THE @ SYMBOL!! **
+$mailto = "someone\@somewhere.changeme";
+
+# The "from" address used in the sent mail
+# ** REMEMBER TO ESCAPE THE @ SYMBOL!! **
+$mailfrom = "someoneelse\@somewhere.changeme";
+
+# Location of your sendmail binary
+$sendmail = "/usr/sbin/sendmail";
+
+# What do you want to get?
+# 1 = Mail out all unacknowledged log entries
+# 2 = Mail out all entries since last email was sent
+$mailwhat = 1;
+
+# Do you want to automatically acknowledge entries that
+# were sent out?  Yes=1, No=0
+$autoack = 1;
+
+# Database connection details for Myth DB
+$dbhost = "localhost";
+$dbname = "mythconverg";
+$dbuser = "mythtv";
+$dbpass = "mythtv";
+
+##
+## End of User-configurable settings
+##
+
+my @priorities = ("Emergency","Alert","Critical","Error","Warning","Notice",
+                  "Info","Debug");
+my $dbh = 
+DBI->connect("dbi:mysql:database=$dbname:host=$dbhost","$dbuser","$dbpass") or
+		 die "Cannot connect to database ($!)\n";
+if ($mailwhat == 2) {
+    $q = "select data from settings where value = 'LogLastEmail'";
+    $sth = $dbh->prepare($q);
+    $numrows = $sth->execute or die "Could not execute ($q)\n";
+    if ($numrows!=0) {
+        @row=$sth->fetchrow_array;
+        $lastemail = 0 + $row[0];
+    } else {
+        $lastemail = 0;
+    }
+    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 
+        localtime($lastemail);
+    $lastdate = sprintf("%4d-%02d-%02dT%02d:%02d:%02d",$year+1900,$mon+1,
+        $mday,$hour,$min,$sec);
+
+    $where = "(logdate > '$lastdate')";
+} else {
+    $where = "(acknowledged = 0)";
+}
+
+$now = time();
+$email = "";
+$q = "select logid,module,priority,acknowledged,logdate,host," .
+     "message,details from mythlog where $where order by logdate";
+$sth = $dbh->prepare($q);
+$numrows = $sth->execute or die "Could not execute ($q)\n";
+while (@row = $sth->fetchrow_array) {
+    $logid = $row[0];
+    $module = $row[1];
+    $priority = $row[2];
+    $ack = $row[3];
+    $logdate = $row[4];
+    $host = $row[5];
+    $message = $row[6];
+    $details = $row[7];
+    if ($mailwhat == 2) {
+        if ($ack == 1) {
+            $printack = "Acknowledged: Yes";
+        } else {
+            $printack = "Acknowledged: No";
+        }
+    } else {
+        $printack = "";
+    }
+
+    $email .= sprintf("%-20s %-15s %s\n",$logdate,$host,$message);
+    $email .= sprintf("    Module: %-20s Priority: %-12s %s\n\n",$module,$priority,
+                      $printack);
+}
+
+if ($numrows == 0) {
+    exit(0);
+}
+
+if ($autoack == 1) {
+    $q = "update mythlog set acknowledged = 1 where $where";
+    $sth = $dbh->prepare($q);
+    $sth->execute or die "Could not execute ($q)\n";
+}
+
+if ($mailwhat == 2) {
+    if ($lastemail == 0) {
+        $q = "insert into settings (value,data) values ('LogLastEmail','$now')";
+    } else {
+        $q = "update settings set data='$now' where value='LogLastEmail'";
+    }
+    $sth = $dbh->prepare($q);
+    $sth->execute or die "Could not execute ($q)\n";
+}
+
+($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 
+        localtime($now);
+$subject = sprintf("Myth Event Report for %4d-%02d-%02d",$year+1900,$mon+1,$mday);
+open MAIL,"| $sendmail -t";
+print MAIL "From: $mailfrom\n";
+print MAIL "To: $mailto\n";
+print MAIL "Subject: $subject\n\n";
+print MAIL $email;
+close MAIL;
+
+exit(0);
Index: libs/libmyth/mythcontext.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/mythcontext.cpp,v
retrieving revision 1.110
diff -u -w -r1.110 mythcontext.cpp
--- libs/libmyth/mythcontext.cpp	5 Feb 2004 22:50:36 -0000	1.110
+++ libs/libmyth/mythcontext.cpp	1 Mar 2004 06:04:34 -0000
@@ -845,6 +845,81 @@
     return retval.toInt();
 }
 
+void MythContext::LogEntry(const QString &module, int priority,
+                     const QString &message, const QString &details)
+{
+    static QMap<QString,int> lastLogCounts;
+    static QMap<QString,QString> lastLogStrings;
+    unsigned int logid;
+    unsigned int howmany;
+
+    if (gContext->GetNumSetting("LogEnabled", 0) == 1)
+    {
+        if (message.left(21) != "Last message repeated")
+	{
+            if (message == lastLogStrings[module])
+            {
+                lastLogCounts[module] += 1;
+    	    return;
+            }
+            else
+            {
+                if (0 < lastLogCounts[module])
+                {
+                    LogEntry(module, priority, QString("Last message repeated %1 times")
+                             .arg(lastLogCounts[module]),lastLogStrings[module]);
+                }
+
+                lastLogCounts[module] = 0;
+                lastLogStrings[module] = message;
+            }
+        }
+
+        unsigned int maxcount = (unsigned int) gContext->GetNumSetting("LogMaxCount",0);
+        d->dbLock.lock();
+    
+        if (d->m_db->isOpen())
+        {
+            KickDatabase(d->m_db);
+    
+            QString querystr = QString("INSERT INTO mythlog ( module, priority, "
+                                       "logdate, host, message, details) "
+                                       "values ( '%1', %2, now(), '%3', "
+                                       "'%4','%5' );") . arg(module) .
+                                       arg(priority) . arg(d->m_localhostname) .
+                                       arg(message) . arg(details);
+    
+            QSqlQuery result = d->m_db->exec(querystr);
+            if (!result.isActive())
+                MythContext::DBError("LogEntry", querystr);
+
+	    if (maxcount > 0)
+	    {
+	        querystr = QString("SELECT logid FROM mythlog WHERE "
+	                           "module='%1' ORDER BY logdate ASC") .arg(module);
+	        result = d->m_db->exec(querystr);
+		howmany = result.size();
+                if (howmany > maxcount)
+                    while (howmany>maxcount)
+                    {
+		        result.next();
+		        logid = result.value(0).toUInt();
+                        querystr = QString("DELETE FROM mythlog WHERE "
+		                           "logid=%1") .arg(logid);
+                        d->m_db->exec(querystr);
+		        howmany--;
+                    }
+	    }
+        }
+    
+        d->dbLock.unlock();
+        int logerr = gContext->GetNumSetting("LogPrintLevel", LP_ERROR);
+	if (priority <= logerr)
+            cout << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") \
+	             << " " << module << ":" << message << endl;
+    }
+}
+
 QString MythContext::GetSettingOnHost(const QString &key, const QString &host,
                                       const QString &defaultval)
 {
Index: libs/libmyth/mythcontext.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmyth/mythcontext.h,v
retrieving revision 1.128
diff -u -w -r1.128 mythcontext.h
--- libs/libmyth/mythcontext.h	17 Feb 2004 01:13:19 -0000	1.128
+++ libs/libmyth/mythcontext.h	1 Mar 2004 06:04:34 -0000
@@ -42,6 +42,17 @@
     VB_ALL       = 0xffff
 };
 
+enum LogPriorities {
+    LP_EMERG     = 0,
+    LP_ALERT     = 1,
+    LP_CRITICAL  = 2,
+    LP_ERROR     = 3,
+    LP_WARNING   = 4,
+    LP_NOTICE    = 5,
+    LP_INFO      = 6,
+    LP_DEBUG     = 7
+};
+
 #define VERBOSE(mask,args...) \
 do { \
 if ((print_verbose_messages & mask) != 0) \
@@ -129,6 +140,9 @@
     QString GetSetting(const QString &key, const QString &defaultval = "");
     int GetNumSetting(const QString &key, int defaultval = 0);
 
+    void LogEntry(const QString &module, int priority,
+                  const QString &message, const QString &details);
+
     QString GetSettingOnHost(const QString &key, const QString &host,
                              const QString &defaultval = "");
     int GetNumSettingOnHost(const QString &key, const QString &host,
Index: libs/libmythtv/dbcheck.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/dbcheck.cpp,v
retrieving revision 1.35
diff -u -w -r1.35 dbcheck.cpp
--- libs/libmythtv/dbcheck.cpp	12 Feb 2004 05:58:02 -0000	1.35
+++ libs/libmythtv/dbcheck.cpp	1 Mar 2004 06:04:40 -0000
@@ -8,7 +8,7 @@
 
 #include "mythcontext.h"
 
-const QString currentDatabaseVersion = "1033";
+const QString currentDatabaseVersion = "1034";
 
 void UpdateDBVersionNumber(const QString &newnumber)
 {
@@ -638,7 +638,29 @@
 };
         performActualUpdate(updates, "1033", dbver);
     }
+    if (dbver == "1033")
+    {
+        const QString updates[] = {
+"CREATE TABLE mythlog ("
+"  logid int(10) unsigned PRIMARY KEY NOT NULL auto_increment,"
+"  module char(32) NOT NULL,"
+"  priority int(11) NOT NULL,"
+"  acknowledged bool default 0,"
+"  logdate datetime,"
+"  host varchar(128),"
+"  message varchar(255) NOT NULL,"
+"  details text"
+");",
+"CREATE TABLE housekeeping ("
+"  tag varchar(64) PRIMARY KEY NOT NULL,"
+"  lastrun datetime"
+");",
+""
 };
+        performActualUpdate(updates, "1034", dbver);
+    }
+
+}
 
 void InitializeDatabase(void)
 {
Index: programs/mythbackend/housekeeper.cpp
===================================================================
RCS file: programs/mythbackend/housekeeper.cpp
diff -N programs/mythbackend/housekeeper.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ programs/mythbackend/housekeeper.cpp	1 Mar 2004 06:04:40 -0000
@@ -0,0 +1,210 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <qsqldatabase.h>
+#include <qsqlquery.h>
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qstringlist.h>
+
+#include <iostream>
+using namespace std;
+
+#include "housekeeper.h"
+
+#include "libmyth/mythcontext.h"
+
+bool HouseKeeper_filldb_running = false;
+
+void reapChild(int sig)
+{
+    (void) wait(0);
+    HouseKeeper_filldb_running = false;
+}
+
+HouseKeeper::HouseKeeper(bool runthread, bool master, QSqlDatabase *ldb)
+{
+    db = ldb;
+    isMaster = master;
+
+    threadrunning = runthread;
+    filldbRunning = false;
+
+    if (runthread)
+    {
+        pthread_t hkthread;
+        pthread_create(&hkthread, NULL, doHouseKeepingThread, this);
+        gContext->addListener(this);
+    }
+}
+
+HouseKeeper::~HouseKeeper()
+{
+    if (threadrunning)
+        gContext->removeListener(this);
+}
+
+bool HouseKeeper::wantToRun(QString dbTag, int period, int minhour,
+                            int maxhour)
+{
+    bool runOK = false;
+    unsigned int oneday = 60 * 60 * 24;
+
+    QDateTime now = QDateTime::currentDateTime();
+    QDateTime lastrun;
+    lastrun.setTime_t(0);
+    if (db->isOpen())
+    {
+        gContext->KickDatabase(db);
+        QString query = QString("SELECT lastrun FROM housekeeping WHERE "
+                                "tag = \"%1\";") .arg(dbTag);
+        QSqlQuery result = db->exec(query);
+        if (result.isActive() && result.numRowsAffected() > 0)
+        {
+            result.next();
+            lastrun = result.value(0).toDateTime();
+        }
+    }
+
+    if ((now.toTime_t() - lastrun.toTime_t()) > period * oneday)
+    {
+        int hour = now.toString(QString("h")).toInt();
+        if ((hour>=minhour) && (hour<=maxhour))
+            runOK = true;       
+    }
+    return(runOK);
+}
+
+void HouseKeeper::updateLastrun(QString dbTag)
+{
+    if (db->isOpen())
+    {
+        gContext->KickDatabase(db);
+        QString query = QString("DELETE FROM housekeeping WHERE "
+                                "tag = \"%1\";") .arg(dbTag);
+        QSqlQuery result = db->exec(query);
+        query = QString("INSERT INTO housekeeping (tag,lastrun) "
+                        "values (\"%1\",now())") .arg(dbTag);
+        result = db->exec(query);
+    }
+}
+
+void HouseKeeper::RunHouseKeeping(void)
+{
+    int period,maxhr,minhr;
+    // wait a little for main server to come up and things to settle down
+    sleep(10);
+
+    while (1)
+    {
+        gContext->LogEntry(QString("mythbackend"),LP_DEBUG,
+	         QString("Running housekeeping thread"),QString(""));
+        // These tasks are only done from the master backend
+        if (isMaster)
+        {
+            // Clean out old database entries
+            if ((bool) gContext->GetNumSetting("LogEnabled", 0) &&
+               (bool) gContext->GetNumSetting("LogCleanEnabled", 0))
+            {
+                period = gContext->GetNumSetting("LogCleanPeriod",1);
+                if (wantToRun(QString("LogClean"),period,0,24))
+                {
+                    QString msg = QString("Running LogClean");
+                    VERBOSE(VB_GENERAL, msg);
+                    flushLogs();
+                    updateLastrun(QString("LogClean"));
+                }
+            }
+
+            // Run mythfilldatabase to grab the TV listings
+            if ((bool) gContext->GetNumSetting("MythFillEnabled", 0))
+            {
+                if (HouseKeeper_filldb_running)
+                {
+                    QString msg = QString("mythfilldatabase still running, skipping checks");
+                    VERBOSE(VB_GENERAL, msg);
+                } else {
+                    period = gContext->GetNumSetting("MythFillPeriod",1);
+                    minhr = gContext->GetNumSetting("MythFillMinHour",-1);
+                    if (minhr == -1)
+                    {
+                        minhr = 0;
+                        maxhr = 24;
+                    } else {
+                        maxhr = gContext->GetNumSetting("MythFillMaxHour",24);
+                    }
+                    if (wantToRun(QString("MythFillDB"),period,minhr,maxhr))
+                    {
+                        QString msg = QString("Running mythfilldatabase");
+                        gContext->LogEntry(QString("mythbackend"),LP_DEBUG,
+                                           msg,QString(""));
+                        VERBOSE(VB_GENERAL, msg);
+                        runFillDatabase();
+                        updateLastrun(QString("MythFillDB"));
+                    }
+                }
+            }
+        }
+    
+        sleep(10);
+    }
+} 
+
+void HouseKeeper::flushLogs()
+{
+    int numdays = gContext->GetNumSetting("LogCleanDays",14);
+    int maxdays = gContext->GetNumSetting("LogCleanMax",30);
+
+    QDateTime days = QDateTime::currentDateTime();
+    days.addDays(0-numdays);
+    QDateTime max = QDateTime::currentDateTime();
+    max.addDays(0-maxdays);
+
+    if (db->isOpen())
+    {
+        gContext->KickDatabase(db);
+        QString dstring = days.toString(QString("yyyy-MM-dd hh:mm:ss"));
+        QString query = QString("DELETE FROM mythlog WHERE "
+                                "acknowledged=1 and logdate<\"%1\";")
+                                .arg(dstring);
+        QSqlQuery result = db->exec(query);
+
+        dstring = max.toString(QString("yyyy-MM-dd hh:mm:ss"));
+        query = QString("DELETE FROM mythlog WHERE logdate<\"%1\";")
+                                .arg(dstring);
+        result = db->exec(query);
+    }
+}
+
+void HouseKeeper::runFillDatabase()
+{
+    QString command;
+
+    QString mfpath = gContext->GetSetting("MythFillDatabasePath","/usr/local/bin/mythfilldatabase");
+    QString mfarg = gContext->GetSetting("MythFillDatabaseArgs","");
+    QString mflog = gContext->GetSetting("MythFillDatabaseLog","/var/log/mythfilldatabase.log");
+
+    if (mflog == "")
+        command = QString("%1 %2") .arg(mfpath) .arg(mfarg);
+    else
+        command = QString("%1 %2 >>%3 2>&1") .arg(mfpath) 
+                                  .arg(mfarg) .arg(mflog);
+    
+    signal(SIGCHLD,&reapChild);
+    HouseKeeper_filldb_running = true;
+    if (fork() == 0)
+    {
+        system(command.ascii());
+        exit(0);
+    }
+}
+
+void *HouseKeeper::doHouseKeepingThread(void *param)
+{
+    HouseKeeper *hkeeper = (HouseKeeper *)param;
+    hkeeper->RunHouseKeeping();
+ 
+    return NULL;
+}
Index: programs/mythbackend/housekeeper.h
===================================================================
RCS file: programs/mythbackend/housekeeper.h
diff -N programs/mythbackend/housekeeper.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ programs/mythbackend/housekeeper.h	1 Mar 2004 06:04:40 -0000
@@ -0,0 +1,38 @@
+#ifndef HOUSEKEEPER_H_
+#define HOUSEKEEPER_H_
+
+class QSqlDatabase;
+
+#include <qmutex.h>
+#include <qobject.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qprocess.h>
+
+using namespace std;
+
+class HouseKeeper : public QObject
+{
+    Q_OBJECT
+  public:
+    HouseKeeper(bool runthread, bool master, QSqlDatabase *ldb);
+   ~HouseKeeper();
+
+  protected:
+    void RunHouseKeeping(void);
+    static void *doHouseKeepingThread(void *param);
+
+
+  private:
+    QSqlDatabase *db;
+
+    bool wantToRun(QString dbTag, int period, int minhour, int maxhour);
+    void updateLastrun(QString dbTag);
+    void flushLogs();
+    void runFillDatabase();
+    bool threadrunning;
+    bool filldbRunning;
+    bool isMaster;
+};
+
+#endif
Index: programs/mythbackend/main.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/main.cpp,v
retrieving revision 1.58
diff -u -w -r1.58 main.cpp
--- programs/mythbackend/main.cpp	10 Feb 2004 03:34:25 -0000	1.58
+++ programs/mythbackend/main.cpp	1 Mar 2004 06:04:41 -0000
@@ -14,6 +14,7 @@
 
 #include "tv.h"
 #include "autoexpire.h"
+#include "housekeeper.h"
 #include "scheduler.h"
 #include "transcoder.h"
 #include "mainserver.h"
@@ -26,6 +27,7 @@
 
 QMap<int, EncoderLink *> tvList;
 AutoExpire *expirer = NULL;
+HouseKeeper *housekeeping = NULL;
 Scheduler *sched = NULL;
 Transcoder *trans = NULL;
 QString pidfile;
@@ -51,6 +53,11 @@
                 cerr << "One of your capturecard entries does not have a "
                      << "hostname.\n  Please run setup and confirm all of the "
                      << "capture cards.\n";
+                gContext->LogEntry("mythbackend",LP_CRITICAL,
+                      "Problem with capture cards",
+                      "One of your capturecard entries does not have a "
+                      "hostname.\n  Please run setup and confirm all of the "
+                      "capture cards.\n");
                 exit(-1);
             }
 
@@ -85,6 +92,8 @@
     {
         cerr << "ERROR: no capture cards are defined in the database.\n";
         cerr << "Perhaps you should read the installation instructions?\n";
+        gContext->LogEntry("mythbackend",LP_CRITICAL,
+                "No capture cards are defined","Please run the setup program.");
         return false;
     }
 
@@ -360,6 +369,13 @@
         return -1;
     }
 
+    QSqlDatabase *hkthread = QSqlDatabase::addDatabase("QMYSQL3", "HKDB");
+    if (!hkthread)
+    {
+        cerr << "Couldn't connect to database\n";
+        return -1;
+    }
+
     QSqlDatabase *transthread = QSqlDatabase::addDatabase("QMYSQL3", "TRANSDB");
     if (!transthread)
     {
@@ -376,6 +392,7 @@
 
     if (!gContext->OpenDatabase(db) || !gContext->OpenDatabase(subthread) ||
         !gContext->OpenDatabase(expthread) ||
+        !gContext->OpenDatabase(hkthread) ||
         !gContext->OpenDatabase(transthread) ||
         !gContext->OpenDatabase(msdb))
     {
@@ -436,6 +453,9 @@
     if (masterip == myip)
     {
         cerr << "Starting up as the master server.\n";
+        gContext->LogEntry("mythbackend",LP_INFO,
+                           "MythBackend started as master server","");
+
         ismaster = true;
 
         if (nosched)
@@ -445,6 +465,8 @@
     else
     {
         cerr << "Running as a slave backend.\n";
+        gContext->LogEntry("mythbackend",LP_INFO,
+                           "MythBackend started as a slave backend","");
     }
  
     bool runsched = setupTVs(ismaster);
@@ -458,6 +480,9 @@
     QSqlDatabase *expdb = QSqlDatabase::database("EXPDB");
     expirer = new AutoExpire(true, ismaster, expdb);
 
+    QSqlDatabase *hkdb = QSqlDatabase::database("HKDB");
+    housekeeping = new HouseKeeper(true, ismaster, hkdb);
+
     QSqlDatabase *trandb = QSqlDatabase::database("TRANSDB");
     trans = new Transcoder(&tvList, trandb);
 
@@ -503,6 +528,8 @@
     a.exec();
 
     // delete trans;
+    gContext->LogEntry("mythbackend",LP_INFO,
+                       "MythBackend exiting","");
 
     cleanup();
 
Index: programs/mythbackend/mythbackend.pro
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/mythbackend.pro,v
retrieving revision 1.12
diff -u -w -r1.12 mythbackend.pro
--- programs/mythbackend/mythbackend.pro	1 Jan 2004 03:38:45 -0000	1.12
+++ programs/mythbackend/mythbackend.pro	1 Mar 2004 06:04:41 -0000
@@ -19,8 +19,8 @@
 
 # Input
 HEADERS += autoexpire.h encoderlink.h filetransfer.h httpstatus.h mainserver.h
-HEADERS += playbacksock.h scheduler.h server.h transcoder.h
+HEADERS += playbacksock.h scheduler.h server.h transcoder.h housekeeper.h
 
 SOURCES += autoexpire.cpp encoderlink.cpp filetransfer.cpp httpstatus.cpp
 SOURCES += main.cpp mainserver.cpp playbacksock.cpp scheduler.cpp server.cpp
-SOURCES += transcoder.cpp
+SOURCES += transcoder.cpp housekeeper.cpp
Index: programs/mythfilldatabase/filldata.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfilldatabase/filldata.cpp,v
retrieving revision 1.92
diff -u -w -r1.92 filldata.cpp
--- programs/mythfilldatabase/filldata.cpp	24 Feb 2004 09:26:03 -0000	1.92
+++ programs/mythfilldatabase/filldata.cpp	1 Mar 2004 06:04:54 -0000
@@ -2131,6 +2131,7 @@
         return -1;
     }
 
+    gContext->LogEntry("mythfilldatabase",LP_INFO,"Listings Download Started","");
     if (from_xawfile)
     {
         readXawtvChannels(fromxawfile_id, fromxawfile_name);
@@ -2168,6 +2169,7 @@
              {
                   cerr << "There are no channel sources defined, did you run the "
                        << "setup program?\n";
+                  gContext->LogEntry("mythfilldatabase",LP_CRITICAL,"No channel sources defined","Could not find any defined channel sources - did you run the setup program?");
                   exit(-1);
              }
         }
@@ -2182,6 +2184,7 @@
         if (!ret)
         {
              cerr << "Failed to fetch some program info\n";
+             gContext->LogEntry("mythfilldatabase",LP_WARNING,"Failed to fetch some program info","");
              exit(1);
         }
     }
@@ -2196,6 +2199,7 @@
 
     ScheduledRecording::signalChange(db);
 
+    gContext->LogEntry("mythfilldatabase",LP_INFO,"Listings Download Finished","");
     delete gContext;
 
     return 0;
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.142
diff -u -w -r1.142 globalsettings.cpp
--- programs/mythfrontend/globalsettings.cpp	24 Feb 2004 07:50:36 -0000	1.142
+++ programs/mythfrontend/globalsettings.cpp	1 Mar 2004 06:05:03 -0000
@@ -966,6 +966,238 @@
     };
 };
 
+class LogEnabled: public CheckBoxSetting, public GlobalSetting {
+public:
+    LogEnabled():
+        GlobalSetting("LogEnabled") {
+        setLabel(QObject::tr("DB Logging Enabled"));
+        setValue(false);
+        setHelpText(QObject::tr("If checked, the Myth modules will send event details "
+                    "to the database, where they can be viewed with MythLog or emailed "
+                    "out periodically."));
+    };
+};
+
+class LogMaxCount: public SpinBoxSetting, public GlobalSetting {
+public:
+    LogMaxCount():
+        SpinBoxSetting(0,500,10),
+        GlobalSetting("LogMaxCount") {
+        setLabel(QObject::tr("Max. Number of Entries per Module"));
+        setValue(0);
+        setHelpText(QObject::tr("If there are more than this number of entries for "
+	                        "a module, the oldest log entries will be deleted to "
+				"reduce the count to this number.  Set to 0 to disable."));
+    };
+};
+
+class LogCleanEnabled: public CheckBoxSetting, public GlobalSetting {
+public:
+    LogCleanEnabled():
+        GlobalSetting("LogCleanEnabled") {
+        setLabel(QObject::tr("Automatic Log Cleaning Enabled"));
+        setValue(false);
+        setHelpText(QObject::tr("This enables the periodic cleanup of the events stored "
+                    "in the Myth database (see 'DB Logging Enabled' on the previous "
+                    "page)."));
+    };
+};
+
+class LogCleanPeriod: public SpinBoxSetting, public GlobalSetting {
+public:
+    LogCleanPeriod():
+        SpinBoxSetting(0,60,1),
+        GlobalSetting("LogCleanPeriod") {
+        setLabel(QObject::tr("Log Cleanup Frequency (Days)"));
+        setValue(14);
+        setHelpText(QObject::tr("The number of days between log cleanup runs"));
+    };
+};
+
+class LogCleanDays: public SpinBoxSetting, public GlobalSetting {
+public:
+    LogCleanDays():
+        SpinBoxSetting(0,60,1),
+        GlobalSetting("LogCleanDays") {
+        setLabel(QObject::tr("Number of days to keep acknowledged log entries"));
+        setValue(14);
+        setHelpText(QObject::tr("The number of days before a log entry that has been "
+	                        "acknowledged will be deleted by the log cleanup "
+				"process."));
+    };
+};
+
+class LogCleanMax: public SpinBoxSetting, public GlobalSetting {
+public:
+    LogCleanMax():
+        SpinBoxSetting(0,60,1),
+        GlobalSetting("LogCleanMax") {
+        setLabel(QObject::tr("Number of days to keep unacknowledged log entries"));
+        setValue(30);
+        setHelpText(QObject::tr("The number of days before a log entry that has NOT "
+	                        "been acknowledged will be deleted by the log cleanup "
+				"process."));
+    };
+};
+
+class LogPrintLevel: public ComboBoxSetting, public GlobalSetting {
+public:
+    LogPrintLevel() :
+      GlobalSetting("LogPrintLevel") {
+        setLabel(QObject::tr("Log Print Threshold"));
+        addSelection(QObject::tr("All Messages"), "8");
+        addSelection(QObject::tr("Debug and Higher"), "7");
+        addSelection(QObject::tr("Info and Higher"), "6");
+        addSelection(QObject::tr("Notice and Higher"), "5");
+        addSelection(QObject::tr("Warning and Higher"), "4");
+        addSelection(QObject::tr("Error and Higher"), "3");
+        addSelection(QObject::tr("Critical and Higher"), "2");
+        addSelection(QObject::tr("Info and Higher"), "1");
+        addSelection(QObject::tr("Emergency Only"), "0");
+        addSelection(QObject::tr("Disable Printed Output"), "-1");
+        setHelpText(QObject::tr("This controls what messages will be printed out as "
+                                "well as being logged to the database."));
+    }
+};
+
+class MythFillEnabled: public CheckBoxSetting, public GlobalSetting {
+public:
+    MythFillEnabled():
+        GlobalSetting("MythFillEnabled") {
+        setLabel(QObject::tr("Automatically run mythfilldatabase"));
+        setValue(false);
+        setHelpText(QObject::tr("This enables the automatic execution of "
+                                "mythfilldatabase."));
+    };
+};
+
+class MythFillPeriod: public SpinBoxSetting, public GlobalSetting {
+public:
+    MythFillPeriod():
+        SpinBoxSetting(0,30,1),
+        GlobalSetting("MythFillPeriod") {
+        setLabel(QObject::tr("mythfilldatabase Run Frequency (Days)"));
+        setValue(1);
+        setHelpText(QObject::tr("The number of days between mythfilldatabase runs"));
+    };
+};
+
+class MythFillMinHour: public SpinBoxSetting, public GlobalSetting {
+public:
+    MythFillMinHour():
+        SpinBoxSetting(0,24,1),
+        GlobalSetting("MythFillMinHour") {
+        setLabel(QObject::tr("mythfilldatabase Execution Start"));
+        setValue(2);
+        setHelpText(QObject::tr("This setting and the following one define a "
+                    "time period when the mythfilldatabase process is allowed to "
+                    "run.  Ex. setting Min to 11 and Max to 13 would mean that "
+                    "the process would only run between 11 AM and 1 PM."));
+    };
+};
+
+class MythFillMaxHour: public SpinBoxSetting, public GlobalSetting {
+public:
+    MythFillMaxHour():
+        SpinBoxSetting(0,24,1),
+        GlobalSetting("MythFillMaxHour") {
+        setLabel(QObject::tr("mythfilldatabase Execution End"));
+        setValue(5);
+        setHelpText(QObject::tr("This setting and the preceding one define a "
+                    "time period when the mythfilldatabase process is allowed to "
+                    "run.  Ex. setting Min to 11 and Max to 13 would mean that "
+                    "the process would only run between 11 AM and 1 PM."));
+    };
+};
+
+class MythFillDatabasePath: public LineEditSetting, public GlobalSetting {
+public:
+    MythFillDatabasePath():
+        GlobalSetting("MythFillDatabasePath") {
+        setLabel(QObject::tr("mythfilldatabase Path"));
+        setValue("/usr/local/bin/mythfilldatabase");
+        setHelpText(QObject::tr("Path (including executable) of the "
+                                "mythfilldatabase program."));
+    };
+};
+
+class MythFillDatabaseArgs: public LineEditSetting, public GlobalSetting {
+public:
+    MythFillDatabaseArgs():
+        GlobalSetting("MythFillDatabaseArgs") {
+        setLabel(QObject::tr("mythfilldatabase Arguments"));
+        setValue("");
+        setHelpText(QObject::tr("Any arguments you want passed to the "
+                                "mythfilldatabase program."));
+    };
+};
+
+class MythFillDatabaseLog: public LineEditSetting, public GlobalSetting {
+public:
+    MythFillDatabaseLog():
+        GlobalSetting("MythFillDatabaseLog") {
+        setLabel(QObject::tr("mythfilldatabase Log Path"));
+        setValue("/var/log/mythfilldatabase.log");
+        setHelpText(QObject::tr("Path to use for logging output from "
+                                "mythfilldatabase program.  Leave blank "
+				"to disable logging."));
+    };
+};
+
+class MythLogSettings: public VerticalConfigurationGroup,
+                      public TriggeredConfigurationGroup {
+public:
+     MythLogSettings():
+         VerticalConfigurationGroup(false),
+         TriggeredConfigurationGroup(false) {
+         setLabel(QObject::tr("Myth Database Logging"));
+//         setUseLabel(false);
+
+         Setting* logEnabled = new LogEnabled();
+         addChild(logEnabled);
+         setTrigger(logEnabled);
+	 addChild(new LogMaxCount());
+
+         ConfigurationGroup* settings = new VerticalConfigurationGroup(false);
+         settings->addChild(new LogPrintLevel());
+         settings->addChild(new LogCleanEnabled());
+         settings->addChild(new LogCleanPeriod());
+         settings->addChild(new LogCleanDays());
+         settings->addChild(new LogCleanMax());
+         addTarget("1", settings);
+         
+         // show nothing if logEnabled is off
+         addTarget("0", new VerticalConfigurationGroup(true));
+     };
+};
+
+class MythFillSettings: public VerticalConfigurationGroup,
+                      public TriggeredConfigurationGroup {
+public:
+     MythFillSettings():
+         VerticalConfigurationGroup(false),
+         TriggeredConfigurationGroup(false) {
+         setLabel(QObject::tr("Mythfilldatabase"));
+         setUseLabel(false);
+
+         Setting* fillEnabled = new MythFillEnabled();
+         addChild(fillEnabled);
+         setTrigger(fillEnabled);
+
+         ConfigurationGroup* settings = new VerticalConfigurationGroup(false);
+         settings->addChild(new MythFillDatabasePath());
+         settings->addChild(new MythFillDatabaseArgs());
+         settings->addChild(new MythFillDatabaseLog());
+         settings->addChild(new MythFillPeriod());
+         settings->addChild(new MythFillMinHour());
+         settings->addChild(new MythFillMaxHour());
+         addTarget("1", settings);
+         
+         // show nothing if fillEnabled is off
+         addTarget("0", new VerticalConfigurationGroup(true));
+     };
+};
+
 class XineramaScreen: public SpinBoxSetting, public GlobalSetting {
 public:
     XineramaScreen():
@@ -1680,6 +1912,12 @@
     general->addChild(new EnableMediaMon());
     general->addChild(new EnableXbox());
     addChild(general);
+
+    MythLogSettings *mythlog = new MythLogSettings();
+    addChild(mythlog);
+
+    MythFillSettings *mythfill = new MythFillSettings();
+    addChild(mythfill);
 }
 
 PlaybackSettings::PlaybackSettings()


More information about the mythtv-dev mailing list