From f60f55651297052cf9498dd74e66a113653e6cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Mon, 12 May 2008 17:27:01 +0000 Subject: [PATCH] Use redblack trees for DVB muxes --- ajaxui/ajaxui_config_dvb.c | 15 +++--- dvb.c | 107 +++++++++++++++++++++++++------------ dvb.h | 2 +- dvb_fe.c | 2 +- dvb_muxconfig.c | 2 +- dvb_support.c | 17 +----- dvb_tables.c | 2 +- tvhead.h | 15 +++--- 8 files changed, 94 insertions(+), 68 deletions(-) diff --git a/ajaxui/ajaxui_config_dvb.c b/ajaxui/ajaxui_config_dvb.c index 0fcfee38..f1a0283d 100644 --- a/ajaxui/ajaxui_config_dvb.c +++ b/ajaxui/ajaxui_config_dvb.c @@ -79,7 +79,7 @@ nicenum(unsigned int v) static void tdmi_displayname(th_dvb_mux_instance_t *tdmi, char *buf, size_t len) { - int f = tdmi->tdmi_fe_params->frequency; + int f = tdmi->tdmi_fe_params.frequency; if(tdmi->tdmi_adapter->tda_type == FE_QPSK) { snprintf(buf, len, "%s kHz %s", nicenum(f), @@ -661,8 +661,7 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr, /* List of muxes */ - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) - nmuxes++; + nmuxes = tda->tda_muxes.entries; if(nmuxes == 0) { tcp_qprintf(tq, "
" @@ -672,7 +671,7 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr, selvector = alloca(sizeof(char *) * (nmuxes + 1)); n = 0; - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) selvector[n++] = tdmi->tdmi_identifier; selvector[n] = NULL; @@ -684,7 +683,7 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr, (int[]) {16,12,7,8,16,8,2}); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { tdmi_displayname(tdmi, buf, sizeof(buf)); @@ -756,8 +755,8 @@ dvbsvccmp(th_transport_t *a, th_transport_t *b) if(a->tht_dvb_mux_instance == b->tht_dvb_mux_instance) return a->tht_dvb_service_id - b->tht_dvb_service_id; - return a->tht_dvb_mux_instance->tdmi_fe_params->frequency - - b->tht_dvb_mux_instance->tdmi_fe_params->frequency; + return a->tht_dvb_mux_instance->tdmi_fe_params.frequency - + b->tht_dvb_mux_instance->tdmi_fe_params.frequency; } /** @@ -818,7 +817,7 @@ ajax_dvbmuxall(http_connection_t *hc, http_reply_t *hr, RB_INIT(&tree); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { LIST_FOREACH(t, &tdmi->tdmi_transports, tht_mux_link) { if(transport_is_available(t)) { RB_INSERT_SORTED(&tree, t, tht_tmp_link, dvbsvccmp); diff --git a/dvb.c b/dvb.c index 9cf93f17..5bd04aa7 100644 --- a/dvb.c +++ b/dvb.c @@ -51,7 +51,7 @@ #include "notify.h" struct th_dvb_adapter_queue dvb_adapters; -struct th_dvb_mux_instance_list dvb_muxes; +struct th_dvb_mux_instance_tree dvb_muxes; static void dvb_mux_scanner(void *aux, int64_t now); static void dvb_fec_monitor(void *aux, int64_t now); @@ -68,7 +68,6 @@ tda_alloc(void) pthread_mutex_init(&tda->tda_lock, NULL); pthread_cond_init(&tda->tda_cond, NULL); TAILQ_INIT(&tda->tda_fe_cmd_queue); - return tda; } @@ -321,11 +320,9 @@ dvb_mux_scanner(void *aux, int64_t now) return; /* someone is here */ /* Check if we have muxes pending for quickscan, if so, choose them */ - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) - if(tdmi->tdmi_quickscan == TDMI_QUICKSCAN_WAITING) - break; - if(tdmi != NULL) { + if((tdmi = RB_FIRST(&tda->tda_muxes_qscan_waiting)) != NULL) { + RB_REMOVE(&tda->tda_muxes_qscan_waiting, tdmi, tdmi_qscan_link); tdmi->tdmi_quickscan = TDMI_QUICKSCAN_RUNNING; dvb_tune_tdmi(tdmi, 0, TDMI_IDLESCAN); return; @@ -337,8 +334,8 @@ dvb_mux_scanner(void *aux, int64_t now) if(tdmi != NULL) tdmi->tdmi_quickscan = TDMI_QUICKSCAN_NONE; - tdmi = tdmi != NULL ? LIST_NEXT(tdmi, tdmi_adapter_link) : NULL; - tdmi = tdmi != NULL ? tdmi : LIST_FIRST(&tda->tda_muxes); + tdmi = tdmi != NULL ? RB_NEXT(tdmi, tdmi_adapter_link) : NULL; + tdmi = tdmi != NULL ? tdmi : RB_FIRST(&tda->tda_muxes); if(tdmi == NULL) return; /* no instances */ @@ -350,11 +347,27 @@ dvb_mux_scanner(void *aux, int64_t now) * */ static int -tdmi_inssort(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b) +tdmi_cmp(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b) { - return a->tdmi_fe_params->frequency - b->tdmi_fe_params->frequency; + if(a->tdmi_switchport != b->tdmi_switchport) + return a->tdmi_switchport - b->tdmi_switchport; + + if(a->tdmi_fe_params.frequency != b->tdmi_fe_params.frequency) + return a->tdmi_fe_params.frequency - b->tdmi_fe_params.frequency; + + return a->tdmi_polarisation - b->tdmi_polarisation; } +/** + * + */ +static int +tdmi_global_cmp(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b) +{ + return strcmp(a->tdmi_identifier, b->tdmi_identifier); +} + + /** * Create a new mux on the given adapter, return NULL if it already exists */ @@ -364,35 +377,44 @@ dvb_mux_create(th_dvb_adapter_t *tda, struct dvb_frontend_parameters *fe_param, uint16_t tsid, const char *network, int flags) { th_dvb_mux_instance_t *tdmi; + static th_dvb_mux_instance_t *skel; char buf[200]; char qpsktxt[20]; + int entries_before = tda->tda_muxes.entries; - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { - if(tdmi->tdmi_fe_params->frequency == fe_param->frequency && - tdmi->tdmi_polarisation == polarisation && - tdmi->tdmi_switchport == switchport) - return NULL; - } + if(skel == NULL) + skel = calloc(1, sizeof(th_dvb_mux_instance_t)); + + skel->tdmi_polarisation = polarisation; + skel->tdmi_switchport = switchport; + skel->tdmi_fe_params.frequency = fe_param->frequency; + + tdmi = RB_INSERT_SORTED(&tda->tda_muxes, skel, tdmi_adapter_link, tdmi_cmp); + if(tdmi != NULL) + return NULL; + + tdmi = skel; + skel = NULL; - tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); - tdmi->tdmi_quickscan = TDMI_QUICKSCAN_WAITING; tdmi->tdmi_refcnt = 1; + + RB_INSERT_SORTED(&tda->tda_muxes_qscan_waiting, tdmi, tdmi_qscan_link, + tdmi_cmp); + + tdmi->tdmi_quickscan = TDMI_QUICKSCAN_WAITING; + pthread_mutex_init(&tdmi->tdmi_table_lock, NULL); tdmi->tdmi_state = TDMI_IDLE; tdmi->tdmi_transport_stream_id = tsid; tdmi->tdmi_adapter = tda; tdmi->tdmi_network = network ? strdup(network) : NULL; - if(LIST_FIRST(&tda->tda_muxes) == NULL && tda->tda_rootpath != NULL) { + if(entries_before == 0 && tda->tda_rootpath != NULL) { /* First mux on adapter with backing hardware, start scanner */ dtimer_arm(&tda->tda_mux_scanner_timer, dvb_mux_scanner, tda, 1); } - - tdmi->tdmi_fe_params = malloc(sizeof(struct dvb_frontend_parameters)); - tdmi->tdmi_polarisation = polarisation; - tdmi->tdmi_switchport = switchport; - memcpy(tdmi->tdmi_fe_params, fe_param, + memcpy(&tdmi->tdmi_fe_params, fe_param, sizeof(struct dvb_frontend_parameters)); if(tda->tda_type == FE_QPSK) @@ -404,11 +426,10 @@ dvb_mux_create(th_dvb_adapter_t *tda, struct dvb_frontend_parameters *fe_param, snprintf(buf, sizeof(buf), "%s%d%s", tda->tda_identifier,fe_param->frequency, qpsktxt); - LIST_INSERT_SORTED(&tda->tda_muxes, tdmi, tdmi_adapter_link, tdmi_inssort); - LIST_INSERT_HEAD(&dvb_muxes, tdmi, tdmi_global_link); - tdmi->tdmi_identifier = strdup(buf); + RB_INSERT_SORTED(&dvb_muxes, tdmi, tdmi_global_link, tdmi_global_cmp); + if(flags & DVB_MUX_SAVE) { dvb_tda_save(tda); notify_tda_change(tda); @@ -432,7 +453,6 @@ dvb_mux_unref(th_dvb_mux_instance_t *tdmi) free(tdmi->tdmi_network); free(tdmi->tdmi_identifier); - free(tdmi->tdmi_fe_params); free(tdmi); } @@ -457,8 +477,11 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) tdmi_stop(tda->tda_mux_current); dtimer_disarm(&tdmi->tdmi_initial_scan_timer); - LIST_REMOVE(tdmi, tdmi_global_link); - LIST_REMOVE(tdmi, tdmi_adapter_link); + RB_REMOVE(&dvb_muxes, tdmi, tdmi_global_link); + RB_REMOVE(&tda->tda_muxes, tdmi, tdmi_adapter_link); + + if(tdmi->tdmi_quickscan == TDMI_QUICKSCAN_WAITING) + RB_REMOVE(&tda->tda_muxes_qscan_waiting, tdmi, tdmi_qscan_link); pthread_mutex_lock(&tda->tda_lock); dvb_fe_flush(tdmi); @@ -490,7 +513,7 @@ dvb_tda_save(th_dvb_adapter_t *tda) fprintf(fp, "type = %s\n", dvb_adaptertype_to_str(tda->tda_type)); fprintf(fp, "displayname = %s\n", tda->tda_displayname); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { fprintf(fp, "mux {\n"); dvb_mux_store(fp, tdmi); @@ -728,13 +751,13 @@ dvb_tda_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src) th_transport_t *t_src, *t_dst; th_stream_t *st_src, *st_dst; - while((tdmi_dst = LIST_FIRST(&dst->tda_muxes)) != NULL) + while((tdmi_dst = RB_FIRST(&dst->tda_muxes)) != NULL) dvb_mux_destroy(tdmi_dst); - LIST_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) { + RB_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) { tdmi_dst = dvb_mux_create(dst, - tdmi_src->tdmi_fe_params, + &tdmi_src->tdmi_fe_params, tdmi_src->tdmi_polarisation, tdmi_src->tdmi_switchport, tdmi_src->tdmi_transport_stream_id, @@ -804,7 +827,7 @@ dvb_tda_destroy(th_dvb_adapter_t *tda) unlink(buf); - while((tdmi = LIST_FIRST(&tda->tda_muxes)) != NULL) + while((tdmi = RB_FIRST(&tda->tda_muxes)) != NULL) dvb_mux_destroy(tdmi); TAILQ_REMOVE(&dvb_adapters, tda, tda_global_link); @@ -842,3 +865,17 @@ dvb_tdmi_fastswitch(th_dvb_mux_instance_t *tdmi) dvb_mux_scanner(tdmi->tdmi_adapter, 0); } + + +/** + * + */ +th_dvb_mux_instance_t * +dvb_mux_find_by_identifier(const char *identifier) +{ + th_dvb_mux_instance_t skel; + + skel.tdmi_identifier = (char *)identifier; + return RB_FIND(&dvb_muxes, &skel, tdmi_global_link, tdmi_global_cmp); +} + diff --git a/dvb.h b/dvb.h index a0301af5..c14a31b4 100644 --- a/dvb.h +++ b/dvb.h @@ -29,7 +29,7 @@ enum polarisation { #define DVB_FEC_ERROR_LIMIT 20 extern struct th_dvb_adapter_queue dvb_adapters; -extern struct th_dvb_mux_instance_list dvb_muxes; +extern struct th_dvb_mux_instance_tree dvb_muxes; void dvb_init(void); diff --git a/dvb_fe.c b/dvb_fe.c index 32931dde..3b6be75e 100644 --- a/dvb_fe.c +++ b/dvb_fe.c @@ -96,7 +96,7 @@ dvb_fe_manager(void *aux) pthread_mutex_unlock(&tda->tda_lock); - p = *tdmi->tdmi_fe_params; + p = tdmi->tdmi_fe_params; if(tda->tda_type == FE_QPSK) { /* DVB-S */ diff --git a/dvb_muxconfig.c b/dvb_muxconfig.c index cb8aa230..c2e46c2d 100644 --- a/dvb_muxconfig.c +++ b/dvb_muxconfig.c @@ -96,7 +96,7 @@ static struct strtab poltab[] = { void dvb_mux_store(FILE *fp, th_dvb_mux_instance_t *tdmi) { - struct dvb_frontend_parameters *f = tdmi->tdmi_fe_params; + struct dvb_frontend_parameters *f = &tdmi->tdmi_fe_params; fprintf(fp, "\ttransportstreamid = %d\n", tdmi->tdmi_transport_stream_id); if(tdmi->tdmi_network != NULL) diff --git a/dvb_support.c b/dvb_support.c index 5e0e7802..565a6b6f 100644 --- a/dvb_support.c +++ b/dvb_support.c @@ -253,19 +253,6 @@ dvb_polarisation_to_str_long(int pol) } -th_dvb_mux_instance_t * -dvb_mux_find_by_identifier(const char *identifier) -{ - th_dvb_mux_instance_t *tdmi; - - LIST_FOREACH(tdmi, &dvb_muxes, tdmi_global_link) - if(!strcmp(identifier, tdmi->tdmi_identifier)) - return tdmi; - return NULL; -} - - - th_dvb_adapter_t * dvb_adapter_find_by_identifier(const char *identifier) { @@ -312,11 +299,11 @@ void dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) { if(tdmi->tdmi_adapter->tda_type == FE_QPSK) - snprintf(buf, size, "%dkHz %s port %d", tdmi->tdmi_fe_params->frequency, + snprintf(buf, size, "%dkHz %s port %d", tdmi->tdmi_fe_params.frequency, dvb_polarisation_to_str_long(tdmi->tdmi_polarisation), tdmi->tdmi_switchport); else - snprintf(buf, size, "%dHz", tdmi->tdmi_fe_params->frequency); + snprintf(buf, size, "%dHz", tdmi->tdmi_fe_params.frequency); } /** diff --git a/dvb_tables.c b/dvb_tables.c index c635ca0f..5225c3c7 100644 --- a/dvb_tables.c +++ b/dvb_tables.c @@ -250,7 +250,7 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, ptr += 11; /* Search all muxes on adapter */ - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + RB_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == transport_stream_id) break; diff --git a/tvhead.h b/tvhead.h index ff17db47..e84d4898 100644 --- a/tvhead.h +++ b/tvhead.h @@ -29,6 +29,7 @@ #include #include #include +#include /* * Commercial status @@ -82,8 +83,7 @@ TAILQ_HEAD(ref_update_queue, ref_update); LIST_HEAD(th_transport_list, th_transport); RB_HEAD(th_transport_tree, th_transport); TAILQ_HEAD(th_transport_queue, th_transport); -LIST_HEAD(th_dvb_mux_list, th_dvb_mux); -LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance); +RB_HEAD(th_dvb_mux_instance_tree, th_dvb_mux_instance); LIST_HEAD(th_stream_list, th_stream); TAILQ_HEAD(th_pkt_queue, th_pkt); LIST_HEAD(th_pkt_list, th_pkt); @@ -157,8 +157,9 @@ typedef struct th_dvb_mux_instance { TDMI_QUICKSCAN_WAITING, } tdmi_quickscan; - LIST_ENTRY(th_dvb_mux_instance) tdmi_global_link; - LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; + RB_ENTRY(th_dvb_mux_instance) tdmi_global_link; + RB_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; + RB_ENTRY(th_dvb_mux_instance) tdmi_qscan_link; struct th_dvb_adapter *tdmi_adapter; @@ -185,7 +186,7 @@ typedef struct th_dvb_mux_instance { time_t tdmi_got_adapter; time_t tdmi_lost_adapter; - struct dvb_frontend_parameters *tdmi_fe_params; + struct dvb_frontend_parameters tdmi_fe_params; uint8_t tdmi_polarisation; /* for DVB-S */ uint8_t tdmi_switchport; /* for DVB-S */ @@ -227,7 +228,9 @@ typedef struct th_dvb_adapter { TAILQ_ENTRY(th_dvb_adapter) tda_global_link; - struct th_dvb_mux_instance_list tda_muxes; + struct th_dvb_mux_instance_tree tda_muxes; + struct th_dvb_mux_instance_tree tda_muxes_qscan_waiting; + th_dvb_mux_instance_t *tda_mux_current; const char *tda_rootpath;