Improve transport status notification changes.

Also let, serviceprobe use the transport built-in timeout facilities.
This commit is contained in:
Andreas Öman 2008-05-04 18:32:46 +00:00
parent 546dd71627
commit 5a5e4854ca
9 changed files with 106 additions and 59 deletions

View file

@ -125,13 +125,14 @@ ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq,
(const char *[]){"", "Last status", "Crypto",
"Type", "Source service",
"", "Target channel", "", NULL},
(int[]){3,6,4,4,12,3,12,1});
(int[]){3,8,4,4,12,3,12,1});
LIST_FOREACH(t, tlist, tht_tmp_link) {
ajax_table_row_start(&ta, t->tht_identifier);
ajax_table_cell_detail_toggler(&ta);
ajax_table_cell(&ta, "status", transport_status_to_text(t->tht_status));
ajax_table_cell(&ta, "status",
transport_status_to_text(t->tht_last_status));
ajax_table_cell(&ta, NULL, "%s", t->tht_scrambled ? "Yes" : "No");
ajax_table_cell(&ta, NULL, "%s", transport_servicetype_txt(t));
ajax_table_cell(&ta, NULL, "%s", t->tht_svcname ?: "");

View file

@ -477,3 +477,11 @@ ajax_mailbox_xmltv_grabber_status_change(xmltv_grabber_t *xg)
}
void
ajax_mailbox_transport_status_change(struct th_transport *t)
{
ajax_mailbox_update_div("xmltvgrabbers",
"status", t->tht_identifier,
transport_status_to_text(t->tht_last_status));
}

View file

@ -39,4 +39,7 @@ struct xmltv_grabber;
void ajax_mailbox_xmltv_grabber_status_change(struct xmltv_grabber *xg);
struct th_transport;
void ajax_mailbox_transport_status_change(struct th_transport *t);
#endif /* AJAXUI_MAILBOX_H_ */

View file

@ -73,3 +73,15 @@ notify_xmltv_grabber_status_change(struct xmltv_grabber *xg)
{
ajax_mailbox_xmltv_grabber_status_change(xg);
}
void
notify_transprot_status_change(struct th_transport *t)
{
th_subscription_t *s;
LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link)
if(s->ths_status_callback != NULL)
s->ths_status_callback(s, t->tht_last_status, s->ths_opaque);
ajax_mailbox_transport_status_change(t);
}

View file

@ -37,4 +37,7 @@ void notify_tda_change(struct th_dvb_adapter *tda);
void notify_xmltv_grabber_status_change(struct xmltv_grabber *xg);
struct th_transport;
void notify_transprot_status_change(struct th_transport *t);
#endif /* NOTIFY_H_ */

View file

@ -31,6 +31,7 @@
#include "bitstream.h"
#include "buffer.h"
#include "dispatch.h"
#include "transports.h"
static const AVRational mpeg_tc = {1, 90000};
@ -821,6 +822,17 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock);
/**
* We've got something, disarm the transport timeout timer
*/
dtimer_disarm(&t->tht_receive_timer);
/**
* Input is ok
*/
transport_signal_status(t, TRANSPORT_STATUS_OK);
/* Alert all muxers tied to us that a new packet has arrived.
Muxers may remove themself as a direct action of receiving a packet
(serviceprober), so we need to traverse in a safe manner */

View file

