Author: sobomax
Date: Mon Oct 15 08:21:49 2012
New Revision: 241576
URL: http://svn.freebsd.org/changeset/base/241576

Log:
  Add per-second scheduling into the cron(8). Right now it's
  only available via the new @every_second shortcut. ENOTIME to
  implement crontab(5) format extensions to allow more flexible
  scheduling.
  
  In order to address some concerns expressed by Terry Lambert
  while discussing the topic few years ago, about per-second cron
  possibly causing some bad effects on /etc/crontab by stat()ing
  it every second instead of every minute now (i.e. atime update),
  only check that database needs to be reloaded on every 60-th
  loop run. This should be close enough to the current behaviour.
  
  Add "@every_minute" shortcut while I am here.
  
  MFC after:    1 month

Modified:
  head/usr.sbin/cron/cron/cron.c
  head/usr.sbin/cron/cron/cron.h
  head/usr.sbin/cron/crontab/crontab.5
  head/usr.sbin/cron/lib/entry.c

Modified: head/usr.sbin/cron/cron/cron.c
==============================================================================
--- head/usr.sbin/cron/cron/cron.c      Mon Oct 15 07:57:55 2012        
(r241575)
+++ head/usr.sbin/cron/cron/cron.c      Mon Oct 15 08:21:49 2012        
(r241576)
@@ -98,6 +98,7 @@ main(argc, argv)
        char    *argv[];
 {
        cron_db database;
+       int runnum;
 
        ProgramName = argv[0];
 
@@ -149,21 +150,24 @@ main(argc, argv)
        load_database(&database);
        run_reboot_jobs(&database);
        cron_sync();
+       runnum = 0;
        while (TRUE) {
 # if DEBUGGING
            /* if (!(DebugFlags & DTEST)) */
 # endif /*DEBUGGING*/
                        cron_sleep(&database);
 
-               load_database(&database);
+               if (runnum % 60 == 0)
+                       load_database(&database);
 
                /* do this iteration
                 */
                cron_tick(&database);
 
-               /* sleep 1 minute
+               /* sleep 1 second
                 */
-               TargetTime += 60;
+               TargetTime += 1;
+               runnum += 1;
        }
 }
 
@@ -194,22 +198,23 @@ cron_tick(db)
        static time_t   diff = 0, /* time difference in seconds from the last 
offset change */
                difflimit = 0; /* end point for the time zone correction */
        struct tm       otztm; /* time in the old time zone */
-       int             otzminute, otzhour, otzdom, otzmonth, otzdow;
+       int             otzsecond, otzminute, otzhour, otzdom, otzmonth, otzdow;
        register struct tm      *tm = localtime(&TargetTime);
-       register int            minute, hour, dom, month, dow;
+       register int            second, minute, hour, dom, month, dow;
        register user           *u;
        register entry          *e;
 
        /* make 0-based values out of these so we can use them as indicies
         */
+       second = tm->tm_sec -FIRST_SECOND;
        minute = tm->tm_min -FIRST_MINUTE;
        hour = tm->tm_hour -FIRST_HOUR;
        dom = tm->tm_mday -FIRST_DOM;
        month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH;
        dow = tm->tm_wday -FIRST_DOW;
 
