From: Jaroslav Kysela Date: Thu, 8 Dec 2016 17:10:55 +0000 (+0100) Subject: webui/api: add possibility to remove dead services (maintenance button in the service... X-Git-Tag: v4.2.1~175 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c506b48f6997bd5b2664d64cf09a82e0bac9f59;p=thirdparty%2Ftvheadend.git webui/api: add possibility to remove dead services (maintenance button in the service grid), fixes #4125 --- diff --git a/src/api/api_service.c b/src/api/api_service.c index d5d6c709f..a4d7d2cbd 100644 --- a/src/api/api_service.c +++ b/src/api/api_service.c @@ -160,6 +160,19 @@ api_service_streams return 0; } +static int +api_service_remove_unseen + ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) +{ + int days = htsmsg_get_s32_or_default(args, "days", 7); + const char *type = htsmsg_get_str(args, "type"); + + pthread_mutex_lock(&global_lock); + service_remove_unseen(type, days); + pthread_mutex_unlock(&global_lock); + return 0; +} + void api_service_init ( void ) { extern const idclass_t service_class; @@ -170,6 +183,7 @@ void api_service_init ( void ) { "service/mapper/status", ACCESS_ADMIN, api_mapper_status, NULL }, { "service/list", ACCESS_ADMIN, api_idnode_load_by_class, (void*)&service_class }, { "service/streams", ACCESS_ADMIN, api_service_streams, NULL }, + { "service/removeunseen", ACCESS_ADMIN, api_service_remove_unseen, NULL }, { NULL }, }; diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index b7381e51b..e426dd1d3 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -736,6 +736,15 @@ mpegts_service_memoryinfo ( service_t *t, int64_t *size ) *size += tvh_strlen(ms->s_dvb_charset); } +static int +mpegts_service_unseen( service_t *t, const char *type, time_t before ) +{ + mpegts_service_t *ms = (mpegts_service_t*)t; + int pat = type && strcasecmp(type, "pat") == 0; + if (pat && ms->s_auto != SERVICE_AUTO_PAT_MISSING) return 0; + return ms->s_dvb_last_seen < before; +} + /* ************************************************************************** * Creation/Location * *************************************************************************/ @@ -790,6 +799,7 @@ mpegts_service_create0 s->s_mapped = mpegts_service_mapped; s->s_satip_source = mpegts_service_satip_source; s->s_memoryinfo = mpegts_service_memoryinfo; + s->s_unseen = mpegts_service_unseen; pthread_mutex_lock(&s->s_stream_mutex); service_make_nicename((service_t*)s); diff --git a/src/service.c b/src/service.c index 39f054782..49defee12 100644 --- a/src/service.c +++ b/src/service.c @@ -2014,6 +2014,23 @@ void service_save ( service_t *t, htsmsg_t *m ) htsmsg_add_msg(m, "stream", list); } +/** + * + */ +void +service_remove_unseen(const char *type, int days) +{ + service_t *s, *sn; + time_t before = gclk() - MAX(days, 5) * 24 * 3600; + + lock_assert(&global_lock); + for (s = TAILQ_FIRST(&service_all); s; s = sn) { + sn = TAILQ_NEXT(s, s_all_link); + if (s->s_unseen && s->s_unseen(s, type, before)) + service_destroy(s, 1); + } +} + /** * */ diff --git a/src/service.h b/src/service.h index 7d15bb689..390adf0d7 100644 --- a/src/service.h +++ b/src/service.h @@ -333,6 +333,8 @@ typedef struct service { void (*s_memoryinfo)(struct service *t, int64_t *size); + int (*s_unseen)(struct service *t, const char *type, time_t before); + /** * Channel info */ @@ -619,6 +621,8 @@ void service_load ( service_t *s, htsmsg_t *c ); void service_save ( service_t *s, htsmsg_t *c ); +void service_remove_unseen(const char *type, int days); + void sort_elementary_streams(service_t *t); const char *service_get_channel_name (service_t *s); diff --git a/src/webui/static/app/mpegts.js b/src/webui/static/app/mpegts.js index cbcd460c0..51d4d0e82 100644 --- a/src/webui/static/app/mpegts.js +++ b/src/webui/static/app/mpegts.js @@ -271,6 +271,48 @@ tvheadend.services = function(panel, index) abuttons.map.setText(_('Map All')); }; + var unseencb = function(type) { + tvheadend.Ajax({ + url: 'api/service/removeunseen', + params: { + type: type, + }, + success: function(d) { + store.reload(); + } + }); + }; + + var maintenanceButton = { + name: 'misc', + builder: function() { + var m = new Ext.menu.Menu() + m.add({ + name: 'rmunsnpat', + tooltip: _('Remove old services marked as missing in PAT/SDT which were not detected more than 7 days (last seen column)'), + iconCls: 'remove', + text: _('Remove unseen services (PAT/SDT) (7 days+)'), + }); + m.add({ + name: 'rmunsn', + tooltip: _('Remove old services which were not detected more than 7 days (last seen column)'), + iconCls: 'remove', + text: _('Remove all unseen services (7 days+)'), + }); + return new Ext.Toolbar.Button({ + tooltip: _('Maintenance operations'), + iconCls: 'wrench', + text: _('Maintenance'), + menu: m, + disabled: false + }); + }, + callback: { + rmunsnpat: function() { unseencb('pat'); }, + rmunsn: function() { unseencb(''); } + } + }; + var actions = new Ext.ux.grid.RowActions({ header: _('Details'), width: 10, @@ -293,7 +335,7 @@ tvheadend.services = function(panel, index) destroy: function() { } }); - conf.tbar = [mapButton]; + conf.tbar = [mapButton, maintenanceButton]; conf.selected = selected; conf.lcol[1] = actions; conf.plugins = [actions];