[interchange-cvs] interchange - heins modified 3 files

interchange-core@icdevgroup.org interchange-core@icdevgroup.org
Fri Jul 19 01:14:00 2002


User:      heins
Date:      2002-07-19 05:13:16 GMT
Modified:  scripts  interchange.PL
Modified:  lib/Vend Server.pm Control.pm
Log:
* Add nascent "cron" capability. While we don't keep the time, and
  a scheduler will have to set the execution time, it allows ITL
  to be run without the hassles of having to deal with HTTP.

* Somewhat documented in pod for bin/interchange

* TODO: Add email of results.

* TODO: Add "Cron" directive to specify directory. Current practice
  of picking a directory in PageDir or *TemplateDir is weak. Cron
  directive could also specify email address and log file for results,
  and possibly other things like write_control for databases, precursor
  ITL, etc.

* TODO: Interchange-core discussion of this facility and its
  features before it goes anywhere.

Revision  Changes    Path
2.41      +159 -44   interchange/scripts/interchange.PL


rev 2.41, prev_rev 2.40
Index: interchange.PL
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /anon_cvs/repository/interchange/scripts/interchange.PL,v
retrieving revision 2.40
retrieving revision 2.41
diff -u -r2.40 -r2.41
--- interchange.PL	7 Jul 2002 04:02:26 -0000	2.40
+++ interchange.PL	19 Jul 2002 05:13:16 -0000	2.41
@@ -3,7 +3,7 @@
 #
 # Interchange version 4.9.1
 #
-# $Id: interchange.PL,v 2.40 2002/07/07 04:02:26 mheins Exp $
+# $Id: interchange.PL,v 2.41 2002/07/19 05:13:16 mheins Exp $
 #
 # Copyright (C) 1996-2002 Red Hat, Inc. <interchange@redhat.com>
 #
@@ -235,6 +235,7 @@
 use autouse 'Vend::Control' =3D> qw/
 											signal_reconfig
 											signal_add
+											signal_cron
 											signal_remove
 											control_interchange
 											remove_catalog
@@ -1445,6 +1446,69 @@
 	return $status;
 }
=20
+sub run_in_catalog {
+	my ($cat_name, $directory, $itl) =3D @_;
+	my ($g,$c);
+
+#::logGlobal("running job in cat=3D$cat_name");
+	$g =3D $Global::Catalog{$cat_name};
+	unless (defined $g) {
+		logGlobal( "Can't find catalog '%s'" , $cat_name );
+		return undef;
+	}
+
+	#$Vend::Log_suppress =3D 1;
+
+	unless ($Vend::Quiet) {
+		logGlobal("Run cron group=3D%s", $directory || 'INTERNAL');
+	}
+	#undef $Vend::Log_suppress;
+
+	open_cat($cat_name);
+
+	my $dir;
+	my @itl;
+	if($directory) {
+		my $ct =3D $Vend::Cfg->{TemplateDir} || [];
+		my $gt =3D $Global::TemplateDir || [];
+
+		for my $d ($Vend::Cfg->{PageDir}, @$ct, @$gt) {
+#::logGlobal("check directory=3D$d for $directory");
+			$dir =3D "$d/$directory"
+				if -d "$d/$directory";
+		}
+		if($dir) {
+			my @f =3D glob("$dir/*");
+			@f =3D grep ! -d $_, @f;
+			@f =3D grep $_ !~ /$Vend::Cfg->{HTMLsuffix}$/, @f;
+			for(@f) {
+#::logGlobal("found cron piece file=3D$_");
+				push @itl, [$_, readfile($_)];
+			}
+		}
+	}
+
+	if ($itl) {
+		push @itl, ["Passed ITL", $itl];
+	}
+
+	if(! @itl) {
+		logGlobal("Empty cron job=3D%s", $directory);
+	}
+
+	my @out;
+	for(@itl) {
+		logError("Running cron task=3D%s", $_->[0]);
+		push @out, interpolate_html($_->[1]);
+	}
+
+	close_cat();
+	my $out =3D join "", @out;
+	$out =3D~ s/^\s+//;
+	$out =3D~ s/\s+$/\n/;
+	return $out;
+}
+
 sub config_named_catalog {
 	my ($cat_name, $source, $db_only, $dbconfig) =3D @_;
 	my ($g,$c);
@@ -1730,28 +1794,32 @@
 					},
 );