-       Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d)\n",
-               getpid(), minute, hour, dom, month, dow))
+       Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d,%d)\n",
+               getpid(), second, minute, hour, dom, month, dow))
 
        if (dst_enabled && last_time != 0 
        && TargetTime > last_time /* exclude stepping back */
@@ -262,6 +267,7 @@ cron_tick(db)
 
                        /* make 0-based values out of these so we can use them 
as indicies
                         */
+                       otzsecond = otztm.tm_sec -FIRST_SECOND;
                        otzminute = otztm.tm_min -FIRST_MINUTE;
                        otzhour = otztm.tm_hour -FIRST_HOUR;
                        otzdom = otztm.tm_mday -FIRST_DOM;
@@ -283,7 +289,8 @@ cron_tick(db)
                                          e->uid, e->gid, e->cmd))
 
                        if ( diff != 0 && (e->flags & (RUN_AT|NOT_UNTIL)) ) {
-                               if (bit_test(e->minute, otzminute)
+                               if (bit_test(e->second, otzsecond)
+                                && bit_test(e->minute, otzminute)
                                 && bit_test(e->hour, otzhour)
                                 && bit_test(e->month, otzmonth)
                                 && ( ((e->flags & DOM_STAR) || (e->flags & 
DOW_STAR))
@@ -302,7 +309,8 @@ cron_tick(db)
                                        continue;
                        }
 
-                       if (bit_test(e->minute, minute)
+                       if (bit_test(e->second, second)
+                        && bit_test(e->minute, minute)
                         && bit_test(e->hour, hour)
                         && bit_test(e->month, month)
                         && ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))

Modified: head/usr.sbin/cron/cron/cron.h
==============================================================================
--- head/usr.sbin/cron/cron/cron.h      Mon Oct 15 07:57:55 2012        
(r241575)
+++ head/usr.sbin/cron/cron/cron.h      Mon Oct 15 08:21:49 2012        
(r241576)
@@ -124,6 +124,10 @@
                         LineNumber = ln; \
                        }
 
+#define        FIRST_SECOND    0
+#define        LAST_SECOND     59
+#define        SECOND_COUNT    (LAST_SECOND - FIRST_SECOND + 1)
+
 #define        FIRST_MINUTE    0
 #define        LAST_MINUTE     59
 #define        MINUTE_COUNT    (LAST_MINUTE - FIRST_MINUTE + 1)
@@ -165,6 +169,7 @@ typedef     struct _entry {
 #endif
        char            **envp;
        char            *cmd;
+       bitstr_t        bit_decl(second, SECOND_COUNT);
        bitstr_t        bit_decl(minute, MINUTE_COUNT);
        bitstr_t        bit_decl(hour,   HOUR_COUNT);
        bitstr_t        bit_decl(dom,    DOM_COUNT);

Modified: head/usr.sbin/cron/crontab/crontab.5
==============================================================================
--- head/usr.sbin/cron/crontab/crontab.5        Mon Oct 15 07:57:55 2012        
(r241575)
+++ head/usr.sbin/cron/crontab/crontab.5        Mon Oct 15 08:21:49 2012        
(r241576)
@@ -232,6 +232,8 @@ string              meaning
 @daily         Run once a day, "0 0 * * *".
 @midnight      (same as @daily)
 @hourly                Run once an hour, "0 * * * *".
+@every_minute  Run once a minute, "*/1 * * * *".
+@every_second  Run once a second.
 .Ed
 .Sh EXAMPLE CRON FILE
 .Bd -literal

Modified: head/usr.sbin/cron/lib/entry.c
==============================================================================
--- head/usr.sbin/cron/lib/entry.c      Mon Oct 15 07:57:55 2012        
(r241575)
+++ head/usr.sbin/cron/lib/entry.c      Mon Oct 15 08:21:49 2012        
(r241576)
@@ -151,6 +151,7 @@ load_entry(file, error_func, pw, envp)
                        e->flags |= WHEN_REBOOT;
                } else if (!strcmp("yearly", cmd) || !strcmp("annually", cmd)){
                        Debug(DPARS, ("load_entry()...yearly shortcut\n"))
+                       bit_set(e->second, 0);
                        bit_set(e->minute, 0);
                        bit_set(e->hour, 0);
                        bit_set(e->dom, 0);
@@ -159,6 +160,7 @@ load_entry(file, error_func, pw, envp)
                        e->flags |= DOW_STAR;
                } else if (!strcmp("monthly", cmd)) {
                        Debug(DPARS, ("load_entry()...monthly shortcut\n"))
+                       bit_set(e->second, 0);
                        bit_set(e->minute, 0);
                        bit_set(e->hour, 0);
                        bit_set(e->dom, 0);
@@ -167,6 +169,7 @@ load_entry(file, error_func, pw, envp)
                        e->flags |= DOW_STAR;
                } else if (!strcmp("weekly", cmd)) {
                        Debug(DPARS, ("load_entry()...weekly shortcut\n"))
+                       bit_set(e->second, 0);
                        bit_set(e->minute, 0);
                        bit_set(e->hour, 0);
                        bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
@@ -175,6 +178,7 @@ load_entry(file, error_func, pw, envp)
                        bit_set(e->dow, 0);
                } else if (!strcmp("daily", cmd) || !strcmp("midnight", cmd)) {
                        Debug(DPARS, ("load_entry()...daily shortcut\n"))
+                       bit_set(e->second, 0);
                        bit_set(e->minute, 0);
                        bit_set(e->hour, 0);
                        bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
@@ -182,11 +186,28 @@ load_entry(file, error_func, pw, envp)
                        bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
                } else if (!strcmp("hourly", cmd)) {
                        Debug(DPARS, ("load_entry()...hourly shortcut\n"))
+                       bit_set(e->second, 0);
                        bit_set(e->minute, 0);
                        bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
                        bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
                        bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
                        bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
+               } else if (!strcmp("every_minute", cmd)) {
+                       Debug(DPARS, ("load_entry()...every_minute shortcut\n"))
+                       bit_set(e->second, 0);
+                       bit_nset(e->minute, 0, (LAST_MINUTE-FIRST_MINUTE+1));
+                       bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
+                       bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
+                       bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
+                       bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
+               } else if (!strcmp("every_second", cmd)) {
+                       Debug(DPARS, ("load_entry()...every_second shortcut\n"))
+                       bit_nset(e->second, 0, (LAST_SECOND-FIRST_SECOND+1));
+                       bit_nset(e->minute, 0, (LAST_MINUTE-FIRST_MINUTE+1));
+                       bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
+                       bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
+                       bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
+                       bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
                } else {
                        ecode = e_timespec;
                        goto eof;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to