From 6f1577a65954ee8a39af033ea96b92409c548eeb Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Mon, 24 Sep 2012 13:41:54 +0200 Subject: [PATCH] Moved cleaning up the EPG data and writing the epg.data file into a separate thread to avoid sluggish response to user input on slow systems --- CONTRIBUTORS | 4 +++ HISTORY | 5 ++- epg.c | 100 +++++++++++++++++++++++++++++++++++++-------------- epg.h | 7 ++-- vdr.c | 6 ++-- 5 files changed, 89 insertions(+), 33 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 28780a7c..3054fd3e 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2955,3 +2955,7 @@ Jens Vogel for suggesting to make cPatPmtParser::ParsePmt() also recognize stream type 0x81 as "AC3", so that recordings that have been converted from the old PES format to TS can be played + +Sören Moch + for a patch that was used to move cleaning up the EPG data and writing the epg.data + file into a separate thread to avoid sluggish response to user input on slow systems diff --git a/HISTORY b/HISTORY index 474d0724..b6de7bde 100644 --- a/HISTORY +++ b/HISTORY @@ -7235,7 +7235,7 @@ Video Disk Recorder Revision History function in order to make use of this new feature. See, for instance, the function cSkinClassicDisplayMenu::SetButtons() in skinclassic.c for details. -2012-09-22: Version 1.7.31 +2012-09-24: Version 1.7.31 - If regenerating an index file fails and no data is written to the file, VDR now reports this error and removes the empty index file. @@ -7258,3 +7258,6 @@ Video Disk Recorder Revision History mechanism if they use intense background I/O. - Increased the size of the TS buffer to 5MB and that of the Recorder buffer to 20MB to better handle HD recordings (suggested by Torsten Lang). +- Moved cleaning up the EPG data and writing the epg.data file into a separate + thread to avoid sluggish response to user input on slow systems (based on a patch from + Sören Moch). diff --git a/epg.c b/epg.c index 8ebfb6e7..ac5792a3 100644 --- a/epg.c +++ b/epg.c @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.c 2.18 2012/08/25 11:10:29 kls Exp $ + * $Id: epg.c 2.19 2012/09/24 13:24:02 kls Exp $ */ #include "epg.h" @@ -18,6 +18,7 @@ #include "timers.h" #define RUNNINGSTATUSTIMEOUT 30 // seconds before the running status is considered unknown +#define EPGDATAWRITEDELTA 600 // seconds between writing the epg.data file // --- tComponent ------------------------------------------------------------ @@ -581,9 +582,20 @@ static void EpgBugFixStat(int Number, tChannelID ChannelID) } } -void ReportEpgBugFixStats(bool Reset) +void ReportEpgBugFixStats(bool Force) { if (Setup.EPGBugfixLevel > 0) { + static time_t LastReport = 0; + time_t now = time(NULL); + if (now - LastReport > 3600 || Force) { + LastReport = now; + struct tm tm_r; + struct tm *ptm = localtime_r(&now, &tm_r); + if (ptm->tm_hour != 5) + return; + } + else + return; bool GotHits = false; char buffer[1024]; for (int i = 0; i < MAXEPGBUGFIXSTATS; i++) { @@ -622,8 +634,7 @@ void ReportEpgBugFixStats(bool Reset) if (*buffer) dsyslog("%s", buffer); } - if (Reset) - p->hits = p->n = 0; + p->hits = p->n = 0; } if (GotHits) dsyslog("====================="); @@ -1109,6 +1120,44 @@ bool cSchedule::Read(FILE *f, cSchedules *Schedules) return false; } +// --- cEpgDataWriter --------------------------------------------------------- + +class cEpgDataWriter : public cThread { +protected: + virtual void Action(void); +public: + cEpgDataWriter(void); + void Perform(void); + }; + +cEpgDataWriter::cEpgDataWriter(void) +:cThread("epg data writer") +{ +} + +void cEpgDataWriter::Action(void) +{ + SetPriority(19); + SetIOPriority(7); + Perform(); +} + +void cEpgDataWriter::Perform(void) +{ + { + cSchedulesLock SchedulesLock(true, 1000); + cSchedules *s = (cSchedules *)cSchedules::Schedules(SchedulesLock); + if (s) { + time_t now = time(NULL); + for (cSchedule *p = s->First(); p; p = s->Next(p)) + p->Cleanup(now); + } + } + cSchedules::Dump(); +} + +static cEpgDataWriter EpgDataWriter; + // --- cSchedulesLock -------------------------------------------------------- cSchedulesLock::cSchedulesLock(bool WriteLock, int TimeoutMs) @@ -1126,7 +1175,6 @@ cSchedulesLock::~cSchedulesLock() cSchedules cSchedules::schedules; char *cSchedules::epgDataFileName = NULL; -time_t cSchedules::lastCleanup = time(NULL); time_t cSchedules::lastDump = time(NULL); time_t cSchedules::modified = 0; @@ -1152,28 +1200,13 @@ void cSchedules::Cleanup(bool Force) if (Force) lastDump = 0; time_t now = time(NULL); - struct tm tm_r; - struct tm *ptm = localtime_r(&now, &tm_r); - if (now - lastCleanup > 3600) { - isyslog("cleaning up schedules data"); - cSchedulesLock SchedulesLock(true, 1000); - cSchedules *s = (cSchedules *)Schedules(SchedulesLock); - if (s) { - for (cSchedule *p = s->First(); p; p = s->Next(p)) - p->Cleanup(now); + if (now - lastDump > EPGDATAWRITEDELTA) { + if (epgDataFileName) { + if (Force) + EpgDataWriter.Perform(); + else if (!EpgDataWriter.Active()) + EpgDataWriter.Start(); } - lastCleanup = now; - if (ptm->tm_hour == 5) - ReportEpgBugFixStats(true); - } - if (epgDataFileName && now - lastDump > 600) { - cSafeFile f(epgDataFileName); - if (f.Open()) { - Dump(f); - f.Close(); - } - else - LOG_ERROR; lastDump = now; } } @@ -1207,8 +1240,23 @@ bool cSchedules::Dump(FILE *f, const char *Prefix, eDumpMode DumpMode, time_t At cSchedulesLock SchedulesLock; cSchedules *s = (cSchedules *)Schedules(SchedulesLock); if (s) { + cSafeFile *sf = NULL; + if (!f) { + sf = new cSafeFile(epgDataFileName); + if (sf->Open()) + f = *sf; + else { + LOG_ERROR; + delete sf; + return false; + } + } for (cSchedule *p = s->First(); p; p = s->Next(p)) p->Dump(f, Prefix, DumpMode, AtTime); + if (sf) { + sf->Close(); + delete sf; + } return true; } return false; diff --git a/epg.h b/epg.h index b9a20935..3a7df772 100644 --- a/epg.h +++ b/epg.h @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider and Rolf Hakenes . * - * $Id: epg.h 2.14 2012/08/25 11:15:18 kls Exp $ + * $Id: epg.h 2.15 2012/09/24 12:53:53 kls Exp $ */ #ifndef __EPG_H @@ -193,7 +193,6 @@ private: cRwLock rwlock; static cSchedules schedules; static char *epgDataFileName; - static time_t lastCleanup; static time_t lastDump; static time_t modified; public: @@ -207,7 +206,7 @@ public: static void Cleanup(bool Force = false); static void ResetVersions(void); static bool ClearAll(void); - static bool Dump(FILE *f, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0); + static bool Dump(FILE *f = NULL, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0); static bool Read(FILE *f = NULL); cSchedule *AddSchedule(tChannelID ChannelID); const cSchedule *GetSchedule(tChannelID ChannelID) const; @@ -220,7 +219,7 @@ public: virtual void Action(void); }; -void ReportEpgBugFixStats(bool Reset = false); +void ReportEpgBugFixStats(bool Force = false); class cEpgHandler : public cListObject { public: diff --git a/vdr.c b/vdr.c index 53a57c31..2e097bae 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.tvdr.de * - * $Id: vdr.c 2.39 2012/09/17 08:56:58 kls Exp $ + * $Id: vdr.c 2.40 2012/09/24 12:43:04 kls Exp $ */ #include @@ -1295,6 +1295,8 @@ int main(int argc, char *argv[]) PluginManager.Housekeeping(); } + ReportEpgBugFixStats(); + // Main thread hooks of plugins: PluginManager.MainThreadHook(); } @@ -1331,7 +1333,7 @@ Exit: EpgHandlers.Clear(); PluginManager.Shutdown(true); cSchedules::Cleanup(true); - ReportEpgBugFixStats(); + ReportEpgBugFixStats(true); if (WatchdogTimeout > 0) dsyslog("max. latency time %d seconds", MaxLatencyTime); if (LastSignal)