=20
-sub dispatch {
-	my($http) =3D @_;
-	$H =3D $http;
-
-	adjust_cgi();
+sub open_cat {
+	my $cat =3D shift;
=20
-    my($sessionid, $seed);
-	my(@path);
-	my($g, $action);
+	if($cat) {
+		%CGI::values =3D ();
+		if($Global::Catalog{$cat}) {
+			$CGI::script_path =3D $Global::Catalog{$cat}->{script};
+			$CGI::script_name =3D $CGI::script_path;
+		}
+	}
=20
 	unless (defined $Global::Selector{$CGI::script_name}) {
 		my $msg =3D get_locale_message(
 						404,
 						"Undefined catalog: %s",
-						$CGI::script_name,
+						$CGI::script_name || $cat,
 						);
 		$Vend::StatusLine =3D <<EOF;
 Status: 404 Not Found
 Content-Type: text/plain
 EOF
-		::response($msg);
+		if($H) {
+			::response($msg);
+		}
 		logGlobal($msg);
+		# No close_cat() necessary
 		return;
 	}
=20
@@ -1764,25 +1832,6 @@
 		$Vend::Cfg =3D $Global::Selector{$CGI::script_name};
 	}
=20
-## Uncomment this to get global directive setting on a per-catalog basis
-## Probably only useful for:
-##
-##   DebugFile
-##   DisplayErrors
-##   DomainTail
-##   ErrorLog
-##   FullUrl
-##   GlobalSub
-##   HitCount
-##   IpHead
-##   IpQuad
-##   Locale
-##   LockoutCommand
-##   NoAbsolute
-##   SafeUntrap
-##   UserTag
-##   Variable
-
 	$Vend::Cat =3D $Vend::Cfg->{CatalogName};
 	my $catref =3D $Global::Catalog{$Vend::Cat};
 	if(! $Global::Foreground and defined $catref->{directive}) {
@@ -1836,7 +1885,7 @@
 			if  $Vend::Cfg->{ImageDirInternal};
 	}
=20
-	if($Global::HitCount) {
+	if($Global::HitCount and ! $cat) {
 		my $ctr =3D new Vend::CounterFile
 					"$Global::ConfDir/hits.$Vend::Cat";
         $ctr->inc();
@@ -1868,6 +1917,25 @@
 #show_times("end cgi and config mapping") if $Global::ShowTimes;
 	open_database();
 #show_times("end open_database") if $Global::ShowTimes;
+}
+
+sub close_cat {
+	put_session() if $Vend::HaveSession;
+	close_session() if $Vend::SessionOpen;
+	close_database();
+}
+
+sub dispatch {
+	my($http) =3D @_;
+	$H =3D $http;
+
+	adjust_cgi();
+
+    my($sessionid, $seed);
+	my(@path);
+	my($g, $action);
+
+	open_cat();
=20
 	$CGI::user =3D Vend::Util::check_authorization($CGI::authorization)
 		if defined $CGI::authorization;
@@ -1929,6 +1997,7 @@
 EOF
 		::response($msg);
 		logGlobal($msg);
+		close_cat();
 		return;
 	}
=20
@@ -2023,6 +2092,7 @@
 Content-Type: text/plain
 EOF
 					::response($msg);
+					close_cat();
 					return;
 			}
 		}
@@ -2341,9 +2411,7 @@
 	$Vend::Track->filetrack();
 # END TRACK
=20
-	put_session() if $Vend::HaveSession;
-	close_session() if $Vend::SessionOpen;
-	close_database();
+	close_cat();
=20
 	undef $H;
=20
@@ -2442,6 +2510,30 @@
 The information is in the form of a standard Interchange catalog line,
 and must be in the single-line format.
=20
+=3Ditem --cron=3Dcatalog[=3Djob]
+
+Run a cron group which is a series of files in a directory with
+the name corresponding to the C<job>. For instance, if you=20
+set up a directory called "weekly" in your pages directory
+for the catalog C<foundation>, you can run those files with:
+
+	interchange --cron=3Dfoundation=3Dweekly
+
+Files ending in .html (or whatever HTMLsuffix is for that catalog)
+are skipped. It is not tree-recursive -- directories are ignored.
+
+Results can be emailed to an address if you specify --email=3Daddress,
+and they will be put in the cron log file.
+
+Alternatively jobs can be specified with --job=3Djobname B<before>
+the --cron option. In other words, this will work:
+
+	interchange --job=3Dweekly --cron=3Dfoundation
+
+This will NOT work:
+
+	interchange --cron=3Dfoundation --job=3Dweekly
+
 =3Ditem -d dir, --dir=3Ddir
=20
 Directory for VendRoot. This is where the Interchange configuration file
@@ -2452,6 +2544,10 @@
=20
 Exclude catalog from this startup.
=20
+=3Ditem -email=3Daddress
+
+Email address to email cron job results to.
+
 =3Ditem -f file, --config=3Dfile
=20
 Configuration file to use (default is interchange.cfg in VendRoot).
@@ -2465,6 +2561,15 @@
 Run with internet-domain socket only. Normally Interchange runs with
 both UNIX- and internet-domain sockets (except on Windows).
