svn commit: r241576 - in head/usr.sbin/cron: cron crontab lib

Maxim Sobolev sobomax at FreeBSD.org
Mon Oct 15 08:21:50 UTC 2012


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 * * * *".
+ at every_minute	Run once a minute, "*/1 * * * *".
+ at 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;


More information about the svn-src-all mailing list