Differences between revisions 17 and 18
Revision 17 as of 2011-08-05 07:41:40
Size: 7199
Editor: daniel-sonck
Comment:
Revision 18 as of 2011-08-26 04:10:17
Size: 7201
Editor: localhost
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.

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


ReplaceCron (last edited 2011-08-26 04:10:17 by localhost)