=20
+=3Ditem --job=3Djob
+
+Sets the job for --cron if that is not included in the --cron
+call. MUST precede the --cron entry on the command line.
+
+	interchange --job=3Dweekly --cron=3Dfoundation
+
+See --cron for an explanation of what this does.
+
 =3Ditem --kill [signal]
=20
 By default, kills the server ungracefully with signal KILL (9, usually).
@@ -2555,14 +2660,18 @@
=20
      --add=3Dcatalog         add a catalog to operation; parms taken from =
the
                            standard input as a "Catalog ..." directive
+     --cron=3Dcatalog[=3Djob]  run cron jobs for a particular catalog
+                           (can use --job and -email)
      -d dir, --dir=3Ddir     directory for VendRoot (interchange.cfg, erro=
r.log, etc.)
      -e name,
         --exclude=3Dname     exclude catalog
+     --email=3Demailaddr     Send results of cron job to emailaddr
      -f file,
         --config=3Dfile      configuration file (default interchange.cfg)
      --files spec          filespec (perl regexp OK) for static page tree
      -h, --help            display this message
      -i, --inetmode        run with Internet-domain socket (TCP)
+     --job=3Djobname         cron jobs to run (hourly, daily, weekly, etc.)
      --kill [signal]       kill server ungracefully (9 or with optional si=
gnal)
      -q, --quiet           suppress informational messages on startup
      --reconfig=3Dcatalog    reconfig a particular catalog on the server
@@ -2671,6 +2780,9 @@
 		version         =3D> sub { version(); exit 0 },
 		stop			=3D> \&control_interchange,
 		add				=3D> \&signal_add,
+		email			=3D> \$Vend::CronEmail,
+		job				=3D> \$Vend::CronJob,
+		cron			=3D> \&signal_cron,
 		remove			=3D> \&signal_remove,
 		kill			=3D> \&control_interchange,
 		Ignore 			=3D> \$ignore,
@@ -2728,16 +2840,19 @@
 		DEBUG:i
 		Ignore
 		add|a=3Ds
-		confdir=3Ds
-		rundir=3Ds
-		configfile|config|c|f=3Ds
-		dir|vendroot|d=3Ds
-		exclude|e=3Ds
-		help|h
-		inetmode|inet|i
-		kill:s
-		log|logfile|l=3Ds
-		quiet|q
+        confdir=3Ds
+        configfile|config|c|f=3Ds
+        cron=3Ds
+        dir|vendroot|d=3Ds
+        email=3Ds
+        exclude|e=3Ds
+        help|h
+        inetmode|inet|i
+        job=3Ds
+        kill:s
+        log|logfile|l=3Ds
+        quiet|q
+        rundir=3Ds
 		pidfile=3Ds
 		reconfig=3Ds
 		remove=3Ds



2.9       +72 -2     interchange/lib/Vend/Server.pm


rev 2.9, prev_rev 2.8
Index: Server.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /anon_cvs/repository/interchange/lib/Vend/Server.pm,v
retrieving revision 2.8
retrieving revision 2.9
diff -u -r2.8 -r2.9
--- Server.pm	27 Jun 2002 22:24:10 -0000	2.8
+++ Server.pm	19 Jul 2002 05:13:16 -0000	2.9
@@ -1,6 +1,6 @@
 # Vend::Server - Listen for Interchange CGI requests as a background server
 #
-# $Id: Server.pm,v 2.8 2002/06/27 22:24:10 jon Exp $
+# $Id: Server.pm,v 2.9 2002/07/19 05:13:16 mheins Exp $
 #
 # Copyright (C) 1996-2002 Red Hat, Inc. <interchange@redhat.com>
 #
@@ -25,7 +25,7 @@
 package Vend::Server;
=20
 use vars qw($VERSION);
-$VERSION =3D substr(q$Revision: 2.8 $, 10);
+$VERSION =3D substr(q$Revision: 2.9 $, 10);
=20
 use POSIX qw(setsid strftime);
 use Vend::Util;
@@ -1114,6 +1114,11 @@
 					{
 						::remove_catalog($1);
 					}
+					elsif( $directive =3D~ /^cron$/i) {
+						my ($cat, @jobs) =3D grep /\S/, split /[\s,\0]+/, $value;
+#::logGlobal("restart line found value=3D'$value'");
+						run_cron($cat, @jobs);
+					}
 					else {
 						::change_global_directive($directive, $value);
 					}
@@ -2309,6 +2314,71 @@
 		or die "create PID file $$: $!\n";
 	lockfile(\*TEMPPID, 1, 0)
 		or die "PID $$ conflict: can't lock\n";
