#!/usr/bin/env perl
#----------------------------------------------------------------------------
#
# Name: free_catalog_lock.pl
#
# This perl script is used for the free_lock task in the OPUS pipeline for the 
# OSF that processes science POD files (data_id = pod). Interactive mode is used
# only during testing. The interactive mode cannot change held OSFs.
#
# Interactive Usage:
#	>free_catalog_lock.pl pod_rootname
#
#       where pod_rootname must have an lock files in the default dirctory.
#
# Pipeline Usage:
#       command:free_catalog_lock.pl 
#     
#       In the pipeline the resource file must set the following ENV 
#       variable: OSF_DATASET
#
#
# History:
# Date     OPR      Who         Reason
# -------- -------- ----------  ---------------------------------------------
# 09/08/04 51692    Baum        Initial code
# 08/11/05 53803    MSwam       Replace PATH_FILE_NAME with PATH_BASENAME
# 03/30/12 70831    Sherbert    For now add messaging 
#----------------------------------------------------------------------------
# set up external routines
unshift @INC,(split /:/, $ENV{PATH});
require 'printmsg.pl';       # prints a formatted status message

#specify exit status values

    $EXIT_FAILURE =     7;   # exit status for XPOLL
    $EXIT_SUCCESS =     9;   # exit status for XPOLL
    $EXIT_GO_ABSENT = 102;   # forces process to go absent

#check for arguments

    $num_arg = scalar @ARGV;
    # get pipeline ENV variables
    $osf_root  = $ENV{"OSF_DATASET"};

    if ($num_arg > 0 && substr($ARGV[0],0,1) ne "-") {
        $interactive = 1;
    } elsif (defined($osf_root)) {
        $interactive = 0;
    } else {
        $fail_msg = 
            "Usage example: >free_catalog_lock.pl <pod_name>\nTry again.\n"; 
        print $fail_msg;
        exit( $EXIT_FAILURE);
    }
    if ($interactive) {
        # get osf_root from argument
        $osf_root = $ARGV[0];
        $lock_dir = "./";
    } else {
        # pipeline variable for path, stripping out the directory
        $osf_path  = $ENV{"PATH_BASENAME"};   
        $colon_idx = rindex($osf_path,":");
        $osf_path  = substr($osf_path,$colon_idx+1);
        
        # get resource variable
        $lock_dir        = $ENV{"CATALOG_LOCK_DIR"};
        $held_stage      = $ENV{"HELD_STAGE"};
        $held_status     = $ENV{"HELD_STATUS"};
        $continue_status = $ENV{"CONTINUE_STATUS"};
        
        if (!defined( $lock_dir) || !defined($held_stage) ||
            !defined( $held_status) || !defined($continue_status) )
        {
            PrintMsg("F","Missing ENV variable: CATALOG_LOCK_DIR,");
            PrintMsg("F","HELD_STAGE, HELD_STATUS, and CONTINUE_STATUS,");
            PrintMsg("F","must all be defined.");
            exit( $EXIT_GO_ABSENT);
        }
    }
    # begin processing
    PrintMsg ("I","--- start --- Free Catalog Locks for $osf_root");
    
    # get all the lock files this POD file
    @lock_list = glob $lock_dir."*.".$osf_root;
    
    if ((scalar @lock_list) == 0) {
        PrintMsg("W","No lock files found in $lock_dir");
        exit ($EXIT_SUCCESS);  # not necessarily an error
    }
    # delete lock files
    $delete_count = unlink @lock_list;
    PrintMsg("I","$delete_count lock files deleted from $lock_dir");
    PrintMsg('D',"These files deleted: @lock_list ") ;

    # retrigger any held OSFs
    if (!$interactive) {
        foreach $lock_file (@lock_list) {
            PrintMsg('D', "Calling release_held_osf($lock_file) " );
            release_held_osf($lock_file);
        }
    }
    PrintMsg ("I","---  end  --- Free Catalog Locks for $osf_root");
    exit ($EXIT_SUCCESS);    

#---------------------------------------------------------------------
# end of main procedure -- subroutines follow
#---------------------------------------------------------------------
sub release_held_osf {
    # one argument - full lock file specification (with directory)
    #
    # get the ipppssoot from the lock file names and test if an OSF
    # is being held for that ipppssoot. If the OSF is held reset it
    # to continue catalog processing. 
    
    my ($lock_file_spec)  = @_;
    
    # Extract the ipppssoot rootname that is the minimal number of non_white
    # characters after the slash and before the period
    my $match = $lock_file_spec =~m#/(\w+?)\.\w+$#;
    if (!$match) {
        PrintMsg("E","Cannot parse dataset from filename $lock_file_spec");
        exit ($EXIT_FAILURE);
    }
    my $ds_name = $1;

    # test if any locks remain for this dataset name
    my $lock_file_mask = $lock_file_spec;
    $lock_file_mask =~s/^(\S+\.)(\S+)$/$1*/;
    my @more_locks = glob $lock_file_mask;
    
    if (scalar @more_locks) {
       PrintMsg("I","More locks found for $lock_file_mask");
       return; 
    }
    # test for OSF in hold state using global variables set in main program
    my $command = "osf_test -p $osf_path -f $ds_name -c $held_stage ".
                  "-s $held_status -pr data_id";

    PrintMsg('D', "osf_data_id=$command" ) ;
    my $osf_data_id = `$command`;
    if ($?) {
        PrintMsg("E","Cannot execute command: $command");
    }
    PrintMsg('D', "osf_data_id=$osf_data_id ") ;
    if ($osf_data_id ne "") {
        chomp $osf_data_id;  # remove newline
        # update OSF with continue status
        $command = "osf_update -p $osf_path -f $ds_name -t $osf_data_id ".
                   "-c $held_stage -s $continue_status"; 
        PrintMsg('D', "update_msg=$command" ) ;
        my $update_msg = `$command`;
        if ($?) {
            PrintMsg("E","Failed command: $command");
            PrintMsg("E","Command response: $update_msg");
            exit ($EXIT_FAILURE);
        }
        PrintMsg("I",
           "$osf_path $held_stage OSF for $ds_name, data_id $osf_data_id released from held state.");
    } else {
        PrintMsg("I","$osf_path $held_stage OSF for $ds_name is not present or not held");
    }
}
