# *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ # ** Copyright UCAR (c) 1992 - 2010 */ # ** University Corporation for Atmospheric Research(UCAR) */ # ** National Center for Atmospheric Research(NCAR) */ # ** Research Applications Laboratory(RAL) */ # ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA */ # ** 2010/10/7 23:12:43 */ # *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */ package NNTUtils; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(initTrigger waitForTrigger waitForTriggerMin findClosest getNowAsUtime expandPath checkExes checkDidssEnvVars advanceHour); # # Externals # # The sys_wait_h is required to get the correct return codes from the system() calls. use POSIX 'sys_wait_h'; use Env; use Cwd; Env::import(); use Time::Local; # make 'date' available # Local RAP libs use lib "$ENV{RAP_SHARED_LIB_DIR}/perl5/"; use lib "$ENV{RAP_LIB_DIR}/perl5/"; use Toolsa; use Niwot; 1; # Perl requires this # =============================== SUBROUTINES =========================== # # # Subroutine: initTrigger # # Usage: initTrigger( $regInt, $dbg, $cronLikeTime ) # # Function: Sets a list of times to be used in the following calls # to wait for the next time. The list will be sorted in # this subroutine and will be a "global" or "static" # variable. In addition, the index will be set to indicate # that we don't yet know where we are in the list of times. # Also sets the registration interval and debug flag. # # Input: $regInt = Registration interval in seconds # # $dbg = Debug flag. 0 - off, 1 - on # # $cronTime = String containing times in cron # like format # # Output: 0 on success and -1 on failure # ######################################################################## sub initTrigger { my ($regInt, $dbg, $cronTime) = @_; # # Initialize values # $regInterval = $regInt; $debug = $dbg; $prevDay = 0; $hourIdex = -1; $minuteIdex = -1; $numHours = 0; $numMinutes = 0; $wrapping = 0; $tolerance = 60; # # Check for weirdnesses in the cron time string # if( cronQC( $cronTime ) ) { Niwot::postError( "Time format incorrect" ); return( -1 ); } # # Parse the time string # First split the times on white space - this should # give us the fields, i.e. minutes, hours, etc. # my @fields = split /\s+/, $cronTime; # # Parse the minute field # if( $debug ) { Niwot::postDebug( "Minutes:"); } ($retVal, @minuteList) = parseCronField( $fields[0], 0, 59 ); if( $retVal ) { return( -1 ); } # # Parse the hour field # if( $debug ) { Niwot::postDebug( "Hours:"); } ($retVal, @hourList) = parseCronField( $fields[1], 0, 23 ); if( $retVal ) { return( -1 ); } # # If there are any other fields that are not set to *, # warn the user that we won't be doing anything about those # settings. # for( $i = 2; $i <= $#fields; $i++ ) { if( $fields[$i] ne "*" ) { Niwot::postWarning( "Day, Month, Day of Week fields not supported" ); } } $numMinutes = $#minuteList + 1; $numHours = $#hourList + 1; return( 0 ); } ################################################################## # # Subroutine: cronQC # # Usage: cronQC( $cronTime ) # # Function: Checks the cron time field for some weirdnesses # # Input: $cronTime = string containing cron time field # # Output: $retVal = 0 on success and -1 on failure # ################################################################## sub cronQC { my( $cronTime ) = @_; if( $cronTime =~ /,\s+/ ) { return( -1 ); } if( $cronTime =~ /-\s+/ ) { return( -1 ); } return( 0 ); } ################################################################## # # Subroutine: parseCronField # # Usage: parseCronField( $field, $minVal, $maxVal, @timeList ) # # Function: Parses the $field string to pull out relavant times # and put into an array. The $field string in in a # cron time format. # # Input: $field = minute or hour field pulled from # cron-like format string # # $minVal = minimum value allowed for this field # # $maxVal = maximum value allowed for this field # # Output: $retVal = 0 on success and -1 on failure # # @timeList = resulting list of times # # NOTE: This subroutine uses source code developed by # David Loren Parsons <http://www.pell.portland.or.us/~orc> # as a reference. His code was written for a slightly different # purpose and in C. However, although the following code is # significantly different from the original, many of the ideas # for how to parse a cron-like field came from this code. # ######################################################################## sub parseCronField { my ($field, $minVal, $maxVal) = @_; # # Declare variables # my $range; my @skips; my @nums; my @timeList; # # Initialize # my $idex = 0; my $skip = 1; my $forever = 1; # # Split field into a list of numbers or ranges # my @ranges = split /,/, $field; foreach $range (@ranges) { # # Are we dealing with a range? A star is treated like # a range, where the lower end of the range is the min allowed # and the upper end of the range is the max allowed # if( $range =~ /-/ || $range =~ /\*/ ) { # # The cron format allows a /(number) to indicate # a skip through a range. In other words, a */2, # for example, would indicate every two hours in # the full range. Strip that off if it is there # and retain the value. # @skips = split /\//, $range; # # If there are more than two substrings after # splitting on '/', that means there is more than # one '/' which is an error # if( $#skips > 1 ) { Niwot::postError( "Time format incorrect" ); return( -1, @timeList ); } # # Otherwise, if there is more than one substring # it means tht there is a skip indicated, save # this value. It will necessarily be the second # substring - if not there is an error. # if ( $#skips == 1 ) { $skip = $skips[1]; if( $skip == 0 ) { Niwot::postError( "Cannot skip by zero" ); return( 1, @timeList ); } if( $debug ) { Niwot::postDebug( " Skip = $skip" ); } } # # If the first substring contains a '*', handle # that case # if( $skips[0] =~ /\*/ ) { # # Make sure that all that is left is a '*'. # Otherwise we have an error. # if( $skips[0] ne "*" ) { Niwot::postError( "Time format incorrect" ); return( -1, @timeList ); } if( $debug ) { Niwot::postDebug( " Use full range" ); } # # Set our "range" to the min through the max # $nums[0] = $minVal; $nums[1] = $maxVal; } else { # # Now we necessarily have a '-' in our first # substring after splitting off any '/', but # make sure it isn't just a '-' # if( $skips[0] eq "-" ) { Niwot::postError( "Time format incorrect" ); return( -1, @timeList ); } @nums = split /-/, $skips[0]; # # Error out if there are more than two substrings, # or if the numbers specifying the range are out of order, # or if there is anything but digits in the range # if( $#nums > 1 || $nums[0] >= $nums[1] || $nums[0] =~ /\D/ || $nums[1] =~ /\D/ ) { Niwot::postError( "Time format incorrect" ); return( -1, @timeList ); } if( $debug ) { Niwot::postDebug( " Use $nums[0] through $nums[1]" ); } } # # We are still dealing with a range of numbers, so check # to see that the range is not out of order with what we've # already put into our time list # if( $idex > 0 && $timeList[$idex] >= $nums[0] ) { Niwot::postError( "Times out of order" ); return( -1, @timeList ); } # # Make sure we are within min and max values # if( $nums[0] < $minVal || $nums[0] > $maxVal || $nums[1] < $minVal || $nums[1] > $maxVal ) { Niwot::postError( "Times out of range" ); return( -1, @timeList ); } # # Use the range and skip to fill in the time list # for( $i = $nums[0]; $i <= $nums[1]; $i += $skip, $idex++ ) { $timeList[$idex] = $i; } } else { # # We have a single number. Make sure it is actually a number # and not some strange characters # if( $range =~ /\D/ ) { Niwot::postError( "Time format incorrect" ); return( -1, @timeList ); } # # Is the number in range? # if( $range < $minVal || $range > $maxVal ) { Niwot::postError( "Time out of range" ); return( -1, @timeList ); } # # Make sure this number is in order with what is already # in the time list # if( $idex > 0 && $timeList[$idex] >= $range ) { Niwot::postError( "Times out of order" ); return( -1, @timeList ); } if( $debug ) { Niwot::postDebug( " Use $range" ); } # # Set the time list value and increment the index # $timeList[$idex] = $range; $idex++; } } return( 0, @timeList ); } ######################################################################## # # Subroutine: waitForTrigger # # Usage: $retVal = waitForTrigger() # # Function: Sleeps until the next time in the trigger time array # occurs, then return. # # Input: none # # Output: 0 on success and -1 on failure # ######################################################################## sub waitForTrigger { # # If the index isn't set, find the closest time in the list # if ( $minuteIdex < 0 || $hourIdex < 0) { if( findIdex() ) { return( -1 ); } } # # Check current time against the next time in the list. If we are # within a tolerance of that time (in the list) return. Otherwise # sleep and try again. # my $currentUTime = 0; my $wantUTime = 0; my $timeDiff = -1; my $sleepSecs = 0; my $totalSleepSecs = 0; my $stillWaiting = 1; my ( $sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst ); # # Find the current time values # $currentUTime = time; ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = gmtime(time()); $year = $year + 1900; # # Find the wanted time # $wantMinute = $minuteList[$minuteIdex]; $wantHour = $hourList[$hourIdex]; $wantUTime = timegm( 0, $wantMinute, $wantHour, $day, $mon, $year ); # # See if we should be wrapping to the next day # if( $wrapping ) { if ( $day == $prevDay ) { $wantUTime += (24 * 60 * 60); } $wrapping = 0; } while ( $stillWaiting ) { # # Find the current utime # $currentUTime = time; # # Calculate the time differece for the current time and the time # we want based upon the above calculations # $timeDiff = $wantUTime - $currentUTime; if ( $timeDiff <= 0 ) { # # The current time has passed the wanted time # if ( $currentUTime - $wantUTime > $tolerance ) { # # We are too far past the wanted time. We must # have skipped over one of the times in # the list. Return with an error message, # but reset the index so that if we come in # here again, we can start from scratch. # Niwot::postError( "Current time too far in the past for " . "desired time" ); Niwot::postError( "Current utime = $currentUTime" ); Niwot::postError( "Desired utime = $wantUTime" ); $hourIdex = -1; $minuteIdex = -1; return( -1 ); } elsif ( $currentTime - $wantUTime <= $tolerance ) { # # We are within tolerance. We can trigger now # if( $debug ) { $msg = sprintf( "Triggering for %.2d:%.2d", $hourList[$hourIdex], $minuteList[$minuteIdex] ); Niwot::postDebug( $msg ); } # # Increment the index (and take care of wrapping) # for next time # $minuteIdex++; if ( $minuteIdex >= $numMinutes ) { if( $debug ) { Niwot::postDebug( "minute index = $minuteIdex, " . "num minutes = $numMinutes, " . "minute idex reset to zero " ); } $minuteIdex = 0; $hourIdex++; if( $hourIdex >= $numHours ) { if( $debug ) { Niwot::postDebug( "hour index = $hourIdex, " . "num hours = $numHours, " . "hour idex reset to zero " ); } $hourIdex = 0; $wrapping = 1; $prevDay = $day; } } # # We're outta here... # return( 0 ); } } else { # # The wanted time is still in the future. We need to # do some sleeping and waiting for a bit. # if( $debug ) { Niwot::postDebug( "Time difference = $timeDiff" ); } # # Register before we begin sleeping to ensure we won't get # killed in the middle of our sleep # Toolsa::PMU_force_register( "Sleeping" ); # # Sleep over the entire time difference, but stop to # register each registration interval. The time # difference will probably not be an even multiple # of the registration interval, so check for the time # remaining in the time difference and take the minimum # of that and the registration interval as the time # to sleep. Once we are all done sleeping, try again. # $totalSleepSecs = 0; while( $totalSleepSecs < $timeDiff ) { $sleepSecs = $regInterval; if( $timeDiff - $totalSleepSecs < $regInterval ) { $sleepSecs = $timeDiff - $totalSleepSecs; } if( $debug ) { Niwot::postDebug( "Slept $totalSleepSecs seconds so far, " . "sleeping $sleepSecs, reg int = $regInterval" ); } sleep( $sleepSecs ); Toolsa::PMU_force_register( "Still Sleeping" ); $totalSleepSecs += $sleepSecs; } } } return( 0 ); } ####################################################################### # # Subroutine: findIdex # # Usage: $retVal = findIdex() # # Function: Finds the indeces in the time arrays for the time closest # to now that is still in the future # # Input: none # # Output: 0 on success, -1 on failure # ####################################################################### sub findIdex { # # Get current time values # my ( $sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst ); ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = gmtime(time()); $year = $year + 1900; my $utimeNow = time; # # Debug statments # if ( $debug ) { my $timeStr = sprintf "%d/%d/%4d %.2d:%.2d:%.2d", $mon+1, $day, $year, $hour, $min, $sec; Niwot::postDebug( "Current time = $timeStr" ); } # # Look through the ordered time list. Find the index of the first # time that is in the future. # my $wantMin = 0; my $wantHour = 0; my $utimeWant = 0; my $timediff = 0; my $i = 0; my $iHour = 0; my $iMinutes = 0; my ($hourVal, $minuteVal); foreach $hourVal (@hourList) { $iMinutes = 0; foreach $minuteVal (@minuteList) { # # Calculated the wanted utime # $utimeWant = timegm( 0, $minuteVal, $hourVal, $day, $mon, $year ); # # Find the time difference # $timediff = $utimeWant - $utimeNow; # # Debug statements # if( $debug ) { Niwot::postDebug( "Finding Index: hour = $hourVal, " . "minute = $minuteVal, " . "time diff = $timediff" ); } # # If the "wanted" time is in the future, we've found our # starting point. Set the indeces and get out. # if ( $timediff >= -1 * $tolerance ) { $minuteIdex = $iMinutes; $hourIdex = $iHour; if( $debug ) { Niwot::postDebug( "Indeces found. minuteIdex = $minuteIdex" . " hourIdex = $hourIdex" ); } return 0; } # # Increment the minute counter # $iMinutes++; } $iHour++; } # # If we didn't find a time in the list that is "greater" than # the current time, we need to wrap around to the first time in the # next day. Let another routine handle the wrapping. # if( $hourIdex < 0 || $minuteIdex < 0 ) { $hourIdex = 0; $minuteIdex = 0; $wrapping = 1; $prevDay = $day; if( $debug ) { Niwot::postDebug( "Off the end of the list, wrap to beginning" ); } } return( 0 ); } ######################################################################## # # Subroutine: waitForTriggerMin # # Usage: ($return_val) = waitForTriggerMin($sleep_secs, $arr_mins, # $do_reg, $test, $dbg) # # Function: Sleep until the next minute in the trigger time array occurs # then return. # # Input: $sleep_secs seconds to sleep # $arr_mins array of trigger times, as either minutes # of every hour e.g., [10, 20, 50] or as # hours:mins e.g., [21:15, 22:30] # $narr size of $arr_mins # $do_reg flag to do PMU_auto_register (1=on, 0=off), # you must have already used PMU_auto_init() # in the calling script # $test test flag, do not actually sleep # $dbg debug flag # # Output: $return_val 1 if trigger time has occurred or 0 on error # # Overview: # sub waitForTriggerMin { my ($sleep_secs, $arr_mins, $narr, $do_reg, $test, $dbg) = @_; # Local variables my($subname, $return_val); my($dbg2, $dbg3); my($i, $found_time, $still_waiting, $now, $udate, $cmd); my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst, $day); my($is_time, $new_sleep_secs, $want_min, $is_ok, $do_sleep); # Set defaults $subname="waitForTriggerMin"; $return_val=0; # Dbg $dbg2=0; $dbg3=0; if ($dbg == 2) { $dbg2=1; } if ($dbg == 3) { $dbg3=1; $dbg2=1; } # Verbose debug if ($dbg2) { print(STDERR "$subname: Input...\n"); print(STDERR "\tsleep_secs: $sleep_secs, narr: $narr, do_reg: $do_reg, test: $test\n"); for ($i=0; $i<$narr; $i++) { print(STDERR "\tarr_mins at i: $i, is: $arr_mins->[$i]\n"); } } # Loop to check for trigger time, sleep and try again $found_time=0; $still_waiting = 1; $do_sleep=1; while ($still_waiting > 0) { ($is_time, $new_sleep_secs)=findClosest($sleep_secs, $arr_mins, $narr, $test, $dbg); if ($is_time > 0) { $found_time=1; } # Did we find a trigger time? # If so, need to get out of this loop # In test mode, need to get out of this loop if ($found_time > 0) { if ($dbg > 0) { print(STDERR "$subname: found a trigger time, new_sleep_secs: $new_sleep_secs\n"); } $still_waiting=0; $do_sleep=0; } if ($test > 0) { $still_waiting=0; } # Sleep if ($do_sleep) { if ($do_reg > 0) { Toolsa::PMU_force_register("Sleeping"); } if ($new_sleep_secs != $sleep_secs) { if ($test > 0) { print(STDERR "$subname: Would sleep new_sleep_secs: $new_sleep_secs\n"); } else { if ($dbg2) { print(STDERR "$subname: sleeping $new_sleep_secs\n"); } sleep($new_sleep_secs); } } else { if ($test > 0) { print(STDERR "$subname: Would sleep sleep_secs: $sleep_secs\n"); } else { if ($dbg2) { print(STDERR "$subname: sleeping $sleep_secs\n"); } sleep($sleep_secs); } } } } #endwhile # Done if ($found_time > 0) { $return_val=1; } return($return_val); } #----------------------------------------------------------------------------------- # Subroutine: findClosest # # Usage: ($return_val, $new_sleep_secs) = findClosest($sleep_secs, $arr, $narr, # $test, $dbg); # # Function: Find the closest time to now # # Input: $arr array of wanted minutes # $narr size of $arr # $test test flag # $dbg debug flag # # Output: $return_val 1 if found a close enough time or 0 on error # $new_sleep_secs how much to sleep next time to get closer to closest time # # Overview: # sub findClosest { my ($sleep_secs, $arr, $narr, $test, $dbg) = @_; # Local variables my($subname, $return_val, $new_sleep_secs); my($dbg2, $dbg3); my($found_idx, $i, $utime_now, $utime_want, $found, $nsecs, $timediff); my($want_time, $want_min, $is_time, $time_is_hrs_mins); my($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst); # Set defaults $subname="findClosest"; $return_val=0; $new_sleep_secs=$sleep_secs; # Dbg $dbg2=0; $dbg3=0; if ($dbg == 2) { $dbg2=1; } if ($dbg == 3) { $dbg3=1; $dbg2=1; } # Debug if ($dbg2) { print(STDERR "$subname: Inputs...\n"); print(STDERR "\tsleep_secs: $sleep_secs, narr: $narr\n"); } # Get time values so can add the want min to them ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst)=gmtime(time()); $year=$year+1900; # Get now as utime $utime_now=&getNowAsUtime; # Find trigger time closest to now but still in future, use utimes $found=0; $nsecs=-1; $found_idx=-1; for ($i=0; $i<$narr; $i++) { # Parse the time, is either a minute (e.g., 10) or hour:min (e.g., 23:10) $time_is_hrs_mins=0; $want_time=$arr->[$i]; if ($want_time =~ /\:/) { ($want_hour, $want_min)=split(":", $want_time); $time_is_hrs_mins=1; } else { $want_hour=$hour; $want_min=$want_time; } if ($dbg3) { print(STDERR "$subname: want_time; $want_time, want_hour: $want_hour, want_min: $want_min\n"); print(STDERR "$subname: current hour: $hour, current_min: $min\n"); } # Because of hour-rollover, or mins and day-rollover for hours:mins # need to handle want minutes/hours:mins less than the current time # by adding the minutes plus an hour (or 24 hours) to the current time if ($time_is_hrs_mins > 0) { $utime_want=timegm($sec, $want_min, $want_hour, $day, $mon, $year); if ($want_hour < $hour) { $utime_want=$utime_want + (60 * 60 * 24); } } else { if ($want_min >= $min) { $utime_want=timegm($sec, $want_min, $hour, $day, $mon, $year); } else { $utime_want=$utime_now + ($want_min * 60) + (60 * 60); } } $timediff=$utime_want - $utime_now; if ($dbg3) { print(STDERR "$subname: timediff: $timediff, nsecs: $nsecs, utime_want: $utime_want, utime_now: $utime_now\n"); } if ((($timediff >= 0) && ($nsecs < 0)) || (($timediff >= 0) && ($timediff < $nsecs))) { $nsecs=$timediff; $found_idx=$i; $found=1; } } if ($dbg2) { print(STDERR "$subname: found: $found, found_idx: $found_idx, nsecs: $nsecs\n"); } # The times are within a minute. Found a time! # Is next closest time shorter than sleep_secs away? if (($found) && ($nsecs <= 60)) { if ($dbg3) { print(STDERR "$subname: found time, times are within a minute\n"); } $return_val=1; } # The closest time is in the future and is more than the # sleep time away. Not a found time. if (($nsecs > $sleep_secs)) { if ($dbg3) { print(STDERR "$subname: not time, want time more than sleep secs away\n"); } } # More complicated, are the times close-enough? # If the sleep is long enough, we may not hit the exact minute # Need to reset the sleep to be shorter if (($found) && (($sleep_secs > $nsecs) && ($nsecs > 60))) { if ($dbg3) { print(STDERR "$subname: closest time closer than sleep_secs away: $nsecs\n"); } $new_sleep_secs = $nsecs; } return($return_val, $new_sleep_secs); } #----------------------------------------------------------------------------------- # Subroutine: getNowAsUtime # # Usage: $utime=getNowAsUtime # # Function: Get now as Unix time # # Input: none # # Output: $utime now in Unix time # sub getNowAsUtime { my ($dbg) = @_; # Local variables my($utime); my($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst); # Get the current time ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst)=gmtime(time()); $utime=timegm($sec, $min, $hour, $day, $mon, $year); return($utime); } #----------------------------------------------------------------------------------- # Subroutine: expandPath # # Usage: $outputPath = processDir($pathText) # # Function: Processes path text, usually retrieved from an XML parameter file, # in order to prepend the path with RAP_DATA_DIR (or DATA_DIR if # RAP_DATA_DIR does not exist) if necessary and to expand environment # variables representing directory names within the path. Note that if # the path text begins with . or / the value of RAP_DATA_DIR will not be # prepended to the text. In addition, environment variables are assumed to # represent directory names. Also note that if RAP_DATA_DIR is not defined # and DATA_DIR is not defined and the path does not start with . or / # the path will remain relative to the current location. # # Input: $pathText = text representing the path # # Output: $outputPath = output path which has been prepended with value of # RAP_DATA_DIR and for which all environent variables have been # replaced with their values #---------------------------------------------------------------------------------- sub expandPath { my( $path ) = @_; # # Local variables # my( $outputDir ); my( $pathPieces, $section, $envVar, $rap_data_dir); # # Look for environment variables in the path, and expand these # for the local file path. It is assumed that the entire directory # name is the environment variable. That is, the environment variable # cannot be embedded in the directory name. # $outputDir = ""; @pathPieces = split /(\/)/, $path; foreach $section (@pathPieces) { if ( $section =~ /^\$/ ) { $envVar = substr( $section, 1 ); $outputDir = $outputDir . $ENV{$envVar}; } else { $outputDir = $outputDir . $section; } } # # If the output directory path does not begin with '.' or '/' # it is assumed to be relative to $RAP_DATA_DIR, so prepend # path with $RAP_DATA_DIR in that case # $rap_data_dir = $ENV{'RAP_DATA_DIR'}; if ( $outputDir !~ /^\./ && $outputDir !~ /^\// ) { if ( !defined($rap_data_dir) ) { $rap_data_dir = $ENV{'DATA_DIR'}; if ( !defined( $rap_data_dir) ) { return( $outputDir ); } } $outputDir = $rap_data_dir . '/' . $outputDir; } # # Replace a '.' or a './' with a fully qualified path # if ( $outputDir =~ /^\./ ) { if ( $outputDir =~ /^\.\// ) { substr( $outputDir, 0, 2 ) = getcwd(); } else { substr( $outputDir, 0, 1 ) = getcwd(); } } return( $outputDir ); } #------------------------------------------------------------------- # Subroutine: checkExes # # Usage: ($return_val) = checkExes($exes_arr, $dbg) # # Function: Check that all the exes listed in the $exes_arr are in the # path # # Input: $exes_arr array of exes to check # $dbg debug flag # # Output: $return_val 1 if all exes found, 0 on error # # Overview: # sub checkExes { my ($exes_arr, $dbg) = @_; # Local variables my($subname, $return_val); my ($exe, $check, $nerror); # Set defaults $subname="checkExes"; $return_val=0; # Do check $nerror=0; for $exe (@{$exes_arr}) { $check=`which $exe`; if (!$check) { print(STDERR "ERROR: needed exe is not in your path: $exe\n"); $nerror++; } else { chop($check); print(STDERR "Info: Will use exe: $exe from your path. This is: $check\n"); } } if ($nerror > 0) { $return_val=0; } else { $return_val=1; } return($return_val); } #------------------------------------------------------------------- # Subroutine: checkDidssEnvVars # # Usage: $return_val=checkDidssEnvVars($dbg) # # Function: Check that all the DIDSS env vars are defined # # Input: $dbg debug flag # # Output: $return_val 1 if all defined, 0 if any not defined # # Overview: # sub checkDidssEnvVars { my ($dbg) = @_; # Local variables my($subname, $return_val); my($procmap_host, $dmap_active, $rap_data_dir); # Set defaults $subname="checkDidssEnvVars"; $return_val=1; # Do check $procmap_host=$ENV{PROCMAP_HOST}; $dmap_active=$ENV{DATA_MAPPER_ACTIVE}; $rap_data_dir=$ENV{RAP_DATA_DIR}; if (!defined($procmap_host)) { print(STDERR "PROCMAP_HOST env var is not defined, cannot register with procmap\n"); $return_val=0; } if (!defined($dmap_active)) { print(STDERR "DATA_MAPPER_ACTIVE env var is not defined, cannot register with DataMapper\n"); $return_val=0; } if (!defined($rap_data_dir)) { print(STDERR "RAP_DATA_DIR env var is not defined\n"); $return_val=0; } return($return_val); } ################################################################## # # Subroutine: advanceHour # # Usage: advanceHour( $ccyymmddhh, $hrs ) # # Function: Take the specified date string, advance it $hrs hours # and return date string in same format # # Input: $ccyymmddhh = date string in ccyymmddhh format # $hrs = number of hours to advance time; # note that this value can be negative to # decriment hours. # # Output: $retVal = new date string with the following format # on success: ccyymmddhh # # = -1 on failure # ################################################################## sub advanceHour { my( $ccyymmddhh, $hrs ) = @_; my( $yr, $mm, $dd, $hh, $min, $sec ); my( $utime, $advUtime, $timeStr ); my( $asec, $amin, $ahr, $aday, $amon, $ayr, $wday, $yday, $isdst ); # # Get year, month, day and hour from the input time string # $yr = substr( $ccyymmddhh, 0, 4 ); $mm = substr( $ccyymmddhh, 4, 2 ); $dd = substr( $ccyymmddhh, 6, 2 ); $hh = substr( $ccyymmddhh, 8, 2 ); # # Minute and seconds will always be zero # $min = 0; $sec = 0; # # Get unix time from the values obtained above # Note that timegm expects the month to be in the # range of 0-11, but the user will be entering # a month in the range of 1-12 # $utime = timegm( $sec, $min, $hh, $dd, $mm-1, $yr ); # # Increase (or decrease if hrs is negative) time by specified # number of hours # $advUtime = $utime + ($hrs*60*60); if( $advUtime < 0 ) { Niwot::postError( "Subtracting off too many hours\n" ); return( -1 ); } # # Get new time values # ($asec,$amin,$ahr,$aday,$amon,$ayr,$wday,$yday,$isdst)=gmtime($advUtime); $ayr += 1900; # # Set up new time string # Note again that gmtime returns a month value between 0 and 11, # but the user will be expecting a value between 1 and 12 # $timeStr = sprintf( "%04d%02d%02d%02d", $ayr, $amon+1, $aday, $ahr ); return( $timeStr ); } #========================================= EOF =====================================