2 # (c) 2011 Martin Mares <mj@ucw.cz>
21 my ($class, $id) = @_;
28 $job->{'ID'} = POSIX::strftime("%Y%m%d-%H%M%S-$$-$job_cnt", localtime);
30 $job->{'Subject'} = '(no subject)';
34 sub new_from_file($$;$) {
35 my ($class, $file, $header_only) = @_;
37 open T, '<', $file or die "Cannot open $file: $!";
41 /^([A-Z][A-Za-z0-9-]*):\s*(.*)/ or die "Cannot load $file: Header syntax error";
42 !defined $job->{$1} or die "Cannot load $file: Header $1 re-defined";
47 $job->{'body'} = join("", @cmds);
50 $job->{'Subject'} //= '?';
51 $job->{'ID'} or die "Cannot load $file: Missing ID";
56 my ($job, $attr, $val) = @_;
57 $job->{$attr} = $val if defined $val;
63 for my $k (sort keys %$job) {
64 print "$k: ", $job->{$k}, "\n";
70 -d "tmp" or mkdir "tmp" or die "Cannot create directory tmp: $!";
71 $fn //= 'tmp/t-' . $job->{'ID'};
72 open T, '>', $fn or die "Cannot create $fn: $!";
73 for my $k (sort grep { /^[A-Z]/ } keys %$job) {
74 print T "$k: ", $job->{$k}, "\n";
77 print T $job->{'body'} if defined $job->{'body'};
85 my ($class, $name) = @_;
87 -d $name or die "Queue directory $name does not exist\n";
88 for my $d ("hosts", "jobs") {
89 -d "$name/$d" or mkdir "$name/$d" or die "Cannot create directory $name/$d: $!";
99 my ($queue, $machine) = @_;
100 return $queue->{'Name'} . '/hosts/' . $machine;
104 my ($queue, $machine, $jid) = @_;
105 return $queue->host_dir($machine) . '/q-' . $jid;
108 sub status_file($$) {
109 my ($queue, $machine, $jid) = @_;
110 return $queue->host_dir($machine) . '/s-' . $jid;
114 my ($queue, $jid) = @_;
115 return $queue->{'Name'} . '/jobs/j-' . $jid;
119 my ($queue, $machine, $job) = @_;
120 my $qf = $queue->queue_file($machine, $job->{'ID'});
121 if (-f $qf) { return 0; }
122 my $fn = $queue->job_file($job->{'ID'});
123 -f $fn or $job->save($fn);
124 my $dir = $queue->host_dir($machine);
125 -d $dir or mkdir $dir or die "Cannot create directory $dir: $!";
126 symlink "../../jobs/j-" . $job->{'ID'}, $qf or die "Cannot create $qf: $!";
131 my ($queue, $machine) = @_;
133 if (opendir D, $queue->host_dir($machine)) {
134 while ($_ = readdir D) {
143 sub job_metadata($$) {
144 my ($queue, $jid) = @_;
145 my $cache = $queue->{'MetaCache'};
146 if (!defined $cache->{$jid}) {
147 $cache->{$jid} = BEX::Job->new_from_file($queue->job_file($jid), 1);
149 return $cache->{$jid};
152 sub read_job_status($$$) {
153 my ($queue, $machine, $jid) = @_;
155 my $sf = status_file($queue, $machine, $jid);
156 if (open S, '<', $sf) {
159 /^(\w+):\s*(.*)/ or die "Parse error in $sf";
167 sub write_job_status($$$$) {
168 my ($queue, $machine, $jid, $stat) = @_;
169 my $sf = status_file($queue, $machine, $jid);
170 open S, '>', $sf or die "Cannot create $sf: $!";
171 for my $k (sort keys %$stat) {
172 print S "$k: ", $stat{$k}, "\n";