Show Contents Previous Page Next Page Appendix A - Standard Noncore Modules In this section... Show Contents Go to Top Previous Page Next PageIn This Appendix
The mod_perl distribution comes with a number of helper classes that add specialized functionality to the package. None of them are essential to write Apache modules in the Perl API or have any equivalent in the C-language API, but they can be very handy at times. Show Contents Go to Top Previous Page Next PageThe Apache::Registry class is essentially a CGI environment emulator that allows many CGI scripts to run without modification under mod_perl. Because there are many differences between CGI and the Apache API, Apache::Registry
has to do a great deal of work to accomplish this sleight of hand. It loads
the scripts in its designated directory, compiles them, and stores them persistently
in a memory structure. Before Apache::Registry runs a script, Despite its complexity, Apache::Registry is easy to set up. The standard configuration consists of an Alias directive and a <Location> section: Alias /perl/ /home/www/perl <Location /perl> SetHandler perl-script PerlHandler Apache::Registry Options +ExecCGI # optional PerlSendHeader On </Location> After restarting the server, you can place any (well, almost any) Perl CGI script into /home/www/perl (or the location of your choice) and make it executable. It runs just like an ordinary CGI script but will load much faster. The behavior of Apache::Registry can be tuned with the following directives: PerlTaintCheck
PerlSendHeader
PerlFreshRestart
PerlWarn
Apache::Registry has several debug levels which write various informational messages to the server error log. Apache::Registry scripts can change the debug level by importing Apache::Debug with its level pragma: use Apache::Debug level => $level; The debug level is a bit mask generated by ORing together some combination of the following values:
The current value of the debug level can be found in the package global The Apache::PerlRun handler is intended for Perl CGI scripts that depend strongly on the traditional one-process-per-execution CGI model and cannot deal with being invoked repeatedly in the same process. For example, a script that depends on a lot of global variables being uninitialized when it starts up is unlikely to work properly under Apache::Registry. Like Apache::Registry, Apache::PerlRun manages a directory of CGI scripts, launching them when they are requested. However, unlike Apache::Registry, this module does not cache compiled scripts between runs. A script is loaded and compiled freshly each time it is requested. However, Apache::PerlRun still avoids the overhead of starting a new Perl interpreter for each CGI script, so it's faster than traditional Perl CGI scripting but slower than Apache::Registry or vanilla Apache API modules. It offers a possible upgrade path for CGI scripts: move the script to Apache::PerlRun initially to get a modest performance bump. This gives you time to rework the script to make it globally clean so that it can run under Apache::Registry for the full performance benefit. The configuration section for running Apache::PerlRun is similar to Apache::Registry: Alias /perl-run/ /home/www/perl-run/ <Location /perl> SetHandler perl-script PerlHandler Apache::PerlRun Options +ExecCGI # optional PerlSendHeader On </Location> The Apache::PerlRun handler is only a small part of the picture. The rest of the Apache::PerlRun class provides subclassable methods that implement the functionality of Apache::Registry. The Apache::PerlRun handler simply uses a subset of these methods; other modules may override certain methods to implement the Apache::Registry enviroment with a few twists. However, these Apache::PerlRun class methods were not fully defined when this book was going to press. The Apache::RegistryLoader Class Show Contents Go to Top Previous Page Next PageOrdinarily, Apache::Registry scripts are not compiled until they are needed. This means that the very first time one of these scripts is required by a child process, there will be a delay while the script is loaded and compiled. Apache::RegistryLoader was designed to avoid this delay by precompiling Apache::Registry scripts during the server startup phase. In addition to minimizing loading time, it also reduces memory consumption because the Registry scripts are compiled into the single server parent process before it forks off the flock of child servers. The memory occupied by this precompiled code is then shared among the children, and although there doesn't appear to be a difference in child process size when you invoke ps (on Unix systems), overall memory consumption is reduced. See the mod_perl_tuning document in the mod_perl distribution for more details. Typically, you will invoke Apache::RegistryLoader from a Perl startup script. A typical entry looks like this: #!/usr/local/bin/perl use MyFavoriteModule1 (); use MyFavoriteModule2 (); ... use Apache::RegistryLoader (); my $rl = Apache::RegistryLoader->new; $rl->handler('/perl/test.pl'=> '/home/www/perl/test.pl'); $rl->handler('/perl/test2.pl'=> '/home/www/perl/test2.pl'); ... This code creates a new Apache::RegistryLoader object by invoking the class's new() Notice that handler() requires two arguments: the URI of the script to compile and its physical pathname. The reason you can't just provide one or the other is that the task of translating from a URI to a filename is usually done at request time by a translation handler. However, at server startup time there's no request to process, and therefore no way of getting at the translation handler. If you specify a URI only, Apache::RegistryLoader will try to interpret it relative to the server root. This will work only if the Apache::Registry directory URI is aliased to an identically named physical directory beneath the server root. Here's an example: # in httpd.conf ServerRoot /home/www Alias /perl/ /home/www/perl/ # in Perl startup script use Apache::RegistryLoader (); Apache::RegistryLoader->new->handler("/perl/test.pl"); Another solution is to provide a URI translation routine to the new() method at the time you create the Apache::RegistryLoader object. The Apache translation handlers can only be run during request time, so we must roll our own during start-up. The translation handler will take an argument consisting of the script URI and return the translated physical pathname to the file as its function result. The following code fragment illustrates how to precompile all .pl files in the directory ~www/perl/: # in perl.conf (or any other configuration file) PerlRequire conf/preload_scripts.pl # in conf/preload_scripts.pl #!/usr/local/bin/perl use Apache::RegistryLoader (); use DirHandle (); use strict; sub do_translate { my $uri = shift; return Apache->server_root_relative($uri); }; my $rl = Apache::RegistryLoader->new(trans => \&do_translate); my $dir = Apache->server_root_relative("perl/"); my $dh = DirHandle->new($dir) or die $!; foreach my $file ($dh->read) { next unless $file =~ /\.pl$/; $rl->handler("/perl/$file"); }Show Contents Go to Top Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |
HIVE: All information for read only. Please respect copyright! |