]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
implemented deferred_unlink() for DVR
authorJaroslav Kysela <perex@perex.cz>
Fri, 24 Apr 2015 11:44:01 +0000 (13:44 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 24 Apr 2015 12:11:01 +0000 (14:11 +0200)
src/dvr/dvr_db.c
src/main.c
src/tvheadend.h
src/utils.c

index 533bcc1a1cbefd68b639900358de563fbcb43ebe..20ab1100694208f0697467cb0c81645272de5ca3 100644 (file)
@@ -2210,6 +2210,7 @@ dvr_entry_delete(dvr_entry_t *de)
   time_t t;
   struct tm tm;
   char tbuf[64];
+  int r;
 
   t = dvr_entry_get_start_time(de);
   localtime_r(&t, &tm);
@@ -2227,9 +2228,10 @@ dvr_entry_delete(dvr_entry_t *de)
 #if ENABLE_INOTIFY
     dvr_inotify_del(de);
 #endif
-    if(unlink(de->de_filename) && errno != ENOENT)
+    r = deferred_unlink(de->de_filename);
+    if(r && r != -ENOENT)
       tvhlog(LOG_WARNING, "dvr", "Unable to remove file '%s' from disk -- %s",
-            de->de_filename, strerror(errno));
+            de->de_filename, strerror(-errno));
 
     /* Also delete directories, if they were created for the recording and if they are empty */
 
index 6a82df71bf6c4d7176d485c0f495722ca406f2e4..2fabff7d5da53f16d3fb493d9bd054d05cb076fa 100644 (file)
@@ -305,6 +305,20 @@ gtimer_disarm(gtimer_t *gti)
   }
 }
 
+/**
+ *
+ */
+tasklet_t *
+tasklet_arm_alloc(tsk_callback_t *callback, void *opaque)
+{
+  tasklet_t *tsk = calloc(1, sizeof(*tsk));
+  if (tsk) {
+    tsk->tsk_allocated = 1;
+    tasklet_arm(tsk, callback, opaque);
+  }
+  return tsk;
+}
+
 /**
  *
  */
@@ -339,6 +353,8 @@ tasklet_disarm(tasklet_t *tsk)
     TAILQ_REMOVE(&tasklets, tsk, tsk_link);
     tsk->tsk_callback(tsk->tsk_opaque, 1);
     tsk->tsk_callback = NULL;
+    if (tsk->tsk_allocated)
+      free(tsk);
   }
 
   pthread_mutex_unlock(&tasklet_lock);
@@ -355,6 +371,8 @@ tasklet_flush()
     TAILQ_REMOVE(&tasklets, tsk, tsk_link);
     tsk->tsk_callback(tsk->tsk_opaque, 1);
     tsk->tsk_callback = NULL;
+    if (tsk->tsk_allocated)
+      free(tsk);
   }
 
   pthread_mutex_unlock(&tasklet_lock);
@@ -538,6 +556,7 @@ main(int argc, char **argv)
   pthread_mutex_init(&atomic_lock, NULL);
   pthread_cond_init(&gtimer_cond, NULL);
   pthread_cond_init(&tasklet_cond, NULL);
+  TAILQ_INIT(&tasklets);
 
   /* Defaults */
   tvheadend_webui_port      = 9981;
@@ -1058,6 +1077,7 @@ main(int argc, char **argv)
   tvhftrace("main", spawn_done);
 
   tvhtrace("main", "tasklet enter");
+  pthread_cond_signal(&tasklet_cond);
   pthread_join(tasklet_tid, NULL);
   tvhtrace("main", "tasklet thread end");
   tasklet_flush();
index 67dead208537c094b0beb160a17e4d3d4a7d1e3c..6db892d68f4bd6978926700638f98f62fe090c09 100644 (file)
@@ -184,8 +184,10 @@ typedef struct tasklet {
   TAILQ_ENTRY(tasklet) tsk_link;
   tsk_callback_t *tsk_callback;
   void *tsk_opaque;
+  int tsk_allocated;
 } tasklet_t;
 
+tasklet_t *tasklet_arm_alloc(tsk_callback_t *callback, void *opaque);
 void tasklet_arm(tasklet_t *tsk, tsk_callback_t *callback, void *opaque);
 void tasklet_disarm(tasklet_t *gti);
 
@@ -736,6 +738,8 @@ char *url_encode(char *str);
 
 int mpegts_word_count(const uint8_t *tsb, int len, uint32_t mask);
 
+int deferred_unlink(const char *filename);
+
 static inline int32_t deltaI32(int32_t a, int32_t b) { return (a > b) ? (a - b) : (b - a); }
 static inline uint32_t deltaU32(uint32_t a, uint32_t b) { return (a > b) ? (a - b) : (b - a); }
   
index ba7ec46cfdbbc14ffea629cfd706e549d4d004ad..3bfe245e01e57570053e4cb2f4c2c7a93843f3f4 100644 (file)
@@ -638,3 +638,34 @@ mpegts_word_count ( const uint8_t *tsb, int len, uint32_t mask )
 
   return r;
 }
+
+static void
+deferred_unlink_cb(void *s, int dearmed)
+{
+  if (unlink((const char *)s))
+    tvherror("main", "unable to remove file '%s'", (const char *)s);
+  free(s);
+}
+
+int
+deferred_unlink(const char *filename)
+{
+  char *s;
+  size_t l;
+  int r;
+
+  l = strlen(filename);
+  s = malloc(l + 9);
+  if (s == NULL)
+    return -ENOMEM;
+  strcpy(s, filename);
+  strcpy(s + l, ".removing");
+  r = rename(filename, s);
+  if (r) {
+    r = -errno;
+    free(s);
+    return r;
+  }
+  tasklet_arm_alloc(deferred_unlink_cb, s);
+  return 0;
+}