On Sun, May 11, 2014 at 07:53:55PM +0400, Alexander Bashmakov wrote: > Issue was rised in this thread: > https://mailman.archlinux.org/pipermail/arch-general/2014-May/036162.html > > Disclaimer: > I almost have no expereince in C. > So this patch can contain some silly mistakes. But it 'works for me'. > Please consider it as RFC. > > -8<------- > Cron-like timers are useful for maintenance tasks > and already used in some distros by default. > But midnight is not best time for this. > Just add a new option allowing user to specify > activation time (and date) for such timers globally.
"daily" is just syntactic sugar for "*-*-* 00:00:00". If you don't want to run at midnight, modify the normalized form to run at the time you want. > Signed-off-by: Alexander Bashmakov <pkunk...@gmail.com> > --- > man/systemd-system.conf.xml | 19 +++++++++++++ > man/systemd.time.xml | 6 ++++- > src/core/load-fragment.c | 2 +- > src/core/main.c | 7 +++++ > src/core/manager.c | 42 +++++++++++++++++++++++++++++ > src/core/manager.h | 4 +++ > src/core/system.conf | 1 + > src/core/user.conf | 1 + > src/shared/calendarspec.c | 64 > +++++++++++++++++++++++++++++++------------- > src/shared/calendarspec.h | 4 ++- > src/test/test-calendarspec.c | 20 +++++++++----- > 11 files changed, 141 insertions(+), 29 deletions(-) > > diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml > index 3814bd2..e38e70a 100644 > --- a/man/systemd-system.conf.xml > +++ b/man/systemd-system.conf.xml > @@ -302,6 +302,25 @@ > </varlistentry> > > <varlistentry> > + > <term><varname>DefaultTimerEventTime=</varname></term> > + > + <listitem><para>Sets the default > + elapsing time for cron-like timer units. > + This controls > + the global default for > + timer units with > + <varname>OnCalendar=</varname> > + set on > + <literal>hourly</literal>, > <literal>daily</literal>, > + <literal>monthly</literal>, > <literal>yearly</literal> > + or <literal>weekly</literal>. > + Only relevant fields are used. > + See > + > <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>5</manvolnum></citerefentry> > + for details.</para></listitem> > + </varlistentry> > + > + <varlistentry> > > <term><varname>DefaultCPUQuotaPeriodSec=</varname></term> > > <listitem><para>Sets the default CPU > diff --git a/man/systemd.time.xml b/man/systemd.time.xml > index 0706cdf..776b6bf 100644 > --- a/man/systemd.time.xml > +++ b/man/systemd.time.xml > @@ -248,7 +248,11 @@ > <literal>*-*-* *:00:00</literal>, <literal>*-*-* > 00:00:00</literal>, <literal>*-*-01 00:00:00</literal> and > <literal>Mon *-*-* 00:00:00</literal>, > - respectively.</para> > + respectively. > + Note that exact time for these expressions depends on > + <varname>DefaultTimerEventTime=</varname> > + setting. > + </para> > > <para>Examples for valid timestamps and their > normalized form:</para> > diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c > index 14c194b..7f9d71f 100644 > --- a/src/core/load-fragment.c > +++ b/src/core/load-fragment.c > @@ -1273,7 +1273,7 @@ int config_parse_timer(const char *unit, > } > > if (b == TIMER_CALENDAR) { > - if (calendar_spec_from_string(rvalue, &c) < 0) { > + if (calendar_spec_from_string(rvalue, &c, > t->meta.manager->default_timer_event_time) < 0) { > log_syntax(unit, LOG_ERR, filename, line, EINVAL, > "Failed to parse calendar specification, > ignoring: %s", > rvalue); > diff --git a/src/core/main.c b/src/core/main.c > index c1b0ffd..78c9711 100644 > --- a/src/core/main.c > +++ b/src/core/main.c > @@ -109,6 +109,7 @@ static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = > {}; > static uint64_t arg_capability_bounding_set_drop = 0; > static nsec_t arg_timer_slack_nsec = (nsec_t) -1; > static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE; > +static char* arg_default_timer_event_time = NULL; > static usec_t arg_default_cpu_quota_period_usec = 100 * USEC_PER_MSEC; > static Set* arg_syscall_archs = NULL; > static FILE* arg_serialization = NULL; > @@ -684,6 +685,7 @@ static int parse_config_file(void) { > #endif > { "Manager", "TimerSlackNSec", config_parse_nsec, > 0, &arg_timer_slack_nsec }, > { "Manager", "DefaultTimerAccuracySec", config_parse_sec, > 0, &arg_default_timer_accuracy_usec }, > + { "Manager", "DefaultTimerEventTime", > config_parse_string, 0, &arg_default_timer_event_time }, > { "Manager", "DefaultCPUQuotaPeriodSec", config_parse_sec, > 0, &arg_default_cpu_quota_period_usec }, > { "Manager", "DefaultStandardOutput", > config_parse_output, 0, &arg_default_std_output }, > { "Manager", "DefaultStandardError", > config_parse_output, 0, &arg_default_std_error }, > @@ -1619,6 +1621,11 @@ int main(int argc, char *argv[]) { > > m->confirm_spawn = arg_confirm_spawn; > m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec; > + > + r = manager_set_default_timer_event_time(m, > arg_default_timer_event_time); > + if (r < 0) > + goto finish; > + > m->default_cpu_quota_period_usec = arg_default_cpu_quota_period_usec; > m->default_std_output = arg_default_std_output; > m->default_std_error = arg_default_std_error; > diff --git a/src/core/manager.c b/src/core/manager.c > index 5772f40..b2d31eb 100644 > --- a/src/core/manager.c > +++ b/src/core/manager.c > @@ -429,6 +429,11 @@ int manager_new(SystemdRunningAs running_as, Manager > **_m) { > m->running_as = running_as; > m->exit_code = _MANAGER_EXIT_CODE_INVALID; > m->default_timer_accuracy_usec = USEC_PER_MINUTE; > + > + r = manager_set_default_timer_event_time(m, NULL); > + if (r < 0) > + goto fail; > + > m->default_cpu_quota_period_usec = 100 * USEC_PER_MSEC; > > m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = > m->idle_pipe[3] = -1; > @@ -821,6 +826,8 @@ void manager_free(Manager *m) { > hashmap_free(m->cgroup_unit); > set_free_free(m->unit_path_cache); > > + calendar_spec_free(m->default_timer_event_time); > + > free(m->switch_root); > free(m->switch_root_init); > > @@ -2720,6 +2727,41 @@ int manager_environment_add(Manager *m, char **minus, > char **plus) { > return 0; > } > > +int manager_set_default_timer_event_time(Manager *m, const char > *default_event_time) { > + int r; > + > + assert(m); > + CalendarSpec *c; > + > + if (isempty(default_event_time) > + || strcaseeq(default_event_time, "hourly") > + || strcaseeq(default_event_time, "daily") > + || strcaseeq(default_event_time, "weekly") > + || strcaseeq(default_event_time, "monthly") > + || strcaseeq(default_event_time, "anually") > + || strcaseeq(default_event_time, "yearly")) { > + > + c = new0(CalendarSpec, 1); > + if (!c) > + return -ENOMEM; > + > + r = calendar_spec_default(c); > + if (r < 0) > + goto fail; > + } else { > + r = calendar_spec_from_string(default_event_time, &c, NULL); > + if (r < 0) > + goto fail; > + } > + > + m->default_timer_event_time = c; > + return 0; > + > +fail: > + calendar_spec_free(c); > + return r; > +} > + > int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { > int i; > > diff --git a/src/core/manager.h b/src/core/manager.h > index a3de351..3dc570b 100644 > --- a/src/core/manager.h > +++ b/src/core/manager.h > @@ -29,6 +29,7 @@ > #include "sd-event.h" > #include "fdset.h" > #include "cgroup-util.h" > +#include "calendarspec.h" > > /* Enforce upper limit how many names we allow */ > #define MANAGER_MAX_NAMES 131072 /* 128K */ > @@ -244,6 +245,8 @@ struct Manager { > > usec_t default_timer_accuracy_usec; > > + CalendarSpec *default_timer_event_time; > + > struct rlimit *rlimit[_RLIMIT_MAX]; > > /* non-zero if we are reloading or reexecuting, */ > @@ -301,6 +304,7 @@ void manager_clear_jobs(Manager *m); > unsigned manager_dispatch_load_queue(Manager *m); > > int manager_environment_add(Manager *m, char **minus, char **plus); > +int manager_set_default_timer_event_time(Manager *m, const char > *default_event_time); > int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit); > > int manager_loop(Manager *m); > diff --git a/src/core/system.conf b/src/core/system.conf > index 4d775fa..3ef8b1b 100644 > --- a/src/core/system.conf > +++ b/src/core/system.conf > @@ -24,6 +24,7 @@ > #SystemCallArchitectures= > #TimerSlackNSec= > #DefaultTimerAccuracySec=1min > +#DefaultTimerEventTime= > #DefaultCPUQuotaPeriodSec=100ms > #DefaultStandardOutput=journal > #DefaultStandardError=inherit > diff --git a/src/core/user.conf b/src/core/user.conf > index 8c7ecde..c108722 100644 > --- a/src/core/user.conf > +++ b/src/core/user.conf > @@ -15,6 +15,7 @@ > #SystemCallArchitectures= > #TimerSlackNSec= > #DefaultTimerAccuracySec=1min > +#DefaultTimerEventTime= > #DefaultStandardOutput=inherit > #DefaultStandardError=inherit > #DefaultTimeoutStartSec=90s > diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c > index 69b7427..7720cf6 100644 > --- a/src/shared/calendarspec.c > +++ b/src/shared/calendarspec.c > @@ -639,7 +639,7 @@ fail: > return r; > } > > -int calendar_spec_from_string(const char *p, CalendarSpec **spec) { > +int calendar_spec_from_string(const char *p, CalendarSpec **spec, const > CalendarSpec *d) { > CalendarSpec *c; > int r; > > @@ -654,66 +654,66 @@ int calendar_spec_from_string(const char *p, > CalendarSpec **spec) { > return -ENOMEM; > > if (strcaseeq(p, "hourly")) { > - r = const_chain(0, &c->minute); > + r = const_chain(d->minute->value, &c->minute); > if (r < 0) > goto fail; > - r = const_chain(0, &c->second); > + r = const_chain(d->second->value, &c->second); > if (r < 0) > goto fail; > > } else if (strcaseeq(p, "daily")) { > - r = const_chain(0, &c->hour); > + r = const_chain(d->hour->value, &c->hour); > if (r < 0) > goto fail; > - r = const_chain(0, &c->minute); > + r = const_chain(d->minute->value, &c->minute); > if (r < 0) > goto fail; > - r = const_chain(0, &c->second); > + r = const_chain(d->second->value, &c->second); > if (r < 0) > goto fail; > > } else if (strcaseeq(p, "monthly")) { > - r = const_chain(1, &c->day); > + r = const_chain(d->day->value, &c->day); > if (r < 0) > goto fail; > - r = const_chain(0, &c->hour); > + r = const_chain(d->hour->value, &c->hour); > if (r < 0) > goto fail; > - r = const_chain(0, &c->minute); > + r = const_chain(d->minute->value, &c->minute); > if (r < 0) > goto fail; > - r = const_chain(0, &c->second); > + r = const_chain(d->second->value, &c->second); > if (r < 0) > goto fail; > > } else if (strcaseeq(p, "anually") || strcaseeq(p, "yearly")) { > - r = const_chain(1, &c->month); > + r = const_chain(d->month->value, &c->month); > if (r < 0) > goto fail; > - r = const_chain(1, &c->day); > + r = const_chain(d->day->value, &c->day); > if (r < 0) > goto fail; > - r = const_chain(0, &c->hour); > + r = const_chain(d->hour->value, &c->hour); > if (r < 0) > goto fail; > - r = const_chain(0, &c->minute); > + r = const_chain(d->minute->value, &c->minute); > if (r < 0) > goto fail; > - r = const_chain(0, &c->second); > + r = const_chain(d->second->value, &c->second); > if (r < 0) > goto fail; > > } else if (strcaseeq(p, "weekly")) { > > - c->weekdays_bits = 1; > + c->weekdays_bits = d->weekdays_bits; > > - r = const_chain(0, &c->hour); > + r = const_chain(d->hour->value, &c->hour); > if (r < 0) > goto fail; > - r = const_chain(0, &c->minute); > + r = const_chain(d->minute->value, &c->minute); > if (r < 0) > goto fail; > - r = const_chain(0, &c->second); > + r = const_chain(d->second->value, &c->second); > if (r < 0) > goto fail; > > @@ -919,6 +919,32 @@ static int find_next(const CalendarSpec *spec, struct tm > *tm) { > } > } > > +int calendar_spec_default(CalendarSpec *c) { > + int r; > + > + assert(c); > + > + c->weekdays_bits = 1; > + > + r = const_chain(1, &c->month); > + if (r < 0) > + return r; > + r = const_chain(1, &c->day); > + if (r < 0) > + return r; > + r = const_chain(0, &c->hour); > + if (r < 0) > + return r; > + r = const_chain(0, &c->minute); > + if (r < 0) > + return r; > + r = const_chain(0, &c->second); > + if (r < 0) > + return r; > + > + return 0; > +} > + > int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t > *next) { > struct tm tm; > time_t t; > diff --git a/src/shared/calendarspec.h b/src/shared/calendarspec.h > index 7baf318..7415455 100644 > --- a/src/shared/calendarspec.h > +++ b/src/shared/calendarspec.h > @@ -52,6 +52,8 @@ int calendar_spec_normalize(CalendarSpec *spec); > bool calendar_spec_valid(CalendarSpec *spec); > > int calendar_spec_to_string(const CalendarSpec *spec, char **p); > -int calendar_spec_from_string(const char *p, CalendarSpec **spec); > +int calendar_spec_from_string(const char *p, CalendarSpec **spec, const > CalendarSpec *d); > + > +int calendar_spec_default(CalendarSpec *c); > > int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t > *next); > diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c > index 21b0024..4660032 100644 > --- a/src/test/test-calendarspec.c > +++ b/src/test/test-calendarspec.c > @@ -25,13 +25,18 @@ > #include "util.h" > > static void test_one(const char *input, const char *output) { > - CalendarSpec *c; > + CalendarSpec *c, *d; > _cleanup_free_ char *p = NULL, *q = NULL; > usec_t u; > char buf[FORMAT_TIMESTAMP_MAX]; > int r; > > - assert_se(calendar_spec_from_string(input, &c) >= 0); > + d = new0(CalendarSpec, 1); > + assert_se(d); > + r = calendar_spec_default(d); > + assert_se(r >= 0); > + > + assert_se(calendar_spec_from_string(input, &c, d) >= 0); > > assert_se(calendar_spec_to_string(c, &p) >= 0); > printf("\"%s\" → \"%s\"\n", input, p); > @@ -43,9 +48,10 @@ static void test_one(const char *input, const char > *output) { > printf("Next: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, > sizeof(buf), u)); > calendar_spec_free(c); > > - assert_se(calendar_spec_from_string(p, &c) >= 0); > + assert_se(calendar_spec_from_string(p, &c, d) >= 0); > assert_se(calendar_spec_to_string(c, &q) >= 0); > calendar_spec_free(c); > + calendar_spec_free(d); > > assert_se(streq(q, p)); > } > @@ -79,10 +85,10 @@ int main(int argc, char* argv[]) { > test_one("weekly", "Mon *-*-* 00:00:00"); > test_one("*:2/3", "*-*-* *:02/3:00"); > > - assert_se(calendar_spec_from_string("test", &c) < 0); > - assert_se(calendar_spec_from_string("", &c) < 0); > - assert_se(calendar_spec_from_string("7", &c) < 0); > - assert_se(calendar_spec_from_string("121212:1:2", &c) < 0); > + assert_se(calendar_spec_from_string("test", &c, NULL) < 0); > + assert_se(calendar_spec_from_string("", &c, NULL) < 0); > + assert_se(calendar_spec_from_string("7", &c, NULL) < 0); > + assert_se(calendar_spec_from_string("121212:1:2", &c, NULL) < 0); > > return 0; > } > -- > 1.9.2 > > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel