]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Fix #1605 - timeshift: correct mistake in file refcounting.
authorAdam Sutton <dev@adamsutton.me.uk>
Fri, 15 Feb 2013 16:39:27 +0000 (16:39 +0000)
committerAdam Sutton <dev@adamsutton.me.uk>
Thu, 21 Feb 2013 16:00:00 +0000 (16:00 +0000)
(cherry picked from commit c33880290202d7181b51da968cd6247328225c92)

src/timeshift/private.h
src/timeshift/timeshift_filemgr.c
src/timeshift/timeshift_reader.c
src/timeshift/timeshift_writer.c

index 0a7f5b86c5770bc31470bbf6bc0c0ab2a3c3f3ac..435eb4f882e4214d89ce368f048875f9b1fd4e02 100644 (file)
@@ -137,10 +137,12 @@ void timeshift_filemgr_init     ( void );
 void timeshift_filemgr_term     ( void );
 int  timeshift_filemgr_makedirs ( int ts_index, char *buf, size_t len );
 
-timeshift_file_t *timeshift_filemgr_last
-  ( timeshift_t *ts );
 timeshift_file_t *timeshift_filemgr_get
   ( timeshift_t *ts, int create );
+timeshift_file_t *timeshift_filemgr_oldest
+  ( timeshift_t *ts );
+timeshift_file_t *timeshift_filemgr_newest
+  ( timeshift_t *ts );
 timeshift_file_t *timeshift_filemgr_prev
   ( timeshift_file_t *ts, int *end, int keep );
 timeshift_file_t *timeshift_filemgr_next
index 19bc6b439b97ae585272f5f81b4403cdc71bc787..cf6906e237cd2cbed8121699da9d5e568ccbf9b7 100644 (file)
@@ -161,6 +161,7 @@ void timeshift_filemgr_remove
 {
   if (tsf->fd != -1)
     close(tsf->fd);
+  tvhlog(LOG_DEBUG, "timeshift", "ts %d remove %s\n", ts->id, tsf->path);
   TAILQ_REMOVE(&ts->files, tsf, link);
   atomic_add_u64(&timeshift_total_size, -tsf->size);
   timeshift_reaper_remove(tsf);
@@ -192,7 +193,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create )
 
   /* Return last file */
   if (!create)
-    return TAILQ_LAST(&ts->files, timeshift_file_list);
+    return timeshift_filemgr_newest(ts);
 
   /* No space */
   if (ts->full)
@@ -216,9 +217,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create )
         if (!tsf_hd->refcount) {
           timeshift_filemgr_remove(ts, tsf_hd, 0);
         } else {
-#ifdef TSHFT_TRACE
           tvhlog(LOG_DEBUG, "timeshift", "ts %d buffer full", ts->id);
-#endif
           ts->full = 1;
         }
       }
@@ -227,8 +226,16 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create )
     /* Check size */
     if (!timeshift_unlimited_size &&
         atomic_pre_add_u64(&timeshift_total_size, 0) >= timeshift_max_size) {
-      tvhlog(LOG_DEBUG, "timshift", "ts %d buffer full", ts->id);
-      ts->full = 1;
+
+      /* Remove the last file (if we can) */
+      if (!tsf_hd->refcount) {
+        timeshift_filemgr_remove(ts, tsf_hd, 0);
+
+      /* Full */
+      } else {
+        tvhlog(LOG_DEBUG, "timshift", "ts %d buffer full", ts->id);
+        ts->full = 1;
+      }
     }
       
     /* Create new file */
@@ -273,6 +280,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int create )
     tsf_tl = tsf_tmp;
   }
 
+  tsf_tl->refcount++;
   return tsf_tl;
 }
 
@@ -303,11 +311,24 @@ timeshift_file_t *timeshift_filemgr_prev
 /*
  * Get the oldest file
  */
