#!/usr/bin/perl
-# Batch EXecutor 2.0
+# Batch EXecutor 2.0 -- Insert to Queue
# (c) 2011 Martin Mares <mj@ucw.cz>
use strict;
use warnings;
+use Getopt::Long;
+use File::stat;
use lib 'lib';
use BEX;
+my $queue_name;
+
+GetOptions(
+ "q|queue=s" => \$queue_name,
+) or die <<AMEN ;
+Usage: benq [<options>] [!]<machine-or-class> ...
+
+Options:
+-q, --queue=<name> Insert new jobs to the given queue
+AMEN
+
+# Prepare machine set
+@ARGV or die "No machines specified\n";
+my @machines = BEX::Config::parse_machine_list(@ARGV);
+@machines or die "No machines match\n";
+
+# Create job template and let the user edit it
my $job = BEX::Job->new;
my $fn = $job->save;
-system "editor", $fn;
-## FIXME: Check exit code of editor
-$job = BEX::Job->new_from_file($fn);
-## FIXME: Compare and exit if no changes
+my $orig_stat = stat($fn) or die;
+system "editor", $fn and die "Editor exited with an error, file kept as $fn\n";
+my $new_stat = stat($fn) or die "File $fn disappeared under my hands: $!\n";
+if ($new_stat->mtime <= $orig_stat->mtime && $new_stat->size == $orig_stat->size) {
+ unlink $fn;
+ die "Cancelled\n";
+}
-my $queue = BEX::Queue->new;
-for my $m (keys %BEX::Config::machines) {
- $queue->enqueue($m, $job);
+# Re-load the job and put it to the queue
+$job = BEX::Job->new_from_file($fn);
+print "New job ", $job->{'ID'}, "\n";
+my $queue = BEX::Queue->new($queue_name);
+for my $m (@machines) {
+ if ($queue->enqueue($m, $job)) {
+ print "\t$m\n";
+ BEX::log("$m " . $job->{'ID'} . " queued");
+ } else {
+ print "\t$m (already queued)\n";
+ }
}
+# Remove the temporary file
unlink $fn;
#!/usr/bin/perl
-# Batch EXecutor 2.0
+# Batch EXecutor 2.0 -- Show Queued Jobs
# (c) 2011 Martin Mares <mj@ucw.cz>
use strict;
use warnings;
+use Getopt::Long;
use lib 'lib';
use BEX;
-my $queue = BEX::Queue->new;
-for my $m (keys %BEX::Config::machines) {
+my $queue_name;
+
+GetOptions(
+ "q|queue=s" => \$queue_name,
+) or die <<AMEN ;
+Usage: bq [<options>] [[!]<machine-or-class> ...]
+
+Options:
+-q, --queue=<name> Show jobs in the given queue
+AMEN
+
+my @machines = BEX::Config::parse_machine_list(@ARGV ? @ARGV : '*');
+my $queue = BEX::Queue->new($queue_name);
+for my $m (@machines) {
print "$m:\n";
my @q = $queue->scan($m);
for my $j (@q) {
--- /dev/null
+# BEX epilog
use strict;
use warnings;
-package BEX::Config;
+use BEX::Config;
-our %machines = (
- 'albireo' => { },
- 'localhost' => { },
-);
+package BEX;
+
+use IO::File;
+
+use POSIX;
+
+my $log_file;
+
+sub log($) {
+ $log_file //= new IO::File '>>log' or die "Cannot open log: $!";
+ print $log_file POSIX::strftime("%Y-%m-%d %H:%M:%S ", localtime), $_[0], "\n";
+}
package BEX::Job;
return $queue->host_dir($machine) . '/s-' . $jid;
}
+sub temp_file($$) {
+ my ($queue, $machine, $jid) = @_;
+ return $queue->host_dir($machine) . '/t-' . $jid;
+}
+
sub job_file($$) {
my ($queue, $jid) = @_;
return $queue->{'Name'} . '/jobs/j-' . $jid;
return @list;
}
+sub remove($$) {
+ my ($queue, $machine, $jid) = @_;
+ unlink $queue->queue_file($machine, $jid);
+ unlink $queue->status_file($machine, $jid);
+ unlink $queue->temp_file($machine, $jid);
+}
+
sub job_metadata($$) {
my ($queue, $jid) = @_;
my $cache = $queue->{'MetaCache'};
sub read_job_status($$$) {
my ($queue, $machine, $jid) = @_;
my %s = ();
- my $sf = status_file($queue, $machine, $jid);
+ my $sf = $queue->status_file($machine, $jid);
if (open S, '<', $sf) {
while (<S>) {
chomp;
sub write_job_status($$$$) {
my ($queue, $machine, $jid, $stat) = @_;
- my $sf = status_file($queue, $machine, $jid);
+ my $sf = $queue->status_file($machine, $jid);
open S, '>', $sf or die "Cannot create $sf: $!";
for my $k (sort keys %$stat) {
- print S "$k: ", $stat{$k}, "\n";
+ print S "$k: ", $stat->{$k}, "\n";
}
close S;
}
our %machines = (
);
+# A file whose contents should be prepended before the job. Should start with the "#!" line.
+our $job_prolog = 'prolog';
+
+# A file whose contents should be appended to the job
+our $job_epilog = 'epilog';
+
# Various utility functions
sub parse_machine_list(@);
--- /dev/null
+#!/bin/sh
+# BEX prolog