Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
idnode: move save calls to another thread
  • Loading branch information
perexg committed Feb 10, 2016
1 parent 98e6009 commit e481234
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 40 deletions.
9 changes: 6 additions & 3 deletions src/dvr/dvr_db.c
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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);
}

/**
Expand Down
135 changes: 99 additions & 36 deletions src/idnode.c
Expand Up @@ -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);

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -1103,14 +1079,29 @@ 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 )
{
int save = 0;
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
Expand All @@ -1125,7 +1116,7 @@ void
idnode_changed( idnode_t *self )
{
idnode_notify_changed(self);
idnode_savefn(self);
idnode_save_queue(self);
}

/* **************************************************************************
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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
*
Expand Down
11 changes: 10 additions & 1 deletion src/idnode.h
Expand Up @@ -28,6 +28,7 @@

struct access;
typedef struct idnode idnode_t;
typedef struct idnode_save idnode_save_t;

/*
* Node set
Expand Down Expand Up @@ -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
*/
Expand Down

0 comments on commit e481234

Please sign in to comment.