Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

CA::AutoSys::Jil module

by runrig (Abbot)
on Apr 11, 2008 at 17:18 UTC ( #679773=sourcecode: print w/replies, xml ) Need Help??
Category: Miscellaneous
Author/Contact Info runrig
Description:

Update: Doesn't seem to work anymore. E.g., latest version of autorep does not seem to have "-D" option. Instances of 'from_autosys' in code should probably be 'from_server'. I haven't used autosys for a while and am just getting back to it, so I may update this in the near future.

This is posted mainly because I said I would in response to a recent post. AutoSys is job scheduling software (like cron on steroids) from Computer Associates. This started out as just a JIL (AutoSys' Job Information Language) parser (to read files with multiple job definitions), and mutated into also getting job status and dependencies, and validating jil scripts. You'll need to configure the AUTOSERV hash...sorry this is mostly as is so things are not as generic as they could be. There is some overlap between this and what is already on CPAN (CA::AutoSys) but the existing CPAN module didn't have any JIL parsing, which is what I really needed in the beginning. If the output format of autorep or job_depends changes in past/future version of AutoSys, then something here will probably break.

And I would appreciate feedback on whether or not this works on other systems :-)

package CA::AutoSys::Jil;

use strict;
use warnings;

use Carp qw(confess);

use vars qw(%AUTOSERV);

use overload '""' => \&name;

# Making assumptions here
# Maybe we shouldn't set these
$ENV{AUTOSERV} = '/usr/local/autosys/autosys';
$ENV{AUTOUSER} = '/usr/local/autosys/autouser';

# Hash of server names and the database server name
# We make assumptions about the database name
# (see use of AUTOSERV hash in from_server method)
%AUTOSERV = (
  dev_server_name => 'DEV',
  prod_server_name => 'PROD',
);

sub autoserv { $AUTOSERV{$_[1]} }

# List of valid sub_commands and attributes
my @sub_commands = qw(
alarm_if_fail
auto_delete
auto_hold
avg_runtime
box_failure
box_name
box_success
box_terminator
chk_files
command
condition
date_conditions
days_of_week
delete_box
delete_job
description
exclude_calendar
heartbeat_interval
insert_job
job_load
job_terminator
job_type
machine
max_exit_success
max_run_alarm
min_run_alarm
n_retrys
override_job
owner
permission
priority
profile
run_calendar
run_window
start_mins
start_times
std_err_file
std_in_file
std_out_file
term_run_time
timezone
update_job
watch_file
watch_file_min_size
watch_interval
);

my ( %valid_cmd, %valid_old_cmd );
$valid_cmd{$_}++, $valid_old_cmd{"#old$_"}++ for @sub_commands;

sub new {
  my $class = shift;
  my $self = bless {}, $class;

  my $opts = {};
  $opts = pop @_ if @_ > 1 and ref $_[-1];

  # This will catch certain edge cases (e.g. where @_ == 2) easily
  if ( @_ > 1 ) {
    for (@_) {
      return $self->read_array(@_, $opts) if /^\s*(?:insert|delete|upd
+ate)_job:/;
    }
  }

  if ( @_ == 1 ) {
    my $arg = shift;
    return
      ref($arg) ? $self->read_file($arg, $opts)
    : ( $arg =~ /\n/ or $arg =~ /^\s*(?:insert|delete|update)_job:/ ) 
+? $self->read_text($arg, $opts)
    : ( $arg =~ m|/| or -f $arg ) ? $self->read_file($arg, $opts)
    : confess "Don't know how to get job $arg\n";
  }
  if ( @_ == 2 ) {
    return $self->from_server(@_);
  }
  # This is probably unnecessary, but will nicely die for bad input
  # (e.g. missing insert/delete/update).
  $self->read_array(@_, $opts) if @_;
  return $self;
}

sub read_text {
  my $self = shift;
  $self = $self->new() unless ref $self;

  my $text = shift;

  my $opts = pop @_ if ref $_[-1];
  $self->read_array( split(/\n/, $text), $opts);
}

sub read_file {
  my $self = shift;
  $self = $self->new() unless ref $self;

  my ($file, $opts) = @_;
  $opts ||= {};
  my $fh;
  if ( ref($file) ) {
    $fh = $file;
  } else {
    open($fh, "<", $file) or confess "Can't open $file: $!";
  }
  my @jil = <$fh>;
  close $fh;

  return $self->read_array(@jil, $opts);
}

sub read_array {
  my $self = shift;
  $self = $self->new() unless ref $self;

  my $opts = {};
  $opts = pop @_ if ref $_[-1];
  my $keep_old = $opts->{keep_old};
  my $cmd_re = $keep_old ? qr/(?:#old)?\w+/ : qr/\w+/;

  my @input = @_;
  my ( $name, $full_text, @text, %jil, @cmd_list, $cmd_type );
  for (@input) {
    next unless defined;
    s/^\s+//; s/\s+$//;
    $self->{FIXED_OWNER} = 1 if s/^#owner:/owner:/;
    s/@.*// if /^owner:/;
    $full_text .= "$_\n";
    next unless /^($cmd_re):\s*(.*)/;
    my ( $cmd, $txt ) = ( $1, $2 );
    push @text, $_;
    push @cmd_list, $cmd;
    if ( $cmd =~ /^(insert|update|delete)_job$/ ) {
      $cmd_type = $1;
      ($name, my ($job_type_cmd, $job_type)) = split " ", $txt;
      $job_type_cmd =~ s/:$// if $job_type_cmd;
      if ( $job_type_cmd ) {
        if ( $job_type_cmd eq 'job_type' ) {
          push @cmd_list, $job_type_cmd;
          $jil{$job_type_cmd} = $job_type;
        } else {
          confess "Can't determine job_type in $txt";
        }
      }
      $txt = $name;
    }
    $jil{$cmd} = $txt;
  }
  confess "No name found for jil" unless $name;
  @$self{qw(NAME TEXT CMD CMD_LIST CMD_TYPE FULLTEXT)} = ( $name, \@te
+xt, \%jil, \@cmd_list, $cmd_type, $full_text );
  return $self;
}

sub fixed_owner { return $_[0]->{FIXED_OWNER} }
sub name     { return $_[0]->{NAME} }
sub cmd_type { return $_[0]->{CMD_TYPE} }
sub status   {
  my $self = shift;

  unless ( @_ )  {
    confess "Must supply server for $self" unless $self->{SERVER};
    $self->get_status() unless $self->{STATUS};
    return $self->{STATUS};
  }

  my $name = $self->name();
  my $server = shift;
  my $jil = ref($self)->from_autosys($name, $server);
  $jil->get_status();
  return $jil->{STATUS};
}

sub from_server {
  my $self = shift;
  $self = $self->new() unless ref $self;

  my ( $jil, $server ) = @_;
  $jil =~ s/\.jil$//i;
  confess "Invalid jil name: $jil" unless $jil =~ /^[\w-]+$/;

  my $srv = $self->autoserv($server) or confess "$server is not a know
+n AutoSys server!\n";
  my $fh = $self->exec_cmd(
    '/usr/local/autosys/autosys/bin/autorep',
    '-J', $jil,
    '-D', "SQL_AUTOSYS_$srv:autosys",
    '-q',
    '-L', 0
  );

  $self->{SERVER} = $server;
  $self->read_file($fh);
  $self->{FIXED_OWNER} = 0;
  return $self;
}

sub box_dependencies {
  my $self = shift;

  unless ( @_ )  {
    confess "Must supply server for $self" unless $self->{SERVER};
    $self->get_box_dependencies() unless $self->{DEPENDENCIES};
    return $self->{DEPENDENCIES};
  }

  my $name = $self->name();
  my $server = shift;
  my $jil = ref($self)->from_autosys($name, $server);
  $jil->get_box_dependencies();
  return $jil->{DEPENDENCIES};
}

sub get_box_dependencies {
  my $self = shift;
  my $server = @_ ? shift() : $self->{SERVER};

  return [] unless $self->job_type() eq 'b';
  my $srv = $self->autoserv($server) or confess "$server is not a know
+n AutoSys server!\n";
  my $fh = $self->exec_cmd(
    '/usr/local/autosys/autosys/bin/job_depends',
    '-J', $self->name(),
    '-D', "SQL_AUTOSYS_$srv:autosys",
    '-d',
    '-L1',
  );

  my @dep_jobs;
  my $got_this_job;
  my $get_jobs;
  my $name = $self->name();
  my $name_re = qr/^\Q$name\E\s/;
  local $_;
  while (<$fh>) {
    $got_this_job++ if /$name_re/;
    next unless $got_this_job;
    next unless $get_jobs++;
    /^\s+([\w-]+)\s/ or next;
    push @dep_jobs, $1;
  }
  $self->{DEPENDENCIES} = \@dep_jobs;
}

sub dependencies {
  my $self = shift;

  unless ( @_ )  {
    confess "Must supply server for $self" unless $self->{SERVER};
    return $self->status->dependent_jobs();
  }

  my $name = $self->name();
  my $server = shift;
  my $jil = ref($self)->from_autosys($name, $server);
  return $jil->status->dependent_jobs();
}

sub get_status {
  my $self = shift;
  my $server = @_ ? shift() : $self->{SERVER};

  my $srv = $self->autoserv($server) or confess "$server is not a know
+n AutoSys server!\n";
  my $fh = $self->exec_cmd(
    '/usr/local/autosys/autosys/bin/job_depends',
    '-J', $self->name(),
    '-D', "SQL_AUTOSYS_$srv:autosys",
    '-c',
  );

  my ( $name, $status, $date_cond, $start_cond, $dep, @cond, @dep_job 
+);
  local $_;
  while (<$fh>) {
    if ( my $cur_stat = /^Job Name/.../^[\w]+/ ) {
      if ( $cur_stat =~ /E/ ) {
        ( $name, $status, $date_cond, $start_cond, $dep ) = split;
      }
    }
  
    # Get Condition Status
    if ( my $cond_stat = /^\s*Atomic Condition/.../^(?:\s*|___________
+______.*)$/ ) {
      if ( $cond_stat > 2 and $cond_stat !~ /E/ ) {
        my ( $cond, $cond_status, $t_f ) = split;
        unless ( $cond =~ /^(\w+)\(([\w-]+)\)/ ) {
          confess "Invalid condition $cond for $self\n";
        }
        my ( $cond_req, $cond_job ) = ( $1, $2 );
        my $met = ( $t_f  eq "T" );
        push @cond, bless {
          JOB_NAME   => $cond_job,
          REQ_STATUS => $cond_req,
          CURRENT    => $cond_status,
          MET        => $met,
        }, "CA::AutoSys::Jil::ConditionStatus";
      }
    }

    if ( my $dep_stat = /^\s*Dependent Job Name/.../^(?:\s*|__________
+_______.*)$/ ) {
      if ( $dep_stat > 2 and $dep_stat !~ /E/ ) {
        my ( $dep_job, $dep_cond ) = split;
        $dep_cond =~ s/\(.*//;
        push @dep_job, bless {
          JOB_NAME  => $dep_job,
          REQ_STATUS => $dep_cond,
        }, "CA::AutoSys::Jil::DependentJob";
      }
    }

  }
  close $fh;

  confess "$self does not exist on $server" unless $name;
  $self->{STATUS} = bless {
    CURRENT =>    $status,
    DATE_COND =>  $date_cond,
    CONDITIONS => \@cond,
    DEP_JOBS => \@dep_job,
  }, "CA::AutoSys::Jil::Status";
}

sub exec_cmd {
  my $self = shift;
  my @cmd = @_;
  my $pid = open(my $pipe, "-|");
  die "Can't fork: $!" unless defined $pid;
  unless ($pid) {
    close STDERR;
    exec @cmd;
    die "Could not exec @cmd: $!";
  }
  return $pipe;
}
  
# Take source and target jils and generate
# an update command
sub mk_update {
  my ( $from, $to, $rev ) = @_;

  ( $from, $to ) = ( $to, $from ) if $rev;

  my @from_cmd = @{$from->{CMD_LIST}};
  my @to_cmd =   @{$to->{CMD_LIST}};
  my $from_cnt = @from_cmd;
  my $to_cnt =   @to_cmd;
  my %from_val = %{$from->{CMD}};
  my %to_val =   %{$to->{CMD}};

  ( my $from_name = $from_val{insert_job} ) =~ s/\s.*//;
  ( my $to_name   = $to_val{insert_job} ) =~ s/\s.*//;
  confess "$from_name != $to_name!\n" if $from_name ne $to_name;;

  my ($to_idx, $from_idx) = (1,1);

  my @upd_txt;
  while ( $from_idx < $from_cnt or $to_idx < $to_cnt ) {
    my $from_cmd = ( $from_idx < $from_cnt ) ? $from_cmd[$from_idx] : 
+'';
    my $to_cmd   = ( $to_idx   < $to_cnt   ) ? $to_cmd[$to_idx] : '';
    my $from_txt = exists($from_val{$from_cmd}) ? $from_val{$from_cmd}
+ : '';
    my $to_txt   = exists($to_val{$to_cmd}) ? $to_val{$to_cmd} : '';
    my $from_sp = length($from_txt) ? " " : "";
    my $to_sp   = length($to_txt)   ? " " : "";
    if ( $from_cmd eq $to_cmd ) {
      if ( $from_txt eq $to_txt ) {
        $from_idx++; $to_idx++;
        next;
      }
      if ( $from_cmd eq 'owner' ) {
        warn "Warning: Change in owner for $from_name\n";
      }
      my $upd_to   = "$to_cmd:$to_sp$to_txt";
      my $upd_from = "#old$from_cmd:$from_sp$from_txt";
      push @upd_txt, $upd_to, $upd_from;
      $from_idx++; $to_idx++;
      next;
    }
    # We are deleting a command
    if ( exists $from_val{$to_cmd} or $to_idx >= $to_cnt ) {
      if ( exists $to_val{$from_cmd} ) {
        warn "Warning: Commands out of order in $from_name--manual upd
+ate required\n";
        last;
      }
      if ( $from_cmd eq 'owner' ) {
        warn "Warning: Can't delete owner from $from_name\n";
        $from_idx++;
        next;
      } elsif ( $from_cmd eq 'date_conditions' ) {
        push @upd_txt, "$from_cmd: 0", "#old$from_cmd: $from_txt";
        $from_idx++;
        next;
      }
      push @upd_txt, "$from_cmd:", "#old$from_cmd: $from_txt";
      $from_idx++;
      next;
    }
    # We are inserting a command
    if ( exists $to_val{$from_cmd} or $from_idx >= $from_cnt ) {
      if ( exists $from_val{$to_cmd} ) {
        # We should never get here, but just for consistency
        warn "Warning: Commands out of order in $to_name--manual updat
+e required\n";
        last;
      }
      if ( $to_cmd eq 'owner' ) {
        warn "Warning: Inserting owner in $to_name\n";
      }
      push @upd_txt, "$to_cmd: $to_txt", "#old$to_cmd:";
      $to_idx++;
      next;
    }
    # Assume there is an insert
    if ( $to_cmd eq 'owner' ) {
      warn "Warning: Insert owner in $to_name\n";
      $to_idx++;
      next;
    }
    push @upd_txt, "$to_cmd: $to_txt", "#old$to_cmd:";
    $to_idx++;
    next;
  }
  if (!@upd_txt) {
    warn "No changes detected in $to_name\n";
    return '';
  }
  return join '', map { "$_\n" } "update_job: $to_name", @upd_txt;
}

# Compare the jils line by line and
# return differences
sub diff {
  my ( $from, $to ) = @_;
  unless ( ref $to ) {
    $to = ref($from)->read_text( $to, { keep_old => 1 } );
  }

  my @from_cmd = @{$from->{CMD_LIST}};
  my @to_cmd =   @{$to->{CMD_LIST}};
  my %from_val = %{$from->{CMD}};
  my %to_val =   %{$to->{CMD}};

  my @diffs;
  my %seen;

  for my $cmd ( @from_cmd ) {
    my $from = "$cmd: $from_val{$cmd}";
    my $to   = (exists $to_val{$cmd}) ? "$cmd: $to_val{$cmd}" : '';

    push @diffs, $from, $to if $from ne $to;
    $seen{$cmd}++;
  }

  for my $cmd ( @to_cmd ) {
    next if $seen{$cmd}++;

    my $from = (exists $from_val{$cmd}) ? "$cmd: $from_val{$cmd}" : ''
+;
    my $to   = "$cmd: $to_val{$cmd}";

    push @diffs, $from, $to if $from ne $to;
  }
  return @diffs;

}

sub validate {
  my $jil = shift;

  my @errors;
  for my $cmd ( @{$jil->{CMD_LIST}} ) {
    push @errors, "$jil has invalid command($cmd)" and next
      unless $valid_cmd{$cmd} or $valid_old_cmd{$cmd};
    if ( my $val = $jil->can("validate_$cmd") ) {
      next unless defined &$val;
      push @errors, $jil->$val();
    }
  }
  return @errors;
}

sub validate_insert_job {
  my $self = shift;

  my $job_name = $self->name();
  my $cmd_type = $self->cmd_type();

  my @errors;
  push @errors, "$job_name failed name > 30 chars" if length($job_name
+) > 30;
  push @errors, "$job_name failed job_type(missing)" if $cmd_type eq '
+insert' and ! defined($self->job_type());

  return @errors;
}
{
  no warnings 'once';
  *validate_update_job = *validate_delete_job = \&validate_insert_job;
}

sub validate_job_type {
  my $self = shift;

  my $job_name = $self->name();
  my $job_type = $self->job_type();

  my @errors;
  push @errors, "$job_name failed job_type($job_type)" unless $job_typ
+e =~ /^[cfb]$/;

  return @errors;
}

sub validate_box_name {
  my $self = shift;

  my $job_name = $self->name();
  my $box_name = $self->box_name();

  my @errors;
  push @errors, "$job_name failed box_name($box_name) > 30 chars" if l
+ength($box_name) > 30;

  return @errors;
}

for my $sub_cmd (@sub_commands) {
  no strict 'refs';
  *$sub_cmd = sub {
    my $self = shift;
    return $self->{CMD}{$sub_cmd};
  };
}

sub text {
  my $self = shift;

  my $type;
  if ( @_ ) {
    $type = shift;
    unless ( $type ) {
      return $self->{FULLTEXT};
    }
  }

  my $txt;
  if ( $type ) {
    $txt .= "/* ----------------- $self->{NAME} ----------------- */\n
+\n";
  }
  $txt .= "$_: $self->{CMD}{$_}" . ( ( $_ eq "insert_job" ) ? "   " : 
+"\n" )
    for @{$self->{CMD_LIST}};
  return $txt;
}

sub split_file {
  my $class = shift;

  my @jils;
  my $splitter = $class->splitter(@_);
  my $jil;
  push @jils, $jil while $jil = $splitter->next_jil();
  return @jils;
}

sub splitter {
  my $class = shift;
  @_ > 0 or confess "Must supply file name or file handle to spltter\n
+";

  my $file = shift;
  return CA::AutoSys::Jil::Splitter->new($file, $class);
}

package CA::AutoSys::Jil::Splitter;

use Carp qw(confess);

sub new {
  my $class = shift;

  my $file = shift or confess "Must supply file name or file handle\n"
+;

  my $proto = shift(@_) || 'CA::AutoSys::Jil';
  $proto = ref($proto) if ref($proto);

  my $fh;
  if ( ref($file) ) {
    $fh = $file;
  } else {
    open($fh, "<", $file) or confess "Can't open $file: $!";
  }

  bless {
    FH => $fh,
    BUFFER => [],
    GOT_COMMENT => \my $got_comment,
    GOT_COMMAND => \my $got_command,
    SAVE => \my $save,
    PROTO => $proto,
  }, $class;
}

sub next_jil {
  my $self = shift;

  my ( $fh, $buffer, $got_comment, $got_command, $save, $proto ) =
    @$self{qw( FH BUFFER GOT_COMMENT GOT_COMMAND SAVE PROTO )};
  my $process_previous;
  local $_;
  # Process the previously saved jil when we find either
  # a comment or a new job command.
  while (<$fh>) {
    if ( m!^\s*/\*! ) {
      $$got_comment = 1;
      $process_previous = 1;
    }
    if ( /^(?:insert|update|delete)_job:/ ) {
      $process_previous = 1 unless $$got_comment;
      $$got_command++;
      $$got_comment = 0;
    }
  } continue {
    my $is_eof = eof($fh);
    if ( $process_previous or $is_eof ) {
      push @$buffer, $_ if $is_eof;
      # Only process if something is in the buffer and
      # it contains a command.
      if ( @$buffer and $$got_command ) {
        $$got_command--;
        my $jil = $proto->read_array( @$buffer, { keep_old => 1 });
        @$buffer = $is_eof ? () : ($_);
        $$save = ! $is_eof;
        return $jil;
      }
      $process_previous = 0;
      $$save = ! $is_eof;
    }
    push @$buffer, $_ if $$save;
  }

  return;
}

package CA::AutoSys::Jil::Status;

use overload '""' => \&current;

sub current    { $_[0]->{CURRENT} }
sub date_cond  { $_[0]->{DATE_COND} }
sub conditions { $_[0]->{CONDITIONS} }
sub dependent_jobs { $_[0]->{DEP_JOBS} }

package CA::AutoSys::Jil::ConditionStatus;

sub job_name   { $_[0]->{JOB_NAME} }
sub req_status { $_[0]->{REQ_STATUS} }
sub current    { $_[0]->{CURRENT} }
sub met        { $_[0]->{MET} }

package CA::AutoSys::Jil::DependentJob;

sub job_name   { $_[0]->{JOB_NAME} }
sub req_status  { $_[0]->{REQ_STATUS} }

1;

__END__

=head1 NAME

CA::AutoSys::Jil - Module for Jil processing

=head1 SYNOPSIS

    use CA::AutoSys::Jil;

    $jil = CA::AutoSys::Jil->new(@lines|$text|$file_path|$fh|$jil_name
+,$server, [\%options])

    $jil->read_file($file_name | $fh, [\%options])

    $jil->read_text($text, [\%options])

    $jil->read_array(@array, [\%options])

    $jil->from_server($jil, $server)

    $jil->name()

    $jil->cmd_type()

    $jil->fixed_owner()

    $jil1->mk_update($jil2, [$reverse])

    $jil1->diff($jil2)

    $jil->text([$type])

    $splitter = CA::AutoSys::Jil->splitter($file|$fh)

    $jil = $splitter->next_jil()

    @jils = CA::AutoSys::Jil->split_file($file|$fh)

    $status = $jil->status([$server]);

    @dependencies = @{ $jil->box_dependencies() };

    @dependent_jobs = @{ $jil->dependencies() };

    $current_status = $status->current();

    @conditions = @{ $status->conditions() };

    @dependent_jobs = @{ $status->dependent_jobs() };

    $job_name = $condition->job_name();

    $required_status = $condition->req_status()

    $current_status = $condition->current();

    $condition_met  = $condition->met();

    $job_name = $dependent_job->job_name();

    $required_status = $dependent_job->req_status();

=head1 DESCRIPTION

Implements methods to facilitate jil processing

=head1 METHODS

=over 4

=item new ()

Creates a new CA::AutoSys::Jil object. Also calls one of the read_* or
+ from_*
methods depending on the arguments. The logic below may seem complex, 
+but
it makes it easy to make the module do the "right" thing.

If there is more than one argument, and the last argument is
a reference, we assume the last argument is an options hash reference,
and it is not counted as an argument below.

If there is only one argument:
  and it is a reference, we call read_file()
  and it contains newlines, we call read_text()
  and it contains any "/", we call read_file()

If there are two arguments:
  and the second argument is a known autosys server, we call from_serv
+er()

If there are more than two arguments, we call read_array()
Otherwise, you must call one of the read_* or from_* methods yourself.

The last argument is an optional hash reference, and if present is pas
+sed along to
the read_* methods.  Common option(s) for the read methods are:

=head2 Options

=over 4

=item keep_old

If this option is true, then lines that begin with "#old" are also
considered "commands" (Default: false).

=back

=item read_array (@lines, [\%options])

Reads jil from an array.

=item read_text ($text, [\%options])

Reads jil from a text string.

=item read_file ($file_name|$fh, [\%options])

Reads jil from a file name or if the argument is a reference,
an already opened file handle.

=item from_server ($jil_name, $server)

Gets jil from autosys server. Also determines current status of job
and the conditions in the job.

=item box_dependencies ([$server])

If the job is a box, returns an array reference to the names of
all the jobs in the box. If the job is not a box, returns a reference
to an empty array.
The server argument is optional if from_server() was used to create th
+e object.

=item dependencies ([$server])

Returns a reference to an array of dependency objects containing
all the jobs dependent on this job. This is the same as getting
dependent jobs from a status object.
The server argument is optional if from_server() was used to create th
+e object.

=item status ([$server])

Returns a jil status object containing the status of the current job
and all jobs in the condition from the given server.
$server is optional if from_server() was used to create the object.

=head2 Status Methods

These are the methods that may be used on a jil status object:

=over 4

=item current ()

Returns the current status of the job from the status object.

=item conditions ()

Returns a list of condition status objects containing the status
of each of the conditions in the jil object.

=item dependent_jobs ()

Returns a list of dependency status objects containing the jobs
dependent on this job.

=back

=head2 Condition Status Methods

These are the methods that may be used on a condition status object:

=over 4

=item job_name ()

Returns the job name or the name of the autosys variable in the condit
+ion.

=item req_status ()

Returns the status of the job required to satisfy the condition (or
'VALUE' if the condition contains a variable).

=item current ()

Returns the current status of the job or variable in the condition.

=item met ()

Returns a boolean indicating  whether or not the condition has been me
+t.

=back

=head2 Dependency Status Methods

These are the methods that may be used on a dependency status object:

=over 4

=item job_name ()

The name of the dependent job.

=item req_status ()

Returns the required status of the job that this job depends on.

=back

=item mk_update ($target_jil, [$reverse])

Compares the original jil object to the target jil passed in,
and returns an update_job command which will transform the original
to the target jil. Or if reverse option is true, returns an
update command to transform the other way around.

=item validate ()

Makes sure every sub_command and attribute is valid, and calls
all existing validate_* methods for every sub command and attribute
that exists in the jil. Checks for correctness and various current jil
policies. See L<Validation Methods> section below.

=item splitter ($file|$fh)

Initializes a jil splitter object from a file name or a file handle,
from which jils will be read. Called as a class method, e.g.:

  my $splitter = CA::AutoSys::Jil->splitter($file);

=over 4

=item next_jil ()

Returns the next jil from the jil splitter object, or undefined if
there are no more jils. Typically used in a while loop, e.g.:

  while ( my $jil = $splitter->next_jil() ) {
    # Process $jil
    ...
  }

=back

=item split_file ($file|$fh)

Reads jils from a file or file handle, and returns a list of jil objec
+ts.
Called as a class method, e.g.:

  my @jils = CA::AutoSys::Jil->split_file($file);

=item diff ($target_jil)

Compares the original jil against another jil, and returns a list
of the differences as an array, where the lines in the array alternate
+ between the
original and the target jil. Does not try to do a 'diff' style output,
+ just
compares every command line from beginning to end and returns any line
+s that differ.
The target_jil may be an CA::AutoSys::Jil object or just the text of a
+ jil.

=item text ([$type])

Returns the text of the insert_jil command.

If called with no arguments, then only the jil command
(e.g. comments will be omitted) will be returned.

If called with a true argument, then a header comment line
will be prepended to the text.

If called with a false argument, then the original text
as read from the source (minus leading and trailing whitespace)
will be returned.

=item name ()

The name of the jil will be returned. If the jil object is used inside
double quotes, this method will be called, and the object will be
stringified to this value.

=item cmd_type ()

The type of command (insert/delete/update) will be returned (same valu
+e as job_type()
but without the trailing "_job").

=item fixed_owner ()

When the jil is read in, any hash("#") is stripped from the beginning 
+of
the "owner:" line, and a flag is set if the hash was
present before being stripped (except when read in via the from_server
+()
method). This method returns the status of that flag.

=item Jil Sub Commands/Attributes

The name of any jil sub-command or attribute may be used as a method a
+nd
the value of the sub-command or attribute will be returned (or undef i
+f
it does not exist).

=back

=head2 Validation Methods

Current validate methods which can be called separately or may all
be called with the validate() method:

=over 4

=item validate_insert_job ()

=item validate_update_job ()

=item validate_delete_job ()

=item validate_box_name ()

Make sure that any job or box name is 30 characters or less.

Make sure insert_job includes a job_type.

=item validate_job_type ()

Make sure job type is c, f, or b.

=back

=head1 AUTHOR

runrig

=cut
Replies are listed 'Best First'.
Re: CA::AutoSys::Jil module
by Anonymous Monk on Sep 18, 2008 at 04:24 UTC
    Hi, how is the Condition string split into different jobs and inserted in the autosys JOB_COND table. If JobA has condition s(B) and S(C) and (s(D) or f(E)) then i see that JOB_COND has several entries for JobA, for each job in the original condition. There are also pointers, Index values that define how the binary expression tree is built to evaluate the condition expression. Can you please let me know where and when exactly is the original condition provided in the input file, is parsed and inserted in the JOB_COND table. And where can i see this parser code. Thanks, -srinivas

      I'm not doing anything with the AutoSys database tables. This code does not create jobs or insert anything into or even directly access any database tables. I'm just parsing the output of the autorep and job_depends commands. job_depends can tell you the status of each condition in the condition string for existing jobs, and I'm parsing that in the get_status() method. The original purpose of that part of the module was to facilitate writing code to tell what condition or job might be holding up another job.

      The CA::AutoSys module on CPAN does get information straight from the AutoSys database.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://679773]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2022-01-25 07:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:












    Results (65 votes). Check out past polls.

    Notices?