|
← Revision 17 as of 2011-08-05 07:41:40
Size: 7199
Comment:
|
← Revision 18 as of 2011-08-26 04:10:17
Size: 7201
Comment: converted to 1.6 markup
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 6: | Line 6: |
| * '''Launchpad entry''': [https://launchpad.net/products/upstart/+spec/replace-cron] | * '''Launchpad entry''': [[https://launchpad.net/products/upstart/+spec/replace-cron]] |
Please check the status of this specification in Launchpad before editing it. If it is Approved, contact the Assignee or another knowledgeable person before making changes.
Launchpad entry: https://launchpad.net/products/upstart/+spec/replace-cron
Summary
This long-term goal of "upstart" is to act as a replacement for _nearly_ all job control services (e.g. init, inetd, cron, anacron, at). This specification proposes how the cron/anacron replacement functionality will work.
Rationale
This will permit jobs (aka services) to be run at a specific time or date.
- Why do we want to do this?
- To create a consistent system for starting services and jobs timed or otherwise.
- What advantage would 'upstart' have over 'cron'?
- It could start timed jobs only when necessary.
- Doesn't this make 'upstart' overly complex?
- No, the only change that is needed is another event type.
Use cases
- A backup system could be started on a specific time but only if the (necessary) filesystem is mounted. Otherwise it will skip its backup round.
Scope
This scope of this specification is limited to job definition and events.
Design
Initial version:
- There would be a new sort of event.
on time TIME=hh:mm DAY_OF_WEEK=dow DATE=mm/dd/yy to start a job on a specific time/date
Cron compatibility
A new cron event
on cron MINUTE=mm HOUR=hh DOM=dd MONTH=mm DOW=w
- This allows a script to use normal cron times because of pattern matching
End version:
- There would be a new sort of event.
on every ... to specify repeating events
on every hour on every monday on every year
on time hh:mm, on date mm/dd/yy, on day-of-week to define a specific time/date.
on time 12:00 # every day on date 10/12/12 # once in a lifetime a full day on day-of-week 1 # every sunday
A time/date definition could have the special * character to define any...
on time *:30 # every hour (on every day) on date 10/12/* # every year a full day on date */*/* # every day a full day
A time/date definition could have a range [1-3] to define multiple values.
on time [0-12]:00 # every hour AM (on every day)
A time/date definition could have a list {1,2,4} to define multiple non-continuous values.
on time *:{0,30} # every half an hour (on every day) on time {0:00,6:00,12:00,18:00} # every six hours
... at hh:mm, ... at mm/dd/yy, ... at monday... to allow combinations:
on every day at 12:00 on every year at monday # a full day on every year at monday at 5:{0,30}
A time hh:mm or at hh:mm event will only happen for a minute (or its logical range), unless or later or or earlier is specified
on every day at 12:00 or later # not before 12:00 on every day at 6:00 or earlier # not after 6:00
Implementation
Code
events.h
Added:
1 /**
2 * TIME_EVENT:
3 *
4 * Name of the event we generate every minute, which includes arguments and
5 * environment indictating when the event was generated.
6 **/
7 #define TIME_EVENT "time"
8
main.c main()
Modified:
1 /* Process the event queue each time through the main loop */
2 NIH_MUST (nih_main_loop_add_func (NULL, (NihMainLoopCb)event_poll,
3 NULL));
4
5 + /* Initialize the timers */
6 + nih_timer_init();
7
8 /* Read configuration */
9 NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE));
10 NIH_MUST (conf_source_new (NULL, CONFDIR, CONF_JOB_DIR));
11
1 m /* Generate and run the startup and time event or read the state from the
2 * init daemon that exec'd us
3 */
4 if (! restart) {
5 NIH_MUST (event_new (NULL, STARTUP_EVENT, NULL));
6 + timer_handler(NULL,NULL);
7 } else {
8 sigset_t mask;
9
10 /* We're ok to receive signals again */
11 sigemptyset (&mask);
12 sigprocmask (SIG_SETMASK, &mask, NULL);
13 }
14
Added:
1 /**
2 * timer_handler:
3 * @data: an integer which specifies the timer phase: initial, next minute, every minute,
4 * @timer: timer that called this handler.
5 *
6 * Handle having recieved the minute-wise timer event, which we use to
7 * generate a TIME event.
8 **/
9 static void
10 timer_handler (void *data,
11 NihTimer *timer)
12 {
13 nih_local char **env = NULL;
14 size_t len;
15 time_t rawtime;
16 struct tm *timeinfo;
17
18 /* Get the current time and splice it */
19 time ( &rawtime );
20 timeinfo = localtime ( &rawtime );
21
22 len = 0;
23 env = NIH_MUST (nih_str_array_new (NULL));
24
25 /* Add the fields in the correct order: TIME DOW DATE */
26 NIH_MUST (environ_set (&env, NULL, &len, TRUE,
27 "TIME=%.2d:%.2d", timeinfo->tm_hour,timeinfo->tm_min));
28 NIH_MUST (environ_set (&env, NULL, &len, TRUE,
29 "DAY_OF_WEEK=%.1d", timeinfo->tm_wday+1));
30 NIH_MUST (environ_set (&env, NULL, &len, TRUE,
31 "DATE=%.2d/%.2d/%.4d", timeinfo->tm_mon+1,timeinfo->tm_mday,timeinfo->tm_year+1900));
32
33 NIH_MUST (event_new (NULL, TIME_EVENT, env));
34
35 /* Check the run cycle */
36 if(data == (void*)0)
37 {
38 /* Start at next minute a new time event */
39 NihTimer *timer = nih_timer_add_timeout(NULL, 61 - (rawtime % 60), timer_handler,
40 (void*)1);
41 }
42 if(data == (void*)1)
43 {
44 /* Every minute a new time event */
45 NihTimer *timer = nih_timer_add_periodic(NULL, 60, timer_handler,
46 (void*)2);
47 }
48 /* if(data == (void*)2) Do nothing */
49 }
50
Data preservation and migration
These changes are backwards compatible with the previous behaviour
Unresolved issues