Ticket #11399: eitscannerpatch.v2

File eitscannerpatch.v2, 18.3 KB (added by Roger James <roger@…>, 11 years ago)

version 2 of eit scanner patch

Line 
1diff --git a/mythtv/libs/libmythtv/eitcache.cpp b/mythtv/libs/libmythtv/eitcache.cpp
2index d42dacd..96bc57d 100644
3--- a/mythtv/libs/libmythtv/eitcache.cpp
4+++ b/mythtv/libs/libmythtv/eitcache.cpp
5@@ -12,11 +12,13 @@
6 #include "mythdb.h"
7 #include "mythlogging.h"
8 #include "mythdate.h"
9+#include "mpegtables.h"
10 
11 #define LOC QString("EITCache: ")
12 
13 // Highest version number. version is 5bits
14 const uint EITCache::kVersionMax = 31;
15+const uint EITCache::kVersionInvalid = 32;
16 
17 EITCache::EITCache()
18     : accessCnt(0), hitCnt(0),   tblChgCnt(0),   verChgCnt(0),
19@@ -71,7 +73,7 @@ static inline uint extract_table_id(uint64_t sig)
20 
21 static inline uint extract_version(uint64_t sig)
22 {
23-    return (sig >> 32) & 0x1f;
24+    return (sig >> 32) & 0xff;
25 }
26 
27 static inline uint extract_endtime(uint64_t sig)
28@@ -248,7 +250,8 @@ event_map_t * EITCache::LoadChannel(uint chanid)
29     {
30         uint eventid = query.value(0).toUInt();
31         uint tableid = query.value(1).toUInt();
32-        uint version = query.value(2).toUInt();
33+        uint version = kVersionInvalid; // Ignore stored version beacuse the version has probably wrapped
34+                                        // by the time we read this!
35         uint endtime = query.value(3).toUInt();
36 
37         (*eventMap)[eventid] = construct_sig(tableid, version, endtime, false);
38@@ -309,10 +312,12 @@ void EITCache::WriteToDB(void)
39 
40 
41 bool EITCache::IsNewEIT(uint chanid,  uint tableid,   uint version,
42-                        uint eventid, uint endtime)
43+                        uint eventid, uint endtime, bool &bEventMayCauseReschedule)
44 {
45     accessCnt++;
46 
47+    bEventMayCauseReschedule = false;
48+
49     if (accessCnt % 500000 == 50000)
50     {
51         LOG(VB_EIT, LOG_INFO, GetStatistics());
52@@ -343,29 +348,114 @@ bool EITCache::IsNewEIT(uint chanid,  uint tableid,   uint version,
53 
54     event_map_t * eventMap = channelMap[chanid];
55     event_map_t::iterator it = eventMap->find(eventid);
56+    bool bEntryUpdated = false;
57+
58     if (it != eventMap->end())
59     {
60-        if (extract_table_id(*it) > tableid)
61-        {
62-            // EIT from lower (ie. better) table number
63-            tblChgCnt++;
64-        }
65-        else if ((extract_table_id(*it) == tableid) &&
66-                 ((extract_version(*it) < version) ||
67-                  ((extract_version(*it) == kVersionMax) &&
68-                   version < kVersionMax)))
69+        uint cached_tableid = extract_table_id(*it);
70+        uint cached_version = extract_version(*it);
71+        uint cached_endtime = extract_endtime(*it);
72+        if ((TableID::PF_EIT == tableid) || (TableID::PF_EITo == tableid))
73         {
74-            // EIT updated version on current table
75-            verChgCnt++;
76+            // tableid is for PF table
77+            if ((TableID::PF_EIT == cached_tableid) || (TableID::PF_EITo == cached_tableid))
78+            {
79+                // Already seen a PF table so check version
80+                // and update if it has changed
81+                if ((kVersionInvalid == cached_version) ||
82+                       (cached_version < version) ||
83+                       ((kVersionMax == cached_version) && (version < kVersionMax)))
84+                {
85+                    LOG(VB_EIT, LOG_INFO, LOC + QString("PF table version change - new (%1 %2) old (%3 %4) eventid %5 for chanid %6")
86+                        .arg(QString().sprintf("%02x", tableid)).arg(QString().sprintf("%02x", version))
87+                        .arg(QString().sprintf("%02x", cached_tableid)).arg(QString().sprintf("%02x", cached_version))
88+                        .arg(eventid).arg(chanid));
89+                    verChgCnt++;
90+                    bEntryUpdated = true;
91+                    if (cached_endtime != endtime)
92+                        bEventMayCauseReschedule = true;
93+                }
94+                else
95+                {
96+                    // EIT data previously seen
97+                    hitCnt++;
98+                    return false;
99+                }
100+            }
101+            else
102+            {
103+                // Old entry is in SC table
104+                LOG(VB_EIT, LOG_INFO, LOC + QString("SC to PF tableid change - new (%1 %2) old (%3 %4) eventid %5 for chanid %6")
105+                        .arg(QString().sprintf("%02x", tableid)).arg(QString().sprintf("%02x", version))
106+                        .arg(QString().sprintf("%02x", cached_tableid)).arg(QString().sprintf("%02x", cached_version))
107+                        .arg(eventid).arg(chanid));
108+                bEntryUpdated = true;
109+                if (cached_endtime != endtime)
110+                    bEventMayCauseReschedule = true;
111+            }
112         }
113         else
114         {
115-            // EIT data previously seen
116-            hitCnt++;
117-            return false;
118+            // tableid is for SC table
119+            if ((TableID::PF_EIT == cached_tableid) || (TableID::PF_EITo == cached_tableid))
120+            {
121+                // Already seen a PF table
122+                hitCnt++;
123+                return false;
124+            }
125+            else if ((cached_tableid & 0x0f) == (tableid & 0x0f))
126+            {
127+                // Already seen in this segment of the table so check version
128+                // and update if it has changed
129+                if ((kVersionInvalid == cached_version) ||
130+                       (cached_version < version) ||
131+                       ((kVersionMax == cached_version) && (version < kVersionMax)))
132+                {
133+                    LOG(VB_EIT, LOG_INFO, LOC + QString("SC table version change - new (%1 %2) old (%3 %4) eventid %5 for chanid %6")
134+                        .arg(QString().sprintf("%02x", tableid)).arg(QString().sprintf("%02x", version))
135+                        .arg(QString().sprintf("%02x", cached_tableid)).arg(QString().sprintf("%02x", cached_version))
136+                        .arg(eventid).arg(chanid));
137+                    verChgCnt++;
138+                    bEntryUpdated = true;
139+                    if (cached_endtime != endtime)
140+                        bEventMayCauseReschedule = true;
141+                }
142+                else
143+                {
144+                    // EIT data previously seen
145+                    hitCnt++;
146+                    return false;
147+                }
148+            }
149+            else if ((cached_tableid & 0x0f) > (tableid < 0x0f))
150+            {
151+                LOG(VB_EIT, LOG_INFO, LOC + QString("SC tableid change - new (%1 %2) old (%3 %4) eventid %5 for chanid %6")
152+                        .arg(QString().sprintf("%02x", tableid)).arg(QString().sprintf("%02x", version))
153+                        .arg(QString().sprintf("%02x", cached_tableid)).arg(QString().sprintf("%02x", cached_version))
154+                        .arg(eventid).arg(chanid));
155+                bEntryUpdated = true;
156+                if (cached_endtime != endtime)
157+                    bEventMayCauseReschedule = true;
158+            }
159+            else
160+            {
161+                // Already seen this segment of SC table
162+                hitCnt++;
163+                return false;
164+            }
165         }
166     }
167+    else
168+        bEventMayCauseReschedule = true;
169 
170+    if (bEntryUpdated)
171+        LOG(VB_EIT, LOG_INFO, LOC + QString("Updated entry - table (%1 %2) eventid %3 for chanid %4 reschedule %5")
172+            .arg(QString().sprintf("%02x", tableid)).arg(QString().sprintf("%02x", version))
173+            .arg(eventid).arg(chanid).arg(bEventMayCauseReschedule));
174+    else
175+        LOG(VB_EIT, LOG_INFO, LOC + QString("New entry - table (%1 %2) eventid %3 for chanid %4 reschedule %5")
176+            .arg(QString().sprintf("%02x", tableid)).arg(QString().sprintf("%02x", version))
177+            .arg(eventid).arg(chanid).arg(bEventMayCauseReschedule));
178     eventMap->insert(eventid, construct_sig(tableid, version, endtime, true));
179     entryCnt++;
180 diff --git a/mythtv/libs/libmythtv/eitcache.h b/mythtv/libs/libmythtv/eitcache.h
181index 330b9aa..92668a4 100644
182--- a/mythtv/libs/libmythtv/eitcache.h
183+++ b/mythtv/libs/libmythtv/eitcache.h
184@@ -26,7 +26,7 @@ class EITCache
185    ~EITCache();
186 
187     bool IsNewEIT(uint chanid, uint tableid,   uint version,
188-                  uint eventid,   uint endtime);
189+                  uint eventid,   uint endtime, bool &bEventMayCauseReschedule);
190 
191     uint PruneOldEntries(uint utc_timestamp);
192     void WriteToDB(void);
193@@ -35,7 +35,7 @@ class EITCache
194     QString GetStatistics(void) const;
195 
196   private:
197-    event_map_t * LoadChannel(uint chanid);
198+    event_map_t * LoadChannel(uint chanid, bool firstLoad);
199     void WriteChannelToDB(uint chanid);
200 
201     // event key cache
202@@ -55,6 +55,7 @@ class EITCache
203     uint        wrongChannelHitCnt;
204 
205     static const uint kVersionMax;
206+    static const uint kVersionInvalid;
207 
208   public:
209     static MTV_PUBLIC void ClearChannelLocks(void);diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp
210index 9ee2cc8..3e335af 100644
211--- a/mythtv/libs/libmythtv/eithelper.cpp
212+++ b/mythtv/libs/libmythtv/eithelper.cpp
213@@ -61,7 +61,7 @@ uint EITHelper::GetListSize(void) const
214  *
215  *  \return Returns number of events inserted into DB.
216  */
217-uint EITHelper::ProcessEvents(void)
218+uint EITHelper::ProcessEvents(uint &rescheduleRequiredCount)
219 {
220     QMutexLocker locker(&eitList_lock);
221     uint insertCount = 0;
222@@ -77,7 +77,12 @@ uint EITHelper::ProcessEvents(void)
223 
224         eitfixup->Fix(*event);
225 
226-        insertCount += event->UpdateDB(query, 1000);
227+       bool rescheduleRequired;
228+
229+        insertCount += event->UpdateDB(query, 1000, rescheduleRequired);
230+
231+        if (rescheduleRequired)
232+            rescheduleRequiredCount++;   
233 
234         delete event;
235         eitList_lock.lock();
236@@ -90,14 +95,14 @@ uint EITHelper::ProcessEvents(void)
237     {
238         LOG(VB_EIT, LOG_INFO,
239             LOC + QString("Added %1 events -- complete(%2) "
240-                          "incomplete(%3) unmatched(%4)")
241+                          "incomplete(%3) unmatched(%4) reschedule(%5)")
242                 .arg(insertCount).arg(db_events.size())
243-                .arg(incomplete_events.size()).arg(unmatched_etts.size()));
244+                .arg(incomplete_events.size()).arg(unmatched_etts.size()).arg(rescheduleRequiredCount));
245     }
246     else
247     {
248         LOG(VB_EIT, LOG_INFO,
249-            LOC + QString("Added %1 events").arg(insertCount));
250+            LOC + QString("Added %1 events - reschedule %2").arg(insertCount).arg(rescheduleRequiredCount));
251     }
252 
253     return insertCount;
254@@ -285,6 +290,9 @@ static inline void parse_dvb_component_descriptors(desc_list_t list,
255 
256 void EITHelper::AddEIT(const DVBEventInformationTable *eit)
257 {
258+    // Skip if not current
259+    if (!eit->IsCurrent())
260+        return;
261     uint descCompression = (eit->TableID() > 0x80) ? 2 : 1;
262     uint fix = fixup.value(eit->OriginalNetworkID() << 16);
263     fix |= fixup.value((((uint64_t)eit->TSID()) << 32) |
264@@ -305,8 +313,9 @@ void EITHelper::AddEIT(const DVBEventInformationTable *eit)
265     for (uint i = 0; i < eit->EventCount(); i++)
266     {
267         // Skip event if we have already processed it before...
268+       bool bEventMayCauseReschedule;
269         if (!eitcache->IsNewEIT(chanid, tableid, version, eit->EventID(i),
270-                              eit->EndTimeUnixUTC(i)))
271+                              eit->EndTimeUnixUTC(i), bEventMayCauseReschedule))
272         {
273             continue;
274         }
275@@ -473,8 +482,33 @@ void EITHelper::AddEIT(const DVBEventInformationTable *eit)
276             subtitle_type,
277             audio_props,
278             video_props, stars,
279-            seriesId,  programId);
280-
281+            seriesId,  programId, bEventMayCauseReschedule);
282+
283+/*     // If the event is from the now next table and the seriesId and programId are present
284+       // then test whether any recording rules match the seriesId amd programId. If not
285+       // then discard the event.
286+        // For a less argressive discard policy swap the following two lines
287+       //if (((0x4e == tableid) || (0x4f == tableid)) && (!seriesId.isEmpty() || !programId.isEmpty()))
288+       if ((0x4e == tableid) || (0x4f == tableid))
289+        {
290+            // Fix up the seriesId and programId
291+            DBEventEIT tempEvent(*event);
292+            tempEvent.fixup = EITFixUp::kFixGenericDVB;
293+            eitfixup->Fix(tempEvent);
294+            MSqlQuery query(MSqlQuery::InitCon());
295+            query.prepare("SELECT EXISTS(SELECT * FROM record WHERE seriesid = :SERIESID AND programid = :PROGRAMID)");
296+            query.bindValue(":SERIESID", tempEvent.seriesId);
297+            query.bindValue(":PROGRAMID", tempEvent.programId);
298+            if (!query.exec())
299+                MythDB::DBError("AddEIT", query);
300+            if (query.next())
301+                if (!query.value(0).toBool())
302+                {
303+                    LOG(VB_EIT, LOG_INFO, LOC + QString("Discarding now next event - eventid %1").arg(eit->EventID(i)));
304+                    continue;
305+                }
306+            LOG(VB_EIT, LOG_INFO, LOC + QString("Adding now next event to queue - eventid %1").arg(eit->EventID(i)));
307+        }*/
308         db_events.enqueue(event);
309     }
310 }
311@@ -559,7 +593,8 @@ void EITHelper::AddEIT(const PremiereContentInformationTable *cit)
312         }
313 
314         // Skip event if we have already processed it before...
315-        if (!eitcache->IsNewEIT(chanid, tableid, version, contentid, endtime))
316+       bool bEventMayCauseReschedule;
317+        if (!eitcache->IsNewEIT(chanid, tableid, version, contentid, endtime, bEventMayCauseReschedule))
318         {
319             continue;
320         }
321@@ -580,7 +615,7 @@ void EITHelper::AddEIT(const PremiereContentInformationTable *cit)
322                 subtitle_type,
323                 audio_props,
324                 video_props, 0.0,
325-                "",  "");
326+                "",  "", bEventMayCauseReschedule);
327 
328             db_events.enqueue(event);
329         }diff --git a/mythtv/libs/libmythtv/eithelper.h b/mythtv/libs/libmythtv/eithelper.h
330index 790d86e..3a11c86 100644
331--- a/mythtv/libs/libmythtv/eithelper.h
332+++ b/mythtv/libs/libmythtv/eithelper.h
333@@ -62,7 +62,7 @@ class EITHelper
334     virtual ~EITHelper();
335 
336     uint GetListSize(void) const;
337-    uint ProcessEvents(void);
338+    uint ProcessEvents(uint &rescheduleRequiredCount);
339 
340     uint GetGPSOffset(void) const { return (uint) (0 - gps_offset); }
341 diff --git a/mythtv/libs/libmythtv/eitscanner.cpp b/mythtv/libs/libmythtv/eitscanner.cpp
342index 0c2a70e..f61f886 100644
343--- a/mythtv/libs/libmythtv/eitscanner.cpp
344+++ b/mythtv/libs/libmythtv/eitscanner.cpp
345@@ -79,6 +79,7 @@ void EITScanner::run(void)
346 
347     MythTimer t;
348     uint eitCount = 0;
349+    uint rescheduleRequiredCount = 0;
350 
351     while (!exitThread)
352     {
353@@ -102,7 +103,7 @@ void EITScanner::run(void)
354 
355         if (list_size)
356         {
357-            eitCount += eitHelper->ProcessEvents();
358+            eitCount += eitHelper->ProcessEvents(rescheduleRequiredCount);
359             t.start();
360         }
361 
362@@ -113,7 +114,14 @@ void EITScanner::run(void)
363             LOG(VB_EIT, LOG_INFO,
364                 LOC_ID + QString("Added %1 EIT Events").arg(eitCount));
365             eitCount = 0;
366-            RescheduleRecordings();
367+
368+            LOG(VB_EIT, LOG_INFO, LOC + QString("rescheduleRequiredCount %1").arg(rescheduleRequiredCount));
369+
370+            if (rescheduleRequiredCount)
371+            {
372+                rescheduleRequiredCount = 0;
373+                RescheduleRecordings();
374+            }
375         }
376 
377         if (activeScan && (MythDate::current() > activeScanNextTrig))
378@@ -124,7 +132,11 @@ void EITScanner::run(void)
379                 LOG(VB_EIT, LOG_INFO,
380                     LOC_ID + QString("Added %1 EIT Events").arg(eitCount));
381                 eitCount = 0;
382-                RescheduleRecordings();
383+                if (rescheduleRequiredCount)
384+                {
385+                    rescheduleRequiredCount = 0;
386+                    RescheduleRecordings();
387+                }
388             }
389 
390             if (activeScanNextChan == activeScanChannels.end())diff --git a/mythtv/libs/libmythtv/programdata.cpp b/mythtv/libs/libmythtv/programdata.cpp
391index 06e822f..a21eff3 100644
392--- a/mythtv/libs/libmythtv/programdata.cpp
393+++ b/mythtv/libs/libmythtv/programdata.cpp
394@@ -750,6 +750,30 @@ uint DBEvent::InsertDB(MSqlQuery &query, uint chanid) const
395     return 1;
396 }
397 
398+uint  DBEventEIT::UpdateDB(MSqlQuery &query, int match_threshold, bool &RescheduleRequired) const
399+{
400+    RescheduleRequired = false;
401+    if (!DBEvent::UpdateDB(query, chanid, match_threshold))
402+        return 0;
403+
404+    if (eventMayCauseReschedule)
405+    {
406+        MSqlQuery localquery(MSqlQuery::InitCon());
407+        localquery.prepare("SELECT EXISTS(SELECT * FROM record WHERE seriesid = :SERIESID AND programid = :PROGRAMID)");
408+        localquery.bindValue(":SERIESID", seriesId);
409+        localquery.bindValue(":PROGRAMID", programId);
410+        if (!localquery.exec())
411+           MythDB::DBError("AddEIT", query);
412+        if (query.next())
413+            if (!query.value(0).toBool())
414+               RescheduleRequired = true;
415+        LOG(VB_EIT, LOG_INFO,
416+            LOC + QString("Checking reschedule - required %1").arg(RescheduleRequired));
417+    }
418+
419+    return 1;
420+}
421+
422 ProgInfo::ProgInfo(const ProgInfo &other) :
423     DBEvent(other.listingsource)
424 {diff --git a/mythtv/libs/libmythtv/programdata.h b/mythtv/libs/libmythtv/programdata.h
425index 9c484e6..d8e3583 100644
426--- a/mythtv/libs/libmythtv/programdata.h
427+++ b/mythtv/libs/libmythtv/programdata.h
428@@ -184,11 +184,13 @@ class MTV_PUBLIC DBEventEIT : public DBEvent
429                unsigned char    _audioProps,
430                unsigned char    _videoProps,
431                float            _stars,
432-               const QString   &_seriesId,  const QString   &_programId) :
433+               const QString   &_seriesId,
434+               const QString   &_programId,
435+               bool _eventMayCauseReschedule) :
436         DBEvent(_title, _subtitle, _desc, _category, _category_type,
437                 _start, _end, _subtitleType, _audioProps, _videoProps,
438                 _stars, _seriesId, _programId, kListingSourceEIT),
439-        chanid(_chanid), fixup(_fixup)
440+        chanid(_chanid), fixup(_fixup), eventMayCauseReschedule(_eventMayCauseReschedule)
441     {
442     }
443 
444@@ -206,14 +208,12 @@ class MTV_PUBLIC DBEventEIT : public DBEvent
445     {
446     }
447 
448-    uint UpdateDB(MSqlQuery &query, int match_threshold) const
449-    {
450-        return DBEvent::UpdateDB(query, chanid, match_threshold);
451-    }
452+    uint UpdateDB(MSqlQuery &query, int match_threshold, bool &RescheduleRequired) const;
453 
454   public:
455     uint32_t      chanid;
456     uint32_t      fixup;
457+    bool eventMayCauseReschedule;
458 };
459 
460 class MTV_PUBLIC ProgInfo : public DBEvent