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