mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Now using hash tables to speed up cSchedule::GetEvent()
This commit is contained in:
parent
b4cbb84489
commit
7701acd968
@ -1361,3 +1361,4 @@ Paavo Hartikainen <pahartik@sci.fi>
|
|||||||
Georg Acher <acher@baycom.de>
|
Georg Acher <acher@baycom.de>
|
||||||
for making tChannelID::operator==() inline for better performance
|
for making tChannelID::operator==() inline for better performance
|
||||||
for introducing cListBase::count for better performance
|
for introducing cListBase::count for better performance
|
||||||
|
for a patch that was used to implement hash tables to speed up cSchedule::GetEvent()
|
||||||
|
2
HISTORY
2
HISTORY
@ -3568,3 +3568,5 @@ Video Disk Recorder Revision History
|
|||||||
- Introduced cListBase::count for better performance (thanks to Georg Acher).
|
- Introduced cListBase::count for better performance (thanks to Georg Acher).
|
||||||
- cEvent no longer stores the channelID directly, but rather has a pointer to
|
- cEvent no longer stores the channelID directly, but rather has a pointer to
|
||||||
the schedule it is in.
|
the schedule it is in.
|
||||||
|
- Now using hash tables to speed up cSchedule::GetEvent() (partially based on
|
||||||
|
a patch from Georg Acher).
|
||||||
|
8
eit.c
8
eit.c
@ -8,7 +8,7 @@
|
|||||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||||
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
||||||
*
|
*
|
||||||
* $Id: eit.c 1.106 2005/05/28 10:07:12 kls Exp $
|
* $Id: eit.c 1.107 2005/05/28 11:35:55 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eit.h"
|
#include "eit.h"
|
||||||
@ -52,11 +52,12 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
|||||||
if (SiEitEvent.getStartTime() == 0 || SiEitEvent.getDuration() == 0)
|
if (SiEitEvent.getStartTime() == 0 || SiEitEvent.getDuration() == 0)
|
||||||
continue;
|
continue;
|
||||||
Empty = false;
|
Empty = false;
|
||||||
|
cEvent *newEvent = NULL;
|
||||||
cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), SiEitEvent.getStartTime());
|
cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), SiEitEvent.getStartTime());
|
||||||
if (!pEvent) {
|
if (!pEvent) {
|
||||||
// If we don't have that event yet, we create a new one.
|
// If we don't have that event yet, we create a new one.
|
||||||
// Otherwise we copy the information into the existing event anyway, because the data might have changed.
|
// Otherwise we copy the information into the existing event anyway, because the data might have changed.
|
||||||
pEvent = pSchedule->AddEvent(new cEvent(pSchedule, SiEitEvent.getEventId()));
|
pEvent = newEvent = new cEvent(SiEitEvent.getEventId());
|
||||||
if (!pEvent)
|
if (!pEvent)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -221,6 +222,9 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
|||||||
delete ExtendedEventDescriptors;
|
delete ExtendedEventDescriptors;
|
||||||
delete ShortEventDescriptor;
|
delete ShortEventDescriptor;
|
||||||
|
|
||||||
|
if (newEvent)
|
||||||
|
pSchedule->AddEvent(newEvent);
|
||||||
|
|
||||||
pEvent->SetComponents(Components);
|
pEvent->SetComponents(Components);
|
||||||
|
|
||||||
pEvent->FixEpgBugs();
|
pEvent->FixEpgBugs();
|
||||||
|
58
epg.c
58
epg.c
@ -7,7 +7,7 @@
|
|||||||
* Original version (as used in VDR before 1.3.0) written by
|
* Original version (as used in VDR before 1.3.0) written by
|
||||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||||
*
|
*
|
||||||
* $Id: epg.c 1.32 2005/05/28 10:03:39 kls Exp $
|
* $Id: epg.c 1.33 2005/05/28 13:17:20 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "epg.h"
|
#include "epg.h"
|
||||||
@ -81,9 +81,9 @@ void cComponents::SetComponent(int Index, uchar Stream, uchar Type, const char *
|
|||||||
|
|
||||||
// --- cEvent ----------------------------------------------------------------
|
// --- cEvent ----------------------------------------------------------------
|
||||||
|
|
||||||
cEvent::cEvent(cSchedule *Schedule, u_int16_t EventID)
|
cEvent::cEvent(u_int16_t EventID)
|
||||||
{
|
{
|
||||||
schedule = Schedule;
|
schedule = NULL;
|
||||||
eventID = EventID;
|
eventID = EventID;
|
||||||
tableID = 0;
|
tableID = 0;
|
||||||
version = 0xFF; // actual version numbers are 0..31
|
version = 0xFF; // actual version numbers are 0..31
|
||||||
@ -119,7 +119,13 @@ tChannelID cEvent::ChannelID(void) const
|
|||||||
|
|
||||||
void cEvent::SetEventID(u_int16_t EventID)
|
void cEvent::SetEventID(u_int16_t EventID)
|
||||||
{
|
{
|
||||||
|
if (eventID != EventID) {
|
||||||
|
if (schedule)
|
||||||
|
schedule->UnhashEvent(this);
|
||||||
eventID = EventID;
|
eventID = EventID;
|
||||||
|
if (schedule)
|
||||||
|
schedule->HashEvent(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cEvent::SetTableID(uchar TableID)
|
void cEvent::SetTableID(uchar TableID)
|
||||||
@ -163,7 +169,13 @@ void cEvent::SetComponents(cComponents *Components)
|
|||||||
|
|
||||||
void cEvent::SetStartTime(time_t StartTime)
|
void cEvent::SetStartTime(time_t StartTime)
|
||||||
{
|
{
|
||||||
|
if (startTime != StartTime) {
|
||||||
|
if (schedule)
|
||||||
|
schedule->UnhashEvent(this);
|
||||||
startTime = StartTime;
|
startTime = StartTime;
|
||||||
|
if (schedule)
|
||||||
|
schedule->HashEvent(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cEvent::SetDuration(int Duration)
|
void cEvent::SetDuration(int Duration)
|
||||||
@ -285,12 +297,15 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
|
|||||||
int n = sscanf(t, "%u %ld %d %X", &EventID, &StartTime, &Duration, &TableID);
|
int n = sscanf(t, "%u %ld %d %X", &EventID, &StartTime, &Duration, &TableID);
|
||||||
if (n == 3 || n == 4) {
|
if (n == 3 || n == 4) {
|
||||||
Event = (cEvent *)Schedule->GetEvent(EventID, StartTime);
|
Event = (cEvent *)Schedule->GetEvent(EventID, StartTime);
|
||||||
|
cEvent *newEvent = NULL;
|
||||||
if (!Event)
|
if (!Event)
|
||||||
Event = Schedule->AddEvent(new cEvent(Schedule, EventID));
|
Event = newEvent = new cEvent(EventID);
|
||||||
if (Event) {
|
if (Event) {
|
||||||
Event->SetTableID(TableID);
|
Event->SetTableID(TableID);
|
||||||
Event->SetStartTime(StartTime);
|
Event->SetStartTime(StartTime);
|
||||||
Event->SetDuration(Duration);
|
Event->SetDuration(Duration);
|
||||||
|
if (newEvent)
|
||||||
|
Schedule->AddEvent(newEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,9 +653,32 @@ cSchedule::cSchedule(tChannelID ChannelID)
|
|||||||
cEvent *cSchedule::AddEvent(cEvent *Event)
|
cEvent *cSchedule::AddEvent(cEvent *Event)
|
||||||
{
|
{
|
||||||
events.Add(Event);
|
events.Add(Event);
|
||||||
|
Event->schedule = this;
|
||||||
|
HashEvent(Event);
|
||||||
return Event;
|
return Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSchedule::DelEvent(cEvent *Event)
|
||||||
|
{
|
||||||
|
if (Event->schedule == this) {
|
||||||
|
UnhashEvent(Event);
|
||||||
|
events.Del(Event);
|
||||||
|
Event->schedule = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSchedule::HashEvent(cEvent *Event)
|
||||||
|
{
|
||||||
|
eventsHashID.Add(Event, Event->EventID());
|
||||||
|
eventsHashStartTime.Add(Event, Event->StartTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSchedule::UnhashEvent(cEvent *Event)
|
||||||
|
{
|
||||||
|
eventsHashID.Del(Event, Event->EventID());
|
||||||
|
eventsHashStartTime.Del(Event, Event->StartTime());
|
||||||
|
}
|
||||||
|
|
||||||
const cEvent *cSchedule::GetPresentEvent(bool CheckRunningStatus) const
|
const cEvent *cSchedule::GetPresentEvent(bool CheckRunningStatus) const
|
||||||
{
|
{
|
||||||
const cEvent *pe = NULL;
|
const cEvent *pe = NULL;
|
||||||
@ -669,13 +707,9 @@ const cEvent *cSchedule::GetEvent(u_int16_t EventID, time_t StartTime) const
|
|||||||
{
|
{
|
||||||
// Returns either the event info with the given EventID or, if that one can't
|
// Returns either the event info with the given EventID or, if that one can't
|
||||||
// be found, the one with the given StartTime (or NULL if neither can be found)
|
// be found, the one with the given StartTime (or NULL if neither can be found)
|
||||||
cEvent *pt = NULL;
|
cEvent *pt = eventsHashID.Get(EventID);
|
||||||
for (cEvent *pe = events.First(); pe; pe = events.Next(pe)) {
|
if (!pt && StartTime > 0) // 'StartTime < 0' is apparently used with NVOD channels
|
||||||
if (pe->EventID() == EventID)
|
pt = eventsHashStartTime.Get(StartTime);
|
||||||
return pe;
|
|
||||||
if (StartTime > 0 && pe->StartTime() == StartTime) // 'StartTime < 0' is apparently used with NVOD channels
|
|
||||||
pt = pe;
|
|
||||||
}
|
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,7 +776,7 @@ void cSchedule::Cleanup(time_t Time)
|
|||||||
if (!Event)
|
if (!Event)
|
||||||
break;
|
break;
|
||||||
if (!Event->HasTimer() && Event->EndTime() + Setup.EPGLinger * 60 + 3600 < Time) { // adding one hour for safety
|
if (!Event->HasTimer() && Event->EndTime() + Setup.EPGLinger * 60 + 3600 < Time) { // adding one hour for safety
|
||||||
events.Del(Event);
|
DelEvent(Event);
|
||||||
a--;
|
a--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
epg.h
10
epg.h
@ -7,7 +7,7 @@
|
|||||||
* Original version (as used in VDR before 1.3.0) written by
|
* Original version (as used in VDR before 1.3.0) written by
|
||||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||||
*
|
*
|
||||||
* $Id: epg.h 1.24 2005/05/28 10:00:12 kls Exp $
|
* $Id: epg.h 1.25 2005/05/28 11:32:36 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __EPG_H
|
#ifndef __EPG_H
|
||||||
@ -47,6 +47,7 @@ public:
|
|||||||
class cSchedule;
|
class cSchedule;
|
||||||
|
|
||||||
class cEvent : public cListObject {
|
class cEvent : public cListObject {
|
||||||
|
friend class cSchedule;
|
||||||
private:
|
private:
|
||||||
cSchedule *schedule; // The Schedule this event belongs to
|
cSchedule *schedule; // The Schedule this event belongs to
|
||||||
u_int16_t eventID; // Event ID of this event
|
u_int16_t eventID; // Event ID of this event
|
||||||
@ -62,7 +63,7 @@ private:
|
|||||||
time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL)
|
time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL)
|
||||||
time_t seen; // When this event was last seen in the data stream
|
time_t seen; // When this event was last seen in the data stream
|
||||||
public:
|
public:
|
||||||
cEvent(cSchedule *Schedule, u_int16_t EventID);
|
cEvent(u_int16_t EventID);
|
||||||
~cEvent();
|
~cEvent();
|
||||||
virtual int Compare(const cListObject &ListObject) const;
|
virtual int Compare(const cListObject &ListObject) const;
|
||||||
tChannelID ChannelID(void) const;
|
tChannelID ChannelID(void) const;
|
||||||
@ -110,6 +111,8 @@ class cSchedule : public cListObject {
|
|||||||
private:
|
private:
|
||||||
tChannelID channelID;
|
tChannelID channelID;
|
||||||
cList<cEvent> events;
|
cList<cEvent> events;
|
||||||
|
cHash<cEvent> eventsHashID;
|
||||||
|
cHash<cEvent> eventsHashStartTime;
|
||||||
bool hasRunning;
|
bool hasRunning;
|
||||||
time_t modified;
|
time_t modified;
|
||||||
time_t presentSeen;
|
time_t presentSeen;
|
||||||
@ -128,6 +131,9 @@ public:
|
|||||||
void Cleanup(time_t Time);
|
void Cleanup(time_t Time);
|
||||||
void Cleanup(void);
|
void Cleanup(void);
|
||||||
cEvent *AddEvent(cEvent *Event);
|
cEvent *AddEvent(cEvent *Event);
|
||||||
|
void DelEvent(cEvent *Event);
|
||||||
|
void cSchedule::HashEvent(cEvent *Event);
|
||||||
|
void cSchedule::UnhashEvent(cEvent *Event);
|
||||||
const cList<cEvent> *Events(void) const { return &events; }
|
const cList<cEvent> *Events(void) const { return &events; }
|
||||||
const cEvent *GetPresentEvent(bool CheckRunningStatus = false) const;
|
const cEvent *GetPresentEvent(bool CheckRunningStatus = false) const;
|
||||||
const cEvent *GetFollowingEvent(bool CheckRunningStatus = false) const;
|
const cEvent *GetFollowingEvent(bool CheckRunningStatus = false) const;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: recording.c 1.105 2005/05/28 10:04:24 kls Exp $
|
* $Id: recording.c 1.106 2005/05/28 11:36:14 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
@ -228,7 +228,7 @@ cRecordingInfo::cRecordingInfo(const cEvent *Event)
|
|||||||
ownEvent = NULL;
|
ownEvent = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
event = ownEvent = new cEvent(NULL, 0);
|
event = ownEvent = new cEvent(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cRecordingInfo::~cRecordingInfo()
|
cRecordingInfo::~cRecordingInfo()
|
||||||
|
54
tools.c
54
tools.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.c 1.93 2005/05/26 11:40:14 kls Exp $
|
* $Id: tools.c 1.94 2005/05/28 11:46:44 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
@ -1060,3 +1060,55 @@ void cListBase::Sort(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cHashBase -------------------------------------------------------------
|
||||||
|
|
||||||
|
cHashBase::cHashBase(int Size)
|
||||||
|
{
|
||||||
|
size = Size;
|
||||||
|
hashTable = (cList<cHashObject>**)calloc(size, sizeof(cList<cHashObject>*));
|
||||||
|
}
|
||||||
|
|
||||||
|
cHashBase::~cHashBase(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
delete hashTable[i];
|
||||||
|
free(hashTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cHashBase::Add(cListObject *Object, int Id)
|
||||||
|
{
|
||||||
|
int hash = hashfn(Id);
|
||||||
|
if (!hashTable[hash])
|
||||||
|
hashTable[hash] = new cList<cHashObject>;
|
||||||
|
hashTable[hash]->Add(new cHashObject(Object, Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cHashBase::Del(cListObject *Object, int Id)
|
||||||
|
{
|
||||||
|
cList<cHashObject> *list = hashTable[hashfn(Id)];
|
||||||
|
if (list) {
|
||||||
|
for (cHashObject *hob = list->First(); hob; hob = list->Next(hob)) {
|
||||||
|
if (hob->object == Object) {
|
||||||
|
list->Del(hob);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cListObject *cHashBase::Get(int Id) const
|
||||||
|
{
|
||||||
|
cList<cHashObject> *list = hashTable[hashfn(Id)];
|
||||||
|
if (list) {
|
||||||
|
for (cHashObject *hob = list->First(); hob; hob = list->Next(hob)) {
|
||||||
|
if (hob->id == Id)
|
||||||
|
return hob->object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cList<cHashObject> *cHashBase::GetList(int Id) const
|
||||||
|
{
|
||||||
|
return hashTable[hashfn(Id)];
|
||||||
|
}
|
||||||
|
34
tools.h
34
tools.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.h 1.70 2005/05/26 11:34:01 kls Exp $
|
* $Id: tools.h 1.71 2005/05/28 11:24:49 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
@ -236,4 +236,36 @@ public:
|
|||||||
T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists"
|
T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cHashObject : public cListObject {
|
||||||
|
friend class cHashBase;
|
||||||
|
private:
|
||||||
|
int id;
|
||||||
|
cListObject *object;
|
||||||
|
public:
|
||||||
|
cHashObject(cListObject *Object, int Id) { object = Object; id = Id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class cHashBase {
|
||||||
|
private:
|
||||||
|
cList<cHashObject> **hashTable;
|
||||||
|
int size;
|
||||||
|
int hashfn(int Id) const { return Id % size; }
|
||||||
|
protected:
|
||||||
|
cHashBase(int Size);
|
||||||
|
public:
|
||||||
|
virtual ~cHashBase();
|
||||||
|
void Add(cListObject *Object, int Id);
|
||||||
|
void Del(cListObject *Object, int Id);
|
||||||
|
cListObject *Get(int Id) const;
|
||||||
|
cList<cHashObject> *GetList(int Id) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HASHSIZE 512
|
||||||
|
|
||||||
|
template<class T> class cHash : public cHashBase {
|
||||||
|
public:
|
||||||
|
cHash(int Size = HASHSIZE) : cHashBase(Size) {}
|
||||||
|
T *Get(int Id) const { return (T *)cHashBase::Get(Id); }
|
||||||
|
};
|
||||||
|
|
||||||
#endif //__TOOLS_H
|
#endif //__TOOLS_H
|
||||||
|
Loading…
Reference in New Issue
Block a user