-timeshift_file_t *timeshift_filemgr_last ( timeshift_t *ts )
+timeshift_file_t *timeshift_filemgr_oldest ( timeshift_t *ts )
 {
-  return TAILQ_FIRST(&ts->files);
+  timeshift_file_t *tsf = TAILQ_FIRST(&ts->files);
+  if (tsf)
+    tsf->refcount++;
+  return tsf;
 }
 
+/*
+ * Get the newest file
+ */
+timeshift_file_t *timeshift_filemgr_newest ( timeshift_t *ts )
+{
+  timeshift_file_t *tsf = TAILQ_LAST(&ts->files, timeshift_file_list);
+  if (tsf)
+    tsf->refcount++;
+  return tsf;
+}
 
 /* **************************************************************************
  * Setup / Teardown
index 70bd9d0ad4454df270f5cbe4264c661f82de7302..e2d4437ef0d1515a8998ec8dee130fa91dfa5af8 100644 (file)
@@ -192,10 +192,11 @@ static timeshift_index_iframe_t *_timeshift_first_frame
 { 
   int end;
   timeshift_index_iframe_t *tsi = NULL;
-  timeshift_file_t *tsf = timeshift_filemgr_last(ts);
+  timeshift_file_t *tsf = timeshift_filemgr_oldest(ts);
   while (tsf && !tsi) {
-    if (!(tsi = TAILQ_FIRST(&tsf->iframes)))
+    if (!(tsi = TAILQ_FIRST(&tsf->iframes))) {
       tsf = timeshift_filemgr_next(tsf, &end, 0);
+    }
   }
   if (tsf)
     tsf->refcount--;
@@ -209,8 +210,9 @@ static timeshift_index_iframe_t *_timeshift_last_frame
   timeshift_index_iframe_t *tsi = NULL;
   timeshift_file_t *tsf = timeshift_filemgr_get(ts, 0);
   while (tsf && !tsi) {
-    if (!(tsi = TAILQ_LAST(&tsf->iframes, timeshift_index_iframe_list)))
+    if (!(tsi = TAILQ_LAST(&tsf->iframes, timeshift_index_iframe_list))) {
       tsf = timeshift_filemgr_prev(tsf, &end, 0);
+    }
   }
   if (tsf)
     tsf->refcount--;
@@ -227,6 +229,10 @@ static int _timeshift_skip
   int64_t                   sec  = req_time / (1000000 * TIMESHIFT_FILE_PERIOD);
   int                       back = (req_time < cur_time) ? 1 : 0;
   int                       end  = 0;
+  
+  /* Hold local ref */
+  if (cur_file)
+    cur_file->refcount++;
 
   /* Coarse search */
   if (!tsi) {
@@ -272,7 +278,7 @@ static int _timeshift_skip
   /* Find start/end of buffer */
   if (end) {
     if (back) {
-      tsf = timeshift_filemgr_last(ts);
+      tsf = timeshift_filemgr_oldest(ts);
       tsi = NULL;
       while (tsf && !tsi) {
         if (!(tsi = TAILQ_FIRST(&tsf->iframes)))
@@ -290,6 +296,9 @@ static int _timeshift_skip
     }
   }
 
+  if (cur_file)
+    cur_file->refcount--;
+
   /* Done */
   *new_file = tsf;
   *iframe   = tsi;
@@ -667,6 +676,8 @@ void *timeshift_reader ( void *p )
         }
 
         /* Position */
+        if (cur_file)
+          cur_file->refcount--;
         cur_file = tsf;
         if (tsi)
           cur_off = tsi->pos;
index 06810a864ad1fd38910223855d33b082033bf263..0e2f50ae1ee498242a6accd0c1ae47162420b3fb 100644 (file)
@@ -271,6 +271,7 @@ static void _process_msg
           tsf->bad = 1;
           ts->full = 1; ///< Stop any more writing
         }
+        tsf->refcount--;
       }
       pthread_mutex_unlock(&ts->rdwr_mutex);
       break;