#!/usr/bin/env perl 
##########################################################################
#
# routine: retrigger.pl
#
# purpose: Script to perform retriggering of OSFs and files.
#
#       This script is activated by a time trigger.  It queries the
#	OSF blackboard for OSFs in need of retriggering as determined
#	by specific environment variables.  Any OSFs found in need
#	are retriggered as specified.
#
#	Currently an OSF can only be queried and retriggered in a single
#       pipeline stage.  For example, if these entries appeared in the
#       resource file for a retrigger process,
#          SEARCH_OSF.DE = z
#          SET_OSF.DE    = w
#
#       then the retrigger process would search for OSFs on the blackboard
#       with the DE column = "z" and alter them to "w".  Currently the
#       stage name appearing in SEARCH_OSF (.DE) must have a corresponding
#       SET_OSF.DE entry.
#
#	Similar retriggering is performed for files.  A file can be
#	retriggered through these resource file entries:
#          SEARCH_DIRECTORY.1 = /home/mswam/  ! directory in which to search
#	   SEARCH_EXT.1       = .pod_dup      ! file extension to search for
#          SET_EXT.1          = .pod          ! file extension to set to
#
#       Multiple sets of these three (3) file search variables can be supplied, 
#       with each set numbered from 1, 2, 3, etc.  All three variables must
#       be supplied for each set.
#
# required:
#	The following environment variables must be available to this
#	routine:
#		PATH_FILE - full path name to the OPUS path file
#
# returns:
#       102 if the path file or stage file cannot be found
#       0   if successful OR no OSFs found to update
#
# modification history:
#
#   date    opr       who     reason
# -------- -----    --------  --------------------------------------
# 12/07/99 37784    MSwam     first version
# 01/31/01 43165    MSwam     mods for OTFR
# 04/05/01 43165_16 MSwam     converted to Perl
# 03/13/03 43915    Sherbert  rm -w and fix `/bin/date`: better logs 
# 08/21/03 48370    Sherbert  Add missing /bin/ qualifier to cat, cut, ls
# 01/05/04 50015    Sherbert  Teach retrigger.pl to ignore duplicate OSFs
# 10/21/10 66464    MSwam     Put tmp output in a known place, not cwd
# 
##########################################################################
#
# prepend the Perl include variable using all components of PATH
# (this allows us to reuse other OTFR Perl code)
#
$PATH  = $ENV{"PATH"};
@parts = split /:/, $PATH;
while (defined($val = pop(@parts))) {
   if (substr($val,0,1) eq "/") { unshift(@INC, $val)}
}

#
# include these modules
#
require 'printmsg.pl';       # prints a formatted status message

# print banner
# print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
$date = `date`;
chomp ($date);
PrintMsg("I","Polling Time is: $date");

# set exit status codes
#
$go_absent=102;          #this exit status is in the FATAL range for XPOLL
$all_is_well=0;

# create a temp file to hold OSF capture output
$tmp_outfile="/tmp/".$ENV{"PROCESS_NAME"}."_tmp$$.osflist";
print "tmp_outfile=$tmp_outfile\n";

