DVR_RET_1MONTH = (30+1),
DVR_RET_2MONTH = (60+2),
DVR_RET_3MONTH = (90+2),
- DVR_RET_6MONTH = (180+2),
+ DVR_RET_6MONTH = (180+3),
DVR_RET_1YEAR = (365+1),
DVR_RET_2YEARS = (2*365+1),
DVR_RET_3YEARS = (3*365+1),
.def.i = DVR_RET_DVRCONFIG,
.off = offsetof(dvr_autorec_entry_t, dae_removal),
.list = dvr_entry_class_removal_list,
- .opts = PO_HIDDEN | PO_EXPERT,
+ .opts = PO_HIDDEN | PO_ADVANCED,
},
{
.type = PT_U32,
dvr_autorec_get_retention_days( dvr_autorec_entry_t *dae )
{
if (dae->dae_retention > 0) {
+ if (dae->dae_retention > DVR_RET_FOREVER)
+ return DVR_RET_FOREVER;
+
uint32_t removal = dvr_autorec_get_removal_days(dae);
/* As we need the db entry when deleting the file on disk */
if (removal != DVR_RET_FOREVER && removal > dae->dae_retention)
uint32_t
dvr_autorec_get_removal_days( dvr_autorec_entry_t *dae )
{
- if (dae->dae_removal > 0)
+ if (dae->dae_removal > 0) {
+ if (dae->dae_removal > DVR_RET_FOREVER)
+ return DVR_RET_FOREVER;
+
return dae->dae_removal;
+ }
return dvr_retention_cleanup(dae->dae_config->dvr_removal_days);
}
cfg->dvr_warm_time = 30;
cfg->dvr_update_window = 24 * 3600;
cfg->dvr_pathname = strdup("$t$n.$x");
- cfg->dvr_cleanup_threshold_free = 200;
- cfg->dvr_cleanup_threshold_used = 2000;
+ cfg->dvr_cleanup_threshold_free = 1000; // keep 1000 MiB of free space on disk by default
+ cfg->dvr_cleanup_threshold_used = 0; // disabled
/* Muxer config */
cfg->dvr_muxcnf.m_cache = MC_CACHE_DONTKEEP;
dvr_config_storage_check(cfg);
if (cfg->dvr_cleanup_threshold_free < 50)
cfg->dvr_cleanup_threshold_free = 50; // as checking is only periodically, lower is not save
- if (cfg->dvr_cleanup_threshold_used < cfg->dvr_cleanup_threshold_used)
- cfg->dvr_cleanup_threshold_used = cfg->dvr_cleanup_threshold_free + 50;
if (cfg->dvr_removal_days != DVR_RET_FOREVER &&
cfg->dvr_removal_days > cfg->dvr_retention_days)
cfg->dvr_retention_days = DVR_RET_ONREMOVE;
+ if (cfg->dvr_removal_days > DVR_RET_FOREVER)
+ cfg->dvr_removal_days = DVR_RET_FOREVER;
+ if (cfg->dvr_retention_days > DVR_RET_FOREVER)
+ cfg->dvr_retention_days = DVR_RET_FOREVER;
idnode_save(&cfg->dvr_id, m);
hts_settings_save(m, "dvr/config/%s", idnode_uuid_as_sstr(&cfg->dvr_id));
htsmsg_destroy(m);
{ N_("3 months"), DVR_RET_3MONTH },
{ N_("6 months"), DVR_RET_6MONTH },
{ N_("1 year"), DVR_RET_1YEAR },
+ { N_("2 years"), DVR_RET_2YEARS },
+ { N_("3 years"), DVR_RET_3YEARS },
{ N_("Maintained space"), DVR_RET_SPACE },
{ N_("Forever"), DVR_RET_FOREVER },
};
.off = offsetof(dvr_config_t, dvr_retention_days),
.def.u32 = DVR_RET_ONREMOVE,
.list = dvr_config_class_retention_list,
+ .opts = PO_EXPERT,
.group = 1,
},
{
{
.type = PT_U32,
.id = "storage-mfree",
- .name = N_("Maintain free storage space (MiB)"),
+ .name = N_("Maintain free storage space in MiB"),
.off = offsetof(dvr_config_t, dvr_cleanup_threshold_free),
- .def.i = 200,
+ .def.i = 1000,
+ .opts = PO_ADVANCED,
.group = 2,
},
{
.type = PT_U32,
.id = "storage-mused",
- .name = N_("Maintain used storage space (MiB)"),
+ .name = N_("Maintain used storage space in MiB (0=disabled)"),
.off = offsetof(dvr_config_t, dvr_cleanup_threshold_used),
- .def.i = 2000,
+ .def.i = 0,
+ .opts = PO_EXPERT,
.group = 2,
},
{
dvr_entry_get_retention_days( dvr_entry_t *de )
{
if (de->de_retention > 0) {
+ if (de->de_retention > DVR_RET_FOREVER)
+ return DVR_RET_FOREVER;
+
/* As we need the db entry when deleting the file on disk */
if (dvr_entry_get_removal_days(de) != DVR_RET_FOREVER &&
dvr_entry_get_removal_days(de) > de->de_retention)
uint32_t
dvr_entry_get_removal_days ( dvr_entry_t *de )
{
- if (de->de_removal > 0)
+ if (de->de_removal > 0) {
+ if (de->de_removal > DVR_RET_FOREVER)
+ return DVR_RET_FOREVER;
+
return de->de_removal;
+ }
return dvr_retention_cleanup(de->de_config->dvr_removal_days);
}
{ N_("3 months"), DVR_RET_3MONTH },
{ N_("6 months"), DVR_RET_6MONTH },
{ N_("1 year"), DVR_RET_1YEAR },
+ { N_("2 years"), DVR_RET_2YEARS },
+ { N_("3 years"), DVR_RET_3YEARS },
{ N_("On file removal"), DVR_RET_ONREMOVE },
{ N_("Forever"), DVR_RET_FOREVER },
};
{ N_("3 months"), DVR_RET_3MONTH },
{ N_("6 months"), DVR_RET_6MONTH },
{ N_("1 year"), DVR_RET_1YEAR },
+ { N_("2 years"), DVR_RET_2YEARS },
+ { N_("3 years"), DVR_RET_3YEARS },
{ N_("Maintained space"), DVR_RET_SPACE },
{ N_("Forever"), DVR_RET_FOREVER },
};
.off = offsetof(dvr_entry_t, de_retention),
.def.i = DVR_RET_DVRCONFIG,
.list = dvr_entry_class_retention_list,
- .opts = PO_HIDDEN | PO_ADVANCED
+ .opts = PO_HIDDEN | PO_EXPERT
},
{
.type = PT_U32,
.def.i = DVR_RET_DVRCONFIG,
.off = offsetof(dvr_timerec_entry_t, dte_removal),
.list = dvr_entry_class_removal_list,
- .opts = PO_EXPERT
+ .opts = PO_ADVANCED
},
{
.type = PT_STR,
dvr_timerec_get_retention_days( dvr_timerec_entry_t *dte )
{
if (dte->dte_retention > 0) {
+ if (dte->dte_retention > DVR_RET_FOREVER)
+ return DVR_RET_FOREVER;
+
/* As we need the db entry when deleting the file on disk */
if (dvr_timerec_get_removal_days(dte) != DVR_RET_FOREVER &&
dvr_timerec_get_removal_days(dte) > dte->dte_retention)
uint32_t
dvr_timerec_get_removal_days( dvr_timerec_entry_t *dte )
{
- if (dte->dte_removal > 0)
+ if (dte->dte_removal > 0) {
+ if (dte->dte_removal > DVR_RET_FOREVER)
+ return DVR_RET_FOREVER;
+
return dte->dte_removal;
+ }
return dvr_retention_cleanup(dte->dte_config->dvr_removal_days);
}
return -1;
}
- tvhlog(LOG_INFO, "dvr","disk space cleanup for config \"%s\", required/current free space \"%"PRId64"/%"PRId64" MiB\", required/current used space \"%"PRId64"/%"PRId64" MB\"",
+ tvhlog(LOG_INFO, "dvr","disk space cleanup for config \"%s\", required/current free space \"%"PRId64"/%"PRId64" MiB\", required/current used space \"%"PRId64"/%"PRId64" MiB\"",
configName, TOMIB(requiredBytes), TOMIB(availBytes), TOMIB(maximalBytes), TOMIB(usedBytes));
- while (availBytes < requiredBytes || maximalBytes < usedBytes) {
+ while (availBytes < requiredBytes || ((maximalBytes < usedBytes) && cfg->dvr_cleanup_threshold_used)) {
oldest = NULL;
stoptime = dispatch_clock;
requiredBytes = MIB(cfg->dvr_cleanup_threshold_free);
maximalBytes = MIB(cfg->dvr_cleanup_threshold_used);
- if (availBytes < requiredBytes || maximalBytes > usedBytes) {
+ if (availBytes < requiredBytes || ((maximalBytes < usedBytes) && cfg->dvr_cleanup_threshold_used)) {
LIST_FOREACH(de, &dvrentries, de_global_link) {
/* only start cleanup if we are actually writing files right now */
if (de->de_sched_state != DVR_RECORDING || !de->de_config || de->de_config != cfg)
- goto checking;
+ continue;
if (availBytes < requiredBytes) {
tvhlog(LOG_WARNING, "dvr","running out of free disk space for dvr config \"%s\", required free space \"%"PRId64" MiB\", current free space \"%"PRId64" MiB\"",
/* only cleanup one directory at the time as the system needs time to delete the actual files */
dvr_disk_space_cleanup(de->de_config);
cleanupDone = 1;
- dvr_disk_space_config_idx = idx + 1;
+ dvr_disk_space_config_idx = idx;
break;
}
+ if (!cleanupDone)
+ goto checking;
} else {
checking:
tvhlog(LOG_DEBUG, "dvr","checking free and used disk space for config \"%s\" : OK",