From ce8de44934136367134fc155e0ffad06139cfbb7 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 11 Dec 2015 16:06:05 +0100 Subject: [PATCH] DVR: enhance dvr_get_filesize() --- src/api/api_dvr.c | 2 +- src/dvr/dvr.h | 6 +++++- src/dvr/dvr_autorec.c | 2 +- src/dvr/dvr_db.c | 39 ++++++++++++++++++++++------------- src/dvr/dvr_rec.c | 3 ++- src/dvr/dvr_vfsmgr.c | 48 ++++++++++++++++++++++++++++++++++--------- src/htsp_server.c | 4 ++-- src/webui/webui.c | 4 ++-- 8 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/api/api_dvr.c b/src/api/api_dvr.c index 0354d81f1..2b0ee5975 100644 --- a/src/api/api_dvr.c +++ b/src/api/api_dvr.c @@ -66,7 +66,7 @@ api_dvr_config_create static int is_dvr_entry_finished(dvr_entry_t *entry) { dvr_entry_sched_state_t state = entry->de_sched_state; - return state == DVR_COMPLETED && !entry->de_last_error && dvr_get_filesize(entry) != -1; + return state == DVR_COMPLETED && !entry->de_last_error && dvr_get_filesize(entry, 0) != -1; } static int is_dvr_entry_upcoming(dvr_entry_t *entry) diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index cf99e944f..8dd4d2344 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -28,6 +28,9 @@ #include "lang_str.h" #include "tvhvfs.h" +#define DVR_FILESIZE_UPDATE (1<<0) +#define DVR_FILESIZE_TOTAL (1<<1) + typedef struct dvr_vfs { LIST_ENTRY(dvr_vfs) link; tvh_fsid_t fsid; @@ -557,7 +560,7 @@ dvr_entry_t *dvr_entry_find_by_event_fuzzy(epg_broadcast_t *e); const char *dvr_get_filename(dvr_entry_t *de); -int64_t dvr_get_filesize(dvr_entry_t *de); +int64_t dvr_get_filesize(dvr_entry_t *de, int flags); int64_t dvr_entry_claenup(dvr_entry_t *de, int64_t requiredBytes); @@ -588,6 +591,7 @@ void dvr_spawn_postcmd(dvr_entry_t *de, const char *postcmd, const char *filenam void dvr_vfs_refresh_entry(dvr_entry_t *de); void dvr_vfs_remove_entry(dvr_entry_t *de); +int64_t dvr_vfs_update_filename(const char *filename, htsmsg_t *fdata); void dvr_disk_space_boot(void); void dvr_disk_space_init(void); diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 46e96ab04..1829d1c0e 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -113,7 +113,7 @@ dvr_autorec_completed(dvr_entry_t *de, int error_code) de_prev = NULL; LIST_FOREACH(de, &dae->dae_spawns, de_autorec_link) { if (de->de_sched_state != DVR_COMPLETED) continue; - if (dvr_get_filesize(de) < 0) continue; + if (dvr_get_filesize(de, 0) < 0) continue; if (de_prev && de_prev->de_start > de->de_start) de_prev = de; count++; diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index e8f2d33c6..0f10531c0 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -499,7 +499,7 @@ dvr_entry_status(dvr_entry_t *de) default: break; } - if(dvr_get_filesize(de) == -1) + if(dvr_get_filesize(de, 0) == -1) return N_("File missing"); if(de->de_last_error) return streaming_code2txt(de->de_last_error); @@ -535,7 +535,7 @@ dvr_entry_schedstatus(dvr_entry_t *de) break; case DVR_COMPLETED: s = "completed"; - if(de->de_last_error || dvr_get_filesize(de) == -1) + if(de->de_last_error || dvr_get_filesize(de, 0) == -1) s = "completedError"; rerecord = de->de_dont_rerecord ? 0 : dvr_entry_get_rerecord_errors(de); if(rerecord && (de->de_errors || de->de_data_errors > rerecord)) @@ -974,15 +974,15 @@ dvr_entry_rerecord(dvr_entry_t *de) if (de->de_sched_state == DVR_COMPLETED && de->de_errors == 0 && de->de_data_errors < de->de_parent->de_data_errors) { - fsize1 = dvr_get_filesize(de); - fsize2 = dvr_get_filesize(de2); + fsize1 = dvr_get_filesize(de, DVR_FILESIZE_TOTAL); + fsize2 = dvr_get_filesize(de2, DVR_FILESIZE_TOTAL); if (fsize1 / 5 < fsize2 / 6) { goto not_so_good; } else { dvr_entry_cancel_delete(de2, 1); } } else if (de->de_sched_state == DVR_COMPLETED) { - if(dvr_get_filesize(de) == -1) { + if(dvr_get_filesize(de, 0) == -1) { delete_me: dvr_entry_cancel_delete(de, 0); dvr_entry_rerecord(de2); @@ -2542,7 +2542,7 @@ dvr_entry_class_filesize_get(void *o) dvr_entry_t *de = (dvr_entry_t *)o; if (de->de_sched_state == DVR_COMPLETED || de->de_sched_state == DVR_RECORDING) { - size = dvr_get_filesize(de); + size = dvr_get_filesize(de, DVR_FILESIZE_UPDATE); if (size < 0) size = 0; } else @@ -3079,20 +3079,31 @@ dvr_get_filename(dvr_entry_t *de) * */ int64_t -dvr_get_filesize(dvr_entry_t *de) +dvr_get_filesize(dvr_entry_t *de, int flags) { + htsmsg_field_t *f; + htsmsg_t *m; const char *filename; - struct stat st; + int first = 1; + int64_t res = 0, size; - filename = dvr_get_filename(de); - - if(filename == NULL) + if (de->de_files == NULL) return -1; - if(stat(filename, &st) != 0) - return -1; + HTSMSG_FOREACH(f, de->de_files) + if ((m = htsmsg_field_get_map(f)) != NULL) { + filename = htsmsg_get_str(m, "filename"); + if (flags & DVR_FILESIZE_UPDATE) + size = dvr_vfs_update_filename(filename, m); + else + size = htsmsg_get_s64_or_default(m, "size", -1); + if (filename && size >= 0) { + res = (flags & DVR_FILESIZE_TOTAL) ? (res + size) : size; + first = 0; + } + } - return st.st_size; + return first ? -1 : res; } /** diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 48047bdd0..c9d85ef49 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -806,7 +806,6 @@ cut1: m = htsmsg_create_map(); htsmsg_add_str(m, "filename", path); htsmsg_add_msg(de->de_files, NULL, m); - dvr_vfs_refresh_entry(de); return 0; } @@ -904,6 +903,8 @@ dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss) return -1; } + dvr_vfs_refresh_entry(de); + ss_copy = streaming_start_copy(ss); if(muxer_init(muxer, ss_copy, lang_str_get(de->de_title, NULL))) { diff --git a/src/dvr/dvr_vfsmgr.c b/src/dvr/dvr_vfsmgr.c index 882ce462f..20d91b71a 100644 --- a/src/dvr/dvr_vfsmgr.c +++ b/src/dvr/dvr_vfsmgr.c @@ -87,22 +87,24 @@ dvr_vfs_refresh_entry(dvr_entry_t *de) HTSMSG_FOREACH(f, de->de_files) if ((m = htsmsg_field_get_map(f)) != NULL) { filename = htsmsg_get_str(m, "filename"); - vfs = dvr_vfs_find(vfs, htsmsg_get_s64(m, "fsid", 0)); + vfs = dvr_vfs_find(vfs, htsmsg_get_s64_or_default(m, "fsid", 0)); if (vfs) { - size = htsmsg_get_s64(m, "size", 0); + size = htsmsg_get_s64_or_default(m, "size", 0); vfs->used_size = size <= vfs->used_size ? vfs->used_size - size : 0; } if(statvfs(filename, &vst) < 0 || stat(filename, &st) < 0) { tvhlog(LOG_ERR, "dvr", "unable to stat file '%s'", filename); - htsmsg_delete_field(m, "fsid"); - htsmsg_delete_field(m, "size"); - continue; + goto rem; } vfs = dvr_vfs_find(vfs, tvh_fsid(vst.f_fsid)); - if (vfs && st.st_size > 0) { + if (vfs && st.st_size >= 0) { htsmsg_set_s64(m, "fsid", tvh_fsid(vst.f_fsid)); htsmsg_set_s64(m, "size", st.st_size); vfs->used_size += st.st_size; + } else { +rem: + htsmsg_delete_field(m, "fsid"); + htsmsg_delete_field(m, "size"); } } } @@ -121,9 +123,9 @@ dvr_vfs_remove_entry(dvr_entry_t *de) lock_assert(&global_lock); HTSMSG_FOREACH(f, de->de_files) if ((m = htsmsg_field_get_map(f)) != NULL) { - vfs = dvr_vfs_find(vfs, htsmsg_get_s64(m, "fsid", 0)); + vfs = dvr_vfs_find(vfs, htsmsg_get_s64_or_default(m, "fsid", 0)); if (vfs) { - size = htsmsg_get_s64(m, "size", 0); + size = htsmsg_get_s64_or_default(m, "size", 0); vfs->used_size = size <= vfs->used_size ? vfs->used_size - size : 0; } htsmsg_delete_field(m, "fsid"); @@ -131,6 +133,32 @@ dvr_vfs_remove_entry(dvr_entry_t *de) } } +/* + * + */ +int64_t +dvr_vfs_update_filename(const char *filename, htsmsg_t *fdata) +{ + dvr_vfs_t *vfs; + struct stat st; + int64_t size; + + if (filename == NULL || fdata == NULL) + return -1; + vfs = dvr_vfs_find(NULL, htsmsg_get_s64_or_default(fdata, "fsid", 0)); + if (vfs) { + size = htsmsg_get_s64_or_default(fdata, "size", 0); + vfs->used_size = size <= vfs->used_size ? vfs->used_size - size : 0; + if (stat(filename, &st) >= 0 && st.st_size >= 0) { + htsmsg_set_s64(fdata, "size", st.st_size); + return st.st_size; + } + } + htsmsg_delete_field(fdata, "fsid"); + htsmsg_delete_field(fdata, "size"); + return -1; +} + /** * Cleanup old recordings for this config until the dvr_cleanup_threshold is reached * Only "Keep until space needed" recordings are deleted, starting with the oldest one @@ -196,7 +224,7 @@ dvr_disk_space_cleanup(dvr_config_t *cfg) if (dvr_entry_get_removal_days(de) != DVR_RET_SPACE) // only remove the allowed ones continue; - if (dvr_get_filename(de) == NULL || dvr_get_filesize(de) <= 0) + if (dvr_get_filename(de) == NULL || dvr_get_filesize(de, DVR_FILESIZE_TOTAL) <= 0) continue; if(statvfs(dvr_get_filename(de), &diskdata) == -1) @@ -212,7 +240,7 @@ dvr_disk_space_cleanup(dvr_config_t *cfg) } if (oldest) { - fileSize = dvr_get_filesize(oldest); + fileSize = dvr_get_filesize(oldest, DVR_FILESIZE_TOTAL); availBytes += fileSize; clearedBytes += fileSize; usedBytes -= fileSize; diff --git a/src/htsp_server.c b/src/htsp_server.c index f808a0277..8d21b2d6f 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -924,7 +924,7 @@ htsp_build_dvrentry(htsp_connection_t *htsp, dvr_entry_t *de, const char *method break; case DVR_RECORDING: s = "recording"; - fsize = dvr_get_filesize(de); + fsize = dvr_get_filesize(de, DVR_FILESIZE_UPDATE); if (de->de_rec_state == DVR_RS_ERROR || (de->de_rec_state == DVR_RS_PENDING && de->de_last_error != SM_CODE_OK)) { @@ -934,7 +934,7 @@ htsp_build_dvrentry(htsp_connection_t *htsp, dvr_entry_t *de, const char *method break; case DVR_COMPLETED: s = "completed"; - fsize = dvr_get_filesize(de); + fsize = dvr_get_filesize(de, DVR_FILESIZE_UPDATE); if (fsize < 0) error = "File missing"; else if(de->de_last_error) diff --git a/src/webui/webui.c b/src/webui/webui.c index 86ba165c6..ebb39b1c1 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -850,7 +850,7 @@ http_dvr_list_playlist(http_connection_t *hc, int pltype) htsbuf_append_str(hq, "#EXTM3U\n"); LIST_FOREACH(de, &dvrentries, de_global_link) { - fsize = dvr_get_filesize(de); + fsize = dvr_get_filesize(de, 0); if(!fsize) continue; @@ -904,7 +904,7 @@ http_dvr_playlist(http_connection_t *hc, int pltype, dvr_entry_t *de) hostpath = http_get_hostpath(hc); durration = dvr_entry_get_stop_time(de) - dvr_entry_get_start_time(de, 0); - fsize = dvr_get_filesize(de); + fsize = dvr_get_filesize(de, 0); if(fsize) { bandwidth = ((8*fsize) / (durration*1024.0)); -- 2.47.3