stas 02/01/09 10:09:49 Modified: src/docs/2.0/devel/help help.pod src/docs/2.0/user/config config.pod src/docs/2.0/user/design design.pod src/docs/2.0/user/overview overview.pod Log: - lots of typos and pod markup fixes Revision Changes Path 1.4 +2 -1 modperl-docs/src/docs/2.0/devel/help/help.pod Index: help.pod =================================================================== RCS file: /home/cvs/modperl-docs/src/docs/2.0/devel/help/help.pod,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- help.pod 31 Dec 2001 10:33:02 -0000 1.3 +++ help.pod 9 Jan 2002 18:09:49 -0000 1.4 @@ -147,6 +147,7 @@ =item * +=back =head2 Apache Portable Runtime (APR) @@ -211,7 +212,7 @@ =back - +=cut 1.3 +1 -1 modperl-docs/src/docs/2.0/user/config/config.pod Index: config.pod =================================================================== RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/config/config.pod,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- config.pod 27 Dec 2001 11:51:54 -0000 1.2 +++ config.pod 9 Jan 2002 18:09:49 -0000 1.3 @@ -154,7 +154,7 @@ =item GlobalRequest -Setup the global request_rec for use with Apache->request +Setup the global request_rec for use with Apache-E<gt>request =item ParseHeaders 1.2 +7 -7 modperl-docs/src/docs/2.0/user/design/design.pod Index: design.pod =================================================================== RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/design/design.pod,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- design.pod 27 Dec 2001 12:02:47 -0000 1.1 +++ design.pod 9 Jan 2002 18:09:49 -0000 1.2 @@ -73,7 +73,7 @@ At request time, If any Perl*Handlers are configured, an available interpreter is selected from the pool. As there is a I<conn_rec> and I<request_rec> per thread, a pointer is saved in either the -conn_rec->pool or request_rec->pool, which will be used for the +conn_rec-E<gt>pool or request_rec-E<gt>pool, which will be used for the lifetime of that request. For handlers that are called when threads are not running (PerlChild{Init,Exit}Handler), the parent interpreter is used. Several configuration directives control the interpreter @@ -161,11 +161,11 @@ Perl*Handlers are now "compiled", that is, the various forms of: - PerlResponseHandler MyModule->handler - # defaults to MyModule::handler or MyModule->handler - PerlResponseHandler MyModule - PerlResponseHandler $MyObject->handler - PerlResponseHandler 'sub { print "foo\n" }' + PerlResponseHandler MyModule->handler + # defaults to MyModule::handler or MyModule->handler + PerlResponseHandler MyModule + PerlResponseHandler $MyObject->handler + PerlResponseHandler 'sub { print "foo\n" }' are only parsed once, unlike 1.xx which parsed every time the handler was used. there will also be an option to parse the handlers at @@ -382,7 +382,7 @@ generated and compiled. The 2.0 version will provide the same functionality, but will not require the generated xs module. -=head1 <Perl> Configuration Sections +=head1 E<lt>PerlE<gt> Configuration Sections The ability to write configuration in Perl will carry over from 1.x, but will likely be implemented much different internally. The mapping 1.2 +594 -591 modperl-docs/src/docs/2.0/user/overview/overview.pod Index: overview.pod =================================================================== RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/overview/overview.pod,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- overview.pod 27 Dec 2001 12:02:47 -0000 1.1 +++ overview.pod 9 Jan 2002 18:09:49 -0000 1.2 @@ -11,28 +11,28 @@ more and more difficult to maintain, in large part to provide compatibility between the many different flavors of Apache and Perl. And, compatibility across these versions and flavors is a more -diffcult goal for mod_perl to reach that a typical Apache or Perl +difficult goal for mod_perl to reach that a typical Apache or Perl module, since mod_perl reaches a bit deeper into the corners of Apache and Perl internals than most. Discussions of the idea to rewrite -mod_perl as version 2.0 started in 1998, but never made it much further -than an idea. When Apache 2.0 development was underway it became -clear that a rewrite of mod_perl would be required to adjust to the -new Apache architechure and API. +mod_perl as version 2.0 started in 1998, but never made it much +further than an idea. When Apache 2.0 development was underway it +became clear that a rewrite of mod_perl would be required to adjust to +the new Apache architecture and API. Of the many changes happening in Apache 2.0, the one which has the -most impact on mod_perl is the introduction of threads to the overall -design. Threads have been a part of Apache on the win32 side since -the Apache port was introduced. The mod_perl port to win32 happened -in verison 1.00b1, released in June of 1997. This port enabled -mod_perl to compile and run in a threaded windows environment, with -one major caveat: only one concurrent mod_perl request could be -handled at any given time. This was due to the fact that Perl did not +most significant impact on mod_perl is the introduction of threads to +the overall design. Threads have been a part of Apache on the win32 +side since the Apache port was introduced. The mod_perl port to win32 +happened in version 1.00b1, released in June of 1997. This port +enabled mod_perl to compile and run in a threaded windows environment, +with one major caveat: only one concurrent mod_perl request could be +handled at any given time. This was due to the fact that Perl did not introduce thread safe interpreters until version 5.6.0, released in -March of 2000. Contrary to popular belief, the "thread support" +March of 2000. Contrary to popular belief, the "threads support" implemented in Perl 5.005 (released July 1998), did not make Perl -thread safe internally. Well before that version, Perl had the notion -of "Multiplicity", which allowed multiple interpreter instances in the -same process. However, these instances were not thread safe, that is, +thread-safe internally. Well before that version, Perl had the notion +of "Multiplicity", which allowed multiple interpreter instances in the +same process. However, these instances were not thread safe, that is, concurrent callbacks into multiple interpreters were not supported. It just so happens that the release of Perl 5.6.0 was nearly at the @@ -46,27 +46,29 @@ implementation based on lessons learned over the 4.5 years since mod_perl was introduced. -This paper and talk assume basic knowlege of mod_perl 1.xx features -and will focus only the differences mod_perl-2.00 will bring. +This document assumes basic knowlege of mod_perl-1.x features and will +focus only the differences mod_perl-2.0 will bring. -Note 1: The Apache and mod_perl APIs mentioned in this paper are both in -an "alpha" state and subject to change. +Note 1: The Apache and mod_perl APIs mentioned in this document are +both in an "alpha" state and subject to change. -Note 2: Some of the mod_perl APIs mentioned in this paper do not even -exist and are subject to be implemented, in which case you would be -redirected to "Note 1". +Note 2: Some of the mod_perl APIs mentioned in this document do not +even exist and are subject to be implemented, in which case you would +be redirected to "Note 1". =head1 Apache 2.0 Summary Note: This section will give you a brief overview of the changes in -Apache 2.0, just enough to understand where mod_perl will fit in. For -more details on Apache 2.0 consult the papers by Ryan Bloom. +Apache 2.0, just enough to understand where mod_perl-2.0 fits in. For +more details on Apache 2.0 consult the documents by Ryan Bloom. + +META: URLs? =head2 MPMs - Multi-Processing Model Modules In Apache 1.3.x concurrent requests were handled by multiple processes, and the logic to manage these processes lived in one place, -I<http_main.c>, 7200 some odd lines of code. If Apache 1.3.x is +I<http_main.c>, 7700 some odd lines of code. If Apache 1.3.x is compiled on a Win32 system large parts of this source file are redefined to handle requests using threads. Now suppose you want to change the way Apache 1.3.x processes requests, say, into a DCE RPC @@ -75,11 +77,11 @@ with a C<-DSTANDALONE_MAIN=your_function> compile time flag. Neither of which is a clean, modular mechanism. -Apache-2.0 solves this problem by intoducing I<Multi Processing Model +Apache-2.0 solves this problem by introducing I<Multi Processing Model modules>, better known as I<MPMs>. The task of managing incoming requests is left to the MPMs, shrinking I<http_main.c> to less than 500 lines of code. Several MPMs are included with Apache 2.0 in the -I<src/modules/mpm> directory: +I<server/mpm> directory: =over 4 @@ -88,22 +90,23 @@ The I<prefork> module emulates 1.3.x's preforking model, where each request is handled by a different process. -=item threaded +=item worker -This MPMs implements a hybrid multi-process multi-threaded -approach based on the I<pthreads> standard. +This MPMs implements a hybrid multi-process multi-threaded approach +based on the I<pthreads> standard. It uses one acceptor thread, +multiple worker threads. -=item os2/winnt/beos +=item spmt_os2, mpmt_os2, netware, win32 and beos These MPMs also implement the hybrid multi-process/multi-threaded model, with each based on native OS thread implementations. =item perchild -The I<perchild> MPM is similar to the I<threaded> MPM, but is extended +The I<perchild> MPM is similar to the I<worker> MPM, but is extended with a mechanism which allows mapping of requests to virtual hosts to -a process running under the user id and group configured for that host. -This provides a robust replacement for the I<suexec> mechanism. +a process running under the user id and group configured for that +host. This provides a robust replacement for the I<suexec> mechanism. =back @@ -112,33 +115,33 @@ Apache 1.3.x has been ported to a very large number of platforms including various flavors of unix, win32, os/2, the list goes on. However, in 1.3.x there was no clear-cut, pre-designed portability -layer for third-party modules to take advantage of. APR provides this -API layer in a very clean way. For mod_perl, APR will assist a great -deal with portability. Combined with the portablity of Perl, mod_perl-2.0 -needs only to implement a portable build system, the rest comes "for free". -A Perl interface will be provided for certain areas of APR, such as -the shared memory abstraction, but the majority of APR will be used by -mod_perl "under the covers". +layer for third-party modules to take advantage of. APR provides this +API layer in a very clean way. APR assists a great deal with mod_perl +portability. Combined with the portablity of Perl, mod_perl-2.0 needs +only to implement a portable build system, the rest comes "for free". +A Perl interface is provided for certain areas of APR, such as the +shared memory abstraction, but the majority of APR is used by mod_perl +"under the covers". =head2 New Hook Scheme In Apache 1.3, modules were registered using the I<module> structure, normally static to I<mod_foo.c>. This structure contains pointers to -the command table, config create/merge functions, response handler -table and function pointers for all of the other hooks, such as -I<child_init> and I<check_user_id>. In 2.0, this structure has been -pruned down to the first three items mention and a new function -pointer added called I<register_hooks>. It is the job of -I<register_hooks> to register functions for all other hooks (such as -I<child_init> and I<check_user_id>). Not only is hook registration -now dynamic, it is also possible for modules to register more than one -function per hook, unlike 1.3. The new hook mechanism also makes it -possible to sort registered functions, unlike 1.3 with function -pointers hardwired into the module structure, and each module +the command table, configuration creation and merging functions, +response handler table and function pointers for all of the other +hooks, such as I<child_init> and I<check_user_id>. In Apache 2.0, +this structure has been pruned down to the first three items mentioned +and a new function pointer added called I<register_hooks>. It is the +job of I<register_hooks> to register functions for all other hooks +(such as I<child_init> and I<check_user_id>). Not only is hook +registration now dynamic, it is also possible for modules to register +more than one function per hook, unlike 1.3. The new hook mechanism +also makes it possible to sort registered functions, unlike 1.3 with +function pointers hardwired into the module structure, and each module structure into a linked list. Order in 1.3 depended on this list, -which was possible to order using compile-time and configuration-time +which was possible to order using compile-time and startup-time configuration, but that was left to the user. Whereas in 2.0, the -add_hook functions accept an order preference parameter, those +I<add_hook> functions accept an order preference parameter, those commonly used are: =over 4 @@ -151,24 +154,25 @@ =back -For mod_perl, dynamic registration provides a cleaner way to bypass the -I<Perl*Handler> configuration. By simply adding this configuration: +For mod_perl, dynamic registration provides a cleaner way to bypass +the C<Perl*Handler> configuration directives. By simply adding this +configuration: - PerlModule Apache::Foo + PerlModule Apache::Foo -I<Apache/Foo.pm> can register hooks itself at server startup: +C<Apache::Foo> can register hooks itself at server startup: - Apache::Hook->add(PerlAuthenHandler => \&authenticate, Apache::Hook::MIDDLE); - Apache::Hook->add(PerlLogHandler => \&logger, Apache::Hook::LAST); + Apache::Hook->add(PerlAuthenHandler => \&authenticate, Apache::Hook::MIDDLE); + Apache::Hook->add(PerlLogHandler => \&logger, Apache::Hook::LAST); However, this means that Perl subroutines registered via this -mechanism will be called for *every* request. It will be left to that -subroutine to decide if it was to handle or decline the given phase. -As there is overhead in entering the Perl runtime, it will most likely -be to your advantage to continue using I<Perl*Handler> configuration -to reduce this overhead. If it is the case that your I<Perl*Handler> -should be invoked for every request, the hook registration mechanism -will save some configuration keystrokes. +mechanism will be called for B<every> request. It will be left to +that subroutine to decide if it was to handle or decline the given +phase. As there is overhead in entering the Perl runtime, it will +most likely be to your advantage to continue using C<Perl*Handler> +configuration directives to reduce this overhead. If it is the case +that your C<Perl*Handler> should be invoked for every request, the +hook registration mechanism will save some configuration keystrokes. =head2 Configuration Tree @@ -178,33 +182,33 @@ first parsed into a tree structure, which is then walked to pass data down to the modules. This tree is then left in memory with an API for accessing it at request time. The tree can be quite useful for other -modules. For example, in 1.3, mod_info has it's own configuration +modules. For example, in 1.3, mod_info has its own configuration parser and parses the configuration files each time you access it. With 2.0 there is already a parse tree in memory, which mod_info can -then walk to output it's information. +then walk to output its information. If a mod_perl 1.xx module wants access to configuration information, -there are two approaches. A module can "subclass" directive handlers, -saving a copy of the data for itself, then returning B<DECLINE_CMD> so +there are two approaches. A module can "subclass" directive handlers, +saving a copy of the data for itself, then returning B<DECLINE_CMD> so the other modules are also handed the info. Or, the -C<$Apache::Server::SaveConfig> variable can be set to save <Perl> -configuration in the C<%Apache::ReadConfig::> namespace. Both methods -are rather kludgy, version 2.0 will provide a Perl interface to the -Apache configuration tree. +C<$Apache::Server::SaveConfig> variable can be set to save +E<lt>PerlE<gt> configuration in the C<%Apache::ReadConfig::> +namespace. Both methods are rather kludgy, version 2.0 will provide a +Perl interface to the Apache configuration tree. =head2 Filtering Filtering of Perl modules output has been possible for years since -tied filehandle support was added to Perl. There are several modules, -such as I<Apache::Filter> and I<Apache::OutputChain> which have been -written to provide mechanisms for filtering the C<STDOUT> "stream". -There are several of these modules because no one approach has quite +tied filehandle support was added to Perl. There are several modules, +such as C<Apache::Filter> and C<Apache::OutputChain> which have been +written to provide mechanisms for filtering the C<STDOUT> stream. +There are several of these modules because no one's approach has quite been able to offer the ease of use one would expect, which is due simply to limitations of the Perl tied filehandle design. Another problem is that these filters can only filter the output of other Perl modules. C modules in Apache 1.3 send data directly to the client and there is no clean way to capture this stream. Apache 2.0 has solved -this problem by introducing a filtering API. With the baseline i/o +this problem by introducing a filtering API. With the baseline I/O stream tied to this filter mechansim, any module can filter the output of any other module, with any number of filters in between. @@ -213,7 +217,7 @@ Apache 1.3 is hardwired to speak only one protocol, HTTP. Apache 2.0 has moved to more of a "server framework" architecture making it possible to plugin handlers for protocols other than HTTP. The -protocol module design also abstracts the transport layer so protocols +protocol module design also abstracts the transport layer so protocols such as SSL can be hooked into the server without requiring modifications to the Apache source code. This allows Apache to be extended much further than in the past, making it possible to add @@ -227,32 +231,33 @@ =head2 Perl 5.6 Thread safe Perl interpreters, also known as "ithreads" (Intepreter -Threads) provide the mechanism need for mod_perl to adapt to the -Apache 2.0 thread architecture. This mechanism is a compile time +Threads) provide the mechanism needed for mod_perl to adapt to the +Apache 2.0 threads architecture. This mechanism is a compile time option which encapsulates the Perl runtime inside of a single -I<PerlInterpreter> structure. With each interpreter instance +C<PerlInterpreter> structure. With each interpreter instance containing its own symbol tables, stacks and other Perl runtime mechanisms, it is possible for any number of threads in the same process to concurrently callback into Perl. This of course requires -each thread to have it's own I<PerlInterpreter> object, or at least +each thread to have its own C<PerlInterpreter> object, or at least that each instance is only access by one thread at any given time. -mod_perl-1.xx has only a single I<PerlInterpreter>, which is +mod_perl-1.xx has only a single C<PerlInterpreter>, which is contructed by the parent process, then inherited across the forks to child processes. mod_perl-2.0 has a configurable number of -I<PerlInterpreters> and two classes of interpreters, I<parent> and +C<PerlInterpreters> and two classes of interpreters, I<parent> and I<clone>. A I<parent> is like that in 1.xx, the main interpreter -created at startup time which compiles any pre-loaded Perl code. -A I<clone> is created from the parent using the Perl API -I<perl_clone()> function. At request time, I<parent> interpreters are -only used for making more I<clones>, as they are the interpreters -which actually handle requests. Care is taken by Perl to copy only -mutable data, which means that no runtime locking is required and -read-only data such as the syntax tree is shared from the I<parent>. +created at startup time which compiles any pre-loaded Perl code. A +I<clone> is created from the parent using the Perl API I<perl_clone()> +function. At request time, I<parent> interpreters are only used for +making more I<clones>, as the I<clones> are the interpreters which +actually handle requests. Care is taken by Perl to copy only mutable +data, which means that no runtime locking is required and read-only +data such as the syntax tree is shared from the I<parent>, which +should reduce the overall mod_perl memory footprint. =head2 New mod_perl Directives for Threaded MPMs -Rather than create a I<PerlInterperter> per-thread by default, +Rather than create a C<PerlInterperter> per-thread by default, mod_perl creates a pool of interpreters. The pool mechanism helps cut down memory usage a great deal. As already mentioned, the syntax tree is shared between all cloned interpreters. If your server is serving @@ -317,17 +322,17 @@ By default, an interpreter will be held for the lifetime of the request, equivalent to this configuration: - PerlInterpScope request + PerlInterpScope request For example, if a PerlAccessHandler is configured, an interpreter will -selected before it is run and not released until after the logging +be selected before it is run and not released until after the logging phase. Intepreters will be shared across subrequests by default, however, it is possible configure the intepreter scope to be per-subrequest on a per-directory basis: - PerlInterpScope subrequest + PerlInterpScope subrequest With this configuration, an autoindex generated page for example would select an interpreter for each item in the listing that is configured @@ -335,7 +340,7 @@ It is also possible to configure the scope to be per-handler: - PerlInterpScope handler + PerlInterpScope handler With this configuration, an interpreter will be selected before PerlAccessHandlers are run, and putback immediately afterwards, before @@ -351,7 +356,7 @@ maintain state for the lifetime of an ftp connection, it is possible to do so on a per-virtualhost basis: - PerlInterpScope connection + PerlInterpScope connection =back @@ -375,12 +380,12 @@ =head1 Thread Item Pool API As we discussed, mod_perl implements a pool mechanism to manage -I<PerlInterpreters> between threads. This mechanism has been +C<PerlInterpreters> between threads. This mechanism has been abstracted into an API known as "tipool", I<Thread Item Pool>. This pool can be used to manage any data structure, in which you wish to have a smaller number than the number of configured threads. A good example of such a data structure is a database connection handle. -The I<Apache::DBI> module implements persisent connections for 1.xx, +The C<Apache::DBI> module implements persisent connections for 1.xx, but may result in each child maintaining its own connection, when it is most often the case that number of connections is never needed concurrently. The TIPool API provides a mechanism to solve this @@ -391,19 +396,19 @@ =item new Create a new thread item pool. This constructor is passed an -I<Apache::Pool> object, a hash reference to pool configuration parameters, +C<Apache::Pool> object, a hash reference to pool configuration parameters, a hash reference to pool callbacks and an optional userdata variable which is passed to callbacks: - my $tip = Apache::TIPool->new($p, - {Start => 3, Max => 6}, - {grow => \&new_connection, - shrink => \&close_connection}, - \%my_config); - -The configuration parameters, I<Start>, I<Max>, I<MinSpare>, I<MaxSpare> -and I<MaxRequests> configure the pool for your items, just as the -I<PerlInterp*> directives do for I<PerlInterpreters>. + my $tip = Apache::TIPool->new($p, + {Start => 3, Max => 6}, + {grow => \&new_connection, + shrink => \&close_connection}, + \%my_config); + +The configuration parameters, C<Start>, C<Max>, C<MinSpare>, C<MaxSpare> +and C<MaxRequests> configure the pool for your items, just as the +C<PerlInterp*> directives do for C<PerlInterpreters>. The I<grow> callback is called to create new items to be added to the pool, I<shrink> is called when an item is removed from the pool. @@ -417,14 +422,14 @@ by calling the configured I<grow> callback. Otherwise, the I<pop> method will block until an item is available. - my $item = $tip->pop; + my $item = $tip->pop; =item putback This method gives an item (returned from I<pop>) back to the pool, which is pushed into the head of the available list: - $tip->putback($item); + $tip->putback($item); =back @@ -435,85 +440,86 @@ =head2 Apache::DBIPool -Now we will take a look at how to make I<DBI> take advantage of -I<TIPool> API with the I<Apache::DBIPool> module. The module -configuration in httpd.conf will look something like so: - - PerlModule Apache::DBIPool - - <DBIPool dbi:mysql:db_name> - DBIPoolStart 10 - DBIPoolMax 20 - DBIPoolMaxSpare 10 - DBIPoolMinSpare 5 - DBIUserName dougm - DBIPassWord XxXx - </DBIPool> - -The module is loaded using the I<PerlModule> directive just as with -other modules. TIPools are then configured using I<DBIPool> -configuration sections. The argument given to the container is the -I<dsn> and within are the pool directives I<Start>, I<Max>, -I<MaxSpare> and I<MinSpare>. The I<UserName> and I<PassWord> -directives will be passed to the I<DBI> I<connect> method. -There can be any number of I<DBIPool> containers, provided each I<dsn> +Now we will take a look at how to make C<DBI> take advantage of +C<TIPool> API with the C<Apache::DBIPool> module. The module +configuration in I<httpd.conf> will look something like so: + + PerlModule Apache::DBIPool + + <DBIPool dbi:mysql:db_name> + DBIPoolStart 10 + DBIPoolMax 20 + DBIPoolMaxSpare 10 + DBIPoolMinSpare 5 + DBIUserName dougm + DBIPassWord XxXx + </DBIPool> + +The module is loaded using the C<PerlModule> directive just as with +other modules. TIPools are then configured using C<DBIPool> + configuration sections. The argument given to the container is the +C<dsn> and within are the pool directives C<Start>, C<Max>, +C<MaxSpare> and C<MinSpare>. The C<UserName> and C<PassWord> +directives will be passed to the C<DBI> C<connect> method. +There can be any number of C<DBIPool> containers, provided each C<dsn> is different, and/or each container is inside a different -I<VirtualHost> container. +C<VirtualHost> container. Now let's examine the source code, keeping in mind this module -contains the basics and the official release (tbd) will likely contain -more details, such as how it hooks into I<DBI.pm> to provide -transparency the way I<Apache::DBI> currently does. +contains the basics and the official release (tbd) will likely contain +more details, such as how it hooks into C<DBI> to provide transparency +the way C<Apache::DBI> currently does. -After pulling in the modules needed I<Apache::TIPool>, -I<Apache::ModuleConfig> and I<DBI>, we setup a callback table. The +After pulling in the needed modules C<Apache::TIPool>, +C<Apache::ModuleConfig> and C<DBI>, we setup a callback table. The I<new_connection> function will be called with the TIP needs to add a new item and I<close_connection> when an item is being removed from -the pool. The I<Apache::Hook> I<add> method registers a -I<PerlPostConfigHandler> which will be called after Apache has read +the pool. The C<Apache::Hook> I<add> method registers a +C<PerlPostConfigHandler> which will be called after Apache has read the configuration files. -This handler (our I<init> function) is passed 3 I<Apache::Pool> -objects and one I<Apache::Server> object. Each I<Apache::Pool> has a +This handler (our I<init> function) is passed three C<Apache::Pool> +objects and one C<Apache::Server> object. Each C<Apache::Pool> has a different lifetime, the first will be alive until configuration is read again, such as during restarts. The second will be alive until logs are re-opened and the third is a temporary pool which is cleared before Apache starts serving requests. Since the DBI connection pool -is associated with configuration in httpd.conf, we will use that pool. +is associated with configuration in I<httpd.conf>, we will use that +pool. -The I<Apache::ModuleConfig> I<get> method is called with the -I<Apache::Server> object to give us the configuration associated with +The C<Apache::ModuleConfig> I<get> method is called with the +C<Apache::Server> object to give us the configuration associated with the given server. Next is a while loop which iterates over the -configuration parsed by the I<DBIPool> directive handler. The keys of -this hash are the configured I<dsn>, of which there is one per -I<DBIPool> configuration section. The values will be a hash reference -to the pool configuration, I<Start>, I<Max>, I<MinSpare>, I<MaxSpare> -and I<MaxRequests>. - -A I<new> I<Apache::TIPool> is then contructed, passing it the -C<$pconf> I<Apache::Pool>, configuration C<$params>, the I<$callbacks> -table and C<$conn> hash ref. The I<TIPool> is then saved into the -C<$cfg> object, indexed by the I<dsn>. +configuration parsed by the C<DBIPool> directive handler. The keys of +this hash are the configured C<dsn>, of which there is one per +C<DBIPool> configuration section. The values will be a hash reference +to the pool configuration, C<Start>, C<Max>, C<MinSpare>, C<MaxSpare> +and C<MaxRequests>. + +A I<new> C<Apache::TIPool> is then constructed, passing it the +C<$pconf>, C<Apache::Pool>, configuration C<$params>, the C<$callbacks> +table and C<$conn> hash ref. The C<TIPool> is then saved into the +C<$cfg> object, indexed by the C<dsn>. -At the time I<Apache::TIPool::new> is called, the I<new_connection> -callback will be called the number of time to which I<Start> is +At the time C<Apache::TIPool::new> is called, the I<new_connection> +callback will be called the number of times to which C<Start> is configured. This callback localizes I<Apache::DBIPool::connect> to a code reference which makes the real database connection. At request time I<Apache::DBIPool::connect> will fetch a database -handle from the I<TIPool>. It does so by digging into the +handle from the C<TIPool>. It does so by digging into the configuration object associated with the current virtual host to -obtain a reference to the I<TIPool> object. It then calls the I<pop> +obtain a reference to the C<TIPool> object. It then calls the I<pop> method, which will immediatly return a database handle if one is -available. If all opened connection are in used and the current -number of connections is less than the configured I<Max>, the call to -I<pop> will result in a call to I<new_connection>. If I<Max> has -already been reached, then I<pop> will block until a handle is -I<putback> into the pool. +available. If all opened connection are in use and the current number +of connections is less than the configured C<Max>, the call to I<pop> +will result in a call to I<new_connection>. If C<Max> has already +been reached, then I<pop> will block until a handle is I<putback> into +the pool. -Finally, the handle is blessed into the I<Apache::DBIPool::db> class +Finally, the handle is blessed into the C<Apache::DBIPool::db> class which will override the dbd class I<disconnect> method. The -overridden I<disconnect> method obtains a reference to the I<TIPool> +overridden I<disconnect> method obtains a reference to the C<TIPool> object and passes it to the I<putback> method, making it available for use by other threads. Should the Perl code using this handle neglect to call the I<disconnect> method, the overridden I<connect> method has @@ -521,183 +527,184 @@ =head2 Apache::DBIPool Source - package Apache::DBIPool; - - use strict; - use Apache::TIPool (); - use Apache::ModuleConfig (); - use DBI (); - - my $callbacks = { - grow => \&new_connection, #add new connection to the pool - shrink => \&close_connection, #handle removed connection from pool - }; - - Apache::Hook->add(PerlPostConfigHandler => \&init); #called at startup - - sub init { - my($pconf, $plog, $ptemp, $s) = @_; - - my $cfg = Apache::ModuleConfig->get($s, __PACKAGE__); - - #create a TIPool for each dsn - while (my($conn, $params) = each %{ $cfg->{DBIPool} }) { - my $tip = Apache::TIPool->new($pconf, $params, $callbacks, $conn); - $cfg->{TIPool}->{ $conn->{dsn} } = $tip; - } - } - - sub new_connection { - my($tip, $conn) = @_; - - #make actual connection to the database - local *Apache::DBIPool::connect = sub { - my($class, $drh) = (shift, shift); - $drh->connect($dbname, @_); - }; - - return DBI->connect(@{$conn}{qw(dsn username password attr)}); - } - - sub close_connection { - my($tip, $conn, $dbh) = @_; - my $driver = (split $conn->{dsn}, ':')[1]; - my $method = join '::', 'DBD', $driver, 'db', 'disconnect'; - $dbh->$method(); #call the real disconnect method - } - - my $EndToken = '</DBIPool>'; - - #parse <DBIPool dbi:mysql:...>... - - sub DBIPool ($$$;*) { - my($cfg, $parms, $dsn, $cfg_fh) = @_; - $dsn =~ s/>$//; - - $cfg->{DBIPool}->{$dsn}->{dsn} = $dsn; - - while((my $line = <$cfg_fh>) !~ m:^$EndToken:o) { - my($name, $value) = split $line, /\s+/, 2; - $name =~ s/^DBIPool(\w+)/lc $1/ei; - $cfg->{DBIPool}->{$dsn}->{$name} = $value; - } - } - - sub config { - my $r = Apache->request; - return Apache::ModuleConfig->get($r, __PACKAGE__); - } - - #called from DBI::connect - sub connect { - my($class, $drh) = (shift, shift); - - $drh->{DSN} = join ':', 'dbi', $drh->{Name}, $_[0]; - my $cfg = config(); - - my $tip = $cfg->{TIPool}->{ $drh->{DSN} }; - - unless ($tip) { - #XXX: do a real connect or fallback to Apache::DBI - } - - my $item = $tip->pop; #select a connection from the pool - - $r->register_cleanup(sub { #incase disconnect() is not called - $tip->putback($item); - }); - - return bless 'Apache::DBIPool::db', $item->data; #the dbh - } - - package Apache::DBIPool::db; - - our @ISA = qw(DBI::db); - - #override disconnect, puts database handle back in the pool - sub disconnect { - my $dbh = shift; - my $tip = config()->{TIPool}->{ $dbh->{DSN} }; - $tip->putback($dbh); - 1; - } - - 1; - __END__ + package Apache::DBIPool; + + use strict; + use Apache::TIPool (); + use Apache::ModuleConfig (); + use DBI (); + + my $callbacks = { + grow => \&new_connection, #add new connection to the pool + shrink => \&close_connection, #handle removed connection from pool + }; + + Apache::Hook->add(PerlPostConfigHandler => \&init); #called at startup + + sub init { + my($pconf, $plog, $ptemp, $s) = @_; + + my $cfg = Apache::ModuleConfig->get($s, __PACKAGE__); + + #create a TIPool for each dsn + while (my($conn, $params) = each %{ $cfg->{DBIPool} }) { + my $tip = Apache::TIPool->new($pconf, $params, $callbacks, $conn); + $cfg->{TIPool}->{ $conn->{dsn} } = $tip; + } + } + + sub new_connection { + my($tip, $conn) = @_; + + #make actual connection to the database + local *Apache::DBIPool::connect = sub { + my($class, $drh) = (shift, shift); + $drh->connect($dbname, @_); + }; + + return DBI->connect(@{$conn}{qw(dsn username password attr)}); + } + + sub close_connection { + my($tip, $conn, $dbh) = @_; + my $driver = (split $conn->{dsn}, ':')[1]; + my $method = join '::', 'DBD', $driver, 'db', 'disconnect'; + $dbh->$method(); #call the real disconnect method + } + + my $EndToken = '</DBIPool>'; + + #parse <DBIPool dbi:mysql:...>... + + sub DBIPool ($$$;*) { + my($cfg, $parms, $dsn, $cfg_fh) = @_; + $dsn =~ s/>$//; + + $cfg->{DBIPool}->{$dsn}->{dsn} = $dsn; + + while((my $line = <$cfg_fh>) !~ m:^$EndToken:o) { + my($name, $value) = split $line, /\s+/, 2; + $name =~ s/^DBIPool(\w+)/lc $1/ei; + $cfg->{DBIPool}->{$dsn}->{$name} = $value; + } + } + + sub config { + my $r = Apache->request; + return Apache::ModuleConfig->get($r, __PACKAGE__); + } + + #called from DBI::connect + sub connect { + my($class, $drh) = (shift, shift); + + $drh->{DSN} = join ':', 'dbi', $drh->{Name}, $_[0]; + my $cfg = config(); + + my $tip = $cfg->{TIPool}->{ $drh->{DSN} }; + + unless ($tip) { + #XXX: do a real connect or fallback to Apache::DBI + } + + my $item = $tip->pop; #select a connection from the pool + + $r->register_cleanup(sub { #incase disconnect() is not called + $tip->putback($item); + }); + + return bless 'Apache::DBIPool::db', $item->data; #the dbh + } + + package Apache::DBIPool::db; + + our @ISA = qw(DBI::db); + + #override disconnect, puts database handle back in the pool + sub disconnect { + my $dbh = shift; + my $tip = config()->{TIPool}->{ $dbh->{DSN} }; + $tip->putback($dbh); + 1; + } + + 1; + __END__ =head1 PerlOptions Directive -A new configuration directive to mod_perl-2.0, I<PerlOptions>, +A new configuration directive to mod_perl-2.0, C<PerlOptions>, provides fine-grained configuration for what were compile-time only options in mod_perl-1.xx. In addition, this directive provides -control over what class of I<PerlInterpreter> is used for a -I<VirtualHost> or location configured with I<Location>, I<Directory>, etc. +control over what class of C<PerlInterpreter> is used for a +C<E<lt>VirtualHostE<gt>> or location configured with +C<E<lt>LocationE<gt>>, C<E<lt>DirectoryE<gt>>, etc. These are all best explained with examples, first here's how to disable mod_perl for a certain host: - <VirtualHost ...> - PerlOptions -Enable - </VirtualHost> + <VirtualHost ...> + PerlOptions -Enable + </VirtualHost> -Suppose a one of the hosts does not want to allow users to configure -I<PerlAuthenHandler>, I<PerlAuthzHandler> or I<PerlAccessHandler> or -<Perl> sections: - - <VirtualHost ...> - PerlOptions -Authen -Authz -Access -Sections - </VirtualHost> +Suppose one of the hosts does not want to allow users to configure +C<PerlAuthenHandler>, C<PerlAuthzHandler>, C<PerlAccessHandler> and +E<lt>PerlE<gt> sections: + + <VirtualHost ...> + PerlOptions -Authen -Authz -Access -Sections + </VirtualHost> Or maybe everything but the response handler: - <VirtualHost ...> - PerlOptions None +Response - </VirtualHost> + <VirtualHost ...> + PerlOptions None +Response + </VirtualHost> A common problem with mod_perl-1.xx was the shared namespace between all code within the process. Consider two developers using the same server and each which to run a different version of a module with the same name. This example will create two I<parent> Perls, one for each -I<VirtualHost>, each with its own namespace and pointing to a +C<E<lt>VirtualHostE<gt>>, each with its own namespace and pointing to a different paths in C<@INC>: - <VirtualHost ...> - ServerName dev1 - PerlOptions +Parent - PerlSwitches -Mblib=/home/dev1/lib/perl - </VirtualHost> - - <VirtualHost ...> - ServerName dev2 - PerlOptions +Parent - PerlSwitches -Mblib=/home/dev2/lib/perl - </VirtualHost> + <VirtualHost ...> + ServerName dev1 + PerlOptions +Parent + PerlSwitches -Mblib=/home/dev1/lib/perl + </VirtualHost> + + <VirtualHost ...> + ServerName dev2 + PerlOptions +Parent + PerlSwitches -Mblib=/home/dev2/lib/perl + </VirtualHost> Or even for a given location, for something like "dirty" cgi scripts: - <Location /cgi-bin> - PerlOptions +Parent - PerlInterpMaxRequests 1 - PerlInterpStart 1 - PerlInterpMax 1 - PerlResponseHandler Apache::Registry - </Location> + <Location /cgi-bin> + PerlOptions +Parent + PerlInterpMaxRequests 1 + PerlInterpStart 1 + PerlInterpMax 1 + PerlResponseHandler Apache::Registry + </Location> -Will use a fresh interpreter with its own namespace to handle each +will use a fresh interpreter with its own namespace to handle each request. Should you wish to fine tune Interpreter pools for a given host: - <VirtualHost ...> - PerlOptions +Clone - PerlInterpStart 2 - PerlInterpMax 2 - </VirtualHost> + <VirtualHost ...> + PerlOptions +Clone + PerlInterpStart 2 + PerlInterpMax 2 + </VirtualHost> This might be worthwhile in the case where certain hosts have their own sets of large-ish modules, used only in each host. By tuning each -host to have it's own pool, that host will continue to reuse the Perl +host to have its own pool, that host will continue to reuse the Perl allocations in their specific modules. In 1.x versions of mod_perl, configured Perl*Handlers which are not a @@ -707,14 +714,14 @@ not auto-loaded during startup-time resolution. It is possible to configure this feature with: - PerlOptions +Autoload + PerlOptions +Autoload Consider this configuration: - PerlResponseHandler Apache::Magick + PerlResponseHandler Apache::Magick -In this case, I<Apache::Magick> is the package name, and the -subroutine name will default to I<handler>. If the I<Apache::Magick> +In this case, C<Apache::Magick> is the package name, and the +subroutine name will default to I<handler>. If the C<Apache::Magick> module is not already loaded, B<PerlOptions +Autoload> will attempt to pull it in at startup time. @@ -722,28 +729,28 @@ The mod_perl-2.0 interface to the Apache filter API is much simpler than the C API, hiding most of the details underneath. Perl filters -are configured using the I<PerlFilterHandler> directive, for example: +are configured using the C<PerlFilterHandler> directive, for example: - PerlFilterHandler Apache::ReverseFilter + PerlFilterHandler Apache::ReverseFilter This simply registers the filter, which can then be turned on using -the core I<AddOutputFilter> directive: +the core C<AddOutputFilter> directive: - <Location /foo> - AddOutputFilter Apache::ReverseFilter - </Location> + <Location /foo> + AddOutputFilter Apache::ReverseFilter + </Location> -The I<Apache::ReverseFilter> handler will now be called for anything -accessed in the I</foo> url space. The I<AddOutputFilter> directive takes +The C<Apache::ReverseFilter> handler will now be called for anything +accessed in the I</foo> url space. The C<AddOutputFilter> directive takes any number of filters, for example, this configuration will first send the output to I<mod_include>, which will in turn pass its output down -to I<Apache::ReverseFilter>: +to C<Apache::ReverseFilter>: - AddOutputFilter INCLUDE Apache::ReverseFilter + AddOutputFilter INCLUDE Apache::ReverseFilter -For our example, I<Apache::ReverseFilter> simply reverses all of the +For our example, C<Apache::ReverseFilter> simply reverses all of the output characters and then sends them downstream. The first argument -to a filter handler is an I<Apache::Filter> object, which at the +to a filter handler is an C<Apache::Filter> object, which at the moment provides two methods I<read> and I<write>. The I<read> method pulls down a chunk of the output stream into the given buffer, returning the length read into the buffer. An optional size argument @@ -753,21 +760,21 @@ filter. In our case C<scalar reverse> takes advantage of Perl's builtins to reverse the upstream buffer: - package Apache::ReverseFilter; - - use strict; - - sub handler { - my $filter = shift; - - while ($filter->read(my $buffer, 1024)) { - $filter->write(scalar reverse $buffer); - } - - return Apache::OK; - } - - 1; + package Apache::ReverseFilter; + + use strict; + + sub handler { + my $filter = shift; + + while ($filter->read(my $buffer, 1024)) { + $filter->write(scalar reverse $buffer); + } + + return Apache::OK; + } + + 1; =head1 Perl interface to the APR and Apache API @@ -779,20 +786,19 @@ The goal for 2.0 is to generate the majority of xs code and provide thin wrappers were needed to make the API more Perlish. As part of this goal, nearly the entire APR and Apache API, along with their -public data structures will covered from the get-go. Certain -functions and structures which are considered "private" to Apache or -otherwise un-useful to Perl will not be glued. The API behaves just -as it did in 1.x, sosers of the API will not notice the difference, -other than the addition of many new methods. And in the case of -I<APR>, it is possible to use I<APR> modules outside of Apache, for -example: +public data structures are covered from the get-go. Certain functions +and structures which are considered "private" to Apache or otherwise +un-useful to Perl aren't glued. The API behaves just as it did in +1.x, so users of the API will not notice the difference, other than the +addition of many new methods. And in the case of C<APR>, it is +possible to use C<APR> modules outside of Apache, for example: - % perl -MAPR -MAPR::UUID -le 'print APR::UUID->new->format' - b059a4b2-d11d-b211-bc23-d644b8ce0981 + % perl -MAPR -MAPR::UUID -le 'print APR::UUID->new->format' + b059a4b2-d11d-b211-bc23-d644b8ce0981 The mod_perl generator is a custom suite of modules specifically tuned for gluing Apache and allows for complete control over I<everything>, -providing many possibilities none of I<xsubpp>, I<swig> nor +providing many possibilities none of I<xsubpp>, I<SWIG> nor I<Inline.pm> are designed to do. Advantages to generating the glue code include: @@ -840,142 +846,141 @@ =head2 Apache::Echo -Apache 2.0 ships with an example protocol module, I<mod_echo>, which +Apache 2.0 ships with an example protocol module, C<mod_echo>, which simply reads data from the client and echos it right back. Here we'll -take a look at a Perl version of that module, called I<Apache::Echo>. +take a look at a Perl version of that module, called C<Apache::Echo>. A protocol handler is configured using the -I<PerlProcessConnectionHandler> directive and we'll use the I<Listen> -and I<VirtualHost> directives to bind to a non-standard port B<8084>: +C<PerlProcessConnectionHandler> directive and we'll use the C<Listen> +and C<E<lt>VirtualHostE<gt>> directives to bind to a non-standard port B<8084>: - Listen 8084 - <VirtualHost _default_:8084> - PerlProcessConnectionHandler Apache::Echo - </VirtualHost> + Listen 8084 + <VirtualHost _default_:8084> + PerlProcessConnectionHandler Apache::Echo + </VirtualHost> -Apache::Echo is then enabled when starting Apache: +C<Apache::Echo> is then enabled when starting Apache: - % httpd + % httpd And we give it a whirl: - % telnet localhost 8084 - Trying 127.0.0.1... - Connected to localhost (127.0.0.1). - Escape character is '^]'. - hello apachecon - hello apachecon - ^] + % telnet localhost 8084 + Trying 127.0.0.1... + Connected to localhost (127.0.0.1). + Escape character is '^]'. + mod_perl rules + mod_perl rules + ^] The code is just a few lines of code, with the standard I<package> declaration and of course, C<use strict;>. As with all -I<Perl*Handler>s, the subroutine name defaults to I<handler>. However, -in the case of a protocol handler, the first argument is not a -I<request_rec>, but a I<conn_rec> blessed into the -I<Apache::Connection> class. We have direct access to the client -socket via I<Apache::Connection>'s I<client_socket> method. This -returns an object blessed into the I<APR::Socket> class. +C<Perl*Handler>s, the subroutine name defaults to I<handler>. +However, in the case of a protocol handler, the first argument is not +a C<request_rec>, but a C<conn_rec> blessed into the +C<Apache::Connection> class. We have direct access to the client +socket via C<Apache::Connection>'s I<client_socket> method. This +returns an object blessed into the C<APR::Socket> class. Inside the echo loop, we attempt to read B<BUFF_LEN> bytes from the client socket into the C<$buff> buffer. The C<$rlen> parameter will -be set to the number of bytes actually read. The I<APR::Socket> +be set to the number of bytes actually read. The C<APR::Socket> I<recv> method will return an I<apr_status_t> value, be we need only check the read length to break out of the loop if it is less than or equal to B<0> bytes. If we received some data, it is immediately -echoed back to the client with the I<APR::Socket> I<send> method. -If we were unable to echo back the same number of bytes read from the +echoed back to the client with the C<APR::Socket> I<send> method. If +we were unable to echo back the same number of bytes read from the client, assume the connection was dropped and break out of the loop. Once the client has disconnected, the module returns B<Apache::OK>, telling Apache we have handled the connection: - package Apache::Echo; - - use strict; - use Apache::Connection (); - use APR::Socket (); - - use constant BUFF_LEN => 1024; - - sub handler { - my Apache::Connection $c = shift; - my APR::Socket $socket = $c->client_socket; - - my $buff; - - for (;;) { - my($rlen, $wlen); - my $rlen = BUFF_LEN; - $socket->recv($buff, $rlen); - last if $rlen <= 0; - $wlen = $rlen; - $socket->send($buff, $wlen); - last if $wlen != $rlen; - } - - return Apache::OK; - } - - 1; - __END__ + package Apache::Echo; + + use strict; + use Apache::Connection (); + use APR::Socket (); + + use constant BUFF_LEN => 1024; + + sub handler { + my Apache::Connection $c = shift; + my APR::Socket $socket = $c->client_socket; + + my $buff; + + for (;;) { + my($rlen, $wlen); + my $rlen = BUFF_LEN; + $socket->recv($buff, $rlen); + last if $rlen <= 0; + $wlen = $rlen; + $socket->send($buff, $wlen); + last if $wlen != $rlen; + } + + return Apache::OK; + } + + 1; =head2 Apache::CommandServer Our first protocol handler example took advange of Apache's server framework, but did not tap into any other modules. The next example is based on the example in the "TCP Servers with IO::Socket" section -of I<perlipc>. Of course, we don't need I<IO::Socket> since Apache -takes care of those details for us. The rest of that example can -still be used to illustrate implementing a simple text protocol. In -this case, one where a command is sent by the client to be executed on -the server side, with results sent back to the client. +of the I<perlipc> manpage. Of course, we don't need C<IO::Socket> +since Apache takes care of those details for us. The rest of that +example can still be used to illustrate implementing a simple text +protocol. In this case, one where a command is sent by the client to +be executed on the server side, with results sent back to the client. -The I<Apache::CommandServer> handler will support four commands: -I<motd>, I<date>, I<who> and I<quit>. These are probably not +The C<Apache::CommandServer> handler will support four commands: +C<motd>, C<date>, C<who> and C<quit>. These are probably not commands which can be exploited, but should we add such commands, we'll want to limit access based on ip address/hostname, authentication and authorization. Protocol handlers need to take care of these tasks themselves, since we bypass the HTTP protocol handler. -As with all I<PerlProcessConnectionHandlers>, we are passed an -I<Apache::Connection> object as the first argument. Again, we will be +As with all C<PerlProcessConnectionHandlers>, we are passed an +C<Apache::Connection> object as the first argument. Again, we will be directly accessing the client socket via the I<client_socket> method. The I<login> subroutine is called to check if access by this client -should be allowed. This routine makes up for what we lost with the +should be allowed. This routine makes up for what we lost with the core HTTP protocol handler bypassed. First we call the -I<Apache::RequestRec> I<new> method, which returns a I<request_rec> -object, just like that which is passed into request time -I<Perl*Handlers> and returned by the subrequest API methods, +C<Apache::RequestRec> I<new> method, which returns a I<request_rec> +object, just like that which is passed at request time to +C<Perl*Handlers> and returned by the subrequest API methods, I<lookup_uri> and I<lookup_file>. However, this "fake request" does not run handlers for any of the phases, it simply returns an object which we can use to do that ourselves. The C<location_merge> method is passed the "location" for this request, it will look up the -<Location> section that matches the given name and merge it with the -default server configuration. For example, should we only wish to -allow access to this server from certain locations: - - <Location Apache::CommandServer> - deny from all - allow from 10.* - </Location> +C<E<lt>LocationE<gt>> section that matches the given name and merge it +with the default server configuration. For example, should we only +wish to allow access to this server from certain locations: + + <Location Apache::CommandServer> + deny from all + allow from 10.* + </Location> The I<location_merge> method only looks up and merges the -configuration, we still need to apply it. -This is done in I<for> loop, iterating over three methods: -I<run_access_checker>, I<run_check_user_id> and I<run_auth_checker>. -These methods will call directly into the Apache functions that invoke -module handlers for these phases and will return an integer status -code, such as B<OK>, B<DECLINED> or B<FORBIDDEN>. If I<run_access_check> -returns something other than B<OK> or B<DECLINED>, that status will be -propagated up to the handler routine and then back up to Apache. -Otherwise, the access check passed and the loop will break unless -I<some_auth_required> returns true. This would be false given the -previous configuration example, but would be true in the presense of a -I<require> directive, such as: - - <Location Apache::CommandServer> - deny from all - allow from 10.* - require user dougm - </Location> +configuration, we still need to apply it. This is done in I<for> +loop, iterating over three methods: I<run_access_checker>, +I<run_check_user_id> and I<run_auth_checker>. These methods will call +directly into the Apache functions that invoke module handlers for +these phases and will return an integer status code, such as C<OK>, +C<DECLINED> or C<FORBIDDEN>. If I<run_access_check> returns something +other than C<OK> or C<DECLINED>, that status will be propagated up to +the handler routine and then back up to Apache. Otherwise, the access +check passed and the loop will break unless I<some_auth_required> +returns true. This would be false given the previous configuration +example, but would be true in the presense of a I<require> directive, +such as: + + <Location Apache::CommandServer> + deny from all + allow from 10.* + require user dougm + </Location> Given this configuration, I<some_auth_required> will return true. The I<user> method is then called, which will return false if we have @@ -1003,141 +1008,141 @@ return a true value, we break out of the loop. Let's give it a try with this configuration: - Listen 8085 - <VirtualHost _default_:8085> - PerlProcessConnectionHandler Apache::CommandServer - - <Location Apache::CommandServer> - allow from 127.0.0.1 - require user dougm - satisfy any - AuthUserFile /tmp/basic-auth - </Location> - </VirtualHost> - - % telnet localhost 8085 - Trying 127.0.0.1... - Connected to localhost (127.0.0.1). - Escape character is '^]'. - Login: dougm - Password: foo - Welcome to Apache::CommandServer - Available commands: motd date who quit - motd - Have a lot of fun... - date - Mon Mar 12 19:20:10 PST 2001 - who - dougm tty1 Mar 12 00:49 - dougm pts/0 Mar 12 11:23 - dougm pts/1 Mar 12 14:08 - dougm pts/2 Mar 12 17:09 - quit - Connection closed by foreign host. + Listen 8085 + <VirtualHost _default_:8085> + PerlProcessConnectionHandler Apache::CommandServer + + <Location Apache::CommandServer> + allow from 127.0.0.1 + require user dougm + satisfy any + AuthUserFile /tmp/basic-auth + </Location> + </VirtualHost> + + % telnet localhost 8085 + Trying 127.0.0.1... + Connected to localhost (127.0.0.1). + Escape character is '^]'. + Login: dougm + Password: foo + Welcome to Apache::CommandServer + Available commands: motd date who quit + motd + Have a lot of fun... + date + Mon Mar 12 19:20:10 PST 2001 + who + dougm tty1 Mar 12 00:49 + dougm pts/0 Mar 12 11:23 + dougm pts/1 Mar 12 14:08 + dougm pts/2 Mar 12 17:09 + quit + Connection closed by foreign host. =head2 Apache::CommandServer Source - package Apache::CommandServer; - - use strict; - use Apache::Connection (); - use APR::Socket (); - - my @cmds = qw(motd date who quit); - my %commands = map { $_, \&{$_} } @cmds; - - sub handler { - my Apache::Connection $c = shift; - my APR::Socket $socket = $c->client_socket; - - if ((my $rc = login($c)) != Apache::OK) { - $socket->send("Access Denied\n"); - return $rc; - } - - $socket->send("Welcome to " . __PACKAGE__ . - "\nAvailable commands: @cmds\n"); - - for (;;) { - my $cmd; - next unless $cmd = getline($socket); - - if (my $sub = $commands{$cmd}) { - last unless $sub->($socket) == APR::SUCCESS; - } - else { - $socket->send("Commands: @cmds\n"); - } - } - - return Apache::OK; - } - - sub login { - my $c = shift; - - my $r = Apache::RequestRec->new($c); - $r->location_merge(__PACKAGE__); - - for my $method (qw(run_access_checker run_check_user_id run_auth_checker)) { - my $rc = $r->$method(); - - if ($rc != Apache::OK and $rc != Apache::DECLINED) { - return $rc; - } - - last unless $r->some_auth_required; - - unless ($r->user) { - my $socket = $c->client_socket; - my $username = prompt($socket, "Login"); - my $password = prompt($socket, "Password"); - - $r->set_basic_credentials($username, $password); - } - } - - return Apache::OK; - } - - sub getline { - my $socket = shift; - my $line; - $socket->recv($line, 1024); - return unless $line; - $line =~ s/[\r\n]*$//; - return $line; - } - - sub prompt { - my($socket, $msg) = @_; - $socket->send("$msg: "); - getline($socket); - } - - sub motd { - my $socket = shift; - open my $fh, '/etc/motd' or return; - local $/; - my $status = $socket->send(scalar <$fh>); - close $fh; - return $status; - } - - sub date { - my $socket = shift; - $socket->send(scalar(localtime) . "\n"); - } - - sub who { - my $socket = shift; - $socket->send(scalar `who`); - } - - sub quit {1} - - 1; - __END__ + package Apache::CommandServer; + + use strict; + use Apache::Connection (); + use APR::Socket (); + + my @cmds = qw(motd date who quit); + my %commands = map { $_, \&{$_} } @cmds; + + sub handler { + my Apache::Connection $c = shift; + my APR::Socket $socket = $c->client_socket; + + if ((my $rc = login($c)) != Apache::OK) { + $socket->send("Access Denied\n"); + return $rc; + } + + $socket->send("Welcome to " . __PACKAGE__ . + "\nAvailable commands: @cmds\n"); + + for (;;) { + my $cmd; + next unless $cmd = getline($socket); + + if (my $sub = $commands{$cmd}) { + last unless $sub->($socket) == APR::SUCCESS; + } + else { + $socket->send("Commands: @cmds\n"); + } + } + + return Apache::OK; + } + + sub login { + my $c = shift; + + my $r = Apache::RequestRec->new($c); + $r->location_merge(__PACKAGE__); + + for my $method (qw(run_access_checker run_check_user_id run_auth_checker)) { + my $rc = $r->$method(); + + if ($rc != Apache::OK and $rc != Apache::DECLINED) { + return $rc; + } + + last unless $r->some_auth_required; + + unless ($r->user) { + my $socket = $c->client_socket; + my $username = prompt($socket, "Login"); + my $password = prompt($socket, "Password"); + + $r->set_basic_credentials($username, $password); + } + } + + return Apache::OK; + } + + sub getline { + my $socket = shift; + my $line; + $socket->recv($line, 1024); + return unless $line; + $line =~ s/[\r\n]*$//; + return $line; + } + + sub prompt { + my($socket, $msg) = @_; + $socket->send("$msg: "); + getline($socket); + } + + sub motd { + my $socket = shift; + open my $fh, '/etc/motd' or return; + local $/; + my $status = $socket->send(scalar <$fh>); + close $fh; + return $status; + } + + sub date { + my $socket = shift; + $socket->send(scalar(localtime) . "\n"); + } + + sub who { + my $socket = shift; + $socket->send(scalar `who`); + } + + sub quit {1} + + 1; + __END__ =head1 mod_perl-2.0 Optimizations @@ -1149,17 +1154,15 @@ tree and some a combination of both. In this section we'll take a brief look at some of the optimizations that are being considered. -The details of these optimizations will from the most part be hidden -from mod_perl users, the exeception being that some will only be turned -on with configuration directives. The explanation of these -optimization ideas are best left for the live talk, a few which will -be overviewed include: +The details of these optimizations from the most part are hidden from +mod_perl users, the exception being that some will only be turned on +with configuration directives. A few of which include: =over 4 =item * -"Compiled" Perl*Handlers +"Compiled" C<Perl*Handlers> =item * @@ -1167,11 +1170,11 @@ =item * -`print' enhancements +I<print> enhancements =item * -Inlined Apache::*.xs calls +Inlined C<Apache::*.xs> calls =item *
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]