stas        2003/03/07 00:31:39

  Modified:    src/docs/2.0/api/Apache compat.pod
               src/docs/2.0/api/ModPerl MethodLookup.pod
               src/docs/2.0/devel/porting porting.pod
               src/docs/2.0/user/compat compat.pod
  Log:
  - add a help section on how to port the 1.0 code
  - add warnings not to use preload_all_modules() and Apache::compat in CPAN
  modules
  
  Revision  Changes    Path
  1.2       +58 -44    modperl-docs/src/docs/2.0/api/Apache/compat.pod
  
  Index: compat.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/api/Apache/compat.pod,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- compat.pod        27 Jan 2003 04:05:12 -0000      1.1
  +++ compat.pod        7 Mar 2003 08:31:39 -0000       1.2
  @@ -4,59 +4,73 @@
   
   =head1 SYNOPSIS
   
  +  # either add at the very beginning of startup.pl
  +  use Apache2
     use Apache::compat;
  +  # or httpd.conf
  +  PerlModule Apache2
  +  PerlModule Apache::compat
   
   =head1 DESCRIPTION
   
  -C<Apache::compat> provides mod_perl 1.0 compatibility layer.
  +C<Apache::compat> provides mod_perl 1.0 compatibility layer and can be
  +used to smooth the transition process to mod_perl 2.0.
   
  -It includes most of the functions that are deprecated in mod_perl
  -2.0. If your code uses any of these functions you should just load
  -this module at the server startup, and chances are that everything
  -should work as it did in 1.0.
  -
  -However, certain functionality is not optimized and therefore it's the
  -best to try to port your code not to use deprecated functions and stop
  -using the compatibility layer.
  +It includes functions that have changed their API or were removed in
  +mod_perl 2.0. If your code uses any of those functions, you should
  +load this module at the server startup, and everything should work as
  +it did in 1.0. If it doesn't please L<report the
  +bug|docs::2.0::user::help::help/Reporting_Problems>, but before you
  +do that please make sure that your code does work properly under
  +mod_perl 1.0.
  +
  +However, remember, that it's implemented in pure Perl and not C,
  +therefore its functionality is not optimized and it's the best to try
  +to L<port your
  +code|docs::2.0::devel::porting::porting> not to use deprecated
  +functions and stop using the compatibility layer.
  +
  +=head1 Use in CPAN Modules
  +
  +The short answer: B<Do not use> C<Apache::compat> in CPAN modules.
  +
  +The long answer:
  +
  +C<Apache::compat> is useful during the mod_perl 1.0 code
  +porting. Though remember that it's implemented in pure Perl. In
  +certain cases it overrides mod_perl 2.0 methods, because their API is
  +very different and doesn't map 1:1 to mod_perl 1.0. So if anything,
  +not under user's control, loads C<Apache::compat> user's code is
  +forced to use the potentially slower method. Which is quite bad.
  +
  +Some users may choose to keep using C<Apache::compat> in production
  +and it may perform just fine. Other users will choose not to use that
  +module, by porting their code to use mod_perl 2.0 API. However it
  +should be users' choice whether to load this module or not and not to
  +be enforced by CPAN modules.
  +
  +If you port your CPAN modules to work with mod_perl 2.0, you should
  +follow the L<porting guidelines|docs::2.0::devel::porting::porting>.
   
  -=head1 API
  -
  -META: complete
  -
  -Function arguments (if any) and return values are shown in the
  -function's synopsis.
  -
  -=over
  -
  -=item * $r-E<gt>header_in()
  -
  -  $r->header_in( $header_name, [$value] )
  -
  -Return the value of a client header:
  -
  -   $ct = $r->header_in($key);
  +Users that are stuck with CPAN modules preloading C<Apache::compat>,
  +can prevent this from happening by adding
   
  -Set or modify the value of a client header:
  +  $INC{'Apache/compat.pm'} = __FILE__;
   
  -   $r->header_in($key, $val);
  +at the very beginning of their I<startup.pl>. But this will most
  +certainly break the module that needed this module.
   
  -=item * $r-E<gt>header_out()
  -
  -  $r->header_out( $header, $value )
  -
  -Return the value of a response header:
  -
  -   $ct = $r->header_out($key);
  -
  -Set or modify the value of a response header:
  -
  -   $r->header_out($key, $val);
  -
  -You should not define any I<"Content-XXX"> headers by calling this
  -method, because these headers use their own specific methods.
  -
  -=item *
  +=head1 API
   
  -=back
  +You should be reading the mod_perl 1.0 L<API
  +docs|docs::1.0::api::index> for usage of the methods and functions
  +in this package, since what this module is doing is providing a
  +backwards compatibility and it makes no sense to duplicate
  +documentation.
  +
  +Another important document to read is: L<Migrating from mod_perl 1.0
  +to mod_perl 2.0|docs::2.0::user::compat::compat> which covers all
  +mod_perl 1.0 constants, functions and methods that have changed in
  +mod_perl 2.0.
   
   =cut
  
  
  
  1.2       +3 -2      modperl-docs/src/docs/2.0/api/ModPerl/MethodLookup.pod
  
  Index: MethodLookup.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/api/ModPerl/MethodLookup.pod,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MethodLookup.pod  24 Feb 2003 02:09:29 -0000      1.1
  +++ MethodLookup.pod  7 Mar 2003 08:31:39 -0000       1.2
  @@ -56,8 +56,9 @@
   =head2 preload_all_modules()
   
   The function C<preload_all_modules()> preloads all mod_perl 2.0
  -modules. This is similar to the mod_perl 1.0 behavior which has most
  -of its methods loaded at the startup.
  +modules, which implement their API in XS. This is similar to the
  +mod_perl 1.0 behavior which has most of its methods loaded at the
  +startup.
   
   CPAN modules developers should make sure their distribution loads each
   of the used mod_perl 2.0 modules explicitly, and not use this
  
  
  
  1.8       +199 -26   modperl-docs/src/docs/2.0/devel/porting/porting.pod
  
  Index: porting.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/devel/porting/porting.pod,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- porting.pod       20 Feb 2003 03:02:25 -0000      1.7
  +++ porting.pod       7 Mar 2003 08:31:39 -0000       1.8
  @@ -6,10 +6,10 @@
   
   If you have released an C<Apache::Foo> module on CPAN you may wonder
   what steps you should take to make your code working under mod_perl
  -2.0 while still preserving 1.0 compatibility. This document attempts
  -to answer some of the questions related to this issue.
  +2.0 while still preserving 1.0 backwards compatibility. This document
  +attempts to answer some of the questions related to this issue.
   
  -API changes are listed in L<the back compatibility
  +API changes are listed in L<the backwards compatibility
   document|docs::2.0::user::compat::compat/>.
   
   =head1 Should the Module Name Be Changed?
  @@ -24,8 +24,8 @@
   in Apache 2.0.
   
   Let's say that you have a module C<Apache::Friendly> whose release
  -version complient with mod_perl 1.0 is 1.57. You keep this version on
  -CPAN and release a new version 2.01 which is complient with 2.0 and
  +version compliant with mod_perl 1.0 is 1.57. You keep this version on
  +CPAN and release a new version 2.01 which is compliant with 2.0 and
   preserves the name of the module. It's possible that a user may need
   to have both versions of the module on the same machine. Since the two
   have the same name they obviously cannot live under the same tree. One
  @@ -42,7 +42,7 @@
   even add to the core a supporting module that will handle this
   functionality.
   
  -The second step is to change the documentation of your 2.0 complient
  +The second step is to change the documentation of your 2.0 compliant
   module to say:
   
     use Apache2 ();
  @@ -95,36 +95,209 @@
         # some 2.0 specific code
     }
   
  -=head1 Adjusting Modules to Work with 1.0 and 2.0.
  +=head1 Porting mod_perl 1.0 Modules to Work with mod_perl 2.0.
   
  -It's possible to adjust your module to work with both 2.0 and
  -1.0. This is quite easy if your aren't using XS. Interfaces that are
  -deprecated in 2.0 can be enabled by adding:
  +The following sections will guide you through the steps of porting
  +your modules to mod_perl 2.0.
   
  -  use Apache::compat();
  +=head2 Figuring Out What Modules Need to be Loaded
   
  -in the code or I<startup.pl>. The API changes are documented in L<the
  -back compatibility document|docs::2.0::user::compat::compat/>.
  -
  -The variable C<$mod_perl::VERSION> should be used in conditionals to
  -use the appropriate code for 1.0 or 2.0. You can use it to load
  -C<Apache::compat> if running under mod_perl 2.0:
  +It'd be certainly nice to have our mod_perl 1.0 code run on the
  +mod_perl 2.0 server unmodified. So first of all, try your luck and
  +test the code.
  +
  +It's almost certain that your code won't work when you try, because
  +mod_perl 2.0 splits the functionality across many modules, and you
  +have to load them before the methods that live in them can be used. So
  +the first step is to L<figure out what these modules
  +are|docs::2.0::api::ModPerl::MethodLookup> and C<use()> them.
  +
  +For example if we have a mod_perl 1.0 code snippet:
  +
  +  $r->content_type('text/plain');
  +  $r->print("Hello cruel world!");
  +
  +and we run it, mod_perl 2.0 will complain that the method
  +C<content_type> can't be found. So off we go to figure out which
  +module provides this method:
  +
  +  % perl -MApache2 -MModPerl::MethodLookup -le \
  +     'print((ModPerl::MethodLookup::lookup_method(shift))[0])' \
  +      content_type
  +
  +and we get:
  +
  +  to use method 'content_type' add:
  +          use Apache::RequestRec ();
  +
  +We copy-n-paste this snippet to our code and mod_perl doesn't complain
  +about this particular method anymore (of course after you've either
  +restarted the server or used
  +C<L<Apache::Reload|docs::2.0::api::Apache::Reload>>). However now it
  +complains about the missing C<print> method.  We know the drill, we
  +will use the above snippet again and add the missing module. Since we
  +have to repeat this procedure more than once why not defining C<L<an
  +alias|docs::2.0::api::ModPerl::MethodLookup/Command_Line_Lookups>> and 
  +then use it:
  +
  +  % lookup print
  +  There is more than one class with method 'print'
  +  try one of:
  +        use Apache::RequestIO ();
  +        use Apache::Filter ();
  +
  +Hmm, indeed there is more than one package that has this method. Since
  +we know, that we call it with the C<$r> object, it must be the
  +C<Apache::RequestIO> module that we are after. Indeed, loading this
  +module solves the problem.
  +
  +The issue of picking the right module, when more than one matches, can
  +be resolved programmatically--
  +C<L<lookup_method|docs::2.0::api::ModPerl::MethodLookup/lookup_method__>>
  +accepts an object as an optional second argument, which is used if
  +there is more than one module that contains the method in
  +question. C<ModPerl::MethodLookup> knows that C<Apache::RequestIO>
  +expects an object of type C<Apache::RequestRec>, and C<Apache::Filter>
  +of type C<Apache::Filter>. So if we call:
  +
  +  ModPerl::MethodLookup::lookup_method($r, 'print');
  +
  +only one module will be matched. This functionality can be used in
  +C<L<AUTOLOAD|docs::2.0::api::ModPerl::MethodLookup/AUTOLOAD>>.
  +
  +Now if you use a wide range of used APIs, the process of finding all
  +the modules that need to be loaded can be quite frustrating. In that
  +case you may find the function
  +C<L<preload_modules()|docs::2.0::api::ModPerl::MethodLookup/preload_all_modules__>>
  +to be right pill. This function preloads B<all> mod_perl 2.0 modules,
  +implementing their API in XS. However before going in production, you
  +should consider removing the call to this function and to load only
  +the modules that are used, in order to save memory. CPAN module
  +developers in no way should be tempted to call this function from
  +their modules, because it prevents from the user of their module to
  +optimize the memory usage.
  +
  +=head2 Handling Missing and Modified mod_perl 1.0 APIs
  +
  +mod_perl 2.0 had to modify or remove certain APIs to adhere to the
  +substantial changes the Apache C API went through. It wasn't core
  +developers desire to break the API, but simply there was no other
  +choice.  If you figure out that some method is reported missing and
  +can't be found using
  +L<ModPerl::MethodLookup|/Figuring_Out_What_Modules_Need_to_be_Loaded>,
  +chances are that this method doesn't exist in mod_perl 2.0 API. Also
  +it's possible that the method exists, but it still doesn't work, since
  +its prototype has been changed (e.g., some functions now require a
  +pool object). Instead of guessing, refer to L<the backwards
  +compatibility
  +document|docs::2.0::user::compat::compat/> to learn which APIs were
  +modified or removed.
  +
  +If the code includes methods whose API have been changed or these
  +methods no longer exist, you have to options:
  +
  +=over
  +
  +=item 1
  +
  +Port your code to use the mod_perl 2.0 API.
  +
  +=item 2
  +
  +Use the C<L<Apache::compat|docs::2.0::api::Apache::compat>> module.
  +
  +=back
  +
  +If you need to have your code working with both mod_perl versions,
  +which is the case for CPAN module writers who wish to continue to
  +maintain a single code base, rather than supplying two separate
  +implementations, the variable C<$mod_perl::VERSION> should be used.
  +
  +For example, the method C<send_http_header> doesn't exist in mod_perl
  +2.0 API. Therefore our code that is supposed to work under both
  +mod_perl versions may look like this:
   
     use mod_perl;
  -  if ($mod_perl::VERSION >= 2.0) {
  -      require Apache::compat;
  +  use constant MP2 => ($mod_perl::VERSION >= 1.99);
  +  ...
  +  sub handler {
  +      my $r = shift;
  +      $r->content_type('text/html');
  +      $r->send_http_header() unless MP2;
  +      ...
     }
   
  -META: while 2.0 is not released, use:
  +The C<L<Apache::compat|docs::2.0::api::Apache::compat>> module tries
  +to hide the changes in API prototypes and implement the removed
  +methods and functions. However it does that in pure Perl, so things
  +are going to be slower. This module is useful for the transition
  +stage, but you are better off to port your code to use the mod_perl
  +2.0 API.
  +
  +It's especially important to repeat that C<L<CPAN module developers are
  +requested not to use this module in their
  +code|docs::2.0::api::Apache::compat/Use_in_CPAN_Modules>>, since it takes the 
control over
  +performance away from users.
  +
  +However the C<L<Apache::compat|docs::2.0::api::Apache::compat>> module
  +is also useful to learn how the API have been changed. Simply look at
  +the source code and see how it should be implemented in mod_perl 2.0.
  +For example mod_perl 2.0 doesn't provide the C<Apache-E<>gensym>
  +method. If we look at the C<Apache/compat.pm> source, we can see that
  +it loads the module C<Symbol> and calls its C<gensym()> function
  +instead. mod_perl 2.0 works with Perl versions 5.6 and higher, and
  +C<Symbol.pm> is included in the core distribution since that version,
  +so was no reason to keep providing C<Apache-E<>gensym>. So if the
  +original code looked as:
  +
  +  my $fh = Apache->gensym;
  +  open $fh, $file or die "Can't open $file: $!";
   
  -  if ($mod_perl::VERSION >= 1.99) {
  +in order to port it mod_perl 2.0 we can write:
   
  -XS modules will need I<Makefile.PL>/C<#ifdef> logic to work with both
  -versions.  But the applications that use them should not need to know
  -the difference.
  +  use mod_perl;
  +  use constant MP2 => ($mod_perl::VERSION >= 1.99);
  +  ...
  +  require Symbol if MP2;
  +  ...
  +  
  +  my $fh = MP2 ? Symbol::gensym : Apache->gensym;
  +  open $fh, $file or die "Can't open $file: $!";
  +
  +If we don't need to keep the backwards compatibility with mod_perl
  +1.0, we don't even have to use the C<Symbol> module, since under Perl
  +version 5.6 and higher we can just do:
  +
  +  open my $fh, $file or die "Can't open $file: $!";
  +
  +
  +=head2 Porting XS Code and Makefile.PL
  +
  +If your module's XS code relies on Apache and mod_perl C APIs, it's
  +very likely that you will have to adjust the XS code to the Apache 2.0
  +and mod_perl 2.0 C API.
  +
  +The C API has changed a lot, so chances are that you are much better
  +off not to mix the two APIs in the same XS file. However if you do
  +want to mix the two you will have to use something like the following:
  +
  +  #include ap_mmn.h
  +  /* ... */
  +  #if AP_MODULE_MAGIC_AT_LEAST(20020329,1)
  +      /* 2.0 code */
  +  #else
  +      /* 1.0 code */
  +  #endif
  +
  +The C<20020329.1> is the value of the magic version number matching
  +Apache 2.0.36, the earliest Apache version supported by mod_perl 2.0.
  +
  +As for porting I<Makefile.PL>, it's only an issue if it was using
  +C<Apache::src>. A new configuration system is in works. So watch this
  +space for updates on this issue.
   
  -META: example? probably the best to use some existing module that
  -co-exists with the two versions.
  +META: ModPerl::MM is a likely candidate for the new replacement of
  +Apache::src
   
   
   =head1 Thread Safety
  
  
  
  1.54      +4 -3      modperl-docs/src/docs/2.0/user/compat/compat.pod
  
  Index: compat.pod
  ===================================================================
  RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/compat/compat.pod,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- compat.pod        7 Mar 2003 05:14:42 -0000       1.53
  +++ compat.pod        7 Mar 2003 08:31:39 -0000       1.54
  @@ -160,9 +160,10 @@
   be used to find out which modules need to be used. This module also
   provides a function
   
C<L<preload_all_modules()|docs::2.0::api::ModPerl::MethodLookup/preload_all_modules__>>
  -that will load all mod_perl 2.0 modules, which is useful when one
  -starts to port their mod_perl 1.0 code, though preferrably avoided in
  -the production environment.
  +that will load all mod_perl 2.0 modules, implementing their API in XS,
  +which is useful when one starts to port their mod_perl 1.0 code,
  +though preferrably avoided in the production environment if you want
  +to save memory.
   
   =head1 C<Apache::Registry>, C<Apache::PerlRun> and Friends
   
  
  
  

Reply via email to