stas        2004/05/07 18:26:40

  Modified:    src/docs/2.0/api/APR Error.pod
  Log:
  explain the new exceptions mechanism
  
  Revision  Changes    Path
  1.2       +111 -8    modperl-docs/src/docs/2.0/api/APR/Error.pod
  
  Index: Error.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/api/APR/Error.pod,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -u -r1.1 -r1.2
  --- Error.pod 7 May 2004 21:38:48 -0000       1.1
  +++ Error.pod 8 May 2004 01:26:40 -0000       1.2
  @@ -1,26 +1,129 @@
   =head1 NAME
   
  -APR::Error - Perl API for APR/mod_perl exceptions
  +APR::Error - Perl API for APR/Apache/mod_perl exceptions
   
   
   
   
   =head1 Synopsis
   
  -  use APR::Error ();
  -
  -
  -
  -
  +  eval { $obj->mp_method() };
  +  if ($@ && $ref $@ eq 'APR::Error' && $@ == $some_code) {
  +      # handle the exception
  +  }
  +  else {
  +      die $@; # rethrow it
  +  }
   
   
   =head1 Description
   
  -C<APR::Error> provides ...
  -
  +Apache and APR API return status code for almost all methods, so if
  +you didn't check the return code and handled any possible problems,
  +you may have silent failures which may cause all kind of obscure
  +problems. On the other hand checking the status code after each call
  +is just too much of a kludge and makes quick prototyping/development
  +almost impossible, not talking about the code readability. Having
  +methods return status codes, also complicates the API if you need to
  +return other values.
  +
  +Therefore to keep things nice and make the API readable we decided to
  +not return status codes, but instead throw exceptions with
  +C<APR::Error> objects for each method that fails. If you don't catch
  +those exceptions, everything works transparently - perl will intercept
  +the exception object and C<die()> with a proper error message. So you
  +get all the errors logged without doing any work.
  +
  +Now, in certain cases you don't want to just die, but instead the
  +error needs to be trapped and handled. For example if some IO
  +operation times out, may be it is OK to trap that and try again. If we
  +were to die with an error message, you would have had to match the
  +error message, which is ugly, inefficient and may not work at all if
  +locale error strings are involved. Therefore you need to be able to
  +get the original status code that Apache or APR has generated. And the
  +exception objects give you that if you want to. Moreover the objects
  +contain additional information, such as the function name (in case you
  +were eval'ing several commands in one block), file and line number
  +where that function was invoked from. More attributes could be added
  +in the future.
  +
  +C<APR::Error> uses method overloading, such that in boolean and
  +numerical contexts, the object returns the status code; in the string
  +context the full error message is returned.
  +
  +When intercepting exceptions you need to check whether C<$@> is an
  +object (reference). If your application uses other exception objects
  +you additionally need to check whether this is a an C<APR::Error>
  +object. Therefore most of the time this is enough:
  +
  +  eval { $obj->mp_method() };
  +  if ($@ && $ref $@ && $@ == $some_code)
  +      warn "handled exception: $@";
  +  }
  +
  +But with other, non-mod_perl, exception objects you need to do:
  +
  +  eval { $obj->mp_method() };
  +  if ($@ && $ref $@ eq 'APR::Error' && $@ == $some_code)
  +      warn "handled exception: $@";
  +  }
  +
  +In theory you could even do:
  +
  +  eval { $obj->mp_method() };
  +  if ($@ && $@ == $some_code)
  +      warn "handled exception: $@";
  +  }
  +
  +but it's possible that the method will die with a plain string and not
  +an object, in which case C<$@ == $some_code> won't quite
  +work. Remember that mod_perl throws exception objects only when Apache
  +and APR fail, and in a few other special cases of its own (like
  +C<L<exit|docs::2.0::api::ModPerl::Util/C_exit_>>).
  +
  +  warn "handled exception: $@" if $@ && $ref $@;
  +
  +For example you wrote a code that performs L<a socket
  +read|docs::2.0::api::APR::Socket/C_recv_>:
  +
  +  my $buff = $sock->recv(1024);
  +  my $rlen = length $buff;
  +  warn "read $rlen bytes\n";
  +
  +and in certain cases it times out. The code will die and log the
  +reason for the failure, which is fine, but later on you decide that
  +you want to give the read another chance before dying. In which case
  +you rewrite the code to handle the exception like so:
  +
  +  use APR::Const -compile => qw(TIMEUP);
  +  my $buff = eval { $sock->recv(1024) };
  +  if ($@) {
  +     die $@ unless ref $@ && $@ == APR::TIMEUP;
  +     goto retry;
  +  }
  +  my $rlen = length $buff;
  +  warn "read $rlen bytes\n";
  +
  +Notice that we handle non-object and non-C<APR::Error> exceptions as
  +well, by simply rethrowing them.
  +
  +
  +Finally, the class is called C<APR::Error> because it needs to be used
  +outside mod_perl as well, when called from
  +C<L<APR|docs::2.0::api::APR>> applications written in perl.
  +
  +
  +=head1 API
  +
  +=head2 C<cluck>
   
  +C<cluck> is an equivalent of C<Carp::cluck> that works with
  +C<APR::Error> exception objects.
   
  +=head2 C<confess>
   
  +C<confess> is an equivalent of C<Carp::confess> that works with
  +C<APR::Error> exception objects.
   
   
   =head1 See Also
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to