#
# locate the pipeline stage file for this path
#
$PATH_FILE = $ENV{"PATH_FILE"};
if ($PATH_FILE eq "") {
   PrintMsg("E","ERROR: No definition found for PATH_FILE");
   exit $go_absent;
}
@stagefile = `egrep STAGE_FILE $PATH_FILE | cut -d '=' -f 2`;
if ($stagefile[0] eq "") {
   PrintMsg("E","ERROR: Failed to find pipeline stage file for $PATH_FILE");
   exit $go_absent;
}
chomp($stagefile[0]);
#
# pass the value through the stretch-resolver command and trim the newline
$command = "osfile_stretch_file $stagefile[0]";
@fullstage = `$command`;
chomp($fullstage[0]);
if ($fullstage[0] eq "") {
   PrintMsg("E","ERROR: Failed to resolve pipeline stage file $stagefile[0]");
   exit $go_absent;
}
#
# loop through the set of pipeline stages in the stage file
#
@stages = `egrep "TITLE =" $fullstage[0]`;
foreach $line (@stages) {
   # parse out the stage name (3rd column)
   @parts = split /\s+/,$line;
   $stage = $parts[2];
   chomp($stage);
   #
   # search for retriggering information in the environment
   $statval = "";
   if (exists($ENV{"SEARCH_OSF.$stage"})) {
      $statval = $ENV{"SEARCH_OSF.$stage"};
   }
   if ($statval ne "") {
      $newstatval = "";
      if (exists($ENV{"SET_OSF.$stage"})) {
         $newstatval = $ENV{"SET_OSF.$stage"};
      }
      if ($newstatval ne "") {
        #
        # a retrigger has been requested 
        #
        # search OSFs for any in need of retriggering and save their names
        #
        `osf_test -p $PATH_FILE -c $stage -s $statval -pr dataset data_id > $tmp_outfile`;
        if ($? != 0) {
          PrintMsg("E","ERROR testing for retriggering candidates.");
          unlink ($tmp_outfile);
          exit $go_absent;
        }
        # loop through qualifying datasets, and retrigger each
        #
        if ( !open (OSF_INFO, "$tmp_outfile")) {
            print "Failed to open $tmp_outfile for input";
            exit $go_absent;
        }
        while (<OSF_INFO>) {
            # split the read buffer ($_) into fields
            my ($dataset, $data_id) = split(/ /, $_);
            if ( $dataset ) {
                PrintMsg("I","Retriggering $data_id $dataset in stage $stage to $newstatval");
                `osf_update -p $PATH_FILE -f $dataset -t $data_id -c $stage -s $newstatval`;
                if ($? != 0) {
                   PrintMsg("W","WARNING: failed to retrigger OSF for $dataset");
                   # possible collision, just try the next one
                }
            }
        }
        close(OSF_INFO);
      }
   }
}
#
# loop through the possible FILE retriggering variables
#   (e.g. SEARCH_FILE.1,SET_FILE.1 , etc.)
#
use File::Basename;
# any characters after first ".", including "." are the file extension
$file_extension_match = "\.[0-z]*";

for ($i = 1; $i < 1000; $i++) {
   if (exists($ENV{"SEARCH_EXT.$i"})) {
      $search_ext = $ENV{"SEARCH_EXT.$i"};
   }
   else {
      $search_ext = "";
   }
   if ($search_ext ne "") {
      if (exists($ENV{"SET_EXT.$i"})) {
         $set_ext = $ENV{"SET_EXT.$i"};
      }
      else {
         $set_ext = "";
      }
      if ($set_ext ne "") {
         if (exists($ENV{"SEARCH_DIRECTORY.$i"})) {
            $search_dir = $ENV{"SEARCH_DIRECTORY.$i"};
         }
         else {
            $search_dir = "";
         }
         if ($search_dir ne "") {
            #
            # rename all matching files
            @matches = `ls -1 $search_dir/*$search_ext`;
            foreach $f (@matches) {
                chomp($f);
                ($name, $path, $dontcare_suffix) = 
                                               fileparse($f, $file_extension_match);
                # apply new extension to file rootname and rename
                $newf = $path . $name . $set_ext;
                PrintMsg("I","renaming $f to $newf");
                if (!rename($f, $newf)) {
                   # failures will try again later
                   PrintMsg("W","exit code indicates rename FAILED for $f to $newf; try later");
                }
                if (-e $f) {
                   # failures will try again later
                   PrintMsg("W","source file still exists; rename FAILED for $f to $newf; try later");
                }
                PrintMsg("D","renamed $f to $newf");
            }
         }
         else {
            PrintMsg("E","ERROR: Found SEARCH_FILE.$i,SET_FILE.$i, but no SEARCH_DIRECTORY.$i");
            last;
         }
      }
      else {
         PrintMsg("E","ERROR: Found SEARCH_FILE.$i, but no SET_FILE.$i");
         last;
      }
   }
   else {
      last;
   }
}
#
# complete, exit success
unlink ($tmp_outfile) || warn "Did not remove $tmp_outfile ";
PrintMsg("I","Done.");
exit $all_is_well;
