diff --git a/src/api/api_imagecache.c b/src/api/api_imagecache.c index e60512df..d8accb6b 100644 --- a/src/api/api_imagecache.c +++ b/src/api/api_imagecache.c @@ -43,9 +43,13 @@ static int api_imagecache_save ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) { + int b; + pthread_mutex_lock(&global_lock); if (imagecache_set_config(args)) imagecache_save(); + if (!htsmsg_get_bool(args, "clean", &b) && b) + imagecache_clean(); pthread_mutex_unlock(&global_lock); *resp = htsmsg_create_map(); htsmsg_add_u32(*resp, "success", 1); diff --git a/src/imagecache.c b/src/imagecache.c index 9713a317..c6c1f6de 100644 --- a/src/imagecache.c +++ b/src/imagecache.c @@ -163,7 +163,7 @@ imagecache_image_fetch ( imagecache_image_t *img ) pthread_mutex_unlock(&global_lock); /* Build command */ - tvhlog(LOG_DEBUG, "imagecache", "fetch %s", img->url); + tvhdebug("imagecache", "fetch %s", img->url); memset(&url, 0, sizeof(url)); if (urlparse(img->url, &url)) { tvherror("imagecache", "Unable to parse url '%s'", img->url); @@ -219,12 +219,13 @@ error: img->failed = 1; if (tmp[0]) unlink(tmp); - tvhlog(LOG_WARNING, "imagecache", "failed to download %s", img->url); + tvhwarn("imagecache", "failed to download %s", img->url); } else { img->failed = 0; unlink(path); - rename(tmp, path); - tvhlog(LOG_DEBUG, "imagecache", "downloaded %s", img->url); + if (rename(tmp, path)) + tvherror("imagecache", "unable to rename file '%s' to '%s'", tmp, path); + tvhdebug("imagecache", "downloaded %s", img->url); } imagecache_image_save(img); pthread_cond_broadcast(&imagecache_cond); @@ -361,6 +362,23 @@ imagecache_init ( void ) #endif } + +/* + * Destroy + */ +static void +imagecache_destroy ( imagecache_image_t *img, int delconf ) +{ + if (delconf) { + hts_settings_remove("imagecache/meta/%d", img->id); + hts_settings_remove("imagecache/data/%d", img->id); + } + RB_REMOVE(&imagecache_by_url, img, url_link); + RB_REMOVE(&imagecache_by_id, img, id_link); + free((void *)img->url); + free(img); +} + /* * Shutdown */ @@ -373,12 +391,8 @@ imagecache_done ( void ) pthread_cond_broadcast(&imagecache_cond); pthread_join(imagecache_tid, NULL); #endif - while ((img = RB_FIRST(&imagecache_by_url)) != NULL) { - RB_REMOVE(&imagecache_by_url, img, url_link); - RB_REMOVE(&imagecache_by_id, img, id_link); - free((void *)img->url); - free(img); - } + while ((img = RB_FIRST(&imagecache_by_id)) != NULL) + imagecache_destroy(img, 0); SKEL_FREE(imagecache_skel); } @@ -419,6 +433,52 @@ imagecache_save ( void ) notify_reload("imagecache"); } +/* + * Clean + */ +void +imagecache_clean( void ) +{ + imagecache_image_t *img, *next, skel; + fb_dirent **namelist; + char path[PATH_MAX], *name; + int i, n; + + lock_assert(&global_lock); + +#if ENABLE_IMAGECACHE + /* remove all cached data, except the one actually fetched */ + for (img = RB_FIRST(&imagecache_by_id); img; img = next) { + next = RB_NEXT(img, id_link); + if (img->state == FETCHING) + continue; + imagecache_destroy(img, 1); + } +#endif + + tvhinfo("imagecache", "clean request"); + /* remove unassociated data*/ + if (hts_settings_buildpath(path, sizeof(path), "imagecache/data")) { + tvherror("imagecache", "clean - buildpath"); + return; + } + if((n = fb_scandir(path, &namelist)) < 0) + return; + for (i = 0; i < n; i++) { + name = namelist[i]->name; + if (name[0] == '.') + continue; + skel.id = atoi(name); + img = RB_FIND(&imagecache_by_id, &skel, id_link, id_cmp); + if (img) + continue; + tvhinfo("imagecache", "clean: removing unassociated file '%s/%s'", path, name); + hts_settings_remove("imagecache/meta/%s", name); + hts_settings_remove("imagecache/data/%s", name); + } + free(namelist); +} + #endif /* ENABLE_IMAGECACHE */ /* diff --git a/src/imagecache.h b/src/imagecache.h index a2afa313..4d9945b1 100644 --- a/src/imagecache.h +++ b/src/imagecache.h @@ -39,6 +39,7 @@ void imagecache_done ( void ); htsmsg_t *imagecache_get_config ( void ); int imagecache_set_config ( htsmsg_t *c ); void imagecache_save ( void ); +void imagecache_clean ( void ); // Note: will return 0 if invalid (must serve original URL) uint32_t imagecache_get_id ( const char *url ); diff --git a/src/webui/static/app/config.js b/src/webui/static/app/config.js index aa780bcb..3cc9987f 100644 --- a/src/webui/static/app/config.js +++ b/src/webui/static/app/config.js @@ -221,6 +221,13 @@ tvheadend.miscconf = function(panel, index) { handler: saveChanges }); + var imagecacheButton = new Ext.Button({ + text: "Clean image (icon) cache", + tooltip: 'Clean image cache on storage', + iconCls: 'drive', + handler: cleanImagecache + }); + var helpButton = new Ext.Button({ text: 'Help', iconCls: 'help', @@ -254,7 +261,7 @@ tvheadend.miscconf = function(panel, index) { bodyStyle: 'padding:15px', layout: 'form', items: _items, - tbar: [saveButton, '->', helpButton] + tbar: [saveButton, '-', imagecacheButton, '->', helpButton] }); tvheadend.paneladd(panel, mpanel, index); @@ -285,6 +292,18 @@ tvheadend.miscconf = function(panel, index) { }); }); + function saveChangesImagecache(params) { + if (imagecache_form) + imagecache_form.getForm().submit({ + url: 'api/imagecache/config/save', + params: params || {}, + waitMsg: 'Saving data...', + failure: function(form, action) { + Ext.Msg.alert('Imagecache save failed', action.result.errormsg); + } + }); + } + function saveChanges() { confpanel.getForm().submit({ url: 'config', @@ -296,13 +315,10 @@ tvheadend.miscconf = function(panel, index) { Ext.Msg.alert('Save failed', action.result.errormsg); } }); - if (imagecache_form) - imagecache_form.getForm().submit({ - url: 'api/imagecache/config/save', - waitMsg: 'Saving data...', - failure: function(form, action) { - Ext.Msg.alert('Imagecache save failed', action.result.errormsg); - } - }); + saveChangesImagecache(); + } + + function cleanImagecache() { + saveChangesImagecache({'clean': 1}); } };