]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
imagecache: add 'expire' time for the cached files, fixes #4304
authorJaroslav Kysela <perex@perex.cz>
Mon, 26 Nov 2018 16:09:17 +0000 (17:09 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 26 Nov 2018 16:09:17 +0000 (17:09 +0100)
src/imagecache.c
src/imagecache.h

index 7eafa677ad904adedff359a02bdab5b0564954db..9b3efae891f55fffb94fbf131fb2e34e80713a07 100644 (file)
@@ -46,6 +46,7 @@ typedef struct imagecache_image
   int         id;       ///< Internal ID
   const char *url;      ///< Upstream URL
   int         failed;   ///< Last update failed
+  time_t      accessed; ///< Last time the file was accessed
   time_t      updated;  ///< Last time the file was checked
   uint8_t     sha1[20]; ///< Contents hash
   enum {
@@ -69,7 +70,8 @@ struct imagecache_config imagecache_conf = {
   .idnode.in_class = &imagecache_class,
 };
 
-static htsmsg_t *imagecache_save(idnode_t *self, char *filename, size_t fsize);
+static htsmsg_t *imagecache_class_save(idnode_t *self, char *filename, size_t fsize);
+static void imagecache_destroy(imagecache_image_t *img, int delconf);
 
 CLASS_DOC(imagecache)
 
@@ -80,7 +82,7 @@ const idclass_t imagecache_class = {
   .ic_event      = "imagecache",
   .ic_perm_def   = ACCESS_ADMIN,
   .ic_doc        = tvh_doc_imagecache_class,
-  .ic_save       = imagecache_save,
+  .ic_save       = imagecache_class_save,
   .ic_properties = (const property_t[]){
     {
       .type   = PT_BOOL,
@@ -100,6 +102,16 @@ const idclass_t imagecache_class = {
                    "self-certified, etc.) certificates"),
       .off    = offsetof(struct imagecache_config, ignore_sslcert),
     },
+    {
+      .type   = PT_U32,
+      .id     = "",
+      .name   = N_("Expire time"),
+      .desc   = N_("The time in hours after the cached URL will "
+                   "be removed. The time starts when the URL was "
+                   "lastly requested. Zero means unlimited cache "
+                   "(not recommended)."),
+      .off    = offsetof(struct imagecache_config, expire),
+    },
     {
       .type   = PT_U32,
       .id     = "ok_period",
@@ -153,6 +165,8 @@ imagecache_image_save ( imagecache_image_t *img )
   char hex[41];
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_str(m, "url", img->url);
+  if (img->accessed)
+    htsmsg_add_s64(m, "accessed", img->accessed);
   if (img->updated)
     htsmsg_add_s64(m, "updated", img->updated);
   if (!sha1_empty(img->sha1)) {
@@ -262,8 +276,6 @@ imagecache_image_fetch ( imagecache_image_t *img )
   if (img->url == NULL || img->url[0] == '\0')
     return res;
 
-  urlinit(&url);
-
   /* Open file  */
   if (hts_settings_buildpath(path, sizeof(path), "imagecache/data/%d",
                               img->id))
@@ -275,6 +287,8 @@ imagecache_image_fetch ( imagecache_image_t *img )
   /* Fetch (release lock, incase of delays) */
   pthread_mutex_unlock(&global_lock);
 
+  urlinit(&url);
+
   /* Build command */
   tvhdebug(LS_IMAGECACHE, "fetch %s", img->url);
   memset(&url, 0, sizeof(url));
@@ -373,10 +387,17 @@ imagecache_thread ( void *p )
 static void
 imagecache_timer_cb ( void *p )
 {
-  time_t now, when;
-  imagecache_image_t *img;
-  time(&now);
-  RB_FOREACH(img, &imagecache_by_url, url_link) {
+  time_t now = gclk(), when;
+  imagecache_image_t *img, *img_next;
+  for (img = RB_FIRST(&imagecache_by_url); img; img = img_next) {
+    img_next = RB_NEXT(img, url_link);
+    if (imagecache_conf.expire > 0 && img->accessed > 0) {
+      when = img->accessed + imagecache_conf.expire * 24 * 3600;
+      if (when < now) {
+        tvhdebug(LS_IMAGECACHE, "expired: %s", img->url);
+        imagecache_destroy(img, 1);
+      }
+    }
     if (img->state != IDLE) continue;
     when = img->failed ? imagecache_conf.fail_period
                        : imagecache_conf.ok_period;
@@ -408,6 +429,7 @@ imagecache_init ( void )
   imagecache_id             = 0;
 #if ENABLE_IMAGECACHE
   imagecache_conf.enabled        = 0;
+  imagecache_conf.expire         = 7;      // 7 days
   imagecache_conf.ok_period      = 24 * 7; // weekly
   imagecache_conf.fail_period    = 24;     // daily
   imagecache_conf.ignore_sslcert = 0;
@@ -509,10 +531,10 @@ imagecache_done ( void )
 #if ENABLE_IMAGECACHE
 
 /*
- * Save
+ * Class save
  */
 static htsmsg_t *
-imagecache_save ( idnode_t *self, char *filename, size_t fsize )
+imagecache_class_save ( idnode_t *self, char *filename, size_t fsize )
 {
   htsmsg_t *c = htsmsg_create_map();
   idnode_save(&imagecache_conf.idnode, c);
@@ -595,7 +617,8 @@ imagecache_trigger( void )
 int
 imagecache_get_id ( const char *url )
 {
-  int id = 0;
+  int id = 0, save = 0;
+  time_t clk;
   imagecache_image_t *i;
 
   lock_assert(&global_lock);
@@ -624,7 +647,7 @@ imagecache_get_id ( const char *url )
     imagecache_new_id(i);
     imagecache_image_add(i);
 #endif
-    imagecache_image_save(i);
+    save = 1;
   }
 #if ENABLE_IMAGECACHE
   if (!strncasecmp(url, "file://", 7) || imagecache_conf.enabled)
@@ -633,7 +656,14 @@ imagecache_get_id ( const char *url )
   if (!strncasecmp(url, "file://", 7))
     id = i->id;
 #endif
-  
+
+  clk = gclk();
+  if (clk != i->accessed) {
+    i->accessed = clk;
+    save = 1;
+  }
+  if (save && i->state != IDLE)
+    imagecache_image_save(i);
   return id;
 }
 
index 0bbc85297c7d4fea05eb43ab3190c9ad3245e3c1..edb8f9529a3751b99cedd8162a61e4b75a7f8157 100644 (file)
@@ -26,6 +26,7 @@ struct imagecache_config {
   idnode_t  idnode;
   int       enabled;
   int       ignore_sslcert;
+  uint32_t  expire;
   uint32_t  ok_period;
   uint32_t  fail_period;
 };