+}
+
+sub cron_job {
+	my ($cat, @jobs) =3D @_;
+	for my $job (@jobs) {
+		::run_in_catalog($cat, $job);
+	}
+}
+
+sub run_cron {
+	my ($cat, @jobs) =3D @_;
+
+#::logGlobal("Vend::Server::run_cron: run cron cat=3Dcat jobs=3D@jobs");
+	my $pid;
+	if($Global::Foreground) {
+		$::Instance =3D {};
+		eval {
+			cron_job($cat, @jobs);
+		};
+		if($@) {
+			my $msg =3D $@;
+			::logGlobal({ level =3D> 'error' }, "Runtime error: %s" , $msg);
+			logError("Runtime cron error: %s", $msg)
+				if defined $Vend::Cfg->{ErrorFile};
+		}
+		clean_up_after_fork();
+		undef $::Instance;
+	}
+	elsif(! defined ($pid =3D fork) ) {
+		my $msg =3D ::errmsg("Can't fork: %s", $!);
+		::logGlobal({ level =3D> 'crit' },  $msg );
+		die ("$msg\n");
+	}
+	elsif (! $pid) {
+		#fork again
+		unless ($pid =3D fork) {
+
+			reset_per_fork();
+			$::Instance =3D {};
+			eval {=20
+				touch_pid() if $Global::PIDcheck;
+				&$Sig_inc;
+				cron_job($cat, @jobs);
+			};
+			if ($@) {
+				my $msg =3D $@;
+				::logGlobal({ level =3D> 'error' }, "Runtime error: %s" , $msg);
+				logError("Runtime cron error: %s", $msg)
+					if defined $Vend::Cfg->{ErrorFile};
+			}
+			clean_up_after_fork();
+
+			undef $::Instance;
+			select(undef,undef,undef,0.050) until getppid =3D=3D 1;
+			if ($Global::PIDcheck) {
+				unlink_pid() and &$Sig_dec;
+			}
+			else {
+				&$Sig_dec;
+			}
+			exit(0);
+		}
+		exit(0);
+	}
+	wait unless $Global::Foreground;
 }
=20
 sub unlink_pid {



2.4       +38 -3     interchange/lib/Vend/Control.pm


rev 2.4, prev_rev 2.3
Index: Control.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /anon_cvs/repository/interchange/lib/Vend/Control.pm,v
retrieving revision 2.3
retrieving revision 2.4
diff -u -r2.3 -r2.4
--- Control.pm	27 Jun 2002 22:24:10 -0000	2.3
+++ Control.pm	19 Jul 2002 05:13:16 -0000	2.4
@@ -1,6 +1,6 @@
 # Vend::Control - Routines that alter the running Interchange daemon
 #=20
-# $Id: Control.pm,v 2.3 2002/06/27 22:24:10 jon Exp $
+# $Id: Control.pm,v 2.4 2002/07/19 05:13:16 mheins Exp $
 #
 # Copyright (C) 1996-2002 Red Hat, Inc. <interchange@redhat.com>
 #
@@ -29,6 +29,7 @@
 @EXPORT =3D qw/
 				signal_reconfig
 				signal_add
+				signal_cron
 				signal_remove
 				control_interchange
 				change_catalog_directive
@@ -49,6 +50,22 @@
 	}
 }
=20
+sub signal_cron {
+	shift;
+	$Vend::mode =3D 'cron';
+	my $arg =3D shift;
+	my ($cat, $job) =3D split /\s*=3D\s*/, $arg, 2;
+	$Vend::CronCat =3D $cat;
+#::logGlobal("signal_cron: called cron cat=3D$cat job=3D$job");
+	$job =3D join ",", $job, $Vend::CronJob;
+	$job =3D~ s/^,+//;
+	$job =3D~ s/,+$//;
+	$Vend::CronJob =3D $job;
+	Vend::Util::writefile("$Global::RunDir/restart", "cron $cat $job\n");
+#::logGlobal("signal_cron: wrote file, ready to control_interchange");
+	control_interchange('cron', 'HUP');
+}
+
 sub signal_remove {
 	shift;
 	$Vend::mode =3D 'reconfig';
@@ -92,8 +109,26 @@
 	if(! $sig) {
 		$sig =3D $mode ne 'kill' ? 'TERM' : 'KILL';
 	}
-	print "Killing Interchange server $pid with $sig.\n"
-		unless $Vend::Quiet;
+	my $msg;
+	if($mode eq 'cron') {
+		$msg =3D ::errmsg(
+					"Dispatching jobs=3D%s for cat %s to Interchange server %s with %s.\n=
",
+					$Vend::CronJob,
+					$Vend::CronCat,
+					$pid,
+					$sig,
+				);
+	}
+	else {
+		$msg =3D ::errmsg(
+					"Killing Interchange server %s with %s.\n",
+					$pid,
+					$sig,
+				);
+	}=20
+
+	print $msg unless $Vend::Quiet;
+
 	kill $sig, $pid
 		or die errmsg("Interchange server would not stop.\n");
 	exit 0 unless $restart;