]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
idnode: move save calls to another thread
authorJaroslav Kysela <perex@perex.cz>
Wed, 10 Feb 2016 13:58:47 +0000 (14:58 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 10 Feb 2016 13:58:47 +0000 (14:58 +0100)
src/dvr/dvr_db.c
src/idnode.c
src/idnode.h

index 33115be4f3822ecf06ed7e5a20e87eefa5f5a3e1..9a34c9a474356dcc5ce6393f429fbc4205cdc125 100644 (file)
@@ -450,16 +450,18 @@ dvr_entry_missed_time(dvr_entry_t *de, int error_code)
 /*
  * Completed
  */
-static void
+static int
 dvr_entry_completed(dvr_entry_t *de, int error_code)
 {
-  dvr_entry_set_state(de, DVR_COMPLETED, DVR_RS_FINISHED, error_code);
+  int change;
+  change = dvr_entry_set_state(de, DVR_COMPLETED, DVR_RS_FINISHED, error_code);
 #if ENABLE_INOTIFY
   dvr_inotify_add(de);
 #endif
   dvr_entry_retention_timer(de);
   if (de->de_autorec)
     dvr_autorec_completed(de->de_autorec, error_code);
+  return change;
 }
 
 /**
@@ -3404,7 +3406,8 @@ void
 dvr_entry_move(dvr_entry_t *de, int failed)
 {
   if(de->de_sched_state == DVR_COMPLETED)
-    dvr_entry_completed(de, failed ? SM_CODE_USER_REQUEST : SM_CODE_OK);
+    if (dvr_entry_completed(de, failed ? SM_CODE_USER_REQUEST : SM_CODE_OK))
+      idnode_changed(&de->de_id);
 }
 
 /**
index 08e4a4b1f390c42634a562e3453377e81dfb3830..0fe0eaddf6524e78f546978c807fb0d351c3932b 100644 (file)
@@ -41,9 +41,14 @@ typedef struct idclass_link
   RB_ENTRY(idclass_link) link;
 } idclass_link_t;
 
-static idnodes_rb_t           idnodes;
-static RB_HEAD(,idclass_link) idclasses;
-static RB_HEAD(,idclass_link) idrootclasses;
+static idnodes_rb_t             idnodes;
+static RB_HEAD(,idclass_link)   idclasses;
+static RB_HEAD(,idclass_link)   idrootclasses;
+static TAILQ_HEAD(,idnode_save) idnodes_save;
+
+pthread_cond_t save_cond;
+pthread_t save_tid;
+static int save_running;
 
 SKEL_DECLARE(idclasses_skel, idclass_link_t);
 
@@ -72,35 +77,6 @@ ic_cmp ( const idclass_link_t *a, const idclass_link_t *b )
  * Registration
  * *************************************************************************/
 
-/**
- *
- */
-pthread_t idnode_tid;
-
-void
-idnode_init(void)
-{
-  RB_INIT(&idnodes);
-  RB_INIT(&idclasses);
-  RB_INIT(&idrootclasses);
-}
-
-void
-idnode_done(void)
-{
-  idclass_link_t *il;
-
-  while ((il = RB_FIRST(&idclasses)) != NULL) {
-    RB_REMOVE(&idclasses, il, link);
-    free(il);
-  }
-  while ((il = RB_FIRST(&idrootclasses)) != NULL) {
-    RB_REMOVE(&idrootclasses, il, link);
-    free(il);
-  }
-  SKEL_FREE(idclasses_skel);
-}
-
 static const idclass_t *
 idnode_root_class(const idclass_t *idc)
 {
@@ -1103,6 +1079,21 @@ idnode_savefn ( idnode_t *self )
   }
 }
 
