sectionsd: fix unlocked event access under high load

This commit is contained in:
Stefan Seyfried
2012-10-14 16:21:37 +02:00
parent 36995d11fc
commit 32597561a0

View File

@@ -5,7 +5,7 @@
* Copyright (C) 2001 by fnbrd (fnbrd@gmx.de) * Copyright (C) 2001 by fnbrd (fnbrd@gmx.de)
* Homepage: http://dbox2.elxsi.de * Homepage: http://dbox2.elxsi.de
* *
* Copyright (C) 2008, 2009 Stefan Seyfried * Copyright (C) 2008, 2009, 2010, 2011, 2012 Stefan Seyfried
* *
* Copyright (C) 2011-2012 CoolStream International Ltd * Copyright (C) 2011-2012 CoolStream International Ltd
* *
@@ -141,10 +141,15 @@ static CFreeSatThread threadFSEIT;
CSdtThread threadSDT; CSdtThread threadSDT;
#endif #endif
#ifdef DEBUG_EVENT_LOCK
static time_t lockstart = 0;
#endif
static int sectionsd_stop = 0; static int sectionsd_stop = 0;
static bool slow_addevent = true; static bool slow_addevent = true;
inline void readLockServices(void) inline void readLockServices(void)
{ {
pthread_rwlock_rdlock(&servicesLock); pthread_rwlock_rdlock(&servicesLock);
@@ -183,10 +188,21 @@ inline void readLockEvents(void)
inline void writeLockEvents(void) inline void writeLockEvents(void)
{ {
pthread_rwlock_wrlock(&eventsLock); pthread_rwlock_wrlock(&eventsLock);
#ifdef DEBUG_EVENT_LOCK
lockstart = time_monotonic_ms();
#endif
} }
inline void unlockEvents(void) inline void unlockEvents(void)
{ {
#ifdef DEBUG_EVENT_LOCK
if (lockstart) {
time_t tmp = time_monotonic_ms() - lockstart;
if (tmp > 50)
xprintf("locked ms %d\n", tmp);
lockstart = 0;
}
#endif
pthread_rwlock_unlock(&eventsLock); pthread_rwlock_unlock(&eventsLock);
} }
@@ -207,10 +223,11 @@ static MySIeventUniqueKeysMetaOrderServiceUniqueKey mySIeventUniqueKeysMetaOrder
static MySIservicesOrderUniqueKey mySIservicesOrderUniqueKey; static MySIservicesOrderUniqueKey mySIservicesOrderUniqueKey;
static MySIservicesNVODorderUniqueKey mySIservicesNVODorderUniqueKey; static MySIservicesNVODorderUniqueKey mySIservicesNVODorderUniqueKey;
/* needs write lock held! */
static bool deleteEvent(const event_id_t uniqueKey) static bool deleteEvent(const event_id_t uniqueKey)
{ {
bool ret = false; bool ret = false;
writeLockEvents(); // writeLockEvents();
MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(uniqueKey); MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(uniqueKey);
if (e != mySIeventsOrderUniqueKey.end()) { if (e != mySIeventsOrderUniqueKey.end()) {
@@ -226,7 +243,7 @@ static bool deleteEvent(const event_id_t uniqueKey)
mySIeventsNVODorderUniqueKey.erase(uniqueKey); mySIeventsNVODorderUniqueKey.erase(uniqueKey);
ret = true; ret = true;
} }
unlockEvents(); // unlockEvents();
return ret; return ret;
} }
@@ -311,7 +328,7 @@ xprintf("addEvent: current %016llx event %016llx running %d messaging_got_CN %d\
unlockMessaging(); unlockMessaging();
} }
readLockEvents(); writeLockEvents();
MySIeventsOrderUniqueKey::iterator si = mySIeventsOrderUniqueKey.find(evt.uniqueKey()); MySIeventsOrderUniqueKey::iterator si = mySIeventsOrderUniqueKey.find(evt.uniqueKey());
bool already_exists = (si != mySIeventsOrderUniqueKey.end()); bool already_exists = (si != mySIeventsOrderUniqueKey.end());
if (already_exists && (evt.table_id < si->second->table_id)) if (already_exists && (evt.table_id < si->second->table_id))
@@ -424,20 +441,16 @@ xprintf("addEvent: current %016llx event %016llx running %d messaging_got_CN %d\
to_delete.push_back(x_key); to_delete.push_back(x_key);
} }
} }
unlockEvents();
while (! to_delete.empty()) while (! to_delete.empty())
{ {
deleteEvent(to_delete.back()); deleteEvent(to_delete.back());
to_delete.pop_back(); to_delete.pop_back();
} }
} else {
// Damit in den nicht nach Event-ID sortierten Mengen
// Mehrere Events mit gleicher ID sind, diese vorher loeschen
unlockEvents();
} }
// Damit in den nicht nach Event-ID sortierten Mengen
// Mehrere Events mit gleicher ID sind, diese vorher loeschen
deleteEvent(e->uniqueKey()); deleteEvent(e->uniqueKey());
readLockEvents();
if ( !mySIeventsOrderUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) { if ( !mySIeventsOrderUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) {
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent = MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent =
mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin();
@@ -471,12 +484,8 @@ xprintf("addEvent: current %016llx event %016llx running %d messaging_got_CN %d\
unlockMessaging(); unlockMessaging();
} }
// else fprintf(stderr, ">"); // else fprintf(stderr, ">");
unlockEvents();
deleteEvent((*lastEvent)->uniqueKey()); deleteEvent((*lastEvent)->uniqueKey());
} }
else
unlockEvents();
readLockEvents();
// Pruefen ob es ein Meta-Event ist // Pruefen ob es ein Meta-Event ist
MySIeventUniqueKeysMetaOrderServiceUniqueKey::iterator i = mySIeventUniqueKeysMetaOrderServiceUniqueKey.find(e->get_channel_id()); MySIeventUniqueKeysMetaOrderServiceUniqueKey::iterator i = mySIeventUniqueKeysMetaOrderServiceUniqueKey.find(e->get_channel_id());
@@ -496,9 +505,6 @@ xprintf("addEvent: current %016llx event %016llx running %d messaging_got_CN %d\
// Falls das Event in den beiden Mengen mit Zeiten nicht vorhanden // Falls das Event in den beiden Mengen mit Zeiten nicht vorhanden
// ist, dieses dort einfuegen // ist, dieses dort einfuegen
MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator i2 = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(ie->second); MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator i2 = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(ie->second);
unlockEvents();
writeLockEvents();
if (i2 == mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) if (i2 == mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end())
{ {
// nicht vorhanden -> einfuegen // nicht vorhanden -> einfuegen
@@ -511,8 +517,6 @@ xprintf("addEvent: current %016llx event %016llx running %d messaging_got_CN %d\
} }
} }
} }
unlockEvents();
writeLockEvents();
// printf("Adding: %04x\n", (int) e->uniqueKey()); // printf("Adding: %04x\n", (int) e->uniqueKey());
// normales Event // normales Event
@@ -540,22 +544,18 @@ static void addNVODevent(const SIevent &evt)
SIeventPtr e(eptr); SIeventPtr e(eptr);
readLockEvents(); writeLockEvents();
MySIeventsOrderUniqueKey::iterator e2 = mySIeventsOrderUniqueKey.find(e->uniqueKey()); MySIeventsOrderUniqueKey::iterator e2 = mySIeventsOrderUniqueKey.find(e->uniqueKey());
if (e2 != mySIeventsOrderUniqueKey.end()) if (e2 != mySIeventsOrderUniqueKey.end())
{ {
// bisher gespeicherte Zeiten retten // bisher gespeicherte Zeiten retten
unlockEvents();
writeLockEvents();
e->times.insert(e2->second->times.begin(), e2->second->times.end()); e->times.insert(e2->second->times.begin(), e2->second->times.end());
} }
unlockEvents();
// Damit in den nicht nach Event-ID sortierten Mengen // Damit in den nicht nach Event-ID sortierten Mengen
// mehrere Events mit gleicher ID sind, diese vorher loeschen // mehrere Events mit gleicher ID sind, diese vorher loeschen
deleteEvent(e->uniqueKey()); deleteEvent(e->uniqueKey());
readLockEvents();
if ( !mySIeventsOrderUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) { if ( !mySIeventsOrderUniqueKey.empty() && mySIeventsOrderUniqueKey.size() >= max_events && max_events != 0 ) {
//TODO: Set Old Events to 0 if limit is reached... //TODO: Set Old Events to 0 if limit is reached...
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent = MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent =
@@ -569,24 +569,18 @@ static void addNVODevent(const SIevent &evt)
--lastEvent; --lastEvent;
} }
unlockMessaging(); unlockMessaging();
unlockEvents();
deleteEvent((*lastEvent)->uniqueKey()); deleteEvent((*lastEvent)->uniqueKey());
} }
else
unlockEvents();
writeLockEvents();
mySIeventsOrderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); mySIeventsOrderUniqueKey.insert(std::make_pair(e->uniqueKey(), e));
mySIeventsNVODorderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); mySIeventsNVODorderUniqueKey.insert(std::make_pair(e->uniqueKey(), e));
unlockEvents();
if (!e->times.empty()) if (!e->times.empty())
{ {
// diese beiden Mengen enthalten nur Events mit Zeiten // diese beiden Mengen enthalten nur Events mit Zeiten
writeLockEvents();
mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e); mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e);
mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e); mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e);
unlockEvents();
} }
unlockEvents();
} }
static void removeOldEvents(const long seconds) static void removeOldEvents(const long seconds)
@@ -596,7 +590,7 @@ static void removeOldEvents(const long seconds)
// Alte events loeschen // Alte events loeschen
time_t zeit = time(NULL); time_t zeit = time(NULL);
readLockEvents(); writeLockEvents();
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin();
@@ -614,10 +608,9 @@ static void removeOldEvents(const long seconds)
to_delete.push_back((*e)->uniqueKey()); to_delete.push_back((*e)->uniqueKey());
++e; ++e;
} }
unlockEvents();
for (std::vector<event_id_t>::iterator i = to_delete.begin(); i != to_delete.end(); ++i) for (std::vector<event_id_t>::iterator i = to_delete.begin(); i != to_delete.end(); ++i)
deleteEvent(*i); deleteEvent(*i);
unlockEvents();
return; return;
} }