@ -43,22 +43,19 @@ static void serviceprobe_engage(void);
struct th_transport_queue probequeue;
typedef struct sp {
dtimer_t sp_timer;
th_muxer_t *sp_muxer;
th_subscription_t *sp_s;
const char *sp_error;
dtimer_t sp_timer;
} sp_t;
static void
sp_done(sp_t *sp)
sp_done_callback(void *aux, int64_t now)
{
sp_t *sp = aux;
th_subscription_t *s = sp->sp_s;
th_transport_t *t = sp->sp_s->ths_transport;
dtimer_disarm(&sp->sp_timer);
muxer_deinit(sp->sp_muxer, s);
LIST_REMOVE(s, ths_transport_link);
@ -75,43 +72,25 @@ sp_done(sp_t *sp)
free(sp);
}
/**
*
* Got a packet, map it
*/
static void
sp_timeout(void *aux, int64_t now)
{
sp_t *sp = aux;
th_transport_t *t = sp->sp_s->ths_transport;
channel_t *ch;
syslog(LOG_INFO, "Probed \"%s\" -- %s\n", t->tht_svcname,
sp->sp_error ?: "Ok");
if(sp->sp_error == NULL) {
if(t->tht_ch == NULL && t->tht_svcname != NULL) {
ch = channel_find(t->tht_svcname, 1, NULL);
transport_map_channel(t, ch);
t->tht_config_change(t);
}
}
sp_done(sp);
}
static void
sp_packet_input(void *opaque, th_muxstream_t *tms, th_pkt_t *pkt)
{
sp_t *sp = opaque;
th_transport_t *t = sp->sp_s->ths_transport;
channel_t *ch;
if(tms->tms_stream->st_type == HTSTV_MPEG2VIDEO ||
tms->tms_stream->st_type == HTSTV_H264) {
sp->sp_error = NULL;
dtimer_arm(&sp->sp_timer, sp_timeout, sp, 0);
syslog(LOG_INFO, "Probed \"%s\" -- Ok\n", t->tht_svcname);
if(t->tht_ch == NULL && t->tht_svcname != NULL) {
ch = channel_find(t->tht_svcname, 1, NULL);
transport_map_channel(t, ch);
t->tht_config_change(t);
}
dtimer_arm(&sp->sp_timer, sp_done_callback, sp, 0);
}
/**
@ -121,22 +100,30 @@ static void
sp_status_callback(struct th_subscription *s, int status, void *opaque)
{
sp_t *sp = opaque;
th_transport_t *t = sp->sp_s->ths_transport;
char *errtxt;
s->ths_status_callback = NULL;
switch(status) {
case TRANSPORT_STATUS_OK:
return;
case TRANSPORT_STATUS_NO_DESCRAMBLER:
sp->sp_error = "No descrambler for stream";
errtxt = "No descrambler for stream";
break;
case TRANSPORT_STATUS_NO_ACCESS:
sp->sp_error = "Access denied";
errtxt = "Access denied";
break;
case TRANSPORT_STATUS_NO_INPUT:
errtxt = "No input detected";
break;
default:
sp->sp_error = "Other error";
errtxt = "Other error";
break;
}
dtimer_arm(&sp->sp_timer, sp_timeout, sp, 0);
syslog(LOG_INFO, "Probed \"%s\" -- %s\n", t->tht_svcname, errtxt);
dtimer_arm(&sp->sp_timer, sp_done_callback, sp, 0);
}
@ -158,7 +145,6 @@ serviceprobe_engage(void)
sp = calloc(1, sizeof(sp_t));
sp->sp_s = s = calloc(1, sizeof(th_subscription_t));
sp->sp_error = "Timeout";
s->ths_title = "probe";
s->ths_weight = INT32_MAX;
s->ths_opaque = sp;
@ -173,15 +159,8 @@ serviceprobe_engage(void)
muxer_play(tm, AV_NOPTS_VALUE);
s->ths_status_callback = sp_status_callback;
dtimer_arm(&sp->sp_timer, sp_timeout, sp, 4);
}
/**
*
*/

View file

@ -52,11 +52,13 @@
#include "buffer.h"
#include "channels.h"
#include "cwc.h"
#include "notify.h"
#define TRANSPORT_HASH_WIDTH 101
static struct th_transport_list transporthash[TRANSPORT_HASH_WIDTH];
static void transport_data_timeout(void *aux, int64_t now);
//static dtimer_t transport_monitor_timer;
@ -79,6 +81,8 @@ transport_stop(th_transport_t *t, int flush_subscriptions)
return;
}
dtimer_disarm(&t->tht_receive_timer);
// dtimer_disarm(&transport_monitor_timer, transport_monitor, t, 1);
t->tht_stop_feed(t);
@ -204,6 +208,8 @@ transport_start(th_transport_t *t, unsigned int weight)
}
cwc_transport_start(t);
dtimer_arm(&t->tht_receive_timer, transport_data_timeout, t, 4);
transport_signal_status(t, TRANSPORT_STATUS_STARTING);
return 0;
}
@ -423,6 +429,17 @@ transport_monitor(void *aux, int64_t now)
#endif
/**
* Timer that fires if transport is not receiving any data
*/
static void
transport_data_timeout(void *aux, int64_t now)
{
th_transport_t *t = aux;
transport_signal_status(t, TRANSPORT_STATUS_NO_INPUT);
}
/**
* Destroy a transport
*/
@ -431,6 +448,8 @@ transport_destroy(th_transport_t *t)
{
th_stream_t *st;
dtimer_disarm(&t->tht_receive_timer);
free((void *)t->tht_name);
if(t->tht_ch != NULL) {
@ -604,16 +623,20 @@ transport_is_available(th_transport_t *t)
void
transport_signal_status(th_transport_t *t, int newstatus)
{
th_subscription_t *s;
char buf[200];
if(t->tht_last_status != newstatus)
if(t->tht_last_status == newstatus)
return;
t->tht_last_status = newstatus;
snprintf(buf, sizeof(buf), "\"%s\" on %s",
t->tht_chname ?: t->tht_svcname, t->tht_sourcename(t));
LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link)
if(s->ths_status_callback != NULL)
s->ths_status_callback(s, newstatus, s->ths_opaque);
syslog(LOG_INFO, "%s -- Changed status from \"%s\" to \"%s\"",
buf, transport_status_to_text(t->tht_last_status),
transport_status_to_text(newstatus));
t->tht_last_status = newstatus;
notify_transprot_status_change(t);
}
@ -622,7 +645,9 @@ transport_signal_status(th_transport_t *t, int newstatus)
*/
static struct strtab transportstatustab[] = {
{ "Unknown", TRANSPORT_STATUS_UNKNOWN },
{ "Starting", TRANSPORT_STATUS_STARTING },
{ "Ok", TRANSPORT_STATUS_OK },
{ "No input", TRANSPORT_STATUS_NO_INPUT },
{ "No descrambler", TRANSPORT_STATUS_NO_DESCRAMBLER },
{ "No access", TRANSPORT_STATUS_NO_ACCESS },
{ "Mux error", TRANSPORT_STATUS_MUX_ERROR },

View file

@ -516,13 +516,17 @@ typedef struct th_transport {
* Last known status (or error)
*/
dtimer_t tht_receive_timer; /* we use this timer to trig when a transport
does not receive any data at all */
int tht_last_status;
#define TRANSPORT_STATUS_UNKNOWN 0
#define TRANSPORT_STATUS_OK 1
#define TRANSPORT_STATUS_NO_DESCRAMBLER 2
#define TRANSPORT_STATUS_NO_ACCESS 3
#define TRANSPORT_STATUS_MUX_ERROR 4
#define TRANSPORT_STATUS_STARTING 1
#define TRANSPORT_STATUS_OK 2
#define TRANSPORT_STATUS_NO_INPUT 3
#define TRANSPORT_STATUS_NO_DESCRAMBLER 4
#define TRANSPORT_STATUS_NO_ACCESS 5
#define TRANSPORT_STATUS_MUX_ERROR 6
} th_transport_t;