+static void
+idnode_save_queue ( idnode_t *self )
+{
+  idnode_save_t *ise;
+
+  if (self->in_save)
+    return;
+  ise = malloc(sizeof(*ise));
+  ise->ise_node = self;
+  if (TAILQ_EMPTY(&idnodes_save))
+    pthread_cond_signal(&save_cond);
+  TAILQ_INSERT_TAIL(&idnodes_save, ise, ise_link);
+  self->in_save = ise;
+}
+
 int
 idnode_write0 ( idnode_t *self, htsmsg_t *c, int optmask, int dosave )
 {
@@ -1110,7 +1101,7 @@ idnode_write0 ( idnode_t *self, htsmsg_t *c, int optmask, int dosave )
   const idclass_t *idc = self->in_class;
   save = idnode_class_write_values(self, idc, c, optmask);
   if ((idc->ic_flags & IDCLASS_ALWAYS_SAVE) != 0 || (save && dosave))
-    idnode_savefn(self);
+    idnode_save_queue(self);
   if (dosave)
     idnode_notify_changed(self);
   // Note: always output event if "dosave", reason is that UI updates on
@@ -1125,7 +1116,7 @@ void
 idnode_changed( idnode_t *self )
 {
   idnode_notify_changed(self);
-  idnode_savefn(self);
+  idnode_save_queue(self);
 }
 
 /* **************************************************************************
@@ -1368,12 +1359,12 @@ idnode_list_notify ( idnode_list_mapping_t *ilm, void *origin )
   if (origin == ilm->ilm_in1) {
     idnode_notify_changed(ilm->ilm_in2);
     if (ilm->ilm_in2_save)
-      idnode_savefn(ilm->ilm_in2);
+      idnode_save_queue(ilm->ilm_in2);
   }
   if (origin == ilm->ilm_in2) {
     idnode_notify_changed(ilm->ilm_in1);
     if (ilm->ilm_in1_save)
-      idnode_savefn(ilm->ilm_in1);
+      idnode_save_queue(ilm->ilm_in1);
   }
 }
 
@@ -1645,6 +1636,78 @@ idnode_notify_title_changed (void *in, const char *lang)
   idnode_notify_changed(in);
 }
 
+/* **************************************************************************
+ * Save thread
+ * *************************************************************************/
+
+static void *
+save_thread ( void *aux )
+{
+  idnode_save_t *ise;
+
+  tvhtread_renice(15);
+
+  pthread_mutex_lock(&global_lock);
+
+  while (save_running) {
+    if ((ise = TAILQ_FIRST(&idnodes_save)) == NULL) {
+      pthread_cond_wait(&save_cond, &global_lock);
+      continue;
+    }
+    idnode_savefn(ise->ise_node);
+    ise->ise_node->in_save = NULL;
+    TAILQ_REMOVE(&idnodes_save, ise, ise_link);
+    free(ise);
+  }
+
+  while ((ise = TAILQ_FIRST(&idnodes_save)) != NULL) {
+    idnode_savefn(ise->ise_node);
+    ise->ise_node->in_save = NULL;
+    TAILQ_REMOVE(&idnodes_save, ise, ise_link);
+    free(ise);
+  }
+
+  pthread_mutex_unlock(&global_lock);
+  return NULL;
+}
+
+/* **************************************************************************
+ * Initialization
+ * *************************************************************************/
+
+void
+idnode_init(void)
+{
+  RB_INIT(&idnodes);
+  RB_INIT(&idclasses);
+  RB_INIT(&idrootclasses);
+  TAILQ_INIT(&idnodes_save);
+
+  pthread_cond_init(&save_cond, NULL);
+  save_running = 1;
+  tvhthread_create(&save_tid, NULL, save_thread, NULL, "save");
+}
+
+void
+idnode_done(void)
+{
+  idclass_link_t *il;
+
+  save_running = 0;
+  pthread_cond_signal(&save_cond);
+  pthread_join(save_tid, NULL);
+
+  while ((il = RB_FIRST(&idclasses)) != NULL) {
+    RB_REMOVE(&idclasses, il, link);
+    free(il);
+  }
+  while ((il = RB_FIRST(&idrootclasses)) != NULL) {
+    RB_REMOVE(&idrootclasses, il, link);
+    free(il);
+  }
+  SKEL_FREE(idclasses_skel);
+}
+
 /******************************************************************************
  * Editor Configuration
  *
index 45a6f27472d00ece96783c8f3aca4e82df1297e4..28fe3a892c4ba837e2a782d13eb61207bb1c5582 100644 (file)
@@ -28,6 +28,7 @@
 
 struct access;
 typedef struct idnode idnode_t;
+typedef struct idnode_save idnode_save_t;
 
 /*
  * Node set
@@ -92,9 +93,17 @@ struct idnode {
   idnodes_rb_t     *in_domain;              ///< Domain nodes
   const idclass_t  *in_class;               ///< Class definition
   struct access    *in_access;              ///< Actual permissions
-
+  idnode_save_t    *in_save;                ///< Pointer to the save link
 };
 
+/*
+ * Node save list
+ */
+typedef struct idnode_save {
+  TAILQ_ENTRY(idnode_save)  ise_link;       ///< List chain
+  idnode_t                 *ise_node;       ///< Node owning this
+} idnode_save_t;
+
 /*
  * Node list mapping definition
  */