eitd/sectionsd.cpp: remove old CN thread code;

reuse code to send response as sendEmptyResponse;
simplify commandSetConfig - less debug in favor of less locks;
reuse code in time and CN threads;
remove unused code in tine thread - bTimeCorrect never used
This commit is contained in:
[CST] Focus
2012-02-23 16:30:07 +04:00
parent effe71d995
commit 11ec2a4502
2 changed files with 102 additions and 360 deletions

View File

@@ -158,6 +158,7 @@ class CEitThread : public CSectionThread
class CCNThread : public CSectionThread class CCNThread : public CSectionThread
{ {
private: private:
void sendCNEvent();
void run(); void run();
}; };

View File

@@ -129,27 +129,20 @@ int ntprefresh;
int ntpenable; int ntpenable;
static int eit_update_fd = -1; static int eit_update_fd = -1;
static bool update_eit = true;
std::string epg_dir(""); std::string epg_dir("");
/* messaging_eit_is_busy does not need locking, it is only written to from CN-Thread */
static bool messaging_eit_is_busy = false;
static bool messaging_need_eit_version = false;
/* messaging_current_servicekey does probably not need locking, since it is /* messaging_current_servicekey does probably not need locking, since it is
changed from one place */ changed from one place */
static t_channel_id messaging_current_servicekey = 0; static t_channel_id messaging_current_servicekey = 0;
static bool channel_is_blacklisted = false; static bool channel_is_blacklisted = false;
bool timeset = false; bool timeset = false;
bool bTimeCorrect = false;
pthread_cond_t timeIsSetCond = PTHREAD_COND_INITIALIZER; pthread_cond_t timeIsSetCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t timeIsSetMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t timeIsSetMutex = PTHREAD_MUTEX_INITIALIZER;
static int messaging_have_CN = 0x00; // 0x01 = CURRENT, 0x02 = NEXT static int messaging_have_CN = 0x00; // 0x01 = CURRENT, 0x02 = NEXT
static int messaging_got_CN = 0x00; // 0x01 = CURRENT, 0x02 = NEXT static int messaging_got_CN = 0x00; // 0x01 = CURRENT, 0x02 = NEXT
static time_t messaging_last_requested = time_monotonic();
static bool messaging_neutrino_sets_time = false; static bool messaging_neutrino_sets_time = false;
// EVENTS... // EVENTS...
@@ -162,9 +155,6 @@ static pthread_rwlock_t messagingLock = PTHREAD_RWLOCK_INITIALIZER;
static pthread_cond_t timeThreadSleepCond = PTHREAD_COND_INITIALIZER; static pthread_cond_t timeThreadSleepCond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t timeThreadSleepMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t timeThreadSleepMutex = PTHREAD_MUTEX_INITIALIZER;
/* no matter how big the buffer, we will receive spurious POLLERR's in table 0x60,
but those are not a big deal, so let's save some memory */
//static DMX dmxEIT(0x12, 3000 /*320*/); //static DMX dmxEIT(0x12, 3000 /*320*/);
static CEitThread threadEIT; static CEitThread threadEIT;
@@ -242,9 +232,6 @@ inline bool waitForTimeset(void)
waitForTimeset() returns. Let's hope that we work around this issue waitForTimeset() returns. Let's hope that we work around this issue
with this sleep */ with this sleep */
sleep(1); sleep(1);
writeLockMessaging();
messaging_last_requested = time_monotonic();
unlockMessaging();
return true; return true;
} }
@@ -656,7 +643,6 @@ static void removeOldEvents(const long seconds)
MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin();
//TODO move messaging_zap_detected check to thread, not here
while ((e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()) && (!messaging_zap_detected)) { while ((e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()) && (!messaging_zap_detected)) {
bool goodtimefound = false; bool goodtimefound = false;
for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) { for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) {
@@ -855,6 +841,15 @@ inline bool writeNbytes(int fd, const char *buf, const size_t numberOfBytes, co
return send_data(fd, buf, numberOfBytes, timeout); return send_data(fd, buf, numberOfBytes, timeout);
} }
/* send back an empty response */
static void sendEmptyResponse(int connfd, char *, const unsigned)
{
struct sectionsd::msgResponseHeader msgResponse;
msgResponse.dataLength = 0;
writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS);
return;
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// connection-thread // connection-thread
// handles incoming requests // handles incoming requests
@@ -908,7 +903,7 @@ static void commandPauseScanning(int connfd, char *data, const unsigned dataLeng
unlockMessaging(); unlockMessaging();
scanning = 1; scanning = 1;
if (!bTimeCorrect && !ntpenable) if (!ntpenable)
{ {
pthread_mutex_lock(&timeThreadSleepMutex); pthread_mutex_lock(&timeThreadSleepMutex);
pthread_cond_broadcast(&timeThreadSleepCond); pthread_cond_broadcast(&timeThreadSleepCond);
@@ -924,12 +919,7 @@ static void commandPauseScanning(int connfd, char *data, const unsigned dataLeng
threadSDT.change(0); threadSDT.change(0);
#endif #endif
} }
sendEmptyResponse(connfd, NULL, 0);
struct sectionsd::msgResponseHeader msgResponse;
msgResponse.dataLength = 0;
writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS);
return;
} }
static void commandserviceChanged(int connfd, char *data, const unsigned dataLength) static void commandserviceChanged(int connfd, char *data, const unsigned dataLength)
@@ -942,9 +932,9 @@ static void commandserviceChanged(int connfd, char *data, const unsigned dataLen
uniqueServiceKey &= 0xFFFFFFFFFFFFULL; uniqueServiceKey &= 0xFFFFFFFFFFFFULL;
dprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); dprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey);
xprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_ID_TYPE "\n\n", uniqueServiceKey); xprintf("[sectionsd] commandserviceChanged: Service change to " PRINTF_CHANNEL_ID_TYPE "\n\n", uniqueServiceKey);
messaging_last_requested = time_monotonic(); static t_channel_id time_trigger_last = 0;
#if 0 #if 0
if(checkBlacklist(uniqueServiceKey)) if(checkBlacklist(uniqueServiceKey))
@@ -1008,7 +998,7 @@ xprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_
messaging_have_CN = 0x00; messaging_have_CN = 0x00;
messaging_got_CN = 0x00; messaging_got_CN = 0x00;
messaging_zap_detected = true; messaging_zap_detected = true;
messaging_need_eit_version = false; //messaging_need_eit_version = false;
unlockMessaging(); unlockMessaging();
threadCN.setCurrentService(messaging_current_servicekey); threadCN.setCurrentService(messaging_current_servicekey);
@@ -1019,17 +1009,20 @@ xprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_
#ifdef ENABLE_SDT #ifdef ENABLE_SDT
threadSDT.setCurrentService(messaging_current_servicekey); threadSDT.setCurrentService(messaging_current_servicekey);
#endif #endif
if (time_trigger_last != (messaging_current_servicekey & 0xFFFFFFFF0000ULL))
{
time_trigger_last = messaging_current_servicekey & 0xFFFFFFFF0000ULL;
pthread_mutex_lock(&timeThreadSleepMutex);
pthread_cond_broadcast(&timeThreadSleepCond);
pthread_mutex_unlock(&timeThreadSleepMutex);
}
} }
else else
dprintf("[sectionsd] commandserviceChanged: no change...\n"); dprintf("[sectionsd] commandserviceChanged: no change...\n");
out: out:
struct sectionsd::msgResponseHeader msgResponse; sendEmptyResponse(connfd, NULL, 0);
msgResponse.dataLength = 0; xprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_ID_TYPE "\n\n", uniqueServiceKey);
writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS);
dprintf("[sectionsd] commandserviceChanged: END!!\n");
return ;
} }
static void commandGetIsScanningActive(int connfd, char* /*data*/, const unsigned /*dataLength*/) static void commandGetIsScanningActive(int connfd, char* /*data*/, const unsigned /*dataLength*/)
@@ -1147,55 +1140,42 @@ static void commandUnRegisterEventClient(int /*connfd*/, char *data, const unsig
eventServer->unRegisterEvent2(((CEventServer::commandUnRegisterEvent*)data)->eventID, ((CEventServer::commandUnRegisterEvent*)data)->clientID); eventServer->unRegisterEvent2(((CEventServer::commandUnRegisterEvent*)data)->eventID, ((CEventServer::commandUnRegisterEvent*)data)->clientID);
} }
static void commandSetConfig(int connfd, char *data, const unsigned /*dataLength*/) static void commandSetConfig(int connfd, char *data, const unsigned /*dataLength*/)
{ {
struct sectionsd::msgResponseHeader responseHeader; sendEmptyResponse(connfd, NULL, 0);
struct sectionsd::commandSetConfig *pmsg; struct sectionsd::commandSetConfig *pmsg;
pmsg = (struct sectionsd::commandSetConfig *)data; pmsg = (struct sectionsd::commandSetConfig *)data;
if (secondsToCache != (long)(pmsg->epg_cache)*24*60L*60L) { /* writeLockEvents not needed because write lock will block if read lock active */
dprintf("new epg_cache = %d\n", pmsg->epg_cache); readLockEvents();
writeLockEvents(); secondsToCache = (long)(pmsg->epg_cache)*24*60L*60L;
secondsToCache = (long)(pmsg->epg_cache)*24*60L*60L; oldEventsAre = (long)(pmsg->epg_old_events)*60L*60L;
unlockEvents(); secondsExtendedTextCache = (long)(pmsg->epg_extendedcache)*60L*60L;
} max_events = pmsg->epg_max_events;
unlockEvents();
if (oldEventsAre != (long)(pmsg->epg_old_events)*60L*60L) { bool time_wakeup = false;
dprintf("new epg_old_events = %d\n", pmsg->epg_old_events); if (ntpserver.compare((std::string)&data[sizeof(struct sectionsd::commandSetConfig)])) {
writeLockEvents(); time_wakeup = true;
oldEventsAre = (long)(pmsg->epg_old_events)*60L*60L;
unlockEvents();
} }
if (secondsExtendedTextCache != (long)(pmsg->epg_extendedcache)*60L*60L) {
dprintf("new epg_extendedcache = %d\n", pmsg->epg_extendedcache);
// lockEvents();
writeLockEvents();
secondsExtendedTextCache = (long)(pmsg->epg_extendedcache)*60L*60L;
unlockEvents();
}
if (max_events != pmsg->epg_max_events) {
dprintf("new epg_max_events = %d\n", pmsg->epg_max_events);
writeLockEvents();
max_events = pmsg->epg_max_events;
unlockEvents();
}
if (ntprefresh != pmsg->network_ntprefresh) { if (ntprefresh != pmsg->network_ntprefresh) {
dprintf("new network_ntprefresh = %d\n", pmsg->network_ntprefresh); dprintf("new network_ntprefresh = %d\n", pmsg->network_ntprefresh);
pthread_mutex_lock(&timeThreadSleepMutex); time_wakeup = true;
ntprefresh = pmsg->network_ntprefresh;
if (timeset) {
// wake up time thread
pthread_cond_broadcast(&timeThreadSleepCond);
}
pthread_mutex_unlock(&timeThreadSleepMutex);
} }
if (ntpenable ^ (pmsg->network_ntpenable == 1)) { if (ntpenable ^ (pmsg->network_ntpenable == 1)) {
dprintf("new network_ntpenable = %d\n", pmsg->network_ntpenable); dprintf("new network_ntpenable = %d\n", pmsg->network_ntpenable);
time_wakeup = true;
}
if(time_wakeup) {
pthread_mutex_lock(&timeThreadSleepMutex); pthread_mutex_lock(&timeThreadSleepMutex);
ntpserver = (std::string)&data[sizeof(struct sectionsd::commandSetConfig)];
dprintf("new network_ntpserver = %s\n", ntpserver.c_str());
ntp_system_cmd = ntp_system_cmd_prefix + ntpserver;
ntprefresh = pmsg->network_ntprefresh;
ntpenable = (pmsg->network_ntpenable == 1); ntpenable = (pmsg->network_ntpenable == 1);
if (timeset) { if (timeset) {
// wake up time thread // wake up time thread
@@ -1204,30 +1184,17 @@ static void commandSetConfig(int connfd, char *data, const unsigned /*dataLength
pthread_mutex_unlock(&timeThreadSleepMutex); pthread_mutex_unlock(&timeThreadSleepMutex);
} }
if (ntpserver.compare((std::string)&data[sizeof(struct sectionsd::commandSetConfig)])) { epg_dir= (std::string)&data[sizeof(struct sectionsd::commandSetConfig) + strlen(&data[sizeof(struct sectionsd::commandSetConfig)]) + 1];
ntpserver = (std::string)&data[sizeof(struct sectionsd::commandSetConfig)];
dprintf("new network_ntpserver = %s\n", ntpserver.c_str());
ntp_system_cmd = ntp_system_cmd_prefix + ntpserver;
}
if (epg_dir.compare((std::string)&data[sizeof(struct sectionsd::commandSetConfig) + strlen(&data[sizeof(struct sectionsd::commandSetConfig)]) + 1])) {
epg_dir= (std::string)&data[sizeof(struct sectionsd::commandSetConfig) + strlen(&data[sizeof(struct sectionsd::commandSetConfig)]) + 1];
dprintf("new epg_dir = %s\n", epg_dir.c_str());
}
responseHeader.dataLength = 0;
writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS);
return ;
} }
static void deleteSIexceptEPG() static void deleteSIexceptEPG()
{ {
writeLockServices();
mySIservicesOrderUniqueKey.clear();
unlockServices();
threadEIT.dropCachedSectionIDs(); threadEIT.dropCachedSectionIDs();
threadEIT.change(0); threadEIT.change(0);
#ifdef ENABLE_SDT #ifdef ENABLE_SDT
writeLockServices();
mySIservicesOrderUniqueKey.clear();
unlockServices();
threadSDT.dropCachedSectionIDs(); threadSDT.dropCachedSectionIDs();
threadSDT.change(0); threadSDT.change(0);
#endif #endif
@@ -1239,13 +1206,15 @@ static void deleteSIexceptEPG()
static void commandFreeMemory(int connfd, char * /*data*/, const unsigned /*dataLength*/) static void commandFreeMemory(int connfd, char * /*data*/, const unsigned /*dataLength*/)
{ {
sendEmptyResponse(connfd, NULL, 0);
deleteSIexceptEPG(); deleteSIexceptEPG();
writeLockEvents(); writeLockEvents();
#ifndef USE_BOOST_SHARED_PTR #ifndef USE_BOOST_SHARED_PTR
std::set<SIeventPtr> allevents; std::set<SIeventPtr> allevents;
allevents.insert(mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(), mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()); allevents.insert(mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(), mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end());
/* this probably not needed, but takes only additional ~2 seconds /* this probably not needed, but takes only additional ~2 seconds
* with even count > 70000 */ * with even count > 70000 */
@@ -1258,7 +1227,6 @@ static void commandFreeMemory(int connfd, char * /*data*/, const unsigned /*data
for(std::set<SIeventPtr>::iterator ait = allevents.begin(); ait != allevents.end(); ++ait) for(std::set<SIeventPtr>::iterator ait = allevents.begin(); ait != allevents.end(); ++ait)
delete (*ait); delete (*ait);
#endif #endif
mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.clear(); mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.clear();
mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.clear(); mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.clear();
@@ -1272,17 +1240,14 @@ static void commandFreeMemory(int connfd, char * /*data*/, const unsigned /*data
printf("total size of memory occupied by chunks handed out by malloc: %d\n" printf("total size of memory occupied by chunks handed out by malloc: %d\n"
"total bytes memory allocated with `sbrk' by malloc, in bytes: %d (%dkB)\n", "total bytes memory allocated with `sbrk' by malloc, in bytes: %d (%dkB)\n",
meminfo.uordblks, meminfo.arena, meminfo.arena / 1024); meminfo.uordblks, meminfo.arena, meminfo.arena / 1024);
struct sectionsd::msgResponseHeader responseHeader;
responseHeader.dataLength = 0;
writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS);
return ;
} }
static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLength) static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLength)
{ {
pthread_t thrInsert; pthread_t thrInsert;
sendEmptyResponse(connfd, NULL, 0);
if (dataLength > 100) if (dataLength > 100)
return ; return ;
@@ -1291,9 +1256,6 @@ static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLeng
epg_dir = (std::string)data + "/"; epg_dir = (std::string)data + "/";
unlockMessaging(); unlockMessaging();
struct sectionsd::msgResponseHeader responseHeader;
responseHeader.dataLength = 0;
writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS);
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);
@@ -1305,17 +1267,13 @@ static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLeng
} }
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
return ;
} }
static void commandWriteSI2XML(int connfd, char *data, const unsigned dataLength) static void commandWriteSI2XML(int connfd, char *data, const unsigned dataLength)
{ {
char epgdir[100] = ""; char epgdir[100] = "";
struct sectionsd::msgResponseHeader responseHeader; sendEmptyResponse(connfd, NULL, 0);
responseHeader.dataLength = 0;
writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS);
if (dataLength > 100) if (dataLength > 100)
return; return;
@@ -1326,24 +1284,6 @@ static void commandWriteSI2XML(int connfd, char *data, const unsigned dataLength
writeEventsToFile(epgdir); writeEventsToFile(epgdir);
eventServer->sendEvent(CSectionsdClient::EVT_WRITE_SI_FINISHED, CEventServer::INITID_SECTIONSD); eventServer->sendEvent(CSectionsdClient::EVT_WRITE_SI_FINISHED, CEventServer::INITID_SECTIONSD);
return;
}
#if 0
/* dummy1: do not send back anything */
static void commandDummy1(int, char *, const unsigned)
{
return;
}
#endif
/* dummy2: send back an empty response */
static void commandDummy2(int connfd, char *, const unsigned)
{
struct sectionsd::msgResponseHeader msgResponse;
msgResponse.dataLength = 0;
writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS);
return;
} }
struct s_cmd_table struct s_cmd_table
@@ -1354,24 +1294,24 @@ struct s_cmd_table
static s_cmd_table connectionCommands[sectionsd::numberOfCommands] = { static s_cmd_table connectionCommands[sectionsd::numberOfCommands] = {
{ commandDumpStatusInformation, "commandDumpStatusInformation" }, { commandDumpStatusInformation, "commandDumpStatusInformation" },
{ commandDummy2, "commandAllEventsChannelIDSearch" }, { sendEmptyResponse, "commandAllEventsChannelIDSearch" },
{ commandPauseScanning, "commandPauseScanning" }, { commandPauseScanning, "commandPauseScanning" },
{ commandGetIsScanningActive, "commandGetIsScanningActive" }, { commandGetIsScanningActive, "commandGetIsScanningActive" },
{ commandDummy2, "commandActualEPGchannelID" }, { sendEmptyResponse, "commandActualEPGchannelID" },
{ commandDummy2, "commandEventListTVids" }, { sendEmptyResponse, "commandEventListTVids" },
{ commandDummy2, "commandEventListRadioIDs" }, { sendEmptyResponse, "commandEventListRadioIDs" },
{ commandDummy2, "commandCurrentNextInfoChannelID" }, { sendEmptyResponse, "commandCurrentNextInfoChannelID" },
{ commandDummy2, "commandEPGepgID" }, { sendEmptyResponse, "commandEPGepgID" },
{ commandDummy2, "commandEPGepgIDshort" }, { sendEmptyResponse, "commandEPGepgIDshort" },
{ commandDummy2, "commandComponentTagsUniqueKey" }, { sendEmptyResponse, "commandComponentTagsUniqueKey" },
{ commandDummy2, "commandAllEventsChannelID" }, { sendEmptyResponse, "commandAllEventsChannelID" },
{ commandDummy2, "commandTimesNVODservice" }, { sendEmptyResponse, "commandTimesNVODservice" },
{ commandGetIsTimeSet, "commandGetIsTimeSet" }, { commandGetIsTimeSet, "commandGetIsTimeSet" },
{ commandserviceChanged, "commandserviceChanged" }, { commandserviceChanged, "commandserviceChanged" },
{ commandDummy2, "commandLinkageDescriptorsUniqueKey" }, { sendEmptyResponse, "commandLinkageDescriptorsUniqueKey" },
{ commandRegisterEventClient, "commandRegisterEventClient" }, { commandRegisterEventClient, "commandRegisterEventClient" },
{ commandUnRegisterEventClient, "commandUnRegisterEventClient" }, { commandUnRegisterEventClient, "commandUnRegisterEventClient" },
{ commandDummy2, "commandSetPrivatePid" }, { sendEmptyResponse, "commandSetPrivatePid" },
{ commandFreeMemory, "commandFreeMemory" }, { commandFreeMemory, "commandFreeMemory" },
{ commandReadSIfromXML, "commandReadSIfromXML" }, { commandReadSIfromXML, "commandReadSIfromXML" },
{ commandWriteSI2XML, "commandWriteSI2XML" }, { commandWriteSI2XML, "commandWriteSI2XML" },
@@ -1410,7 +1350,7 @@ bool sectionsd_parse_command(CBasicMessage::Header &rmsg, int connfd)
if (rc == true) if (rc == true)
{ {
dprintf("%s\n", connectionCommands[header.command].sCmd.c_str()); dprintf("%s\n", connectionCommands[header.command].sCmd.c_str());
if(connectionCommands[header.command].cmd == commandDummy2) if(connectionCommands[header.command].cmd == sendEmptyResponse)
printf("sectionsd_parse_command: UNUSED cmd used: %d (%s)\n", header.command, connectionCommands[header.command].sCmd.c_str()); printf("sectionsd_parse_command: UNUSED cmd used: %d (%s)\n", header.command, connectionCommands[header.command].sCmd.c_str());
connectionCommands[header.command].cmd(connfd, data, header.dataLength); connectionCommands[header.command].cmd(connfd, data, header.dataLength);
} }
@@ -1438,6 +1378,21 @@ static void dump_sched_info(std::string label)
// updates system time according TOT every 30 minutes // updates system time according TOT every 30 minutes
//--------------------------------------------------------------------- //---------------------------------------------------------------------
static void sendTimeEvent(bool by_ntp, time_t tim = 0)
{
time_t actTime = time(NULL);
if(!by_ntp) {
struct tm *tmTime = localtime(&actTime);
xprintf("[%sThread] - current: %02d.%02d.%04d %02d:%02d:%02d, dvb: %s", "time",
tmTime->tm_mday, tmTime->tm_mon+1, tmTime->tm_year+1900, tmTime->tm_hour, tmTime->tm_min, tmTime->tm_sec, ctime(&tim));
}
pthread_mutex_lock(&timeIsSetMutex);
timeset = true;
pthread_cond_broadcast(&timeIsSetCond);
pthread_mutex_unlock(&timeIsSetMutex );
eventServer->sendEvent(CSectionsdClient::EVT_TIMESET, CEventServer::INITID_SECTIONSD, &actTime, sizeof(actTime) );
}
static void *timeThread(void *) static void *timeThread(void *)
{ {
UTC_t UTC; UTC_t UTC;
@@ -1449,10 +1404,6 @@ static void *timeThread(void *)
bool time_ntp = false; bool time_ntp = false;
bool success = true; bool success = true;
//t_channel_id time_trigger_last = 0;
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
dprintf("[%sThread] pid %d (%lu) start\n", "time", getpid(), pthread_self()); dprintf("[%sThread] pid %d (%lu) start\n", "time", getpid(), pthread_self());
while(!sectionsd_stop) while(!sectionsd_stop)
@@ -1462,38 +1413,12 @@ static void *timeThread(void *)
break; break;
sleep(1); sleep(1);
} }
#if 0
t_channel_id new_transponder = (messaging_current_servicekey & 0xFFFFFFFF0000ULL);
if (time_trigger_last != new_transponder)
{
time_trigger_last = new_transponder;
}
#endif
if (bTimeCorrect == true) { // sectionsd started with parameter "-tc"
if (first_time == true) { // only do this once!
time_t actTime;
actTime=time(NULL);
pthread_mutex_lock(&timeIsSetMutex);
timeset = true;
pthread_cond_broadcast(&timeIsSetCond);
pthread_mutex_unlock(&timeIsSetMutex );
eventServer->sendEvent(CSectionsdClient::EVT_TIMESET, CEventServer::INITID_SECTIONSD, &actTime, sizeof(actTime) );
printf("[timeThread] Time is already set by system, no further timeThread work!\n");
break;
}
}
else if ( ntpenable && system( ntp_system_cmd.c_str() ) == 0) if ( ntpenable && system( ntp_system_cmd.c_str() ) == 0)
{ {
time_t actTime;
actTime = time(NULL);
first_time = false; first_time = false;
pthread_mutex_lock(&timeIsSetMutex);
timeset = true;
time_ntp = true; time_ntp = true;
pthread_cond_broadcast(&timeIsSetCond); sendTimeEvent(true);
pthread_mutex_unlock(&timeIsSetMutex );
eventServer->sendEvent(CSectionsdClient::EVT_TIMESET, CEventServer::INITID_SECTIONSD, &actTime, sizeof(actTime) );
} else { } else {
if (dvb_time_update) { if (dvb_time_update) {
xprintf("timeThread: getting UTC\n"); xprintf("timeThread: getting UTC\n");
@@ -1502,6 +1427,8 @@ xprintf("timeThread: getting UTC done : %d\n", success);
if (success) if (success)
{ {
tim = changeUTCtoCtime((const unsigned char *) &UTC); tim = changeUTCtoCtime((const unsigned char *) &UTC);
time_ntp = false;
sendTimeEvent(false, tim);
if (tim) { if (tim) {
if ((!messaging_neutrino_sets_time) && (geteuid() == 0)) { if ((!messaging_neutrino_sets_time) && (geteuid() == 0)) {
@@ -1514,18 +1441,6 @@ xprintf("timeThread: getting UTC done : %d\n", success);
} }
} }
} }
time_t actTime;
struct tm *tmTime;
actTime = time(NULL);
tmTime = localtime(&actTime);
xprintf("[%sThread] - %02d.%02d.%04d %02d:%02d:%02d, tim: %s", "time", tmTime->tm_mday, tmTime->tm_mon+1, tmTime->tm_year+1900, tmTime->tm_hour, tmTime->tm_min, tmTime->tm_sec, ctime(&tim));
pthread_mutex_lock(&timeIsSetMutex);
timeset = true;
time_ntp = false;
pthread_cond_broadcast(&timeIsSetCond);
pthread_mutex_unlock(&timeIsSetMutex );
eventServer->sendEvent(CSectionsdClient::EVT_TIMESET, CEventServer::INITID_SECTIONSD, &tim, sizeof(tim));
} }
} }
} }
@@ -1569,6 +1484,7 @@ xprintf("timeThread: going to sleep for %d sec\n\n", seconds);
restartWait.tv_sec += seconds; restartWait.tv_sec += seconds;
pthread_mutex_lock( &timeThreadSleepMutex ); pthread_mutex_lock( &timeThreadSleepMutex );
int ret = pthread_cond_timedwait( &timeThreadSleepCond, &timeThreadSleepMutex, &restartWait ); int ret = pthread_cond_timedwait( &timeThreadSleepCond, &timeThreadSleepMutex, &restartWait );
pthread_mutex_unlock( &timeThreadSleepMutex );
if (ret == ETIMEDOUT) if (ret == ETIMEDOUT)
{ {
dprintf("TDT-Thread sleeping is over - no signal received\n"); dprintf("TDT-Thread sleeping is over - no signal received\n");
@@ -1577,8 +1493,6 @@ xprintf("timeThread: going to sleep for %d sec\n\n", seconds);
{ {
dprintf("TDT-Thread sleeping interrupted\n"); dprintf("TDT-Thread sleeping interrupted\n");
} }
// else if (ret == 0) //everything is fine :) e.g. timeThreadSleepCond maybe signalled @zap time to get a valid time
pthread_mutex_unlock( &timeThreadSleepMutex );
} }
printf("[sectionsd] timeThread ended\n"); printf("[sectionsd] timeThread ended\n");
@@ -1622,19 +1536,12 @@ int eit_set_update_filter(int *fd)
mask[2] = 0xFF; mask[2] = 0xFF;
int timeout = 0; int timeout = 0;
#if 1 //!HAVE_COOL_HARDWARE
filter[3] = (cur_eit << 1) | 0x01; filter[3] = (cur_eit << 1) | 0x01;
mask[3] = (0x1F << 1) | 0x01; mask[3] = (0x1F << 1) | 0x01;
mode[3] = 0x1F << 1; mode[3] = 0x1F << 1;
eitDmx->sectionFilter(0x12, filter, mask, 4, timeout, mode); eitDmx->sectionFilter(0x12, filter, mask, 4, timeout, mode);
#else
/* coolstream drivers broken? */
filter[3] = (((cur_eit + 1) & 0x01) << 1) | 0x01;
mask[3] = (0x01 << 1) | 0x01;
eitDmx->sectionFilter(0x12, filter, mask, 4, timeout, NULL);
#endif
//printf("[sectionsd] start EIT update filter: current version %02X, filter %02X %02X %02X %02X, mask %02X mode %02X \n", cur_eit, dsfp.filter.filter[0], dsfp.filter.filter[1], dsfp.filter.filter[2], dsfp.filter.filter[3], dsfp.filter.mask[3], dsfp.filter.mode[3]);
*fd = 1; *fd = 1;
return 0; return 0;
} }
@@ -1939,6 +1846,13 @@ void CEitThread::run()
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// CN-thread: eit thread, but only current/next // CN-thread: eit thread, but only current/next
//--------------------------------------------------------------------- //---------------------------------------------------------------------
void CCNThread::sendCNEvent()
{
eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG,
CEventServer::INITID_SECTIONSD,
&messaging_current_servicekey,
sizeof(messaging_current_servicekey));
}
void CCNThread::run() void CCNThread::run()
{ {
@@ -1948,42 +1862,24 @@ void CCNThread::run()
dmx_num = 1; dmx_num = 1;
cache = false; cache = false;
/* we are holding the start_stop lock during this timeout, so don't
make it too long... */
timeoutInMSeconds = EIT_READ_TIMEOUT; timeoutInMSeconds = EIT_READ_TIMEOUT;
bool sendToSleepNow = false; bool sendToSleepNow = false;
// -- set EIT filter 0x4e // -- set EIT filter 0x4e
addfilter(0x4e, 0xff); //0 current TS, current/next addfilter(0x4e, 0xff); //0 current TS, current/next
//t_channel_id time_trigger_last = 0;
writeLockMessaging();
messaging_eit_is_busy = true;
messaging_need_eit_version = false;
unlockMessaging();
waitForTimeset(); waitForTimeset();
#ifdef DEBUG_CN_THREAD #ifdef DEBUG_CN_THREAD
xprintf("CCNThread::run:: time set..\n"); xprintf("CCNThread::run:: time set..\n");
#endif #endif
DMX::start(); // -> unlock DMX::start(); // -> unlock
//time_t eit_waiting_since = time_monotonic();
while(running) while(running)
{ {
if(sendToSleepNow || !scanning || channel_is_blacklisted) { if(sendToSleepNow || !scanning || channel_is_blacklisted) {
#ifdef DEBUG_CN_THREAD #ifdef DEBUG_CN_THREAD
xprintf("%s: going to sleep, running %d scanning %d blacklisted %d events %d\n", name.c_str(), running, scanning, channel_is_blacklisted, event_count); xprintf("%s: going to sleep, running %d scanning %d blacklisted %d events %d\n", name.c_str(), running, scanning, channel_is_blacklisted, event_count);
//xprintf("%s: eit_version %02x messaging_need_eit_version %d rc %d\n", name.c_str(), get_eit_version(), messaging_need_eit_version, rc);
#endif #endif
writeLockMessaging();
messaging_eit_is_busy = false;
unlockMessaging();
int rs = 0; int rs = 0;
do { do {
real_pause(); real_pause();
@@ -2002,12 +1898,6 @@ void CCNThread::run()
break; break;
sendToSleepNow = false; sendToSleepNow = false;
writeLockMessaging();
messaging_need_eit_version = false;
messaging_eit_is_busy = true;
unlockMessaging();
#if HAVE_IPBOX_HARDWARE #if HAVE_IPBOX_HARDWARE
if (rs == 0) if (rs == 0)
change(0); change(0);
@@ -2019,41 +1909,6 @@ void CCNThread::run()
addEvents(); addEvents();
time_t zeit = time_monotonic(); time_t zeit = time_monotonic();
if (update_eit) {
#if 0
xprintf("%s: eit_version %02x messaging_need_eit_version %d rc %d\n", name.c_str(), get_eit_version(), messaging_need_eit_version, rc);
if (get_eit_version() != 0xff) {
writeLockMessaging();
messaging_need_eit_version = false;
unlockMessaging();
} else {
readLockMessaging();
if (!messaging_need_eit_version) {
unlockMessaging();
dprintf("waiting for eit_version...\n");
zeit = time_monotonic(); /* reset so that we don't get negative */
eit_waiting_since = zeit; /* and still compensate for getSection */
lastChanged = zeit; /* this is ugly - needs somehting better */
sendToSleepNow = false; /* reset after channel change */
writeLockMessaging();
messaging_need_eit_version = true;
}
unlockMessaging();
if (zeit - eit_waiting_since > TIME_EIT_VERSION_WAIT) {
dprintf("waiting for more than %d seconds - bail out...\n", TIME_EIT_VERSION_WAIT);
/* send event anyway, so that we know there is no EPG */
eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG,
CEventServer::INITID_SECTIONSD,
&messaging_current_servicekey,
sizeof(messaging_current_servicekey));
writeLockMessaging();
messaging_need_eit_version = false;
unlockMessaging();
sendToSleepNow = true;
}
}
#endif
} // if (update_eit)
readLockMessaging(); readLockMessaging();
if (messaging_got_CN != messaging_have_CN) if (messaging_got_CN != messaging_have_CN)
@@ -2067,31 +1922,12 @@ void CCNThread::run()
name.c_str(), timeoutsDMX, messaging_have_CN, messaging_got_CN); name.c_str(), timeoutsDMX, messaging_have_CN, messaging_got_CN);
#endif #endif
dprintf("[cnThread] got current_next (0x%x) - sending event!\n", messaging_have_CN); dprintf("[cnThread] got current_next (0x%x) - sending event!\n", messaging_have_CN);
eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG, sendCNEvent();
CEventServer::INITID_SECTIONSD,
&messaging_current_servicekey,
sizeof(messaging_current_servicekey));
/* we received an event => reset timeout timer... */
//eit_waiting_since = zeit;
lastChanged = zeit; /* this is ugly - needs somehting better */ lastChanged = zeit; /* this is ugly - needs somehting better */
//readLockMessaging();
} }
else else
unlockMessaging(); unlockMessaging();
#if 0
if (messaging_have_CN == 0x03) // current + next
{
xprintf("%s: have all CN: timeoutsDMX %d messaging_have_CN %x messaging_got_CN %x\n\n",
name.c_str(), timeoutsDMX, messaging_have_CN, messaging_got_CN);
unlockMessaging();
//sendToSleepNow = true;
//timeoutsDMX = 0;
}
else {
unlockMessaging();
}
#endif
#if 1
if(timeoutsDMX < 0) { if(timeoutsDMX < 0) {
#ifdef DEBUG_CN_THREAD #ifdef DEBUG_CN_THREAD
xprintf("%s: timeoutsDMX %d messaging_got_CN %x messaging_have_CN %x sid %016llx\n\n", xprintf("%s: timeoutsDMX %d messaging_got_CN %x messaging_have_CN %x sid %016llx\n\n",
@@ -2100,7 +1936,6 @@ void CCNThread::run()
timeoutsDMX = 0; timeoutsDMX = 0;
sendToSleepNow = true; sendToSleepNow = true;
} }
#endif
if (zeit > lastChanged + TIME_EIT_VERSION_WAIT) { if (zeit > lastChanged + TIME_EIT_VERSION_WAIT) {
#ifdef DEBUG_CN_THREAD #ifdef DEBUG_CN_THREAD
xprintf("%s: zeit > lastChanged + TIME_EIT_VERSION_WAIT\n", name.c_str()); xprintf("%s: zeit > lastChanged + TIME_EIT_VERSION_WAIT\n", name.c_str());
@@ -2110,95 +1945,8 @@ void CCNThread::run()
if (sendToSleepNow && messaging_have_CN == 0x00) { if (sendToSleepNow && messaging_have_CN == 0x00) {
/* send a "no epg" event anyway before going to sleep */ /* send a "no epg" event anyway before going to sleep */
eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG, sendCNEvent();
CEventServer::INITID_SECTIONSD,
&messaging_current_servicekey,
sizeof(messaging_current_servicekey));
} }
#if 0
/* ignore sleep if channel not blacklisted and messaging_need_eit_version == false */
if(!channel_is_blacklisted && messaging_need_eit_version) {
xprintf("%s: sendToSleepNow ignored: messaging_need_eit_version %d\n", name.c_str(), messaging_need_eit_version);
sendToSleepNow = false;
}
#endif
#if 0
/* sleep if channel blacklisted OR sleep requested and messaging_need_eit_version == false */
if ((sendToSleepNow && !messaging_need_eit_version) || channel_is_blacklisted)
{
sendToSleepNow = false;
real_pause();
dprintf("dmxCN: going to sleep...\n");
writeLockMessaging();
messaging_eit_is_busy = false;
unlockMessaging();
/* re-fetch time if transponder changed
Why I'm doing this here and not from commandserviceChanged?
commandserviceChanged is called on zap *start*, not after zap finished
this would lead to often actually fetching the time on the transponder
you are switching away from, not the one you are switching onto.
Doing it here at least gives us a good chance to have actually tuned
to the channel we want to get the time from...
*/
if (time_trigger_last != (messaging_current_servicekey & 0xFFFFFFFF0000ULL))
{
time_trigger_last = messaging_current_servicekey & 0xFFFFFFFF0000ULL;
pthread_mutex_lock(&timeThreadSleepMutex);
pthread_cond_broadcast(&timeThreadSleepCond);
pthread_mutex_unlock(&timeThreadSleepMutex);
}
xprintf("dmxCN: going to sleep, processed %d events\n\n", event_count);
event_count = 0;
int rs;
do {
pthread_mutex_lock( &start_stop_mutex );
if (!channel_is_blacklisted)
eit_set_update_filter(&eit_update_fd);
rs = pthread_cond_wait(&change_cond, &start_stop_mutex);
eit_stop_update_filter(&eit_update_fd);
pthread_mutex_unlock(&start_stop_mutex);
} while (channel_is_blacklisted);
writeLockMessaging();
messaging_need_eit_version = false;
messaging_eit_is_busy = true;
unlockMessaging();
if (rs == 0)
{
dprintf("dmxCN: waking up again - requested from .change()\n");
// fix EPG problems on IPBox
// http://tuxbox-forum.dreambox-fan.de/forum/viewtopic.php?p=367937#p367937
#if HAVE_IPBOX_HARDWARE
change(0);
#endif
}
else
{
printf("dmxCN: waking up again - unknown reason %d\n",rs);
real_unpause();
}
zeit = time_monotonic();
}
else if (zeit > lastChanged + TIME_EIT_VERSION_WAIT && !messaging_need_eit_version)
{
xprintf("zeit > lastChanged + TIME_EIT_VERSION_WAIT\n");
sendToSleepNow = true;
/* we can get here if we got the EIT version but no events */
/* send a "no epg" event anyway before going to sleep */
if (messaging_have_CN == 0x00)
eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG,
CEventServer::INITID_SECTIONSD,
&messaging_current_servicekey,
sizeof(messaging_current_servicekey));
continue;
}
#endif
} // for } // for
delete[] static_buf; delete[] static_buf;
printf("[sectionsd] %s ended\n", name.c_str()); printf("[sectionsd] %s ended\n", name.c_str());
@@ -2582,7 +2330,6 @@ printf("SIevent size: %d\n", sizeof(SIevent));
writeLockMessaging(); writeLockMessaging();
messaging_have_CN = 0x00; messaging_have_CN = 0x00;
messaging_got_CN = 0x00; messaging_got_CN = 0x00;
messaging_last_requested = time_monotonic();
unlockMessaging(); unlockMessaging();
sched_yield(); sched_yield();
@@ -2768,7 +2515,7 @@ void sectionsd_getCurrentNextServiceKey(t_channel_id uniqueServiceKey, CSections
SIevent nextEvt; SIevent nextEvt;
unsigned flag = 0, flag2=0; unsigned flag = 0, flag2=0;
/* ugly hack: retry fetching current/next by restarting dmxCN if this is true */ /* ugly hack: retry fetching current/next by restarting dmxCN if this is true */
bool change = false; bool change = false;//TODO remove ?
//t_channel_id * uniqueServiceKey = (t_channel_id *)data; //t_channel_id * uniqueServiceKey = (t_channel_id *)data;
@@ -2940,14 +2687,8 @@ void sectionsd_getCurrentNextServiceKey(t_channel_id uniqueServiceKey, CSections
current_next.current_fsk = currentEvt.getFSK(); current_next.current_fsk = currentEvt.getFSK();
unlockEvents(); unlockEvents();
xprintf("change: %s, messaging_eit_busy: %s, last_request: %d\n", change?"true":"false", messaging_eit_is_busy?"true":"false",(int) (time_monotonic() - messaging_last_requested));
if (change && !messaging_eit_is_busy && (time_monotonic() - messaging_last_requested) < 11) {
/* restart dmxCN, but only if it is not already running, and only for 10 seconds */
xprintf("change && !messaging_eit_is_busy => dmxCN.change(0)\n");
threadCN.change(0);
}
} }
/* commandEPGepgIDshort */ /* commandEPGepgIDshort */
bool sectionsd_getEPGidShort(event_id_t epgID, CShortEPGData * epgdata) bool sectionsd_getEPGidShort(event_id_t epgID, CShortEPGData * epgdata)
{ {