Astro-FITS-CFITSIO-CheckStatus

 view release on metacpan or  search on metacpan

CheckStatus.pm  view on Meta::CPAN

{
  my $self = shift;
  my $old_ar = $self->{reset_usub};
  $self->{reset_usub} = shift if @_;
  $old_ar;
}

1;
__END__

=head1 NAME

Astro::FITS::CFITSIO::CheckStatus - automatically catch CFITSIO status errors

=head1 SYNOPSIS

  use Astro::FITS::CFITSIO::CheckStatus;

  # call Carp::croak upon error
  tie my $status, 'Astro::FITS::CFITSIO::CheckStatus';
  $fptr = Astro::FITS::CFITSIO::create_file( $file, $status );

  # call user specified function upon error:
  tie my $status, 'Astro::FITS::CFITSIO::CheckStatus', $mycroak;
  $fptr = Astro::FITS::CFITSIO::create_file( $file, $status );

  # call Log::Log4perl->logcroak;
  $logger = Log::Log4perl::get_logger();
  tie my $status, 'Astro::FITS::CFITSIO::CheckStatus', $logger;
  $fptr = Astro::FITS::CFITSIO::create_file( $file, $status );

=head1 DESCRIPTION

The B<CFITSIO> library uses the concept of a status variable passed to
each B<CFITSIO> function call to return an error status.  At present,
the B<Astro::FITS::CFITSIO> Perl interface mirrors the B<CFITSIO>
interfaces directly, and does not do anything special to handle error
returns (e.g., by throwing an exception).  It should be noted that
B<CFITSIO> routines will not perform their requested action if a
non-zero status value is passed in, so as long as the same status
variable is used throughout, B<CFITSIO> routines won't do extra work
after an error. However, this can lead to the situation where one does
not know at which step the error occurred.

In order to immediately catch an error, the status error must be
checked after each call to a B<CFITSIO> routine.  Littering one's code
with status variable checks is ugly.

This module resolves the impasse by tieing the status variable to a
class which will check the value every time it is set, and throw an
exception (via B<Carp::croak>) containing the B<CFITISO> error message
if the value is non-zero.  

The drawback to this approach is that only the (sometimes)
impenetrable B<CFITSIO> error message is available.  If the
tied variable is set equal to a string (which should not pass the
B<Scalar::Util::look_like_number()> test) or a subroutine, the string
or return value from the subroutine is prepended to the B<CFITSIO>
error message.  For example

  Astro::FITS::CFITSIO::open_file( 'file_does_not_exist.fits',
	   Astro::FITS::CFITSIO::READONLY(), $status = "Bad Open:" );

will result in:

  Bad Open: CFITSIO error: could not open the named file

The prefixing value may also be specified with the the B<utxt()>
method (see L<Class Methods>).  Whenever the status variable is set to
zero, the prefixing value is forgotten.  As Astro::FITS::CFITSIO sets
the status variable (whether zero or not) after every call to a
B<CFITSIO> function, this implies that the prefix will not reset after
every successful function call.  This behavior may be modified by the
B<reset_ustr()> and B<reset_usub()> class methods in L<Class Methods>.
Alternatively, the prefix may be reset by assigning C<undef> to the
status variable.

The caller may provide an alternate means of throwing the exception,
either by passing in a subroutine reference,

  tie my $status, 'Astro::FITS::CFITSIO::CheckStatus', 
           sub { die "An awful thing happened: @_" };
  $fptr = Astro::FITS::CFITSIO::create_file( $file, $status );

or a reference to a B<Log::Log4perl::Logger> object.

  $logger = Log::Log4perl::get_logger();
  tie my $status, 'Astro::FITS::CFITSIO::CheckStatus', $logger;
  $fptr = Astro::FITS::CFITSIO::create_file( $file, $status );

In the latter case, it will be equivalent to calling
C<$logger-E<gt>logcroak>.  An alternative interface is available via
the B<set_croak()> method (see L<Class Methods>).

=head2 Class Methods

The object to which the status variable is tied (accessible via the Perl
B<tied> function) has the following methods:

=over

=item set_croak

  $func = $obj->set_croak;
  $old_value = $obj->set_croak( sub { ... } )

Get or set the function called if the status variable is set to a
non-zero numerical value.  The function takes a single argument.

=item utxt

  $utxt = $obj->utxt;
  $old_value = $obj->utxt( "user error message" );

This provides access to the "user text" which may prefix the output
error message.  It is another interface to the functionality provided
by setting the status variable to either a string or a code reference.

=item etxt

  print $obj->etxt, "\n";



( run in 0.779 second using v1.01-cache-2.11-cpan-39bf76dae61 )