perl-modperl-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sbek...@hyperreal.org
Subject cvs commit: modperl-site/guide correct_headers.html CHANGES all.html config.html control.html databases.html dbm.html debug.html guide-src.tar.gz guide.tar.gz help.html index.html install.html intro.html mod_perl_guide.ps.gz modules.html performance.html porting.html scenario.html security.html snippets.html strategy.html warnings.html
Date Fri, 15 Oct 1999 22:54:05 GMT
sbekman     99/10/15 15:53:55

  Modified:    guide    CHANGES all.html config.html control.html
                        databases.html dbm.html debug.html guide-src.tar.gz
                        guide.tar.gz help.html index.html install.html
                        intro.html mod_perl_guide.ps.gz modules.html
                        performance.html porting.html scenario.html
                        security.html snippets.html strategy.html
                        warnings.html
  Added:       guide    correct_headers.html
  Log:
  ver 1.17:
  
  * intro: CREDITS section was updated the long list of contributors!!!
    Thank you all!!! If I've missed your name, please let me know!!!
  
  * control: added "Safe Code Updates on a Live Production Server"
  
  * control: added "An Intentional Disabling of Live Scripts"
  
  * scenario: added a big new section "One Light and One Heavy Servers
    where ALL htmls are Perl-Generated" (Wesley Darlington)
  
  * dbm: David Harris has detected a corruption with the suggested
    locking methods in the Camel book and DB_File man page (at least
    before the version 1.72). They are flawed and if you use them in the
    environment where more than one process modify the dbm file, it can
    get corrupted!!! I've modified the DB_File::Lock module to fix the
    problem by integrating the previously written DB_File::Wrap and the
    module David wrote (David Harris)
  
  * snippets: added "Sending multiply cookies with Perl API" (Rick
    Myers)
  
  * install: added a big section "using RPM, DEB and other packages to
    install mod_perl" (Young, Geoffrey S , David Harris)
  
  * install: added "Automating installation" - James G Smith's Apache
    Builder script
  
  * install: added a new section "using CPAN to install mod_perl"
  
  * performance: extended the "Forking or Executing subprocesses from
    mod_perl" with information and code to avoid zombies.
  
  * performance: added a converted to pod "Jeff's guide to mod_perl
    database performance" (Jeffrey W. Baker)
  
  * new chapter: "Correct Headers" contributed by Andreas Koenig!!!
  
  * help: updated the link to DBI homepage (hermetica has gone)
  
  * performance: added sizing benchmarks of CGI.pm's imported
    symbols. (CGI.pm's object methods calls vs. function calls)
  
  * porting: fixed a typo with local() and Special variables (Andrei
    A. Voropaev)
  
  * snippets: fixed a taint problem in the sample error_log display
    script.(John Walker)
  
  * install: added "Should I Build mod_perl with gcc or cc" (Tom Hughes)
  
  * warnings: added to the troubleshotting section "Missing right
    bracket at line " with a link to the item explaining that in
    porting.pod ("__END__ and __DATA__ tokens") (Eric Strovink)
  
  * install: added a tip of saving config.status files for each module
    build (php. mod_perl, ssl) for a later easier reuse. (Dave
    Hodgkinson)
  
  * performance: added clarification to "PerlSetupEnv Off" item (Doug)
  
  * snippets: added "Passing environment variables between handlers"
    (Doug)
  
  * warnings: added "Can't locate loadable object for module XXX" (Doug)
  
  * config: corrected the <Perl> section dump typo (Gerald Richter)
  
  * scenario: corrected the snippet to extract the client IP from the
    X-Forwarded-For header to use headers_in instead of the obsolete
    header_in (Oleg Bartunov)
  
  * scenario: added a note about "Ben Laurie's Apache-SSL setting
    REMOTE_ADDER instead of X-Forwarded-For header (Jie Gao)
  
  * performance: started "Analysis of SW and HW Requirements" (Jeffrey
    W. Baker)
  
  * warnings: clarification of "rwrite returned -1" (Eric Cholet)
  
  * warnings: added "Invalid command 'PerlHandler" (Doug)
  
  * debug: started "Apache::Debug" and Carp::confess("init") (Doug)
  
  * install: "undefined reference to 'Perl_newAV'" documented (Doug)
  
  * modules: added a clarification about Apache::PerlVINC (Doug)
  
  * warnings: updated the "Callback Called Exit & -D
    PERL_EMERGENCY_SBRK" (Doug)
  
  * databases: added $Apache::DBI::DEBUG = 2 (instead of '1') for ver
    0.84+ (Edmund Mergl)
  
  * performance: added "Caching prepare() statements" + rolling your own
    Apache::DBO code (Jeffrey Baker)
  
  * porting: replaced "Apache::Registry::handler" with
    "Apache::Registry". It caused problems to some of the users (Daniel
    W. Burke)
  
  * performance: added "Increasing the shared memory with mergemem" (no
    real info but a link to the util's site. Please take a look and
    submit your opinions) (Doug Bagley)
  
  * snippets: added "Redirect a POST request, forwarding the content"
   (Eric Cholet, Doug)
  
  * performance extended the "Using $|=1 under mod_perl and better
    print() techniques" with notes about rflush()
  
  * shuffled many items around to help more intuitive search of the them
  
  * performance: added "Cached stat() calls"
  
  Revision  Changes    Path
  1.17      +118 -2    modperl-site/guide/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/CHANGES,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- CHANGES	1999/09/25 23:13:47	1.16
  +++ CHANGES	1999/10/15 22:52:35	1.17
  @@ -1,6 +1,122 @@
  -This is a CHANGES file for mod_perl guide
  +This is a CHANGES file for mod_perl Guide
   
  -09.20.99 ver 1.16
  +10.16.99 ver 1.17
  +
  +* intro: CREDITS section was updated the long list of contributors!!!
  +  Thank you all!!! If I've missed your name, please let me know!!!
  +
  +* control: added "Safe Code Updates on a Live Production Server"
  +
  +* control: added "An Intentional Disabling of Live Scripts"
  +
  +* scenario: added a big new section "One Light and One Heavy Servers
  +  where ALL htmls are Perl-Generated" (Wesley Darlington)
  +
  +* dbm: David Harris has detected a corruption with the suggested
  +  locking methods in the Camel book and DB_File man page (at least
  +  before the version 1.72). They are flawed and if you use them in the
  +  environment where more than one process modify the dbm file, it can
  +  get corrupted!!! I've modified the DB_File::Lock module to fix the
  +  problem by integrating the previously written DB_File::Wrap and the
  +  module David wrote (David Harris)
  +
  +* snippets: added "Sending multiply cookies with Perl API" (Rick
  +  Myers)
  +
  +* install: added a big section "using RPM, DEB and other packages to
  +  install mod_perl" (Young, Geoffrey S , David Harris)
  +
  +* install: added "Automating installation" - James G Smith's Apache
  +  Builder script
  +
  +* install: added a new section "using CPAN to install mod_perl"
  +
  +* performance: extended the "Forking or Executing subprocesses from
  +  mod_perl" with information and code to avoid zombies.
  +
  +* performance: added a converted to pod "Jeff's guide to mod_perl
  +  database performance" (Jeffrey W. Baker)
  +
  +* new chapter: "Correct Headers" contributed by Andreas Koenig!!!
  +
  +* help: updated the link to DBI homepage (hermetica has gone)
  +
  +* performance: added sizing benchmarks of CGI.pm's imported
  +  symbols. (CGI.pm's object methods calls vs. function calls)
  +
  +* porting: fixed a typo with local() and Special variables (Andrei
  +  A. Voropaev)
  +
  +* snippets: fixed a taint problem in the sample error_log display
  +  script.(John Walker)
  +
  +* install: added "Should I Build mod_perl with gcc or cc" (Tom Hughes)
  +
  +* warnings: added to the troubleshotting section "Missing right
  +  bracket at line " with a link to the item explaining that in
  +  porting.pod ("__END__ and __DATA__ tokens") (Eric Strovink)
  +
  +* install: added a tip of saving config.status files for each module
  +  build (php. mod_perl, ssl) for a later easier reuse. (Dave
  +  Hodgkinson)
  +
  +* performance: added clarification to "PerlSetupEnv Off" item (Doug)
  +
  +* snippets: added "Passing environment variables between handlers"
  +  (Doug)
  +
  +* warnings: added "Can't locate loadable object for module XXX" (Doug)
  +
  +* config: corrected the <Perl> section dump typo (Gerald Richter)
  +
  +* scenario: corrected the snippet to extract the client IP from the
  +  X-Forwarded-For header to use headers_in instead of the obsolete
  +  header_in (Oleg Bartunov)
  +
  +* scenario: added a note about "Ben Laurie's Apache-SSL setting
  +  REMOTE_ADDER instead of X-Forwarded-For header (Jie Gao)
  +
  +* performance: started "Analysis of SW and HW Requirements" (Jeffrey
  +  W. Baker)
  +
  +* warnings: clarification of "rwrite returned -1" (Eric Cholet)
  +
  +* warnings: added "Invalid command 'PerlHandler" (Doug) 
  +
  +* debug: started "Apache::Debug" and Carp::confess("init") (Doug) 
  +
  +* install: "undefined reference to 'Perl_newAV'" documented (Doug)
  +
  +* modules: added a clarification about Apache::PerlVINC (Doug)
  +
  +* warnings: updated the "Callback Called Exit & -D
  +  PERL_EMERGENCY_SBRK" (Doug)
  +
  +* databases: added $Apache::DBI::DEBUG = 2 (instead of '1') for ver
  +  0.84+ (Edmund Mergl)
  +
  +* performance: added "Caching prepare() statements" + rolling your own
  +  Apache::DBO code (Jeffrey Baker)
  +
  +* porting: replaced "Apache::Registry::handler" with
  +  "Apache::Registry". It caused problems to some of the users (Daniel
  +  W. Burke)
  +
  +* performance: added "Increasing the shared memory with mergemem" (no
  +  real info but a link to the util's site. Please take a look and
  +  submit your opinions) (Doug Bagley)
  +
  +* snippets: added "Redirect a POST request, forwarding the content"
  + (Eric Cholet, Doug)
  +
  +* performance extended the "Using $|=1 under mod_perl and better
  +  print() techniques" with notes about rflush()
  +
  +* shuffled many items around to help more intuitive search of the them
  +
  +* performance: added "Cached stat() calls"
  +
  +09.26.99 ver 1.16
   
   * Many little things fixed, rewritten - didn't worth listing them all
     here.
  
  
  
  1.18      +9137 -6137modperl-site/guide/all.html
  
  Index: all.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/all.html,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- all.html	1999/09/25 23:13:48	1.17
  +++ all.html	1999/10/15 22:52:35	1.18
  @@ -30,8 +30,8 @@
   <CENTER><P><B>Deploying mod_perl technology to give a rocket speed
   to your CGI/perl scripts.</B></P></CENTER>
   
  -<CENTER><P><B>Version 1.16
  - Sep, 26 1999</B></P></CENTER>
  +<CENTER><P><B>Version 1.17
  + Oct, 16 1999</B></P></CENTER>
    
   <P>
   <HR WIDTH="100%"></P>
  @@ -73,7 +73,6 @@
   	<LI><A HREF="porting.html#Before_you_start_to_code">Before you start to code</A>
   	<LI><A HREF="porting.html#Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A>
   	<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A>
  -	<LI><A HREF="porting.html#What_s_different_about_modperl">What's different about modperl</A>
   	<LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
   	<LI><A HREF="porting.html#Messing_with_INC">Messing with @INC</A>
   	<LI><A HREF="porting.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  @@ -94,7 +93,7 @@
   
   	<LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
   	<LI><A HREF="porting.html#More_package_name_related_issues">More package name related issues</A>
  -	<LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  +	<LI><A HREF="porting.html#_END_and_DATA_tokens">__END__ and __DATA__ tokens</A>
   	<LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
   	<LI><A HREF="porting.html#Using_format_and_write_">Using format() and write()</A>
   	<LI><A HREF="porting.html#Using_exit_">Using exit()</A>
  @@ -110,24 +109,23 @@
   	<LI><A HREF="porting.html#Turning_warnings_ON">Turning warnings ON</A>
   	<LI><A HREF="porting.html#diagnostics_pragma">diagnostics pragma</A>
   	<LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
  -	<LI><A HREF="porting.html#Global_Variables">Global Variables</A>
   	<LI><A HREF="porting.html#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
   	<LI><A HREF="porting.html#Apache_and_syslog">Apache and syslog</A>
  -	<LI><A HREF="porting.html#Memory_leakage">Memory leakage</A>
   	<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
   	<LI><A HREF="porting.html#The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A>
   	<LI><A HREF="porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
   	<LI><A HREF="porting.html#Sharing_variables_between_proces">Sharing variables between processes</A>
   	<LI><A HREF="porting.html#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
   	<LI><A HREF="porting.html#Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A>
  -	<LI><A HREF="porting.html#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
   	<LI><A HREF="porting.html#Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A>
   </UL>
   <P><LI><A HREF="performance.html"><B><FONT SIZE=+1>Performance. Benchmarks.</FONT></B></A></LI><P>
   <UL>
   
  -	<LI><A HREF="performance.html#Performance_The_Overall_picture">Performance: The Overall picture</A>
  +	<LI><A HREF="performance.html#Performance_An_Overall_picture">Performance: An Overall picture</A>
  +	<LI><A HREF="performance.html#Analysis_of_SW_and_HW_Requiremen">Analysis of SW and HW Requirements</A>
   	<LI><A HREF="performance.html#Sharing_Memory">Sharing Memory</A>
  +	<LI><A HREF="performance.html#How_Shared_My_Memory_Is">How Shared My Memory Is</A>
   	<LI><A HREF="performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
   	<UL>
   
  @@ -135,12 +133,14 @@
   	</UL>
   
   	<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
  +	<LI><A HREF="performance.html#Global_vs_Fully_Qualified_Variab">Global vs Fully Qualified Variables </A>
   	<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</A>
   	<LI><A HREF="performance.html#PerlSetupEnv_Off">PerlSetupEnv Off</A>
  +	<LI><A HREF="performance.html#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
  +	<LI><A HREF="performance.html#Memory_leakage">Memory leakage</A>
   	<LI><A HREF="performance.html#_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A>
  -	<LI><A HREF="performance.html#Shared_Memory">Shared Memory</A>
   	<LI><A HREF="performance.html#Checking_script_modification_tim">Checking script modification times</A>
  -	<LI><A HREF="performance.html#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
  +	<LI><A HREF="performance.html#Cached_stat_calls">Cached stat() calls</A>
   	<LI><A HREF="performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
   	<LI><A HREF="performance.html#Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A>
   	<LI><A HREF="performance.html#Limiting_the_request_rate_speed_">Limiting the request rate speed (robots blocking)</A>
  @@ -165,11 +165,29 @@
   	</UL>
   
   	<LI><A HREF="performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Preopening_Connections_at_the_Ch">Preopening Connections at the Child Process' Fork Time</A>
  +		<LI><A HREF="performance.html#Caching_prepare_statements">Caching prepare() statements</A>
  +		<LI><A HREF="performance.html#Handling_Timeouts">Handling Timeouts</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Jeff_s_guide_to_mod_perl_databas">Jeff's guide to mod_perl database performance</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Analysis_of_the_Problem">Analysis of the Problem</A>
  +		<LI><A HREF="performance.html#Optimizing_Database_Connections">Optimizing Database Connections</A>
  +		<LI><A HREF="performance.html#Utilizing_the_Database_Server_s_">Utilizing the Database Server's Cache</A>
  +		<LI><A HREF="performance.html#Eliminating_SQL_Statement_Parsin">Eliminating SQL Statement Parsing</A>
  +		<LI><A HREF="performance.html#Conclusion">Conclusion</A>
  +	</UL>
  +
   	<LI><A HREF="performance.html#Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</A>
   	<LI><A HREF="performance.html#More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A>
   	<LI><A HREF="performance.html#Profiling">Profiling</A>
   	<LI><A HREF="performance.html#CGI_pm_s_object_methods_calls_vs">CGI.pm's object methods calls vs. function calls</A>
   	<LI><A HREF="performance.html#Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A>
  +	<LI><A HREF="performance.html#Increasing_the_shared_memory_wit">Increasing the shared memory with mergemem</A>
   </UL>
   <P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Choosing the Right Strategy</FONT></B></A></LI><P>
   <UL>
  @@ -215,8 +233,14 @@
   
   	<LI><A HREF="scenario.html#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
   	<LI><A HREF="scenario.html#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A>
  +	<LI><A HREF="scenario.html#One_Light_and_One_Heavy_Servers_">One Light and One Heavy Servers where ALL htmls are Perl-Generated</A>
  +	<UL>
  +
  +		<LI><A HREF="scenario.html#Installation_and_Configuration">Installation and Configuration</A>
  +		<LI><A HREF="scenario.html#Tricks_traps_and_gotchas">Tricks, traps and gotchas</A>
  +	</UL>
  +
   	<LI><A HREF="scenario.html#Building_and_Using_mod_proxy">Building and Using mod_proxy</A>
  -	<LI><A HREF="scenario.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>
   	<LI><A HREF="scenario.html#HTTP_Authentication_with_2_serve">HTTP Authentication with 2 servers + proxy</A>
   </UL>
   <P><LI><A HREF="install.html"><B><FONT SIZE=+1>Installation Notes</FONT></B></A></LI><P>
  @@ -230,6 +254,22 @@
   		<LI><A HREF="install.html#mod_perl">mod_perl</A>
   	</UL>
   
  +	<LI><A HREF="install.html#using_CPAN_to_install_mod_perl">using CPAN to install mod_perl</A>
  +	<LI><A HREF="install.html#using_RPM_DEB_and_other_package">using RPM, DEB and other packages to install mod_perl</A>
  +	<UL>
  +
  +		<LI><A HREF="install.html#A_word_on_mod_perl_RPM_packages">A word on mod_perl RPM packages</A>
  +		<LI><A HREF="install.html#Getting_Started">Getting Started</A>
  +		<LI><A HREF="install.html#Compiling_RPM_source_files">Compiling RPM source files</A>
  +		<LI><A HREF="install.html#Mix_and_Match_RPM_and_source">Mix and Match RPM and source</A>
  +		<LI><A HREF="install.html#Installing_a_single_apache_mod_p">Installing a single apache+mod_perl RPM</A>
  +		<LI><A HREF="install.html#Compiling_libapreq_Apache_Requ">Compiling libapreq (Apache::Request) with the RH 6.0 mod_perl RPM</A>
  +		<LI><A HREF="install.html#Compiling_libapreq_with_mod_perl">Compiling libapreq with mod_perl installed from RPM (general)</A>
  +		<LI><A HREF="install.html#Installing_separate_Apache_and_m">Installing separate Apache and mod_perl RPMs</A>
  +		<LI><A HREF="install.html#Testing_the_mod_perl_API">Testing the mod_perl API</A>
  +	</UL>
  +
  +	<LI><A HREF="install.html#Automating_installation">Automating installation</A>
   	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
   	<UL>
   
  @@ -243,10 +283,11 @@
   	<LI><A HREF="install.html#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
   	<LI><A HREF="install.html#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
   	<LI><A HREF="install.html#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
  -	<LI><A HREF="install.html#Server_Installation_problems">Server Installation problems</A>
  +	<LI><A HREF="install.html#Installation_problems">Installation problems</A>
   	<UL>
   
  -		<LI><A HREF="install.html#_skipping_test_on_this_plat">......skipping test on this platform</A>
  +		<LI><A HREF="install.html#make_problems">make problems</A>
  +		<LI><A HREF="install.html#make_test_skipping_test_on_">make test......skipping test on this platform</A>
   		<LI><A HREF="install.html#make_test_fails">make test fails</A>
   		<LI><A HREF="install.html#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
   		<LI><A HREF="install.html#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
  @@ -254,6 +295,9 @@
   
   	<LI><A HREF="install.html#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
   	<LI><A HREF="install.html#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  +	<LI><A HREF="install.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>
  +	<LI><A HREF="install.html#Caveats_of_adding_mod_perl_php_">Caveats of adding mod_perl, php, ssl and other into Apache</A>
  +	<LI><A HREF="install.html#Should_I_Build_mod_perl_with_gcc">Should I Build mod_perl with gcc or cc?</A>
   </UL>
   <P><LI><A HREF="config.html"><B><FONT SIZE=+1>Server Configuration</FONT></B></A></LI><P>
   <UL>
  @@ -265,12 +309,8 @@
   		<LI><A HREF="config.html#Location_Configuration">Location Configuration</A>
   		<LI><A HREF="config.html#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
   		<LI><A HREF="config.html#Perl_Handlers">Perl*Handlers</A>
  -	</UL>
  -
  -	<LI><A HREF="config.html#STACKED_HANDLERS">STACKED HANDLERS</A>
  -	<LI><A HREF="config.html#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
  -	<UL>
  -
  +		<LI><A HREF="config.html#Stacked_Handlers">Stacked Handlers</A>
  +		<LI><A HREF="config.html#Perl_Method_Handlers">Perl Method Handlers</A>
   		<LI><A HREF="config.html#PerlFreshRestart">PerlFreshRestart</A>
   		<LI><A HREF="config.html#_perl_status_location">/perl-status location</A>
   		<UL>
  @@ -326,6 +366,8 @@
   	<LI><A HREF="control.html#Restarting_techniques">Restarting techniques</A>
   	<LI><A HREF="control.html#Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A>
   	<LI><A HREF="control.html#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
  +	<LI><A HREF="control.html#Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A>
  +	<LI><A HREF="control.html#An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A>
   	<LI><A HREF="control.html#SUID_start_up_scripts">SUID start-up scripts</A>
   	<LI><A HREF="control.html#Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A>
   	<LI><A HREF="control.html#Running_server_in_a_single_mode">Running server in a single mode</A>
  @@ -359,13 +401,16 @@
   <UL>
   
   	<LI><A HREF="warnings.html#General_Advice">General Advice </A>
  +	<LI><A HREF="warnings.html#Installation_problems">Installation problems</A>
   	<LI><A HREF="warnings.html#Incorrect_line_number_reporting_">Incorrect line number reporting in error/warn log messages</A>
   	<LI><A HREF="warnings.html#Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A>
   	<LI><A HREF="warnings.html#Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A>
  -	<LI><A HREF="warnings.html#mod_perl_rwrite_returned_1">mod_perl: rwrite returned -1</A>
  +	<LI><A HREF="warnings.html#rwrite_returned_1">rwrite returned -1</A>
  +	<LI><A HREF="warnings.html#Can_t_locate_loadable_object_for">Can't locate loadable object for module XXX</A>
  +	<LI><A HREF="warnings.html#Missing_right_bracket_at_line_">Missing right bracket at line ...</A>
   	<LI><A HREF="warnings.html#caught_SIGPIPE_in_process">caught SIGPIPE in process</A>
   	<LI><A HREF="warnings.html#Client_hit_STOP_or_Netscape_bit_">Client hit STOP or Netscape bit it!</A>
  -	<LI><A HREF="warnings.html#Constant_subroutine_redefine">Constant subroutine ... redefined</A>
  +	<LI><A HREF="warnings.html#Constant_subroutine_XXX_redefine">Constant subroutine XXX redefined</A>
   	<LI><A HREF="warnings.html#Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</A>
   	<LI><A HREF="warnings.html#Can_t_undef_active_subroutine">Can't undef active subroutine</A>
   	<LI><A HREF="warnings.html#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
  @@ -373,12 +418,58 @@
   	<LI><A HREF="warnings.html#Can_t_load_auto_DBI_DBI_so_">Can't load '.../auto/DBI/DBI.so' for module DBI</A>
   	<LI><A HREF="warnings.html#Callback_called_exit">Callback called exit</A>
   	<LI><A HREF="warnings.html#Out_of_memory_">Out of memory!</A>
  +	<LI><A HREF="warnings.html#Invalid_command_PerlHandler_">Invalid command 'PerlHandler'...</A>
   	<LI><A HREF="warnings.html#_warn_child_process_30388_did_n">[warn] child process 30388 did not exit, sending another SIGHUP</A>
   	<LI><A HREF="warnings.html#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
   	<LI><A HREF="warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
   	<LI><A HREF="warnings.html#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
   	<LI><A HREF="warnings.html#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near &quot;line arguments:&quot;</A>
   </UL>
  +<P><LI><A HREF="correct_headers.html"><B><FONT SIZE=+1>Correct Headers - A quick guide for mod_perl users</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="correct_headers.html#SYNOPSIS">SYNOPSIS</A>
  +	<LI><A HREF="correct_headers.html#The_origin_of_this_chapter">The origin of this chapter</A>
  +	<LI><A HREF="correct_headers.html#DESCRIPTION">DESCRIPTION</A>
  +	<LI><A HREF="correct_headers.html#1_Why_headers">1) Why headers</A>
  +	<LI><A HREF="correct_headers.html#2_Which_Headers">2) Which Headers</A>
  +	<UL>
  +
  +		<LI><A HREF="correct_headers.html#2_1_Date_related_headers">2.1) Date related headers</A>
  +		<LI><A HREF="correct_headers.html#2_1_1_Date">2.1.1) Date</A>
  +		<LI><A HREF="correct_headers.html#2_1_2_Last_Modified">2.1.2) Last-Modified</A>
  +		<LI><A HREF="correct_headers.html#2_1_3_Expires_and_Cache_Control">2.1.3) Expires and Cache-Control</A>
  +		<LI><A HREF="correct_headers.html#2_2_Content_related_headers">2.2) Content related headers</A>
  +		<LI><A HREF="correct_headers.html#2_2_1_Content_Type">2.2.1) Content-Type</A>
  +		<LI><A HREF="correct_headers.html#2_2_2_Content_Length">2.2.2) Content-Length</A>
  +		<LI><A HREF="correct_headers.html#2_2_3_Entity_Tags">2.2.3) Entity Tags</A>
  +		<LI><A HREF="correct_headers.html#2_3_Content_Negotiation">2.3) Content Negotiation</A>
  +		<LI><A HREF="correct_headers.html#2_3_1_Vary">2.3.1) Vary</A>
  +	</UL>
  +
  +	<LI><A HREF="correct_headers.html#3_Requests">3) Requests</A>
  +	<UL>
  +
  +		<LI><A HREF="correct_headers.html#3_1_HEAD">3.1) HEAD</A>
  +		<LI><A HREF="correct_headers.html#3_2_POST">3.2) POST</A>
  +		<LI><A HREF="correct_headers.html#3_3_C_GET_">3.3) &lt;CODE&gt;GET&lt;/CODE&gt;</A>
  +		<LI><A HREF="correct_headers.html#3_4_Conditional_GET">3.4) Conditional GET</A>
  +		<LI><A HREF="correct_headers.html#3_Avoiding_to_deal_with_them">3.) Avoiding to deal with them</A>
  +	</UL>
  +
  +	<LI><A HREF="correct_headers.html#References_and_other_literature">References and other literature</A>
  +	<UL>
  +
  +		<LI><A HREF="correct_headers.html#_1_">[1]</A>
  +		<LI><A HREF="correct_headers.html#_2_">[2]</A>
  +		<LI><A HREF="correct_headers.html#_3_">[3]</A>
  +		<LI><A HREF="correct_headers.html#_4_">[4]</A>
  +		<LI><A HREF="correct_headers.html#_5_">[5]</A>
  +	</UL>
  +
  +	<LI><A HREF="correct_headers.html#VERSION">VERSION</A>
  +	<LI><A HREF="correct_headers.html#AUTHOR">AUTHOR</A>
  +</UL>
   <P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
   <UL>
   
  @@ -437,7 +528,7 @@
   	<LI><A HREF="dbm.html#mod_perl_and_dbm">mod_perl and dbm</A>
   	<LI><A HREF="dbm.html#Locking_dbm_handlers">Locking dbm handlers</A>
   	<LI><A HREF="dbm.html#Tie_DB_Lock">Tie::DB_Lock</A>
  -	<LI><A HREF="dbm.html#Code_snippets">Code snippets</A>
  +	<LI><A HREF="dbm.html#Locking_techniques_that_works_wi">Locking techniques that works with dbm files</A>
   </UL>
   <P><LI><A HREF="multiuser.html"><B><FONT SIZE=+1>mod_perl for ISPs. mod_perl and Virtual Hosts.</FONT></B></A></LI><P>
   <UL>
  @@ -462,6 +553,7 @@
   
   	<LI><A HREF="debug.html#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
   	<LI><A HREF="debug.html#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
  +	<LI><A HREF="debug.html#Apache_Debug">Apache::Debug</A>
   	<LI><A HREF="debug.html#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
   	<LI><A HREF="debug.html#Debugging_Core_Dumps">Debugging Core Dumps</A>
   	<LI><A HREF="debug.html#Debug_Tracing">Debug Tracing</A>
  @@ -469,9 +561,10 @@
   	<LI><A HREF="debug.html#Monitoring_error_log_file">Monitoring error_log file</A>
   	<LI><A HREF="debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
   	<LI><A HREF="debug.html#Spinning_httpds">Spinning httpds</A>
  -	<LI><A HREF="debug.html#PROFILING">PROFILING</A>
  -	<LI><A HREF="debug.html#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="debug.html#Code_Profiling">Code Profiling</A>
  +	<LI><A HREF="debug.html#Examples_of_strace_or_truss_us">Examples of strace (or truss) usage</A>
   	<LI><A HREF="debug.html#Devel_Peek">Devel::Peek</A>
  +	<LI><A HREF="debug.html#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
   </UL>
   <P><LI><A HREF="browserbugs.html"><B><FONT SIZE=+1>Workarounds for some known bugs in browsers.</FONT></B></A></LI><P>
   <UL>
  @@ -509,10 +602,13 @@
   <P><LI><A HREF="snippets.html"><B><FONT SIZE=+1>Code Snippets</FONT></B></A></LI><P>
   <UL>
   
  +	<LI><A HREF="snippets.html#Redirect_a_POST_request_forward">Redirect a POST request, forwarding the content</A>
   	<LI><A HREF="snippets.html#More_on_relative_paths">More on relative paths</A>
   	<LI><A HREF="snippets.html#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server</A>
   	<LI><A HREF="snippets.html#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
   	<LI><A HREF="snippets.html#Handling_cookies">Handling cookies</A>
  +	<LI><A HREF="snippets.html#Sending_multiply_cookies_with_Pe">Sending multiply cookies with Perl API</A>
  +	<LI><A HREF="snippets.html#Passing_environment_variables_be">Passing environment variables between handlers</A>
   </UL>
   <P><LI><A HREF="hardware.html"><B><FONT SIZE=+1>Choosing an Operating System and Hardware</FONT></B></A></LI><P>
   <UL>
  @@ -670,7 +766,7 @@
   
   <TR ALIGN=CENTER VALIGN=TOP>
   <TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A
  -HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 09/26/1999
  +HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 10/16/1999
   </FONT></B></TD>
   
   <TD><A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg"  BORDER=0 ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
  @@ -1041,47 +1137,110 @@
   <STRONG>Ken Williams</STRONG>, who reviewed a lot of stuff in the guide. Many snippets from his emails
   are included in the guide.
   
  +<P><LI>
  +<P>
  +<STRONG>Wesley Darlington</STRONG> for contributing a big section for scenario chapter.
  +
  +<P><LI>
  +<P>
  +<STRONG>Young, Geoffrey S</STRONG> and <STRONG>David Harris</STRONG> for contributing a big sections about mod_perl and RPM packages.
  +
  +<P><LI>
  +<P>
  +<STRONG>Andreas J. Koenig</STRONG> for contributing his ``Correct HTTP headers'' document.
  +
  +<P><LI>
  +<P>
  +<STRONG>Jeffrey W. Baker</STRONG> for his ``guide to mod_perl database performance''.
  +
  +<P><LI>
  +<P>
  +<STRONG>Richard A. Wells</STRONG> for reviewing a correcting a big part of the guide.
  +
  +<P><LI>
  +<P>
  +<STRONG>Randy Harmon</STRONG> for rewriting the mod_perl advocacy chapter
  +
  +<P><LI>
  +<P>
  +<STRONG>Dean Fitz</STRONG> for reviewing the ``Operating System and Hardware Demands'' chapter.
  +
   </UL>
   <P>
   Credits of course go to ( alphabetically sorted ):
   
   <UL>
   <P><LI><STRONG><A NAME="item_Andreas">Andreas J. Koenig</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Andrei">Andrei A. Voropaev</A></STRONG>
   <P><LI><STRONG><A NAME="item_Ask">Ask Bjoern Hansen</A></STRONG>
   <P><LI><STRONG><A NAME="item_Brian">Brian Moseley</A></STRONG>
   <P><LI><STRONG><A NAME="item_Chad">Chad K. Lewis</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Christof">Christof Damian</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Cliff">Cliff Rayman</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Daniel">Daniel Koch</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Daniel">Daniel W. Burke</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Dave">Dave Hodgkinson</A></STRONG>
  +<P><LI><STRONG><A NAME="item_David">David Harris</A></STRONG>
   <P><LI><STRONG><A NAME="item_David">David Landgren</A></STRONG>
   <P><LI><STRONG><A NAME="item_Dean">Dean Fitz</A></STRONG>
   <P><LI><STRONG><A NAME="item_Doug">Doug Bagley</A></STRONG>
   <P><LI><STRONG><A NAME="item_Ed">Ed Park</A></STRONG>
   <P><LI><STRONG><A NAME="item_Edmund">Edmund Mergl</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Eric">Eric Cholet</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Eric">Eric Strovink</A></STRONG>
   <P><LI><STRONG><A NAME="item_Evan">Evan A. Zacks</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Frank">Frank Schoeters</A></STRONG>
   <P><LI><STRONG><A NAME="item_G">G.Richter</A></STRONG>
   <P><LI><STRONG><A NAME="item_Garr">Garr Updegraff</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Gerald">Gerald Richter</A></STRONG>
   <P><LI><STRONG><A NAME="item_Gunther">Gunther Birznieks</A></STRONG>
   <P><LI><STRONG><A NAME="item_Henrique">Henrique Pantarotto</A></STRONG>
   <P><LI><STRONG><A NAME="item_Howard">Howard Jones</A></STRONG>
  +<P><LI><STRONG><A NAME="item_James">James G Smith</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Jan">Jan Peter Hecking</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Jason">Jason Bodnar</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Jauder">Jauder Ho</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Jay">Jay J</A></STRONG>
   <P><LI><STRONG><A NAME="item_Jeff">Jeff Baker</A></STRONG>
   <P><LI><STRONG><A NAME="item_Jeff">Jeff Rowe</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Jeffrey">Jeffrey W. Baker</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Jie">Jie Gao</A></STRONG>
  +<P><LI><STRONG><A NAME="item_John">John Milton</A></STRONG>
  +<P><LI><STRONG><A NAME="item_John">John Walker</A></STRONG>
   <P><LI><STRONG><A NAME="item_Jon">Jon Orwant</A></STRONG>
   <P><LI><STRONG><A NAME="item_Jonathan">Jonathan Peterson</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Joshua">Joshua Chamas</A></STRONG>
   <P><LI><STRONG><A NAME="item_Leslie">Leslie Mikesell</A></STRONG>
   <P><LI><STRONG><A NAME="item_Lincoln">Lincoln Stein</A></STRONG>
   <P><LI><STRONG><A NAME="item_Mark">Mark Mills</A></STRONG>
   <P><LI><STRONG><A NAME="item_Marshall">Marshall Dudley</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Matthew">Matthew Darwin</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Michael">Michael Hall</A></STRONG>
   <P><LI><STRONG><A NAME="item_Mike">Mike Fletcher</A></STRONG>
   <P><LI><STRONG><A NAME="item_Nancy">Nancy Lin</A></STRONG>
   <P><LI><STRONG><A NAME="item_Nathan">Nathan Torkington</A></STRONG>
   <P><LI><STRONG><A NAME="item_Nathan">Nathan Vonnahme</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Oleg">Oleg Bartunov</A></STRONG>
   <P><LI><STRONG><A NAME="item_Perrin">Perrin Harkins</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Peter">Peter Galbavy</A></STRONG>
   <P><LI><STRONG><A NAME="item_Peter">Peter Skov</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Philip">Philip Jacob</A></STRONG>
   <P><LI><STRONG><A NAME="item_Radu">Radu Greab</A></STRONG>
   <P><LI><STRONG><A NAME="item_Ralf">Ralf Engelschall</A></STRONG>
  -<P><LI><STRONG><A NAME="item_Randal">Randal Schwartz</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Randal">Randal L. Schwartz</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Randy">Randy Harmon</A></STRONG>
   <P><LI><STRONG><A NAME="item_Rauznitz">Rauznitz Balazs</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Richard">Richard A. Wells</A></STRONG>
   <P><LI><STRONG><A NAME="item_Richard">Richard Dice</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Rick">Rick Myers</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Robin">Robin Berjon</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Steve">Steve Reppucci</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Tom">Tom Hughes</A></STRONG>
   <P><LI><STRONG><A NAME="item_Tzvetan">Tzvetan Stoyanov</A></STRONG>
   <P><LI><STRONG><A NAME="item_Ulrich">Ulrich Pfeifer</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Vivek">Vivek Khera</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Wesley">Wesley Darlington</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Young">Young, Geoffrey S</A></STRONG>
   <P><LI>
   <P><LI><STRONG><A NAME="item_Did">Did I miss your name? Tell me!</A></STRONG>
   </UL>
  @@ -1125,7 +1284,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  +	     <BR>Last Modified at 10/16/1999
         </FONT>
       </B>
     </TD>
  @@ -1422,7 +1581,6 @@
   	<LI><A HREF="#Before_you_start_to_code">Before you start to code</A>
   	<LI><A HREF="#Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A>
   	<LI><A HREF="#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A>
  -	<LI><A HREF="#What_s_different_about_modperl">What's different about modperl</A>
   	<LI><A HREF="#Script_s_name_space">Script's name space</A>
   	<LI><A HREF="#Messing_with_INC">Messing with @INC</A>
   	<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  @@ -1443,7 +1601,7 @@
   
   	<LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
   	<LI><A HREF="#More_package_name_related_issues">More package name related issues</A>
  -	<LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  +	<LI><A HREF="#_END_and_DATA_tokens">__END__ and __DATA__ tokens</A>
   	<LI><A HREF="#Output_from_system_calls">Output from system calls</A>
   	<LI><A HREF="#Using_format_and_write_">Using format() and write()</A>
   	<LI><A HREF="#Using_exit_">Using exit()</A>
  @@ -1459,17 +1617,14 @@
   	<LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
   	<LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
   	<LI><A HREF="#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A>
  -	<LI><A HREF="#Global_Variables">Global Variables</A>
   	<LI><A HREF="#Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A>
   	<LI><A HREF="#Apache_and_syslog">Apache and syslog</A>
  -	<LI><A HREF="#Memory_leakage">Memory leakage</A>
   	<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
   	<LI><A HREF="#The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A>
   	<LI><A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
   	<LI><A HREF="#Sharing_variables_between_proces">Sharing variables between processes</A>
   	<LI><A HREF="#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
   	<LI><A HREF="#Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A>
  -	<LI><A HREF="#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
   	<LI><A HREF="#Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A>
   </UL>
   <!-- INDEX END -->
  @@ -1672,7 +1827,7 @@
     &lt;Location /perl&gt;
       PerlFixupHandler Apache::DB
       SetHandler perl-script
  -    PerlHandler Apache::Registry::handler
  +    PerlHandler Apache::Registry
       Options ExecCGI
       PerlSendHeader On
     &lt;/Location&gt;
  @@ -2173,13 +2328,6 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="What_s_different_about_modperl">What's different about modperl</A></H1></CENTER>
  -<P>
  -There are a few things that behave differently under mod_perl. It's good to
  -know what they are.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Script_s_name_space">Script's name space</A></H1></CENTER>
   <P>
   Scripts under <CODE>Apache::Registry</CODE> do not run in package <STRONG>main</STRONG>, they run in a unique name space based on the requested URI. For example,
  @@ -2330,7 +2478,7 @@
   <PRE>  PerlModule Apache::StatINC
     &lt;Location /perl&gt;
       SetHandler perl-script
  -    PerlHandler Apache::Registry::handler
  +    PerlHandler Apache::Registry
       Options ExecCGI
       PerlSendHeader On
       PerlInitHandler Apache::StatINC
  @@ -3073,7 +3221,7 @@
     # update the config file but first validate that the values are correct ones
     #########################
     sub process_change_config{
  -    my %updates = @_; # dereference
  +    my %updates = @_;
     
         # we will list here all the malformatted vars
       my %malformatted = ();
  @@ -3559,7 +3707,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H1></CENTER>
  +<CENTER><H1><A NAME="_END_and_DATA_tokens">__END__ and __DATA__ tokens</A></H1></CENTER>
   <P>
   <CODE>Apache::Registry</CODE> scripts cannot contain <CODE>__END__</CODE> or <CODE>__DATA__</CODE>
   tokens.
  @@ -3750,7 +3898,7 @@
   
   <P>
   <PRE>  {
  -    $/ = undef; 
  +    local $/ = undef; 
       open IN, &quot;file&quot; ....
         # slurp it all inside a variable
       $all_the_file = &lt;IN&gt;;
  @@ -3956,6 +4104,11 @@
   additional headers, like cookies and alike.
   
   <P>
  +See also <A HREF="././correct_headers.html#">Correct Headers - A quick guide for mod_perl users</A>
  +
  +
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H1></CENTER>
   <P>
  @@ -4223,38 +4376,6 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Global_Variables">Global Variables</A></H1></CENTER>
  -<P>
  -It's always a good idea to stay away from global variables when possible.
  -Some variables must be global so Perl can see them, such as a module's <CODE>@ISA</CODE> or <CODE>$VERSION</CODE> variables (or fully qualified
  -<STRONG>@MyModule::ISA</STRONG>). In common practice, a combination of <CODE>strict</CODE> and
  -<CODE>vars</CODE> pragmas keeps modules clean and reduces a bit of noise. However, <CODE>vars</CODE> pragma also creates aliases as the <CODE>Exporter</CODE>
  -does, which eat up more memory. When possible, try to use fully qualified
  -names instead of use vars. Example:
  -
  -<P>
  -<PRE>  package MyPackage;
  -  use strict;
  -  @MyPackage::ISA = qw(...);
  -  $MyPackage::VERSION = &quot;1.00&quot;;
  -</PRE>
  -<P>
  -vs.
  -
  -<P>
  -<PRE>  package MyPackage;
  -  use strict;
  -  use vars qw(@ISA $VERSION);
  -  @ISA = qw(...);
  -  $VERSION = &quot;1.00&quot;;
  -</PRE>
  -<P>
  -Also see <A HREF="././perl.html#Using_global_variables_and_shari">Using global variables and sharing them</A>
  -
  -
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H1></CENTER>
   <P>
   Files pulled in via <STRONG>use</STRONG> or <STRONG>require</STRONG> statements are not automatically reloaded when changed on disk. See <A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A> for more info.
  @@ -4272,387 +4393,101 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Memory_leakage">Memory leakage</A></H1></CENTER>
  +<CENTER><H1><A NAME="Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A></H1></CENTER>
   <P>
  -Scripts under mod_perl can very easily leak memory! Global variables stay
  -around indefinitely, lexical variables (declared with <CODE>my()</CODE> are destroyed when they go out of scope, provided there are no references
  -to them from outside of that scope.
  +When you write a script running under mod_cgi, you can get away with sloppy
  +programming, like opening a file and letting the interpreter to close it
  +for you when the script had finished his run:
   
   <P>
  -Perl doesn't return the memory it acquired from the kernel. It does reuse
  -it though!
  -
  +<PRE>  open IN, &quot;in.txt&quot; or die &quot;Cannot open in.txt for reading : $!\n&quot;;
  +</PRE>
   <P>
  -<STRONG>First example</STRONG> demonstrates reading in a whole file:
  +For mod_perl you <STRONG>must</STRONG>  <CODE>close()</CODE> the files you opened!
   
   <P>
  -<PRE>  open IN, $file or die $!;
  -  $/ = undef; # will read the whole file in
  -  $content = &lt;IN&gt;;
  -  close IN;
  +<PRE>  close IN;
   </PRE>
   <P>
  -If your file is 5Mb, the child who served that script will grow exactly by
  -that size. Now if you have 20 children and all of them will serve this CGI,
  -all of them will consume additional 20*5M = 100M of RAM! If that's the
  -case, try to use other approaches of processing the file, if possible of
  -course. Try to process a line at a time and print it back to the file. (If
  -you need to modify the file itself, use a temporary file. When finished,
  -overwrite the source file, make sure to provide a locking mechanism!)
  +somewhere before the end of the script, since if you forget to
  +<CODE>close()</CODE>, you might get a file descriptor leakage and unlock problem (if you <CODE>flock()ed</CODE> on this file descriptor). Even if you do have it, but for some reason the
  +interpreter was stopped before the cleanup call, because of various
  +reasons, such as user aborted script ( See
  +<A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>) the leakage is still there. In a long run your machine might get run out
  +of file descriptors, and even worse - file might be left locked and
  +unusable by other invocations of the same and other scripts.
   
   <P>
  -<STRONG>Second example</STRONG> demonstrates copying variables between functions (passing variables by
  -value). Let's use the example above, assuming we have no choice but to read
  -the whole file before any data processing takes place. Now you have some
  -imagine <CODE>process()</CODE> subroutine that processes the data and returns it back. What happens if you
  -pass the
  -<CODE>$content</CODE> by value? You have just copied another 5M and the child has grown by
  -another 5M in size (watch your swap space!) now multiply it again by factor
  -of 20 you have 200M of wasted RAM, which will be apparently reused but it's
  -a waste! Whenever you think the variable can grow bigger than few Kb, pass
  -it by reference!
  +What can you do? Use <CODE>IO::File</CODE> (and other <CODE>IO::*</CODE> modules), which allows you to assign the file handler to variable, which
  +can be
  +<CODE>my()</CODE> (lexically) scoped. And when this variable goes out of scope the file or
  +other file system entity will be properly closed and unlocked (if it was
  +locked). Lexically scoped variable will always go out of scope at the end
  +of the script's run even if it was aborted in the middle or before the end
  +if it was defined inside some internal block. For example:
   
   <P>
  -Once I wrote a script that passed a content of a little flat file DataBase
  -to a function that processed it by value -- it worked and it was processed
  -fast, but with a time the DataBase became bigger, so passing it by value
  -was an overkill -- I had to make a decision, whether to buy more memory or
  -to rewrite the code. It's obvious that adding more memory will be merely a
  -temporary solution. So it's better to plan ahead and pass the variables by
  -reference, if a variable you are going to pass might be bigger than you
  -think at the time of your coding process. There are a few approaches you
  -can use to pass and use variables passed by reference. For example:
  +<PRE>  {
  +    my $fh = new IO::File(&quot;filename&quot;) or die $!;
  +    # read from $fh
  +  } # ...$fh is closed automatically at end of block, without leaks.
  +</PRE>
  +<P>
  +As I have just mentioned, you don't have to create a special block for this
  +purpose, for a file the code is written in is a virtual block as well, so
  +you can simply write:
   
   <P>
  -<PRE>  my $content = qq{foobarfoobar};
  -  process(\$content);
  -  sub process{
  -    my $r_var = shift; 
  -    $$r_var =~ s/foo/bar/gs;
  -      # nothing returned - the variable $content outside has been
  -      # already modified
  -  }
  -  
  -  @{$var_lr} -- dereferences an array
  -  %{$var_hr} -- dereferences a hash
  +<PRE>  my $fh = new IO::File(&quot;filename&quot;) or die $!;
  +    # read from $fh
  +    # ...$fh is closed automatically at end of block, without leaks.
   </PRE>
   <P>
  -For more info see <CODE>perldoc perlref</CODE>.
  +What the first technique (using <CODE>{ BLOCK }</CODE>) makes sure is that the file will be closed the moment, the block is
  +finished.
   
   <P>
  -Another approach would be to directly use a <CODE>@_</CODE> array. Using directly the <CODE>@_</CODE> array serves the job of passing by reference!
  +But even faster and lighter technique is to use <CODE>Symbol.pm</CODE>:
   
   <P>
  -<PRE>  process($content);
  -  sub process{
  -    $_[0] =~ s/foo/bar/gs;
  -      # nothing returned - the variable $content outside has been
  -      # already modified
  -  }
  +<PRE>  my $fh = Symbol::gensym();
  +  open $fh, &quot;filename&quot; or die $!
   </PRE>
   <P>
  -From <CODE>perldoc perlsub</CODE>:
  +Use these approaches to ensure you have no leakages, but don't be lazy to
  +write <CODE>close()</CODE> statements, make it a habit.
   
  -<P>
  -<PRE>      The array @_ is a local array, but its elements are aliases for
  -      the actual scalar parameters.  In particular, if an element
  -      $_[0] is updated, the corresponding argument is updated (or an
  -      error occurs if it is not possible to update)...
  -</PRE>
   <P>
  -Be careful when you write this kind of subroutines, since it can confuse a
  -potential user. It's not obvious that call like
  -<CODE>process($content);</CODE> modifies the passed variable -- programmers (which are the users of your
  -library in this case) are used to subs that either modify variables passed
  -by reference or return the processed variable (e.g. <CODE>$content=process($content);</CODE>).
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A></H1></CENTER>
   <P>
  -<STRONG>Third example</STRONG> demonstrates a work with DataBases. If you do some DB processing, many
  -times you encounter the need to read lots of records into your program, and
  -then print them to the browser after they are formatted. (I don't even
  -mention the horrible case where programmers read in the whole DB and then
  -use perl to process it!!! Use a relational DB and let the SQL do the job,
  -so you get only the records you need!!!).
  +You still can win from using mod_perl. 
   
   <P>
  -We will use <CODE>DBI</CODE> for this (assume that we are already connected to the DB) (refer to <CODE>perldoc DBI</CODE> for a complete manual of the <CODE>DBI</CODE>
  -module):
  +One approach is to replace the <CODE>Apache::Registry</CODE> handler with
  +<CODE>Apache::PerlRun</CODE> and define a new location (the script can reside in the same directory on
  +the disk. 
   
   <P>
  -<PRE>  $sth-&gt;execute;
  -  while(@row_ary  = $sth-&gt;fetchrow_array;) {
  -        &lt;do DB accumulation into some variable&gt;
  -  }
  -  &lt;print the output using the the data returned from the DB&gt;
  +<PRE>  # srm.conf
  +  Alias /cgi-perl/ /home/httpd/cgi/
  +  
  +  # httpd.conf
  +  &lt;Location /cgi-perl&gt;
  +    #AllowOverride None
  +    SetHandler perl-script
  +    PerlHandler Apache::PerlRun
  +    Options ExecCGI
  +    allow from all
  +    PerlSendHeader On
  +  &lt;/Location&gt;
   </PRE>
   <P>
  -In the example above the httpd_process will grow up by the size of the
  -variables that have been allocated for the records that matched the query.
  -(Again remember to multiply it by the number of the children your server
  -runs!).
  +See <A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
   
  -<P>
  -A better approach is to not accumulate the records, but rather print them
  -as they are fetched from the DB. Moreover, we will use the
  -<CODE>bind_col()</CODE> and <CODE>$sth-&amp;gt;fetchrow_arrayref()</CODE> (aliased to
  -<CODE>$sth-&amp;gt;fetch()</CODE>) methods, to fetch the data in the fastest possible way. The example below
  -prints a HTML TABLE with matched data, the only memory that is being used
  -is a <CODE>@cols</CODE> array to hold temporary row values:
  +
   
   <P>
  -<PRE>  my @select_fields = qw(a b c);
  -      # create a list of cols values
  -  my @cols = ();
  -  @cols[0..$#select_fields] = ();
  -  $sth = $dbh-&gt;prepare($do_sql);
  -  $sth-&gt;execute;
  -    # Bind perl variables to columns.
  -  $sth-&gt;bind_columns(undef,\(@cols));
  -  print &quot;&lt;TABLE&gt;&quot;;
  -  while($sth-&gt;fetch) {
  -     print &quot;&lt;TR&gt;&quot;,
  -           map(&quot;&lt;TD&gt;$_&lt;/TD&gt;&quot;, @cols),
  -           &quot;&lt;/TR&gt;&quot;;
  -  }
  -  print &quot;&lt;/TABLE&gt;&quot;;
  -</PRE>
  -<P>
  -Note: the above method doesn't allow you to know how many records have been
  -matched. The workaround is to run an identical query before the code above
  -where you use <CODE>SELECT count(*) ...</CODE> instead of <CODE>'SELECT *
  -...</CODE> to get the number of matched records. It should be much faster, since you
  -can remove any <STRONG>SORTBY</STRONG> and alike attributes.
  -
  -<P>
  -For those who think that <STRONG>$sth-&gt;rows</STRONG> will do the job, here is the quote from the <CODE>DBI</CODE> manpage:
  -
  -<P>
  -<PRE>  rows();
  -</PRE>
  -<P>
  -<PRE>  $rv = $sth-&gt;rows;
  -</PRE>
  -<P>
  -<PRE>  Returns the number of rows affected by the last database altering
  -  command, or -1 if not known or not available.  Generally you can
  -  only rely on a row count after a do or non-select execute (for some
  -  specific operations like update and delete) or after fetching all
  -  the rows of a select statement.
  -</PRE>
  -<P>
  -<PRE>  For select statements it is generally not possible to know how many
  -  rows will be returned except by fetching them all.  Some drivers
  -  will return the number of rows the application has fetched so far
  -  but others may return -1 until all rows have been fetched. So use of
  -  the rows method with select statements is not recommended.
  -</PRE>
  -<P>
  -As a bonus, I wanted to write a single sub that flexibly processes any
  -query, accepting: conditions, call-back closure sub, select fields and
  -restrictions. 
  -
  -<P>
  -<PRE>  # Usage:
  -  # $o-&gt;dump(\%conditions,\&amp;callback_closure,\@select_fields,@restrictions);
  -  #
  -  sub dump{
  -    my $self = shift;
  -    my %param = %{+shift}; # dereference hash
  -    my $rsub = shift;
  -    my @select_fields = @{+shift}; # dereference list
  -    my @restrict = shift || '';
  -  
  -      # create a list of cols values
  -    my @cols = ();
  -    @cols[0..$#select_fields] = ();
  -  
  -    my $do_sql = '';
  -    my @where = ();
  -  
  -      # make a @where list 
  -    map { push @where, &quot;$_=\'$param{$_}\'&quot; if $param{$_};} keys %param;
  -  
  -      # prepare the sql statement
  -    $do_sql = &quot;SELECT &quot;;
  -    $do_sql .= join(&quot; &quot;, @restrict) if @restrict;# append the restriction list
  -    $do_sql .= &quot; &quot; .join(&quot;,&quot;, @select_fields) ;      # append the select list 
  -    $do_sql .= &quot; FROM $DBConfig{TABLE} &quot;;         # from table
  -  
  -      # we will not add the WHERE clause if @where is empty
  -    $do_sql .= &quot; WHERE &quot; . join &quot; AND &quot;, @where if @where;
  -  
  -    print &quot;SQL: $do_sql \n&quot; if $debug;
  -  
  -    $dbh-&gt;{RaiseError} = 1;     # do this, or check every call for errors
  -    $sth = $dbh-&gt;prepare($do_sql);
  -    $sth-&gt;execute;
  -      # Bind perl variables to columns.
  -    $sth-&gt;bind_columns(undef,\(@cols));
  -    while($sth-&gt;fetch) {
  -      &amp;$rsub(@cols);
  -    }
  -      # print the tail or &quot;no records found&quot; message
  -      # according to the previous calls
  -    &amp;$rsub();
  -  
  -  } # end of sub dump
  -</PRE>
  -<P>
  -Now a callback closure sub can do lots of things. We need a closure to know
  -what stage are we in: header, body or tail. For example, we want a callback
  -closure for formatting the rows to print: 
  -
  -<P>
  -<PRE>  my $rsub = eval {
  -      # make a copy of @fields list, since it might go
  -      # out of scope when this closure will be called
  -    my @fields = @fields; 
  -    my @query_fields = qw(user dir tool act); # no date field!!!
  -    my $header = 0;
  -    my $tail   = 0;
  -    my $counter = 0;
  -    my %cols = (); # columns name=&gt; value hash
  -  
  -    # Closure with the following behavior:
  -    # 1. Header's code will be executed on the first call only and
  -    #    if @_ was set
  -    # 2. Row's printing code will be executed on every call with @_ set
  -    # 3. Tail's code will be executed only if Header's code was
  -    #    printed and @_ isn't set
  -    # 4. &quot;No record found&quot; code will be executed if Header's code
  -    #    wasn't executed
  -  
  -    sub {
  -          # Header
  -        if (@_ and !$header){
  -          print &quot;&lt;TABLE&gt;\n&quot;;
  -          print $q-&gt;Tr(map{ $q-&gt;td($_) } @fields );
  -          $header = 1; 
  -        }
  -        
  -          # Body
  -        if (@_) {
  -          print $q-&gt;Tr(map{$q-&gt;td($_)} @_ );
  -          $counter++;
  -          return; 
  -        }
  -        
  -          # Tail, will be printed only at the end
  -        if ($header and !($tail or @_)){
  -          print &quot;&lt;/TABLE&gt;\n $counter records found&quot;;
  -          $tail = 1;
  -          return;
  -        }
  -        
  -          # No record found
  -        unless ($header){
  -          print $q-&gt;p($q-&gt;center($q-&gt;b(&quot;No record was found!\n&quot;)));
  -        }
  -  
  -      }  #  end of sub {}
  -  };  #  end of my $rsub = eval {
  -</PRE>
  -<P>
  -You might also want to check <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
  -and <A HREF="././performance.html#Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A>.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A></H1></CENTER>
  -<P>
  -When you write a script running under mod_cgi, you can get away with sloppy
  -programming, like opening a file and letting the interpreter to close it
  -for you when the script had finished his run:
  -
  -<P>
  -<PRE>  open IN, &quot;in.txt&quot; or die &quot;Cannot open in.txt for reading : $!\n&quot;;
  -</PRE>
  -<P>
  -For mod_perl you <STRONG>must</STRONG>  <CODE>close()</CODE> the files you opened!
  -
  -<P>
  -<PRE>  close IN;
  -</PRE>
  -<P>
  -somewhere before the end of the script, since if you forget to
  -<CODE>close()</CODE>, you might get a file descriptor leakage and unlock problem (if you <CODE>flock()ed</CODE> on this file descriptor). Even if you do have it, but for some reason the
  -interpreter was stopped before the cleanup call, because of various
  -reasons, such as user aborted script ( See
  -<A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>) the leakage is still there. In a long run your machine might get run out
  -of file descriptors, and even worse - file might be left locked and
  -unusable by other invocations of the same and other scripts.
  -
  -<P>
  -What can you do? Use <CODE>IO::File</CODE> (and other <CODE>IO::*</CODE> modules), which allows you to assign the file handler to variable, which
  -can be
  -<CODE>my()</CODE> (lexically) scoped. And when this variable goes out of scope the file or
  -other file system entity will be properly closed and unlocked (if it was
  -locked). Lexically scoped variable will always go out of scope at the end
  -of the script's run even if it was aborted in the middle or before the end
  -if it was defined inside some internal block. For example:
  -
  -<P>
  -<PRE>  {
  -    my $fh = new IO::File(&quot;filename&quot;) or die $!;
  -    # read from $fh
  -  } # ...$fh is closed automatically at end of block, without leaks.
  -</PRE>
  -<P>
  -As I have just mentioned, you don't have to create a special block for this
  -purpose, for a file the code is written in is a virtual block as well, so
  -you can simply write:
  -
  -<P>
  -<PRE>  my $fh = new IO::File(&quot;filename&quot;) or die $!;
  -    # read from $fh
  -    # ...$fh is closed automatically at end of block, without leaks.
  -</PRE>
  -<P>
  -What the first technique (using <CODE>{ BLOCK }</CODE>) makes sure is that the file will be closed the moment, the block is
  -finished.
  -
  -<P>
  -But even faster and lighter technique is to use <CODE>Symbol.pm</CODE>:
  -
  -<P>
  -<PRE>  my $fh = Symbol::gensym();
  -  open $fh, &quot;filename&quot; or die $!
  -</PRE>
  -<P>
  -Use these approaches to ensure you have no leakages, but don't be lazy to
  -write <CODE>close()</CODE> statements, make it a habit.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="The_Script_is_too_dirty_but_It_">The Script is too dirty, but It does the job and I can't afford rewriting it.</A></H1></CENTER>
  -<P>
  -You still can win from using mod_perl. 
  -
  -<P>
  -One approach is to replace the <CODE>Apache::Registry</CODE> handler with
  -<CODE>Apache::PerlRun</CODE> and define a new location (the script can reside in the same directory on
  -the disk. 
  -
  -<P>
  -<PRE>  # srm.conf
  -  Alias /cgi-perl/ /home/httpd/cgi/
  -  
  -  # httpd.conf
  -  &lt;Location /cgi-perl&gt;
  -    #AllowOverride None
  -    SetHandler perl-script
  -    PerlHandler Apache::PerlRun
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  -</PRE>
  -<P>
  -See <A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
  -
  -
  -
  -<P>
   Another ``bad'', but working method is to set <CODE>MaxRequestsPerChild</CODE> to 1, which will force each child to exit after serving only one request,
   so you'll get the preloaded modules, etc., the script will be compiled each
   request, then killed off. This isn't good for ``high-traffic'' sites
  @@ -4961,138 +4796,8 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A></H1></CENTER>
   <P>
  -Generally you should not fork from your mod_perl scripts, since when you do
  --- you are forking the entire apache web server, lock, stock and barrel.
  -Not only is your perl code being duplicated, but so is mod_ssl,
  -mod_rewrite, mod_log, mod_proxy, mod_spelling or whatever modules you have
  -used in your server, all the core routines and so on.
  -
  -<P>
  -A much wiser approach would be to spawn a sub-process, hand it the
  -information it needs to do the task, and have it detach (close x3 +
  -<CODE>setsid()</CODE>). This is wise only if the parent who spawns this process, immediately
  -continue, you do not wait for the sub-process to complete. This approach is
  -suitable for a situation when you want to trigger a long time taking
  -process through the web interface, like processing some data, sending email
  -to thousands of subscribed users and etc. Otherwise, you should convert the
  -code into a module, and use its functions or methods to call from CGI
  -script.
  -
  -<P>
  -Just making a <CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
  -should be loaded again for this external program to run.
  -
  -<P>
  -Basically, you would do:
  -
  -<P>
  -<PRE>  $params=FreezeThaw::freeze(
  -        [all data to pass to the other process]
  -        );
  -  system(&quot;program.pl $params&quot;);
  -</PRE>
  -<P>
  -and in <CODE>program.pl</CODE> :
  -
  -<P>
  -<PRE>  @params=FreezeThaw::thaw(shift @ARGV);
  -  # check that @params is ok
  -  close STDIN;
  -  close STDOUT;
  -  open STDERR, &quot;&gt;/dev/null&quot;;
  -  setsid(); # to detach
  -</PRE>
  -<P>
  -At this point, <CODE>program.pl</CODE> is running in the ``background'' while the
  -<CODE>system()</CODE> returns and permits apache to get on with life.
  -
  -<P>
  -This has obvious problems. Not the least of which is that <CODE>@params</CODE>
  -must not be bigger then whatever your architecture's limit is (could depend
  -on your shell).
  -
  -<P>
  -Also, the communication is only one way.
  -
  -<P>
  -However, you might want be trying to do the ``wrong thing''. If what you
  -want is to send information to the browser and then do some
  -post-processing, look into <CODE>PerlCleanupHandler</CODE>.
  -
  -<P>
  -If you are interested in more deep level details, this is what actually
  -happens when you fork and make a system call, like
  -
  -<P>
  -<PRE>  system(&quot;echo Hi&quot;),exit unless fork();
  -</PRE>
  -<P>
  -What happens is that <CODE>fork()</CODE> gives you 2 execution paths and
  -the child gets virtual memory sharing a copy of the program text (read
  -only) and sharing a copy of the data space copy-on-write (remember why you
  -pre-load modules in mod_perl?). In the above code a parent will immediately
  -continue with the code that comes up after the fork, while the forked
  -process will execute <CODE>system(&quot;echo Hi&quot;)</CODE> and then terminate itself. Note that you might need to set:
  -
  -<P>
  -<PRE>  $SIG{CHLD} = sub {wait};
  -</PRE>
  -<P>
  -or
  -
  -<P>
  -<PRE>  $SIG{CHLD} = IGNORE;
  -</PRE>
  -<P>
  -or the terminated process might become a zombie. Normally, every process
  -has its parent, many processes a children of PID 1, the init process.
  -Zombie, is a process that doesn't have a father. When the child quits, it
  -reports the termination to his parent. If he doesn't know who the father is
  -it becomes zombie. (META: Did I formulate it correctly?)
  -
  -<P>
  -The only work is setting up the page tables for the virtual memory and the
  -second process goes on its separate way.
  -
  -<P>
  -Next, Perl will find <CODE>/bin/echo</CODE> along the search path, and invoke it directly. Perl <CODE>system()</CODE>
  -is *not* <CODE>system(3)</CODE> [C-library]. Only when the command has shell meta-chars does Perl invoke a
  -real shell. That's a *very* nice optimization.
  -
  -<P>
  -Only if you do:
  -
  -<P>
  -<PRE>  system &quot;sh -c 'echo foo'&quot;
  -</PRE>
  -<P>
  -OS actually parses your command with a shell so you <CODE>exec()</CODE> a
  -copy of
  -<CODE>/bin/sh</CODE>, but since one is almost certainly already running somewhere, the system
  -will notice that (via the disk inode reference) and replace your virtual
  -memory page table with one pointed at the already-loaded program code plus
  -your own data space. Then the shell parses the passed command.
  -
  -<P>
  -Since it is <CODE>echo</CODE>, it will execute it as a built-in in the latter example or a <CODE>/bin/echo</CODE> in the former and be done, but this is only an example. You aren't calling <CODE>system(&quot;echo Hi&quot;)</CODE> in your mod_perl scripts, right? Since most other real things (heavy
  -programs executed as a subprocess) would involve repeating the process to
  -load the specified command or script (it might involve some actual demand
  -paging from the program file if you execute new code).
  -
  -<P>
  -The only place you see real overhead from this scheme is when the parent
  -process is huge (unfortunately like mod_perl...) and the page table becomes
  -large as a side effect. The whole point of mod_perl is to avoid having to
  -<CODE>fork()</CODE> / <CODE>exec()</CODE> something on every hit, though.
  -Perl can do just about anything by itself. However, you probably won't get
  -in trouble until you hit about 30 forks/sec on a so-so pentium.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Passing_and_preserving_custom_da">Passing and preserving custom data structures between handlers</A></H1></CENTER>
  -<P>
   Let's say that you wrote a few handlers to process a request, and they all
   need to share some custom Perl data structure. The <CODE>pnotes()</CODE>
   method comes to rescue. Taken that one of the handlers stored some data in
  @@ -5146,7 +4851,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/26/1999
  +	     <BR>Last Modified at 10/16/1999
         </FONT>
       </B>
     </TD>
  @@ -5198,8 +4903,10 @@
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Performance_The_Overall_picture">Performance: The Overall picture</A>
  +	<LI><A HREF="#Performance_An_Overall_picture">Performance: An Overall picture</A>
  +	<LI><A HREF="#Analysis_of_SW_and_HW_Requiremen">Analysis of SW and HW Requirements</A>
   	<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
  +	<LI><A HREF="#How_Shared_My_Memory_Is">How Shared My Memory Is</A>
   	<LI><A HREF="#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
   	<UL>
   
  @@ -5207,12 +4914,14 @@
   	</UL>
   
   	<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
  +	<LI><A HREF="#Global_vs_Fully_Qualified_Variab">Global vs Fully Qualified Variables </A>
   	<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</A>
   	<LI><A HREF="#PerlSetupEnv_Off">PerlSetupEnv Off</A>
  +	<LI><A HREF="#Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A>
  +	<LI><A HREF="#Memory_leakage">Memory leakage</A>
   	<LI><A HREF="#_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A>
  -	<LI><A HREF="#Shared_Memory">Shared Memory</A>
   	<LI><A HREF="#Checking_script_modification_tim">Checking script modification times</A>
  -	<LI><A HREF="#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
  +	<LI><A HREF="#Cached_stat_calls">Cached stat() calls</A>
   	<LI><A HREF="#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
   	<LI><A HREF="#Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A>
   	<LI><A HREF="#Limiting_the_request_rate_speed_">Limiting the request rate speed (robots blocking)</A>
  @@ -5237,11 +4946,29 @@
   	</UL>
   
   	<LI><A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>
  +	<UL>
  +
  +		<LI><A HREF="#Preopening_Connections_at_the_Ch">Preopening Connections at the Child Process' Fork Time</A>
  +		<LI><A HREF="#Caching_prepare_statements">Caching prepare() statements</A>
  +		<LI><A HREF="#Handling_Timeouts">Handling Timeouts</A>
  +	</UL>
  +
  +	<LI><A HREF="#Jeff_s_guide_to_mod_perl_databas">Jeff's guide to mod_perl database performance</A>
  +	<UL>
  +
  +		<LI><A HREF="#Analysis_of_the_Problem">Analysis of the Problem</A>
  +		<LI><A HREF="#Optimizing_Database_Connections">Optimizing Database Connections</A>
  +		<LI><A HREF="#Utilizing_the_Database_Server_s_">Utilizing the Database Server's Cache</A>
  +		<LI><A HREF="#Eliminating_SQL_Statement_Parsin">Eliminating SQL Statement Parsing</A>
  +		<LI><A HREF="#Conclusion">Conclusion</A>
  +	</UL>
  +
   	<LI><A HREF="#Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</A>
   	<LI><A HREF="#More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A>
   	<LI><A HREF="#Profiling">Profiling</A>
   	<LI><A HREF="#CGI_pm_s_object_methods_calls_vs">CGI.pm's object methods calls vs. function calls</A>
   	<LI><A HREF="#Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A>
  +	<LI><A HREF="#Increasing_the_shared_memory_wit">Increasing the shared memory with mergemem</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -5268,7 +4995,7 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Performance_The_Overall_picture">Performance: The Overall picture</A></H1></CENTER>
  +<CENTER><H1><A NAME="Performance_An_Overall_picture">Performance: An Overall picture</A></H1></CENTER>
   <P>
   Before we dive into performance issues, there is something very important
   to understand. It applies to any webserver, not only apache. All the
  @@ -5304,6 +5031,51 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Analysis_of_SW_and_HW_Requiremen">Analysis of SW and HW Requirements</A></H1></CENTER>
  +<P>
  +(META: Only partial analysis. Please submit more points. Many points are
  +scattered around the document and should be gathered here, to represent the
  +whole picture. It also should be merged with the above item!)
  +
  +<P>
  +You need to analyze all of the problem's dimensions. There are several
  +things that need to be considered:
  +
  +<P>
  +<CODE>*How</CODE> long does it take to process each request
  +
  +<P>
  +<CODE>*How</CODE> many requests can you process simultaneously
  +
  +<P>
  +<CODE>*How</CODE> many simultaneous requests are you planning to get
  +
  +<P>
  +The first one is probably the easiest to optimize. Follow the performance
  +optimization tips in the guide and other docs, let a profeccional perl
  +(mod_perl) programmer to work out your code and improve it.
  +
  +<P>
  +The second one is a function of RAM. How much RAM is in the box, how many
  +boxes do you have, and how much RAM does each mod_perl process take?
  +Multiply the first two and divide by the third. Ask yourself whether it is
  +better to switch to another, possibly just as inefficient language will
  +actually cost more than throwing another Ultra 2 into the rack. Also ask
  +yourself whether switching to another language will even help. In some
  +applications, a huge chunk of memory is needed e.g. to link in Oracle
  +runtime libraries. So you would pay this price even if you switch from Perl
  +to C.
  +
  +<P>
  +The last one is important. You need to have a realistic answer. Are you
  +really expecting 8 million hits per day? What is the expected peak load,
  +and what kind of response time do you need to guarantee? Remember that this
  +numbers might change drastically when you apply code changes and your site
  +becomes more popular. Remember that when the you get a very high hits rate,
  +the requirements wouldn't grow lineary by exponentialy!
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Sharing_Memory">Sharing Memory</A></H1></CENTER>
   <P>
   A very important point is the sharing of memory. If your OS supports this
  @@ -5346,6 +5118,32 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="How_Shared_My_Memory_Is">How Shared My Memory Is</A></H1></CENTER>
  +<P>
  +You've probably noticed that the word shared is being repeated many times
  +in many things related to mod_perl. Indeed, shared memory might save you a
  +lot of money, since with sharing in place you can run many more servers
  +than without it. See <A HREF="././performance.html#Choosing_MaxClients">the Formula and the numbers</A>.
  +
  +<P>
  +How much shared memory do you have? You can see it by either using the
  +memory utils that comes with your system or you can deploy <CODE>GTop</CODE>
  +module:
  +
  +<P>
  +<PRE>  print &quot;Shared memory of the current process: &quot;,
  +    GTop-&gt;new-&gt;proc_mem($$)-&gt;share,&quot;\n&quot;;
  +</PRE>
  +<P>
  +<PRE>  print &quot;Total shared memory: &quot;,
  +    GTop-&gt;new-&gt;mem-&gt;share,&quot;\n&quot;;
  +</PRE>
  +<P>
  +When you watch the output of the <CODE>top</CODE> utility, don't confuse <STRONG>RSS</STRONG>
  +(or <STRONG>RES</STRONG>) column with <STRONG>SHARE</STRONG> column -- <STRONG>RES</STRONG> is a RESident memory, which is a size of pages currently swapped in.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A></H1></CENTER>
   <P>
   Use the <CODE>PerlRequire</CODE> and <CODE>PerlModule</CODE> directives to load commonly used modules such as <CODE>CGI.pm</CODE>, <CODE>DBI</CODE> and etc., when the server is started. On most systems, server children will
  @@ -5739,13 +5537,51 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Global_vs_Fully_Qualified_Variab">Global vs Fully Qualified Variables</A></H1></CENTER>
  +<P>
  +It's always a good idea to stay away from global variables when possible.
  +Some variables must be global so Perl can see them, such as a module's <CODE>@ISA</CODE> or <CODE>$VERSION</CODE> variables (or fully qualified
  +<STRONG>@MyModule::ISA</STRONG>). In common practice, a combination of <CODE>strict</CODE> and
  +<CODE>vars</CODE> pragmas keeps modules clean and reduces a bit of noise. However, <CODE>vars</CODE> pragma also creates aliases as the <CODE>Exporter</CODE>
  +does, which eat up more memory. When possible, try to use fully qualified
  +names instead of use vars. Example:
  +
  +<P>
  +<PRE>  package MyPackage;
  +  use strict;
  +  @MyPackage::ISA = qw(...);
  +  $MyPackage::VERSION = &quot;1.00&quot;;
  +</PRE>
  +<P>
  +vs.
  +
  +<P>
  +<PRE>  package MyPackage;
  +  use strict;
  +  use vars qw(@ISA $VERSION);
  +  @ISA = qw(...);
  +  $VERSION = &quot;1.00&quot;;
  +</PRE>
  +<P>
  +Also see <A HREF="././perl.html#Using_global_variables_and_shari">Using global variables and sharing them</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Avoid_Importing_Functions">Avoid Importing Functions</A></H1></CENTER>
   <P>
   When possible, avoid importing a module's functions into your name space.
   The aliases which are created can take up quite a bit of space. Try to use
   method interfaces and fully qualified
  -<CODE>Package::function</CODE> or <CODE>$Package::variable</CODE> like names instead.
  +<CODE>Package::function</CODE> or <CODE>$Package::variable</CODE> like names instead. For benchmarks see <A HREF="././performance.html#CGI_pm_s_object_methods_calls_vs">CGI.pm's object methods calls vs. function calls</A>
  +
   
  +
  +<P>
  +Note: method interfaces are a little bit slower than function calls. You
  +can use a <CODE>Benchmark</CODE> module to profile your specific code. 
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="PerlSetupEnv_Off">PerlSetupEnv Off</A></H1></CENTER>
  @@ -5761,2240 +5597,2511 @@
   But <CODE>%ENV</CODE> population is expensive. Those who have moved to the Perl Apache API no
   longer need this extra <CODE>%ENV</CODE> population, can gain by turning it <STRONG>Off</STRONG>.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A></H1></CENTER>
   <P>
  -Newer Perl versions also have build time options to reduce runtime memory
  -consumption. These options might shrink down the size of your httpd by
  -about ~150k (quite big number if you remember to multiply it by the number
  -of chidren you use.)
  +By default it is On.
   
   <P>
  -<CODE>-DTWO_POT_OPTIMIZE</CODE> macro improves allocations of data with size close to a power of two; but
  -this works for big allocations (starting with 16K by default). Such
  -allocations are typical for big hashes and special-purpose scripts,
  -especially image processing.
  +Note that you can still set ENV variables. e.g. when you use the following
  +configuration:
   
   <P>
  -Perl memory allocation is by bucket with sizes close to powers of two.
  -Because of these malloc overhead may be big, especially for data of size
  -exactly a power of two. If <CODE>PACK_MALLOC</CODE> is defined, perl uses a slightly different algorithm for small allocations
  -(up to 64 bytes long), which makes it possible to have overhead down to 1
  -byte for allocations which are powers of two (and appear quite often). 
  -
  +<PRE> &lt;Location /perl&gt;
  +   PerlSetupEnv Off
  +   PerlSetEnv TEST hi
  +   SetHandler perl-script
  +   PerlHandler Apache::RegistryNG-&gt;handler
  +   Options +ExecCGI
  + &lt;/Location&gt;
  +</PRE>
   <P>
  -Expected memory savings (with 8-byte alignment in <CODE>alignbytes</CODE>) is about 20% for typical Perl usage. Expected slowdown due to additional
  -malloc overhead is in fractions of a percent (hard to measure, because of
  -the effect of saved memory on speed).
  +A script having a <CODE>print Data::Dumper(\%ENV)</CODE> line, prints:
   
   <P>
  -You will find these and other memory improvement details in
  -<CODE>perl5004delta.pod</CODE>.
  -
  +<PRE>  $VAR1 = {
  +            'GATEWAY_INTERFACE' =&gt; 'CGI-Perl/1.1',
  +            'MOD_PERL' =&gt; 'mod_perl/1.21_01-dev',
  +            'PATH' =&gt; '/usr/lib/perl5/5.00503:... snipped ...',
  +            'TEST' =&gt; 'hi'
  +          };
  +</PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Shared_Memory">Shared Memory</A></H1></CENTER>
  -<P>
  -You've probably noticed that the word shared is being repeated many times
  -in many things related to mod_perl. Indeed, shared memory might save you a
  -lot of money, since with sharing in place you can run many more servers
  -than without it. See <A HREF="././performance.html#Choosing_MaxClients">the Formula and the numbers</A>.
  -
  +<CENTER><H1><A NAME="Forking_or_Executing_subprocesse">Forking or Executing subprocesses from mod_perl</A></H1></CENTER>
   <P>
  -How much shared memory do you have? You can see it by either using the
  -memory utils that comes with your system or you can deploy <CODE>GTop</CODE>
  -module:
  +Generally you should not fork from your mod_perl scripts, since when you do
  +-- you are forking the entire apache web server, lock, stock and barrel.
  +Not only is your perl code being duplicated, but so is mod_ssl,
  +mod_rewrite, mod_log, mod_proxy, mod_spelling or whatever modules you have
  +used in your server, all the core routines and so on.
   
   <P>
  -<PRE>  print &quot;Shared memory of the current process: &quot;,
  -    GTop-&gt;new-&gt;proc_mem($$)-&gt;share,&quot;\n&quot;;
  -</PRE>
  -<P>
  -<PRE>  print &quot;Total shared memory: &quot;,
  -    GTop-&gt;new-&gt;mem-&gt;share,&quot;\n&quot;;
  -</PRE>
  -<P>
  -When you watch the output of the <CODE>top</CODE> utility, don't confuse <STRONG>RSS</STRONG>
  -(or <STRONG>RES</STRONG>) column with <STRONG>SHARE</STRONG> column -- <STRONG>RES</STRONG> is a RESident memory, which is a size of pages currently swapped in.
  +A much wiser approach would be to spawn a sub-process, hand it the
  +information it needs to do the task, and have it detach (close x3 +
  +<CODE>setsid()</CODE>). This is wise only if the parent who spawns this process, immediately
  +continue, you do not wait for the sub-process to complete. This approach is
  +suitable for a situation when you want to trigger a long time taking
  +process through the web interface, like processing some data, sending email
  +to thousands of subscribed users and etc. Otherwise, you should convert the
  +code into a module, and use its functions or methods to call from CGI
  +script.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Checking_script_modification_tim">Checking script modification times</A></H1></CENTER>
  +Just making a <CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
  +should be loaded again for this external program to run.
  +
   <P>
  -Under <CODE>Apache::Registry</CODE> the requested CGI script is always being
  -<CODE>stat()</CODE>'ed to check whether it was modified. It adds a very little overhead, but
  -if you are into squeezing all the jouces from the server, you might want to
  -save this call. If you do -- take a look at
  -<A HREF="././modules.html#">Apache::RegistryBB</A> module.
  +Basically, you would do:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A></H1></CENTER>
  +<PRE>  $params=FreezeThaw::freeze(
  +        [all data to pass to the other process]
  +        );
  +  system(&quot;program.pl $params&quot;);
  +</PRE>
   <P>
  -<CODE>Apache::Leak</CODE> (derived from <CODE>Devel::Leak</CODE>) should help you with this task. Example:
  +and in <CODE>program.pl</CODE> :
   
   <P>
  -<PRE>  use Apache::Leak;
  -  
  -  my $global = &quot;FooAAA&quot;;
  -  
  -  leak_test {
  -    $$global = 1;
  -    ++$global;
  -  };
  +<PRE>  @params=FreezeThaw::thaw(shift @ARGV);
  +  # check that @params is ok
  +  close STDIN;
  +  close STDOUT;
  +  open STDERR, &quot;&gt;/dev/null&quot;;
  +  setsid(); # to detach
   </PRE>
   <P>
  -The argument to <CODE>leak_test()</CODE> is an anonymous sub, so you can just throw it around any code you suspect
  -might be leaking. Beware, it will run the code twice, because the first
  -time in, new <CODE>SV</CODE>s are created, but does not mean you are leaking, the second pass will give
  -better evidence. You do not need to be inside mod_perl to use it, from the
  -command line, the above script outputs:
  +At this point, <CODE>program.pl</CODE> is running in the ``background'' while the
  +<CODE>system()</CODE> returns and permits apache to get on with life.
   
   <P>
  -<PRE>  ENTER: 1482 SVs
  -  new c28b8 : new c2918 : 
  -  LEAVE: 1484 SVs
  -  ENTER: 1484 SVs
  -  new db690 : new db6a8 : 
  -  LEAVE: 1486 SVs
  -  !!! 2 SVs leaked !!!
  -</PRE>
  +This has obvious problems. Not the least of which is that <CODE>@params</CODE>
  +must not be bigger then whatever your architecture's limit is (could depend
  +on your shell).
  +
   <P>
  -Build a debuggable perl to see dumps of the <CODE>SV</CODE>s. The simple way to have both a normal perl and debuggable perl, is to
  -follow hints in the
  -<CODE>SUPPORT</CODE> doc for building <CODE>libperld.a</CODE>, when that is built copy the
  -<CODE>perl</CODE> from that directory to your perl bin directory, but name it
  -<CODE>dperl</CODE>.
  +Also, the communication is only one way.
   
   <P>
  -Leak explanation: <CODE>$$global = 1;</CODE> : new global variable created
  -<CODE>FooAAA</CODE> with value of <CODE>1</CODE>, will not be destructed until this module is destroyed.
  +However, you might want be trying to do the ``wrong thing''. If what you
  +want is to send information to the browser and then do some
  +post-processing, look into <CODE>PerlCleanupHandler</CODE>.
   
   <P>
  -<CODE>Apache::Leak</CODE> is not very user-friendly, have a look at
  -<CODE>B::LexInfo</CODE>. You'll see that what might appear to be a leak, is actually just a Perl
  -optimization. e.g. consider this code:
  +If you are interested in more deep level details, this is what actually
  +happens when you fork and make a system call, like
   
   <P>
  -<PRE>  sub foo {
  -    my $string = shift;
  -  }
  +<PRE>  system(&quot;echo Hi&quot;),CORE::exit(0) unless fork();
   </PRE>
   <P>
  -<PRE>  foo(&quot;a string&quot;);
  +which is might be more familiar in this form:
  +
  +<P>
  +<PRE>  if (fork){
  +    #do nothing
  +  } else {
  +    system(&quot;echo Hi&quot;);
  +    CORE::exit(0);
  +  }
   </PRE>
   <P>
  -<CODE>B::LexInfo</CODE> will show you that Perl does not release the value from $string, unless you
  -undef it. this is because Perl anticipates the memory will be needed for
  -another string, the next time the subroutine is entered. you'll see similar
  -for <CODE>@array</CODE> length, <CODE>%hash</CODE> keys, and scratch areas of the padlist for ops such as <CODE>join()</CODE>, `<CODE>.</CODE>', etc.
  +What happens is that <CODE>fork()</CODE> gives you 2 execution paths and
  +the child gets virtual memory sharing a copy of the program text (read
  +only) and sharing a copy of the data space copy-on-write (remember why you
  +pre-load modules in mod_perl?). In the above code a parent will immediately
  +continue with the code that comes up after the fork, while the forked
  +process will execute <CODE>system(&quot;echo Hi&quot;)</CODE> and then terminate itself.
   
   <P>
  -<CODE>Apache::Status</CODE> now includes a new StatusLexInfo option.
  +Notice that we have used <CODE>CORE::exit</CODE> and not <CODE>exit</CODE> which would be automatically overriden by <CODE>Apache::exit</CODE> if used in conjunction with
  +<CODE>Apache::Registry</CODE> and friends.
   
   <P>
  -Apache::Leak works better if you've built a libperld.a (see SUPPORT) and
  -given PERL_DEBUG=1 to mod_perl's Makefile.PL
  +The only work is setting up the page tables for the virtual memory and the
  +second process goes on its separate way.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Limiting_the_size_of_the_process">Limiting the size of the processes</A></H1></CENTER>
   <P>
  -<CODE>Apache::SizeLimit</CODE> allows you to kill off Apache httpd processes if they grow too large. see
  -perldoc <CODE>Apache::SizeLimit</CODE> for more details.
  +Next, Perl will find <CODE>/bin/echo</CODE> along the search path, and invoke it directly. Perl <CODE>system()</CODE>
  +is *not* <CODE>system(3)</CODE> [C-library]. Only when the command has shell meta-chars does Perl invoke a
  +real shell. That's a *very* nice optimization.
   
   <P>
  -By using this module, you should be able to discontinue using the Apache
  -configuration directive <CODE>MaxRequestsPerChild</CODE>, although for some folks, using both in combination does the job.
  +Only if you do:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A></H1></CENTER>
  +<PRE>  system &quot;sh -c 'echo foo'&quot;
  +</PRE>
   <P>
  -<CODE>Apache::Resource</CODE> uses the <CODE>BSD::Resource</CODE> module, which uses the C function <CODE>setrlimit()</CODE> to set limits on system resources such as memory and cpu usage.
  +OS actually parses your command with a shell so you <CODE>exec()</CODE> a
  +copy of
  +<CODE>/bin/sh</CODE>, but since one is almost certainly already running somewhere, the system
  +will notice that (via the disk inode reference) and replace your virtual
  +memory page table with one pointed at the already-loaded program code plus
  +your own data space. Then the shell parses the passed command.
   
   <P>
  -To configure use:
  +Since it is <CODE>echo</CODE>, it will execute it as a built-in in the latter example or a <CODE>/bin/echo</CODE> in the former and be done, but this is only an example. You aren't calling <CODE>system(&quot;echo Hi&quot;)</CODE> in your mod_perl scripts, right? Since most other real things (heavy
  +programs executed as a subprocess) would involve repeating the process to
  +load the specified command or script (it might involve some actual demand
  +paging from the program file if you execute new code).
   
   <P>
  -<PRE>  PerlModule Apache::Resource
  -    # set child memory limit in megabytes
  -    # (default is 64 Meg)
  -  PerlSetEnv PERL_RLIMIT_DATA 32:48
  -  
  -    # set child CPU limit in seconds
  -    # (default is 360 seconds)
  -  PerlSetEnv PERL_RLIMIT_CPU 120
  -  
  -  PerlChildInitHandler Apache::Resource
  -</PRE>
  +The only place you see real overhead from this scheme is when the parent
  +process is huge (unfortunately like mod_perl...) and the page table becomes
  +large as a side effect. The whole point of mod_perl is to avoid having to
  +<CODE>fork()</CODE> / <CODE>exec()</CODE> something on every hit, though.
  +Perl can do just about anything by itself. However, you probably won't get
  +in trouble until you hit about 30 forks/sec on a so-so pentium.
  +
   <P>
  -The following limit values are in megabytes: <CODE>DATA</CODE>, <CODE>RSS</CODE>,
  -<CODE>STACK</CODE>, <CODE>FSIZE</CODE>, <CODE>CORE</CODE>, <CODE>MEMLOCK</CODE>; all others are treated as their natural unit. Prepend <CODE>PERL_RLIMIT_</CODE> for each one you want to use. Refer to <CODE>setrlimit</CODE> man page on your OS for other possible resources.
  +Now let's get to the gory details of forking. Normally, every process has
  +its parent. Many processes are children of the <CODE>init</CODE> process, whose <CODE>PID</CODE> equals to <CODE>1</CODE>. When you fork a process you must <CODE>wait()</CODE> for it to finish. If
  +you don't wait for it becomes a zombie.
   
   <P>
  -If the value of the variable is of the form <CODE>S:H</CODE>, <CODE>S</CODE> is treated as the soft limit, and <CODE>H</CODE> is the hard limit. If it is just a single number, it is used for both soft
  -and hard limits.
  +Zombie, is a process that doesn't have a father. When the child quits, it
  +reports the termination to his parent. If no one <CODE>wait()s</CODE> to
  +collect the exit status of the child, it gets ``confused'' and becomes a
  +ghost process, that can be seen, but not killed. It will be killed only
  +when you stop the httpd! (generally <CODE>top()/ps()</CODE> utilities
  +display these processes with <CODE>&lt;defunc</CODE>&gt; tag, and you will see an increment of the zombies counter reported
  +when doing <CODE>top().)</CODE>
   
   <P>
  -To debug add:
  +So the proper fork is:
   
   <P>
  -<PRE>  &lt;Perl&gt;
  -    $Apache::Resource::Debug = 1;
  -    require Apache::Resource;
  -  &lt;/Perl&gt;
  -  PerlChildInitHandler Apache::Resource
  +<PRE>  print &quot;Content-type: text/plain\n\n&quot;;
  +  
  +  defined (my $kid = fork) or die &quot;Cannot fork: $!\n&quot;;
  +  if ($kid) {
  +    waitpid($kid,0);
  +    print &quot;Parent has finished\n&quot;;
  +  } else {
  +      # do something
  +      CORE::exit(0);
  +  }
   </PRE>
  -<P>
  -and look in the error_log to see what it's doing.
  -
   <P>
  -Refer to <CODE>perldoc Apache::Resource</CODE> and <CODE>man 2 setrlimit</CODE> for more info.
  +But in most cases the only reason you would want to fork is when you need
  +to spawn a process that would take a lot of time to complete. So if the
  +child that spawns this process has to wait for it to finish, you gained
  +nothing. You cannot neither wait for its completion, nor continue because
  +you will get yet another zombie process.
  +
  +<P>
  +The simplest solution is to ignore your dead children (this doesn't work
  +everywhere, however) (META: do you know where? tell me!!! It works with
  +linux!):
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Limiting_the_request_rate_speed_">Limiting the request rate speed (robots blocking)</A></H1></CENTER>
  +<PRE>  $SIG{CHLD} = IGNORE;
  +</PRE>
   <P>
  -A limitation of using pattern matching to identify robots is that it only
  -catches the robots that you know about, and only those that identify
  -themselves by name. A few devious robots masquerade as users by using user
  -agent strings that identify themselves as conventional browsers. To catch
  -such robots, you'll have to be more sophisticated.
  +When you set <CODE>CHLD</CODE> signal handler to <CODE>IGNORE</CODE>, all the processes will be collected by the <CODE>init</CODE> process and prevent from them to become zombies.
   
   <P>
  -<CODE>Apache::SpeedLimit</CODE> comes for you to help, see:
  +Note, that you cannot localize this setting with <CODE>local()</CODE>. If you do, it wouldn't take the desired effect. (META: anyone to explain
  +why? It doesn't work...)
   
   <P>
  -<A
  -HREF="http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients">http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients</A>
  +The other thing that you must do -- is to close all the pipes to the
  +connection socket that were opened by the parent process (a <CODE>STDIN</CODE>
  +and a <CODE>STDOUT</CODE>) and inherited by the child, so the parent will be able to complete the
  +request and free itself for serving other requests. You may need to close
  +and reopen a <CODE>STDERR</CODE> filehandler (It's opened to append to the error_log file as inhereted by
  +parent, so chances are that you want it to leave untouched).
   
  +<P>
  +So now the code would look like:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A></H1></CENTER>
  +<PRE>  print &quot;Content-type: text/plain\n\n&quot;;
  +  
  +  $SIG{CHLD} = IGNORE;
  +  
  +  defined (my $kid = fork) or die &quot;Cannot fork: $!\n&quot;;
  +  if ($kid) {
  +    waitpid($kid,0);
  +    print &quot;Parent has finished\n&quot;;
  +  } else {
  +      close STDIN;
  +      close STDOUT;
  +      close STDERR;
  +      # do something long lasting
  +      CORE::exit(0);
  +  }
  +</PRE>
   <P>
  -How much faster is mod_perl than mod_cgi (aka plain perl/CGI)? There are
  -many ways to benchmark the two. I'll present a few examples and numbers
  -below. Checkout the <CODE>benchmark</CODE> directory of mod_perl distribution for more examples.
  +Another more portable, but slightly more expensive solution is to use a
  +double fork approach.
   
   <P>
  -If you are going to write your own benchmarking utility -- use
  -<CODE>Benchmark</CODE> module for heavy scripts and <CODE>Time::HiRes</CODE> module for very fast scripts (faster than 1 sec) where you need better time
  -precision.
  -
  +<PRE>  print &quot;Content-type: text/plain\n\n&quot;;
  +  
  +  defined (my $kid = fork) or die &quot;Cannot fork: $!\n&quot;;
  +  if ($kid) {
  +    waitpid($kid,0);
  +  } else {
  +    defined (my $grandkid = fork) or die &quot;Kid cannot fork: $!\n&quot;;
  +    if ($grandkid) {
  +      CORE::exit(0);
  +  
  +    } else {
  +      # code here
  +      close STDIN;
  +      close STDOUT;
  +      close STDERR;
  +      # do something long lasting
  +      CORE::exit(0);
  +    }
  +  }
  +</PRE>
   <P>
  -There is no need to write a special benchmark though. If you want to
  -impress your boss or colleagues, just take some heavy CGI script you have
  -(e.g. a script that crunches some data and prints the results to STDOUT),
  -open 2 xterms and call the same script in mod_perl mode in one xterm and in
  -mod_cgi mode in the other. You can use <CODE>lwp-get</CODE>
  -from <CODE>LWP</CODE> package to emulate the web agent (browser). (<CODE>benchmark</CODE>
  -directory of mod_perl distribution includes such an example)
  +Grandkid becomes a <EM>"child of init"</EM> (parent process ID is 1).
   
   <P>
  -See also 2 tools for benchmarking:
  -<A HREF="././performance.html#Tuning_with_ab_ApacheBench">ApacheBench</A> and <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>
  +Note that the last two solutions do allow you to know the exit status of
  +the process, but in our case we don't want to.
   
  +<P>
  +You will probably want to open your own log file in the spawned process and
  +log some info so you know what have happened there. At least while
  +debugging your code.
   
  +<P>
  +Check also <CODE>Apache::SubProcess</CODE> for a better <CODE>system</CODE> and <CODE>exec</CODE>
  +implementations for mod_perl (use CPAN!). META: some docs regarding this
  +module?
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Developers_Talk">Developers Talk</A></H2></CENTER>
  +<CENTER><H1><A NAME="Memory_leakage">Memory leakage</A></H1></CENTER>
   <P>
  -Perrin Harkins writes on benchmarks or comparisons, official or unofficial:
  -
  -<BLOCKQUOTE>
  +Scripts under mod_perl can very easily leak memory! Global variables stay
  +around indefinitely, lexical variables (declared with <CODE>my()</CODE> are destroyed when they go out of scope, provided there are no references
  +to them from outside of that scope.
   
   <P>
  -I have used some of the platforms you mentioned and researched others. What
  -I can tell you for sure, is that no commercially available system offers
  -the depth, power, and ease of use that mod_perl has. Either they don't let
  -you access the web server internals, or they make you use less productive
  -languages than Perl, sometimes forcing you into restrictive and confusing
  -APIs and/or GUI development environments. None of them offer the level of
  -support available from simply posting a message to this list, at any price.
  +Perl doesn't return the memory it acquired from the kernel. It does reuse
  +it though!
   
   <P>
  -As for performance, beyond doing several important things (code-caching,
  -pre-forking/threading, and persistent database connections) there isn't
  -much these tools can do, and it's mostly in your hands as the developer to
  -see that the things which really take the time (like database queries) are
  -optimized.
  +<STRONG>First example</STRONG> demonstrates reading in a whole file:
   
   <P>
  -The downside of all this is that most manager types seem to be unable to
  -believe that web development software available for free could be better
  -than the stuff that cost $25,000 per CPU. This appears to be the major
  -reason most of the web tools companies are still in business. They send a
  -bunch of suits to give PowerPoint presentations and hand out glossy
  -literature to your boss, and you end up with an expensive disaster and an
  -approaching deadline.
  +<PRE>  open IN, $file or die $!;
  +  local $/ = undef; # will read the whole file in
  +  $content = &lt;IN&gt;;
  +  close IN;
  +</PRE>
  +<P>
  +If your file is 5Mb, the child who served that script will grow exactly by
  +that size. Now if you have 20 children and all of them will serve this CGI,
  +all of them will consume additional 20*5M = 100M of RAM! If that's the
  +case, try to use other approaches of processing the file, if possible of
  +course. Try to process a line at a time and print it back to the file. (If
  +you need to modify the file itself, use a temporary file. When finished,
  +overwrite the source file, make sure to provide a locking mechanism!)
   
   <P>
  -But I'm not bitter or anything...
  -
  -</BLOCKQUOTE>
  -
  -<P>
  -Jonathan Peterson adds:
  -
  -<BLOCKQUOTE>
  -
  -<P>
  -Most of the major solutions have something that they do better than the
  -others, and each of them has faults. Microsoft's ASP has a very nice
  -objects model, and has IMO the best data access object (better than DBI to
  -use - but less portable) It has the worst scripting language. PHP has many
  -of the advantages of Perl-based solutions, but is less complicated for
  -developers. Netscape's Livewire has a good object model too, and provides
  -good server-side Java integration - if you want to leverage Java skills,
  -it's good. Also, it has a compiled scripting language - which is great if
  -you aren't selling your clients the source code (and a pain otherwise).
  +<STRONG>Second example</STRONG> demonstrates copying variables between functions (passing variables by
  +value). Let's use the example above, assuming we have no choice but to read
  +the whole file before any data processing takes place. Now you have some
  +imagine <CODE>process()</CODE> subroutine that processes the data and returns it back. What happens if you
  +pass the
  +<CODE>$content</CODE> by value? You have just copied another 5M and the child has grown by
  +another 5M in size (watch your swap space!) now multiply it again by factor
  +of 20 you have 200M of wasted RAM, which will be apparently reused but it's
  +a waste! Whenever you think the variable can grow bigger than few Kb, pass
  +it by reference!
   
   <P>
  -mod_perl's advantage is that it is the most powerful. It offers the
  -greatest degree of control with one of the more powerful languages. It also
  -offers the greatest granularity. You can use an embedding module (eg eperl)
  -from one place, a session module (Session) from another, and your data
  -access module from yet another.
  +Once I wrote a script that passed a content of a little flat file DataBase
  +to a function that processed it by value -- it worked and it was processed
  +fast, but with a time the DataBase became bigger, so passing it by value
  +was an overkill -- I had to make a decision, whether to buy more memory or
  +to rewrite the code. It's obvious that adding more memory will be merely a
  +temporary solution. So it's better to plan ahead and pass the variables by
  +reference, if a variable you are going to pass might be bigger than you
  +think at the time of your coding process. There are a few approaches you
  +can use to pass and use variables passed by reference. For example:
   
   <P>
  -I think the <CODE>Apache::ASP</CODE> module looks very promising. It has very easy to use and adequately
  -powerful state maintenance, a good embedding system, and a sensible object
  -model (that emulates the Microsoft ASP one). It doesn't replicate MS's ADO
  -for data access, but
  -<CODE>DBI</CODE> is fine for that.
  -
  +<PRE>  my $content = qq{foobarfoobar};
  +  process(\$content);
  +  sub process{
  +    my $r_var = shift; 
  +    $$r_var =~ s/foo/bar/gs;
  +      # nothing returned - the variable $content outside has been
  +      # already modified
  +  }
  +  
  +  @{$var_lr} -- dereferences an array
  +  %{$var_hr} -- dereferences a hash
  +</PRE>
   <P>
  -I have always found that the developers available make the greatest impact
  -on the decision. If you have a team with no Perl experience, and a small or
  -medium task, using something like PHP, or Microsoft ASP, makes more sense
  -than driving your staff into the vertical learning curve they'll need to
  -use mod_perl.
  +For more info see <CODE>perldoc perlref</CODE>.
   
   <P>
  -For very large jobs, it may be worth finding the best technical solution,
  -and then recruiting the team with the necessary skills.
  -
  -</BLOCKQUOTE>
  +Another approach would be to directly use a <CODE>@_</CODE> array. Using directly the <CODE>@_</CODE> array serves the job of passing by reference!
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A></H2></CENTER>
  +<PRE>  process($content);
  +  sub process{
  +    $_[0] =~ s/foo/bar/gs;
  +      # nothing returned - the variable $content outside has been
  +      # already modified
  +  }
  +</PRE>
   <P>
  -Here are the numbers from Michael Parker's mod_perl presentation at Perl
  -Conference (Aug, 98) <A
  -HREF="http://www.realtime.net/~parkerm/perl/conf98/index.htm">http://www.realtime.net/~parkerm/perl/conf98/index.htm</A>
  -. The script is a standard hits counter, but it logs the counts into the
  -mysql relational DataBase:
  +From <CODE>perldoc perlsub</CODE>:
   
   <P>
  -<PRE>    Benchmark: timing 100 iterations of cgi, perl...  [rate 1:28]
  -    
  -    cgi: 56 secs ( 0.33 usr 0.28 sys = 0.61 cpu) 
  -    perl: 2 secs ( 0.31 usr 0.27 sys = 0.58 cpu) 
  -    
  -    Benchmark: timing 1000 iterations of cgi,perl...  [rate 1:21]
  -     
  -    cgi: 567 secs ( 3.27 usr 2.83 sys = 6.10 cpu) 
  -    perl: 26 secs ( 3.11 usr 2.53 sys = 5.64 cpu)      
  -    
  -    Benchmark: timing 10000 iterations of cgi, perl   [rate 1:21]
  -     
  -    cgi: 6494 secs (34.87 usr 26.68 sys = 61.55 cpu) 
  -    perl: 299 secs (32.51 usr 23.98 sys = 56.49 cpu) 
  +<PRE>      The array @_ is a local array, but its elements are aliases for
  +      the actual scalar parameters.  In particular, if an element
  +      $_[0] is updated, the corresponding argument is updated (or an
  +      error occurs if it is not possible to update)...
   </PRE>
   <P>
  -We don't know what server configurations was used for these tests, but I
  -guess the numbers speak for themselves.
  +Be careful when you write this kind of subroutines, since it can confuse a
  +potential user. It's not obvious that call like
  +<CODE>process($content);</CODE> modifies the passed variable -- programmers (which are the users of your
  +library in this case) are used to subs that either modify variables passed
  +by reference or return the processed variable (e.g. <CODE>$content=process($content);</CODE>).
   
   <P>
  -The source code of the script is available at <A
  -HREF="http://www.realtime.net/~parkerm/perl/conf98/sld006.htm">http://www.realtime.net/~parkerm/perl/conf98/sld006.htm</A>
  -.
  +<STRONG>Third example</STRONG> demonstrates a work with DataBases. If you do some DB processing, many
  +times you encounter the need to read lots of records into your program, and
  +then print them to the browser after they are formatted. (I don't even
  +mention the horrible case where programmers read in the whole DB and then
  +use perl to process it!!! Use a relational DB and let the SQL do the job,
  +so you get only the records you need!!!).
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A></H2></CENTER>
   <P>
  -As noted before, for very fast scripts you will have to use the
  -<CODE>Time::HiRes</CODE> module, its usage is similar to the <CODE>Benchmark</CODE>'s.
  +We will use <CODE>DBI</CODE> for this (assume that we are already connected to the DB) (refer to <CODE>perldoc DBI</CODE> for a complete manual of the <CODE>DBI</CODE>
  +module):
   
   <P>
  -<PRE>  use Time::HiRes qw(gettimeofday tv_interval);
  -  my $start_time = [ gettimeofday ];
  -  &amp;sub_that_takes_a_teeny_bit_of_time()
  -  my $end_time = [ gettimeofday ];
  -  my $elapsed = tv_interval($start_time,$end_time);
  -  print &quot;the sub took $elapsed secs.&quot;
  +<PRE>  $sth-&gt;execute;
  +  while(@row_ary  = $sth-&gt;fetchrow_array;) {
  +        &lt;do DB accumulation into some variable&gt;
  +  }
  +  &lt;print the output using the the data returned from the DB&gt;
   </PRE>
  -<P>
  -See also <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A></H2></CENTER>
  -<P>
  -At <A
  -HREF="http://perl.apache.org/dist/contrib/">http://perl.apache.org/dist/contrib/</A>
  -you will find
  -<CODE>Apache::Timeit</CODE> package which does <CODE>PerlHandler</CODE>'s Benchmarking.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A></H1></CENTER>
   <P>
  -It's very important to make a correct configuration of the
  -<CODE>MinSpareServers</CODE>, <CODE>MaxSpareServers</CODE>, <CODE>StartServers</CODE>,
  -<CODE>MaxClients</CODE>, and <CODE>MaxRequestsPerChild</CODE> parameters. There are no defaults, the values of these variable are very
  -important, as if too ``low'' you will under-use the system's capabilities,
  -and if too ``high'' chances that the server will bring the machine to its
  -knees.
  +In the example above the httpd_process will grow up by the size of the
  +variables that have been allocated for the records that matched the query.
  +(Again remember to multiply it by the number of the children your server
  +runs!).
   
   <P>
  -All the above parameters should be specified on the basis of the resources
  -you have. While with a plain apache server, there is no big deal if you run
  -too many servers (not too many of course) since the processes are of ~1Mb
  -and aren't eating a lot of your RAM. Generally the numbers are even smaller
  -if memory sharing is taking place. The situation is different with
  -mod_perl. I have seen mod_perl processes of 20Mb and more. Now if you have <CODE>MaxClients</CODE> set to 50: 50x20Mb = 1Gb - do you have 1Gb of RAM? Probably not. So how do
  -you tune these parameters? Generally by trying different combinations and
  -benchmarking the server. Again mod_perl processes can be of much smaller
  -size if sharing is in place.
  +A better approach is to not accumulate the records, but rather print them
  +as they are fetched from the DB. Moreover, we will use the
  +<CODE>bind_col()</CODE> and <CODE>$sth-&amp;gt;fetchrow_arrayref()</CODE> (aliased to
  +<CODE>$sth-&amp;gt;fetch()</CODE>) methods, to fetch the data in the fastest possible way. The example below
  +prints a HTML TABLE with matched data, the only memory that is being used
  +is a <CODE>@cols</CODE> array to hold temporary row values:
   
   <P>
  -Before you start this task you should be armed with a proper weapon. You
  -need a <STRONG>crashme</STRONG> utility, which will load your server with mod_perl scripts you possess. You
  -need it to have an ability to emulate a multiuser environment and to
  -emulate multiple clients behavior which will call the mod_perl scripts at
  -your server simultaneously. While there are commercial solutions, you can
  -get away with free ones which do the same job. You can use an
  -<A HREF="././performance.html#Tuning_with_ab_ApacheBench">ApacheBench</A>  <STRONG><CODE>ab</CODE></STRONG> utility that comes with apache distribution, a <A HREF="././performance.html#Tuning_with_crashme_script">crashme script</A> which uses
  -<CODE>LWP::Parallel::UserAgent</CODE> or <CODE>httperf</CODE> (see <A HREF="././download.html#">Download page</A>).
  -
  +<PRE>  my @select_fields = qw(a b c);
  +      # create a list of cols values
  +  my @cols = ();
  +  @cols[0..$#select_fields] = ();
  +  $sth = $dbh-&gt;prepare($do_sql);
  +  $sth-&gt;execute;
  +    # Bind perl variables to columns.
  +  $sth-&gt;bind_columns(undef,\(@cols));
  +  print &quot;&lt;TABLE&gt;&quot;;
  +  while($sth-&gt;fetch) {
  +     print &quot;&lt;TR&gt;&quot;,
  +           map(&quot;&lt;TD&gt;$_&lt;/TD&gt;&quot;, @cols),
  +           &quot;&lt;/TR&gt;&quot;;
  +  }
  +  print &quot;&lt;/TABLE&gt;&quot;;
  +</PRE>
   <P>
  -Another important issue is to make sure to run testing client (load
  -generator) on a system that is more powerful than the system being tested.
  -After all we are trying to simulate the Internet users, where many users
  -are trying to reach your service at once -- since a number of concurrent
  -users can be quite large, your testing machine much be very powerful and
  -capable to generate a heavy load. Of course you should not run the clients
  -and the server on the same machine. If you do -- your testing results would
  -be incorrect, since clients will eat a CPU and a memory that have to be
  -dedicated to the server, and vice versa.
  +Note: the above method doesn't allow you to know how many records have been
  +matched. The workaround is to run an identical query before the code above
  +where you use <CODE>SELECT count(*) ...</CODE> instead of <CODE>'SELECT *
  +...</CODE> to get the number of matched records. It should be much faster, since you
  +can remove any <STRONG>SORTBY</STRONG> and alike attributes.
   
   <P>
  -See also 2 tools for benchmarking:
  -<A HREF="././performance.html#Tuning_with_ab_ApacheBench">ApacheBench</A> and <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>
  -
  -
  +For those who think that <STRONG>$sth-&gt;rows</STRONG> will do the job, here is the quote from the <CODE>DBI</CODE> manpage:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench</A></H2></CENTER>
  +<PRE>  rows();
  +</PRE>
   <P>
  -<STRONG>ab</STRONG> is a tool for benchmarking your Apache HTTP server. It is designed to give
  -you an impression on how much performance your current Apache installation
  -can give. In particular, it shows you how many requests per secs your
  -Apache server is capable of serving. The
  -<STRONG>ab</STRONG> tool comes bundled with apache source distribution (and it's free :).
  -
  +<PRE>  $rv = $sth-&gt;rows;
  +</PRE>
   <P>
  -Let's try it. We will simulate 10 users concurrently requesting a very
  -light script at <CODE>www.nowhere.com:81/test/test.pl</CODE>. Each ``user'' makes 10 requests.
  -
  +<PRE>  Returns the number of rows affected by the last database altering
  +  command, or -1 if not known or not available.  Generally you can
  +  only rely on a row count after a do or non-select execute (for some
  +  specific operations like update and delete) or after fetching all
  +  the rows of a select statement.
  +</PRE>
   <P>
  -<PRE>  % ./ab -n 100 -c 10 www.nowhere.com:81/test/test.pl
  +<PRE>  For select statements it is generally not possible to know how many
  +  rows will be returned except by fetching them all.  Some drivers
  +  will return the number of rows the application has fetched so far
  +  but others may return -1 until all rows have been fetched. So use of
  +  the rows method with select statements is not recommended.
   </PRE>
   <P>
  -The results are:
  +As a bonus, I wanted to write a single sub that flexibly processes any
  +query, accepting: conditions, call-back closure sub, select fields and
  +restrictions. 
   
   <P>
  -<PRE>  Concurrency Level:      10
  -  Time taken for tests:   0.715 seconds
  -  Complete requests:      100
  -  Failed requests:        0
  -  Non-2xx responses:      100
  -  Total transferred:      60700 bytes
  -  HTML transferred:       31900 bytes
  -  Requests per second:    139.86
  -  Transfer rate:          84.90 kb/s received
  +<PRE>  # Usage:
  +  # $o-&gt;dump(\%conditions,\&amp;callback_closure,\@select_fields,@restrictions);
  +  #
  +  sub dump{
  +    my $self = shift;
  +    my %param = %{+shift}; # dereference hash
  +    my $rsub = shift;
  +    my @select_fields = @{+shift}; # dereference list
  +    my @restrict = shift || '';
     
  -  Connection Times (ms)
  -                min   avg   max
  -  Connect:        0     0     3
  -  Processing:    13    67    71
  -  Total:         13    67    74
  +      # create a list of cols values
  +    my @cols = ();
  +    @cols[0..$#select_fields] = ();
  +  
  +    my $do_sql = '';
  +    my @where = ();
  +  
  +      # make a @where list 
  +    map { push @where, &quot;$_=\'$param{$_}\'&quot; if $param{$_};} keys %param;
  +  
  +      # prepare the sql statement
  +    $do_sql = &quot;SELECT &quot;;
  +    $do_sql .= join(&quot; &quot;, @restrict) if @restrict;# append the restriction list
  +    $do_sql .= &quot; &quot; .join(&quot;,&quot;, @select_fields) ;      # append the select list 
  +    $do_sql .= &quot; FROM $DBConfig{TABLE} &quot;;         # from table
  +  
  +      # we will not add the WHERE clause if @where is empty
  +    $do_sql .= &quot; WHERE &quot; . join &quot; AND &quot;, @where if @where;
  +  
  +    print &quot;SQL: $do_sql \n&quot; if $debug;
  +  
  +    $dbh-&gt;{RaiseError} = 1;     # do this, or check every call for errors
  +    $sth = $dbh-&gt;prepare($do_sql);
  +    $sth-&gt;execute;
  +      # Bind perl variables to columns.
  +    $sth-&gt;bind_columns(undef,\(@cols));
  +    while($sth-&gt;fetch) {
  +      &amp;$rsub(@cols);
  +    }
  +      # print the tail or &quot;no records found&quot; message
  +      # according to the previous calls
  +    &amp;$rsub();
  +  
  +  } # end of sub dump
   </PRE>
   <P>
  -The only numbers we really care about are:
  +Now a callback closure sub can do lots of things. We need a closure to know
  +what stage are we in: header, body or tail. For example, we want a callback
  +closure for formatting the rows to print: 
   
   <P>
  -<PRE>  Complete requests:      100
  -  Failed requests:        0
  -  Requests per second:    139.86
  +<PRE>  my $rsub = eval {
  +      # make a copy of @fields list, since it might go
  +      # out of scope when this closure will be called
  +    my @fields = @fields; 
  +    my @query_fields = qw(user dir tool act); # no date field!!!
  +    my $header = 0;
  +    my $tail   = 0;
  +    my $counter = 0;
  +    my %cols = (); # columns name=&gt; value hash
  +  
  +    # Closure with the following behavior:
  +    # 1. Header's code will be executed on the first call only and
  +    #    if @_ was set
  +    # 2. Row's printing code will be executed on every call with @_ set
  +    # 3. Tail's code will be executed only if Header's code was
  +    #    printed and @_ isn't set
  +    # 4. &quot;No record found&quot; code will be executed if Header's code
  +    #    wasn't executed
  +  
  +    sub {
  +          # Header
  +        if (@_ and !$header){
  +          print &quot;&lt;TABLE&gt;\n&quot;;
  +          print $q-&gt;Tr(map{ $q-&gt;td($_) } @fields );
  +          $header = 1; 
  +        }
  +        
  +          # Body
  +        if (@_) {
  +          print $q-&gt;Tr(map{$q-&gt;td($_)} @_ );
  +          $counter++;
  +          return; 
  +        }
  +        
  +          # Tail, will be printed only at the end
  +        if ($header and !($tail or @_)){
  +          print &quot;&lt;/TABLE&gt;\n $counter records found&quot;;
  +          $tail = 1;
  +          return;
  +        }
  +        
  +          # No record found
  +        unless ($header){
  +          print $q-&gt;p($q-&gt;center($q-&gt;b(&quot;No record was found!\n&quot;)));
  +        }
  +  
  +      }  #  end of sub {}
  +  };  #  end of my $rsub = eval {
   </PRE>
   <P>
  -Let's raise the load of requests to 100 x 10 (10 users, each makes 100
  -requests)
  +You might also want to check <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
  +and <A HREF="././performance.html#Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A>.
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 10 www.nowhere.com:81/perl/access/access.cgi
  -  Concurrency Level:      10
  -  Complete requests:      1000
  -  Failed requests:        0
  -  Requests per second:    139.76
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="_DTWO_POT_OPTIMIZE_and_DPACK_MA">-DTWO_POT_OPTIMIZE and -DPACK_MALLOC Perl Options</A></H1></CENTER>
   <P>
  -As expected nothing changes -- we have the same 10 concurrent users. Now
  -let's raise the number of concurrent users to 50:
  +Newer Perl versions also have build time options to reduce runtime memory
  +consumption. These options might shrink down the size of your httpd by
  +about ~150k (quite big number if you remember to multiply it by the number
  +of chidren you use.)
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
  -  Complete requests:      1000
  -  Failed requests:        0
  -  Requests per second:    133.01
  -</PRE>
  +<CODE>-DTWO_POT_OPTIMIZE</CODE> macro improves allocations of data with size close to a power of two; but
  +this works for big allocations (starting with 16K by default). Such
  +allocations are typical for big hashes and special-purpose scripts,
  +especially image processing.
  +
   <P>
  -We see that the server is capable of serving 50 concurrent users at an
  -amazing 133 req/sec! Let's find the upper boundary. Using <CODE>-n 10000
  --c 1000</CODE> failed to get results (Broken Pipe?). Using <CODE>-n 10000 -c
  -500</CODE> derived 94.82 req/sec. The server's performance went down with the high
  -load.
  +Perl memory allocation is by bucket with sizes close to powers of two.
  +Because of these malloc overhead may be big, especially for data of size
  +exactly a power of two. If <CODE>PACK_MALLOC</CODE> is defined, perl uses a slightly different algorithm for small allocations
  +(up to 64 bytes long), which makes it possible to have overhead down to 1
  +byte for allocations which are powers of two (and appear quite often). 
   
   <P>
  -The above tests were performed with the following configuration:
  +Expected memory savings (with 8-byte alignment in <CODE>alignbytes</CODE>) is about 20% for typical Perl usage. Expected slowdown due to additional
  +malloc overhead is in fractions of a percent (hard to measure, because of
  +the effect of saved memory on speed).
   
   <P>
  -<PRE>  MinSpareServers 8
  -  MaxSpareServers 6
  -  StartServers 10
  -  MaxClients 50
  -  MaxRequestsPerChild 1500
  -</PRE>
  +You will find these and other memory improvement details in
  +<CODE>perl5004delta.pod</CODE>.
  +
   <P>
  -Now let's kill a child after a single request, we will use the following
  -configuration:
  +Important: both options are On by default in perl versions 5.005 and
  +higher.
   
   <P>
  -<PRE>  MinSpareServers 8
  -  MaxSpareServers 6
  -  StartServers 10
  -  MaxClients 100
  -  MaxRequestsPerChild 1
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Checking_script_modification_tim">Checking script modification times</A></H1></CENTER>
   <P>
  -Simulate 50 users each generating a total of 20 requests:
  +Under <CODE>Apache::Registry</CODE> the requested CGI script is always being
  +<CODE>stat()</CODE>'ed to check whether it was modified. It adds a very little overhead, but
  +if you are into squeezing all the jouces from the server, you might want to
  +save this call. If you do -- take a look at
  +<A HREF="././modules.html#">Apache::RegistryBB</A> module.
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Cached_stat_calls">Cached stat() calls</A></H1></CENTER>
   <P>
  -The benchmark timed out with the above configuration.... I watched the
  -output of <STRONG><CODE>ps</CODE></STRONG> as I ran it, the parent process just wasn't capable of respawning the
  -killed children at that rate...When I raised the
  -<CODE>MaxRequestsPerChild</CODE> to 10 I've got 8.34 req/sec - very bad (18 times slower!) (You can't
  -benchmark the importance of the
  -<CODE>MinSpareServers</CODE>, <CODE>MaxSpareServers</CODE> and <CODE>StartServers</CODE> with this kind of test).
  +When you do a <CODE>stat()</CODE> or its variations (<CODE>-M</CODE> - modification time,
  +<CODE>-A</CODE> last access time, <CODE>-C</CODE> inode-change time, and other), the information is being cached, so if you
  +need to make an additional check for the same file, save the overhead of
  +this check and use a
  +<CODE>_</CODE> variable instead. For example when testing for existance and read
  +permissions you might use:
   
   <P>
  -Now let's try to return <CODE>MaxRequestsPerChild</CODE> to 1500, but to lower the
  -<CODE>MaxClients</CODE> to 10 and run the same test:
  +<PRE>  my $filename = &quot;./test&quot;;
  +    # two stat() calls
  +  print &quot;OK\n&quot; if -e $filename and -r $filename; 
  +  my $mod_time = (-M $filename) * 24 * 60 * 60;
  +  print &quot;$filename was modified $mod_time seconds ago\n&quot;;
  +</PRE>
  +<P>
  +or the more efficient (two <CODE>stat()</CODE> syscalls saved)!:
   
   <P>
  -<PRE>  MinSpareServers 8
  -  MaxSpareServers 6
  -  StartServers 10
  -  MaxClients 10
  -  MaxRequestsPerChild 1500
  +<PRE>  my $filename = &quot;./test&quot;;
  +    # two stat() calls
  +  print &quot;OK\n&quot; if -e $filename and -r _;
  +  my $mod_time = (-M _) * 24 * 60 * 60;
  +  print &quot;$filename was modified $mod_time seconds ago\n&quot;;
   </PRE>
   <P>
  -I've got 27.12 req/sec, which is better but still 4-5 times slower (133
  -with <CODE>MaxClients</CODE> of 50)
  +Remember that with mod_perl you might get negative times when you use
  +<CODE>-M</CODE> and alike file tests. <CODE>-M</CODE> tests the difference in time between file modification file and the start
  +of the script that performs this check. Because <CODE>^T</CODE> variable is not being reset on each script invocation, and equal to the
  +time the process has been forked at, you might want to perform:
   
   <P>
  -<STRONG>Summary:</STRONG> I have tested a few combinations of server configuration variables (<CODE>MinSpareServers</CODE>  <CODE>MaxSpareServers</CODE>  <CODE>StartServers</CODE>
  -
  -<CODE>MaxClients</CODE>  <CODE>MaxRequestsPerChild</CODE>). And the results we have received are as follows:
  +<PRE>  $^T = time();
  +</PRE>
  +<P>
  +at the beginning of your scripts to get the regular perl script behaviour
  +of file tests
   
   <P>
  -<CODE>MinSpareServers</CODE>, <CODE>MaxSpareServers</CODE> and <CODE>StartServers</CODE> are only important for user response times (sometimes user will have to
  -wait a bit).
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Limiting_the_size_of_the_process">Limiting the size of the processes</A></H1></CENTER>
  +<P>
  +<CODE>Apache::SizeLimit</CODE> allows you to kill off Apache httpd processes if they grow too large. see
  +perldoc <CODE>Apache::SizeLimit</CODE> for more details.
   
   <P>
  -The important parameters are <CODE>MaxClients</CODE> and
  -<CODE>MaxRequestsPerChild</CODE>. <CODE>MaxClients</CODE> should be not to big so it will not abuse your machine's memory resources
  -and not too small, when users will be forced to wait for the children to
  -become free to come serve them. <CODE>MaxRequestsPerChild</CODE> should be as big as possible, to take the full benefit of mod_perl, but
  -watch your server at the beginning to make sure your scripts are not
  -leaking memory, thereby causing your server (and your service) to die very
  -fast.
  +By using this module, you should be able to discontinue using the Apache
  +configuration directive <CODE>MaxRequestsPerChild</CODE>, although for some folks, using both in combination does the job.
   
   <P>
  -Also it is important to understand that we didn't test the response times
  -in the tests above, but the ability of the server to respond under a heavy
  -load of requests. If the script that was used to test was heavier, the
  -numbers would be different but the conclusions are very similar.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A></H1></CENTER>
  +<P>
  +<CODE>Apache::Resource</CODE> uses the <CODE>BSD::Resource</CODE> module, which uses the C function <CODE>setrlimit()</CODE> to set limits on system resources such as memory and cpu usage.
   
   <P>
  -The benchmarks were run with:
  +To configure use:
   
   <P>
  -<PRE>  HW: RS6000, 1Gb RAM
  -  SW: AIX 4.1.5 . mod_perl 1.16, apache 1.3.3
  -  Machine running only mysql, httpd docs and mod_perl servers.
  -  Machine was _completely_ unloaded during the benchmarking.
  +<PRE>  PerlModule Apache::Resource
  +    # set child memory limit in megabytes
  +    # (default is 64 Meg)
  +  PerlSetEnv PERL_RLIMIT_DATA 32:48
  +  
  +    # set child CPU limit in seconds
  +    # (default is 360 seconds)
  +  PerlSetEnv PERL_RLIMIT_CPU 120
  +  
  +  PerlChildInitHandler Apache::Resource
   </PRE>
   <P>
  -After each server restart when I did changes to the server's
  -configurations, I made sure the scripts were preloaded by fetching a script
  -at least once by every child.
  +The following limit values are in megabytes: <CODE>DATA</CODE>, <CODE>RSS</CODE>,
  +<CODE>STACK</CODE>, <CODE>FSIZE</CODE>, <CODE>CORE</CODE>, <CODE>MEMLOCK</CODE>; all others are treated as their natural unit. Prepend <CODE>PERL_RLIMIT_</CODE> for each one you want to use. Refer to <CODE>setrlimit</CODE> man page on your OS for other possible resources.
   
   <P>
  -It is important to notice that none of requests timed out, even if was kept
  -in server's queue for more than 1 minute! (That is the way <STRONG>ab</STRONG>
  -works, which is OK for the testing purposes but will be unacceptable in the
  -real world - users will not wait for more than 5-10 secs for a request to
  -complete, and the client (browser) will timeout in a few minutes.)
  +If the value of the variable is of the form <CODE>S:H</CODE>, <CODE>S</CODE> is treated as the soft limit, and <CODE>H</CODE> is the hard limit. If it is just a single number, it is used for both soft
  +and hard limits.
   
   <P>
  -Now let's take a look at some real code whose execution time is more than a
  -few millisecs. We will do real testing and collect the data in tables for
  -easier viewing.
  -
  -<P>
  -I will use the following abbreviations:
  +To debug add:
   
   <P>
  -<PRE>  NR    = Total Number of Request
  -  NC    = Concurrency
  -  MC    = MaxClients
  -  MRPC  = MaxRequestsPerChild
  -  RPS   = Requests per second
  +<PRE>  &lt;Perl&gt;
  +    $Apache::Resource::Debug = 1;
  +    require Apache::Resource;
  +  &lt;/Perl&gt;
  +  PerlChildInitHandler Apache::Resource
   </PRE>
   <P>
  -Running a mod_perl script with lots of mysql queries (the script under test
  -is mysqld bounded)
  -(http://www.nowhere.com:81/perl/access/access.cgi?do_sub=query_form), with
  -configuration:
  +and look in the error_log to see what it's doing.
   
  -<P>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       16
  -  StartServers          10
  -  MaxClients            50
  -  MaxRequestsPerChild 5000
  -</PRE>
   <P>
  -gives us:
  +Refer to <CODE>perldoc Apache::Resource</CODE> and <CODE>man 2 setrlimit</CODE> for more info.
   
   <P>
  -<PRE>     NR   NC    RPS     comment
  -  ------------------------------------------------
  -     10   10    3.33    # not a reliable statistics
  -    100   10    3.94    
  -   1000   10    4.62    
  -   1000   50    4.09    
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Limiting_the_request_rate_speed_">Limiting the request rate speed (robots blocking)</A></H1></CENTER>
   <P>
  -<STRONG>Conclusions:</STRONG> Here I wanted to show that when the application is slow -- not due to perl
  -loading, code compilation and execution, but bounded to some external
  -operation like mysqld querying which made the bottleneck -- it almost does
  -not matter what load we place on the server. The RPS (Requests per second)
  -is almost the same (given that all the requests have been served, you have
  -an ability to queue the clients, but be aware that something that goes to
  -queue means a waiting client and a client (browser) that might time out!)
  +A limitation of using pattern matching to identify robots is that it only
  +catches the robots that you know about, and only those that identify
  +themselves by name. A few devious robots masquerade as users by using user
  +agent strings that identify themselves as conventional browsers. To catch
  +such robots, you'll have to be more sophisticated.
   
   <P>
  -Now we will benchmark the same script without using the mysql (perl only
  -bounded code) (http://www.nowhere.com:81/perl/access/access.cgi), it's the
  -same script that just returns a HTML form, without making any SQL queries.
  +<CODE>Apache::SpeedLimit</CODE> comes for you to help, see:
   
   <P>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       16
  -  StartServers          10
  -  MaxClients            50
  -  MaxRequestsPerChild 5000
  -</PRE>
  +<A
  +HREF="http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients">http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients</A>
  +
  +
   <P>
  -<PRE>     NR   NC      RPS   comment
  -  ------------------------------------------------
  -     10   10    26.95   # not a reliable statistics
  -    100   10    30.88   
  -   1000   10    29.31
  -   1000   50    28.01
  -   1000  100    29.74
  -  10000  200    24.92
  - 100000  400    24.95
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A></H1></CENTER>
   <P>
  -<STRONG>Conclusions:</STRONG> This time the script we executed was pure perl (not bounded to I/O or
  -mysql), so we see that the server serves the requests much faster. You can
  -see the <CODE>RequestPerSecond</CODE> (RPS) is almost the same for any load, but goes lower when the number of
  -concurrent clients goes beyond the <CODE>MaxClients</CODE>. With 25 RPS, the client supplying a load of 400 concurrent clients will
  -be served in 16 secs. But to get more realistic and assume the max
  -concurrency of 100, with 30 RPS, the client will be served in 3.5 secs,
  -which is pretty good for a highly loaded server.
  +How much faster is mod_perl than mod_cgi (aka plain perl/CGI)? There are
  +many ways to benchmark the two. I'll present a few examples and numbers
  +below. Checkout the <CODE>benchmark</CODE> directory of mod_perl distribution for more examples.
   
   <P>
  -Now we will use the server for its full capacity, by keeping all
  -<CODE>MaxClients</CODE> alive all the time and having a big
  -<CODE>MaxRequestsPerChild</CODE>, so no server will be killed during the benchmarking.
  +If you are going to write your own benchmarking utility -- use
  +<CODE>Benchmark</CODE> module for heavy scripts and <CODE>Time::HiRes</CODE> module for very fast scripts (faster than 1 sec) where you need better time
  +precision.
   
  -<P>
  -<PRE>  MinSpareServers       50
  -  MaxSpareServers       50
  -  StartServers          50
  -  MaxClients            50
  -  MaxRequestsPerChild 5000
  -  
  -     NR   NC      RPS   comment
  -  ------------------------------------------------
  -    100   10    32.05
  -   1000   10    33.14
  -   1000   50    33.17
  -   1000  100    31.72
  -  10000  200    31.60
  -</PRE>
   <P>
  -Conclusion: In this scenario there is no overhead involving the parent
  -server loading new children, all the servers are available, and the only
  -bottleneck is contention for the CPU.
  +There is no need to write a special benchmark though. If you want to
  +impress your boss or colleagues, just take some heavy CGI script you have
  +(e.g. a script that crunches some data and prints the results to STDOUT),
  +open 2 xterms and call the same script in mod_perl mode in one xterm and in
  +mod_cgi mode in the other. You can use <CODE>lwp-get</CODE>
  +from <CODE>LWP</CODE> package to emulate the web agent (browser). (<CODE>benchmark</CODE>
  +directory of mod_perl distribution includes such an example)
   
   <P>
  -Now we will try to change the <CODE>MaxClients</CODE> and to watch the results: Let's reduce MC to 10.
  +See also 2 tools for benchmarking:
  +<A HREF="././performance.html#Tuning_with_ab_ApacheBench">ApacheBench</A> and <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>
   
  +
  +
   <P>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       10
  -  StartServers          10
  -  MaxClients            10
  -  MaxRequestsPerChild 5000
  -  
  -     NR   NC      RPS   comment
  -  ------------------------------------------------
  -     10   10    23.87   # not a reliable statistics
  -    100   10    32.64 
  -   1000   10    32.82
  -   1000   50    30.43
  -   1000  100    25.68
  -   1000  500    26.95
  -   2000  500    32.53
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Developers_Talk">Developers Talk</A></H2></CENTER>
   <P>
  -<STRONG>Conclusions:</STRONG> A very little difference! Almost no change! 10 servers were able to serve
  -almost with the same throughput as 50 servers. Why? My guess it's because
  -of CPU throttling. It seems that 10 servers were serving requests 5 times
  -faster than when in the test above we worked with 50 servers. In the case
  -above each child received its CPU time slice 5 times less frequently. So
  -having a big value for
  -<CODE>MaxClients</CODE>, doesn't mean that the performance will be better. You have just seen the
  -numbers!
  +Perrin Harkins writes on benchmarks or comparisons, official or unofficial:
  +
  +<BLOCKQUOTE>
   
   <P>
  -Now we will start to drastically reduce the <CODE>MaxRequestsPerChild</CODE>:
  +I have used some of the platforms you mentioned and researched others. What
  +I can tell you for sure, is that no commercially available system offers
  +the depth, power, and ease of use that mod_perl has. Either they don't let
  +you access the web server internals, or they make you use less productive
  +languages than Perl, sometimes forcing you into restrictive and confusing
  +APIs and/or GUI development environments. None of them offer the level of
  +support available from simply posting a message to this list, at any price.
   
   <P>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       16
  -  StartServers          10
  -  MaxClients            50
  -  
  -     NR   NC    MRPC     RPS    comment
  -  ------------------------------------------------
  -    100   10      10    5.77 
  -    100   10       5    3.32
  -   1000   50      20    8.92
  -   1000   50      10    5.47
  -   1000   50       5    2.83
  -   1000  100      10    6.51
  -</PRE>
  +As for performance, beyond doing several important things (code-caching,
  +pre-forking/threading, and persistent database connections) there isn't
  +much these tools can do, and it's mostly in your hands as the developer to
  +see that the things which really take the time (like database queries) are
  +optimized.
  +
   <P>
  -<STRONG>Conclusions:</STRONG> When we drastically reduce the <CODE>MaxRequestsPerChild</CODE>, the performance starts to become closer to the plain mod_cgi. Just for
  -comparison with mod_cgi, here are the numbers of this run with mod_cgi:
  +The downside of all this is that most manager types seem to be unable to
  +believe that web development software available for free could be better
  +than the stuff that cost $25,000 per CPU. This appears to be the major
  +reason most of the web tools companies are still in business. They send a
  +bunch of suits to give PowerPoint presentations and hand out glossy
  +literature to your boss, and you end up with an expensive disaster and an
  +approaching deadline.
   
   <P>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       16
  -  StartServers          10
  -  MaxClients            50
  -  
  -     NR   NC    RPS     comment
  -  ------------------------------------------------
  -    100   10    1.12
  -   1000   50    1.14
  -   1000  100    1.13
  -</PRE>
  +But I'm not bitter or anything...
  +
  +</BLOCKQUOTE>
  +
   <P>
  -<STRONG>Conclusion</STRONG>: mod_cgi is much slower :) in test NReq/NClients 100/10 the RPS in mod_cgi
  -was of 1.12 and in mod_perl of 32, which is 30 times faster!!! In the first
  -test each child waited about 100 secs to be served. In the second and third
  -1000 secs!
  +Jonathan Peterson adds:
   
  +<BLOCKQUOTE>
  +
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Tuning_with_crashme_script">Tuning with crashme script</A></H2></CENTER>
  +Most of the major solutions have something that they do better than the
  +others, and each of them has faults. Microsoft's ASP has a very nice
  +objects model, and has IMO the best data access object (better than DBI to
  +use - but less portable) It has the worst scripting language. PHP has many
  +of the advantages of Perl-based solutions, but is less complicated for
  +developers. Netscape's Livewire has a good object model too, and provides
  +good server-side Java integration - if you want to leverage Java skills,
  +it's good. Also, it has a compiled scripting language - which is great if
  +you aren't selling your clients the source code (and a pain otherwise).
  +
   <P>
  -This is another crashme suite originally written by Michael Schilli and
  -located at <A
  -HREF="http://www.linux-magazin.de/ausgabe.1998.08/Pounder/pounder.html">http://www.linux-magazin.de/ausgabe.1998.08/Pounder/pounder.html</A>
  -. I did a few modifications (mostly adding <CODE>my()</CODE> operands). I
  -also allowed it to accept more than one url to test, since sometimes you
  -want to test an overall and not just one script.
  +mod_perl's advantage is that it is the most powerful. It offers the
  +greatest degree of control with one of the more powerful languages. It also
  +offers the greatest granularity. You can use an embedding module (eg eperl)
  +from one place, a session module (Session) from another, and your data
  +access module from yet another.
   
   <P>
  -The tool provides the same results as <STRONG>ab</STRONG> above but it also allows you to set the timeout value, so requests will
  -fail if not served within the time out period. You also get <STRONG>Latency</STRONG> (secs/Request) and
  -<STRONG>Throughput</STRONG> (Requests/sec) numbers. It can give you a better picture and make a
  -complete simulation of your favorite Netscape browser :).
  +I think the <CODE>Apache::ASP</CODE> module looks very promising. It has very easy to use and adequately
  +powerful state maintenance, a good embedding system, and a sensible object
  +model (that emulates the Microsoft ASP one). It doesn't replicate MS's ADO
  +for data access, but
  +<CODE>DBI</CODE> is fine for that.
   
   <P>
  -I have noticed while running these 2 benchmarking suites - <STRONG>ab</STRONG> gave me results 2.5-3.0 times better. Both suites run on the same machine
  -with the same load with the same parameters. But the implementations are
  -different.
  +I have always found that the developers available make the greatest impact
  +on the decision. If you have a team with no Perl experience, and a small or
  +medium task, using something like PHP, or Microsoft ASP, makes more sense
  +than driving your staff into the vertical learning curve they'll need to
  +use mod_perl.
   
   <P>
  -Sample output:
  +For very large jobs, it may be worth finding the best technical solution,
  +and then recruiting the team with the necessary skills.
  +
  +</BLOCKQUOTE>
   
   <P>
  -<PRE>  URL(s):          <A HREF="http://www.nowhere.com:81/perl/access/access.cgi">http://www.nowhere.com:81/perl/access/access.cgi</A>
  -  Total Requests:  100
  -  Parallel Agents: 10
  -  Succeeded:       100 (100.00%)
  -  Errors:          NONE
  -  Total Time:      9.39 secs
  -  Throughput:      10.65 Requests/sec
  -  Latency:         0.85 secs/Request
  -</PRE>
  -<P>
  -And the code:
  -
  -<P>
  -<PRE>  #!/usr/apps/bin/perl -w
  -  
  -  use LWP::Parallel::UserAgent;
  -  use Time::HiRes qw(gettimeofday tv_interval);
  -  use strict;
  -  
  -  ###
  -  # Configuration
  -  ###
  -  
  -  my $nof_parallel_connections = 10; 
  -  my $nof_requests_total = 100; 
  -  my $timeout = 10;
  -  my @urls = (
  -            '<A HREF="http://www.nowhere.com:81/perl/faq_manager/faq_manager.pl">http://www.nowhere.com:81/perl/faq_manager/faq_manager.pl</A>',
  -            '<A HREF="http://www.nowhere.com:81/perl/access/access.cgi">http://www.nowhere.com:81/perl/access/access.cgi</A>',
  -           );
  -  
  -  
  -  ##################################################
  -  # Derived Class for latency timing
  -  ##################################################
  -  
  -  package MyParallelAgent;
  -  @MyParallelAgent::ISA = qw(LWP::Parallel::UserAgent);
  -  use strict;
  -  
  -  ###
  -  # Is called when connection is opened
  -  ###
  -  sub on_connect {
  -    my ($self, $request, $response, $entry) = @_;
  -    $self-&gt;{__start_times}-&gt;{$entry} = [Time::HiRes::gettimeofday];
  -  }
  -  
  -  ###
  -  # Are called when connection is closed
  -  ###
  -  sub on_return {
  -    my ($self, $request, $response, $entry) = @_;
  -    my $start = $self-&gt;{__start_times}-&gt;{$entry};
  -    $self-&gt;{__latency_total} += Time::HiRes::tv_interval($start);
  -  }
  -  
  -  sub on_failure {
  -    on_return(@_);  # Same procedure
  -  }
  -  
  -  ###
  -  # Access function for new instance var
  -  ###
  -  sub get_latency_total {
  -    return shift-&gt;{__latency_total};
  -  }
  -  
  -  ##################################################
  -  package main;
  -  ##################################################
  -  ###
  -  # Init parallel user agent
  -  ###
  -  my $ua = MyParallelAgent-&gt;new();
  -  $ua-&gt;agent(&quot;pounder/1.0&quot;);
  -  $ua-&gt;max_req($nof_parallel_connections);
  -  $ua-&gt;redirect(0);    # No redirects
  -  
  -  ###
  -  # Register all requests
  -  ###
  -  foreach (1..$nof_requests_total) {
  -    foreach my $url (@urls) {
  -      my $request = HTTP::Request-&gt;new('GET', $url);
  -      $ua-&gt;register($request);
  -    }
  -  }
  -  
  -  ###
  -  # Launch processes and check time
  -  ###
  -  my $start_time = [gettimeofday];
  -  my $results = $ua-&gt;wait($timeout);
  -  my $total_time = tv_interval($start_time);
  -  
  -  ###
  -  # Requests all done, check results
  -  ###
  -  
  -  my $succeeded     = 0;
  -  my %errors = ();
  -  
  -  foreach my $entry (values %$results) {
  -    my $response = $entry-&gt;response();
  -    if($response-&gt;is_success()) {
  -      $succeeded++; # Another satisfied customer
  -    } else {
  -      # Error, save the message
  -      $response-&gt;message(&quot;TIMEOUT&quot;) unless $response-&gt;code();
  -      $errors{$response-&gt;message}++;
  -    }
  -  }
  -  
  -  ###
  -  # Format errors if any from %errors 
  -  ###
  -  my $errors = join(',', map &quot;$_ ($errors{$_})&quot;, keys %errors);
  -  $errors = &quot;NONE&quot; unless $errors;
  -  
  -  ###
  -  # Format results
  -  ###
  -  
  -  #@urls = map {($_,&quot;.&quot;)} @urls;
  -  my @P = (
  -        &quot;URL(s)&quot;          =&gt; join(&quot;\n\t\t &quot;, @urls),
  -        &quot;Total Requests&quot;  =&gt; &quot;$nof_requests_total&quot;,
  -        &quot;Parallel Agents&quot; =&gt; $nof_parallel_connections,
  -        &quot;Succeeded&quot;       =&gt; sprintf(&quot;$succeeded (%.2f%%)\n&quot;,
  -                                   $succeeded * 100 / $nof_requests_total),
  -        &quot;Errors&quot;          =&gt; $errors,
  -        &quot;Total Time&quot;      =&gt; sprintf(&quot;%.2f secs\n&quot;, $total_time),
  -        &quot;Throughput&quot;      =&gt; sprintf(&quot;%.2f Requests/sec\n&quot;, 
  -                                   $nof_requests_total / $total_time),
  -        &quot;Latency&quot;         =&gt; sprintf(&quot;%.2f secs/Request&quot;, 
  -                                   ($ua-&gt;get_latency_total() || 0) / 
  -                                   $nof_requests_total),
  -       );
  -  
  -  
  -  my ($left, $right);
  -  ###
  -  # Print out statistics
  -  ###
  -  format STDOUT =
  -  @&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; @*
  -  &quot;$left:&quot;,        $right
  -  .
  -  
  -  while(($left, $right) = splice(@P, 0, 2)) {
  -    write;
  -  }
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Choosing_MaxClients">Choosing MaxClients</A></H2></CENTER>
  +<CENTER><H2><A NAME="Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A></H2></CENTER>
   <P>
  -The <CODE>MaxClients</CODE> directive sets the limit on the number of simultaneous requests that can be
  -supported; no more than this number of child server processes will be
  -created. To configure more than 256 clients, you must edit the <CODE>HARD_SERVER_LIMIT</CODE> entry in <CODE>httpd.h</CODE>
  -and recompile. In our case we want this variable to be as small as
  -possible, this way we can virtually bound the resources used by the server
  -children. Since we can restrict each child's process size (see
  -<A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>) -- the calculation of <CODE>MaxClients</CODE> is pretty straightforward :
  +Here are the numbers from Michael Parker's mod_perl presentation at Perl
  +Conference (Aug, 98) <A
  +HREF="http://www.realtime.net/~parkerm/perl/conf98/index.htm">http://www.realtime.net/~parkerm/perl/conf98/index.htm</A>
  +. The script is a standard hits counter, but it logs the counts into the
  +mysql relational DataBase:
   
   <P>
  -<PRE>               Total RAM Dedicated to the Webserver
  -  MaxClients = ------------------------------------
  -                     MAX child's process size
  +<PRE>    Benchmark: timing 100 iterations of cgi, perl...  [rate 1:28]
  +    
  +    cgi: 56 secs ( 0.33 usr 0.28 sys = 0.61 cpu) 
  +    perl: 2 secs ( 0.31 usr 0.27 sys = 0.58 cpu) 
  +    
  +    Benchmark: timing 1000 iterations of cgi,perl...  [rate 1:21]
  +     
  +    cgi: 567 secs ( 3.27 usr 2.83 sys = 6.10 cpu) 
  +    perl: 26 secs ( 3.11 usr 2.53 sys = 5.64 cpu)      
  +    
  +    Benchmark: timing 10000 iterations of cgi, perl   [rate 1:21]
  +     
  +    cgi: 6494 secs (34.87 usr 26.68 sys = 61.55 cpu) 
  +    perl: 299 secs (32.51 usr 23.98 sys = 56.49 cpu) 
   </PRE>
   <P>
  -So if I have 400Mb left for the webserver to run with, I can set the
  -<CODE>MaxClients</CODE> to be of 40 if I know that each child is bounded to the 10Mb of memory
  -(e.g. with
  -<A HREF="././performance.html#Limiting_the_size_of_the_process"><CODE>Apache::SizeLimit</CODE></A>).
  +We don't know what server configurations was used for these tests, but I
  +guess the numbers speak for themselves.
   
   <P>
  -Certainly you will wonder what happens to your server if there are more
  -than <CODE>MaxClients</CODE> concurrent users at some moment. This situation is accompanied by the
  -following warning message into the
  -<CODE>error.log</CODE> file:
  +The source code of the script is available at <A
  +HREF="http://www.realtime.net/~parkerm/perl/conf98/sld006.htm">http://www.realtime.net/~parkerm/perl/conf98/sld006.htm</A>
  +.
   
   <P>
  -<PRE>  [Sun Jan 24 12:05:32 1999] [error] server reached MaxClients setting,
  -  consider raising the MaxClients setting
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A></H2></CENTER>
   <P>
  -There is no problem -- any connection attempts over the <CODE>MaxClients</CODE>
  -limit will normally be queued, up to a number based on the
  -<CODE>ListenBacklog</CODE> directive. Once a child process is freed at the end of a different request,
  -the connection will then be served.
  +As noted before, for very fast scripts you will have to use the
  +<CODE>Time::HiRes</CODE> module, its usage is similar to the <CODE>Benchmark</CODE>'s.
   
   <P>
  -But it <STRONG>is an error</STRONG> because clients are being put in the queue rather than getting served at
  -once, despite the fact that they do not get an error response. The error
  -can be allowed to persist to balance available system resources and
  -response time, but sooner or later you will need to get more RAM so you can
  -start more children. The best approach is to try not to have this condition
  -reached at all, and if reach it often you should start to worry about it.
  -
  +<PRE>  use Time::HiRes qw(gettimeofday tv_interval);
  +  my $start_time = [ gettimeofday ];
  +  &amp;sub_that_takes_a_teeny_bit_of_time()
  +  my $end_time = [ gettimeofday ];
  +  my $elapsed = tv_interval($start_time,$end_time);
  +  print &quot;the sub took $elapsed secs.&quot;
  +</PRE>
   <P>
  -It's important to understand how much real memory a child occupies. Your
  -children can share the memory between them (when OS supports that and you
  -take action to allow the sharing happen - See
  -<A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>). If this is the case, chances are that your <CODE>MaxClients</CODE> can be even higher. But it seems that it's not so simple to calculate the
  -absolute number. (If you come up with solution please let us know!). If the
  -shared memory was of the same size through the child's life, we could
  -derive a much better formula:
  +See also <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>.
   
   <P>
  -<PRE>               Total_RAM + Shared_RAM_per_Child * MaxClients
  -  MaxClients = ---------------------------------------------
  -                        Max_Process_Size - 1
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A></H2></CENTER>
   <P>
  -which is:
  +At <A
  +HREF="http://perl.apache.org/dist/contrib/">http://perl.apache.org/dist/contrib/</A>
  +you will find
  +<CODE>Apache::Timeit</CODE> package which does <CODE>PerlHandler</CODE>'s Benchmarking.
   
   <P>
  -<PRE>                    Total_RAM - Max_Process_Size
  -  MaxClients = ---------------------------------------
  -               Max_Process_Size - Shared_RAM_per_Child
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A></H1></CENTER>
   <P>
  -Let's roll some calculations:
  +It's very important to make a correct configuration of the
  +<CODE>MinSpareServers</CODE>, <CODE>MaxSpareServers</CODE>, <CODE>StartServers</CODE>,
  +<CODE>MaxClients</CODE>, and <CODE>MaxRequestsPerChild</CODE> parameters. There are no defaults, the values of these variable are very
  +important, as if too ``low'' you will under-use the system's capabilities,
  +and if too ``high'' chances that the server will bring the machine to its
  +knees.
   
   <P>
  -<PRE>  Total_RAM            = 500Mb
  -  Max_Process_Size     =  10Mb
  -  Shared_RAM_per_Child =   4Mb
  -</PRE>
  +All the above parameters should be specified on the basis of the resources
  +you have. While with a plain apache server, there is no big deal if you run
  +too many servers (not too many of course) since the processes are of ~1Mb
  +and aren't eating a lot of your RAM. Generally the numbers are even smaller
  +if memory sharing is taking place. The situation is different with
  +mod_perl. I have seen mod_perl processes of 20Mb and more. Now if you have <CODE>MaxClients</CODE> set to 50: 50x20Mb = 1Gb - do you have 1Gb of RAM? Probably not. So how do
  +you tune these parameters? Generally by trying different combinations and
  +benchmarking the server. Again mod_perl processes can be of much smaller
  +size if sharing is in place.
  +
   <P>
  -<PRE>              500 - 10
  - MaxClients = --------- = 81
  -               10 - 4
  -</PRE>
  +Before you start this task you should be armed with a proper weapon. You
  +need a <STRONG>crashme</STRONG> utility, which will load your server with mod_perl scripts you possess. You
  +need it to have an ability to emulate a multiuser environment and to
  +emulate multiple clients behavior which will call the mod_perl scripts at
  +your server simultaneously. While there are commercial solutions, you can
  +get away with free ones which do the same job. You can use an
  +<A HREF="././performance.html#Tuning_with_ab_ApacheBench">ApacheBench</A>  <STRONG><CODE>ab</CODE></STRONG> utility that comes with apache distribution, a <A HREF="././performance.html#Tuning_with_crashme_script">crashme script</A> which uses
  +<CODE>LWP::Parallel::UserAgent</CODE> or <CODE>httperf</CODE> (see <A HREF="././download.html#">Download page</A>).
  +
   <P>
  -With no sharing in place
  +Another important issue is to make sure to run testing client (load
  +generator) on a system that is more powerful than the system being tested.
  +After all we are trying to simulate the Internet users, where many users
  +are trying to reach your service at once -- since a number of concurrent
  +users can be quite large, your testing machine much be very powerful and
  +capable to generate a heavy load. Of course you should not run the clients
  +and the server on the same machine. If you do -- your testing results would
  +be incorrect, since clients will eat a CPU and a memory that have to be
  +dedicated to the server, and vice versa.
   
   <P>
  -<PRE>                 500
  - MaxClients = --------- = 50
  -                 10
  -</PRE>
  +See also 2 tools for benchmarking:
  +<A HREF="././performance.html#Tuning_with_ab_ApacheBench">ApacheBench</A> and <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>
  +
  +
  +
   <P>
  -With sharing in place you can have 60% more servers without purchasing more
  -RAM, if you improve and keep the sharing level, let's say:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench</A></H2></CENTER>
  +<P>
  +<STRONG>ab</STRONG> is a tool for benchmarking your Apache HTTP server. It is designed to give
  +you an impression on how much performance your current Apache installation
  +can give. In particular, it shows you how many requests per secs your
  +Apache server is capable of serving. The
  +<STRONG>ab</STRONG> tool comes bundled with apache source distribution (and it's free :).
   
   <P>
  -<PRE>  Total_RAM            = 500Mb
  -  Max_Process_Size     =  10Mb
  -  Shared_RAM_per_Child =   8Mb
  -</PRE>
  +Let's try it. We will simulate 10 users concurrently requesting a very
  +light script at <CODE>www.nowhere.com:81/test/test.pl</CODE>. Each ``user'' makes 10 requests.
  +
   <P>
  -<PRE>              500 - 10
  - MaxClients = --------- = 245
  -               10 - 8
  +<PRE>  % ./ab -n 100 -c 10 www.nowhere.com:81/test/test.pl
   </PRE>
   <P>
  -390% more servers!!! You've got the point :)
  +The results are:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A></H2></CENTER>
  +<PRE>  Concurrency Level:      10
  +  Time taken for tests:   0.715 seconds
  +  Complete requests:      100
  +  Failed requests:        0
  +  Non-2xx responses:      100
  +  Total transferred:      60700 bytes
  +  HTML transferred:       31900 bytes
  +  Requests per second:    139.86
  +  Transfer rate:          84.90 kb/s received
  +  
  +  Connection Times (ms)
  +                min   avg   max
  +  Connect:        0     0     3
  +  Processing:    13    67    71
  +  Total:         13    67    74
  +</PRE>
   <P>
  -The <CODE>MaxRequestsPerChild</CODE> directive sets the limit on the number of requests that an individual child
  -server process will handle. After
  -<CODE>MaxRequestsPerChild</CODE> requests, the child process will die. If
  -<CODE>MaxRequestsPerChild</CODE> is 0, then the process will live forever.
  +The only numbers we really care about are:
   
   <P>
  -Setting <CODE>MaxRequestsPerChild</CODE> to a non-zero limit has two beneficial effects: it solves memory leakages
  -and helps reduce the number of processes when the server load reduces.
  -
  +<PRE>  Complete requests:      100
  +  Failed requests:        0
  +  Requests per second:    139.86
  +</PRE>
   <P>
  -The first reason is the most crucial for mod_perl, since sloppy programming
  -will cause a child process to consume more memory after each request. If
  -left unbounded, then after a certain number of requests the children will
  -use up all the available memory and leave the server to die from memory
  -starvation. Note, that sometimes standard system libraries leak memory too,
  -especially on OSes with bad memory management (e.g. Solaris 2.5 on x86
  -arch). If this is your case you can set <CODE>MaxRequestsPerChild</CODE> to a small number, which will allow the system to reclaim the memory,
  -greedy child process consumed, when it exits after <CODE>MaxRequestsPerChild</CODE> requests. But beware -- if you set this number too low, you will loose a
  -fracture of the speed bonus you receive with mod_perl. Consider using <CODE>Apache::PerlRun</CODE> if this is the case. Also setting <CODE>MaxSpareServers</CODE> to a number close to
  -<CODE>MaxClients</CODE>, will improve the response time (but your parent process will be busy
  -respawning new children all the time!)
  +Let's raise the load of requests to 100 x 10 (10 users, each makes 100
  +requests)
   
   <P>
  -Another approach is to use <CODE>Apache::SizeLimit</CODE> (See <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>). By using this module, you should be able to discontinue using the
  -<CODE>MaxRequestsPerChild</CODE>, although for some folks, using both in combination does the job.
  -
  +<PRE>  % ./ab -n 1000 -c 10 www.nowhere.com:81/perl/access/access.cgi
  +  Concurrency Level:      10
  +  Complete requests:      1000
  +  Failed requests:        0
  +  Requests per second:    139.76
  +</PRE>
   <P>
  -See also <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A> and
  -<A HREF="././performance.html#Sharing_Memory">Sharing Memory</A>.
  +As expected nothing changes -- we have the same 10 concurrent users. Now
  +let's raise the number of concurrent users to 50:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A></H2></CENTER>
  +<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
  +  Complete requests:      1000
  +  Failed requests:        0
  +  Requests per second:    133.01
  +</PRE>
   <P>
  -With mod_perl enabled, it might take as much as 30 seconds from the time
  -you start the server until it is ready to serve incoming requests. This
  -delay depends on the OS, the number of preloaded modules and the process
  -load of the machine. So it's best to set
  -<CODE>StartServers</CODE> and <CODE>MinSpareServers</CODE> to high numbers, so that if you get a high load just after the server has
  -been restarted, the fresh servers will be ready to serve requests
  -immediately. With mod_perl, it's usually a good idea to raise all 3
  -variables higher than normal. In order to maximize the benefits of
  -mod_perl, you don't want to kill servers when they are idle, rather you
  -want them to stay up and available to immediately handle new requests. I
  -think an ideal configuration is to set <CODE>MinSpareServers</CODE> and <CODE>MaxSpareServers</CODE> to similar values, maybe even the same. Having the <CODE>MaxSpareServers</CODE>
  -close to <CODE>MaxClients</CODE> will completely use all of your resources (if
  -<CODE>MaxClients</CODE> has been chosen to take the full advantage of the resources), but it'll
  -make sure that at any given moment your system will be capable of
  -responding to requests with the maximum speed (given that number of
  -concurrent requests is not higher than
  -<CODE>MaxClients</CODE>.)
  +We see that the server is capable of serving 50 concurrent users at an
  +amazing 133 req/sec! Let's find the upper boundary. Using <CODE>-n 10000
  +-c 1000</CODE> failed to get results (Broken Pipe?). Using <CODE>-n 10000 -c
  +500</CODE> derived 94.82 req/sec. The server's performance went down with the high
  +load.
   
   <P>
  -Let's try some numbers. For a heavily loaded web site and a dedicated
  -machine I would think of (note 400Mb is just for example):
  +The above tests were performed with the following configuration:
   
   <P>
  -<PRE>  Available to webserver RAM:   400Mb
  -  Child's memory size bounded:  10Mb
  -  MaxClients:                   400/10 = 40 (larger with mem sharing)
  -  StartServers:                 20
  -  MinSpareServers:              20
  -  MaxSpareServers:              35
  +<PRE>  MinSpareServers 8
  +  MaxSpareServers 6
  +  StartServers 10
  +  MaxClients 50
  +  MaxRequestsPerChild 1500
   </PRE>
   <P>
  -However if I want to use the server for many other tasks, but make it
  -capable of handling a high load, I'd think of:
  +Now let's kill a child after a single request, we will use the following
  +configuration:
   
   <P>
  -<PRE>  Available to webserver RAM:   400Mb
  -  Child's memory size bounded:  10Mb
  -  MaxClients:                   400/10 = 40
  -  StartServers:                 5
  -  MinSpareServers:              5
  -  MaxSpareServers:              10
  +<PRE>  MinSpareServers 8
  +  MaxSpareServers 6
  +  StartServers 10
  +  MaxClients 100
  +  MaxRequestsPerChild 1
   </PRE>
   <P>
  -(These numbers are taken off the top of my head, and it shouldn't be used
  -as a rule, but rather as examples to show you some possible scenarios. Use
  -this information wisely!)
  +Simulate 50 users each generating a total of 20 requests:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A></H2></CENTER>
  +<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
  +</PRE>
   <P>
  -OK, we've run various benchmarks -- let's summarize the conclusions:
  +The benchmark timed out with the above configuration.... I watched the
  +output of <STRONG><CODE>ps</CODE></STRONG> as I ran it, the parent process just wasn't capable of respawning the
  +killed children at that rate...When I raised the
  +<CODE>MaxRequestsPerChild</CODE> to 10 I've got 8.34 req/sec - very bad (18 times slower!) (You can't
  +benchmark the importance of the
  +<CODE>MinSpareServers</CODE>, <CODE>MaxSpareServers</CODE> and <CODE>StartServers</CODE> with this kind of test).
   
  -<UL>
  -<P><LI><STRONG><A NAME="item_MaxRequestsPerChild">MaxRequestsPerChild</A></STRONG>
   <P>
  -If your scripts are clean and don't leak memory, set this variable to a
  -number as large as possible (10000?). If you use
  -<CODE>Apache::SizeLimit</CODE>, you can set this parameter to 0 (equal to infinity). You will want this
  -parameter to be smaller if your code becomes unshared over the process'
  -life.
  +Now let's try to return <CODE>MaxRequestsPerChild</CODE> to 1500, but to lower the
  +<CODE>MaxClients</CODE> to 10 and run the same test:
   
  -<P><LI><STRONG><A NAME="item_StartServers">StartServers</A></STRONG>
   <P>
  -If you keep a small number of servers active most of the time, keep this
  -number low. Especially if <CODE>MaxSpareServers</CODE> is low as it'll kill the just loaded servers before they were utilized at
  -all (if there is no load). If your service is heavily loaded, make this
  -number close to
  -<CODE>MaxClients</CODE> (and keep <CODE>MaxSpareServers</CODE> equal to <CODE>MaxClients</CODE> as well.)
  +<PRE>  MinSpareServers 8
  +  MaxSpareServers 6
  +  StartServers 10
  +  MaxClients 10
  +  MaxRequestsPerChild 1500
  +</PRE>
  +<P>
  +I've got 27.12 req/sec, which is better but still 4-5 times slower (133
  +with <CODE>MaxClients</CODE> of 50)
   
  -<P><LI><STRONG><A NAME="item_MinSpareServers">MinSpareServers</A></STRONG>
   <P>
  -If your server performs other work besides web serving, make this low so
  -the memory of unused children will be freed when there is no big load. If
  -your server's load varies (you get loads in bursts) and you want fast
  -response for all clients at any time, you will want to make it high, so
  -that new children will be respawned in advance and be waiting to handle
  -bursts of requests.
  +<STRONG>Summary:</STRONG> I have tested a few combinations of server configuration variables (<CODE>MinSpareServers</CODE>  <CODE>MaxSpareServers</CODE>  <CODE>StartServers</CODE>
   
  -<P><LI><STRONG><A NAME="item_MaxSpareServers">MaxSpareServers</A></STRONG>
  +<CODE>MaxClients</CODE>  <CODE>MaxRequestsPerChild</CODE>). And the results we have received are as follows:
  +
   <P>
  -The logic is the same as of <CODE>MinSpareServers</CODE> - low if you need the machine for other tasks, high if it's a dedicated web
  -host and you want a minimal response delay.
  +<CODE>MinSpareServers</CODE>, <CODE>MaxSpareServers</CODE> and <CODE>StartServers</CODE> are only important for user response times (sometimes user will have to
  +wait a bit).
   
  -<P><LI><STRONG><A NAME="item_MaxClients">MaxClients</A></STRONG>
   <P>
  -Not too low, so you don't get into a situation where clients are waiting
  -for the server to start serving them (they might wait, but not for too
  -long). Do not set it too high, since if you get a high load and all
  -requests will be immediately granted and served, your CPU will have a hard
  -time keeping up, and if the child's size * number of running children is
  -larger than the total available RAM, your server will start swapping (which
  -will slow down everything, which in turn will make things even more slower,
  -until eventually your machine will die). It's important that you take pains
  -to ensure that swapping does not normally happen. Swap space is an
  -emergency pool, not a resource to be used on a consistent basis. If you are
  -low on memory and you badly need it - buy it, memory is amazingly cheap
  -these days. 
  +The important parameters are <CODE>MaxClients</CODE> and
  +<CODE>MaxRequestsPerChild</CODE>. <CODE>MaxClients</CODE> should be not to big so it will not abuse your machine's memory resources
  +and not too small, when users will be forced to wait for the children to
  +become free to come serve them. <CODE>MaxRequestsPerChild</CODE> should be as big as possible, to take the full benefit of mod_perl, but
  +watch your server at the beginning to make sure your scripts are not
  +leaking memory, thereby causing your server (and your service) to die very
  +fast.
   
   <P>
  -But based on the test I conducted above, even if you have plenty of memory
  -like I have (1Gb), increasing <CODE>MaxClients</CODE> sometimes will give you no speedup. The more clients are running, the more
  -CPU time will be required, the less CPU time slices each process will
  -receive. The response latency (the time to respond to a request) will grow,
  -so you won't see the expected improvement. The best approach is to find the
  -minimum requirement for your kind of service and the maximum capability of
  -your machine. Then start at the minimum and test like I did, successively
  -raising this parameter until you find the point on the curve of the graph
  -of the latency or/and throughput where the improvement becomes smaller.
  -Stop there and use it. Of course when you use these parameters in
  -production server, you will have the ability to tune them more precisely,
  -since then you will see the real numbers. Also don't forget that if you add
  -more scripts, or just modify the running ones -- most probably that the
  -parameters need to be recalculated, since the processes will grow in size
  -as you compile in more code.
  +Also it is important to understand that we didn't test the response times
  +in the tests above, but the ability of the server to respond under a heavy
  +load of requests. If the script that was used to test was heavier, the
  +numbers would be different but the conclusions are very similar.
   
  -</UL>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Persistent_DB_Connections">Persistent DB Connections</A></H1></CENTER>
  -<P>
  -Another popular use of mod_perl is to take advantage of its ability to
  -maintain persistent open database connections. The basic approach is as
  -follows:
  +The benchmarks were run with:
   
   <P>
  -<PRE>  # Apache::Registry script
  -  -------------------------
  -  use strict;
  -  use vars qw($dbh);
  -  
  -  $dbh ||= SomeDbPackage-&gt;connect(...);
  +<PRE>  HW: RS6000, 1Gb RAM
  +  SW: AIX 4.1.5 . mod_perl 1.16, apache 1.3.3
  +  Machine running only mysql, httpd docs and mod_perl servers.
  +  Machine was _completely_ unloaded during the benchmarking.
   </PRE>
   <P>
  -Since <CODE>$dbh</CODE> is a global variable for the child, once the child has opened the
  -connection it will use it over and over again, unless you perform <CODE>disconnect()</CODE>.
  +After each server restart when I did changes to the server's
  +configurations, I made sure the scripts were preloaded by fetching a script
  +at least once by every child.
   
   <P>
  -Be careful to use different names for handlers if you open connection to
  -different databases!
  +It is important to notice that none of requests timed out, even if was kept
  +in server's queue for more than 1 minute! (That is the way <STRONG>ab</STRONG>
  +works, which is OK for the testing purposes but will be unacceptable in the
  +real world - users will not wait for more than 5-10 secs for a request to
  +complete, and the client (browser) will timeout in a few minutes.)
   
   <P>
  -<CODE>Apache::DBI</CODE> allows you to make a persistent database connection. With this module
  -enabled, every <CODE>connect()</CODE> request to the plain <CODE>DBI</CODE> module will be forwarded to the <CODE>Apache::DBI</CODE>
  -module. This looks to see whether a database handle from a previous
  -<CODE>connect()</CODE> request has already been opened, and if this handle is still valid using
  -the ping method. If these two conditions are fulfilled it just returns the
  -database handle. If there is no appropriate database handle or if the ping
  -method fails, a new connection is established and the handle is stored for
  -later re-use. <STRONG>There is no need to delete the <CODE>disconnect()</CODE> statements
  -from your code</STRONG>. They will not do a thing, as the <CODE>Apache::DBI</CODE>
  -module overloads the <CODE>disconnect()</CODE> method with a NOP. On child's exit there is no explicit disconnect, the
  -child dies and so does the database connection. You may leave the <CODE>use DBI;</CODE> statement inside the scripts as well.
  +Now let's take a look at some real code whose execution time is more than a
  +few millisecs. We will do real testing and collect the data in tables for
  +easier viewing.
   
   <P>
  -The usage is simple -- add to <CODE>httpd.conf</CODE>:
  +I will use the following abbreviations:
   
   <P>
  -<PRE>  PerlModule Apache::DBI
  +<PRE>  NR    = Total Number of Request
  +  NC    = Concurrency
  +  MC    = MaxClients
  +  MRPC  = MaxRequestsPerChild
  +  RPS   = Requests per second
   </PRE>
   <P>
  -It is important, to load this module before any other <CODE>DBI</CODE>,
  -<CODE>DBD::*</CODE> and <CODE>ApacheDBI*</CODE> modules!
  +Running a mod_perl script with lots of mysql queries (the script under test
  +is mysqld bounded)
  +(http://www.nowhere.com:81/perl/access/access.cgi?do_sub=query_form), with
  +configuration:
   
   <P>
  -<PRE>  db.pl
  -  ------------
  -  use DBI;
  -  use strict;
  -  
  -  my $dbh = DBI-&gt;connect( 'DBI:mysql:database', 'user', 'password',
  -                          { autocommit =&gt; 0 }
  -                        ) || die $DBI::errstr;
  -  
  -  ...rest of the program
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
  +  MaxRequestsPerChild 5000
   </PRE>
   <P>
  -If you use <CODE>DBI</CODE> for DB connections, and you use <CODE>Apache::DBI</CODE> to make them persistent, it also allows you to preopen connections to DB
  -for each child with <CODE>connect_on_init()</CODE> method, thus saving up a connection overhead on the very first request of
  -every child.
  +gives us:
   
   <P>
  -<PRE>  use Apache::DBI ();
  -  Apache::DBI-&gt;connect_on_init(&quot;DBI:mysql:test&quot;,
  -                               &quot;login&quot;,
  -                               &quot;passwd&quot;,
  -                               {
  -                                RaiseError =&gt; 1,
  -                                PrintError =&gt; 0,
  -                                AutoCommit =&gt; 1,
  -                               }
  -                              );
  +<PRE>     NR   NC    RPS     comment
  +  ------------------------------------------------
  +     10   10    3.33    # not a reliable statistics
  +    100   10    3.94    
  +   1000   10    4.62    
  +   1000   50    4.09    
   </PRE>
   <P>
  -This can be used as a simple way to have apache children establish
  -connections on server startup. This call should be in a startup file
  -<CODE>require()d</CODE> by <CODE>PerlRequire</CODE> or inside &lt;Perl&gt; section. It will establish a connection when a child is started in
  -that child process. See the <CODE>Apache::DBI</CODE> manpage to see the requirements for this method.
  -
  -<P>
  -You can also benefit from persistent connections by replacing
  -<CODE>prepare()</CODE> with <CODE>prepare_cached().</CODE> But it can
  -produce a little overhead (META, why?).
  -
  -<P>
  -Another problem is with timeouts: some databases disconnect the client
  -after a certain time of inactivity. This problem is known as <STRONG>morning
  -bug</STRONG>. The <CODE>ping()</CODE> method ensures that this will not happen. Some
  -<CODE>DBD</CODE> drivers don't have this method, check the <CODE>Apache::DBI</CODE>
  -manpage to see how to write a <CODE>ping()</CODE> method.
  +<STRONG>Conclusions:</STRONG> Here I wanted to show that when the application is slow -- not due to perl
  +loading, code compilation and execution, but bounded to some external
  +operation like mysqld querying which made the bottleneck -- it almost does
  +not matter what load we place on the server. The RPS (Requests per second)
  +is almost the same (given that all the requests have been served, you have
  +an ability to queue the clients, but be aware that something that goes to
  +queue means a waiting client and a client (browser) that might time out!)
   
   <P>
  -Another approach is to change the client's connection timeout. For mysql
  -users, starting from mysql-3.22.x you can set a <CODE>wait_timeout</CODE>
  -option at mysqld server startup to change the default value. Setting it to
  -36 hours probably would fix the timeout problem.
  +Now we will benchmark the same script without using the mysql (perl only
  +bounded code) (http://www.nowhere.com:81/perl/access/access.cgi), it's the
  +same script that just returns a HTML form, without making any SQL queries.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</A></H1></CENTER>
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
  +  MaxRequestsPerChild 5000
  +</PRE>
   <P>
  -As you know <CODE>local $|=1;</CODE> disables the buffering of the currently selected file handle (default is <CODE>STDOUT</CODE>). If you enable it,
  -<CODE>ap_rflush()</CODE> is called after each <CODE>print()</CODE>, unbuffering Apache's IO.
  -
  +<PRE>     NR   NC      RPS   comment
  +  ------------------------------------------------
  +     10   10    26.95   # not a reliable statistics
  +    100   10    30.88   
  +   1000   10    29.31
  +   1000   50    28.01
  +   1000  100    29.74
  +  10000  200    24.92
  + 100000  400    24.95
  +</PRE>
   <P>
  -If you are using a _bad_ style in generating output, which consist of
  -multiple <CODE>print()</CODE> calls, or you just have too many of them, you will experience a degradation
  -in performance. The severity depends on the number of the calls you make.
  +<STRONG>Conclusions:</STRONG> This time the script we executed was pure perl (not bounded to I/O or
  +mysql), so we see that the server serves the requests much faster. You can
  +see the <CODE>RequestPerSecond</CODE> (RPS) is almost the same for any load, but goes lower when the number of
  +concurrent clients goes beyond the <CODE>MaxClients</CODE>. With 25 RPS, the client supplying a load of 400 concurrent clients will
  +be served in 16 secs. But to get more realistic and assume the max
  +concurrency of 100, with 30 RPS, the client will be served in 3.5 secs,
  +which is pretty good for a highly loaded server.
   
   <P>
  -Many old CGIs were written in the style of:
  +Now we will use the server for its full capacity, by keeping all
  +<CODE>MaxClients</CODE> alive all the time and having a big
  +<CODE>MaxRequestsPerChild</CODE>, so no server will be killed during the benchmarking.
   
   <P>
  -<PRE>  print &quot;&lt;BODY BGCOLOR=\&quot;black\&quot; TEXT=\&quot;white\&quot;&gt;&quot;;
  -  print &quot;&lt;H1&gt;&quot;;
  -  print &quot;Hello&quot;;
  -  print &quot;&lt;/H1&gt;&quot;;
  -  print &quot;&lt;A HREF=\&quot;foo.html\&quot;&gt; foo &lt;/A&gt;&quot;;
  -  print &quot;&lt;/BODY&gt;&quot;;
  +<PRE>  MinSpareServers       50
  +  MaxSpareServers       50
  +  StartServers          50
  +  MaxClients            50
  +  MaxRequestsPerChild 5000
  +  
  +     NR   NC      RPS   comment
  +  ------------------------------------------------
  +    100   10    32.05
  +   1000   10    33.14
  +   1000   50    33.17
  +   1000  100    31.72
  +  10000  200    31.60
   </PRE>
   <P>
  -which reveals the following drawbacks: multiple <CODE>print()</CODE> calls - performance degradation with <CODE>$|=1</CODE>, backslashism which makes the code less readable and more difficult to
  -format the HTML to be easily readable as CGI's output. The code below
  -solves them all:
  +Conclusion: In this scenario there is no overhead involving the parent
  +server loading new children, all the servers are available, and the only
  +bottleneck is contention for the CPU.
   
  -<P>
  -<PRE>  print qq{
  -    &lt;BODY BGCOLOR=&quot;black&quot; TEXT=&quot;white&quot;&gt;
  -      &lt;H1&gt;
  -        Hello
  -      &lt;/H1&gt;
  -      &lt;A HREF=&quot;foo.html&quot;&gt; foo &lt;/A&gt;
  -    &lt;/BODY&gt;
  -  };
  -</PRE>
   <P>
  -I guess you see the difference. Be careful though, when printing a
  -<CODE>&lt;HTML</CODE>&gt; tag. The correct way is:
  +Now we will try to change the <CODE>MaxClients</CODE> and to watch the results: Let's reduce MC to 10.
   
   <P>
  -<PRE>  print qq{&lt;HTML&gt;
  -    &lt;HEAD&gt;&lt;/HEAD&gt;
  -    &lt;BODY&gt;
  -  }
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       10
  +  StartServers          10
  +  MaxClients            10
  +  MaxRequestsPerChild 5000
  +  
  +     NR   NC      RPS   comment
  +  ------------------------------------------------
  +     10   10    23.87   # not a reliable statistics
  +    100   10    32.64 
  +   1000   10    32.82
  +   1000   50    30.43
  +   1000  100    25.68
  +   1000  500    26.95
  +   2000  500    32.53
   </PRE>
   <P>
  -If you try the following:
  +<STRONG>Conclusions:</STRONG> A very little difference! Almost no change! 10 servers were able to serve
  +almost with the same throughput as 50 servers. Why? My guess it's because
  +of CPU throttling. It seems that 10 servers were serving requests 5 times
  +faster than when in the test above we worked with 50 servers. In the case
  +above each child received its CPU time slice 5 times less frequently. So
  +having a big value for
  +<CODE>MaxClients</CODE>, doesn't mean that the performance will be better. You have just seen the
  +numbers!
   
  -<P>
  -<PRE>  print qq{
  -    &lt;HTML&gt;
  -    &lt;HEAD&gt;&lt;/HEAD&gt;
  -    &lt;BODY&gt;
  -  }
  -</PRE>
   <P>
  -Some older browsers might not accept the output as HTML, but rather print
  -it as a plain text, since they expect the first characters after the
  -headers and empty line to be <CODE>&lt;HTML</CODE>&gt; and not spaces and/or additional newline and then <CODE>&lt;HTML</CODE>&gt;. Even if it works with your browser, it might not work for others.
  +Now we will start to drastically reduce the <CODE>MaxRequestsPerChild</CODE>:
   
   <P>
  -Now let's go back to the <CODE>$|=1</CODE> topic. I still disable buffering, for 2 reasons: I use few <CODE>print()</CODE> calls by printing out multiline HTML and not a line per <CODE>print()</CODE> and I want my users to see the output immediately. So if I am about to
  -produce the results of the DB query, which might take some time to
  -complete, I want users to get some titles ahead. This improves the
  -usability of my site. Recall yourself: What do you like better: getting the
  -output a bit slower, but steadily from the moment you've pressed the <STRONG>Submit</STRONG> button or having to watch the ``falling stars'' for awhile and then to
  -receive the whole output at once, even a few millisecs faster (if the
  -client (browser) did not time out till then).
  -
  -<P>
  -<STRONG>Conclusion</STRONG>: Do not blindly follow suggestions, but think what is best for you in
  -every given case.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A></H1></CENTER>
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
  +  
  +     NR   NC    MRPC     RPS    comment
  +  ------------------------------------------------
  +    100   10      10    5.77 
  +    100   10       5    3.32
  +   1000   50      20    8.92
  +   1000   50      10    5.47
  +   1000   50       5    2.83
  +   1000  100      10    6.51
  +</PRE>
   <P>
  -One of the important issues in improving the performance is reduction of
  -memory usage - the less memory each server uses, the more server processes
  -you can start, and thus the more performance you have (from the user's
  -point of view - the response speed )
  +<STRONG>Conclusions:</STRONG> When we drastically reduce the <CODE>MaxRequestsPerChild</CODE>, the performance starts to become closer to the plain mod_cgi. Just for
  +comparison with mod_cgi, here are the numbers of this run with mod_cgi:
   
   <P>
  -See <A HREF="././porting.html#Global_Variables">Global Variables</A>
  -
  -
  -
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
  +  
  +     NR   NC    RPS     comment
  +  ------------------------------------------------
  +    100   10    1.12
  +   1000   50    1.14
  +   1000  100    1.13
  +</PRE>
   <P>
  -See <A HREF="././porting.html#Memory_leakage">Memory "leakages"</A>
  -
  -
  +<STRONG>Conclusion</STRONG>: mod_cgi is much slower :) in test NReq/NClients 100/10 the RPS in mod_cgi
  +was of 1.12 and in mod_perl of 32, which is 30 times faster!!! In the first
  +test each child waited about 100 secs to be served. In the second and third
  +1000 secs!
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Profiling">Profiling</A></H1></CENTER>
  +<CENTER><H2><A NAME="Tuning_with_crashme_script">Tuning with crashme script</A></H2></CENTER>
   <P>
  -Profiling process helps you to determine which subroutines or just snippets
  -of code take the longest execution time and which subroutines are being
  -called most often. Probably you will want to optimize those, and to improve
  -the code toward efficiency.
  +This is another crashme suite originally written by Michael Schilli and
  +located at <A
  +HREF="http://www.linux-magazin.de/ausgabe.1998.08/Pounder/pounder.html">http://www.linux-magazin.de/ausgabe.1998.08/Pounder/pounder.html</A>
  +. I did a few modifications (mostly adding <CODE>my()</CODE> operands). I
  +also allowed it to accept more than one url to test, since sometimes you
  +want to test an overall and not just one script.
   
   <P>
  -It is possible to profile code running under mod_perl with the
  -<CODE>Devel::DProf</CODE> module, available on CPAN. However, you must have apache version 1.3b3 or
  -higher and the <CODE>PerlChildExitHandler</CODE> enabled (during the httpd build process). When the server is started,
  -<CODE>Devel::DProf</CODE> installs an <CODE>END</CODE> block to write the <CODE>tmon.out</CODE>
  -file. This block will be called at the server shutdown. Here is how to
  -start and stop a server with the profiler enabled:
  +The tool provides the same results as <STRONG>ab</STRONG> above but it also allows you to set the timeout value, so requests will
  +fail if not served within the time out period. You also get <STRONG>Latency</STRONG> (secs/Request) and
  +<STRONG>Throughput</STRONG> (Requests/sec) numbers. It can give you a better picture and make a
  +complete simulation of your favorite Netscape browser :).
   
  -<P>
  -<PRE>  % setenv PERL5OPT -d:DProf
  -  % httpd -X -d `pwd` &amp;
  -  ... make some requests to the server here ...
  -  % kill `cat logs/httpd.pid`
  -  % unsetenv PERL5OPT
  -  % dprofpp
  -</PRE>
   <P>
  -The <CODE>Devel::DProf</CODE> package is a Perl code profiler. It will collect information on the
  -execution time of a Perl script and of the subs in that script (remember
  -that <CODE>print()</CODE> and <CODE>map()</CODE> are just like any other subroutines you write, but they are come bundled
  -with Perl!)
  +I have noticed while running these 2 benchmarking suites - <STRONG>ab</STRONG> gave me results 2.5-3.0 times better. Both suites run on the same machine
  +with the same load with the same parameters. But the implementations are
  +different.
   
   <P>
  -Another approach is to use <CODE>Apache::DProf</CODE>, which hooks
  -<CODE>Devel::DProf</CODE> into mod_perl. The <CODE>Apache::DProf</CODE> module will run a
  -<CODE>Devel::DProf</CODE> profiler inside each child server and write the
  -<CODE>tmon.out</CODE> file in the directory <CODE>$ServerRoot/logs/dprof/$$</CODE> when the child is shutdown (where <CODE>$$</CODE> is a number of the child process). All it takes is to add to <CODE>httpd.conf</CODE>:
  +Sample output:
   
   <P>
  -<PRE>  PerlModule Apache::DProf
  +<PRE>  URL(s):          <A HREF="http://www.nowhere.com:81/perl/access/access.cgi">http://www.nowhere.com:81/perl/access/access.cgi</A>
  +  Total Requests:  100
  +  Parallel Agents: 10
  +  Succeeded:       100 (100.00%)
  +  Errors:          NONE
  +  Total Time:      9.39 secs
  +  Throughput:      10.65 Requests/sec
  +  Latency:         0.85 secs/Request
   </PRE>
   <P>
  -Remember that any PerlHandler that was pulled in before
  -<CODE>Apache::DProf</CODE> in the <CODE>httpd.conf</CODE> or &lt;startup.pl&gt;, would not have its code debugging info inserted. To run <CODE>dprofpp</CODE>, chdir to
  -<CODE>$ServerRoot/logs/dprof/$$</CODE> and run:
  +And the code:
   
   <P>
  -<PRE>  % dprofpp
  +<PRE>  #!/usr/apps/bin/perl -w
  +  
  +  use LWP::Parallel::UserAgent;
  +  use Time::HiRes qw(gettimeofday tv_interval);
  +  use strict;
  +  
  +  ###
  +  # Configuration
  +  ###
  +  
  +  my $nof_parallel_connections = 10; 
  +  my $nof_requests_total = 100; 
  +  my $timeout = 10;
  +  my @urls = (
  +            '<A HREF="http://www.nowhere.com:81/perl/faq_manager/faq_manager.pl">http://www.nowhere.com:81/perl/faq_manager/faq_manager.pl</A>',
  +            '<A HREF="http://www.nowhere.com:81/perl/access/access.cgi">http://www.nowhere.com:81/perl/access/access.cgi</A>',
  +           );
  +  
  +  
  +  ##################################################
  +  # Derived Class for latency timing
  +  ##################################################
  +  
  +  package MyParallelAgent;
  +  @MyParallelAgent::ISA = qw(LWP::Parallel::UserAgent);
  +  use strict;
  +  
  +  ###
  +  # Is called when connection is opened
  +  ###
  +  sub on_connect {
  +    my ($self, $request, $response, $entry) = @_;
  +    $self-&gt;{__start_times}-&gt;{$entry} = [Time::HiRes::gettimeofday];
  +  }
  +  
  +  ###
  +  # Are called when connection is closed
  +  ###
  +  sub on_return {
  +    my ($self, $request, $response, $entry) = @_;
  +    my $start = $self-&gt;{__start_times}-&gt;{$entry};
  +    $self-&gt;{__latency_total} += Time::HiRes::tv_interval($start);
  +  }
  +  
  +  sub on_failure {
  +    on_return(@_);  # Same procedure
  +  }
  +  
  +  ###
  +  # Access function for new instance var
  +  ###
  +  sub get_latency_total {
  +    return shift-&gt;{__latency_total};
  +  }
  +  
  +  ##################################################
  +  package main;
  +  ##################################################
  +  ###
  +  # Init parallel user agent
  +  ###
  +  my $ua = MyParallelAgent-&gt;new();
  +  $ua-&gt;agent(&quot;pounder/1.0&quot;);
  +  $ua-&gt;max_req($nof_parallel_connections);
  +  $ua-&gt;redirect(0);    # No redirects
  +  
  +  ###
  +  # Register all requests
  +  ###
  +  foreach (1..$nof_requests_total) {
  +    foreach my $url (@urls) {
  +      my $request = HTTP::Request-&gt;new('GET', $url);
  +      $ua-&gt;register($request);
  +    }
  +  }
  +  
  +  ###
  +  # Launch processes and check time
  +  ###
  +  my $start_time = [gettimeofday];
  +  my $results = $ua-&gt;wait($timeout);
  +  my $total_time = tv_interval($start_time);
  +  
  +  ###
  +  # Requests all done, check results
  +  ###
  +  
  +  my $succeeded     = 0;
  +  my %errors = ();
  +  
  +  foreach my $entry (values %$results) {
  +    my $response = $entry-&gt;response();
  +    if($response-&gt;is_success()) {
  +      $succeeded++; # Another satisfied customer
  +    } else {
  +      # Error, save the message
  +      $response-&gt;message(&quot;TIMEOUT&quot;) unless $response-&gt;code();
  +      $errors{$response-&gt;message}++;
  +    }
  +  }
  +  
  +  ###
  +  # Format errors if any from %errors 
  +  ###
  +  my $errors = join(',', map &quot;$_ ($errors{$_})&quot;, keys %errors);
  +  $errors = &quot;NONE&quot; unless $errors;
  +  
  +  ###
  +  # Format results
  +  ###
  +  
  +  #@urls = map {($_,&quot;.&quot;)} @urls;
  +  my @P = (
  +        &quot;URL(s)&quot;          =&gt; join(&quot;\n\t\t &quot;, @urls),
  +        &quot;Total Requests&quot;  =&gt; &quot;$nof_requests_total&quot;,
  +        &quot;Parallel Agents&quot; =&gt; $nof_parallel_connections,
  +        &quot;Succeeded&quot;       =&gt; sprintf(&quot;$succeeded (%.2f%%)\n&quot;,
  +                                   $succeeded * 100 / $nof_requests_total),
  +        &quot;Errors&quot;          =&gt; $errors,
  +        &quot;Total Time&quot;      =&gt; sprintf(&quot;%.2f secs\n&quot;, $total_time),
  +        &quot;Throughput&quot;      =&gt; sprintf(&quot;%.2f Requests/sec\n&quot;, 
  +                                   $nof_requests_total / $total_time),
  +        &quot;Latency&quot;         =&gt; sprintf(&quot;%.2f secs/Request&quot;, 
  +                                   ($ua-&gt;get_latency_total() || 0) / 
  +                                   $nof_requests_total),
  +       );
  +  
  +  
  +  my ($left, $right);
  +  ###
  +  # Print out statistics
  +  ###
  +  format STDOUT =
  +  @&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; @*
  +  &quot;$left:&quot;,        $right
  +  .
  +  
  +  while(($left, $right) = splice(@P, 0, 2)) {
  +    write;
  +  }
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="CGI_pm_s_object_methods_calls_vs">CGI.pm's object methods calls vs. function calls</A></H1></CENTER>
  -<P>
  -Which approach is better?
  -
  +<CENTER><H2><A NAME="Choosing_MaxClients">Choosing MaxClients</A></H2></CENTER>
   <P>
  -<PRE>  use CGI;
  -  my $q = new CGI;
  -  print $q-&gt;param('x');
  -</PRE>
  -<P>
  -versus
  +The <CODE>MaxClients</CODE> directive sets the limit on the number of simultaneous requests that can be
  +supported; no more than this number of child server processes will be
  +created. To configure more than 256 clients, you must edit the <CODE>HARD_SERVER_LIMIT</CODE> entry in <CODE>httpd.h</CODE>
  +and recompile. In our case we want this variable to be as small as
  +possible, this way we can virtually bound the resources used by the server
  +children. Since we can restrict each child's process size (see
  +<A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>) -- the calculation of <CODE>MaxClients</CODE> is pretty straightforward :
   
   <P>
  -<PRE>  use CGI (:standard);
  -  print param('x');
  +<PRE>               Total RAM Dedicated to the Webserver
  +  MaxClients = ------------------------------------
  +                     MAX child's process size
   </PRE>
   <P>
  -There is not any performance benefit of using the object calls rather than
  -the function calls, but there is a real memory hit when you import all of <CODE>CGI.pm</CODE>'s function calls into your process memory. This can be significant,
  -particularly when there are many child daemons.
  +So if I have 400Mb left for the webserver to run with, I can set the
  +<CODE>MaxClients</CODE> to be of 40 if I know that each child is bounded to the 10Mb of memory
  +(e.g. with
  +<A HREF="././performance.html#Limiting_the_size_of_the_process"><CODE>Apache::SizeLimit</CODE></A>).
   
   <P>
  -I strongly endorse <A HREF="././modules.html#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>. Its guts are all written in C, giving it a significant memory and
  -performance benefit.
  +Certainly you will wonder what happens to your server if there are more
  +than <CODE>MaxClients</CODE> concurrent users at some moment. This situation is accompanied by the
  +following warning message into the
  +<CODE>error.log</CODE> file:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A></H1></CENTER>
  +<PRE>  [Sun Jan 24 12:05:32 1999] [error] server reached MaxClients setting,
  +  consider raising the MaxClients setting
  +</PRE>
   <P>
  -See <A HREF="././modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  -
  -
  -
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -	     The <a href="http://www.modperl.com/">
  -	     <B>Writing Apache Modules with Perl and C</B></a>
  -	     book can be purchased online from <a
  -	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  -	     and <a
  -	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  -	     Amazon.com</a>.
  -
  -	     <HR>
  -
  -	     Your corrections of either technical or grammatical
  -	     errors are very welcome. You are encouraged to help me
  -	     to improve this guide.  If you have something to
  -	     contribute please <A
  -	     HREF="help.html#This_document_s_Author"> send it
  -	     directly to me</A>.
  -
  -	     <HR>
  -
  -	     [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]
  -
  -<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
  -<TR ALIGN=CENTER VALIGN=TOP>
  -  <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  -	     <HR>
  -  </TD>
  -</TR>
  -<TR ALIGN=CENTER VALIGN=TOP>
  -  <TD ALIGN=CENTER VALIGN=CENTER>
  -    <B>
  -      <FONT SIZE=-1>
  -	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/26/1999
  -      </FONT>
  -    </B>
  -  </TD>
  -
  -  <TD>
  -	     <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
  -  </TD>
  -
  -  <TD>
  -    <FONT SIZE=-2>
  -	     Use of the Camel for Perl is <BR>
  -	     a trademark of <A HREF="http://www.ora.com">O'Reilly &amp; Associates</A>,<BR>
  -             and is used by permission. 
  -    </FONT> 
  -  </TD>
  -</TR>
  -</TABLE></CENTER>
  -
  -</BODY>
  -</HTML>
  -	    
  -
  -<HR SIZE=6>
  -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  -<HTML>
  -<HEAD>
  -   <TITLE>mod_perl guide: Choosing the Right Strategy</TITLE>
  -   <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
  -   <META NAME="Author" CONTENT="Stas Bekman">
  -   <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  -   <META NAME="keywords" CONTENT="mod_perl modperl perl apache cgi webserver speed  fast guide mod_perl apache guide help info faq mod_perl installation cgi troubleshooting help no sex speedup free open source OSS mod_perl apache guide">
  -</HEAD>
  -     <LINK REL=STYLESHEET TYPE="text/css"
  -        HREF="style.css" TITLE="refstyle">
  -     <style type="text/css">
  -     <!-- 
  -        @import url(style.css);
  -     -->
  -     
  -     </style>
  -<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
  -<A NAME="toc"></A>
  -<H1 ALIGN=CENTER>
  -<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
  -<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Choosing the Right Strategy</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  -<UL>
  -
  -	<LI><A HREF="#Do_it_like_me_">Do it like me?!</A>
  -	<LI><A HREF="#mod_perl_Deployment_Overview">mod_perl Deployment Overview</A>
  -	<LI><A HREF="#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
  -	<LI><A HREF="#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl-enabled Apache Servers</A>
  -	<LI><A HREF="#One_light_non_Apache_and_One_mod">One light non-Apache and One mod_perl enabled Apache Servers</A>
  -	<LI><A HREF="#Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A>
  -	<LI><A HREF="#The_Squid_Server">The Squid Server</A>
  -	<LI><A HREF="#An_Apache_s_mod_proxy">An Apache's mod_proxy</A>
  -</UL>
  -<!-- INDEX END -->
  -
  -<HR>
  -
  -	     The <a href="http://www.modperl.com/">
  -	     <B>Writing Apache Modules with Perl and C</B></a>
  -	     book can be purchased online from <a
  -	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  -	     and <a
  -	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  -	     Amazon.com</a>.
  -
  -	     <HR>
  +There is no problem -- any connection attempts over the <CODE>MaxClients</CODE>
  +limit will normally be queued, up to a number based on the
  +<CODE>ListenBacklog</CODE> directive. Once a child process is freed at the end of a different request,
  +the connection will then be served.
   
  -	       Your corrections of either technical or grammatical
  -	       errors are very welcome. You are encouraged to help me
  -	       to improve this guide.  If you have something to
  -	       contribute please <A
  -	       HREF="help.html#This_document_s_Author"> send it
  -	       directly to me</A>.
  +<P>
  +But it <STRONG>is an error</STRONG> because clients are being put in the queue rather than getting served at
  +once, despite the fact that they do not get an error response. The error
  +can be allowed to persist to balance available system resources and
  +response time, but sooner or later you will need to get more RAM so you can
  +start more children. The best approach is to try not to have this condition
  +reached at all, and if reach it often you should start to worry about it.
   
  -	       <HR>
  +<P>
  +It's important to understand how much real memory a child occupies. Your
  +children can share the memory between them (when OS supports that and you
  +take action to allow the sharing happen - See
  +<A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>). If this is the case, chances are that your <CODE>MaxClients</CODE> can be even higher. But it seems that it's not so simple to calculate the
  +absolute number. (If you come up with solution please let us know!). If the
  +shared memory was of the same size through the child's life, we could
  +derive a much better formula:
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Do_it_like_me_">Do it like me?!</A></H1></CENTER>
  +<PRE>               Total_RAM + Shared_RAM_per_Child * MaxClients
  +  MaxClients = ---------------------------------------------
  +                        Max_Process_Size - 1
  +</PRE>
   <P>
  -There is no such a thing as a single <STRONG>RIGHT</STRONG> strategy in web server business, though there are many wrong ones. Never
  -believe a person who says: <EM>"Do it this way, this is the best!"</EM>. As the old saying goes:
  -<EM>"Trust but verify"</EM>. There are too many technologies out there to choose from, and it would
  -take an enormous investment of time and money to try to validate each one
  -before deciding which is the best choice for your situation. Keeping this
  -idea in mind, I will present some different combinations of mod_perl and
  -other technologies or just standalone mod_perl. I'll describe how these
  -things work together, and offer my opinions on the pros and cons of each,
  -the relative degree of difficulty in installing and maintaining them, some
  -hints on approaches that should be used and things to avoid.
  +which is:
   
   <P>
  -To be clear, I will not address all technologies and tools, but limit this
  -discussion to those complementing mod_perl.
  -
  +<PRE>                    Total_RAM - Max_Process_Size
  +  MaxClients = ---------------------------------------
  +               Max_Process_Size - Shared_RAM_per_Child
  +</PRE>
   <P>
  -Please let me stress it again: <STRONG>DO NOT</STRONG> blindly copy someone's setup and hope for a good result. Choose what is
  -best for your situation -- it might take <STRONG>some</STRONG> effort to find it out.
  +Let's roll some calculations:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_Deployment_Overview">mod_perl Deployment Overview</A></H1></CENTER>
  +<PRE>  Total_RAM            = 500Mb
  +  Max_Process_Size     =  10Mb
  +  Shared_RAM_per_Child =   4Mb
  +</PRE>
   <P>
  -There are several different ways to build, configure and deploy your
  -mod_perl enabled server. Some of them are:
  -
  -<OL>
  -<P><LI>
  +<PRE>              500 - 10
  + MaxClients = --------- = 81
  +               10 - 4
  +</PRE>
   <P>
  -Having one binary and one config file (one big binary for mod_perl).
  +With no sharing in place
   
  -<P><LI>
   <P>
  -Having two binaries and two config files (one big binary for mod_perl and
  -one small for static objects like images.)
  -
  -<P><LI>
  +<PRE>                 500
  + MaxClients = --------- = 50
  +                 10
  +</PRE>
   <P>
  -Having one DSO-style binary, mod_perl loadable object and two config files
  -(Dynamic linking lets you compile once and have a big and a small binary in
  -memory BUT you have to deal with a freshly made solution that has weak
  -documentation and is still subject to change and is rather more complex.)
  +With sharing in place you can have 60% more servers without purchasing more
  +RAM, if you improve and keep the sharing level, let's say:
   
  -<P><LI>
   <P>
  -Any of the above plus a reverse proxy server in http accelerator mode.
  -
  -</OL>
  +<PRE>  Total_RAM            = 500Mb
  +  Max_Process_Size     =  10Mb
  +  Shared_RAM_per_Child =   8Mb
  +</PRE>
   <P>
  -If you are a newbie, I would recommend that you start with the first option
  -and work on getting your feet wet with apache and mod_perl. Later, you can
  -decide whether to move to the second one which allows better tuning at the
  -expense of more complicated administration, or to the third option -- the
  -more state-of-the-art-yet-suspiciously-new DSO system, or to the fourth
  -option which gives you even more power.
  -
  -<OL>
  -<P><LI>
  +<PRE>              500 - 10
  + MaxClients = --------- = 245
  +               10 - 8
  +</PRE>
   <P>
  -The first option will kill your production site if you serve a lot of
  -static data with ~2-12 MB webserver processes. On the other hand, while
  -testing you will have no other server interaction to mask or add to your
  -errors.
  +390% more servers!!! You've got the point :)
   
  -<P><LI>
   <P>
  -The second option allows you to seriously tune the two servers for maximum
  -performance. On the other hand you have to deal with proxying or fancy site
  -design to keep the two servers in synchronization. In this configuration,
  -you also need to choose between running the two servers on multiple ports,
  -multiple IPs, etc... This adds the burden of administrating more than one
  -server.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A></H2></CENTER>
  +<P>
  +The <CODE>MaxRequestsPerChild</CODE> directive sets the limit on the number of requests that an individual child
  +server process will handle. After
  +<CODE>MaxRequestsPerChild</CODE> requests, the child process will die. If
  +<CODE>MaxRequestsPerChild</CODE> is 0, then the process will live forever.
   
  -<P><LI>
   <P>
  -The third option (DSO) -- as mentioned above -- means playing with the
  -bleeding edge. In addition <CODE>mod_so</CODE> (the DSO module) adds size and complexity to your binaries. With DSO,
  -modules can be added and removed without recompiling the server, and
  -modules are even shared among multiple servers. Again, it is bleeding edge
  -and still somewhat platform specific, but your mileage may vary. See <A HREF="././scenario.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>.
  +Setting <CODE>MaxRequestsPerChild</CODE> to a non-zero limit has two beneficial effects: it solves memory leakages
  +and helps reduce the number of processes when the server load reduces.
   
  -<P><LI>
   <P>
  -The fourth option (proxy in http accelerator mode), once correctly
  -configured and tuned, improves the performance of any of the above three
  -options by caching and buffering page results.
  +The first reason is the most crucial for mod_perl, since sloppy programming
  +will cause a child process to consume more memory after each request. If
  +left unbounded, then after a certain number of requests the children will
  +use up all the available memory and leave the server to die from memory
  +starvation. Note, that sometimes standard system libraries leak memory too,
  +especially on OSes with bad memory management (e.g. Solaris 2.5 on x86
  +arch). If this is your case you can set <CODE>MaxRequestsPerChild</CODE> to a small number, which will allow the system to reclaim the memory,
  +greedy child process consumed, when it exits after <CODE>MaxRequestsPerChild</CODE> requests. But beware -- if you set this number too low, you will loose a
  +fracture of the speed bonus you receive with mod_perl. Consider using <CODE>Apache::PerlRun</CODE> if this is the case. Also setting <CODE>MaxSpareServers</CODE> to a number close to
  +<CODE>MaxClients</CODE>, will improve the response time (but your parent process will be busy
  +respawning new children all the time!)
   
  -</OL>
   <P>
  -The rest of this chapter discusses the pros and the cons of each of these
  -presented configurations.  <A HREF="././scenario.html#">Real World Scenarios Implementaion</A> describes the implementation techniques of these schemas.
  +Another approach is to use <CODE>Apache::SizeLimit</CODE> (See <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>). By using this module, you should be able to discontinue using the
  +<CODE>MaxRequestsPerChild</CODE>, although for some folks, using both in combination does the job.
  +
  +<P>
  +See also <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A> and
  +<A HREF="././performance.html#Sharing_Memory">Sharing Memory</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></CENTER>
  +<CENTER><H2><A NAME="Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A></H2></CENTER>
   <P>
  -The first approach is to implement a straightforward mod_perl server. Just
  -take your plain apache server and add mod_perl, like you add any other
  -apache module. You continue to run it at the port it was running before.
  -You probably want to try this before you proceed to more sophisticated and
  -complex techniques.
  +With mod_perl enabled, it might take as much as 30 seconds from the time
  +you start the server until it is ready to serve incoming requests. This
  +delay depends on the OS, the number of preloaded modules and the process
  +load of the machine. So it's best to set
  +<CODE>StartServers</CODE> and <CODE>MinSpareServers</CODE> to high numbers, so that if you get a high load just after the server has
  +been restarted, the fresh servers will be ready to serve requests
  +immediately. With mod_perl, it's usually a good idea to raise all 3
  +variables higher than normal. In order to maximize the benefits of
  +mod_perl, you don't want to kill servers when they are idle, rather you
  +want them to stay up and available to immediately handle new requests. I
  +think an ideal configuration is to set <CODE>MinSpareServers</CODE> and <CODE>MaxSpareServers</CODE> to similar values, maybe even the same. Having the <CODE>MaxSpareServers</CODE>
  +close to <CODE>MaxClients</CODE> will completely use all of your resources (if
  +<CODE>MaxClients</CODE> has been chosen to take the full advantage of the resources), but it'll
  +make sure that at any given moment your system will be capable of
  +responding to requests with the maximum speed (given that number of
  +concurrent requests is not higher than
  +<CODE>MaxClients</CODE>.)
   
   <P>
  -The advantages:
  +Let's try some numbers. For a heavily loaded web site and a dedicated
  +machine I would think of (note 400Mb is just for example):
   
  -<UL>
  -<P><LI>
   <P>
  -Simplicity. You just follow the installation instructions, configure it,
  -restart the server and you are done.
  -
  -<P><LI>
  +<PRE>  Available to webserver RAM:   400Mb
  +  Child's memory size bounded:  10Mb
  +  MaxClients:                   400/10 = 40 (larger with mem sharing)
  +  StartServers:                 20
  +  MinSpareServers:              20
  +  MaxSpareServers:              35
  +</PRE>
   <P>
  -No network changes. You do not have to worry about using additional ports
  -as we will see later.
  +However if I want to use the server for many other tasks, but make it
  +capable of handling a high load, I'd think of:
   
  -<P><LI>
   <P>
  -Speed. You get a very fast server, you see an enormous speedup from the
  -first moment you start to use it.
  -
  -</UL>
  +<PRE>  Available to webserver RAM:   400Mb
  +  Child's memory size bounded:  10Mb
  +  MaxClients:                   400/10 = 40
  +  StartServers:                 5
  +  MinSpareServers:              5
  +  MaxSpareServers:              10
  +</PRE>
   <P>
  -The disadvantages:
  +(These numbers are taken off the top of my head, and it shouldn't be used
  +as a rule, but rather as examples to show you some possible scenarios. Use
  +this information wisely!)
   
  -<UL>
  -<P><LI>
   <P>
  -The process size of a mod_perl-enabled Apache server is huge (starting from
  -4Mb at startup and growing to 10Mb and more, depending on how you use it)
  -compared to the typical plain Apache. Of course if memory sharing is in
  -place -- RAM requirements will be smaller.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A></H2></CENTER>
   <P>
  -You probably have a few tens of children processes. The additional memory
  -requirements add up in direct relation to the number of children processes.
  -Your memory demands are growing by an order of magnitude, but this is the
  -price you pay for the additional performance boost of mod_perl. With memory
  -prices so cheap nowadays, the additional cost is low -- especially when you
  -consider the dramatic performance boost mod_perl gives to your services
  -with every 100Mb of RAM you add.
  +OK, we've run various benchmarks -- let's summarize the conclusions:
   
  +<UL>
  +<P><LI><STRONG><A NAME="item_MaxRequestsPerChild">MaxRequestsPerChild</A></STRONG>
   <P>
  -While you will be happy to have these monster processes serving your
  -scripts with monster speed, you should be very worried about having them
  -serve static objects such as images and html files. Each static request
  -served by a mod_perl-enabled server means another large process running,
  -competing for system resources such as memory and CPU cycles. The real
  -overhead depends on static objects request rate. Remember that if your
  -mod_perl code produces HTML code which includes images, each one will turn
  -into another static object request. Having another plain webserver to serve
  -the static objects solves this not pleasant obstacle. Having a proxy server
  -as a front end, caching the static objects and freeing the mod_perl
  -processes from this burden is another solution. We will discuss both below.
  +If your scripts are clean and don't leak memory, set this variable to a
  +number as large as possible (10000?). If you use
  +<CODE>Apache::SizeLimit</CODE>, you can set this parameter to 0 (equal to infinity). You will want this
  +parameter to be smaller if your code becomes unshared over the process'
  +life.
   
  -<P><LI>
  +<P><LI><STRONG><A NAME="item_StartServers">StartServers</A></STRONG>
   <P>
  -Another drawback of this approach is that when serving output to a client
  -with a slow connection, the huge mod_perl-enabled server process (with all
  -of its system resources) will be tied up until the response is completely
  -written to the client. While it might take a few milliseconds for your
  -script to complete the request, there is a chance it will be still busy for
  -some number of seconds or even minutes if the request is from a slow
  -connection client. As in the previous drawback, a proxy solution can solve
  -this problem. More on proxies later.
  +If you keep a small number of servers active most of the time, keep this
  +number low. Especially if <CODE>MaxSpareServers</CODE> is low as it'll kill the just loaded servers before they were utilized at
  +all (if there is no load). If your service is heavily loaded, make this
  +number close to
  +<CODE>MaxClients</CODE> (and keep <CODE>MaxSpareServers</CODE> equal to <CODE>MaxClients</CODE> as well.)
   
  +<P><LI><STRONG><A NAME="item_MinSpareServers">MinSpareServers</A></STRONG>
   <P>
  -Proxying dynamic content is not going to help much if all the clients are
  -on a fast local net (for example, if you are administering an Intranet.) On
  -the contrary, it can decrease performance. Still, remember that some of
  -your Intranet users might work from home through the slow modem links.
  +If your server performs other work besides web serving, make this low so
  +the memory of unused children will be freed when there is no big load. If
  +your server's load varies (you get loads in bursts) and you want fast
  +response for all clients at any time, you will want to make it high, so
  +that new children will be respawned in advance and be waiting to handle
  +bursts of requests.
   
  -</UL>
  +<P><LI><STRONG><A NAME="item_MaxSpareServers">MaxSpareServers</A></STRONG>
   <P>
  -If you are new to mod_perl, this is probably the best way to get yourself
  -started.
  +The logic is the same as of <CODE>MinSpareServers</CODE> - low if you need the machine for other tasks, high if it's a dedicated web
  +host and you want a minimal response delay.
   
  +<P><LI><STRONG><A NAME="item_MaxClients">MaxClients</A></STRONG>
   <P>
  -And of course, if your site is serving only mod_perl scripts (close to zero
  -static objects, like images), this might be the perfect choice for you!
  +Not too low, so you don't get into a situation where clients are waiting
  +for the server to start serving them (they might wait, but not for too
  +long). Do not set it too high, since if you get a high load and all
  +requests will be immediately granted and served, your CPU will have a hard
  +time keeping up, and if the child's size * number of running children is
  +larger than the total available RAM, your server will start swapping (which
  +will slow down everything, which in turn will make things even more slower,
  +until eventually your machine will die). It's important that you take pains
  +to ensure that swapping does not normally happen. Swap space is an
  +emergency pool, not a resource to be used on a consistent basis. If you are
  +low on memory and you badly need it - buy it, memory is amazingly cheap
  +these days. 
   
   <P>
  -For implementation notes see : <A HREF="././scenario.html#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A>
  -
  -
  +But based on the test I conducted above, even if you have plenty of memory
  +like I have (1Gb), increasing <CODE>MaxClients</CODE> sometimes will give you no speedup. The more clients are running, the more
  +CPU time will be required, the less CPU time slices each process will
  +receive. The response latency (the time to respond to a request) will grow,
  +so you won't see the expected improvement. The best approach is to find the
  +minimum requirement for your kind of service and the maximum capability of
  +your machine. Then start at the minimum and test like I did, successively
  +raising this parameter until you find the point on the curve of the graph
  +of the latency or/and throughput where the improvement becomes smaller.
  +Stop there and use it. Of course when you use these parameters in
  +production server, you will have the ability to tune them more precisely,
  +since then you will see the real numbers. Also don't forget that if you add
  +more scripts, or just modify the running ones -- most probably that the
  +parameters need to be recalculated, since the processes will grow in size
  +as you compile in more code.
   
  +</UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl-enabled Apache Servers</A></H1></CENTER>
  +<CENTER><H1><A NAME="Persistent_DB_Connections">Persistent DB Connections</A></H1></CENTER>
   <P>
  -As I have mentioned before, when running scripts under mod_perl, you will
  -notice that the httpd processes consume a huge amount of virtual memory,
  -from 5Mb to 15Mb and even more. That is the price you pay for the enormous
  -speed improvements under mod_perl. (Again -- shared memory keeps the real
  -memory that is being used much smaller :)
  +Another popular use of mod_perl is to take advantage of its ability to
  +maintain persistent open database connections. The basic approach is as
  +follows:
   
   <P>
  -Using these large processes to serve static objects like images and html
  -documents is overkill. A better approach is to run two servers: a very
  -light, plain apache server to serve static objects and a heavier
  -mod_perl-enabled apache server to serve requests for dynamic (generated)
  -objects (aka CGI).
  -
  +<PRE>  # Apache::Registry script
  +  -------------------------
  +  use strict;
  +  use vars qw($dbh);
  +  
  +  $dbh ||= SomeDbPackage-&gt;connect(...);
  +</PRE>
   <P>
  -From here on, I will refer to these two servers as <STRONG>httpd_docs</STRONG>
  -(vanilla apache) and <STRONG>httpd_perl</STRONG> (mod_perl enabled apache).
  +Since <CODE>$dbh</CODE> is a global variable for the child, once the child has opened the
  +connection it will use it over and over again, unless you perform <CODE>disconnect()</CODE>.
   
   <P>
  -The advantages:
  +Be careful to use different names for handlers if you open connection to
  +different databases!
   
  -<UL>
  -<P><LI>
   <P>
  -The heavy mod_perl processes serve only dynamic requests, which allows the
  -deployment of fewer of these large servers.
  +<CODE>Apache::DBI</CODE> allows you to make a persistent database connection. With this module
  +enabled, every <CODE>connect()</CODE> request to the plain <CODE>DBI</CODE> module will be forwarded to the <CODE>Apache::DBI</CODE>
  +module. This looks to see whether a database handle from a previous
  +<CODE>connect()</CODE> request has already been opened, and if this handle is still valid using
  +the ping method. If these two conditions are fulfilled it just returns the
  +database handle. If there is no appropriate database handle or if the ping
  +method fails, a new connection is established and the handle is stored for
  +later re-use. <STRONG>There is no need to delete the <CODE>disconnect()</CODE> statements
  +from your code</STRONG>. They will not do a thing, as the <CODE>Apache::DBI</CODE>
  +module overloads the <CODE>disconnect()</CODE> method with a NOP. On child's exit there is no explicit disconnect, the
  +child dies and so does the database connection. You may leave the <CODE>use DBI;</CODE> statement inside the scripts as well.
   
  -<P><LI>
   <P>
  -<CODE>MaxClients</CODE>, <CODE>MaxRequestsPerChild</CODE> and related parameters can now be optimally tuned for both <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE> servers, something we could not do before. This allows us to fine tune the
  -memory usage and get a better server performance.
  +The usage is simple -- add to <CODE>httpd.conf</CODE>:
   
   <P>
  -Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
  -
  -</UL>
  +<PRE>  PerlModule Apache::DBI
  +</PRE>
   <P>
  -An <STRONG>important</STRONG> note: When user browses static pages and the base URL in the <STRONG>Location</STRONG> window points to the static server, for example
  -<CODE>http://www.nowhere.com/index.html</CODE> -- all relative URLs (e.g. <CODE>&lt;A
  -HREF=&quot;/main/download.html&quot;</CODE>&gt;) are being served by the light plain apache server. But this is not
  -the case with dynamically generated pages. For example when the base URL in
  -the <STRONG>Location</STRONG> window points to the dynamic server -- (e.g. <CODE>http://www.nowhere.com:8080/perl/index.pl</CODE>) all relative URLs in the dynamically generated HTML will be served by the
  -heavy mod_perl processes. You must use a fully qualified URLs and not the
  -relative ones! <CODE>http://www.nowhere.com/icons/arrow.gif</CODE> is a full URL, while
  -<CODE>/icons/arrow.gif</CODE> is a relative one. Using <CODE>&lt;BASE
  -HREF=&quot;http://www.nowhere.com/&quot;</CODE>&gt; in the generated HTML is another way to handle this problem. Also the <CODE>httpd_perl</CODE> server could rewrite the requests back to <CODE>httpd_docs</CODE> (much slower) and you still need an attention of the heavy servers. This is
  -not an issue if you hide the internal port implementations, so client sees
  -only one server running on port <CODE>80</CODE>. (See <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>)
  +It is important, to load this module before any other <CODE>DBI</CODE>,
  +<CODE>DBD::*</CODE> and <CODE>ApacheDBI*</CODE> modules!
   
   <P>
  -The disadvantages:
  -
  -<UL>
  -<P><LI>
  +<PRE>  db.pl
  +  ------------
  +  use DBI;
  +  use strict;
  +  
  +  my $dbh = DBI-&gt;connect( 'DBI:mysql:database', 'user', 'password',
  +                          { autocommit =&gt; 0 }
  +                        ) || die $DBI::errstr;
  +  
  +  ...rest of the program
  +</PRE>
   <P>
  -An administration overhead.
  -
  -<UL>
  -<P><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Preopening_Connections_at_the_Ch">Preopening Connections at the Child Process' Fork Time</A></H2></CENTER>
   <P>
  -A need for two different sets of configuration, log and other files. We
  -need a special directory layout to manage these. While some directories can
  -be shared between the two servers (like the <CODE>include</CODE>
  -directory, containing the apache include files -- assuming that both are
  -built from the same source distribution), most of them should be separated
  -and the configuration files updated to reflect the changes.
  +If you use <CODE>DBI</CODE> for DB connections, and you use <CODE>Apache::DBI</CODE> to make them persistent, it also allows you to preopen connections to DB
  +for each child with <CODE>connect_on_init()</CODE> method, thus saving up a connection overhead on the very first request of
  +every child.
   
  -<P><LI>
   <P>
  -A need for two sets of controlling scripts (startup/shutdown) and
  -watchdogs.
  -
  -<P><LI>
  +<PRE>  use Apache::DBI ();
  +  Apache::DBI-&gt;connect_on_init(&quot;DBI:mysql:test&quot;,
  +                               &quot;login&quot;,
  +                               &quot;passwd&quot;,
  +                               {
  +                                RaiseError =&gt; 1,
  +                                PrintError =&gt; 0,
  +                                AutoCommit =&gt; 1,
  +                               }
  +                              );
  +</PRE>
   <P>
  -If you are processing log files, now you probably will have to merge the
  -two separate log files into one before processing them.
  +This can be used as a simple way to have apache children establish
  +connections on server startup. This call should be in a startup file
  +<CODE>require()d</CODE> by <CODE>PerlRequire</CODE> or inside &lt;Perl&gt; section. It will establish a connection when a child is started in
  +that child process. See the <CODE>Apache::DBI</CODE> manpage to see the requirements for this method.
   
  -</UL>
  -<P><LI>
   <P>
  -We still have the problem of a mod_perl process spending its precious time
  -serving slow clients, when the processing portion of the request was
  -completed long time ago, exactly as in the one server approach. Deploying a
  -proxy solves this, and will be covered in the next sections.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Caching_prepare_statements">Caching prepare() statements</A></H2></CENTER>
   <P>
  -As with only one server approach, this is not a major disadvantage if you
  -are on a fast local Intranet. It is likely that you do not want a buffering
  -server in this case.
  +You can also benefit from persistent connections by replacing
  +<CODE>prepare()</CODE> with <CODE>prepare_cached().</CODE> That way you
  +will always be sure that you have a good statement handle and you will get
  +some caching benefit. The downside is that you are going to pay for DBI to
  +parse your SQL and do a cache lookup every time you call
  +<CODE>prepare_cached().</CODE>
   
  -</UL>
   <P>
  -Before you go on with this solution you really want to look at the
  -<A HREF="././strategy.html#Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A> section.
  +Be warned that some databases doesn't support caches of prepared plans.
  +(e.g PostgreSQL and Sybase). Though with Sybase you could open multiple
  +connections to achieve the same result (at the risk of getting deadlocks
  +depending on what you are trying to do!)
   
   <P>
  -For implementation notes see : <A HREF="././scenario.html#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A>
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Handling_Timeouts">Handling Timeouts</A></H2></CENTER>
  +<P>
  +Another problem is with timeouts: some databases disconnect the client
  +after a certain time of inactivity. This problem is known as <STRONG>morning
  +bug</STRONG>. The <CODE>ping()</CODE> method ensures that this will not happen. Some
  +<CODE>DBD</CODE> drivers don't have this method, check the <CODE>Apache::DBI</CODE>
  +manpage to see how to write a <CODE>ping()</CODE> method.
   
  +<P>
  +Another approach is to change the client's connection timeout. For mysql
  +users, starting from mysql-3.22.x you can set a <CODE>wait_timeout</CODE>
  +option at mysqld server startup to change the default value. Setting it to
  +36 hours probably would fix the timeout problem.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="One_light_non_Apache_and_One_mod">One light non-Apache and One mod_perl enabled Apache Servers</A></H1></CENTER>
  +<CENTER><H1><A NAME="Jeff_s_guide_to_mod_perl_databas">Jeff's guide to mod_perl database performance</A></H1></CENTER>
   <P>
  -If the only requirement from the light server is for it to serve static
  -objects, then you can get away with non-apache servers having an even
  -smaller memory footprint. <CODE>thttpd</CODE> has been reported to be about 5 times faster then apache (especially under
  -a heavy load), since it is very simple and uses almost no memory (260k) and
  -does not spawn child processes.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Analysis_of_the_Problem">Analysis of the Problem</A></H2></CENTER>
   <P>
  -Meta: Hey, No personal experience here, only rumours. Please let me know if
  -I have missed some pros/cons here. Thanks!
  +A common web application architecture is one or more application servers
  +which handle requests from client browsers by consulting one or more
  +database servers and performing a transform on the data. When an
  +application must consult the database on every request, the interaction
  +with the database server becomes the central performance issue. Spending a
  +bit of time optimizing your database access can result in significant
  +application performance improvements. In this analysis, a system using
  +Apache, mod_perl, <CODE>DBI</CODE>, and Oracle will be considered. The application server uses Apache and
  +mod_perl to service client requests, and <CODE>DBI</CODE> to communicate with a remote Oracle database.
   
   <P>
  -The Advantages:
  +In the course of servicing a typical client request, the application server
  +must retrieve some data from the database and execute a stored procedure.
  +There are several steps that need to be done to complete the request:
   
  -<UL>
  -<P><LI>
   <P>
  -All the advantages of the 2 servers scenario.
  +<PRE> 1: Connect to the database server
  + 2: Prepare a SQL SELECT statement
  + 3: Execute the SELECT statement
  + 4: Retrieve the results of the SELECT statement
  + 5: Release the SELECT statement handle
  + 6: Prepare a PL/SQL stored procedure call
  + 7: Execute the stored procedure
  + 8: Release the stored procedure statement handle
  + 9: Commit or rollback
  + 10: Disconnect from the database server
  +</PRE>
  +<P>
  +In this document, an application will be described which achieves maximum
  +performance by eliminating some of the steps above and optimizing others.
   
  -<P><LI>
   <P>
  -More memory saving. Apache is about 4 times bigger then <STRONG>thttpd</STRONG>, if you spawn 30 children you use about 30M of memory, while <STRONG>thttpd</STRONG>
  -uses only 260k - 100 times less! You could use the saved 30M to run more
  -mod_perl servers.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Optimizing_Database_Connections">Optimizing Database Connections</A></H2></CENTER>
  +<P>
  +A naive implementation would perform steps 1 through 10 from above on every
  +request. A portion of the source code might look like this:
   
   <P>
  -Note that this is not true if your OS supports memory sharing and you
  -configured apache to use it (it is a DSO approach. There is no memory
  -sharing if apache modules are being statically compiled into httpd). If you
  -do allow memory sharing -- 30 light apache servers ought to use about 3-4Mb
  -only, because most of it will be shared. If this is the case -- the save
  -ups are much smaller with <STRONG>thttpd</STRONG>.
  +<PRE>  # ...
  +  my $dbh = DBI-&gt;connect('dbi:Oracle:host', 'user', 'pass')
  +        || die $DBI::errstr;
  +  
  +  my $baz = $r-&gt;param('baz');
  +  
  +  eval {
  +        my $sth = $dbh-&gt;prepare(qq{
  +                SELECT foo 
  +                  FROM bar 
  +                 WHERE baz = $baz
  +        });
  +        $sth-&gt;execute;
  +  
  +        while (my @row = $sth-&gt;fetchrow_array) {
  +                # do HTML stuff
  +        }
  +        
  +        $sth-&gt;finish;
  +  
  +        my $sph = $dbh-&gt;prepare(qq{
  +                BEGIN
  +                        my_procedure(
  +                                arg_in =&gt; $baz
  +                        );
  +                END;
  +        });
  +        $sph-&gt;execute;
  +        $sph-&gt;finish;
  +        
  +        $dbh-&gt;commit;
  +  };
  +  if ($@) {
  +        $dbh-&gt;rollback;
  +  }
  +  
  +  $dbh-&gt;disconnect;
  +  # ...
  +</PRE>
  +<P>
  +In practice, such an implementation would have hideous performance
  +problems. The majority of the execution time of this program would likely
  +be spent connecting to the database. An examination shows that step 1 is
  +comprised of many smaller steps:
   
  -<P><LI>
   <P>
  -Reported to be about 5 times faster then plain apache serving static
  -objects.
  +<PRE> 1: Connect to the database server
  + 1a: Build client-side data structures for an Oracle connection
  + 1b: Look up the server's alias in a file
  + 1c: Look up the server's hostname
  + 1d: Build a socket to the server
  + 1e: Build server-side data structures for this connection
  +</PRE>
  +<P>
  +The naive implementation waits for all of these steps to happen, and then
  +throws away the database connection when it is done! This is obviously
  +wasteful, and easily rectified. The best solution is to hoist the database
  +connection step out of the per-request lifecycle so that more than one
  +request can use the same database connection. This can be done by
  +connecting to the database server once, and then not disconnecting until
  +the Apache child process exits. The
  +<CODE>Apache::DBI</CODE> module does this transparently and automatically with little effort on the
  +part of the programmer.
   
  -</UL>
   <P>
  -The Disadvantages:
  +<CODE>Apache::DBI</CODE> intercepts calls to <CODE>DBI</CODE>'s connect and disconnect methods and replaces them with its own.  <CODE>Apache::DBI</CODE> caches database connections when they are first opened, and it ignores
  +disconnect commands. When an application tries to connect to the same
  +database, <CODE>Apache::DBI</CODE> returns a cached connection, thus saving the significant time penalty of
  +repeatedly connecting to the database. You will find a full treatment of <CODE>Apache::DBI</CODE> at <A HREF="././performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
   
  -<UL>
  -<P><LI>
  +
  +
   <P>
  -Lacks some of apache's features, like access control, error redirection,
  -customizable log file formats, and so on.
  +When <CODE>Apache::DBI</CODE> is in use, none of the code in the example needs to change. The code is
  +upgraded from naive to respectable with the use of a simple module! The
  +first and biggest database performance problem is quickly dispensed with.
   
  -</UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A></H1></CENTER>
  +<CENTER><H2><A NAME="Utilizing_the_Database_Server_s_">Utilizing the Database Server's Cache</A></H2></CENTER>
   <P>
  -At the beginning there were 2 servers: one - plain apache server, which was <STRONG>very light</STRONG>, and configured to serve static objects, the other -- mod_perl enabled,
  -which was <STRONG>very heavy</STRONG> and aimed to serve mod_perl scripts. We named them: <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE>
  -appropriately. The two servers coexisted at the same <CODE>IP(DNS)</CODE>
  -by listening to different ports: 80 -- for <CODE>httpd_docs</CODE>
  -(e.g. <A
  -HREF="http://www.nowhere.com/images/test.gif">http://www.nowhere.com/images/test.gif</A>
  -) and 8080 -- for
  -<CODE>httpd_perl</CODE> (e.g. <A
  -HREF="http://www.nowhere.com:8080/perl/test.pl">http://www.nowhere.com:8080/perl/test.pl</A>
  -). Note that I did not write <A
  -HREF="http://www.nowhere.com:80">http://www.nowhere.com:80</A> for the
  -first example, since port 80 is a default http port. (Later on, I will be
  -moving the
  -<CODE>httpd_docs</CODE> server to port 81.)
  +Most database servers, including Oracle, utilize a cache to improve the
  +performance of recently seen queries. The cache is keyed on the SQL
  +statement. If a statement is identical to a previously seen statement, the
  +execution plan for the previous statement is reused. This can be a
  +considerable improvement over building a new statement execution plan.
   
   <P>
  -Now I am going to convince you that you <STRONG>want</STRONG> to use a proxy server (in the http accelerator mode). The advantages are:
  +Our respectable implementation from the last section is not making use of
  +this caching ability. It is preparing the statement: 
   
  -<UL>
  -<P><LI>
   <P>
  -Allow serving of static objects from the proxy's cache (objects that
  -previously were entirely served by the <CODE>httpd_docs</CODE> server).
  +<PRE>  SELECT foo FROM bar WHERE baz = $baz
  +</PRE>
  +<P>
  +The problem is that <CODE>$baz</CODE> is being read from an HTML form, and is therefore likely to change on every
  +request. When the database server sees this statement, it is going to look
  +like:
   
  -<P><LI>
   <P>
  -You get less I/O activity reading static objects from the disk (proxy
  -serves the most ``popular'' objects from the RAM memory - of course you
  -benefit more if you allow the proxy server to consume more RAM). Since you
  -do not wait for the I/O to be completed you are able to serve the static
  -objects much faster.
  +<PRE>  SELECT foo FROM bar WHERE baz = 1
  +</PRE>
  +<P>
  +and on the next request, the SQL will be:
   
  -<P><LI>
   <P>
  -The proxy server acts as a sort of output buffer for the dynamic content.
  -The mod_perl server sends the entire response to the proxy and is then free
  -to deal with other requests. The proxy server is responsible for sending
  -the response to the browser. So if the transfer is over a slow link, the
  -mod_perl server is not waiting around for the data to move.
  +<PRE>  SELECT foo FROM bar WHERE baz = 42
  +</PRE>
  +<P>
  +Since the statements are different, the database server will not be able to
  +reuse its execution plan, and will proceed to make another one. This
  +defeats the purpose of the SQL statement cache.
   
   <P>
  -Using numbers is always more convincing :) Let's take a user connected to
  -your site with 28.8 kbps (bps == bits/sec) modem. It means that the speed
  -of the user's link is 28.8/8 = 3.6 kbytes/sec. I assume an average
  -generated HTML page to be of 10kb (kb == kilobytes) and an average script
  -that generates this output in 0.5 secs. How much time will the server wait
  -before the user gets the whole output response? A simple calculation
  -reveals pretty scary numbers - it will have to wait for another 6 secs
  -(20kb/3.6kb), when it could serve another 12 (6/0.5) dynamic requests in
  -this time. This very simple example shows us that we need a twelve the
  -number of children running, which means you will need only one twelve of
  -the memory (which is not quite true because some parts of the code are
  -being shared). But you know that nowadays scripts return pages which
  -sometimes are being blown up with javascript code and similar, which makes
  -them of 100kb size and download time to be of... (This calculation is left
  -to you as an exercise :)
  +The application server needs to make sure that SQL statements which are the
  +same look the same. The way to achieve this is to use placeholders and
  +bound parameters. The placeholder is a blank in the SQL statement, which
  +tells the database server that the value will be filled in later. The bound
  +parameter is the value which is inserted into the blank before the
  +statement is executed.
   
   <P>
  -To make your estimation of download time numbers even worse, let me remind
  -you that many users like to open many browser windows and do many things at
  -once (download files and browse <STRONG>heavy</STRONG> sites). So the speed of 3.6kb/sec we were assuming before, may many times
  -be 5-10 times slower.
  +With placeholders, the SQL statement looks like: 
   
  -<P><LI>
   <P>
  -Also we are going to hide the details of the server's implementation. Users
  -will never see ports in the URLs (more on that topic later). And you can
  -have a few boxes serving the requests, and only one serving as a front end,
  -which spreads the jobs between the servers in a way you configured it too.
  -So you can actually put down one server down for upgrade, but end user will
  -never notice that because the front end server will dispatch the jobs to
  -other servers. (Of course this is a pretty big issue, and it would not be
  -discussed in the scope of this document)
  +<PRE>  SELECT foo FROM bar WHERE baz = :baz
  +</PRE>
  +<P>
  +Regardless of whether <CODE>baz</CODE> is 1 or 42, the SQL always looks the same, and the database server can
  +reuse its cached execution plan for this statement. This technique has
  +eliminated the execution plan generation penalty from the per-request
  +runtime. The potential performance improvement from this optimization could
  +range from modest to very significant.
   
  -<P><LI>
   <P>
  -For security reasons, using any httpd accelerator (or a proxy in httpd
  -accelerator mode) is essential because you do not let your internal server
  -get directly attacked by arbitrary packets from whomever. The httpd
  -accelerator and internal server communicate in expected HTTP requests. This
  -allows for only your public ``bastion'' accelerating www server to get
  -hosed in a successful attack, while leaving your internal data safe.
  +Here is the updated code fragment which employs this optimization:
   
  -</UL>
   <P>
  -The disadvantages are:
  +<PRE>  # ...
  +  my $dbh = DBI-&gt;connect('dbi:Oracle:host', 'user', 'pass')
  +        || die $DBI::errstr;
  +  
  +  my $baz = $r-&gt;param('baz');
  +  
  +  eval {
  +        my $sth = $dbh-&gt;prepare(qq{
  +                SELECT foo 
  +                  FROM bar 
  +                 WHERE baz = :baz
  +        });
  +        $sth-&gt;bind_param(':baz', $baz);
  +        $sth-&gt;execute;
  +  
  +        while (my @row = $sth-&gt;fetchrow_array) {
  +                # do HTML stuff
  +        }
  +        
  +        $sth-&gt;finish;
  +  
  +        my $sph = $dbh-&gt;prepare(qq{
  +                BEGIN
  +                        my_procedure(
  +                                arg_in =&gt; :baz
  +                        );
  +                END;
  +        });
  +        $sph-&gt;bind_param(':baz', $baz);
  +        $sph-&gt;execute;
  +        $sph-&gt;finish;
  +        
  +        $dbh-&gt;commit;
  +  };
  +  if ($@) {
  +        $dbh-&gt;rollback;
  +  }
  +  # ...
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Eliminating_SQL_Statement_Parsin">Eliminating SQL Statement Parsing</A></H2></CENTER>
  +<P>
  +The example program has certainly come a long way and the performance is
  +now probably much better than that of the first revision. However, there is
  +still more speed that can be wrung out of this server architecture. The
  +last bottleneck is in SQL statement parsing. Every time <CODE>DBI</CODE>'s <CODE>prepare()</CODE> method is called, <CODE>DBI</CODE> parses the SQL command looking for placeholder strings, and does some
  +housekeeping work. Worse, a context has to be built on the client and
  +server sides of the connection which the database will use to refer to the
  +statement. These things take time, and by eliminating these steps the time
  +can be saved.
   
  -<UL>
  -<P><LI>
   <P>
  -Of course there are drawbacks. Luckily, these are not functionality
  -drawbacks, but more of administration hassle. You add another daemon to
  -worry about, and while proxies are generally stable, you have to make sure
  -to prepare proper startup and shutdown scripts, which are being run at the
  -boot and reboot appropriately. Also, maybe a watchdog script running at the
  -crontab.
  +To get rid of the statement handle construction and statement parsing
  +penalties, we could use <CODE>DBI</CODE>'s <CODE>prepare_cached()</CODE> method. This method compares the SQL
  +statement to others that have already been executed. If there is a match,
  +the cached statement handle is returned. But the application server is
  +still spending time calling an object method (very expensive in Perl), and
  +doing a hash lookup. Both of these steps are unnecessary, since the SQL is
  +very likely to be static and known at compile time. The smart programmer
  +can take advantage of these two attributes to gain better database
  +performance. In this example, the database statements will be prepared
  +immediately after the connection to the database is made, and they will be
  +cached in package scalars to eliminate the method call.
   
  -<P><LI>
   <P>
  -Proxy servers can be configured to be light or heavy, the admin must decide
  -what gives the highest performance for his application. A proxy server like
  -squid is light in the concept of having only one process serving all
  -requests. But it can appear pretty heavy when it loads objects into memory
  -for faster service.
  +What is needed is a routine that will connect to the database and prepare
  +the statements. Since the statements are dependent upon the connection, the
  +integrity of the connection needs to be checked before using the
  +statements, and a reconnection should be attempted if needed. Since the
  +routine presented here does everything that
  +<CODE>Apache::DBI</CODE> does, it does not use <CODE>Apache::DBI</CODE> and therefore has the added benefit of eliminating a cache lookup on the
  +connection.
   
  -</UL>
   <P>
  -Have I succeeded in convincing you that you want the proxy server?
  +Here is an example of such a package:
   
   <P>
  -If you are on a local area network (LAN), then the big benefit of the proxy
  -buffering the output and feeding a slow client is gone. You are probably
  -better off sticking with a straight mod_perl server in this case.
  +<PRE>  package My::DB;
  +  
  +  use strict;
  +  use DBI;
  +  
  +  sub connect {
  +        if (defined $My::DB::conn) {
  +                eval {
  +                        $My::DB::conn-&gt;ping;
  +                };
  +                if (!$@) {
  +                        return $My::DB::conn;
  +                }
  +        }
  +  
  +        $My::DB::conn = DBI-&gt;connect(
  +                'dbi:Oracle:server', 'user', 'pass', {
  +                        PrintError =&gt; 1,
  +                        RaiseError =&gt; 1,
  +                        AutoCommit =&gt; 0
  +                }
  +        ) || die $DBI::errstr; #Assume application handles this
  +  
  +        $My::DB::select = $My::DB::conn-&gt;prepare(q{
  +                SELECT foo
  +                  FROM bar
  +                 WHERE baz = :baz
  +        });
  +        
  +        $My::DB::procedure = $My::DB::conn-&gt;prepare(q{
  +                BEGIN
  +                        my_procedure(
  +                                arg_in =&gt; :baz
  +                        );
  +                END;
  +        });
  +  
  +        return $My::DB::conn;
  +  }
  +  
  +  1;
  +</PRE>
  +<P>
  +Now the example program needs to be modified to use this package.
   
   <P>
  -As of this writing the two proxy implementations are known to be used in
  -bundle with mod_perl - <STRONG>squid</STRONG> proxy server and <STRONG>mod_proxy</STRONG> which is a part of the apache server. Let's compare the two of them.
  +<PRE>  # ...
  +  my $dbh = My::DB-&gt;connect;
  +  
  +  my $baz = $r-&gt;param('baz');
  +  
  +  eval {
  +        my $sth = $My::DB::select;
  +        $sth-&gt;bind_param(':baz', $baz);
  +        $sth-&gt;execute;
  +  
  +        while (my @row = $sth-&gt;fetchrow_array) {
  +                # do HTML stuff
  +        }
  +  
  +        my $sph = $My::DB::procedure;
  +        $sph-&gt;bind_param(':baz', $baz);
  +        $sph-&gt;execute;
  +         
  +        $dbh-&gt;commit;
  +  };
  +  if ($@) {
  +        $dbh-&gt;rollback;
  +  }
  +  # ...
  +</PRE>
  +<P>
  +Notice that several improvements have been made. Since the statement
  +handles have a longer life than the request, there is no need for each
  +request to prepare the statement, and no need to call the statement
  +handle's finish method. Since <CODE>Apache::DBI</CODE> and the <CODE>prepare_cached()</CODE> method are not used, no cache lookups
  +are needed.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="The_Squid_Server">The Squid Server</A></H1></CENTER>
  +<CENTER><H2><A NAME="Conclusion">Conclusion</A></H2></CENTER>
   <P>
  -The Advantages:
  +The number of steps needed to service the request in the example system has
  +been reduced significantly. In addition, the hidden cost of building and
  +tearing down statement handles and of creating query execution plans is
  +removed. Compare the new sequence with the original:
  +
  +<P>
  +<PRE> 1: Check connection to database
  + 2: Bind parameter to SQL SELECT statement
  + 3: Execute SELECT statement
  + 4: Fetch rows
  + 5: Bind parameters to PL/SQL stored procedure
  + 6: Execute PL/SQL stored procedure
  + 7: Commit or rollback
  +</PRE>
  +<P>
  +It is probably possible to optimize this example even further, but I have
  +not tried. It is very likely that the time could be better spent improving
  +your database indexing scheme or web server buffering and load balancing.
  +If there are any suggestions for further optimization of the
  +application-database interaction, please mail them to me at <A
  +HREF="mailto:jwb@cp.net.">jwb@cp.net.</A>
   
  -<UL>
  -<P><LI>
   <P>
  -Caching of static objects. So these are being served much faster assuming
  -that your cache size is big enough to keep the most requested objects in
  -the cache.
  +Jeffrey Baker, 4 October 1999
   
  -<P><LI>
   <P>
  -Buffering of dynamic content, by taking the burden of returning the content
  -generated by mod_perl servers to slow clients, thus freeing mod_perl
  -servers from waiting for the slow clients to download the data. Freed
  -servers immediately switch to serve other requests, thus your number of
  -required servers goes dramatically down.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</A></H1></CENTER>
  +<P>
  +As you know <CODE>local $|=1;</CODE> disables the buffering of the currently selected file handle (default is <CODE>STDOUT</CODE>). If you enable it,
  +<CODE>ap_rflush()</CODE> is called after each <CODE>print()</CODE>, unbuffering Apache's IO.
   
  -<P><LI>
   <P>
  -Non-linear URL space / server setup. You can use Squid to play some tricks
  -with the URL space and/or domain based virtual server support.
  +If you are using a _bad_ style in generating output, which consist of
  +multiple <CODE>print()</CODE> calls, or you just have too many of them, you will experience a degradation
  +in performance. The severity depends on the number of the calls you make.
   
  -</UL>
   <P>
  -The Disadvantages:
  +Many old CGIs were written in the style of:
   
  -<UL>
  -<P><LI>
   <P>
  -Proxying dynamic content is not going to help much if all the clients are
  -on a fast local net. Also, a message on the squid mailing list implied that
  -squid only buffers in 16k chunks so it would not allow a mod_perl to
  -complete immediately if the output is larger.
  +<PRE>  print &quot;&lt;BODY BGCOLOR=\&quot;black\&quot; TEXT=\&quot;white\&quot;&gt;&quot;;
  +  print &quot;&lt;H1&gt;&quot;;
  +  print &quot;Hello&quot;;
  +  print &quot;&lt;/H1&gt;&quot;;
  +  print &quot;&lt;A HREF=\&quot;foo.html\&quot;&gt; foo &lt;/A&gt;&quot;;
  +  print &quot;&lt;/BODY&gt;&quot;;
  +</PRE>
  +<P>
  +which reveals the following drawbacks: multiple <CODE>print()</CODE> calls - performance degradation with <CODE>$|=1</CODE>, backslashism which makes the code less readable and more difficult to
  +format the HTML to be easily readable as CGI's output. The code below
  +solves them all:
   
  -<P><LI>
   <P>
  -Speed. Squid is not very fast today when compared to plain file based web
  -servers available. Only if you are using a lot of dynamic features such as
  -mod_perl or similar speed is a reason to use Squid, and then only if the
  -application and server is designed with caching in mind.
  +<PRE>  print qq{
  +    &lt;BODY BGCOLOR=&quot;black&quot; TEXT=&quot;white&quot;&gt;
  +      &lt;H1&gt;
  +        Hello
  +      &lt;/H1&gt;
  +      &lt;A HREF=&quot;foo.html&quot;&gt; foo &lt;/A&gt;
  +    &lt;/BODY&gt;
  +  };
  +</PRE>
  +<P>
  +I guess you see the difference. Be careful though, when printing a
  +<CODE>&lt;HTML</CODE>&gt; tag. The correct way is:
   
  -<P><LI>
   <P>
  -Memory usage. Squid uses quite a bit of memory.
  +<PRE>  print qq{&lt;HTML&gt;
  +    &lt;HEAD&gt;&lt;/HEAD&gt;
  +    &lt;BODY&gt;
  +  }
  +</PRE>
  +<P>
  +If you try the following:
   
  -<P><LI>
   <P>
  -HTTP protocol level. Squid is pretty much a <CODE>HTTP/1.0</CODE> server, which seriously limits the deployment of <CODE>HTTP/1.1</CODE> features.
  +<PRE>  print qq{
  +    &lt;HTML&gt;
  +    &lt;HEAD&gt;&lt;/HEAD&gt;
  +    &lt;BODY&gt;
  +  }
  +</PRE>
  +<P>
  +Some older browsers might not accept the output as HTML, but rather print
  +it as a plain text, since they expect the first characters after the
  +headers and empty line to be <CODE>&lt;HTML</CODE>&gt; and not spaces and/or additional newline and then <CODE>&lt;HTML</CODE>&gt;. Even if it works with your browser, it might not work for others.
   
  -<P><LI>
   <P>
  -HTTP headers, dates and freshness. The squid server might give out ``old''
  -pages, confusing downstream/client caches. Also chances are that you will
  -be giving out stale pages. (You update the some documents on the site, but
  -squid will still serve the old ones.)
  +Now let's go back to the <CODE>$|=1</CODE> topic. I still disable buffering, for 2 reasons: I use few <CODE>print()</CODE> calls by printing out multiline HTML and not a line per <CODE>print()</CODE> and I want my users to see the output immediately. So if I am about to
  +produce the results of the DB query, which might take some time to
  +complete, I want users to get some titles ahead. This improves the
  +usability of my site. Recall yourself: What do you like better: getting the
  +output a bit slower, but steadily from the moment you've pressed the <STRONG>Submit</STRONG> button or having to watch the ``falling stars'' for awhile and then to
  +receive the whole output at once, even a few millisecs faster (if the
  +client (browser) did not time out till then).
   
  -<P><LI>
   <P>
  -Stability. Compared to plain web servers Squid is not the most stable.
  +An even better solution is to keep the buffering enabled, and use a Perl
  +API <CODE>rflush()</CODE> call to flush the buffers when wanted. This way you can aggregate in the
  +buffer the top of the page you are going to send to user, and flush it a
  +moment before you are going to do some lenghty operation, like DB query. So
  +you kill the two birds in one shoot: You show some of the data to the user
  +immediately, so user will feel that something is actually happening, and
  +you almost have no performance hit caused by disabled buffering.
   
  -</UL>
   <P>
  -The presented pros and cons lead to an idea, that probably you might want
  -squid more for its dynamic content buffering features, but only if your
  -server serves mostly dynamic requests. So in this situation it is better to
  -have a plain apache server serving static objects, and squid proxying the
  -mod_perl enabled server only. At least when performance is the goal.
  +<PRE>  use CGI ();
  +  my $r = shift;
  +  my $q = new CGI;
  +  print $q-&gt;header('text/html');
  +  print $q-&gt;start_html;
  +  print $q-&gt;p(&quot;Searching...Please wait&quot;);
  +  $r-&gt;rflush;
  +    # imitate a lenghty operation
  +  for (1..5) {
  +    sleep 1;
  +  }
  +  print $q-&gt;p(&quot;Done!&quot;);
  +</PRE>
  +<P>
  +<STRONG>Conclusion</STRONG>: Do not blindly follow suggestions, but think what is best for you in
  +every given case.
   
   <P>
  -For implementation details see: <A HREF="././scenario.html#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A> and
  -<A HREF="././scenario.html#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A></H1></CENTER>
  +<P>
  +One of the important issues in improving the performance is reduction of
  +memory usage - the less memory each server uses, the more server processes
  +you can start, and thus the more performance you have (from the user's
  +point of view - the response speed )
  +
  +<P>
  +See <A HREF="././performance.html#Global_vs_Fully_Qualified_Variab">Global vs Fully Qualified Variables</A>
   
   
   
   <P>
  +See <A HREF="././performance.html#Memory_leakage">Memory "leakages"</A>
  +
  +
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="An_Apache_s_mod_proxy">An Apache's mod_proxy</A></H1></CENTER>
  +<CENTER><H1><A NAME="Profiling">Profiling</A></H1></CENTER>
   <P>
  -I do not think the difference in speed between apache's <STRONG>mod_proxy</STRONG>
  -and <STRONG>squid</STRONG> is relevant for most sites, since the real value of what they do is
  -buffering for slow client connections. However squid runs as a single
  -process and probably consumes fewer system resources. The trade-off is that
  -mod_rewrite is easy to use if you want to spread parts of the site across
  -different back end servers, and mod_proxy knows how to fix up redirects
  -containing the back-end server's idea of the location. With squid you can
  -run a redirector process to proxy to more than one back end, but there is a
  -problem in fixing redirects in a way that keeps the client's view of both
  -server names and port numbers in all cases. The difficult case being where
  -you have DNS aliases that map to the same IP address for an alias and you
  -want the redirect to use port 80 (when the server is really on a different
  -port) but you want it to keep the specific name the browser sent so it does
  -not change in the client's <STRONG>Location</STRONG> window.
  +Profiling process helps you to determine which subroutines or just snippets
  +of code take the longest execution time and which subroutines are being
  +called most often. Probably you will want to optimize those, and to improve
  +the code toward efficiency.
   
   <P>
  -The Advantages:
  +It is possible to profile code running under mod_perl with the
  +<CODE>Devel::DProf</CODE> module, available on CPAN. However, you must have apache version 1.3b3 or
  +higher and the <CODE>PerlChildExitHandler</CODE> enabled (during the httpd build process). When the server is started,
  +<CODE>Devel::DProf</CODE> installs an <CODE>END</CODE> block to write the <CODE>tmon.out</CODE>
  +file. This block will be called at the server shutdown. Here is how to
  +start and stop a server with the profiler enabled:
   
  -<UL>
  -<P><LI>
   <P>
  -No additional server is needed. We keep the one plain plus one mod_perl
  -enabled apache servers. All you need is to enable the
  -<CODE>mod_proxy</CODE> in the <CODE>httpd_docs</CODE> server and add a few lines to
  -<CODE>httpd.conf</CODE> file.
  +<PRE>  % setenv PERL5OPT -d:DProf
  +  % httpd -X -d `pwd` &amp;
  +  ... make some requests to the server here ...
  +  % kill `cat logs/httpd.pid`
  +  % unsetenv PERL5OPT
  +  % dprofpp
  +</PRE>
  +<P>
  +The <CODE>Devel::DProf</CODE> package is a Perl code profiler. It will collect information on the
  +execution time of a Perl script and of the subs in that script (remember
  +that <CODE>print()</CODE> and <CODE>map()</CODE> are just like any other subroutines you write, but they are come bundled
  +with Perl!)
   
  -<P><LI>
   <P>
  -<CODE>ProxyPass</CODE> and <CODE>ProxyPassReverse</CODE> directives allow you to hide the internal redirects, so if <CODE>http://nowhere.com/modperl/</CODE> is actually
  -<CODE>http://localhost:81/modperl/</CODE>, it will be absolutely transparent for user. <CODE>ProxyPass</CODE> redirects the request to the mod_perl server, and when it gets the respond, <CODE>ProxyPassReverse</CODE> rewrites the URL back to the original one, e.g:
  +Another approach is to use <CODE>Apache::DProf</CODE>, which hooks
  +<CODE>Devel::DProf</CODE> into mod_perl. The <CODE>Apache::DProf</CODE> module will run a
  +<CODE>Devel::DProf</CODE> profiler inside each child server and write the
  +<CODE>tmon.out</CODE> file in the directory <CODE>$ServerRoot/logs/dprof/$$</CODE> when the child is shutdown (where <CODE>$$</CODE> is a number of the child process). All it takes is to add to <CODE>httpd.conf</CODE>:
   
   <P>
  -<PRE>  ProxyPass        /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  -  ProxyPassReverse /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  +<PRE>  PerlModule Apache::DProf
   </PRE>
  -<P><LI>
   <P>
  -It does mod_perl output buffering like squid does. See the <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A> notes for more details.
  +Remember that any PerlHandler that was pulled in before
  +<CODE>Apache::DProf</CODE> in the <CODE>httpd.conf</CODE> or &lt;startup.pl&gt;, would not have its code debugging info inserted. To run <CODE>dprofpp</CODE>, chdir to
  +<CODE>$ServerRoot/logs/dprof/$$</CODE> and run:
   
  -<P><LI>
   <P>
  -It even does caching. You have to produce correct <CODE>Content-Length</CODE>,
  -<CODE>Last-Modified</CODE> and <CODE>Expires</CODE> http headers for it to work. If some dynamic content is not to change
  -constantly, you can dramatically increase performance by caching it with <CODE>ProxyPass</CODE>.
  +<PRE>  % dprofpp
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="CGI_pm_s_object_methods_calls_vs">CGI.pm's object methods calls vs. function calls</A></H1></CENTER>
  +<P>
  +Which approach is better?
   
  -<P><LI>
   <P>
  -<CODE>ProxyPass</CODE> happens before the authentication phase, so you do not have to worry about
  -authenticating twice.
  +<PRE>  use CGI;
  +  my $q = new CGI;
  +  print $q-&gt;param('x');
  +</PRE>
  +<P>
  +versus
   
  -<P><LI>
   <P>
  -Apache is able to accel https (secure) requests completely, while also
  -doing http accel. (with squid you have to use an external redirection
  -program for that).
  +<PRE>  use CGI (:standard);
  +  print param('x');
  +</PRE>
  +<P>
  +There is not any performance benefit of using the object calls rather than
  +the function calls, but there is a real memory hit when you import all of <CODE>CGI.pm</CODE>'s function calls into your process memory. This can be significant,
  +particularly when there are many child processes.
   
  -<P><LI>
   <P>
  -The latest (from apache 1.3.6) Apache proxy accel mode reported to be very
  -stable.
  +Aside of namespace pollution, when importing symbols from any module any
  +script, its size grows by the size of the allocated space for those
  +symbols. The more you import (e.g. <CODE>qw(:standard)</CODE> vs
  +<CODE>qw(:all))</CODE> the more memory will be used. Let's say the overhead
  +is of size X. Now take the number of scripts you deploy the function method
  +interface, let's call it Y. Finally let's say that you have Z number of
  +processes.
   
  -</UL>
   <P>
  -The Disadvantages:
  +You will need X*Y*Z size of additional memory, taking X=100k, Y=10, Z=30,
  +we get 100k*10*30 = 30Mb!!! Now you understand the difference.
   
  -<UL>
  -<P><LI>
   <P>
  -Users reported that it might be a bit slow, but the latest version is fast
  -enough. (How fast is enough? :)
  +Now to benchmark this use <CODE>GTop.pm</CODE>:
   
  -</UL>
   <P>
  -For implementation see <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A>.
  +<PRE>  use GTop ();
  +  use CGI ();
  +  print GTop-&gt;new-&gt;proc_mem($$)-&gt;size;
  +  
  +  1 949 696 
  +</PRE>
  +<P>
  +<PRE>  use GTop ();
  +  use CGI qw(:standard);
  +  print GTop-&gt;new-&gt;proc_mem($$)-&gt;size;
  +  
  +  1 966 080
  +</PRE>
  +<P>
  +<PRE>  use GTop ();
  +  use CGI qw(:all);
  +  print GTop-&gt;new-&gt;proc_mem($$)-&gt;size;
  +  
  +  1 970 176
  +</PRE>
  +<P>
  +Results:
  +
  +<P>
  +<PRE>  import symbols  size(bytes)  delta(bytes) relative to ()
  +  --------------------------------------
  +  ()              1949696             0
  +  qw(:standard)   1966080         16384
  +  qw(:all)        1970176         20480
  +</PRE>
  +<P>
  +So in my example above X=20k =&gt; 20K*10*30 = 6Mb. You will need 6Mb more
  +when importing all the <CODE>CGI.pm</CODE>'s symbols versus not importing at all.
  +
  +<P>
  +But generally you use more scripts, more processes and probably import more
  +symbols from the additional modules that use deploy.
  +
  +<P>
  +But, as reported, function method is faster in general case, because of the
  +time overhead that takes to resolve the pointer from the object.
  +
  +<P>
  +If you are heading to performance improving direction, you will have to
  +face the fact, that having to type <CODE>My::Module::my_method</CODE> might save you a good chunk of memory if the above call must not be called
  +with a reference to an object, but even then it can be passed by value.
  +
  +<P>
  +I strongly endorse <A HREF="././modules.html#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>. Its guts are all written in C, giving it a significant memory and
  +performance benefit. It has all the functionality <CODE>CGI.pm</CODE> has, but HTML generation functions.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A></H1></CENTER>
  +<P>
  +See <A HREF="././modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +
   
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Increasing_the_shared_memory_wit">Increasing the shared memory with mergemem</A></H1></CENTER>
  +<P>
  +<CODE>mergemem</CODE> is an experimental utility for linux, which looks *very* interesting for us
  +mod_perl users:
  +
  +<P>
  +<PRE>        <A HREF="http://mondoshawan.ml.org/mergemem/">http://mondoshawan.ml.org/mergemem/</A>
  +</PRE>
  +<P>
  +It looks like it could be run periodically on your server to find and merge
  +duplicate pages. There are caveats: it would halt your httpds during the
  +merge (it appears to be very fast, but still ...).
  +
  +<P>
  +This software comes with a utility called memcmp to tell you how much you
  +might save.
  +
  +<P>
  +<STRONG>If you have tried this utility, please let us know what do you think
  +about it! Thanks</STRONG>
  +
  +
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -8015,7 +8122,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]
  +	     [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -8028,7 +8135,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 08/17/1999
  +	     <BR>Last Modified at 10/16/1999
         </FONT>
       </B>
     </TD>
  @@ -8055,7 +8162,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Real World Scenarios Implementation</TITLE>
  +   <TITLE>mod_perl guide: Choosing the Right Strategy</TITLE>
      <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
      <META NAME="Author" CONTENT="Stas Bekman">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  @@ -8074,44 +8181,20 @@
   <H1 ALIGN=CENTER>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Real World Scenarios Implementation</H1>
  +Choosing the Right Strategy</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="strategy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  +	<LI><A HREF="#Do_it_like_me_">Do it like me?!</A>
  +	<LI><A HREF="#mod_perl_Deployment_Overview">mod_perl Deployment Overview</A>
   	<LI><A HREF="#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
  -	<UL>
  -
  -		<LI><A HREF="#Installation_in_10_lines">Installation in 10 lines</A>
  -		<LI><A HREF="#Installation_in_10_paragraphs">Installation in 10 paragraphs</A>
  -		<LI><A HREF="#Configuration_Process">Configuration Process</A>
  -	</UL>
  -
  -	<LI><A HREF="#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A>
  -	<UL>
  -
  -		<LI><A HREF="#Configuration_and_Compilation_of">Configuration and Compilation of the Sources.</A>
  -		<UL>
  -
  -			<LI><A HREF="#Building_the_httpd_docs_Server">Building the httpd_docs Server</A>
  -			<LI><A HREF="#Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A>
  -		</UL>
  -
  -		<LI><A HREF="#Configuration_of_the_servers">Configuration of the servers</A>
  -		<UL>
  -
  -			<LI><A HREF="#Basic_httpd_docs_Server_s_Config">Basic httpd_docs Server's Configuration</A>
  -			<LI><A HREF="#Basic_httpd_perl_Server_s_Config">Basic httpd_perl Server's Configuration</A>
  -		</UL>
  -
  -	</UL>
  -
  -	<LI><A HREF="#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
  -	<LI><A HREF="#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A>
  -	<LI><A HREF="#Building_and_Using_mod_proxy">Building and Using mod_proxy</A>
  -	<LI><A HREF="#mod_perl_server_as_DSO">mod_perl server as DSO</A>
  -	<LI><A HREF="#HTTP_Authentication_with_2_serve">HTTP Authentication with 2 servers + proxy</A>
  +	<LI><A HREF="#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl-enabled Apache Servers</A>
  +	<LI><A HREF="#One_light_non_Apache_and_One_mod">One light non-Apache and One mod_perl enabled Apache Servers</A>
  +	<LI><A HREF="#Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A>
  +	<LI><A HREF="#The_Squid_Server">The Squid Server</A>
  +	<LI><A HREF="#An_Apache_s_mod_proxy">An Apache's mod_proxy</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -8137,1905 +8220,2201 @@
   	       <HR>
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<P>
  -<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></CENTER>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Installation_in_10_lines">Installation in 10 lines</A></H2></CENTER>
  +<CENTER><H1><A NAME="Do_it_like_me_">Do it like me?!</A></H1></CENTER>
   <P>
  -The Installation is very very simple (example of installation on Linux OS):
  +There is no such a thing as a single <STRONG>RIGHT</STRONG> strategy in web server business, though there are many wrong ones. Never
  +believe a person who says: <EM>"Do it this way, this is the best!"</EM>. As the old saying goes:
  +<EM>"Trust but verify"</EM>. There are too many technologies out there to choose from, and it would
  +take an enormous investment of time and money to try to validate each one
  +before deciding which is the best choice for your situation. Keeping this
  +idea in mind, I will present some different combinations of mod_perl and
  +other technologies or just standalone mod_perl. I'll describe how these
  +things work together, and offer my opinions on the pros and cons of each,
  +the relative degree of difficulty in installing and maintaining them, some
  +hints on approaches that should be used and things to avoid.
   
  -<P>
  -<PRE>  % cd /usr/src
  -  % lwp-download <A HREF="http://www.apache.org/dist/apache_x.x.x.tar.gz">http://www.apache.org/dist/apache_x.x.x.tar.gz</A>
  -  % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
  -  % tar zvxf apache_x.xx.tar.gz
  -  % tar zvxf mod_perl-x.xx.tar.gz
  -  % cd mod_perl-x.xx
  -  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  -  % make &amp;&amp; make test &amp;&amp; make install
  -  % cd ../apache_x.x.x
  -  % make install
  -</PRE>
   <P>
  -That's all!
  +To be clear, I will not address all technologies and tools, but limit this
  +discussion to those complementing mod_perl.
   
   <P>
  -Notes: Replace x.x.x with the real version numbers of mod_perl and apache.
  -gnu <CODE>tar</CODE> uncompresses as well (with <CODE>z</CODE> flag).
  +Please let me stress it again: <STRONG>DO NOT</STRONG> blindly copy someone's setup and hope for a good result. Choose what is
  +best for your situation -- it might take <STRONG>some</STRONG> effort to find it out.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Installation_in_10_paragraphs">Installation in 10 paragraphs</A></H2></CENTER>
  +<CENTER><H1><A NAME="mod_perl_Deployment_Overview">mod_perl Deployment Overview</A></H1></CENTER>
   <P>
  -First download the sources of both packages, e.g. you can use
  -<CODE>lwp-download</CODE> utility to do it. <CODE>lwp-download</CODE> is a part of the LWP (or <CODE>libwww</CODE>) package, you will need to have it installed in order for mod_perl's <CODE>make test</CODE> to pass. Once you install this package unless it's already installed, <CODE>lwp-download</CODE> will be available for you as well.
  +There are several different ways to build, configure and deploy your
  +mod_perl enabled server. Some of them are:
   
  -<P>
  -<PRE>  % lwp-download <A HREF="http://www.apache.org/dist/apache_x.x.x.tar.gz">http://www.apache.org/dist/apache_x.x.x.tar.gz</A>
  -  % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
  -</PRE>
  +<OL>
  +<P><LI>
   <P>
  -Extract both sources. Usually I open all the sources in <CODE>/usr/src/</CODE>, your mileage may vary. So move the sources and <CODE>chdir</CODE> to the directory, you want to put the sources in. Gnu <CODE>tar</CODE> utility knows to uncompress too with <CODE>z</CODE> flag, if you have a non-gnu <CODE>tar</CODE> utility, it will be incapable to decompress, so you would do it in two
  -steps: first uncompressing the packages with <CODE>gzip -d apache_x.xx.tar.gz</CODE>
  -and <CODE>gzip -d mod_perl-x.xx.tar.gz</CODE>, second un-tarring them with <CODE>tar
  -xvf apache_x.xx.tar</CODE> and <CODE>tar xvf mod_perl-x.xx.tar</CODE>.
  +Having one binary and one config file (one big binary for mod_perl).
   
  -<P>
  -<PRE>  % cd /usr/src
  -  % tar zvxf apache_x.xx.tar.gz
  -  % tar zvxf mod_perl-x.xx.tar.gz
  -</PRE>
  +<P><LI>
   <P>
  -<CODE>chdir</CODE> to the mod_perl source directory:
  +Having two binaries and two config files (one big binary for mod_perl and
  +one small for static objects like images.)
   
  -<P>
  -<PRE>  % cd mod_perl-x.xx
  -</PRE>
  +<P><LI>
   <P>
  -Now build the make file, for a basic work and first time installation the
  -parameters in the example below are the only ones you would need. <CODE>APACHE_SRC</CODE> tells where the apache <CODE>src</CODE> directory is. If you have followed my suggestion and have extracted the
  -both sources under the same directory (<CODE>/usr/src</CODE>), do:
  +Having one DSO-style binary, mod_perl loadable object and two config files
  +(Dynamic linking lets you compile once and have a big and a small binary in
  +memory BUT you have to deal with a freshly made solution that has weak
  +documentation and is still subject to change and is rather more complex.)
   
  -<P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  -</PRE>
  +<P><LI>
   <P>
  -There are many additional parameters. You can find some of them in the
  -configuration dedicated and other sections. While running <CODE>perl
  -Makefile.PL ...</CODE> the process will check for prerequisites and tell you if something is
  -missing, If you are missing some of the perl packages or other software --
  -you will have to install these before you proceed.
  +Any of the above plus a reverse proxy server in http accelerator mode.
   
  +</OL>
   <P>
  -Now we <STRONG>make</STRONG> the project (by building the mod_perl extension and calling <CODE>make</CODE> in apache source directory to build a <CODE>httpd</CODE>),
  -<STRONG>test</STRONG> it (by running various tests) and <STRONG>install</STRONG> the mod_perl modules.
  +If you are a newbie, I would recommend that you start with the first option
  +and work on getting your feet wet with apache and mod_perl. Later, you can
  +decide whether to move to the second one which allows better tuning at the
  +expense of more complicated administration, or to the third option -- the
  +more state-of-the-art-yet-suspiciously-new DSO system, or to the fourth
  +option which gives you even more power.
   
  -<P>
  -<PRE>  % make &amp;&amp; make test &amp;&amp; make install
  -</PRE>
  +<OL>
  +<P><LI>
   <P>
  -Note that if <STRONG>make</STRONG> fails, neither <STRONG>make test</STRONG> nor <STRONG>make
  -install</STRONG> will be not executed. If <STRONG>make test</STRONG> fails, <STRONG>make install</STRONG>
  -will be not executed.
  +The first option will kill your production site if you serve a lot of
  +static data with ~2-12 MB webserver processes. On the other hand, while
  +testing you will have no other server interaction to mask or add to your
  +errors.
   
  +<P><LI>
   <P>
  -Now change to apache source directory and run <CODE>make install</CODE> to install apache's headers, default configuration files, to build apache
  -directory tree and to put the <CODE>httpd</CODE> there.
  +The second option allows you to seriously tune the two servers for maximum
  +performance. On the other hand you have to deal with proxying or fancy site
  +design to keep the two servers in synchronization. In this configuration,
  +you also need to choose between running the two servers on multiple ports,
  +multiple IPs, etc... This adds the burden of administrating more than one
  +server.
   
  -<P>
  -<PRE>  % cd ../apache_x.x.x
  -  % make install
  -</PRE>
  +<P><LI>
   <P>
  -When you execute the above command, apache installation process will tell
  -you how to start a freshly built webserver (the path of the
  -<CODE>apachectl</CODE>, more about it later) and where the configuration files are. Remember (or
  -even better write down) both, since you will need this information very
  -soon. On my machine the two important paths are:
  +The third option (DSO) -- as mentioned above -- means playing with the
  +bleeding edge. In addition <CODE>mod_so</CODE> (the DSO module) adds size and complexity to your binaries. With DSO,
  +modules can be added and removed without recompiling the server, and
  +modules are even shared among multiple servers. Again, it is bleeding edge
  +and still somewhat platform specific, but your mileage may vary. See <A HREF="././install.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>.
   
  +<P><LI>
   <P>
  -<PRE>  /usr/local/apache/bin/apachectl
  -  /usr/local/apache/conf/httpd.conf
  -</PRE>
  +The fourth option (proxy in http accelerator mode), once correctly
  +configured and tuned, improves the performance of any of the above three
  +options by caching and buffering page results.
  +
  +</OL>
   <P>
  -Now the build and the installation processes are completed. Just configure <CODE>httpd.conf</CODE> and start the webserver.
  +The rest of this chapter discusses the pros and the cons of each of these
  +presented configurations.  <A HREF="././scenario.html#">Real World Scenarios Implementaion</A> describes the implementation techniques of these schemas.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Configuration_Process">Configuration Process</A></H2></CENTER>
  +<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></CENTER>
   <P>
  -A basic configuration is a simple one. First configure the apache as you
  -always do (set <CODE>Port</CODE>, <CODE>User</CODE>, <CODE>Group</CODE>, correct <CODE>ErrorLog</CODE> and other file paths and etc), start the server and make sure it works. One
  -of the ways to start and stop the server is to use
  -<CODE>apachectl</CODE> utility:
  +The first approach is to implement a straightforward mod_perl server. Just
  +take your plain apache server and add mod_perl, like you add any other
  +apache module. You continue to run it at the port it was running before.
  +You probably want to try this before you proceed to more sophisticated and
  +complex techniques.
   
  -<P>
  -<PRE>  % /usr/local/apache/bin/apachectl start
  -  % /usr/local/apache/bin/apachectl stop
  -</PRE>
   <P>
  -Shut the server down, open the <CODE>httpd.conf</CODE> in your favorite editor and scroll to the end of the file, where we will
  -add the mod_perl configuration directives (of course you can place them
  -anywhere in the file).
  +The advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -Add the following configuration directives:
  +Simplicity. You just follow the installation instructions, configure it,
  +restart the server and you are done.
   
  -<P>
  -<PRE>  Alias /perl/ /home/httpd/perl/
  -</PRE>
  +<P><LI>
   <P>
  -Assuming that you put all your scripts, that should be executed by mod_perl
  -enabled server, under <CODE>/home/httpd/perl/</CODE> directory.
  +No network changes. You do not have to worry about using additional ports
  +as we will see later.
   
  -<P>
  -<PRE>  PerlModule Apache::Registry
  -  &lt;Location /perl&gt;
  -    SetHandler perl-script
  -    PerlHandler Apache::Registry
  -    Options ExecCGI
  -    PerlSendHeader On
  -    allow from all
  -  &lt;/Location&gt;
  -</PRE>
  +<P><LI>
   <P>
  -Now put a test script into <CODE>/home/httpd/perl/</CODE> directory:
  +Speed. You get a very fast server, you see an enormous speedup from the
  +first moment you start to use it.
   
  -<P>
  -<PRE>  test.pl
  -  -------
  -  #!/usr/bin/perl -w
  -  use strict;
  -  print &quot;Content-type: text/html\r\n\r\n&quot;;
  -  print &quot;It worked!!!\n&quot;;
  -  -------
  -</PRE>
  +</UL>
   <P>
  -Make it executable and readable by server, if your server is running as
  -user <CODE>nobody</CODE> (hint: look for <CODE>User</CODE> directive in <CODE>httpd.conf</CODE>
  -file), do the following:
  +The disadvantages:
   
  +<UL>
  +<P><LI>
   <P>
  -<PRE>  % chown nobody /home/httpd/perl/test.pl
  -  % chmod u+rx   /home/httpd/perl/test.pl
  -</PRE>
  +The process size of a mod_perl-enabled Apache server is huge (starting from
  +4Mb at startup and growing to 10Mb and more, depending on how you use it)
  +compared to the typical plain Apache. Of course if memory sharing is in
  +place -- RAM requirements will be smaller.
  +
   <P>
  -Test that the script is running from the command line, by executing it:
  +You probably have a few tens of children processes. The additional memory
  +requirements add up in direct relation to the number of children processes.
  +Your memory demands are growing by an order of magnitude, but this is the
  +price you pay for the additional performance boost of mod_perl. With memory
  +prices so cheap nowadays, the additional cost is low -- especially when you
  +consider the dramatic performance boost mod_perl gives to your services
  +with every 100Mb of RAM you add.
   
   <P>
  -<PRE>  % /home/httpd/perl/test.pl
  -</PRE>
  +While you will be happy to have these monster processes serving your
  +scripts with monster speed, you should be very worried about having them
  +serve static objects such as images and html files. Each static request
  +served by a mod_perl-enabled server means another large process running,
  +competing for system resources such as memory and CPU cycles. The real
  +overhead depends on static objects request rate. Remember that if your
  +mod_perl code produces HTML code which includes images, each one will turn
  +into another static object request. Having another plain webserver to serve
  +the static objects solves this not pleasant obstacle. Having a proxy server
  +as a front end, caching the static objects and freeing the mod_perl
  +processes from this burden is another solution. We will discuss both below.
  +
  +<P><LI>
   <P>
  -You should see:
  +Another drawback of this approach is that when serving output to a client
  +with a slow connection, the huge mod_perl-enabled server process (with all
  +of its system resources) will be tied up until the response is completely
  +written to the client. While it might take a few milliseconds for your
  +script to complete the request, there is a chance it will be still busy for
  +some number of seconds or even minutes if the request is from a slow
  +connection client. As in the previous drawback, a proxy solution can solve
  +this problem. More on proxies later.
   
   <P>
  -<PRE>  Content-type: text/html
  -  
  -  It worked!!!
  -</PRE>
  +Proxying dynamic content is not going to help much if all the clients are
  +on a fast local net (for example, if you are administering an Intranet.) On
  +the contrary, it can decrease performance. Still, remember that some of
  +your Intranet users might work from home through the slow modem links.
  +
  +</UL>
   <P>
  -Now it is a time to test our mod_perl server, assuming that your config
  -file includes <CODE>Port 80</CODE>, go to your favorite Netscape browser and fetch the following URL (after
  -you have started the server):
  +If you are new to mod_perl, this is probably the best way to get yourself
  +started.
   
   <P>
  -<PRE>  <A HREF="http://localhost/perl/test.pl">http://localhost/perl/test.pl</A>
  -</PRE>
  +And of course, if your site is serving only mod_perl scripts (close to zero
  +static objects, like images), this might be the perfect choice for you!
  +
   <P>
  -Make sure that you have a loop-back device configured, if not -- use the
  -real server name for this test, for example:
  +For implementation notes see : <A HREF="././scenario.html#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A>
  +
   
  +
   <P>
  -<PRE>  <A HREF="http://www.nowhere.com/perl/test.pl">http://www.nowhere.com/perl/test.pl</A>
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl-enabled Apache Servers</A></H1></CENTER>
   <P>
  -You should see:
  +As I have mentioned before, when running scripts under mod_perl, you will
  +notice that the httpd processes consume a huge amount of virtual memory,
  +from 5Mb to 15Mb and even more. That is the price you pay for the enormous
  +speed improvements under mod_perl. (Again -- shared memory keeps the real
  +memory that is being used much smaller :)
   
   <P>
  -<PRE>  It worked!!!
  -</PRE>
  +Using these large processes to serve static objects like images and html
  +documents is overkill. A better approach is to run two servers: a very
  +light, plain apache server to serve static objects and a heavier
  +mod_perl-enabled apache server to serve requests for dynamic (generated)
  +objects (aka CGI).
  +
   <P>
  -If something went wrong, go through the installation process again, and
  -make sure you didn't make a mistake. If that doesn't help, read the <CODE>INSTALL</CODE> pod document (<CODE>perlpod INSTALL</CODE>) in the mod_perl distribution directory.
  +From here on, I will refer to these two servers as <STRONG>httpd_docs</STRONG>
  +(vanilla apache) and <STRONG>httpd_perl</STRONG> (mod_perl enabled apache).
   
   <P>
  -Now copy some of your perl/CGI scripts into a <CODE>/home/httpd/perl/</CODE>
  -directory and see them working much much faster, from the newly configured
  -base URL (<CODE>/perl/</CODE>). Some of your scripts will not work out of box and will demand some minor
  -tweaking or major rewrite to make them work properly with mod_perl enabled
  -server. Chances are that if you are not practicing a sloppy programming
  -techniques -- the scripts will work without any modifications at all.
  +The advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -The above setup is very basic, it will help you to have a mod_perl enabled
  -server running and to get a good feeling from watching your previously slow
  -CGIs now flying.
  +The heavy mod_perl processes serve only dynamic requests, which allows the
  +deployment of fewer of these large servers.
   
  +<P><LI>
   <P>
  -As with <STRONG>perl</STRONG> you can start benefit from <STRONG>mod_perl</STRONG> from the very first moment you try it. When you become more familiar with
  -mod_perl you will want to start writing apache handlers and deploy more of
  -the mod_perl power.
  +<CODE>MaxClients</CODE>, <CODE>MaxRequestsPerChild</CODE> and related parameters can now be optimally tuned for both <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE> servers, something we could not do before. This allows us to fine tune the
  +memory usage and get a better server performance.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A></H1></CENTER>
  +Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
  +
  +</UL>
   <P>
  -Since we are going to run two apache servers we will need two different
  -sets of configuration, log and other files. We need a special directory
  -layout. While some of the directories can be shared between the two servers
  -(assuming that both are built from the same source distribution), others
  -should be separated. From now on I will refer to these two servers as <STRONG>httpd_docs</STRONG> (vanilla Apache) and
  -<STRONG>httpd_perl</STRONG> (Apache/mod_perl).
  +An <STRONG>important</STRONG> note: When user browses static pages and the base URL in the <STRONG>Location</STRONG> window points to the static server, for example
  +<CODE>http://www.nowhere.com/index.html</CODE> -- all relative URLs (e.g. <CODE>&lt;A
  +HREF=&quot;/main/download.html&quot;</CODE>&gt;) are being served by the light plain apache server. But this is not
  +the case with dynamically generated pages. For example when the base URL in
  +the <STRONG>Location</STRONG> window points to the dynamic server -- (e.g. <CODE>http://www.nowhere.com:8080/perl/index.pl</CODE>) all relative URLs in the dynamically generated HTML will be served by the
  +heavy mod_perl processes. You must use a fully qualified URLs and not the
  +relative ones! <CODE>http://www.nowhere.com/icons/arrow.gif</CODE> is a full URL, while
  +<CODE>/icons/arrow.gif</CODE> is a relative one. Using <CODE>&lt;BASE
  +HREF=&quot;http://www.nowhere.com/&quot;</CODE>&gt; in the generated HTML is another way to handle this problem. Also the <CODE>httpd_perl</CODE> server could rewrite the requests back to <CODE>httpd_docs</CODE> (much slower) and you still need an attention of the heavy servers. This is
  +not an issue if you hide the internal port implementations, so client sees
  +only one server running on port <CODE>80</CODE>. (See <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>)
   
   <P>
  -For this illustration, we will use <CODE>/usr/local</CODE> as our <EM>root</EM>
  -directory. The Apache installation directories will be stored under this
  -root (<CODE>/usr/local/bin</CODE>, <CODE>/usr/local/etc</CODE> and etc...)
  +The disadvantages:
   
  +<UL>
  +<P><LI>
   <P>
  -First let's prepare the sources. We will assume that all the sources go
  -into <CODE>/usr/src</CODE> dir. It is better when you use two separate copies of apache sources. Since
  -you probably will want to tune each apache version at separate and to do
  -some modifications and recompilations as the time goes. Having two
  -independent source trees will prove helpful, unless you use <CODE>DSO</CODE>, which is covered later in this section.
  +An administration overhead.
   
  +<UL>
  +<P><LI>
   <P>
  -Make two subdirectories:
  +A need for two different sets of configuration, log and other files. We
  +need a special directory layout to manage these. While some directories can
  +be shared between the two servers (like the <CODE>include</CODE>
  +directory, containing the apache include files -- assuming that both are
  +built from the same source distribution), most of them should be separated
  +and the configuration files updated to reflect the changes.
   
  +<P><LI>
   <P>
  -<PRE>  % mkdir /usr/src/httpd_docs
  -  % mkdir /usr/src/httpd_perl
  -</PRE>
  +A need for two sets of controlling scripts (startup/shutdown) and
  +watchdogs.
  +
  +<P><LI>
   <P>
  -Put the Apache sources into a <CODE>/usr/src/httpd_docs</CODE> directory:
  +If you are processing log files, now you probably will have to merge the
  +two separate log files into one before processing them.
   
  +</UL>
  +<P><LI>
   <P>
  -<PRE>  % cd /usr/src/httpd_docs
  -  % gzip -dc /tmp/apache_x.x.x.tar.gz | tar xvf -
  -</PRE>
  +We still have the problem of a mod_perl process spending its precious time
  +serving slow clients, when the processing portion of the request was
  +completed long time ago, exactly as in the one server approach. Deploying a
  +proxy solves this, and will be covered in the next sections.
  +
   <P>
  -If you have a gnu tar:
  +As with only one server approach, this is not a major disadvantage if you
  +are on a fast local Intranet. It is likely that you do not want a buffering
  +server in this case.
   
  +</UL>
   <P>
  -<PRE>  % tar xvzf /tmp/apache_x.x.x.tar.gz
  -</PRE>
  +Before you go on with this solution you really want to look at the
  +<A HREF="././strategy.html#Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A> section.
  +
   <P>
  -Replace <CODE>/tmp</CODE> directory with a path to a downloaded file and
  -<CODE>x.x.x</CODE> with the version of the server you have.
  +For implementation notes see : <A HREF="././scenario.html#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A>
   
  +
  +
   <P>
  -<PRE>  % cd /usr/src/httpd_docs
  -  
  -  % ls -l
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_x.x.x/
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="One_light_non_Apache_and_One_mod">One light non-Apache and One mod_perl enabled Apache Servers</A></H1></CENTER>
   <P>
  -Now we will prepare the <CODE>httpd_perl</CODE> server sources:
  +If the only requirement from the light server is for it to serve static
  +objects, then you can get away with non-apache servers having an even
  +smaller memory footprint. <CODE>thttpd</CODE> has been reported to be about 5 times faster then apache (especially under
  +a heavy load), since it is very simple and uses almost no memory (260k) and
  +does not spawn child processes.
   
   <P>
  -<PRE>  % cd /usr/src/httpd_perl
  -  % gzip -dc /tmp/apache_x.x.x.tar.gz | tar xvf -
  -  % gzip -dc /tmp/modperl-x.xx.tar.gz | tar xvf -
  -  
  -  % ls -l
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_x.x.x/
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 modperl-x.xx/
  -</PRE>
  +Meta: Hey, No personal experience here, only rumours. Please let me know if
  +I have missed some pros/cons here. Thanks!
  +
   <P>
  -Time to decide on the desired directory structure layout (where the apache
  -files go):
  +The Advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -<PRE>  ROOT = /usr/local
  -</PRE>
  -<P>
  -The two servers can share the following directories (so we will not
  -duplicate data):
  +All the advantages of the 2 servers scenario.
   
  -<P>
  -<PRE>  /usr/local/bin/
  -  /usr/local/lib
  -  /usr/local/include/
  -  /usr/local/man/
  -  /usr/local/share/
  -</PRE>
  +<P><LI>
   <P>
  -<STRONG>Important:</STRONG> we assume that both servers are built from the same Apache source version.
  +More memory saving. Apache is about 4 times bigger then <STRONG>thttpd</STRONG>, if you spawn 30 children you use about 30M of memory, while <STRONG>thttpd</STRONG>
  +uses only 260k - 100 times less! You could use the saved 30M to run more
  +mod_perl servers.
   
   <P>
  -Servers store their specific files either in <CODE>httpd_docs</CODE> or
  -<CODE>httpd_perl</CODE> sub-directories:
  +Note that this is not true if your OS supports memory sharing and you
  +configured apache to use it (it is a DSO approach. There is no memory
  +sharing if apache modules are being statically compiled into httpd). If you
  +do allow memory sharing -- 30 light apache servers ought to use about 3-4Mb
  +only, because most of it will be shared. If this is the case -- the save
  +ups are much smaller with <STRONG>thttpd</STRONG>.
   
  +<P><LI>
   <P>
  -<PRE>  /usr/local/etc/httpd_docs/
  -                 httpd_perl/
  -  
  -  /usr/local/sbin/httpd_docs/
  -                  httpd_perl/
  -  
  -  /usr/local/var/httpd_docs/logs/
  -                            proxy/
  -                            run/
  -                 httpd_perl/logs/
  -                            proxy/
  -                            run/
  -</PRE>
  +Reported to be about 5 times faster then plain apache serving static
  +objects.
  +
  +</UL>
   <P>
  -After completion of the compilation and the installation of the both
  -servers, you will need to configure them. To make things clear before we
  -proceed into details, you should configure the
  -<CODE>/usr/local/etc/httpd_docs/httpd.conf</CODE> as a plain apache and <CODE>Port</CODE>
  -directive to be 80 for example. And
  -<CODE>/usr/local/etc/httpd_perl/httpd.conf</CODE> to configure for mod_perl server and of course whose <CODE>Port</CODE> should be different from the one
  -<CODE>httpd_docs</CODE> server listens to (e.g. 8080). The port numbers issue will be discussed
  -later.
  +The Disadvantages:
   
  +<UL>
  +<P><LI>
   <P>
  -The next step is to configure and compile the sources: Below are the
  -procedures to compile both servers taking into account the directory layout
  -I have just suggested to use.
  +Lacks some of apache's features, like access control, error redirection,
  +customizable log file formats, and so on.
   
  +</UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Configuration_and_Compilation_of">Configuration and Compilation of the Sources.</A></H2></CENTER>
  +<CENTER><H1><A NAME="Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A></H1></CENTER>
   <P>
  -Let's proceed with installation. I will use x.x.x instead of real version
  -numbers so this document will never become obsolete :).
  +At the beginning there were 2 servers: one - plain apache server, which was <STRONG>very light</STRONG>, and configured to serve static objects, the other -- mod_perl enabled,
  +which was <STRONG>very heavy</STRONG> and aimed to serve mod_perl scripts. We named them: <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE>
  +appropriately. The two servers coexisted at the same <CODE>IP(DNS)</CODE>
  +by listening to different ports: 80 -- for <CODE>httpd_docs</CODE>
  +(e.g. <A
  +HREF="http://www.nowhere.com/images/test.gif">http://www.nowhere.com/images/test.gif</A>
  +) and 8080 -- for
  +<CODE>httpd_perl</CODE> (e.g. <A
  +HREF="http://www.nowhere.com:8080/perl/test.pl">http://www.nowhere.com:8080/perl/test.pl</A>
  +). Note that I did not write <A
  +HREF="http://www.nowhere.com:80">http://www.nowhere.com:80</A> for the
  +first example, since port 80 is a default http port. (Later on, I will be
  +moving the
  +<CODE>httpd_docs</CODE> server to port 81.)
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Building_the_httpd_docs_Server">Building the httpd_docs Server</A></H3></CENTER>
  -<DL>
  -<P><DT><STRONG><A NAME="item_Sources">Sources Configuration:</A></STRONG><DD>
  +Now I am going to convince you that you <STRONG>want</STRONG> to use a proxy server (in the http accelerator mode). The advantages are:
  +
  +<UL>
  +<P><LI>
   <P>
  -<PRE>  % cd /usr/src/httpd_docs/apache_x.x.x
  -  % make clean
  -  % env CC=gcc \
  -  ./configure --prefix=/usr/local \
  -    --sbindir=/usr/local/sbin/httpd_docs \
  -    --sysconfdir=/usr/local/etc/httpd_docs \
  -    --localstatedir=/usr/local/var/httpd_docs \
  -    --runtimedir=/usr/local/var/httpd_docs/run \
  -    --logfiledir=/usr/local/var/httpd_docs/logs \
  -    --proxycachedir=/usr/local/var/httpd_docs/proxy
  -</PRE>
  +Allow serving of static objects from the proxy's cache (objects that
  +previously were entirely served by the <CODE>httpd_docs</CODE> server).
  +
  +<P><LI>
   <P>
  -If you need some other modules, like mod_rewrite and mod_include (SSI), add
  -them here as well:
  +You get less I/O activity reading static objects from the disk (proxy
  +serves the most ``popular'' objects from the RAM memory - of course you
  +benefit more if you allow the proxy server to consume more RAM). Since you
  +do not wait for the I/O to be completed you are able to serve the static
  +objects much faster.
   
  +<P><LI>
   <P>
  -<PRE>    --enable-module=include --enable-module=rewrite
  -</PRE>
  +The proxy server acts as a sort of output buffer for the dynamic content.
  +The mod_perl server sends the entire response to the proxy and is then free
  +to deal with other requests. The proxy server is responsible for sending
  +the response to the browser. So if the transfer is over a slow link, the
  +mod_perl server is not waiting around for the data to move.
  +
   <P>
  -Note: <CODE>gcc</CODE> -- compiles httpd by 100K+ smaller then <CODE>cc</CODE> on AIX OS. Remove the line <CODE>env CC=gcc</CODE> if you want to use the default compiler. If you want to use it and you are
  -a (ba)?sh user you will not need the
  -<CODE>env</CODE> function, t?csh users will have to keep it in.
  +Using numbers is always more convincing :) Let's take a user connected to
  +your site with 28.8 kbps (bps == bits/sec) modem. It means that the speed
  +of the user's link is 28.8/8 = 3.6 kbytes/sec. I assume an average
  +generated HTML page to be of 10kb (kb == kilobytes) and an average script
  +that generates this output in 0.5 secs. How much time will the server wait
  +before the user gets the whole output response? A simple calculation
  +reveals pretty scary numbers - it will have to wait for another 6 secs
  +(20kb/3.6kb), when it could serve another 12 (6/0.5) dynamic requests in
  +this time. This very simple example shows us that we need a twelve the
  +number of children running, which means you will need only one twelve of
  +the memory (which is not quite true because some parts of the code are
  +being shared). But you know that nowadays scripts return pages which
  +sometimes are being blown up with javascript code and similar, which makes
  +them of 100kb size and download time to be of... (This calculation is left
  +to you as an exercise :)
   
   <P>
  -Note: add <CODE>--layout</CODE> to see the resulting directories' layout without actually running the
  -configuration process.
  +To make your estimation of download time numbers even worse, let me remind
  +you that many users like to open many browser windows and do many things at
  +once (download files and browse <STRONG>heavy</STRONG> sites). So the speed of 3.6kb/sec we were assuming before, may many times
  +be 5-10 times slower.
   
  -<P><DT><STRONG>Sources Compilation:</STRONG><DD>
  +<P><LI>
   <P>
  -<PRE>  % make
  -  % make install
  -</PRE>
  +Also we are going to hide the details of the server's implementation. Users
  +will never see ports in the URLs (more on that topic later). And you can
  +have a few boxes serving the requests, and only one serving as a front end,
  +which spreads the jobs between the servers in a way you configured it too.
  +So you can actually put down one server down for upgrade, but end user will
  +never notice that because the front end server will dispatch the jobs to
  +other servers. (Of course this is a pretty big issue, and it would not be
  +discussed in the scope of this document)
  +
  +<P><LI>
   <P>
  -Rename <CODE>httpd</CODE> to <CODE>http_docs</CODE>
  +For security reasons, using any httpd accelerator (or a proxy in httpd
  +accelerator mode) is essential because you do not let your internal server
  +get directly attacked by arbitrary packets from whomever. The httpd
  +accelerator and internal server communicate in expected HTTP requests. This
  +allows for only your public ``bastion'' accelerating www server to get
  +hosed in a successful attack, while leaving your internal data safe.
   
  +</UL>
  +<P>
  +The disadvantages are:
   
  +<UL>
  +<P><LI>
  +<P>
  +Of course there are drawbacks. Luckily, these are not functionality
  +drawbacks, but more of administration hassle. You add another daemon to
  +worry about, and while proxies are generally stable, you have to make sure
  +to prepare proper startup and shutdown scripts, which are being run at the
  +boot and reboot appropriately. Also, maybe a watchdog script running at the
  +crontab.
   
  +<P><LI>
   <P>
  -<PRE>  % mv /usr/local/sbin/httpd_docs/httpd \
  -  /usr/local/sbin/httpd_docs/httpd_docs
  -</PRE>
  +Proxy servers can be configured to be light or heavy, the admin must decide
  +what gives the highest performance for his application. A proxy server like
  +squid is light in the concept of having only one process serving all
  +requests. But it can appear pretty heavy when it loads objects into memory
  +for faster service.
  +
  +</UL>
   <P>
  -Now update an <STRONG>apachectl</STRONG> utility to point to the renamed httpd via your favorite text editor or by
  -using perl:
  +Have I succeeded in convincing you that you want the proxy server?
   
   <P>
  -<PRE>  % perl -p -i -e 's|httpd_docs/httpd|httpd_docs/httpd_docs|' \
  -  /usr/local/sbin/httpd_docs/apachectl
  -</PRE>
  -</DL>
  +If you are on a local area network (LAN), then the big benefit of the proxy
  +buffering the output and feeding a slow client is gone. You are probably
  +better off sticking with a straight mod_perl server in this case.
  +
  +<P>
  +As of this writing the two proxy implementations are known to be used in
  +bundle with mod_perl - <STRONG>squid</STRONG> proxy server and <STRONG>mod_proxy</STRONG> which is a part of the apache server. Let's compare the two of them.
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A></H3></CENTER>
  +<CENTER><H1><A NAME="The_Squid_Server">The Squid Server</A></H1></CENTER>
   <P>
  -Before you start to configure the mod_perl sources, you should be aware
  -that there are a few Perl modules that have to be installed before building
  -mod_perl. You will be alerted if any required modules are missing when you
  -run the <CODE>perl Makefile.PL</CODE> command line below. If you discover that some are missing, pick them from
  -your nearest CPAN repository (if you do not know what is it, make a visit
  -to <A HREF="http://www.perl.com/CPAN">http://www.perl.com/CPAN</A> ) or run
  -the <CODE>CPAN</CODE> interactive shell via the command line <CODE>perl -MCPAN -e shell</CODE>.
  +The Advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -Make sure the sources are clean:
  +Caching of static objects. So these are being served much faster assuming
  +that your cache size is big enough to keep the most requested objects in
  +the cache.
   
  +<P><LI>
   <P>
  -<PRE>  % cd /usr/src/httpd_perl/apache_x.x.x
  -  % make clean
  -  % cd /usr/src/httpd_perl/mod_perl-x.xx
  -  % make clean
  -</PRE>
  +Buffering of dynamic content, by taking the burden of returning the content
  +generated by mod_perl servers to slow clients, thus freeing mod_perl
  +servers from waiting for the slow clients to download the data. Freed
  +servers immediately switch to serve other requests, thus your number of
  +required servers goes dramatically down.
  +
  +<P><LI>
   <P>
  -It is important to <STRONG>make clean</STRONG> since some of the versions are not binary compatible (e.g apache 1.3.3 vs
  -1.3.4) so any ``third-party'' C modules need to be re-compiled against the
  -latest header files.
  +Non-linear URL space / server setup. You can use Squid to play some tricks
  +with the URL space and/or domain based virtual server support.
   
  +</UL>
   <P>
  -Here I did not find a way to compile with <CODE>gcc</CODE> (my perl was compiled with <CODE>cc</CODE> so we have to compile with the same compiler!!!
  +The Disadvantages:
   
  +<UL>
  +<P><LI>
   <P>
  -<PRE>  % cd /usr/src/httpd_perl/mod_perl-x.xx
  -</PRE>
  +Proxying dynamic content is not going to help much if all the clients are
  +on a fast local net. Also, a message on the squid mailing list implied that
  +squid only buffers in 16k chunks so it would not allow a mod_perl to
  +complete immediately if the output is larger.
  +
  +<P><LI>
   <P>
  -<PRE>  % /usr/local/bin/perl Makefile.PL \
  -  APACHE_PREFIX=/usr/local/ \
  -  APACHE_SRC=../apache_x.x.x/src \
  -  DO_HTTPD=1 \
  -  USE_APACI=1 \
  -  PERL_MARK_WHERE=1 \
  -  PERL_STACKED_HANDLERS=1 \
  -  ALL_HOOKS=1 \
  -  APACI_ARGS=--sbindir=/usr/local/sbin/httpd_perl, \
  -         --sysconfdir=/usr/local/etc/httpd_perl, \
  -         --localstatedir=/usr/local/var/httpd_perl, \
  -         --runtimedir=/usr/local/var/httpd_perl/run, \
  -         --logfiledir=/usr/local/var/httpd_perl/logs, \
  -         --proxycachedir=/usr/local/var/httpd_perl/proxy
  -</PRE>
  -<P>
  -Notice that <STRONG>all</STRONG>  <CODE>APACI_ARGS</CODE> (above) must be passed as one long line if you work with <CODE>t?csh</CODE>!!! However it works correctly the way it shown above with <CODE>(ba)?sh</CODE> (by breaking the long lines with '<CODE>\</CODE>'). If you work with <CODE>t?csh</CODE> it does not work, since <CODE>t?csh</CODE>
  -passes <CODE>APACI_ARGS</CODE> arguments to <CODE>./configure</CODE> by keeping the new lines untouched, but stripping the original '<CODE>\</CODE>', thus breaking the configuration process.
  -
  -<P>
  -As with <CODE>httpd_docs</CODE> you might need other modules like
  -<CODE>mod_rewrite</CODE>, so add them here:
  -
  -<P>
  -<PRE>         --enable-module=rewrite
  -</PRE>
  -<P>
  -Note: <CODE>PERL_STACKED_HANDLERS=1</CODE> is needed for <CODE>Apache::DBI</CODE>
  -
  -
  +Speed. Squid is not very fast today when compared to plain file based web
  +servers available. Only if you are using a lot of dynamic features such as
  +mod_perl or similar speed is a reason to use Squid, and then only if the
  +application and server is designed with caching in mind.
   
  +<P><LI>
   <P>
  -Now, build, test and install the <CODE>httpd_perl</CODE>.
  +Memory usage. Squid uses quite a bit of memory.
   
  -<P>
  -<PRE>  % make &amp;&amp; make test &amp;&amp; make install
  -</PRE>
  +<P><LI>
   <P>
  -Note: apache puts a stripped version of <CODE>httpd</CODE> at
  -<CODE>/usr/local/sbin/httpd_perl/httpd</CODE>. The original version which includes debugging symbols (if you need to run
  -a debugger on this executable) is located at
  -<CODE>/usr/src/httpd_perl/apache_x.x.x/src/httpd</CODE>.
  +HTTP protocol level. Squid is pretty much a <CODE>HTTP/1.0</CODE> server, which seriously limits the deployment of <CODE>HTTP/1.1</CODE> features.
   
  +<P><LI>
   <P>
  -Note: You may have noticed that we did not run <CODE>make install</CODE> in the apache's source directory. When <CODE>USE_APACI</CODE> is enabled,
  -<CODE>APACHE_PREFIX</CODE> will specify the <CODE>--prefix</CODE> option for apache's
  -<CODE>configure</CODE> utility, specifying the installation path for apache. When this option is
  -used, mod_perl's <CODE>make install</CODE> will also
  -<CODE>make install</CODE> on the apache side, installing the httpd binary, support tools, along with
  -the configuration, log and document trees.
  +HTTP headers, dates and freshness. The squid server might give out ``old''
  +pages, confusing downstream/client caches. Also chances are that you will
  +be giving out stale pages. (You update the some documents on the site, but
  +squid will still serve the old ones.)
   
  +<P><LI>
   <P>
  -If <CODE>make test</CODE> fails, look into <CODE>t/logs</CODE> and see what is in there. Also see <A HREF="././install.html#make_test_fails">make test fails</A>.
  +Stability. Compared to plain web servers Squid is not the most stable.
   
  +</UL>
   <P>
  -While doing <CODE>perl Makefile.PL ...</CODE> mod_perl might complain by warning you about missing <CODE>libgdbm</CODE>. Users reported that it is actually crucial, and you must have it in order
  -to successfully complete the mod_perl building process.
  +The presented pros and cons lead to an idea, that probably you might want
  +squid more for its dynamic content buffering features, but only if your
  +server serves mostly dynamic requests. So in this situation it is better to
  +have a plain apache server serving static objects, and squid proxying the
  +mod_perl enabled server only. At least when performance is the goal.
   
   <P>
  -Now rename the <CODE>httpd</CODE> to <CODE>httpd_perl</CODE>:
  +For implementation details see: <A HREF="././scenario.html#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A> and
  +<A HREF="././scenario.html#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
   
  -<P>
  -<PRE>  % mv /usr/local/sbin/httpd_perl/httpd \
  -  /usr/local/sbin/httpd_perl/httpd_perl
  -</PRE>
  -<P>
  -Update the apachectl utility to point to renamed httpd name:
   
  -<P>
  -<PRE>  % perl -p -i -e 's|httpd_perl/httpd|httpd_perl/httpd_perl|' \
  -  /usr/local/sbin/httpd_perl/apachectl
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Configuration_of_the_servers">Configuration of the servers</A></H2></CENTER>
  -<P>
  -Now when we have completed the building process, the last stage before
  -running the servers, is to configure them.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Basic_httpd_docs_Server_s_Config">Basic httpd_docs Server's Configuration</A></H3></CENTER>
  -<P>
  -Configuring of <CODE>httpd_docs</CODE> server is a very easy task. Open
  -<CODE>/usr/local/etc/httpd_docs/httpd.conf</CODE> into your favorite editor (starting from version 1.3.4 of Apache - there is
  -only one file to edit). And configure it as you always do. Make sure you
  -configure the log files and other paths according to the directory layout
  -we decided to use.
  -
  +<CENTER><H1><A NAME="An_Apache_s_mod_proxy">An Apache's mod_proxy</A></H1></CENTER>
   <P>
  -Start the server with:
  +I do not think the difference in speed between apache's <STRONG>mod_proxy</STRONG>
  +and <STRONG>squid</STRONG> is relevant for most sites, since the real value of what they do is
  +buffering for slow client connections. However squid runs as a single
  +process and probably consumes fewer system resources. The trade-off is that
  +mod_rewrite is easy to use if you want to spread parts of the site across
  +different back end servers, and mod_proxy knows how to fix up redirects
  +containing the back-end server's idea of the location. With squid you can
  +run a redirector process to proxy to more than one back end, but there is a
  +problem in fixing redirects in a way that keeps the client's view of both
  +server names and port numbers in all cases. The difficult case being where
  +you have DNS aliases that map to the same IP address for an alias and you
  +want the redirect to use port 80 (when the server is really on a different
  +port) but you want it to keep the specific name the browser sent so it does
  +not change in the client's <STRONG>Location</STRONG> window.
   
  -<P>
  -<PRE>  /usr/local/sbin/httpd_docs/apachectl start
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Basic_httpd_perl_Server_s_Config">Basic httpd_perl Server's Configuration</A></H3></CENTER>
   <P>
  -Here we will make a basic configuration of the <CODE>httpd_perl</CODE> server. We edit the <CODE>/usr/local/etc/httpd_perl/httpd.conf</CODE> file. As with
  -<CODE>httpd_docs</CODE> server configuration, make sure that <CODE>ErrorLog</CODE> and other file's location directives are set to point to the right places,
  -according to the chosen directory layout.
  +The Advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -The first thing to do is to set a <CODE>Port</CODE> directive - it should be different from <CODE>80</CODE> since we cannot bind 2 servers to use the same port number on the same
  -machine. Here we will use <CODE>8080</CODE>. Some developers use port <CODE>81</CODE>, but you can bind to it, only if you have root permissions. If you are
  -running on multiuser machine, there is a chance someone already uses that
  -port, or will start using it in the future - which as you understand might
  -cause a collision. If you are the only user on your machine, basically you
  -can pick any not used port number. Port number choosing is a controversial
  -topic, since many organizations use firewalls, which may block some of the
  -ports, or enable only a known ones. From my experience the most used port
  -numbers are: <CODE>80</CODE>, <CODE>81</CODE>, <CODE>8000</CODE> and <CODE>8080</CODE>. Personally, I prefer the port <CODE>8080</CODE>. Of course with 2 server scenario you can hide the nonstandard port number
  -from firewalls and users, by either using the mod_proxy's <CODE>ProxyPass</CODE> or proxy server like squid.
  +No additional server is needed. We keep the one plain plus one mod_perl
  +enabled apache servers. All you need is to enable the
  +<CODE>mod_proxy</CODE> in the <CODE>httpd_docs</CODE> server and add a few lines to
  +<CODE>httpd.conf</CODE> file.
   
  +<P><LI>
   <P>
  -For more details see <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80 </A>, <A HREF="././scenario.html#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A>,
  -<A HREF="././scenario.html#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
  -and <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A>.
  +<CODE>ProxyPass</CODE> and <CODE>ProxyPassReverse</CODE> directives allow you to hide the internal redirects, so if <CODE>http://nowhere.com/modperl/</CODE> is actually
  +<CODE>http://localhost:81/modperl/</CODE>, it will be absolutely transparent for user. <CODE>ProxyPass</CODE> redirects the request to the mod_perl server, and when it gets the respond, <CODE>ProxyPassReverse</CODE> rewrites the URL back to the original one, e.g:
   
   <P>
  -Now we proceed to mod_perl specific directives. A good idea will be to add
  -them all at the end of the <CODE>httpd.conf</CODE>, since you are going to fiddle a lot with them at the beginning.
  -
  +<PRE>  ProxyPass        /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  +  ProxyPassReverse /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  +</PRE>
  +<P><LI>
   <P>
  -First, you need to specify the location where all mod_perl scripts will be
  -located.
  +It does mod_perl output buffering like squid does. See the <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A> notes for more details.
   
  +<P><LI>
   <P>
  -Add the following configuration directive:
  +It even does caching. You have to produce correct <CODE>Content-Length</CODE>,
  +<CODE>Last-Modified</CODE> and <CODE>Expires</CODE> http headers for it to work. If some dynamic content is not to change
  +constantly, you can dramatically increase performance by caching it with <CODE>ProxyPass</CODE>.
   
  -<P>
  -<PRE>    # mod_perl scripts will be called from
  -  Alias /perl/ /usr/local/myproject/perl/
  -</PRE>
  +<P><LI>
   <P>
  -From now on, all requests starting with <CODE>/perl</CODE> will be executed under <CODE>mod_perl</CODE> and will be mapped to the files in
  -<CODE>/usr/local/myproject/perl/</CODE>.
  +<CODE>ProxyPass</CODE> happens before the authentication phase, so you do not have to worry about
  +authenticating twice.
   
  +<P><LI>
   <P>
  -Now we should configure the <CODE>/perl</CODE> location.
  +Apache is able to accel https (secure) requests completely, while also
  +doing http accel. (with squid you have to use an external redirection
  +program for that).
   
  -<P>
  -<PRE>  PerlModule Apache::Registry
  -</PRE>
  -<P>
  -<PRE>  &lt;Location /perl&gt;
  -    #AllowOverride None
  -    SetHandler perl-script
  -    PerlHandler Apache::Registry
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  -</PRE>
  +<P><LI>
   <P>
  -This configuration causes all scripts that are called with a <CODE>/perl</CODE>
  -path prefix to be executed under the <CODE>Apache::Registry</CODE> module and as a CGI (so the <CODE>ExecCGI</CODE>, if you omit this option the script will be printed to the user's browser
  -as a plain text or will possibly trigger a '<STRONG>Save-As</STRONG>' window). <CODE>Apache::Registry</CODE> module lets you run almost unaltered CGI/perl scripts under <CODE>mod_perl</CODE>. <CODE>PerlModule</CODE> directive is an equivalent of perl's <CODE>require()</CODE>. We load the
  -<CODE>Apache::Registry</CODE> module before we use it in the <CODE>PerlHandler</CODE> in the <CODE>Location</CODE> configuration.
  +The latest (from apache 1.3.6) Apache proxy accel mode reported to be very
  +stable.
   
  +</UL>
   <P>
  -<CODE>PerlSendHeader On</CODE> tells the server to send an HTTP header to the browser on every script
  -invocation. You will want to turn this off for nph (non-parsed-headers)
  -scripts.
  +The Disadvantages:
   
  +<UL>
  +<P><LI>
   <P>
  -This is only a very basic configuration. <A HREF="././config.html#">Server Configuration</A> section covers the rest of the details.
  +Users reported that it might be a bit slow, but the latest version is fast
  +enough. (How fast is enough? :)
   
  +</UL>
   <P>
  -Now start the server with:
  +For implementation see <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A>.
   
  -<P>
  -<PRE>  /usr/local/sbin/httpd_perl/apachectl start
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A></H1></CENTER>
  -<P>
  -While I have detailed the mod_perl server installation, you are on your own
  -with installing the squid server (See <A HREF="././help.html#">Getting Helped</A> for more details). I run linux, so I downloaded the rpm package, installed
  -it, configured the <CODE>/etc/squid/squid.conf</CODE>, fired off the server and was all set. Basically once you have the squid
  -installed, you just need to modify the default <CODE>squid.conf</CODE> the way I will explain below, then you are ready to run it.
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     book can be purchased online from <a
  +	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  +	     and <a
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
   
  -<P>
  -First, let's understand what do we have in hands and what do we want from
  -squid. We have an <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE> servers listening on ports 81 and 8080 accordingly (we have to move the
  -httpd_docs server to port 81, since port 80 will be taken over by squid).
  -Both reside on the same machine as squid. We want squid to listen on port
  -80, forward a single static object request to the port httpd_docs server
  -listens to, and dynamic request to httpd_perl's port. Both servers return
  -the data to the proxy server (unless it is already cached in the squid), so
  -user never sees the other ports and never knows that there might be more
  -then one server running. Proxy server makes all the magic behind it
  -transparent to user. Do not confuse it with <STRONG>mod_rewrite</STRONG>, where a server redirects the request somewhere according to the rules and
  -forgets about it. The described functionality is being known as <CODE>httpd accelerator mode</CODE> in proxy dialect.
  +	     <HR>
   
  -<P>
  -You should understand that squid can be used as a straight forward proxy
  -server, generally used at companies and ISPs to cut down the incoming
  -traffic by caching the most popular requests. However we want to run it in
  -the <CODE>httpd accelerator mode</CODE>. Two directives:
  -<CODE>httpd_accel_host</CODE> and <CODE>httpd_accel_port</CODE> enable this mode. We will see more details in a few seconds. If you are
  -currently using the squid in the regular proxy mode, you can extend its
  -functionality by running both modes concurrently. To accomplish this, you
  -extend the existent squid configuration with <CODE>httpd accelerator mode</CODE>'s related directives or you just create one from scratch.
  +	     Your corrections of either technical or grammatical
  +	     errors are very welcome. You are encouraged to help me
  +	     to improve this guide.  If you have something to
  +	     contribute please <A
  +	     HREF="help.html#This_document_s_Author"> send it
  +	     directly to me</A>.
   
  -<P>
  -As stated before, squid listens now to the port 80, we have to move the
  -httpd_docs server to listen for example to the port 81 (your mileage may
  -vary :). So you have to modify the httpd.conf in the httpd_docs
  -configuration directory and restart the httpd_docs server (But not before
  -we get the squid running if you are working on the production server). And
  -as you remember httpd_perl listens to port 8080.
  +	     <HR>
   
  -<P>
  -Let's go through the changes we should make to the default configuration
  -file. Since this file (<CODE>/etc/squid/squid.conf</CODE>) is huge (about 60k+) and we would not use 95% of it, my suggestion is to
  -write a new one including only the modified directives.
  +	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]
   
  -<P>
  -We want to enable the redirect feature, to be able to serve requests, by
  -more then one server (in our case we have httpd_docs and httpd_perl)
  -servers. So we specify <CODE>httpd_accel_host</CODE> as virtual. This assumes that your server has multiple interfaces - Squid
  -will bind to all of them.
  +<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  +	     <HR>
  +  </TD>
  +</TR>
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <TD ALIGN=CENTER VALIGN=CENTER>
  +    <B>
  +      <FONT SIZE=-1>
  +	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  +	     <BR>Last Modified at 10/16/1999
  +      </FONT>
  +    </B>
  +  </TD>
  +
  +  <TD>
  +	     <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
  +  </TD>
  +
  +  <TD>
  +    <FONT SIZE=-2>
  +	     Use of the Camel for Perl is <BR>
  +	     a trademark of <A HREF="http://www.ora.com">O'Reilly &amp; Associates</A>,<BR>
  +             and is used by permission. 
  +    </FONT> 
  +  </TD>
  +</TR>
  +</TABLE></CENTER>
  +
  +</BODY>
  +</HTML>
  +	    
  +
  +<HR SIZE=6>
  +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  +<HTML>
  +<HEAD>
  +   <TITLE>mod_perl guide: Real World Scenarios Implementation</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
  +   <META NAME="Author" CONTENT="Stas Bekman">
  +   <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  +   <META NAME="keywords" CONTENT="mod_perl modperl perl apache cgi webserver speed  fast guide mod_perl apache guide help info faq mod_perl installation cgi troubleshooting help no sex speedup free open source OSS mod_perl apache guide">
  +</HEAD>
  +     <LINK REL=STYLESHEET TYPE="text/css"
  +        HREF="style.css" TITLE="refstyle">
  +     <style type="text/css">
  +     <!-- 
  +        @import url(style.css);
  +     -->
  +     
  +     </style>
  +<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
  +<A NAME="toc"></A>
  +<H1 ALIGN=CENTER>
  +<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
  +<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  +Real World Scenarios Implementation</H1>
  +<HR WIDTH="100%">
  +	    [    <A HREF="strategy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
  +	<UL>
  +
  +		<LI><A HREF="#Installation_in_10_lines">Installation in 10 lines</A>
  +		<LI><A HREF="#Installation_in_10_paragraphs">Installation in 10 paragraphs</A>
  +		<LI><A HREF="#Configuration_Process">Configuration Process</A>
  +	</UL>
  +
  +	<LI><A HREF="#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A>
  +	<UL>
  +
  +		<LI><A HREF="#Configuration_and_Compilation_of">Configuration and Compilation of the Sources.</A>
  +		<UL>
  +
  +			<LI><A HREF="#Building_the_httpd_docs_Server">Building the httpd_docs Server</A>
  +			<LI><A HREF="#Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A>
  +		</UL>
  +
  +		<LI><A HREF="#Configuration_of_the_servers">Configuration of the servers</A>
  +		<UL>
  +
  +			<LI><A HREF="#Basic_httpd_docs_Server_s_Config">Basic httpd_docs Server's Configuration</A>
  +			<LI><A HREF="#Basic_httpd_perl_Server_s_Config">Basic httpd_perl Server's Configuration</A>
  +		</UL>
  +
  +	</UL>
  +
  +	<LI><A HREF="#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
  +	<LI><A HREF="#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A>
  +	<LI><A HREF="#One_Light_and_One_Heavy_Servers_">One Light and One Heavy Servers where ALL htmls are Perl-Generated</A>
  +	<UL>
   
  +		<LI><A HREF="#Installation_and_Configuration">Installation and Configuration</A>
  +		<LI><A HREF="#Tricks_traps_and_gotchas">Tricks, traps and gotchas</A>
  +	</UL>
  +
  +	<LI><A HREF="#Building_and_Using_mod_proxy">Building and Using mod_proxy</A>
  +	<LI><A HREF="#HTTP_Authentication_with_2_serve">HTTP Authentication with 2 servers + proxy</A>
  +</UL>
  +<!-- INDEX END -->
  +
  +<HR>
  +
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     book can be purchased online from <a
  +	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  +	     and <a
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
  +
  +	     <HR>
  +
  +	       Your corrections of either technical or grammatical
  +	       errors are very welcome. You are encouraged to help me
  +	       to improve this guide.  If you have something to
  +	       contribute please <A
  +	       HREF="help.html#This_document_s_Author"> send it
  +	       directly to me</A>.
  +
  +	       <HR>
  +
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<PRE>  httpd_accel_host virtual
  -</PRE>
  +<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></CENTER>
   <P>
  -Then we define the default port - by default, if not redirected, httpd_docs
  -will serve the pages. We assume that most requests will be of the static
  -nature. We have our httpd_docs listening on port 81.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Installation_in_10_lines">Installation in 10 lines</A></H2></CENTER>
  +<P>
  +The Installation is very very simple (example of installation on Linux OS):
   
   <P>
  -<PRE>  httpd_accel_port 81
  +<PRE>  % cd /usr/src
  +  % lwp-download <A HREF="http://www.apache.org/dist/apache_x.x.x.tar.gz">http://www.apache.org/dist/apache_x.x.x.tar.gz</A>
  +  % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
  +  % tar zvxf apache_x.xx.tar.gz
  +  % tar zvxf mod_perl-x.xx.tar.gz
  +  % cd mod_perl-x.xx
  +  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  +    DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  +  % make &amp;&amp; make test &amp;&amp; make install
  +  % cd ../apache_x.x.x
  +  % make install
   </PRE>
   <P>
  -And as described before, squid listens to port 80.
  +That's all!
   
   <P>
  -<PRE>  http_port 80
  -</PRE>
  +Notes: Replace x.x.x with the real version numbers of mod_perl and apache.
  +gnu <CODE>tar</CODE> uncompresses as well (with <CODE>z</CODE> flag).
  +
   <P>
  -We do not use icp (icp used for cache sharing between neighbor machines),
  -which is more relevant in the proxy mode.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Installation_in_10_paragraphs">Installation in 10 paragraphs</A></H2></CENTER>
  +<P>
  +First download the sources of both packages, e.g. you can use
  +<CODE>lwp-download</CODE> utility to do it. <CODE>lwp-download</CODE> is a part of the LWP (or <CODE>libwww</CODE>) package, you will need to have it installed in order for mod_perl's <CODE>make test</CODE> to pass. Once you install this package unless it's already installed, <CODE>lwp-download</CODE> will be available for you as well.
   
   <P>
  -<PRE>  icp_port 0
  +<PRE>  % lwp-download <A HREF="http://www.apache.org/dist/apache_x.x.x.tar.gz">http://www.apache.org/dist/apache_x.x.x.tar.gz</A>
  +  % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
   </PRE>
   <P>
  -<CODE>hierarchy_stoplist</CODE> defines a list of words which, if found in a URL, causes the object to be
  -handled directly by this cache. In other words, use this to not query
  -neighbor caches for certain objects. Note that I have configured the <CODE>/cgi-bin</CODE> and <CODE>/perl</CODE> aliases for my dynamic documents, if you named them in a different way,
  -make sure to use the correct aliases here.
  +Extract both sources. Usually I open all the sources in <CODE>/usr/src/</CODE>, your mileage may vary. So move the sources and <CODE>chdir</CODE> to the directory, you want to put the sources in. Gnu <CODE>tar</CODE> utility knows to uncompress too with <CODE>z</CODE> flag, if you have a non-gnu <CODE>tar</CODE> utility, it will be incapable to decompress, so you would do it in two
  +steps: first uncompressing the packages with <CODE>gzip -d apache_x.xx.tar.gz</CODE>
  +and <CODE>gzip -d mod_perl-x.xx.tar.gz</CODE>, second un-tarring them with <CODE>tar
  +xvf apache_x.xx.tar</CODE> and <CODE>tar xvf mod_perl-x.xx.tar</CODE>.
   
   <P>
  -<PRE>  hierarchy_stoplist /cgi-bin /perl
  +<PRE>  % cd /usr/src
  +  % tar zvxf apache_x.xx.tar.gz
  +  % tar zvxf mod_perl-x.xx.tar.gz
   </PRE>
   <P>
  -Now we tell squid not to cache dynamic pages.
  +<CODE>chdir</CODE> to the mod_perl source directory:
   
   <P>
  -<PRE>  acl QUERY urlpath_regex /cgi-bin /perl
  -  no_cache deny QUERY
  +<PRE>  % cd mod_perl-x.xx
   </PRE>
   <P>
  -Please note that the last two directives are controversial ones. If you
  -want your scripts to be more complying with the HTTP standards, the headers
  -of your scripts should carry the <CODE>Caching Directives</CODE>
  -according to the HTTP specs. You will find a complete tutorial about this
  -topic in <CODE>Tutorial on HTTP Headers for mod_perl users</CODE> by Andreas J. Koenig (at <A
  -HREF="http://perl.apache.org">http://perl.apache.org</A> ). If you set the
  -headers correctly there is no need to tell squid accelerator to <STRONG>NOT</STRONG>
  -try to cache something. The headers I am talking about are
  -<CODE>Last-Modified</CODE> and <CODE>Expires</CODE>. What are they good for? Squid would not bother your mod_perl server a
  -second time if a request is (a) cachable and (b) still in the cache. Many
  -mod_perl applications will produce identical results on identical requests
  -at least if not much time goes by between the requests. So your squid might
  -have a hit ratio of 50%, which means that mod_perl servers will have as
  -twice as less work to do than before. This is only possible by setting the
  -headers correctly.
  +Now build the make file, for a basic work and first time installation the
  +parameters in the example below are the only ones you would need. <CODE>APACHE_SRC</CODE> tells where the apache <CODE>src</CODE> directory is. If you have followed my suggestion and have extracted the
  +both sources under the same directory (<CODE>/usr/src</CODE>), do:
   
   <P>
  -Even if you insert user-ID and date in your page, caching can save
  -resources when you set the expiration time to 1 second. A user might double
  -click where a single click would do, thus sending two requests in parallel,
  -squid could serve the second request.
  -
  +<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  +    DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  +</PRE>
   <P>
  -But if you are lazy, or just have too many things to deal with, you can
  -leave the above directives the way I described. But keep in mind that one
  -day you will want to reread this snippet and the Andreas' tutorial and
  -squeeze even more power from your servers without investing money for
  -additional memory and better hardware.
  +There are many additional parameters. You can find some of them in the
  +configuration dedicated and other sections. While running <CODE>perl
  +Makefile.PL ...</CODE> the process will check for prerequisites and tell you if something is
  +missing, If you are missing some of the perl packages or other software --
  +you will have to install these before you proceed.
   
   <P>
  -While testing you might want to enable the debugging options and watch the
  -log files in <CODE>/var/log/squid/</CODE>. But turn it off in your production server. I list it commented out. (28
  -== access control routes).
  +Now we <STRONG>make</STRONG> the project (by building the mod_perl extension and calling <CODE>make</CODE> in apache source directory to build a <CODE>httpd</CODE>),
  +<STRONG>test</STRONG> it (by running various tests) and <STRONG>install</STRONG> the mod_perl modules.
   
   <P>
  -<PRE>  # debug_options ALL, 1, 28, 9
  +<PRE>  % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -We need to provide a way for squid to dispatch the requests to the correct
  -servers, static object requests should be redirected to httpd_docs (unless
  -they are already cached), while dynamic should go to the httpd_perl server.
  -The configuration below tells squid to fire off 10 redirect daemons at the
  -specified path of the redirect daemon and disables rewriting of any <CODE>Host:</CODE> headers in redirected requests (as suggested by squid's documentation). The
  -redirection daemon script is enlisted below.
  +Note that if <STRONG>make</STRONG> fails, neither <STRONG>make test</STRONG> nor <STRONG>make
  +install</STRONG> will be not executed. If <STRONG>make test</STRONG> fails, <STRONG>make install</STRONG>
  +will be not executed.
   
   <P>
  -<PRE>  redirect_program /usr/lib/squid/redirect.pl
  -  redirect_children 10
  -  redirect_rewrites_host_header off
  +Now change to apache source directory and run <CODE>make install</CODE> to install apache's headers, default configuration files, to build apache
  +directory tree and to put the <CODE>httpd</CODE> there.
  +
  +<P>
  +<PRE>  % cd ../apache_x.x.x
  +  % make install
   </PRE>
   <P>
  -Maximum allowed request size in kilobytes. This one is pretty obvious. If
  -you are using POST to upload files, then set this to the largest file's
  -size plus a few extra kbytes.
  +When you execute the above command, apache installation process will tell
  +you how to start a freshly built webserver (the path of the
  +<CODE>apachectl</CODE>, more about it later) and where the configuration files are. Remember (or
  +even better write down) both, since you will need this information very
  +soon. On my machine the two important paths are:
   
   <P>
  -<PRE>  request_size 1000 KB
  +<PRE>  /usr/local/apache/bin/apachectl
  +  /usr/local/apache/conf/httpd.conf
   </PRE>
   <P>
  -Then we have access permissions, which I will not explain. But you might
  -want to read the documentation so to avoid any security flaws.
  +Now the build and the installation processes are completed. Just configure <CODE>httpd.conf</CODE> and start the webserver.
   
   <P>
  -<PRE>  acl all src 0.0.0.0/0.0.0.0
  -  acl manager proto cache_object
  -  acl localhost src 127.0.0.1/255.255.255.255
  -  acl myserver src 127.0.0.1/255.255.255.255
  -  acl SSL_ports port 443 563
  -  acl Safe_ports port 80 81 8080 81 443 563
  -  acl CONNECT method CONNECT
  -  
  -  http_access allow manager localhost
  -  http_access allow manager myserver
  -  http_access deny manager
  -  http_access deny !Safe_ports
  -  http_access deny CONNECT !SSL_ports
  -  # http_access allow all
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Configuration_Process">Configuration Process</A></H2></CENTER>
  +<P>
  +A basic configuration is a simple one. First configure the apache as you
  +always do (set <CODE>Port</CODE>, <CODE>User</CODE>, <CODE>Group</CODE>, correct <CODE>ErrorLog</CODE> and other file paths and etc), start the server and make sure it works. One
  +of the ways to start and stop the server is to use
  +<CODE>apachectl</CODE> utility:
  +
  +<P>
  +<PRE>  % /usr/local/apache/bin/apachectl start
  +  % /usr/local/apache/bin/apachectl stop
   </PRE>
   <P>
  -Since squid should be run as non-root user, you need these if you are
  -invoking the squid as root.
  +Shut the server down, open the <CODE>httpd.conf</CODE> in your favorite editor and scroll to the end of the file, where we will
  +add the mod_perl configuration directives (of course you can place them
  +anywhere in the file).
   
   <P>
  -<PRE>  cache_effective_user squid
  -  cache_effective_group squid
  +Add the following configuration directives:
  +
  +<P>
  +<PRE>  Alias /perl/ /home/httpd/perl/
   </PRE>
   <P>
  -Now configure a memory size to be used for caching. A squid documentation
  -warns that the actual size of squid can grow three times larger than the
  -value you are going to set.
  +Assuming that you put all your scripts, that should be executed by mod_perl
  +enabled server, under <CODE>/home/httpd/perl/</CODE> directory.
   
   <P>
  -<PRE>  cache_mem 20 MB
  +<PRE>  PerlModule Apache::Registry
  +  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    Options ExecCGI
  +    PerlSendHeader On
  +    allow from all
  +  &lt;/Location&gt;
   </PRE>
   <P>
  -Keep pools of allocated (but unused) memory available for future use. Read
  -more about it in the squid documents.
  +Now put a test script into <CODE>/home/httpd/perl/</CODE> directory:
   
   <P>
  -<PRE>  memory_pools on
  +<PRE>  test.pl
  +  -------
  +  #!/usr/bin/perl -w
  +  use strict;
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  print &quot;It worked!!!\n&quot;;
  +  -------
   </PRE>
   <P>
  -Now tight the runtime permissions of the cache manager CGI script (<CODE>cachemgr.cgi</CODE>,that comes bundled with squid) on your production server.
  +Make it executable and readable by server, if your server is running as
  +user <CODE>nobody</CODE> (hint: look for <CODE>User</CODE> directive in <CODE>httpd.conf</CODE>
  +file), do the following:
   
   <P>
  -<PRE>  cachemgr_passwd disable shutdown
  -  #cachemgr_passwd none all
  +<PRE>  % chown nobody /home/httpd/perl/test.pl
  +  % chmod u+rx   /home/httpd/perl/test.pl
   </PRE>
   <P>
  -Now the redirection daemon script (you should put it at the location you
  -have specified by <CODE>redirect_program</CODE> parameter in the config file above, and make it executable by webserver of
  -course):
  +Test that the script is running from the command line, by executing it:
   
   <P>
  -<PRE>  #!/usr/local/bin/perl
  -  
  -  $|=1;
  +<PRE>  % /home/httpd/perl/test.pl
  +</PRE>
  +<P>
  +You should see:
  +
  +<P>
  +<PRE>  Content-type: text/html
     
  -  while (&lt;&gt;) {
  -      # redirect to mod_perl server (httpd_perl)
  -    print($_), next if s|(:81)?/perl/|:8080/perl/|o;
  +  It worked!!!
   </PRE>
   <P>
  -<PRE>      # send it unchanged to plain apache server (http_docs)
  -    print;
  -  }
  +Now it is a time to test our mod_perl server, assuming that your config
  +file includes <CODE>Port 80</CODE>, go to your favorite Netscape browser and fetch the following URL (after
  +you have started the server):
  +
  +<P>
  +<PRE>  <A HREF="http://localhost/perl/test.pl">http://localhost/perl/test.pl</A>
   </PRE>
   <P>
  -In my scenario the proxy and the apache servers are running on the same
  -machine, that's why I just substitute the port. In the presented squid
  -configuration, requests that passed through squid are converted to point to
  -the <STRONG>localhost</STRONG> (which is <CODE>127.0.0.1</CODE>). The above redirector can be more complex of course, but you know the
  -perl, right?
  +Make sure that you have a loop-back device configured, if not -- use the
  +real server name for this test, for example:
   
   <P>
  -A few notes regarding redirector script:
  +<PRE>  <A HREF="http://www.nowhere.com/perl/test.pl">http://www.nowhere.com/perl/test.pl</A>
  +</PRE>
  +<P>
  +You should see:
   
   <P>
  -You must disable buffering. <CODE>$|=1;</CODE> does the job. If you do not disable buffering, the <CODE>STDOUT</CODE> will be flushed only when the buffer becomes full and its default size is
  -about 4096 characters. So if you have an average URL of 70 chars, only
  -after 59 (4096/70) requests the buffer will be flushed, and the requests
  -will finally achieve the server in target. Your users will just wait till
  -it will be filled up.
  +<PRE>  It worked!!!
  +</PRE>
  +<P>
  +If something went wrong, go through the installation process again, and
  +make sure you didn't make a mistake. If that doesn't help, read the <CODE>INSTALL</CODE> pod document (<CODE>perlpod INSTALL</CODE>) in the mod_perl distribution directory.
   
   <P>
  -If you think that it is a very ineffective way to redirect, I'll try to
  -prove you the opposite. The redirector runs as a daemon, it fires up N
  -redirect daemons, so there is no problem with perl interpreter loading,
  -exactly like mod_perl -- perl is loaded all the time and the code was
  -already compiled, so redirect is very fast (not slower if redirector was
  -written in C or alike). Squid keeps an open pipe to each redirect daemon,
  -thus there is even no overhead of the expensive system calls.
  +Now copy some of your perl/CGI scripts into a <CODE>/home/httpd/perl/</CODE>
  +directory and see them working much much faster, from the newly configured
  +base URL (<CODE>/perl/</CODE>). Some of your scripts will not work out of box and will demand some minor
  +tweaking or major rewrite to make them work properly with mod_perl enabled
  +server. Chances are that if you are not practicing a sloppy programming
  +techniques -- the scripts will work without any modifications at all.
   
   <P>
  -Now it is time to restart the server, at linux I do it with:
  +The above setup is very basic, it will help you to have a mod_perl enabled
  +server running and to get a good feeling from watching your previously slow
  +CGIs now flying.
   
   <P>
  -<PRE>  /etc/rc.d/init.d/squid restart
  -</PRE>
  +As with <STRONG>perl</STRONG> you can start benefit from <STRONG>mod_perl</STRONG> from the very first moment you try it. When you become more familiar with
  +mod_perl you will want to start writing apache handlers and deploy more of
  +the mod_perl power.
  +
   <P>
  -Now the setup is complete ...
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A></H1></CENTER>
  +<P>
  +Since we are going to run two apache servers we will need two different
  +sets of configuration, log and other files. We need a special directory
  +layout. While some of the directories can be shared between the two servers
  +(assuming that both are built from the same source distribution), others
  +should be separated. From now on I will refer to these two servers as <STRONG>httpd_docs</STRONG> (vanilla Apache) and
  +<STRONG>httpd_perl</STRONG> (Apache/mod_perl).
   
   <P>
  -Almost... When you try the new setup, you will be surprised and upset to
  -discover a port 81 showing up in the URLs of the static objects (like
  -htmls). Hey, we did not want the user to see the port 81 and use it instead
  -of 80, since then it will bypass the squid server and the hard work we went
  -through was just a waste of time? 
  +For this illustration, we will use <CODE>/usr/local</CODE> as our <EM>root</EM>
  +directory. The Apache installation directories will be stored under this
  +root (<CODE>/usr/local/bin</CODE>, <CODE>/usr/local/etc</CODE> and etc...)
   
   <P>
  -The solution is to run both squid and httpd_docs at the same port. This can
  -be accomplished by binding each one to a specific interface. Modify the <CODE>httpd.conf</CODE> in the <CODE>httpd_docs</CODE> configuration directory:
  +First let's prepare the sources. We will assume that all the sources go
  +into <CODE>/usr/src</CODE> dir. It is better when you use two separate copies of apache sources. Since
  +you probably will want to tune each apache version at separate and to do
  +some modifications and recompilations as the time goes. Having two
  +independent source trees will prove helpful, unless you use <CODE>DSO</CODE>, which is covered later in this section.
   
   <P>
  -<PRE>  Port 80
  -  BindAddress 127.0.0.1
  -  Listen 127.0.0.1:80
  +Make two subdirectories:
  +
  +<P>
  +<PRE>  % mkdir /usr/src/httpd_docs
  +  % mkdir /usr/src/httpd_perl
   </PRE>
   <P>
  -Modify the <CODE>squid.conf</CODE>:
  +Put the Apache sources into a <CODE>/usr/src/httpd_docs</CODE> directory:
   
   <P>
  -<PRE>  http_port 80
  -  tcp_incoming_address 123.123.123.3
  -  tcp_outgoing_address 127.0.0.1
  -  httpd_accel_host 127.0.0.1
  -  httpd_accel_port 80
  +<PRE>  % cd /usr/src/httpd_docs
  +  % gzip -dc /tmp/apache_x.x.x.tar.gz | tar xvf -
   </PRE>
   <P>
  -Where <CODE>123.123.123.3</CODE> should be replaced with IP of your main server. Now restart squid and
  -httpd_docs in either order you want, and voila the port number has gone.
  +If you have a gnu tar:
   
   <P>
  -You must also have in the <CODE>/etc/hosts</CODE> an entry (most chances that it's already there):
  +<PRE>  % tar xvzf /tmp/apache_x.x.x.tar.gz
  +</PRE>
  +<P>
  +Replace <CODE>/tmp</CODE> directory with a path to a downloaded file and
  +<CODE>x.x.x</CODE> with the version of the server you have.
   
   <P>
  -<PRE>  127.0.0.1  localhost.localdomain   localhost
  +<PRE>  % cd /usr/src/httpd_docs
  +  
  +  % ls -l
  +  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_x.x.x/
   </PRE>
   <P>
  -Now if your scripts were generating HTML including fully qualified self
  -references, using the 8080 or other port -- you should fix them to generate
  -links to point to port 80 (which means not using the port at all). If you
  -do not, users will bypass squid, like if it was not there at all, by making
  -direct requests to the mod_perl server's port.
  +Now we will prepare the <CODE>httpd_perl</CODE> server sources:
   
   <P>
  -The only question left is what to do with users who bookmarked your
  -services and they still have the port 8080 inside the URL. Do not worry
  -about it. The most important thing is for your scripts to return a full
  -URLs, so if the user comes from the link with 8080 port inside, let it be.
  -Just make sure that all the consecutive calls to your server will be
  -rewritten correctly. During a period of time users will change their
  -bookmarks. What can be done is to send them an email if you have one, or to
  -leave a note on your pages asking users to update their bookmarks. You
  -could avoid this problem if you did not publish this non-80 port in first
  -place. See <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>.
  +<PRE>  % cd /usr/src/httpd_perl
  +  % gzip -dc /tmp/apache_x.x.x.tar.gz | tar xvf -
  +  % gzip -dc /tmp/modperl-x.xx.tar.gz | tar xvf -
  +  
  +  % ls -l
  +  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_x.x.x/
  +  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 modperl-x.xx/
  +</PRE>
  +<P>
  +Time to decide on the desired directory structure layout (where the apache
  +files go):
   
   <P>
  -&lt;META&gt; Need to write up a section about server logging with squid.
  -One thing I sure would like to know is how requests are logged with this
  -setup. I have, as most everyone I imagine, log rotation, analysis,
  -archiving scripts and they all assume a single log. Does one have different
  -logs that have to be merged (up to 3 for each server + squid) ? Even when
  -squid responds to a request out of its cache I'd still want the thing to be
  -logged. &lt;/META&gt;
  +<PRE>  ROOT = /usr/local
  +</PRE>
  +<P>
  +The two servers can share the following directories (so we will not
  +duplicate data):
   
   <P>
  -See <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A> for information about <CODE>X-Forwarded-For</CODE>.
  +<PRE>  /usr/local/bin/
  +  /usr/local/lib
  +  /usr/local/include/
  +  /usr/local/man/
  +  /usr/local/share/
  +</PRE>
  +<P>
  +<STRONG>Important:</STRONG> we assume that both servers are built from the same Apache source version.
   
   <P>
  -To save you some keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
  +Servers store their specific files either in <CODE>httpd_docs</CODE> or
  +<CODE>httpd_perl</CODE> sub-directories:
   
   <P>
  -<PRE>  http_port 80
  -  tcp_incoming_address 123.123.123.3
  -  tcp_outgoing_address 127.0.0.1
  -  httpd_accel_host 127.0.0.1
  -  httpd_accel_port 80
  +<PRE>  /usr/local/etc/httpd_docs/
  +                 httpd_perl/
     
  -  icp_port 0
  -  
  -  hierarchy_stoplist /cgi-bin /perl
  -  acl QUERY urlpath_regex /cgi-bin /perl
  -  no_cache deny QUERY
  -  
  -  # debug_options ALL,1 28,9
  -  
  -  redirect_program /usr/lib/squid/redirect.pl
  -  redirect_children 10
  -  redirect_rewrites_host_header off
  -  
  -  request_size 1000 KB
  -  
  -  acl all src 0.0.0.0/0.0.0.0
  -  acl manager proto cache_object
  -  acl localhost src 127.0.0.1/255.255.255.255
  -  acl myserver src 127.0.0.1/255.255.255.255
  -  acl SSL_ports port 443 563
  -  acl Safe_ports port 80 81 8080 81 443 563
  -  acl CONNECT method CONNECT
  -  
  -  http_access allow manager localhost
  -  http_access allow manager myserver
  -  http_access deny manager
  -  http_access deny !Safe_ports
  -  http_access deny CONNECT !SSL_ports
  -  # http_access allow all
  -  
  -  cache_effective_user squid
  -  cache_effective_group squid
  -  
  -  cache_mem 20 MB
  -  
  -  memory_pools on
  +  /usr/local/sbin/httpd_docs/
  +                  httpd_perl/
     
  -  cachemgr_passwd disable shutdown
  +  /usr/local/var/httpd_docs/logs/
  +                            proxy/
  +                            run/
  +                 httpd_perl/logs/
  +                            proxy/
  +                            run/
   </PRE>
   <P>
  -Note that all directives should start at the beginning of the line.
  +After completion of the compilation and the installation of the both
  +servers, you will need to configure them. To make things clear before we
  +proceed into details, you should configure the
  +<CODE>/usr/local/etc/httpd_docs/httpd.conf</CODE> as a plain apache and <CODE>Port</CODE>
  +directive to be 80 for example. And
  +<CODE>/usr/local/etc/httpd_perl/httpd.conf</CODE> to configure for mod_perl server and of course whose <CODE>Port</CODE> should be different from the one
  +<CODE>httpd_docs</CODE> server listens to (e.g. 8080). The port numbers issue will be discussed
  +later.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A></H1></CENTER>
  -<P>
  -When I was first told about squid, I thought: ``Hey, Now I can drop the
  -<CODE>httpd_docs</CODE> server and to have only squid and <CODE>httpd_perl</CODE>
  -servers``. Since all my static objects will be cached by squid, I do not
  -need the light <CODE>httpd_docs</CODE> server. But it was a wrong assumption. Why? Because you still have the
  -overhead of loading the objects into squid at first time, and if your site
  -has many of them -- not all of them will be cached (unless you have devoted
  -a huge chunk of memory to squid) and my heavy mod_perl servers will still
  -have an overhead of serving the static objects. How one would measure the
  -overhead? The difference between the two servers is memory consumption,
  -everything else (e.g. I/O) should be equal. So you have to estimate the
  -time needed for first time fetching of each static object at a peak period
  -and thus the number of additional servers you need for serving the static
  -objects. This will allow you to calculate additional memory requirements. I
  -can imagine, this amount could be significant in some installations.
  +The next step is to configure and compile the sources: Below are the
  +procedures to compile both servers taking into account the directory layout
  +I have just suggested to use.
   
   <P>
  -So I have decided to have even more administration overhead and to stick
  -with squid, httpd_docs and httpd_perl scenario, where I can optimize and
  -fine tune everything. Of course this can be not your case. If you are
  -feeling that the scenario from the previous section is too complicated for
  -you, make it simpler. Have only one server with mod_perl built in and let
  -the squid to do most of the job that plain light apache used to do. As I
  -have explained in the previous paragraph, you should pick this lighter
  -setup only if you can make squid cache most of your static objects. If it
  -cannot, your mod_perl server will do the work we do not want it to.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Configuration_and_Compilation_of">Configuration and Compilation of the Sources.</A></H2></CENTER>
   <P>
  -If you are still with me, install apache with mod_perl and squid. Then use
  -a similar configuration from the previous section, but now httpd_docs is
  -not there anymore. Also we do not need the redirector anymore and we
  -specify <CODE>httpd_accel_host</CODE> as a name of the server and not <CODE>virtual</CODE>. There is no need to bind two servers on the same port, because we do not
  -redirect and there is neither <CODE>Bind</CODE> nor <CODE>Listen</CODE>
  -directives in the <CODE>httpd.conf</CODE> anymore.
  +Let's proceed with installation. I will use x.x.x instead of real version
  +numbers so this document will never become obsolete :).
   
   <P>
  -The modified configuration (see the explanations in the previous section):
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Building_the_httpd_docs_Server">Building the httpd_docs Server</A></H3></CENTER>
  +<DL>
  +<P><DT><STRONG><A NAME="item_Sources">Sources Configuration:</A></STRONG><DD>
   <P>
  -<PRE>  httpd_accel_host put.your.hostname.here
  -  httpd_accel_port 8080
  -  http_port 80
  -  icp_port 0
  -  
  -  hierarchy_stoplist /cgi-bin /perl
  -  acl QUERY urlpath_regex /cgi-bin /perl
  -  no_cache deny QUERY
  -  
  -  # debug_options ALL, 1, 28, 9
  -  
  -  # redirect_program /usr/lib/squid/redirect.pl
  -  # redirect_children 10
  -  # redirect_rewrites_host_header off
  -  
  -  request_size 1000 KB
  -  
  -  acl all src 0.0.0.0/0.0.0.0
  -  acl manager proto cache_object
  -  acl localhost src 127.0.0.1/255.255.255.255
  -  acl myserver src 127.0.0.1/255.255.255.255
  -  acl SSL_ports port 443 563
  -  acl Safe_ports port 80 81 8080 81 443 563
  -  acl CONNECT method CONNECT
  -  
  -  http_access allow manager localhost
  -  http_access allow manager myserver
  -  http_access deny manager
  -  http_access deny !Safe_ports
  -  http_access deny CONNECT !SSL_ports
  -  # http_access allow all
  -  
  -  cache_effective_user squid
  -  cache_effective_group squid
  -  
  -  cache_mem 20 MB
  -  
  -  memory_pools on
  -  
  -  cachemgr_passwd disable shutdown
  +<PRE>  % cd /usr/src/httpd_docs/apache_x.x.x
  +  % make clean
  +  % env CC=gcc \
  +  ./configure --prefix=/usr/local \
  +    --sbindir=/usr/local/sbin/httpd_docs \
  +    --sysconfdir=/usr/local/etc/httpd_docs \
  +    --localstatedir=/usr/local/var/httpd_docs \
  +    --runtimedir=/usr/local/var/httpd_docs/run \
  +    --logfiledir=/usr/local/var/httpd_docs/logs \
  +    --proxycachedir=/usr/local/var/httpd_docs/proxy
   </PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Building_and_Using_mod_proxy">Building and Using mod_proxy</A></H1></CENTER>
  -<P>
  -To build it into apache just add <STRONG>--enable-module=proxy</STRONG> during the apache <STRONG>configure</STRONG> stage.
  +If you need some other modules, like mod_rewrite and mod_include (SSI), add
  +them here as well:
   
   <P>
  -Now we will talk about apache's mod_proxy and understand how it works.
  +<PRE>    --enable-module=include --enable-module=rewrite
  +</PRE>
  +<P>
  +Note: <CODE>gcc</CODE> -- compiles httpd by 100K+ smaller then <CODE>cc</CODE> on AIX OS. Remove the line <CODE>env CC=gcc</CODE> if you want to use the default compiler. If you want to use it and you are
  +a (ba)?sh user you will not need the
  +<CODE>env</CODE> function, t?csh users will have to keep it in.
   
   <P>
  -The server on port 80 answers http requests directly and proxies the
  -mod_perl enabled server in the following way:
  +Note: add <CODE>--layout</CODE> to see the resulting directories' layout without actually running the
  +configuration process.
   
  +<P><DT><STRONG>Sources Compilation:</STRONG><DD>
   <P>
  -<PRE>  ProxyPass        /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  -  ProxyPassReverse /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  +<PRE>  % make
  +  % make install
   </PRE>
   <P>
  -<CODE>PPR</CODE> is the saving grace here, that makes apache a win over Squid. It rewrites
  -the redirect on its way back to the original URI.
  +Rename <CODE>httpd</CODE> to <CODE>http_docs</CODE>
   
  -<P>
  -You can control the buffering feature with <CODE>ProxyReceiveBufferSize</CODE>
  -directive:
   
  +
   <P>
  -<PRE>  ProxyReceiveBufferSize 1048576
  +<PRE>  % mv /usr/local/sbin/httpd_docs/httpd \
  +  /usr/local/sbin/httpd_docs/httpd_docs
   </PRE>
   <P>
  -The above setting will set a buffer size to be of 1Mb. If it is not set
  -explicitly, then the default buffer size is used, which depends on OS, for
  -Linux I suspect it is somewhere below 32k. So basically to get an immediate
  -release of the mod_perl server from stale awaiting,
  -<CODE>ProxyReceiveBufferSize</CODE> should be set to a value greater than the biggest generated respond
  -produced by any mod_perl script.
  +Now update an <STRONG>apachectl</STRONG> utility to point to the renamed httpd via your favorite text editor or by
  +using perl:
   
   <P>
  -The <CODE>ProxyReceiveBufferSize</CODE> directive specifies an explicit buffer size for <STRONG>outgoing</STRONG> HTTP and FTP connections. It has to be greater than 512 or set to 0 to
  -indicate that the system's default buffer size should be used.
  -
  +<PRE>  % perl -p -i -e 's|httpd_docs/httpd|httpd_docs/httpd_docs|' \
  +  /usr/local/sbin/httpd_docs/apachectl
  +</PRE>
  +</DL>
   <P>
  -As the name states, its buffering feature applies only to <STRONG>downstream
  -data</STRONG> (coming from the origin server to the proxy) and not upstream (i.e.
  -buffering the data being uploaded from the client browser to the proxy,
  -thus freeing the httpd_perl origin server from being tied up during a large
  -POST such as a file upload).
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A></H3></CENTER>
   <P>
  -Apache does caching as well. It's relevant to mod_perl only if you produce
  -proper headers, so your scripts' output can be cached. See apache
  -documentation for more details on configuration of this capability.
  +Before you start to configure the mod_perl sources, you should be aware
  +that there are a few Perl modules that have to be installed before building
  +mod_perl. You will be alerted if any required modules are missing when you
  +run the <CODE>perl Makefile.PL</CODE> command line below. If you discover that some are missing, pick them from
  +your nearest CPAN repository (if you do not know what is it, make a visit
  +to <A HREF="http://www.perl.com/CPAN">http://www.perl.com/CPAN</A> ) or run
  +the <CODE>CPAN</CODE> interactive shell via the command line <CODE>perl -MCPAN -e shell</CODE>.
   
   <P>
  -Ask Bjoern Hansen has written a <CODE>mod_proxy_add_forward</CODE> module for apache, that sets the <CODE>X-Forwarded-For</CODE> field when doing a
  -<CODE>ProxyPass</CODE>, similar to what squid can do. (Its location is specified in the help
  -section). Basically, that module adds an extra HTTP header to proxying
  -requests. You can access that header in the mod_perl-enabled server, and
  -set the IP of the remote server. You won't need to compile anything into
  -the back-end server, if you are using <CODE>Apache::{Registry,PerlRun}</CODE> just put something like the following into <CODE>start-up.pl</CODE>:
  +Make sure the sources are clean:
   
   <P>
  -<PRE>  sub My::ProxyRemoteAddr ($) {
  -    my $r = shift;
  -   
  -        # we'll only look at the X-Forwarded-For header if the requests
  -        # comes from our proxy at localhost
  -        return OK unless ($r-&gt;connection-&gt;remote_ip eq &quot;127.0.0.1&quot;);
  -   
  -        if (my ($ip) = $r-&gt;header_in('X-Forwarded-For') =~ /([^,\s]+)$/) {
  -          $r-&gt;connection-&gt;remote_ip($ip);
  -        }
  -        
  -        return OK;
  -  }
  +<PRE>  % cd /usr/src/httpd_perl/apache_x.x.x
  +  % make clean
  +  % cd /usr/src/httpd_perl/mod_perl-x.xx
  +  % make clean
   </PRE>
   <P>
  -And in <CODE>httpd.conf</CODE>:
  +It is important to <STRONG>make clean</STRONG> since some of the versions are not binary compatible (e.g apache 1.3.3 vs
  +1.3.4) so any ``third-party'' C modules need to be re-compiled against the
  +latest header files.
   
   <P>
  -<PRE>  PerlPostReadRequestHandler My::ProxyRemoteAddr
  -</PRE>
  -<P>
  -Different sites have different needs. If you're using the header to set the
  -IP address, apache believes it is dealing with (in the logging and stuff),
  -you really don't want anyone but your own system to set the header. That's
  -why the above ``recommended code'' checks where the request is really
  -coming from, before changing the <CODE>remote_ip</CODE>.
  +Here I did not find a way to compile with <CODE>gcc</CODE> (my perl was compiled with <CODE>cc</CODE> so we have to compile with the same compiler!!!
   
   <P>
  -Generally you shouldn't trust the <CODE>X-Forwarded-For</CODE> header. You only want to rely on <CODE>X-Forwarded-For</CODE> headers from proxies you control yourself. If you know how to spoof a
  -cookie you've probably got the general idea on making HTTP headers and can
  -spoof the
  -<CODE>X-Forwarded-For</CODE> header as well. The only address *you* can count on as being a reliable
  -value is the one from
  -<CODE>r-&amp;gt;connection-&amp;gt;remote_ip</CODE>.
  -
  +<PRE>  % cd /usr/src/httpd_perl/mod_perl-x.xx
  +</PRE>
   <P>
  -From that point on, the remote IP address is correct. You should be able to
  -access <CODE>REMOTE_ADDR</CODE> as usual.
  +<PRE>  % /usr/local/bin/perl Makefile.PL \
  +  APACHE_PREFIX=/usr/local/ \
  +  APACHE_SRC=../apache_x.x.x/src \
  +  DO_HTTPD=1 \
  +  USE_APACI=1 \
  +  PERL_MARK_WHERE=1 \
  +  PERL_STACKED_HANDLERS=1 \
  +  ALL_HOOKS=1 \
  +  APACI_ARGS=--sbindir=/usr/local/sbin/httpd_perl, \
  +         --sysconfdir=/usr/local/etc/httpd_perl, \
  +         --localstatedir=/usr/local/var/httpd_perl, \
  +         --runtimedir=/usr/local/var/httpd_perl/run, \
  +         --logfiledir=/usr/local/var/httpd_perl/logs, \
  +         --proxycachedir=/usr/local/var/httpd_perl/proxy
  +</PRE>
  +<P>
  +Notice that <STRONG>all</STRONG>  <CODE>APACI_ARGS</CODE> (above) must be passed as one long line if you work with <CODE>t?csh</CODE>!!! However it works correctly the way it shown above with <CODE>(ba)?sh</CODE> (by breaking the long lines with '<CODE>\</CODE>'). If you work with <CODE>t?csh</CODE> it does not work, since <CODE>t?csh</CODE>
  +passes <CODE>APACI_ARGS</CODE> arguments to <CODE>./configure</CODE> by keeping the new lines untouched, but stripping the original '<CODE>\</CODE>', thus breaking the configuration process.
   
   <P>
  -You could do the same thing with other environment variables (though I
  -think several of them are preserved, you will want to run some tests to see
  -which ones).
  +As with <CODE>httpd_docs</CODE> you might need other modules like
  +<CODE>mod_rewrite</CODE>, so add them here:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_server_as_DSO">mod_perl server as DSO</A></H1></CENTER>
  +<PRE>         --enable-module=rewrite
  +</PRE>
   <P>
  -To build the mod_perl as DSO add <CODE>USE_DSO=1</CODE> to the rest of configuration parameters (to build <CODE>libperl.so</CODE> instead of
  -<CODE>libperl.a</CODE>), like:
  +Note: <CODE>PERL_STACKED_HANDLERS=1</CODE> is needed for <CODE>Apache::DBI</CODE>
  +
  +
   
   <P>
  -<PRE>  perl Makefile.PL USE_DSO=1 ...
  +Now, build, test and install the <CODE>httpd_perl</CODE>.
  +
  +<P>
  +<PRE>  % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -If you run <CODE>./configure</CODE> from apache source do not forget to add:
  -<CODE>--enable-shared=perl</CODE>
  +Note: apache puts a stripped version of <CODE>httpd</CODE> at
  +<CODE>/usr/local/sbin/httpd_perl/httpd</CODE>. The original version which includes debugging symbols (if you need to run
  +a debugger on this executable) is located at
  +<CODE>/usr/src/httpd_perl/apache_x.x.x/src/httpd</CODE>.
   
  +<P>
  +Note: You may have noticed that we did not run <CODE>make install</CODE> in the apache's source directory. When <CODE>USE_APACI</CODE> is enabled,
  +<CODE>APACHE_PREFIX</CODE> will specify the <CODE>--prefix</CODE> option for apache's
  +<CODE>configure</CODE> utility, specifying the installation path for apache. When this option is
  +used, mod_perl's <CODE>make install</CODE> will also
  +<CODE>make install</CODE> on the apache side, installing the httpd binary, support tools, along with
  +the configuration, log and document trees.
   
  +<P>
  +If <CODE>make test</CODE> fails, look into <CODE>t/logs</CODE> and see what is in there. Also see <A HREF="././install.html#make_test_fails">make test fails</A>.
   
   <P>
  -Then just add the <CODE>LoadModule</CODE> directive into your <CODE>httpd.conf</CODE>.
  +While doing <CODE>perl Makefile.PL ...</CODE> mod_perl might complain by warning you about missing <CODE>libgdbm</CODE>. Users reported that it is actually crucial, and you must have it in order
  +to successfully complete the mod_perl building process.
   
   <P>
  -You will find a complete explanation in the <CODE>INSTALL.apaci</CODE> pod which can be found in the mod_perl distribution.
  +Now rename the <CODE>httpd</CODE> to <CODE>httpd_perl</CODE>:
   
   <P>
  -Some people reported that DSO compiled mod_perl would not run on specific
  -OS/perl version. Also threads enabled perl reported sometimes to break the
  -mod_perl/DSO. But it still can work for you.
  +<PRE>  % mv /usr/local/sbin/httpd_perl/httpd \
  +  /usr/local/sbin/httpd_perl/httpd_perl
  +</PRE>
  +<P>
  +Update the apachectl utility to point to renamed httpd name:
   
   <P>
  +<PRE>  % perl -p -i -e 's|httpd_perl/httpd|httpd_perl/httpd_perl|' \
  +  /usr/local/sbin/httpd_perl/apachectl
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="HTTP_Authentication_with_2_serve">HTTP Authentication with 2 servers + proxy</A></H1></CENTER>
  +<CENTER><H2><A NAME="Configuration_of_the_servers">Configuration of the servers</A></H2></CENTER>
   <P>
  -Assuming that you have a setup of one ``front-end'' server, which proxies
  -the ``back-end'' (mod_perl) server, if you need to perform the
  -authentication in the ``back-end'' server, it should handle all
  -authentication itself. If apache proxies correctly, it seems like it would
  -pass through all authentication information, making the ``front-end''
  -apache somewhat ``dumb'', as it does nothing, but passes through all the
  -information.
  +Now when we have completed the building process, the last stage before
  +running the servers, is to configure them.
   
   <P>
  -The only possible caveat in the config file is that your <CODE>Auth</CODE> stuff needs to be in <CODE>&lt;Directory ...</CODE>&gt; ... <CODE>&lt;/Directory</CODE>&gt; tags because if you use a <CODE>&lt;Location /...</CODE>&gt; ... <CODE>&lt;/Location</CODE>&gt; the proxypass server takes the auth info for its own authentication
  -and would not pass it on.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Basic_httpd_docs_Server_s_Config">Basic httpd_docs Server's Configuration</A></H3></CENTER>
  +<P>
  +Configuring of <CODE>httpd_docs</CODE> server is a very easy task. Open
  +<CODE>/usr/local/etc/httpd_docs/httpd.conf</CODE> into your favorite editor (starting from version 1.3.4 of Apache - there is
  +only one file to edit). And configure it as you always do. Make sure you
  +configure the log files and other paths according to the directory layout
  +we decided to use.
   
   <P>
  -The same with mod_ssl, if plugged into a front-end server, all the SSL
  -requests be encoded/decoded properly by it.
  +Start the server with:
   
  +<P>
  +<PRE>  /usr/local/sbin/httpd_docs/apachectl start
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -	     The <a href="http://www.modperl.com/">
  -	     <B>Writing Apache Modules with Perl and C</B></a>
  -	     book can be purchased online from <a
  -	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  -	     and <a
  -	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  -	     Amazon.com</a>.
  -
  -	     <HR>
  -
  -	     Your corrections of either technical or grammatical
  -	     errors are very welcome. You are encouraged to help me
  -	     to improve this guide.  If you have something to
  -	     contribute please <A
  -	     HREF="help.html#This_document_s_Author"> send it
  -	     directly to me</A>.
  +<CENTER><H3><A NAME="Basic_httpd_perl_Server_s_Config">Basic httpd_perl Server's Configuration</A></H3></CENTER>
  +<P>
  +Here we will make a basic configuration of the <CODE>httpd_perl</CODE> server. We edit the <CODE>/usr/local/etc/httpd_perl/httpd.conf</CODE> file. As with
  +<CODE>httpd_docs</CODE> server configuration, make sure that <CODE>ErrorLog</CODE> and other file's location directives are set to point to the right places,
  +according to the chosen directory layout.
   
  -	     <HR>
  +<P>
  +The first thing to do is to set a <CODE>Port</CODE> directive - it should be different from <CODE>80</CODE> since we cannot bind 2 servers to use the same port number on the same
  +machine. Here we will use <CODE>8080</CODE>. Some developers use port <CODE>81</CODE>, but you can bind to it, only if you have root permissions. If you are
  +running on multiuser machine, there is a chance someone already uses that
  +port, or will start using it in the future - which as you understand might
  +cause a collision. If you are the only user on your machine, basically you
  +can pick any not used port number. Port number choosing is a controversial
  +topic, since many organizations use firewalls, which may block some of the
  +ports, or enable only a known ones. From my experience the most used port
  +numbers are: <CODE>80</CODE>, <CODE>81</CODE>, <CODE>8000</CODE> and <CODE>8080</CODE>. Personally, I prefer the port <CODE>8080</CODE>. Of course with 2 server scenario you can hide the nonstandard port number
  +from firewalls and users, by either using the mod_proxy's <CODE>ProxyPass</CODE> or proxy server like squid.
   
  -	     [    <A HREF="strategy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A>      ]
  +<P>
  +For more details see <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80 </A>, <A HREF="././scenario.html#Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A>,
  +<A HREF="././scenario.html#Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A>
  +and <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A>.
   
  -<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
  -<TR ALIGN=CENTER VALIGN=TOP>
  -  <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  -	     <HR>
  -  </TD>
  -</TR>
  -<TR ALIGN=CENTER VALIGN=TOP>
  -  <TD ALIGN=CENTER VALIGN=CENTER>
  -    <B>
  -      <FONT SIZE=-1>
  -	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  -      </FONT>
  -    </B>
  -  </TD>
  +<P>
  +Now we proceed to mod_perl specific directives. A good idea will be to add
  +them all at the end of the <CODE>httpd.conf</CODE>, since you are going to fiddle a lot with them at the beginning.
   
  -  <TD>
  -	     <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
  -  </TD>
  +<P>
  +First, you need to specify the location where all mod_perl scripts will be
  +located.
   
  -  <TD>
  -    <FONT SIZE=-2>
  -	     Use of the Camel for Perl is <BR>
  -	     a trademark of <A HREF="http://www.ora.com">O'Reilly &amp; Associates</A>,<BR>
  -             and is used by permission. 
  -    </FONT> 
  -  </TD>
  -</TR>
  -</TABLE></CENTER>
  +<P>
  +Add the following configuration directive:
   
  -</BODY>
  -</HTML>
  -	    
  +<P>
  +<PRE>    # mod_perl scripts will be called from
  +  Alias /perl/ /usr/local/myproject/perl/
  +</PRE>
  +<P>
  +From now on, all requests starting with <CODE>/perl</CODE> will be executed under <CODE>mod_perl</CODE> and will be mapped to the files in
  +<CODE>/usr/local/myproject/perl/</CODE>.
   
  -<HR SIZE=6>
  -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  -<HTML>
  -<HEAD>
  -   <TITLE>mod_perl guide: Installation Notes</TITLE>
  -   <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
  -   <META NAME="Author" CONTENT="Stas Bekman">
  -   <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  -   <META NAME="keywords" CONTENT="mod_perl modperl perl apache cgi webserver speed  fast guide mod_perl apache guide help info faq mod_perl installation cgi troubleshooting help no sex speedup free open source OSS mod_perl apache guide">
  -</HEAD>
  -     <LINK REL=STYLESHEET TYPE="text/css"
  -        HREF="style.css" TITLE="refstyle">
  -     <style type="text/css">
  -     <!-- 
  -        @import url(style.css);
  -     -->
  -     
  -     </style>
  -<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
  -<A NAME="toc"></A>
  -<H1 ALIGN=CENTER>
  -<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
  -<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Installation Notes</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="scenario.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="config.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  -<UL>
  +<P>
  +Now we should configure the <CODE>/perl</CODE> location.
   
  -	<LI><A HREF="#Configuration_and_Installation">Configuration and Installation</A>
  -	<UL>
  +<P>
  +<PRE>  PerlModule Apache::Registry
  +</PRE>
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    #AllowOverride None
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    Options ExecCGI
  +    allow from all
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +This configuration causes all scripts that are called with a <CODE>/perl</CODE>
  +path prefix to be executed under the <CODE>Apache::Registry</CODE> module and as a CGI (so the <CODE>ExecCGI</CODE>, if you omit this option the script will be printed to the user's browser
  +as a plain text or will possibly trigger a '<STRONG>Save-As</STRONG>' window). <CODE>Apache::Registry</CODE> module lets you run almost unaltered CGI/perl scripts under <CODE>mod_perl</CODE>. <CODE>PerlModule</CODE> directive is an equivalent of perl's <CODE>require()</CODE>. We load the
  +<CODE>Apache::Registry</CODE> module before we use it in the <CODE>PerlHandler</CODE> in the <CODE>Location</CODE> configuration.
   
  -		<LI><A HREF="#perl">perl</A>
  -		<LI><A HREF="#apache">apache</A>
  -		<LI><A HREF="#mod_perl">mod_perl</A>
  -	</UL>
  +<P>
  +<CODE>PerlSendHeader On</CODE> tells the server to send an HTTP header to the browser on every script
  +invocation. You will want to turn this off for nph (non-parsed-headers)
  +scripts.
   
  -	<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
  -	<UL>
  +<P>
  +This is only a very basic configuration. <A HREF="././config.html#">Server Configuration</A> section covers the rest of the details.
   
  -		<LI><A HREF="#Testing_by_checking_the_error_lo">Testing by checking the error_log file</A>
  -		<LI><A HREF="#Testing_by_viewing_perl_status">Testing by viewing /perl-status</A>
  -		<LI><A HREF="#Testing_via_telnet">Testing via telnet</A>
  -		<LI><A HREF="#Testing_via_a_CGI_script">Testing via a CGI script</A>
  -		<LI><A HREF="#Testing_via_lwp_request">Testing via lwp-request</A>
  -	</UL>
  +<P>
  +Now start the server with:
   
  -	<LI><A HREF="#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
  -	<LI><A HREF="#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
  -	<LI><A HREF="#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
  -	<LI><A HREF="#Server_Installation_problems">Server Installation problems</A>
  -	<UL>
  -
  -		<LI><A HREF="#_skipping_test_on_this_plat">......skipping test on this platform</A>
  -		<LI><A HREF="#make_test_fails">make test fails</A>
  -		<LI><A HREF="#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
  -		<LI><A HREF="#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
  -	</UL>
  -
  -	<LI><A HREF="#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
  -	<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  -</UL>
  -<!-- INDEX END -->
  -
  -<HR>
  -
  -	     The <a href="http://www.modperl.com/">
  -	     <B>Writing Apache Modules with Perl and C</B></a>
  -	     book can be purchased online from <a
  -	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  -	     and <a
  -	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  -	     Amazon.com</a>.
  -
  -	     <HR>
  -
  -	       Your corrections of either technical or grammatical
  -	       errors are very welcome. You are encouraged to help me
  -	       to improve this guide.  If you have something to
  -	       contribute please <A
  -	       HREF="help.html#This_document_s_Author"> send it
  -	       directly to me</A>.
  -
  -	       <HR>
  -
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
  +<PRE>  /usr/local/sbin/httpd_perl/apachectl start
  +</PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="perl">perl</A></H2></CENTER>
  +<CENTER><H1><A NAME="Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</A></H1></CENTER>
   <P>
  -Make sure you have perl installed -- the newer stable version you have the
  -better (minimum perl.5.004!). If you don't have it -- install it. Follow
  -the instructions in the distribution's <CODE>INSTALL</CODE>
  -file. During the configuration stage (while running <CODE>./Configure</CODE>), make sure you answer <CODE>YES</CODE> to the question:
  +While I have detailed the mod_perl server installation, you are on your own
  +with installing the squid server (See <A HREF="././help.html#">Getting Helped</A> for more details). I run linux, so I downloaded the rpm package, installed
  +it, configured the <CODE>/etc/squid/squid.conf</CODE>, fired off the server and was all set. Basically once you have the squid
  +installed, you just need to modify the default <CODE>squid.conf</CODE> the way I will explain below, then you are ready to run it.
   
   <P>
  -<PRE>  Do you wish to use dynamic loading? [y]
  -</PRE>
  +First, let's understand what do we have in hands and what do we want from
  +squid. We have an <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE> servers listening on ports 81 and 8080 accordingly (we have to move the
  +httpd_docs server to port 81, since port 80 will be taken over by squid).
  +Both reside on the same machine as squid. We want squid to listen on port
  +80, forward a single static object request to the port httpd_docs server
  +listens to, and dynamic request to httpd_perl's port. Both servers return
  +the data to the proxy server (unless it is already cached in the squid), so
  +user never sees the other ports and never knows that there might be more
  +then one server running. Proxy server makes all the magic behind it
  +transparent to user. Do not confuse it with <STRONG>mod_rewrite</STRONG>, where a server redirects the request somewhere according to the rules and
  +forgets about it. The described functionality is being known as <CODE>httpd accelerator mode</CODE> in proxy dialect.
  +
   <P>
  -Answer <CODE>y</CODE> to be able to load dynamically Perl Modules extensions.
  +You should understand that squid can be used as a straight forward proxy
  +server, generally used at companies and ISPs to cut down the incoming
  +traffic by caching the most popular requests. However we want to run it in
  +the <CODE>httpd accelerator mode</CODE>. Two directives:
  +<CODE>httpd_accel_host</CODE> and <CODE>httpd_accel_port</CODE> enable this mode. We will see more details in a few seconds. If you are
  +currently using the squid in the regular proxy mode, you can extend its
  +functionality by running both modes concurrently. To accomplish this, you
  +extend the existent squid configuration with <CODE>httpd accelerator mode</CODE>'s related directives or you just create one from scratch.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="apache">apache</A></H2></CENTER>
  +As stated before, squid listens now to the port 80, we have to move the
  +httpd_docs server to listen for example to the port 81 (your mileage may
  +vary :). So you have to modify the httpd.conf in the httpd_docs
  +configuration directory and restart the httpd_docs server (But not before
  +we get the squid running if you are working on the production server). And
  +as you remember httpd_perl listens to port 8080.
  +
   <P>
  -It is a good idea to try to install the apache webserver without mod_perl
  -first. This way, if something goes wrong, you will know that it's not the
  -apache server's problem. But you can skip this stage if you already have a
  -working (non-mod_perl) apache server, or if you are just the daring type.
  -In any case you should unpack the apache source distribution, preferably at
  -the same level as the mod_perl distribution.
  +Let's go through the changes we should make to the default configuration
  +file. Since this file (<CODE>/etc/squid/squid.conf</CODE>) is huge (about 60k+) and we would not use 95% of it, my suggestion is to
  +write a new one including only the modified directives.
   
   <P>
  -<PRE>  % ls -l /usr/src
  -  drwxr-xr-x   8 stas  bar         2048 Oct  6 09:46 apache_x.x.x/
  -  drwxr-xr-x  19 stas  bar         4096 Oct  2 14:33 mod_perl-x.xx/
  -</PRE>
  +We want to enable the redirect feature, to be able to serve requests, by
  +more then one server (in our case we have httpd_docs and httpd_perl)
  +servers. So we specify <CODE>httpd_accel_host</CODE> as virtual. This assumes that your server has multiple interfaces - Squid
  +will bind to all of them.
  +
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="mod_perl">mod_perl</A></H2></CENTER>
  +<PRE>  httpd_accel_host virtual
  +</PRE>
   <P>
  -Now we come to the main point of this document.
  +Then we define the default port - by default, if not redirected, httpd_docs
  +will serve the pages. We assume that most requests will be of the static
  +nature. We have our httpd_docs listening on port 81.
   
   <P>
  -Here I will give only a short example of mod_perl installation. You should
  -read the <A HREF="././scenario.html#">Real World Scenarios Implementaion</A> for a more complete description.
  -
  +<PRE>  httpd_accel_port 81
  +</PRE>
   <P>
  -As with any perl package, the installation of mod_perl is very easy and
  -standard. <CODE>perldoc INSTALL</CODE> will guide you through the configuration and the installation processes.
  +And as described before, squid listens to port 80.
   
   <P>
  -The fastest way to install would be:
  +<PRE>  http_port 80
  +</PRE>
  +<P>
  +We do not use icp (icp used for cache sharing between neighbor machines),
  +which is more relevant in the proxy mode.
   
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    DO_HTTPD=1  USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  -  % make &amp;&amp; make test &amp;&amp; make install
  +<PRE>  icp_port 0
   </PRE>
   <P>
  -Note: replace x.x.x with the version numbers you actually use.
  +<CODE>hierarchy_stoplist</CODE> defines a list of words which, if found in a URL, causes the object to be
  +handled directly by this cache. In other words, use this to not query
  +neighbor caches for certain objects. Note that I have configured the <CODE>/cgi-bin</CODE> and <CODE>/perl</CODE> aliases for my dynamic documents, if you named them in a different way,
  +make sure to use the correct aliases here.
   
   <P>
  -To change the installation target (either if you are not <CODE>root</CODE> or you need to install a second copy for testing purposes), assuming you
  -use <CODE>/foo/server</CODE> as a base directory, you have to run this:
  +<PRE>  hierarchy_stoplist /cgi-bin /perl
  +</PRE>
  +<P>
  +Now we tell squid not to cache dynamic pages.
   
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    DO_HTTPD=1 PERL_MARK_WHERE=1 EVERYTHING=1 \
  -    APACHE_PREFIX=/foo/server PREFIX=/foo/server
  +<PRE>  acl QUERY urlpath_regex /cgi-bin /perl
  +  no_cache deny QUERY
   </PRE>
   <P>
  -Where <CODE>PREFIX</CODE> specifies where to install the perl modules,
  -<CODE>APACHE_PREFIX</CODE> -- the same for the apache files.
  +Please note that the last two directives are controversial ones. If you
  +want your scripts to be more complying with the HTTP standards, the headers
  +of your scripts should carry the <CODE>Caching Directives</CODE>
  +according to the HTTP specs. You will find a complete tutorial about this
  +topic in <CODE>Tutorial on HTTP Headers for mod_perl users</CODE> by Andreas J. Koenig (at <A
  +HREF="http://perl.apache.org">http://perl.apache.org</A> ). If you set the
  +headers correctly there is no need to tell squid accelerator to <STRONG>NOT</STRONG>
  +try to cache something. The headers I am talking about are
  +<CODE>Last-Modified</CODE> and <CODE>Expires</CODE>. What are they good for? Squid would not bother your mod_perl server a
  +second time if a request is (a) cachable and (b) still in the cache. Many
  +mod_perl applications will produce identical results on identical requests
  +at least if not much time goes by between the requests. So your squid might
  +have a hit ratio of 50%, which means that mod_perl servers will have as
  +twice as less work to do than before. This is only possible by setting the
  +headers correctly.
   
   <P>
  -The next step is to configure the mod_perl sections of the apache
  -configuration file. (See <A HREF="././config.html#">ModPerlConfiguration</A>).
  +Even if you insert user-ID and date in your page, caching can save
  +resources when you set the expiration time to 1 second. A user might double
  +click where a single click would do, thus sending two requests in parallel,
  +squid could serve the second request.
   
   <P>
  -Fire up the server with <CODE>/foo/server/sbin/apachectl start</CODE>, Look for the error reports at the <CODE>error_log</CODE> file in case the server does not start up (No error message will be printed
  -to the console!).
  +But if you are lazy, or just have too many things to deal with, you can
  +leave the above directives the way I described. But keep in mind that one
  +day you will want to reread this snippet and the Andreas' tutorial and
  +squeeze even more power from your servers without investing money for
  +additional memory and better hardware.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A></H1></CENTER>
   <P>
  -There are a few ways. In older versions of apache ( &lt; 1.3.6 ?) you could check that by running <CODE>httpd -v</CODE>, it no longer works. Now you should use <CODE>httpd -l</CODE>. Please notice that it is not enough to have it installed - you should of
  -course configure it for mod_perl and restart the server.
  +While testing you might want to enable the debugging options and watch the
  +log files in <CODE>/var/log/squid/</CODE>. But turn it off in your production server. I list it commented out. (28
  +== access control routes).
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Testing_by_checking_the_error_lo">Testing by checking the error_log file</A></H2></CENTER>
  +<PRE>  # debug_options ALL, 1, 28, 9
  +</PRE>
   <P>
  -When starting the server, just check the <CODE>error_log</CODE> file for the following message:
  +We need to provide a way for squid to dispatch the requests to the correct
  +servers, static object requests should be redirected to httpd_docs (unless
  +they are already cached), while dynamic should go to the httpd_perl server.
  +The configuration below tells squid to fire off 10 redirect daemons at the
  +specified path of the redirect daemon and disables rewriting of any <CODE>Host:</CODE> headers in redirected requests (as suggested by squid's documentation). The
  +redirection daemon script is enlisted below.
   
   <P>
  -<PRE>  [Thu Dec  3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured 
  -                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  -    -- resuming normal operations
  +<PRE>  redirect_program /usr/lib/squid/redirect.pl
  +  redirect_children 10
  +  redirect_rewrites_host_header off
   </PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Testing_by_viewing_perl_status">Testing by viewing /perl-status</A></H2></CENTER>
  -<P>
  -Assuming that you have configured the <CODE>&lt;Location /perl-status</CODE>&gt; section in the server configuration file fetch: <A
  -HREF="http://www.nowhere.com/perl-status">http://www.nowhere.com/perl-status</A>
  -using your favorite Netscape browser :-)
  -
   <P>
  -You should see something like this:
  +Maximum allowed request size in kilobytes. This one is pretty obvious. If
  +you are using POST to upload files, then set this to the largest file's
  +size plus a few extra kbytes.
   
   <P>
  -<PRE>  Embedded Perl version 5.00502 for Apache/1.3.1 (Unix) mod_perl/1.19 
  -  process 50880, running since Tue Oct 6 14:31:45 1998
  +<PRE>  request_size 1000 KB
   </PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Testing_via_telnet">Testing via telnet</A></H2></CENTER>
   <P>
  -Knowing the port you have configured apache to listen on, you can use
  -<CODE>telnet</CODE> to talk directly to it.
  +Then we have access permissions, which I will not explain. But you might
  +want to read the documentation so to avoid any security flaws.
   
   <P>
  -Assuming that your mod_perl enabled server listens to port 8080, telnet to
  -your server at port 8080, and type <CODE>HEAD / HTTP/1.0</CODE> then press the &lt;ENTER&gt; key TWICE:
  +<PRE>  acl all src 0.0.0.0/0.0.0.0
  +  acl manager proto cache_object
  +  acl localhost src 127.0.0.1/255.255.255.255
  +  acl myserver src 127.0.0.1/255.255.255.255
  +  acl SSL_ports port 443 563
  +  acl Safe_ports port 80 81 8080 81 443 563
  +  acl CONNECT method CONNECT
  +  
  +  http_access allow manager localhost
  +  http_access allow manager myserver
  +  http_access deny manager
  +  http_access deny !Safe_ports
  +  http_access deny CONNECT !SSL_ports
  +  # http_access allow all
  +</PRE>
  +<P>
  +Since squid should be run as non-root user, you need these if you are
  +invoking the squid as root.
   
   <P>
  -<PRE>  % telnet localhost 8080&lt;ENTER&gt;
  -  HEAD / HTTP/1.0&lt;ENTER&gt;&lt;ENTER&gt;
  +<PRE>  cache_effective_user squid
  +  cache_effective_group squid
   </PRE>
   <P>
  -You should see a response like this:
  +Now configure a memory size to be used for caching. A squid documentation
  +warns that the actual size of squid can grow three times larger than the
  +value you are going to set.
   
   <P>
  -<PRE>  HTTP/1.1 200 OK
  -  Date: Tue, 01 Dec 1998 12:27:52 GMT
  -  Server: Apache/1.3.6 (Unix) mod_perl/1.19
  -  Connection: close
  -  Content-Type: text/html
  -  
  -  Connection closed.
  +<PRE>  cache_mem 20 MB
   </PRE>
   <P>
  -The line: <CODE>Server: Apache/1.3.6 (Unix) mod_perl/1.19</CODE> --confirms that you <STRONG>do</STRONG> have mod_perl installed and its version is <CODE>1.19</CODE>. Of course in your case it would be the version you have installed.
  +Keep pools of allocated (but unused) memory available for future use. Read
  +more about it in the squid documents.
   
   <P>
  -However, just because you have got mod_perl linked in there, that does not
  -mean that you have configured your server to handle Perl scripts with
  -mod_perl. You will find the configuration assistance at
  -<A HREF="././config.html#">ModPerlConfiguration</A>
  -
  -
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Testing_via_a_CGI_script">Testing via a CGI script</A></H2></CENTER>
  -<P>
  -Another method is to invoke a CGI script which dumps the server's
  -environment.
  -
  -<P>
  -Copy and paste the script below (no need for the first perl calling
  -(shebang) line!). Let's say you named it <CODE>test.pl</CODE>, saved it at the root of the CGI scripts and CGI root is mapped directly
  -to the
  -<CODE>/perl</CODE> location of your server.
  -
  -<P>
  -<PRE>  print &quot;Content-type: text/html\n\n&quot;;
  -  print &quot;Server's environment&lt;P&gt;\n&quot;;
  -  print &quot;&lt;TABLE&gt;&quot;;
  -  foreach ( keys %ENV ) {
  -      print &quot;&lt;TR&gt;&lt;TD&gt;$_ &lt;/TD&gt;&lt;TD&gt;$ENV{$_}&lt;/TR&gt;&lt;/TD&gt;&quot;;
  -  }
  -  print &quot;&lt;/TABLE&gt;&quot;;
  -</PRE>
  -<P>
  -Make it readable and executable by server:
  -
  -<P>
  -<PRE>  % chmod a+rx test.pl
  +<PRE>  memory_pools on
   </PRE>
  -<P>
  -(you will want to tune permissions on the public host).
  -
   <P>
  -Now fetch the URL <CODE>http://www.nowhere.com:8080/perl/test.pl</CODE> (replace 8080 with the port your mod_perl enabled server is listening to.
  -You should see something like this (the generated output was trimmed):
  +Now tight the runtime permissions of the cache manager CGI script (<CODE>cachemgr.cgi</CODE>,that comes bundled with squid) on your production server.
   
   <P>
  -<PRE>  SERVER_SOFTWARE    Apache/1.3.6 (Unix) mod_perl/1.19
  -  GATEWAY_INTERFACE  CGI-Perl/1.1
  -  REQUEST_METHOD     GET
  -  HTTP_ACCEPT        image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
  -  MOD_PERL           1.19
  -  REQUEST_URI        /perl/test.pl
  -  SCRIPT_NAME        /perl/test.pl
  -  [...snipped]
  +<PRE>  cachemgr_passwd disable shutdown
  +  #cachemgr_passwd none all
   </PRE>
   <P>
  -Now if I run the same script in mod_cgi mode (configured with
  -<CODE>/cgi-bin</CODE> Alias) (you will need to add the perl invocation line
  -<CODE>#!/bin/perl</CODE> for the above script) and fetch
  -<CODE>http://www.nowhere.com/cgi-bin/test.pl</CODE>.
  +Now the redirection daemon script (you should put it at the location you
  +have specified by <CODE>redirect_program</CODE> parameter in the config file above, and make it executable by webserver of
  +course):
   
   <P>
  -<PRE>  SERVER_SOFTWARE   Apache/1.3.6 (Unix)
  -  GATEWAY_INTERFACE CGI/1.1
  -  [...snipped]
  +<PRE>  #!/usr/local/bin/perl
  +  
  +  $|=1;
  +  
  +  while (&lt;&gt;) {
  +      # redirect to mod_perl server (httpd_perl)
  +    print($_), next if s|(:81)?/perl/|:8080/perl/|o;
   </PRE>
  -<P>
  -You will see that two variables, <CODE>SERVER_SOFTWARE</CODE> and
  -<CODE>GATEWAY_INTERFACE</CODE>, are different from the case above. This gives you a hint of how to tell
  -in what mode you are running in your cgi scripts. I start all my cgi
  -scripts that are mod_perl aware with:
  -
   <P>
  -<PRE>  BEGIN {
  -      # Auto-detect if we are running under mod_perl or CGI.
  -    $USE_MOD_PERL = ((exists $ENV{'GATEWAY_INTERFACE'}
  -                  and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/)
  -                   or exists $ENV{'MOD_PERL'} );
  -      # perl5.004 is a must under mod_perl
  -    require 5.004 if $USE_MOD_PERL;
  +<PRE>      # send it unchanged to plain apache server (http_docs)
  +    print;
     }
   </PRE>
   <P>
  -You might wonder why in the world you would need to know in what mode you
  -are running. For example you will want to use <CODE>Apache::exit()</CODE>
  -and not <CODE>CORE::exit()</CODE> in your modules, but if you think that your script might be used in both
  -environments (mod_cgi vs. mod_perl), you will have to override the <CODE>exit()</CODE> subroutine and to make the runtime decision of what method you will use.
  -Not that if you run scripts under <CODE>Apache::Registry</CODE> handler, it takes care of overriding the
  -<CODE>exit()</CODE> call for you, so it's not an issue if this is your case. For reasons and
  -implementations see: <A HREF="././porting.html#Using_exit_">Using exit()</A> and the whole <A HREF="././porting.html#">Writing Mod Perl scripts and Porting plain CGIs to it</A> page.
  +In my scenario the proxy and the apache servers are running on the same
  +machine, that's why I just substitute the port. In the presented squid
  +configuration, requests that passed through squid are converted to point to
  +the <STRONG>localhost</STRONG> (which is <CODE>127.0.0.1</CODE>). The above redirector can be more complex of course, but you know the
  +perl, right?
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Testing_via_lwp_request">Testing via lwp-request</A></H2></CENTER>
   <P>
  -Yet another one. Why do I show all these approaches? While here they are
  -serving a very simple purpose, they can be helpful in other situations.
  +A few notes regarding redirector script:
   
   <P>
  -Assuming you have the <CODE>libwww-perl</CODE> (<CODE>LWP</CODE>) package installed (you will need it installed in order to pass mod_perl's <CODE>make test</CODE> anyway):
  +You must disable buffering. <CODE>$|=1;</CODE> does the job. If you do not disable buffering, the <CODE>STDOUT</CODE> will be flushed only when the buffer becomes full and its default size is
  +about 4096 characters. So if you have an average URL of 70 chars, only
  +after 59 (4096/70) requests the buffer will be flushed, and the requests
  +will finally achieve the server in target. Your users will just wait till
  +it will be filled up.
   
   <P>
  -<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A>
  -</PRE>
  +If you think that it is a very ineffective way to redirect, I'll try to
  +prove you the opposite. The redirector runs as a daemon, it fires up N
  +redirect daemons, so there is no problem with perl interpreter loading,
  +exactly like mod_perl -- perl is loaded all the time and the code was
  +already compiled, so redirect is very fast (not slower if redirector was
  +written in C or alike). Squid keeps an open pipe to each redirect daemon,
  +thus there is even no overhead of the expensive system calls.
  +
   <P>
  -Will show you all the headers. (The <CODE>-d</CODE> option disables printing the response content.)
  +Now it is time to restart the server, at linux I do it with:
   
   <P>
  -<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A> | egrep '^Server:'
  +<PRE>  /etc/rc.d/init.d/squid restart
   </PRE>
  -<P>
  -To see the server's version only.
  -
   <P>
  -Use <CODE>http://www.nowhere.com:port_number</CODE> if your server is listening to a non-default 80 port.
  +Now the setup is complete ...
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A></H1></CENTER>
   <P>
  -Yes, no problem with that. Follow the installation instructions and when
  -you encounter <CODE>APACI_ARGS</CODE> use your home directory (or some other directory which you have write
  -access to) as a prefix, (e.g. <CODE>/home/stas/www</CODE>), and everything will be installed there. There is a chance that some perl
  -libs will be not installed on your server by root and you will have to
  -install these locally too. See the <A
  -HREF="http://www.singlesheaven.com/stas/TULARC/webmaster/myfaq.html#7">http://www.singlesheaven.com/stas/TULARC/webmaster/myfaq.html#7</A>
  -for more information on local perl installations.
  +Almost... When you try the new setup, you will be surprised and upset to
  +discover a port 81 showing up in the URLs of the static objects (like
  +htmls). Hey, we did not want the user to see the port 81 and use it instead
  +of 80, since then it will bypass the squid server and the hard work we went
  +through was just a waste of time? 
   
   <P>
  -So you end up with something like:
  +The solution is to run both squid and httpd_docs at the same port. This can
  +be accomplished by binding each one to a specific interface. Modify the <CODE>httpd.conf</CODE> in the <CODE>httpd_docs</CODE> configuration directory:
   
   <P>
  -<PRE>  $ gunzip &lt;apache_x.x.xx.tar.gz | tar xvf -
  -  $ gunzip &lt;mod_perl-x.xx.tar.gz | tar xvf -
  -  $ cd mod_perl-x.xx
  -  $ perl Makefile.PL \
  -      APACHE_SRC=../apache-1.3.X/src \
  -      DO_HTTPD=1 \
  -      USE_APACI=1 \
  -      EVERYTHING=1 \
  -      APACI_ARGS=--sbindir=/home/stas/sbin/httpd_perl, \
  -           --sysconfdir=/home/stas/etc/httpd_perl, \
  -           --localstatedir=/home/stas/var/httpd_perl, \
  -           --runtimedir=/home/stas/var/httpd_perl/run, \
  -           --logfiledir=/home/stas/var/httpd_perl/logs, \
  -           --proxycachedir=/home/stas/var/httpd_perl/proxy
  +<PRE>  Port 80
  +  BindAddress 127.0.0.1
  +  Listen 127.0.0.1:80
   </PRE>
  -<P>
  -You will not be able to have the server listen to a port lower then 1024 if
  -you are not starting it as <CODE>root</CODE>, so choose a port number above 1024. (I use 8080 in most cases). Note that
  -you will have to use a URL like <CODE>http://www.nowhere.com:8080</CODE> in that case, but that is not a problem since usually users do not directly
  -access URLs to CGI scripts, but rather are directed to them from a link on
  -a web page or as the '<CODE>ACTION</CODE>' of a HTML form, so they should not know at all that the port is different
  -from the default port 80.
  -
  -<P>
  -If you want your apache server to start automatically on system reboot, you
  -will need to invoke the server startup script from somewhere within the
  -init scripts on your host. This is often somewhere under <CODE>/etc/rc.d</CODE>, but this path can vary depending upon the flavor of Unix you are using.
  -
  -<P>
  -One more important thing to keep in mind is system resources. mod_perl is
  -memory hungry -- if you run a lot of mod_perl processes on a public,
  -multiuser (not dedicated) machine -- most likely the system administrator
  -of the host will ask you to use less resources and even to shut down your
  -mod_perl server and to find another home for it. You have a few solutions:
  -
  -<UL>
  -<P><LI>
   <P>
  -Reduce resources usage (see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>).
  +Modify the <CODE>squid.conf</CODE>:
   
  -<P><LI>
   <P>
  -Ask your ISP if you can put a dedicated machine into their computer room
  -and be root there.
  -
  -<P><LI>
  +<PRE>  http_port 80
  +  tcp_incoming_address 123.123.123.3
  +  tcp_outgoing_address 127.0.0.1
  +  httpd_accel_host 127.0.0.1
  +  httpd_accel_port 80
  +</PRE>
   <P>
  -Look for another ISP with lots of resources or one that supports mod_perl.
  -You can find a list of these ISP at <A
  -HREF="http://perl.apache.org">http://perl.apache.org</A> .
  +Where <CODE>123.123.123.3</CODE> should be replaced with IP of your main server. Now restart squid and
  +httpd_docs in either order you want, and voila the port number has gone.
   
  -</UL>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A></H1></CENTER>
   <P>
  -Sure, you can take a look at the symbols inside the httpd executable. e.g.
  -if you want to see whether you have enabled PERL_AUTH=1 while building the
  -mod_perl, you do:
  +You must also have in the <CODE>/etc/hosts</CODE> an entry (most chances that it's already there):
   
   <P>
  -<PRE>  nm httpd | grep perl_authenticate
  +<PRE>  127.0.0.1  localhost.localdomain   localhost
   </PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A></H1></CENTER>
   <P>
  -It is possible to determine which options were given to modperl's
  -<CODE>Makefile.PL</CODE> during the configuration stage, so to be used later in recreating the same
  -build tree when rebuilding the server. This is relevant only if you did not
  -use the default config parameters and altered some of them during the
  -configuration stage.
  +Now if your scripts were generating HTML including fully qualified self
  +references, using the 8080 or other port -- you should fix them to generate
  +links to point to port 80 (which means not using the port at all). If you
  +do not, users will bypass squid, like if it was not there at all, by making
  +direct requests to the mod_perl server's port.
   
   <P>
  -I was into this problem many times. I am going to build something by
  -passing some non-default parameters to the config script and then later
  -when I need to rebuild the tool either to upgrade it or to make an
  -identical copy at another machine, I would find that I do not remember what
  -parameters I altered.
  +The only question left is what to do with users who bookmarked your
  +services and they still have the port 8080 inside the URL. Do not worry
  +about it. The most important thing is for your scripts to return a full
  +URLs, so if the user comes from the link with 8080 port inside, let it be.
  +Just make sure that all the consecutive calls to your server will be
  +rewritten correctly. During a period of time users will change their
  +bookmarks. What can be done is to send them an email if you have one, or to
  +leave a note on your pages asking users to update their bookmarks. You
  +could avoid this problem if you did not publish this non-80 port in first
  +place. See <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>.
   
   <P>
  -The best solution for this problem is to prepare the run file with all the
  -parameters that are about to be used and then run it instead of typing it
  -all by hand. So later I will have the script handy to be reused.
  +&lt;META&gt; Need to write up a section about server logging with squid.
  +One thing I sure would like to know is how requests are logged with this
  +setup. I have, as most everyone I imagine, log rotation, analysis,
  +archiving scripts and they all assume a single log. Does one have different
  +logs that have to be merged (up to 3 for each server + squid) ? Even when
  +squid responds to a request out of its cache I'd still want the thing to be
  +logged. &lt;/META&gt;
   
   <P>
  -mod_perl suggests using the <CODE>makepl_args.mod_perl</CODE> file which comes with mod_perl distribution. This is the file where you
  -should specify all the parameters you are going to use.
  +See <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A> for information about <CODE>X-Forwarded-For</CODE>.
   
   <P>
  -But if you have found yourself with a compiled tool and no traces of the
  -specified parameters left, usually you can still find them out, if the
  -sources were not <CODE>make clean</CODE>'d. You will find the apache specific parameters in <CODE>apache_x.x.x/config.status</CODE> and modperl's at in <CODE>mod_perl_x.xx/apaci/mod_perl.config</CODE>.
  +To save you some keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Server_Installation_problems">Server Installation problems</A></H1></CENTER>
  +<PRE>  http_port 80
  +  tcp_incoming_address 123.123.123.3
  +  tcp_outgoing_address 127.0.0.1
  +  httpd_accel_host 127.0.0.1
  +  httpd_accel_port 80
  +  
  +  icp_port 0
  +  
  +  hierarchy_stoplist /cgi-bin /perl
  +  acl QUERY urlpath_regex /cgi-bin /perl
  +  no_cache deny QUERY
  +  
  +  # debug_options ALL,1 28,9
  +  
  +  redirect_program /usr/lib/squid/redirect.pl
  +  redirect_children 10
  +  redirect_rewrites_host_header off
  +  
  +  request_size 1000 KB
  +  
  +  acl all src 0.0.0.0/0.0.0.0
  +  acl manager proto cache_object
  +  acl localhost src 127.0.0.1/255.255.255.255
  +  acl myserver src 127.0.0.1/255.255.255.255
  +  acl SSL_ports port 443 563
  +  acl Safe_ports port 80 81 8080 81 443 563
  +  acl CONNECT method CONNECT
  +  
  +  http_access allow manager localhost
  +  http_access allow manager myserver
  +  http_access deny manager
  +  http_access deny !Safe_ports
  +  http_access deny CONNECT !SSL_ports
  +  # http_access allow all
  +  
  +  cache_effective_user squid
  +  cache_effective_group squid
  +  
  +  cache_mem 20 MB
  +  
  +  memory_pools on
  +  
  +  cachemgr_passwd disable shutdown
  +</PRE>
  +<P>
  +Note that all directives should start at the beginning of the line.
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="_skipping_test_on_this_plat">......skipping test on this platform</A></H2></CENTER>
  +<CENTER><H1><A NAME="Running_1_webserver_and_squid_in">Running 1 webserver and squid in httpd accelerator mode</A></H1></CENTER>
   <P>
  -While doing <CODE>make test</CODE> you would notice that some of the tests are being reported as skipped. The
  -real reason is that you are missing some optional modules for these test to
  -be passed. For a hint you might want to peek at the content of each test
  -(you will find them all in the <CODE>./t</CODE> directory (mnemonic - t, tests). I'll list a few examples, but of course
  -the requirements might be changed in the future.
  +When I was first told about squid, I thought: ``Hey, Now I can drop the
  +<CODE>httpd_docs</CODE> server and to have only squid and <CODE>httpd_perl</CODE>
  +servers``. Since all my static objects will be cached by squid, I do not
  +need the light <CODE>httpd_docs</CODE> server. But it was a wrong assumption. Why? Because you still have the
  +overhead of loading the objects into squid at first time, and if your site
  +has many of them -- not all of them will be cached (unless you have devoted
  +a huge chunk of memory to squid) and my heavy mod_perl servers will still
  +have an overhead of serving the static objects. How one would measure the
  +overhead? The difference between the two servers is memory consumption,
  +everything else (e.g. I/O) should be equal. So you have to estimate the
  +time needed for first time fetching of each static object at a peak period
  +and thus the number of additional servers you need for serving the static
  +objects. This will allow you to calculate additional memory requirements. I
  +can imagine, this amount could be significant in some installations.
   
   <P>
  -&gt; modules/cookie......skipping test on this platform
  +So I have decided to have even more administration overhead and to stick
  +with squid, httpd_docs and httpd_perl scenario, where I can optimize and
  +fine tune everything. Of course this can be not your case. If you are
  +feeling that the scenario from the previous section is too complicated for
  +you, make it simpler. Have only one server with mod_perl built in and let
  +the squid to do most of the job that plain light apache used to do. As I
  +have explained in the previous paragraph, you should pick this lighter
  +setup only if you can make squid cache most of your static objects. If it
  +cannot, your mod_perl server will do the work we do not want it to.
   
   <P>
  -install libapreq
  +If you are still with me, install apache with mod_perl and squid. Then use
  +a similar configuration from the previous section, but now httpd_docs is
  +not there anymore. Also we do not need the redirector anymore and we
  +specify <CODE>httpd_accel_host</CODE> as a name of the server and not <CODE>virtual</CODE>. There is no need to bind two servers on the same port, because we do not
  +redirect and there is neither <CODE>Bind</CODE> nor <CODE>Listen</CODE>
  +directives in the <CODE>httpd.conf</CODE> anymore.
   
   <P>
  -&gt; modules/psections...skipping test on this platform
  +The modified configuration (see the explanations in the previous section):
   
   <P>
  -install Devel::Symdump / Data::Dumper
  -
  +<PRE>  httpd_accel_host put.your.hostname.here
  +  httpd_accel_port 8080
  +  http_port 80
  +  icp_port 0
  +  
  +  hierarchy_stoplist /cgi-bin /perl
  +  acl QUERY urlpath_regex /cgi-bin /perl
  +  no_cache deny QUERY
  +  
  +  # debug_options ALL, 1, 28, 9
  +  
  +  # redirect_program /usr/lib/squid/redirect.pl
  +  # redirect_children 10
  +  # redirect_rewrites_host_header off
  +  
  +  request_size 1000 KB
  +  
  +  acl all src 0.0.0.0/0.0.0.0
  +  acl manager proto cache_object
  +  acl localhost src 127.0.0.1/255.255.255.255
  +  acl myserver src 127.0.0.1/255.255.255.255
  +  acl SSL_ports port 443 563
  +  acl Safe_ports port 80 81 8080 81 443 563
  +  acl CONNECT method CONNECT
  +  
  +  http_access allow manager localhost
  +  http_access allow manager myserver
  +  http_access deny manager
  +  http_access deny !Safe_ports
  +  http_access deny CONNECT !SSL_ports
  +  # http_access allow all
  +  
  +  cache_effective_user squid
  +  cache_effective_group squid
  +  
  +  cache_mem 20 MB
  +  
  +  memory_pools on
  +  
  +  cachemgr_passwd disable shutdown
  +</PRE>
   <P>
  -&gt; modules/request.....skipping test on this platform
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="One_Light_and_One_Heavy_Servers_">One Light and One Heavy Servers where ALL htmls are Perl-Generated</A></H1></CENTER>
  +<P>
  +Instead of keeping all your perl scripts in <CODE>/perl</CODE> and your static content everywhere else, you could keep your static content
  +in special directories and keep your perl scripts everywhere else. You can
  +still use the light/heavy apache separation approach described before, with
  +a few minor modifications.
   
   <P>
  -libapreq
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Installation_and_Configuration">Installation and Configuration</A></H2></CENTER>
  +<P>
  +First you need to compile your light apache with mod_proxy and mod_rewrite
   
   <P>
  -&gt; modules/sandwich....skipping test on this platform
  +<PRE>  % ./configure --prefix=[snip...] --enable-module=rewrite --enable-module=proxy
  +</PRE>
  +<P>
  +In the <EM>light</EM> apache's <CODE>httpd.conf</CODE> file, turn rewriting on:
   
   <P>
  -Apache::Sandwich
  +<PRE>  RewriteEngine on
  +</PRE>
  +<P>
  +and list the static directories something like this:
   
   <P>
  -&gt; modules/stage.......skipping test on this platform
  +<PRE>  RewriteRule ^/img - [L]
  +  RewriteRule ^/style - [L]
  +</PRE>
  +<P>
  +The <CODE>[L]</CODE> means that the rewrite engine should stop if it has a match. This is
  +necessary because the very last rewrite rule proxies everything to the <EM>heavy</EM> server:
   
   <P>
  -Apache::Stage
  +<PRE>  RewriteRule ^/(.*) <A HREF="http://www.myservername.com:8080/">http://www.myservername.com:8080/</A>$1 [P]
  +</PRE>
  +<P>
  +This line (<STRONG>which must be the last <CODE>RewriteRule</CODE></STRONG>) is the difference between a server for which static content is the
  +default and one for which dynamic (perlish) content is the default. (The
  +above
  +<CODE>RewriteRule</CODE> assumes the heavy server runs on the same machine as the light server. You
  +can just insert a different URL in here if the heavy apache is elsewhere,
  +but keeping the two servers on the one machine and treating them as one has
  +some advantages described later.)
   
   <P>
  -&gt; modules/symbol......skipping test on this platform
  +You should also add the <EM>reverse rewrite rule</EM>:
   
   <P>
  -Devel::Symdump
  +<PRE>  ProxyPassReverse / <A HREF="http://www.myservername.com/">http://www.myservername.com/</A>
  +</PRE>
  +<P>
  +so that the user doesn't see <CODE>:8080</CODE> port number in her browser's location window.
   
   <P>
  -Chances are that all of these are installed if you use <CODE>CPAN.pm</CODE> to
  -<CODE>install Bundle::Apache</CODE>.
  +Of course, <CODE>www.myservername.com</CODE> should be replaced with *your* domain name. You *could* use <CODE>localhost</CODE> in the RewriteRule above if the heavy and light servers are on the same
  +machine, but your heavy server might accidentally say <CODE>localhost</CODE> in a client redirect (see below) which would not be good. Also, if your
  +heavy server understands virtual hosts, you probably don't want to use <CODE>localhost</CODE> name.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="make_test_fails">make test fails</A></H2></CENTER>
  +<CENTER><H2><A NAME="Tricks_traps_and_gotchas">Tricks, traps and gotchas</A></H2></CENTER>
  +<UL>
  +<P><LI><STRONG><A NAME="item__Closing_your_shutters_temporar">'Closing your shutters' temporarily</A></STRONG>
   <P>
  -There are two configuration parameters: <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>, that you can use in:
  +Very occasionally, your mod_perl server will suffer glitches. Perhaps you
  +changed a module and restarted your mod_perl httpd when a <CODE>perl
  +-cw</CODE> would have given you some very interesting information! Since *all* your
  +html is dynamically generated, suddenly *nobody* can view *any* pages on
  +your site. Disaster!! Worse - your users are getting horribly cryptic <STRONG>Unable to contact upstream server</STRONG> error messages on a grey background, not those nice customised error
  +messages you generate with perl.
   
   <P>
  -<PRE>  perl Makefile.PL [options]
  +If you insert a line into the light apache's <CODE>httpd.conf</CODE> file:
  +
  +<P>
  +<PRE>  RewriteRule ^/(.*) /sorry.html [L]
   </PRE>
   <P>
  -<CODE>DO_HTTPD=1</CODE> means default to '<CODE>y</CODE>' for the two apache's
  -<CODE>configure</CODE> utility prompts: (a) 'which source tree to configure against' and (b)
  -'whether to build the httpd in that tree'. <CODE>PREP_HTTPD=1</CODE> just means default '<CODE>n</CODE>' to the second prompt -- meaning, <EM>do not build httpd (make) in the
  -apache source tree</EM>. In other words if you use <CODE>PREP_HTTPD=1</CODE> the httpd will be not build. It will be build only if you use
  -<CODE>DO_HTTPD=1</CODE> option and not use <CODE>PREP_HTTPD=1</CODE>.
  +*after* the list of static directories but *before* the rule that proxies
  +everything else to the heavy apache, your users now get a (relatively) nice
  +`Sorry for the inconvenience' message instead of the cryptic message
  +described above. What's more, because this
  +<CODE>sorry.html</CODE>  <CODE>RewriteRule</CODE> is listed *after* the image directory, you can refer to your images in it.
  +Now all you have to do is figure out how to fix the module you broke.
   
   <P>
  -If you did not build the httpd, chdir to the apache source, and execute:
  +Of course you need the <CODE>sorry.html</CODE> be ready and when you alter the configuration, you will have to restart the
  +light server for the changes to take effect and when you fix all the errors
  +in mod_perl server, remove the change and restart it again.
   
   <P>
  -<PRE>  make
  -</PRE>
  +This situation is easy to prevent. See <A HREF="././control.html#Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A> for more info.
  +
  +<P><LI><STRONG><A NAME="item_Logging">Logging</A></STRONG>
   <P>
  -Then return to the mod_perl source and run:
  +There are a number of different ways to maintain logs of your hits. The
  +easiest way is to let both apaches log to their own
  +<CODE>access_log</CODE> file. Unfortunately, this means that many requests will be logged twice
  +(which makes it tricky to merge the two logfiles, should you want to).
  +Also, as far as the heavy apache is concerned, all requests will appear to
  +come from the IP address of the machine on which the light apache is
  +running. If you are logging IP addresses, as part of your <CODE>access_log</CODE> the logs written by the heavy apache will be fairly meaningless.
   
   <P>
  -<PRE>  make test
  -  make install
  -</PRE>
  +One solution is to tell the heavy apache not to bother logging requests
  +that seem to come from the light apache's machine. You might do this by
  +installing a custom <CODE>PerlLogHandler</CODE> or just piping to
  +<CODE>access_log</CODE> via an <CODE>grep -v</CODE> (match all but this pattern) for the
  +<EM>bad</EM> IP address. In this scenario, the <CODE>access_log</CODE> written by the light apache is *the* <CODE>access_log</CODE>, plus any direct accesses to the heavy server in case they bypassed the
  +proxy server.
  +
   <P>
  -Note that you would have to do the same if you do not pass
  -<CODE>APACHE_PREFIX=/path_to_installation_prefix</CODE> during the <CODE>perl
  -Makefile.PL [options]</CODE> stage.
  +Note that you don't want to pipe the access_log from the heavy apache to <CODE>/dev/null</CODE>. If you do this, you won't be able to see any requests that bypass the
  +lightweight apache and come straight in on port 8080 (or alike). As you
  +will see shortly, this *can* happen and every time you see one, you should
  +ask yourself <CODE>Why?</CODE> and take steps to eliminate it.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A></H2></CENTER>
  +It's quote easy to make the logger to log the original client's IP and not
  +the one that comes from proxy server. Look for
  +<CODE>mod_proxy_add_forward</CODE> at <A HREF="././scenario.html#Building_and_Using_mod_proxy">Building and Using mod_proxy</A> for a hint.
  +
  +<P><LI><STRONG><A NAME="item_Eliminating">Eliminating :8080's</A></STRONG>
   <P>
  -You will see this message when you try to run a httpd, if you have had a
  -stale old apache header layout in one of the <CODE>include</CODE> paths during the build process. Do run <CODE>find</CODE> (or <CODE>locate</CODE>) utility in order to locate <CODE>ap_mmn.h</CODE> file. In my case I have had a
  -<CODE>/usr/local/include/ap_mmn.h</CODE> which was installed by RedHat install process. If this is the case get rid
  -of it, and rebuild it again.
  +There are a number of ways in which the user can somehow be directed to
  +URLs which have a <CODE>:8080</CODE> in them. (Replace 8080 with the port your mod_perl enabled Apache listens
  +at.) If you are running the heavy apache on a different machine to that of
  +the light apache this will be less of a problem (provided the heavy apache
  +has the same
  +<CODE>ServerName</CODE> as the light apache), but this section may still apply to you...
   
   <P>
  -For all RH fans, before you are going to build the apache by yourself, do:
  +If the user requests a URL that maps to a directory without a trailing
  +slash (<CODE>/</CODE>), apache will issue a client redirect (301?) to the
  +<EM>correct</EM> URL. Unfortunately, Apache that will issue this redirect will most likely
  +be the heavy apache, since most distinct requests are answered by it. It
  +will issue the redirect to *its* port on *its*
  +<CODE>ServerName</CODE> and because the redirect is a so-called *client* redirect, the URL (with
  +the :8080 on the end) will be in the body, not the header, of the data
  +returned to the user's browser. This means that the <CODE>ProxyPassReverse</CODE> in the light apache's configuration file to catch such things will be
  +unable to catch this. :-(
   
   <P>
  -<PRE>  rpm -e apache
  +Since this will tend only to be a problem when the heavy and light apaches
  +are running on the same machine (but on different ports), if the light and
  +heavy apaches have the same <CODE>DocumentRoot</CODE> we can have the *light* apache figure out that a request is for a directory
  +without a trailing slash and have it do the redirect itself, *before* the
  +heavy apache finds out about it:
  +
  +<P>
  +<PRE>    RewriteCond /www/shop%{SCRIPT_FILENAME} -d
  +    RewriteRule ^(.+[^/])$ $1/ [R]   
   </PRE>
   <P>
  -to remove the pre-installed package first!
  +Note that these two lines should be *after* the <CODE>RewriteRule</CODE>s for the static directories but (of course) *before* the final
  +all-encompassing <CODE>RewriteRule</CODE> that proxies <EM>everything else</EM> to the heavy apache. If you put these two lines in the light <CODE>httpd.conf</CODE>
  +*before* the static directories are mentioned, the light httpd may find
  +itself in an infinite loop if somebody were to request for example <CODE>/img</CODE> in our setup.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A></H2></CENTER>
  +Another way in which <CODE>:8080</CODE>'s can creep into URLs is if you have perl code which issues a redirect to <CODE>http://$ENV{HTTP_HOST}/...</CODE>. If you are migrating from one heavy server to one heavy and one light,
  +you may find a few of these. If you replace <CODE>HTTP_HOST</CODE> with
  +<CODE>SERVER_NAME</CODE>, all should be well. Note that you may need to do this whether or not the
  +light and heavy servers are on the same machine.
  +
   <P>
  -Yes, you should. You have to rebuild mod_perl enabled server since it has a
  -hard coded <CODE>@INC</CODE> which points to the old perl and it is is probably linked to the an old <CODE>libperl</CODE> library. You can try to modify the <CODE>@INC</CODE> in the startup script (if you keep the old perl version around), but it is
  -better to build a fresh one to save you a mess.
  +The <CODE>:8080</CODE> effect can be insidious. Once a user gets a URL with
  +<CODE>:8080</CODE>, in, odd things will happen. If the heavy and light apaches have the same <CODE>DocumentRoot</CODE> (normal if they are on the same machine) and/or the heavy apache is able to
  +deliver the same static content as the light apache, the worst that will
  +happen is that the user's browser will display <CODE>:8080</CODE> in the location box for every subsequent URL on your site until they follow
  +an absolute link within your site (ie. <A
  +HREF="http://www.myservername.com/file/stuff">http://www.myservername.com/file/stuff</A>
  +as opposed to just /file/stuff) If the request is in a password-protected
  +area, then the user may have to log in twice.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_auth_dbm_nuances">mod_auth_dbm nuances</A></H1></CENTER>
  +If the heavy and light apaches do not share the same <CODE>DocumentRoot</CODE>
  +directory (normal if they are on different servers or have different
  +<CODE>DocumentRoot</CODE>'s) then images won't appear. This is worse than the previous scenario. At
  +least if the heavy apache can serve images, your site will still look
  +normal. If the heavy apache is *unable* to serve images, all your pages
  +will be imageless. This is a fairly compelling reason to run your light and
  +heavy servers on the same machine and to have them share a <CODE>DocumentRoot</CODE>.
  +
   <P>
  -If you are a user of <STRONG>mod_auth_dbm</STRONG> or <STRONG>mod_auth_db</STRONG>, you may need to edit Perl's <CODE>Config</CODE> module. When Perl is configured it attempts to find libraries for ndbm,
  -gdbm, db, etc., for the *DBM*_File modules. By default, these libraries are
  -linked with Perl and remembered by the <STRONG>Config</STRONG> module. When mod_perl is configured with apache, the <STRONG>ExtUtils::Embed</STRONG> module returns these libraries to be linked with httpd so Perl extensions
  -will work under mod_perl. However, the order in which these libraries are
  -stored in
  -<STRONG>Config.pm</STRONG>, may confuse <CODE>mod_auth_db*</CODE>. If <CODE>mod_auth_db*</CODE> does not work with mod_perl, take a look at this order with the following
  -command:
  +Regardless of how hard you try to eliminate <CODE>:8080</CODE>s, they *will* crop up from time to time. You should occasionally examine
  +the access_log of the heavy apache - any requests that appear in there
  +(assuming you aren't bothering to log requests that come via the light
  +apache) should be investigated.
   
   <P>
  -<PRE> % perl -V:libs
  -</PRE>
  +Interestingly, if the final catch-all <CODE>RedirectRule</CODE> is to
  +<CODE>localhost:8080</CODE>, it is possible that <CODE>localhost</CODE> will leak into stray client redirects. Moral: use your server's name in
  +redirects, unless you know different.
  +
  +<P><LI><STRONG><A NAME="item_Security">Security</A></STRONG>
   <P>
  -If <CODE>-lgdbm</CODE> or <CODE>-ldb</CODE> is before <CODE>-lndbm</CODE>, example:
  +Because all http requests will appear to your perl scripts to be coming
  +from the light httpd, you must be careful not to authenticate based on the
  +IP address from which a request came. This can be easy to overlook if you
  +are moving from a single- to a dual-server scenario.
   
   <P>
  -<PRE> libs='-lnet -lnsl_s -lgdbm -lndbm -ldb -ldld -lm -lc -lndir -lcrypt';
  -</PRE>
  +The URLs that return the <CODE>/server-status</CODE> and <CODE>/perl-status</CODE> of your apache servers are often protected based on IP address. The
  +<CODE>/server-status</CODE> URL for the heavy server is probably safe if the light apache also defines
  +an identical <CODE>/server-status</CODE> URL, but the
  +<CODE>/perl-status</CODE> URL should be protected.
  +
   <P>
  -Edit <STRONG>Config.pm</STRONG> and move <CODE>-lgdbm</CODE> and <CODE>-ldb</CODE> to the end of the list. Here's how to find <STRONG>Config.pm</STRONG>:
  +If you must authenticate based on IP address, you should either make sure
  +that the light apache's IP address is not in any way privileged or you
  +should block access to port <CODE>8080</CODE> from anywhere except the light apache's IP address.
   
   <P>
  -<PRE> % perl -MConfig -e 'print &quot;$Config{archlibexp}/Config.pm\n&quot;'
  -</PRE>
  +If your heavy and light httpds can both serve static content (where
  +<CODE>:8080</CODE>s only affect URLs - not content), then blocking port <CODE>8080</CODE>
  +is not recommended. After all, if a user accidentally (or intentionaly)
  +gets onto port <CODE>8080</CODE> in this scenario, the worst that will happen is that URLs will look odd.
  +
   <P>
  -Another solution for building Apache/mod_perl+mod_auth_dbm under Solaris is
  -to remove the DBM and NDBM ``emulation'' from libgdbm.a. Seems Solaris
  -already provides its own DBM and NDBM, and there's no reason to build GDBM
  -with them (for us anyway).
  +Note that if you are using the
  +<A HREF="././scenario.html#Building_and_Using_mod_proxy"><CODE>X-Forwarded-For</CODE></A> HTTP header, then this subsection is of limited relevance to you.
   
  +</UL>
   <P>
  -In our Makefile for GDBM, we changed
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Building_and_Using_mod_proxy">Building and Using mod_proxy</A></H1></CENTER>
  +<P>
  +To build it into apache just add <STRONG>--enable-module=proxy</STRONG> during the apache <STRONG>configure</STRONG> stage.
   
   <P>
  -<PRE>  OBJS = $(DBM_OF) $(NDBM_OF) $(GDBM_OF)
  +Now we will talk about apache's mod_proxy and understand how it works.
  +
  +<P>
  +The server on port 80 answers http requests directly and proxies the
  +mod_perl enabled server in the following way:
  +
  +<P>
  +<PRE>  ProxyPass        /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  +  ProxyPassReverse /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
   </PRE>
   <P>
  -to
  +<CODE>PPR</CODE> is the saving grace here, that makes apache a win over Squid. It rewrites
  +the redirect on its way back to the original URI.
   
   <P>
  -<PRE>  OBJS = $(GDBM_OF)
  +You can control the buffering feature with <CODE>ProxyReceiveBufferSize</CODE>
  +directive:
  +
  +<P>
  +<PRE>  ProxyReceiveBufferSize 1048576
   </PRE>
   <P>
  -Rebuild libgdbm, then Apache/mod_perl.  
  +The above setting will set a buffer size to be of 1Mb. If it is not set
  +explicitly, then the default buffer size is used, which depends on OS, for
  +Linux I suspect it is somewhere below 32k. So basically to get an immediate
  +release of the mod_perl server from stale awaiting,
  +<CODE>ProxyReceiveBufferSize</CODE> should be set to a value greater than the biggest generated respond
  +produced by any mod_perl script.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A></H1></CENTER>
  +The <CODE>ProxyReceiveBufferSize</CODE> directive specifies an explicit buffer size for <STRONG>outgoing</STRONG> HTTP and FTP connections. It has to be greater than 512 or set to 0 to
  +indicate that the system's default buffer size should be used.
  +
   <P>
  -Since most of the functionality that various apache mod_* modules provide
  -is being implemented in <CODE>Apache::{*}</CODE> perl modules, it was reported that one can build an apache server with
  -mod_perl only. If you can reduce the problems down to whatever mod_perl can
  -handle, you can eliminate nearly every other module. Then basically you
  -will have a perl-server, with C code to handle the tricky HTTP bits. The
  -only module you will need to leave in is a <CODE>mod_actions</CODE>.
  +As the name states, its buffering feature applies only to <STRONG>downstream
  +data</STRONG> (coming from the origin server to the proxy) and not upstream (i.e.
  +buffering the data being uploaded from the client browser to the proxy,
  +thus freeing the httpd_perl origin server from being tied up during a large
  +POST such as a file upload).
  +
  +<P>
  +Apache does caching as well. It's relevant to mod_perl only if you produce
  +proper headers, so your scripts' output can be cached. See apache
  +documentation for more details on configuration of this capability.
  +
  +<P>
  +Ask Bjoern Hansen has written a <CODE>mod_proxy_add_forward</CODE> module for apache, that sets the <CODE>X-Forwarded-For</CODE> field when doing a
  +<CODE>ProxyPass</CODE>, similar to what squid can do. (Its location is specified in the help
  +section). Basically, that module adds an extra HTTP header to proxying
  +requests. You can access that header in the mod_perl-enabled server, and
  +set the IP of the remote server. You won't need to compile anything into
  +the back-end server, if you are using <CODE>Apache::{Registry,PerlRun}</CODE> just put something like the following into <CODE>start-up.pl</CODE>:
  +
  +<P>
  +<PRE>  sub My::ProxyRemoteAddr ($) {
  +        my $r = shift;
  +   
  +        # we'll only look at the X-Forwarded-For header if the requests
  +        # comes from our proxy at localhost
  +        return OK unless ($r-&gt;connection-&gt;remote_ip eq &quot;127.0.0.1&quot;);
  +  
  +        # Select last value in the chain -- original client's ip
  +        if (my ($ip) = $r-&gt;headers_in-&gt;{'X-Forwarded-For'} =~ /([^,\s]+)$/) {
  +          $r-&gt;connection-&gt;remote_ip($ip);
  +        }
  +        
  +        return OK;
  +  }
  +</PRE>
  +<P>
  +And in <CODE>httpd.conf</CODE>:
  +
  +<P>
  +<PRE>  PerlPostReadRequestHandler My::ProxyRemoteAddr
  +</PRE>
  +<P>
  +Different sites have different needs. If you're using the header to set the
  +IP address, apache believes it is dealing with (in the logging and stuff),
  +you really don't want anyone but your own system to set the header. That's
  +why the above ``recommended code'' checks where the request is really
  +coming from, before changing the <CODE>remote_ip</CODE>.
  +
  +<P>
  +Generally you shouldn't trust the <CODE>X-Forwarded-For</CODE> header. You only want to rely on <CODE>X-Forwarded-For</CODE> headers from proxies you control yourself. If you know how to spoof a
  +cookie you've probably got the general idea on making HTTP headers and can
  +spoof the
  +<CODE>X-Forwarded-For</CODE> header as well. The only address *you* can count on as being a reliable
  +value is the one from
  +<CODE>r-&amp;gt;connection-&amp;gt;remote_ip</CODE>.
  +
  +<P>
  +From that point on, the remote IP address is correct. You should be able to
  +access <CODE>REMOTE_ADDR</CODE> as usual.
  +
  +<P>
  +It was reported that Ben Laurie's Apache-SSL does not seem to put the IPs
  +in the <CODE>X-Forwarded-For</CODE> header (it does not set up such a header at all). However, the <CODE>REMOTE_ADDER</CODE> it sets up and contains the IP of the original client machine.
  +
  +<P>
  +You could do the same thing with other environment variables (though I
  +think several of them are preserved, you will want to run some tests to see
  +which ones).
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="HTTP_Authentication_with_2_serve">HTTP Authentication with 2 servers + proxy</A></H1></CENTER>
  +<P>
  +Assuming that you have a setup of one ``front-end'' server, which proxies
  +the ``back-end'' (mod_perl) server, if you need to perform the
  +authentication in the ``back-end'' server, it should handle all
  +authentication itself. If apache proxies correctly, it seems like it would
  +pass through all authentication information, making the ``front-end''
  +apache somewhat ``dumb'', as it does nothing, but passes through all the
  +information.
   
  +<P>
  +The only possible caveat in the config file is that your <CODE>Auth</CODE> stuff needs to be in <CODE>&lt;Directory ...</CODE>&gt; ... <CODE>&lt;/Directory</CODE>&gt; tags because if you use a <CODE>&lt;Location /...</CODE>&gt; ... <CODE>&lt;/Location</CODE>&gt; the proxypass server takes the auth info for its own authentication
  +and would not pass it on.
  +
  +<P>
  +The same with mod_ssl, if plugged into a front-end server, all the SSL
  +requests be encoded/decoded properly by it.
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -10056,7 +10435,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="scenario.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="config.html">Next</A>      ]
  +	     [    <A HREF="strategy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -10069,7 +10448,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  +	     <BR>Last Modified at 10/16/1999
         </FONT>
       </B>
     </TD>
  @@ -10096,7 +10475,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Server Configuration</TITLE>
  +   <TITLE>mod_perl guide: Installation Notes</TITLE>
      <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
      <META NAME="Author" CONTENT="Stas Bekman">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  @@ -10115,66 +10494,64 @@
   <H1 ALIGN=CENTER>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Server Configuration</H1>
  +Installation Notes</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="install.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="frequent.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="scenario.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="config.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#mod_perl_Specific_Configuration">mod_perl Specific Configuration</A>
  +	<LI><A HREF="#Configuration_and_Installation">Configuration and Installation</A>
   	<UL>
   
  -		<LI><A HREF="#Alias_Configurations">Alias Configurations</A>
  -		<LI><A HREF="#Location_Configuration">Location Configuration</A>
  -		<LI><A HREF="#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
  -		<LI><A HREF="#Perl_Handlers">Perl*Handlers</A>
  +		<LI><A HREF="#perl">perl</A>
  +		<LI><A HREF="#apache">apache</A>
  +		<LI><A HREF="#mod_perl">mod_perl</A>
   	</UL>
   
  -	<LI><A HREF="#STACKED_HANDLERS">STACKED HANDLERS</A>
  -	<LI><A HREF="#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
  +	<LI><A HREF="#using_CPAN_to_install_mod_perl">using CPAN to install mod_perl</A>
  +	<LI><A HREF="#using_RPM_DEB_and_other_package">using RPM, DEB and other packages to install mod_perl</A>
   	<UL>
  -
  -		<LI><A HREF="#PerlFreshRestart">PerlFreshRestart</A>
  -		<LI><A HREF="#_perl_status_location">/perl-status location</A>
  -		<UL>
  -
  -			<LI><A HREF="#Configuration">Configuration</A>
  -			<LI><A HREF="#Usage">Usage</A>
  -			<LI><A HREF="#Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A>
  -		</UL>
   
  -		<LI><A HREF="#PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A>
  -		<LI><A HREF="#perl_startup_file">perl-startup file</A>
  -		<UL>
  +		<LI><A HREF="#A_word_on_mod_perl_RPM_packages">A word on mod_perl RPM packages</A>
  +		<LI><A HREF="#Getting_Started">Getting Started</A>
  +		<LI><A HREF="#Compiling_RPM_source_files">Compiling RPM source files</A>
  +		<LI><A HREF="#Mix_and_Match_RPM_and_source">Mix and Match RPM and source</A>
  +		<LI><A HREF="#Installing_a_single_apache_mod_p">Installing a single apache+mod_perl RPM</A>
  +		<LI><A HREF="#Compiling_libapreq_Apache_Requ">Compiling libapreq (Apache::Request) with the RH 6.0 mod_perl RPM</A>
  +		<LI><A HREF="#Compiling_libapreq_with_mod_perl">Compiling libapreq with mod_perl installed from RPM (general)</A>
  +		<LI><A HREF="#Installing_separate_Apache_and_m">Installing separate Apache and mod_perl RPMs</A>
  +		<LI><A HREF="#Testing_the_mod_perl_API">Testing the mod_perl API</A>
  +	</UL>
   
  -			<LI><A HREF="#Sample_perl_startup_file">Sample perl-startup file</A>
  -			<LI><A HREF="#What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A>
  -			<LI><A HREF="#The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A>
  -			<LI><A HREF="#The_confusion_with_defining_glob">The confusion with defining globals in startup</A>
  -		</UL>
  +	<LI><A HREF="#Automating_installation">Automating installation</A>
  +	<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
  +	<UL>
   
  +		<LI><A HREF="#Testing_by_checking_the_error_lo">Testing by checking the error_log file</A>
  +		<LI><A HREF="#Testing_by_viewing_perl_status">Testing by viewing /perl-status</A>
  +		<LI><A HREF="#Testing_via_telnet">Testing via telnet</A>
  +		<LI><A HREF="#Testing_via_a_CGI_script">Testing via a CGI script</A>
  +		<LI><A HREF="#Testing_via_lwp_request">Testing via lwp-request</A>
   	</UL>
   
  -	<LI><A HREF="#Running_apachectl_configtest_o">Running 'apachectl configtest' or 'httpd -t'</A>
  -	<LI><A HREF="#Perl_behavior_controls">Perl behavior controls</A>
  -	<LI><A HREF="#Tuning_MinSpareServers_MaxSpareS">Tuning MinSpareServers MaxSpareServers StartServers MaxClients</A>
  -	<LI><A HREF="#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
  -	<LI><A HREF="#Perl_Sections">Perl Sections</A>
  -	<LI><A HREF="#Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A>
  -	<LI><A HREF="#General_pitfalls">General pitfalls</A>
  +	<LI><A HREF="#Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A>
  +	<LI><A HREF="#Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A>
  +	<LI><A HREF="#Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A>
  +	<LI><A HREF="#Installation_problems">Installation problems</A>
   	<UL>
   
  -		<LI><A HREF="#My_cgi_perl_code_is_being_return">My cgi/perl code is being returned as a plain text instead of being executed by the webserver?</A>
  -		<LI><A HREF="#My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A>
  -		<LI><A HREF="#Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A>
  -		<LI><A HREF="#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A>
  -		<LI><A HREF="#A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A>
  -		<LI><A HREF="#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
  +		<LI><A HREF="#make_problems">make problems</A>
  +		<LI><A HREF="#make_test_skipping_test_on_">make test......skipping test on this platform</A>
  +		<LI><A HREF="#make_test_fails">make test fails</A>
  +		<LI><A HREF="#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
  +		<LI><A HREF="#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
   	</UL>
   
  -	<LI><A HREF="#Configuration_Security_Concerns">Configuration Security Concerns</A>
  -	<LI><A HREF="#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
  -	<LI><A HREF="#Apache_restarts_twice_on_start">Apache restarts twice on start</A>
  +	<LI><A HREF="#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
  +	<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  +	<LI><A HREF="#mod_perl_server_as_DSO">mod_perl server as DSO</A>
  +	<LI><A HREF="#Caveats_of_adding_mod_perl_php_">Caveats of adding mod_perl, php, ssl and other into Apache</A>
  +	<LI><A HREF="#Should_I_Build_mod_perl_with_gcc">Should I Build mod_perl with gcc or cc?</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -10201,1263 +10578,1164 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="mod_perl_Specific_Configuration">mod_perl Specific Configuration</A></H1></CENTER>
  +<CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
   <P>
  -The next step after building and installing your new mod_perl enabled
  -apache server, is to configure the server. To learn how to modify apache's
  -configuration files, please refer to the documentation included with the
  -apache distribution, or just view the files in
  -<CODE>conf</CODE> directory and follow the instructions in these files - the embedded
  -comments within the file do a good job of explaining the options.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="perl">perl</A></H2></CENTER>
   <P>
  -Before you start with mod_perl specific configuration, first configure
  -apache, and see that it works. When done, return here to continue...
  +Make sure you have perl installed -- the newer stable version you have the
  +better (minimum perl.5.004!). If you don't have it -- install it. Follow
  +the instructions in the distribution's <CODE>INSTALL</CODE>
  +file. During the configuration stage (while running <CODE>./Configure</CODE>), make sure you answer <CODE>YES</CODE> to the question:
   
   <P>
  -[ Note that prior to version 1.3.4, the default apache install used three
  -configuration files -- <STRONG>httpd.conf</STRONG>, <STRONG>srm.conf</STRONG>, and
  -<STRONG>access.conf</STRONG>. The 1.3.4 version began distributing the configuration directives in a
  -single file -- <STRONG>httpd.conf</STRONG>. The remainder of this chapter refers to the location of the configuration
  -directives using their historical location. ]
  +<PRE>  Do you wish to use dynamic loading? [y]
  +</PRE>
  +<P>
  +Answer <CODE>y</CODE> to be able to load dynamically Perl Modules extensions.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Alias_Configurations">Alias Configurations</A></H2></CENTER>
  -<P>
  -First, you need to specify the locations on a file-system for the scripts
  -to be found.
  -
  +<CENTER><H2><A NAME="apache">apache</A></H2></CENTER>
   <P>
  -Add the following configuration directives:
  +It is a good idea to try to install the apache webserver without mod_perl
  +first. This way, if something goes wrong, you will know that it's not the
  +apache server's problem. But you can skip this stage if you already have a
  +working (non-mod_perl) apache server, or if you are just the daring type.
  +In any case you should unpack the apache source distribution, preferably at
  +the same level as the mod_perl distribution.
   
   <P>
  -<PRE>    # for plain cgi-bin:
  -  ScriptAlias /cgi-bin/ /usr/local/myproject/cgi/
  -    
  -    # for Apache::Registry mode
  -  Alias /perl/ /usr/local/myproject/cgi/
  -    
  -    # Apache::PerlRun mode
  -  Alias /cgi-perl/ /usr/local/myproject/cgi/
  +<PRE>  % ls -l /usr/src
  +  drwxr-xr-x   8 stas  bar         2048 Oct  6 09:46 apache_x.x.x/
  +  drwxr-xr-x  19 stas  bar         4096 Oct  2 14:33 mod_perl-x.xx/
   </PRE>
   <P>
  -<CODE>Alias</CODE> provides a mapping of URL to file system object under
  -<CODE>mod_perl</CODE>. <CODE>ScriptAlias</CODE> is being used for <CODE>mod_cgi</CODE>.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="mod_perl">mod_perl</A></H2></CENTER>
   <P>
  -Alias defines the start of the URL path to the script you are referencing.
  -For example, using the above configuration, fetching
  -<CODE>http://www.nowhere.com/perl/test.pl</CODE>, will cause the server to look for the file <CODE>test.pl</CODE> at <CODE>/usr/local/myproject/cgi</CODE>, and execute it as an <CODE>Apache::Registry</CODE> script if we define <CODE>Apache::Registry</CODE> to be the handler of <CODE>/perl</CODE> location (see below). The URL
  -<CODE>http://www.nowhere.com/perl/test.pl</CODE> will be mapped to
  -<CODE>/usr/local/myproject/cgi/test.pl</CODE>. This means that you can have all your CGIs located at the same place in
  -the file-system, and call the script in any of three modes simply by
  -changing the directory name component of the URL (<CODE>cgi-bin|perl|cgi-perl</CODE>) - is not this neat? (That is the configuration you see above - all three
  -Aliases point to the same directory within your file system, but of course
  -they can be different). If your script does not seem to be working while
  -running under mod_perl, you can easily call the script in straight mod_cgi
  -mode without making any script changes (in most cases), but rather by
  -changing the URL you invoke it by.
  +Now we come to the main point of this document.
   
   <P>
  -FYI: for modperl <CODE>ScriptAlias</CODE> is the same thing as:
  +Here I will give only a short example of mod_perl installation. You should
  +read the <A HREF="././scenario.html#">Real World Scenarios Implementaion</A> for a more complete description.
   
  -<P>
  -<PRE>  Alias /foo/ /path/to/foo/
  -  SetHandler cgi-handler
  -</PRE>
   <P>
  -where <CODE>SetHandler cgi-handler</CODE> invokes mod_cgi. The latter will be overwritten if you enable <CODE>Apache::Registry</CODE>. In other words,
  -<CODE>ScriptAlias</CODE> does not work for mod_perl, it only appears to work when the additional
  -configuration is in there. If the
  -<CODE>Apache::Registry</CODE> configuration came before the <CODE>ScriptAlias</CODE>, scripts would be run under mod_cgi. While handy, <CODE>ScriptAlias</CODE> is a known kludge, always better to use <CODE>Alias</CODE> and <CODE>SetHandler</CODE>.
  +As with any perl package, the installation of mod_perl is very easy and
  +standard. <CODE>perldoc INSTALL</CODE> will guide you through the configuration and the installation processes.
   
   <P>
  -Of course you can choose any other Alias (you will use it later in
  -<CODE>httpd.conf</CODE>), you can choose to use all three modes or only one of these. It is
  -undesirable to run scripts in plain mod_cgi from a mod_perl-enabled server
  -- the price is too high, it is better to run these on plain apache server.
  -(See <A HREF="././strategy.html#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>)
  +The fastest way to install would be:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Location_Configuration">Location Configuration</A></H2></CENTER>
  +<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  +    DO_HTTPD=1  USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  +  % make &amp;&amp; make test &amp;&amp; make install
  +</PRE>
   <P>
  -Now we will work with the <CODE>httpd.conf</CODE> file. I add all the mod_perl stuff at the end of the file, after the native
  -apache configurations.
  +Note: replace x.x.x with the version numbers you actually use.
   
   <P>
  -First we add:
  +To change the installation target (either if you are not <CODE>root</CODE> or you need to install a second copy for testing purposes), assuming you
  +use <CODE>/foo/server</CODE> as a base directory, you have to run this:
   
   <P>
  -<PRE>  &lt;Location /perl&gt;
  -    #AllowOverride None
  -    SetHandler perl-script
  -    PerlHandler Apache::Registry
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  +<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  +    DO_HTTPD=1 PERL_MARK_WHERE=1 EVERYTHING=1 \
  +    APACHE_PREFIX=/foo/server PREFIX=/foo/server
   </PRE>
  -<P>
  -This configuration causes all scripts that are called with a <CODE>/perl</CODE>
  -path prefix to be executed under the <CODE>Apache::Registry</CODE> module and as a CGI (so the <STRONG>ExecCGI</STRONG>, if you omit this option the script will be printed to the caller's
  -browser as a plain text or possibly will trigger a 'Save-As' window).
  -
   <P>
  -<CODE>PerlSendHeader On</CODE> tells the server to send an HTTP header to the browser on every script
  -invocation. You will want to turn this off for nph (non-parsed-headers)
  -scripts. <CODE>PerlSendHeader On</CODE> means to call
  -<CODE>ap_send_http_header()</CODE> after parsing your script headers. It is only meant for CGI emulation, its
  -always better to use <CODE>CGI-&amp;gt;header</CODE>
  -from <CODE>CGI.pm</CODE> module or <CODE>$r-&amp;gt;send_http_header</CODE> directly.
  +Where <CODE>PREFIX</CODE> specifies where to install the perl modules,
  +<CODE>APACHE_PREFIX</CODE> -- the same for the apache files.
   
   <P>
  -Remember the <STRONG>Alias</STRONG> from the section above? We must use the same
  -<CODE>Alias</CODE> here, if you use <CODE>Location</CODE> that does not have the same
  -<CODE>Alias</CODE> defined in <CODE>srm.conf</CODE>, the server will fail to locate the script in the file system. (We are
  -talking about script execution here -- there are cases where <CODE>Location</CODE> is something that is being executed by the server itself, without having
  -the corresponding file, like <CODE>/perl-status</CODE> location.)
  +The next step is to configure the mod_perl sections of the apache
  +configuration file. (See <A HREF="././config.html#">ModPerlConfiguration</A>).
   
   <P>
  -Note that sometimes you will have to add :
  +Fire up the server with <CODE>/foo/server/sbin/apachectl start</CODE>, Look for the error reports at the <CODE>error_log</CODE> file in case the server does not start up (No error message will be printed
  +to the console!).
   
   <P>
  -<PRE>  PerlModule Apache::Registry
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="using_CPAN_to_install_mod_perl">using CPAN to install mod_perl</A></H1></CENTER>
   <P>
  -before you specify the location that uses <CODE>Apache::Registry</CODE> as a
  -<CODE>PerlHandler</CODE>. Basically you can start running the scripts in the
  -<CODE>Apache::Registry</CODE> mode...
  +To install mod_perl and all the required packages is much easier with help
  +of <CODE>CPAN.pm</CODE> module, which provides you among other features a shell interface to a CPAN
  +repository (CPAN = Comprehensive Perl Archive Network, which is a
  +repository of thousands Perl modules, scripts and documentation. See <A
  +HREF="http://cpan.org">http://cpan.org</A> for more info)
   
   <P>
  -You have nothing to do about <CODE>/cgi-bin</CODE> location (mod_cgi), since it has nothing to do with mod_perl.
  +First thing first is to download an Apache source code, unpack it into a
  +directory the name of which you will need very soon. 
   
   <P>
  -Here is a similar location configuration for <CODE>Apache::PerlRun</CODE> (More about <A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun</A>):
  +Now execute:
   
   <P>
  -<PRE>  &lt;Location /cgi-perl&gt;
  -    #AllowOverride None
  -    SetHandler perl-script
  -    PerlHandler Apache::PerlRun
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  +<PRE>  % perl -MCPAN -eshell
   </PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A></H2></CENTER>
   <P>
  -You may load modules from the config file at server startup via:
  +If it's a first time that you use it, it will ask you about 10 questions to
  +configure the module. It's quite easy to accomplish this task, when
  +following the very helful hints coming along with the questions. When you
  +done, you will see a <CODE>cpan</CODE> prompt:
   
   <P>
  -<PRE>    PerlModule Apache::DBI CGI DBD::Mysql
  +<PRE>  cpan&gt; 
   </PRE>
   <P>
  -There is a limit of 10 <CODE>PerlModule</CODE>'s, if you need more to be loaded when the server starts, use one <CODE>PerlModule</CODE> to pull in many or write them all in a regular perl syntax and put them
  -into a startup file which can be loaded with use of the <CODE>PerlRequire</CODE> directive. 
  +CPAN will download mod_perl for you, unpack it, will check prerequisites,
  +detect the missing third party modules if any, download and install them.
  +All you need to install mod_perl is to type at the prompt:
   
   <P>
  -<PRE>    PerlRequire  /home/httpd/perl/lib/startup.pl
  +<PRE>  cpan&gt; install mod_perl
   </PRE>
   <P>
  -Both <CODE>PerlModule</CODE> and <CODE>PerlRequire</CODE> are implemented by <CODE>require(),</CODE> but there is a subtle change. <CODE>PerlModule</CODE> works like <CODE>use(),</CODE> expecting a module name without <CODE>.pm</CODE> extension and slashes.
  -<CODE>Apache::DBI</CODE> is OK, while <CODE>Apache/DBI.pm</CODE> is not. <CODE>PerlRequire</CODE> is the opposite to <CODE>PerlModule</CODE> -- it expects a relative or full path to the module or a filename, like in
  -the example above.
  +You will see (I'll use <CODE>x.xx</CODE> instead of real version numbers, since these change very frequently):
   
   <P>
  -As with any file that's being <CODE>required()</CODE> -- it must return a <STRONG>true</STRONG>
  -value, to ensure that this happens don't forget to add <CODE>1;</CODE> at the end of such files.
  -
  +<PRE>  Running make for DOUGM/mod_perl-x.xx.tar.gz
  +  Fetching with LWP:
  +  <A HREF="http://www.perl.com/CPAN-local/authors/id/DOUGM/mod_perl-x.xx.tar.gz">http://www.perl.com/CPAN-local/authors/id/DOUGM/mod_perl-x.xx.tar.gz</A>
  +  
  +  CPAN.pm: Going to build DOUGM/mod_perl-x.xx.tar.gz
  +  
  +  Enter `q' to stop search
  +  Please tell me where I can find your apache src
  +  [../apache-x.x.x/src]
  +</PRE>
   <P>
  -We must stress that all the code that is run at the server initialization
  -time is run with root priveleges if you are executing it as a root user
  -(you have to unless you choose an unpriveledged port, above 1024.
  -somethings that you might have to if you don't have a root access. Just
  -remember that you better pick a well known port like 8000 or 8080 since
  -other non-standard ports might be blocked by firewalls that protect many
  -organizations and individuals). This means that anyone who has write access
  -to a script or module that is loaded by <CODE>PerlModule</CODE> or <CODE>PerlRequire</CODE>, effectively has root access to the system. You might want to take a look
  -at the new and experimental <CODE>PerlOpmask</CODE> directive and <CODE>PERL_OPMASK_DEFAULT</CODE>
  -compile time option to try to disable some dangerous operators.
  +It will search for a latest apache sources and suggest a directory. Here
  +you need to type in the directory you have unpacked the apache in unless it
  +CPAN detected and suggested the right directory... The next question is
  +about the <CODE>src</CODE> directory which resides at the root level of the unpacked Apache
  +distribution. In most cases CPAN would ``guess'' the correct directory.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Perl_Handlers">Perl*Handlers</A></H2></CENTER>
  +<PRE>  Please tell me where I can find your apache src
  +  [../apache-x.x.x/src] 
  +</PRE>
   <P>
  -As you know Apache specifies about 11 phases of the request loop, namely in
  -that order: Post-Read-Request, URI Translation, Header Parsing, Access
  -Control, Authentication, Authorization, MIME type checking, FixUp, Response
  -(Content phase). Logging and finally Cleanup. These are the stages of a
  -request where the Apache API allows a module to step in and do something.
  -There is a dedicated PerlHandler for each of these stages. Namely:
  +Answer yes to all the following questions, unless you have a reason not to
  +do that.
   
   <P>
  -<PRE>    PerlChildInitHandler
  -    PerlPostReadRequestHandler
  -    PerlInitHandler
  -    PerlTransHandler
  -    PerlHeaderParserHandler
  -    PerlAccessHandler
  -    PerlAuthenHandler
  -    PerlAuthzHandler
  -    PerlTypeHandler
  -    PerlFixupHandler
  -    PerlHandler
  -    PerlLogHandler
  -    PerlCleanupHandler
  -    PerlChildExitHandler
  +<PRE>  Configure mod_perl with /usr/src/apache_x.x.x/src ? [y] 
  +  Shall I build httpd in /usr/src/apache_x.x.x/src for you? [y] 
   </PRE>
   <P>
  -The first 4 handlers cannot be used in the <CODE>&lt;Location</CODE>&gt;,
  -<CODE>&lt;Directory</CODE>&gt;, <CODE>&lt;Files</CODE>&gt; and <CODE>.htaccess</CODE> file, the main reason is all the above require a known path to the file in
  -order to bind a requested path with one or more of the identifiers above.
  -Starting from <CODE>PerlHeaderParserHandler</CODE> (5th) URI is allready being mapped to a physical pathname, thus can be used
  -to match the <CODE>&lt;Location</CODE>&gt;,
  -<CODE>&lt;Directory</CODE>&gt; or <CODE>&lt;Files</CODE>&gt; configuration section, or to look at
  -<CODE>.htaccess</CODE> file if exists at the specified directory in the translated path.
  +Now it will build the apache with enabled mod_perl. The only thing left to
  +do is to go to apache sources root directory (when you quit
  +<CODE>CPAN</CODE> shell or use using another terminal) and run:
   
   <P>
  -The Apache documentation (or even better -- the ``Writing Apache Modules
  -with Perl and C'' book by Doug MacEachern and Lincoln Stein) will tell you
  -all about those stages and what your modules can do. By default, these
  -hooks are disabled at compile time, see the INSTALL document for
  -information on enabling these hooks.
  +<PRE>  % make install
  +</PRE>
  +<P>
  +which will complete the installation by installing Apache headers and the
  +binary at the appropriate directories.
   
   <P>
  -Note that by default Perl API expects a subrotine called <CODE>handler</CODE> to handle the request in the registered PerlHandler module. Thus if your
  -module implements this subrotine, you can register the handler as simple as
  -writing:
  +The only caveat of descibed process is that you don't have a control over a
  +configuration process. Actually, it's an easy to solve problem -- you can
  +tell &lt;CPAN.pm&gt; to pass whatever parameters you want to
  +<CODE>perl Makefile.PL</CODE>. You do this with <CODE>o conf make_arg</CODE> command:
   
   <P>
  -<PRE>  Perl*Handler Apache::SomeModule
  +<PRE>  cpan&gt; o conf make_arg 'DO_HTTPD=1 USE_APACI=1 EVERYTHING=1'
   </PRE>
   <P>
  -replace <EM>Perl*Handler</EM> with a wanted name of the handler. mod_perl will preload the specified
  -module for you. But if you decide to give the handler code a different
  -name, like <CODE>my_handler</CODE>, you must preload the module and to write explicitly the chosen name.
  +You just enlist all the parameters like you were to pass to a familiar
  +<CODE>perl Makefile.PL</CODE>.
   
   <P>
  -<PRE>  PerlModule Apache::SomeModule
  -  Perl*Handler Apache::SomeModule::my_handler
  +Now procceed with <CODE>install mod_perl</CODE>, like before. When the installation is completed, remember to unset the <CODE>make_arg</CODE> variable, by executing:
  +
  +<P>
  +<PRE>  cpan&gt; o conf make_arg ''
   </PRE>
   <P>
  -Please note that the former approach will not preload the module at the
  -startup, so either explicitly preload it with <CODE>PerlModule</CODE>
  -directive, add it to the startup file or use a nice shortcut the
  -<CODE>Perl*Handler</CODE> syntax suggests:
  +In case you have the <CODE>make_arg</CODE> previously (before you altered it for a mod_perl installation) set to some
  +value, you will probably want to save it somewhere, and restore when you
  +done with mod_perl installation. To read the original value, use:
   
   <P>
  -<PRE>  Perl*Handler +Apache::SomeModule
  +<PRE>  cpan&gt; o conf make_arg
   </PRE>
   <P>
  -Notice the leading <CODE>+</CODE> character. It's equal to:
  +You can install all the modules you might want to use with mod_perl. You
  +install them all by typing a singe command:
   
   <P>
  -<PRE>  PerlModule Apache::SomeModule
  -  Perl*Handler Apache::SomeModule
  +<PRE>  cpan&gt; install Bundle::Apache
   </PRE>
   <P>
  -If a module wishes to know what handler is currently being run, it can find
  -out with the <EM>current_callback</EM> method. This method is most useful to <EM>PerlDispatchHandlers</EM> who wish to only take action for certain phases.
  +It'll install mod_perl if isn't yet installed and many other packages like: <CODE>ExtUtils::Embed</CODE>, <CODE>MIME::Base64</CODE>, <CODE>URI::URL</CODE>,
  +<CODE>Digest::MD5</CODE>, <CODE>Net::FTP</CODE>, <CODE>LWP</CODE>, <CODE>HTML::TreeBuilder</CODE>, <CODE>CGI</CODE>,
  +<CODE>Devel::Symdump</CODE>, <CODE>Apache::DB</CODE>, <CODE>Tie::IxHash</CODE>, <CODE>Data::Dumper</CODE> and etc.
   
   <P>
  -<PRE> if($r-&gt;current_callback eq &quot;PerlLogHandler&quot;) {
  -     $r-&gt;warn(&quot;Logging request&quot;);
  - }
  +A helpful hint: If you have a system with all the perl modules you use and
  +you want to replicate them all at some other place, and if you cannot just
  +copy the whole <CODE>/usr/lib/perl5</CODE> directory because of a possible binary incompatibility of the other system,
  +making your own bundle comes as a handy solution. To accomplish that the
  +command
  +<CODE>autobundle</CODE> can be used on the CPAN shell command line. This command writes a bundle
  +definition file for all modules that are installed for the currently
  +running perl interpreter.
  +
  +<P>
  +With a clever bundle file you can then simply say
  +
  +<P>
  +<PRE>  cpan&gt; install Bundle::my_bundle
   </PRE>
   <P>
  +then answer a few questions and then go out for a coffee.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="STACKED_HANDLERS">STACKED HANDLERS</A></H1></CENTER>
  +<CENTER><H1><A NAME="using_RPM_DEB_and_other_package">using RPM, DEB and other packages to install mod_perl</A></H1></CENTER>
   <P>
  -With the mod_perl stacked handlers mechanism, it is possible for more than
  -one <CODE>Perl*Handler</CODE> to be defined and run during each stage of a request.
  +META: meanwhile only RPM. please submit the info about DEB and other
  +available packages.
   
   <P>
  -Perl*Handler directives can define any number of subroutines, e.g. (in
  -config files)
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="A_word_on_mod_perl_RPM_packages">A word on mod_perl RPM packages</A></H2></CENTER>
  +<P>
  +The virtues of RPM packages is the subject of much debate among mod_perl
  +users. While RPMs do take the pain away from package installation and
  +maintenance for most applications, the nuances of mod_perl make RPMs
  +somewhat less than ideal for those just getting started. The following help
  +and advice is for those new to mod_perl, Apache, Linux, and RPMs. If you
  +know what you are doing, this is probably old hat - contributing your past
  +experiences is, as always, welcome by the community.
   
   <P>
  -<PRE> PerlTransHandler OneTrans TwoTrans RedTrans BlueTrans
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Getting_Started">Getting Started</A></H2></CENTER>
   <P>
  -With the method, <CODE>Apache-&amp;gt;push_handlers()</CODE>, callbacks can be added to the stack by scripts at runtime by mod_perl
  -scripts.
  +If you are new to mod_perl and are using this Guide and the Eagle book to
  +help you on your way, it is probably better to grab the latest Apache and
  +mod_perl sources and compile the sources yourself. Not only will you find
  +that this is less daunting than you suspect, but it will probably save you
  +a few headaches down the line for several reasons.
   
   <P>
  -<CODE>Apache-&amp;gt;push_handlers()</CODE> takes the callback hook name as its first argument and a subroutine name or
  -reference as its second. e.g.:
  +First, given the pace at which the open source community produces software,
  +RPMs, especially those found on distribution CDs, are often several
  +versions out of date. The most recent version will not only be more stable,
  +but will likely incorporate some new functionality that you will eventually
  +want to play with.
   
   <P>
  -<PRE> Apache-&gt;push_handlers(&quot;PerlLogHandler&quot;, \&amp;first_one);
  - 
  - $r-&gt;push_handlers(&quot;PerlLogHandler&quot;, sub {
  -     print STDERR &quot;__ANON__ called\n&quot;;
  -     return 0;
  - });
  -</PRE>
  +It is also unlikely that the file system's layout of an RPM package will
  +match what you see in either the Eagle book or this Guide. If you are new
  +to mod_perl, Apache, or both, you will probably want to get familiar with
  +file system used by the examples given here before trying something less
  +standard.
  +
   <P>
  -After each request, this stack is cleared out.
  +Finally, the RPMs found on a typical distribution CDs use mod_perl build
  +with Apache's Dynamic Shared Objects (<CODE>DSO</CODE>) support. While mod_perl can be successfully used as a DSO module, it adds
  +a layer of complexity that you may want to live without for now.
   
   <P>
  -All handlers will be called unless a handler returns a status other than <CODE>OK</CODE> or <CODE>DECLINED</CODE>.
  +All that being said, should you still feel that rolling your own mod_perl
  +enabled Apache server is not likely, here are a few helpful hints...
   
   <P>
  -example uses:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Compiling_RPM_source_files">Compiling RPM source files</A></H2></CENTER>
  +<P>
  +It is possible to compile the source files provided my RPM packages, but if
  +you are using RPMs to ease mod_perl installation, that is not the way to do
  +it. Both Apache and mod_perl RPMs are designed to be install-and-go. If you
  +really want to compile mod_perl to your own specific needs, your best bet
  +is to get the most recent sources from CPAN.
   
   <P>
  -<CODE>CGI.pm</CODE> maintains a global object for its plain function interface. Since the
  -object is global, it does not go out of scope, DESTROY is never called.  <CODE>CGI-&amp;gt;new</CODE> can call:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Mix_and_Match_RPM_and_source">Mix and Match RPM and source</A></H2></CENTER>
  +<P>
  +It is probably not the best idea to use a self-compiled Apache with a
  +mod_perl RPM (or vice versa). Sticking with one format or the other at
  +first will result in fewer headaches and more hair.
   
   <P>
  -<PRE> Apache-&gt;push_handlers(&quot;PerlCleanupHandler&quot;, \&amp;CGI::_reset_globals);
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Installing_a_single_apache_mod_p">Installing a single apache+mod_perl RPM</A></H2></CENTER>
   <P>
  -This function will be called during the final stage of a request,
  -refreshing <CODE>CGI.pm</CODE>'s globals before the next request comes in.
  +If you use an apache+mod_perl RPM, chances are <CODE>rpm -i</CODE> or <CODE>glint</CODE>
  +(GUI for RPM) will have you up and running immediately, no compilation
  +necessary. If you encounter problems, try downloading from another mirror
  +site or searching <A HREF="http://rpmfind.net/">http://rpmfind.net/</A> for
  +a different package - there are plenty out there to choose from. 
   
   <P>
  -<CODE>Apache::DCELogin</CODE> establishes a DCE login context which must exist for the lifetime of a
  -request, so the <CODE>DCE::Login</CODE> object is stored in a global variable. Without stacked handlers, users must
  -set
  +David Harris has started the efforts to build a better RPM/SRPM mod_perl
  +packages. You will find them at: <A
  +HREF="http://www.davideous.com/modperlrpm/distrib/">http://www.davideous.com/modperlrpm/distrib/</A>
  +
   
   <P>
  -<PRE> PerlCleanupHandler Apache::DCELogin::purge
  -</PRE>
  +Features of this RPM:
  +
  +<UL>
  +<P><LI>
   <P>
  -in the configuration files to destroy the context. This is not
  -``user-friendly''. Now, <CODE>Apache::DCELogin::handler</CODE> can call:
  +Installs mod_perl as an ``add in'' to the RedHat Apache package, but does
  +not install mod_perl as a DSO and all the problems that brings.
   
  +<P><LI>
   <P>
  -<PRE> Apache-&gt;push_handlers(&quot;PerlCleanupHandler&quot;, \&amp;purge);
  -</PRE>
  +Includes the four header files required for building <CODE>libapreq</CODE>
  +(<CODE>Apache::Request</CODE>)
  +
  +<P><LI>
   <P>
  -Persistent database connection modules such as <CODE>Apache::DBI</CODE> could push a <CODE>PerlCleanupHandler</CODE> handler that iterates over <CODE>%Connected</CODE>, refreshing connections or just checking that ones have not gone stale.
  -Remember, by the time we get to <CODE>PerlCleanupHandler</CODE>, the client has what it wants and has gone away, we can spend as much time
  -as we want here without slowing down response time to the client (but the
  -process is unavailable for serving new request befor the operation is
  -completed).
  +Distributes plain text forms of the pod documentation files that come with
  +mod_perl.
   
  +<P><LI>
   <P>
  -<CODE>PerlTransHandlers</CODE> may decide, based on URI or other condition, whether or not to handle a
  -request, e.g. <CODE>Apache::MsqlProxy</CODE>. Without stacked handlers, users must configure:
  +Checks the module magic number on the existing apache package to see if
  +things are compatible
   
  +</UL>
   <P>
  -<PRE> PerlTransHandler Apache::MsqlProxy::translate
  - PerlHandler      Apache::MsqlProxy
  -</PRE>
  +Notes on this un-conventional RPM packaging of mod_perl
  +
   <P>
  -<CODE>PerlHandler</CODE> is never actually invoked unless <CODE>translate()</CODE> sees the request is a proxy request (<CODE>$r-&amp;gt;proxyreq</CODE>), if it is a proxy request, <CODE>translate()</CODE> sets <CODE>$r-&amp;gt;handler(&quot;perl-script&quot;)</CODE>, only then will <CODE>PerlHandler</CODE> handle the request. Now, users do not have to specify <CODE>PerlHandler Apache::MsqlProxy</CODE>, the <CODE>translate()</CODE>
  -function can set it with <CODE>push_handlers()</CODE>.
  +by David Harris &lt;<A
  +HREF="mailto:dharris@drh.net">dharris@drh.net</A>&gt; on Oct 13, 1999
   
   <P>
  -Includes, footers, headers, etc., piecing together a document, imagine (no
  -need for SSI parsing!):
  +This package will install the mod_perl library files on your machine along
  +with the following two Apache files:
   
   <P>
  -<PRE> PerlHandler My::Header Some::Body A::Footer
  +<PRE>  /usr/lib/apache/mod_include_modperl.so
  +  /usr/sbin/httpd_modperl
   </PRE>
   <P>
  -A little test:
  +This package does not install a complete apache subtree built with
  +mod_perl, but rather just the two above files that are different for
  +mod_perl. This conceptually thinks of mod_perl as a kind of an ``add on''
  +that we would like to add to the regular apache tree. However, we are
  +prevented from distributing mod_perl as an actual DSO, because it is not
  +recommended by the mod_perl developers and various features must be turned
  +off. So, instead, we distribute a httpd binary with mod_perl statically
  +linked (httpd_modperl) and the special modified mod_include.so required for
  +this binary (mod_include_modperl.so). You can use the exact same
  +configuration files and other DSO modules, but you just ``enable'' the
  +mod_perl ``add on'' by following the below directions.
   
  -<P>
  -<PRE> #My.pm
  - package My;
  -</PRE>
   <P>
  -<PRE> sub header {
  -     my $r = shift;
  -     $r-&gt;content_type(&quot;text/plain&quot;);
  -     $r-&gt;send_http_header;
  -     $r-&gt;print(&quot;header text\n&quot;);
  - }
  - sub body   { shift-&gt;print(&quot;body text\n&quot;)   }
  - sub footer { shift-&gt;print(&quot;footer text\n&quot;) }
  - 1;
  - __END__
  -</PRE>
  +To enable mod_perl, do the following:
  +
   <P>
  -<PRE> #in config
  - &lt;Location /foo&gt;
  - SetHandler &quot;perl-script&quot;
  - PerlHandler My::header My::body My::footer   
  - &lt;/Location&gt;
  +<PRE>  (1) Configure /etc/rc.d/init.d/httpd to run httpd_modperl instead of
  +      httpd by chaning the &quot;daemon&quot; command line.
  +  (2) Replace mod_include.so with mod_include_modperl.so in the
  +      module loading section of /etc/httpd/conf/httpd.conf
  +  (3) Uncomment the &quot;AddModule mod_perl.c&quot; line in /etc/httpd/conf/httpd.conf
   </PRE>
   <P>
  -Parsing the output of another PerlHandler? this is a little more tricky,
  -but consider:
  +Or run the following command: (and the other version to disable mod_perl)
   
   <P>
  -<PRE> &lt;Location /foo&gt;
  -   SetHandler &quot;perl-script&quot;
  -   PerlHandler OutputParser SomeApp
  - &lt;/Location&gt;
  - 
  - &lt;Location /bar&gt;
  -   SetHandler &quot;perl-script&quot;
  -   PerlHandler OutputParser AnotherApp
  - &lt;/Location&gt;
  +<PRE>  /usr/sbin/modperl-enable on
  +  /usr/sbin/modperl-enable off
   </PRE>
   <P>
  -Now, OutputParser goes first, but it <CODE>untie()'s</CODE> <CODE>*STDOUT</CODE> and re-tie()'s to its own package like so:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Compiling_libapreq_Apache_Requ">Compiling libapreq (Apache::Request) with the RH 6.0 mod_perl RPM</A></H2></CENTER>
  +<P>
  +The instructions are as follows:
   
  +<OL>
  +<P><LI>
   <P>
  -<PRE> package OutputParser;
  -</PRE>
  +Install the source RPM for your mod_perl RPM and then do a build prep,
  +which unpacks the sources. From there, copy four header files (mod_perl.h,
  +mod_perl_version.h, mod_perl_xs.h, and mod_PL.h) to <CODE>/usr/include/apache</CODE>.
  +
  +<OL>
  +<P><LI>
   <P>
  -<PRE> sub handler {
  -     my $r = shift;
  -     untie *STDOUT;
  -     tie *STDOUT =&gt; 'OutputParser', $r;
  - }
  -  
  - sub TIEHANDLE {
  -     my($class, $r) = @_;
  -     bless { r =&gt; $r}, $class;
  - }
  - 
  - sub PRINT {
  -     my $self = shift;   
  -     for (@_) {
  -         #do whatever you want to $_
  -         $self-&gt;{r}-&gt;print($_ . &quot;[insert stuff]&quot;);
  -     }
  - }
  -</PRE>
  +Get the SRPM from
  +<CODE>somemirror.../redhat-6.0/SRPMS/mod_perl-1.19-2.src.rpm</CODE>.
  +
  +<P><LI>
   <P>
  -<PRE> 1;
  - __END__
  +Install the SRPM. (This creates files in <CODE>/usr/src/redhat/SPECS</CODE> and
  +<CODE>/usr/src/redhat/SOURCES</CODE>). Run:
  +
  +<P>
  +<PRE> % rpm -ih mod_perl-1.19-2.src.rpm
   </PRE>
  +<P><LI>
   <P>
  -To build in this feature, configure with:
  +Do a <CODE>&quot;prep&quot;</CODE> build of the package, which just un-packags the sources and applies any
  +patches.
   
   <P>
  -<PRE> % perl Makefile.PL PERL_STACKED_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
  +<PRE>  % rpm -bp /usr/src/redhat/SPECS/mod_perl.spec
  +  Executing: %prep
  +  + umask 022
  +  + cd /usr/src/redhat/BUILD
  +  + cd /usr/src/redhat/BUILD
  +  + rm -rf mod_perl-1.19
  +  + /bin/gzip -dc /usr/src/redhat/SOURCES/mod_perl-1.19.tar.gz
  +  + tar -xf -
  +  + STATUS=0
  +  + [ 0 -ne 0 ]
  +  + cd mod_perl-1.19
  +  ++ /usr/bin/id -u
  +  + [ 0 = 0 ]
  +  + /bin/chown -Rf root .
  +  ++ /usr/bin/id -u
  +  + [ 0 = 0 ]
  +  + /bin/chgrp -Rf root .
  +  + /bin/chmod -Rf a+rX,g-w,o-w .
  +  + echo Patch #0:
  +  Patch #0:
  +  + patch -p1 -b --suffix .rh -s
  +  + exit 0
   </PRE>
   <P>
  -Another method <CODE>Apache-&amp;gt;can_stack_handlers</CODE> will return TRUE if mod_perl was configured with <CODE>PERL_STACKED_HANDLERS=1</CODE>, FALSE otherwise.
  +NOTE: What you have just done in steps 1.1 through 1.3 was just a fancy
  +un-packing of the source tree that builds the RPM into
  +<CODE>/usr/src/redhat/BUILD/mod_perl-1.19</CODE>. You could un-pack the
  +<CODE>mod_perl-x.xx.tar.gz</CODE> file somewhere and then do the following steps on that souce tree. But this
  +is more ``pure'' because I'm grabbing the header files from the same tree
  +that built the RPM. But this does not matter because RedHat is not patching
  +that file. So, it might be better if you just tell the person to grab the
  +mod_perl source and unpack it to get these files.. less fuss and mess.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A></H1></CENTER>
  +<P><LI>
   <P>
  -If a Perl*Handler is prototyped with <CODE>$$</CODE>, this handler will be invoked as method. e.g.
  +Look at the files you will copy: (this is not really a step, but useful to
  +show)
   
   <P>
  -<PRE> package My;
  - @ISA = qw(BaseClass);
  -  
  - sub handler ($$) {
  -     my($class, $r) = @_;
  -     ...;
  - }
  -  
  - package BaseClass;
  -  
  - sub method ($$) {
  -     my($class, $r) = @_;
  -     ...;
  - }
  - __END__
  +<PRE>  % find /usr/src/redhat/BUILD/mod_perl-1.19 -name '*.h'
  +  /usr/src/redhat/BUILD/mod_perl-1.19/src/modules/perl/mod_perl.h
  +  /usr/src/redhat/BUILD/mod_perl-1.19/src/modules/perl/mod_perl_xs.h
  +  /usr/src/redhat/BUILD/mod_perl-1.19/src/modules/perl/mod_perl_version.h
  +  /usr/src/redhat/BUILD/mod_perl-1.19/src/modules/perl/perl_PL.h
   </PRE>
  +<P><LI>
   <P>
  -Configuration:
  +Copy the files into <CODE>/usr/include/apache</CODE>.
   
  -<P>
  -<PRE> PerlHandler My
  -</PRE>
   <P>
  -or
  +NOTE: You should not have to do a:
   
   <P>
  -<PRE> PerlHandler My-&gt;handler
  +<PRE>  mkdir /usr/include/apache
   </PRE>
   <P>
  -Since the handler is invoked as a method, it may inherit from other
  -classes:
  +Because that directory should be created by apache-devel, which I think you
  +will need to compile libapreq. The machine I did this test on just happened
  +not to have the apache-devel package.
   
   <P>
  -<PRE> PerlHandler My-&gt;method
  +<PRE>  % mkdir /usr/include/apache
  +  % cp ` find /usr/src/redhat/BUILD/mod_perl-1.19 -name '*.h' `
  +    /usr/include/apache
   </PRE>
  +</OL>
  +<P><LI>
   <P>
  -In this case, the <CODE>My</CODE> class inherits this method from <CODE>BaseClass</CODE>.
  +Apply this patch to libapreq: <A
  +HREF="http://www.davideous.com/modperlrpm/distrib/libapreq-0.31_include.patch">http://www.davideous.com/modperlrpm/distrib/libapreq-0.31_include.patch</A>
   
  -<P>
  -To build in this feature, configure with:
   
  -<P>
  -<PRE> % perl Makefile.PL PERL_METHOD_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="PerlFreshRestart">PerlFreshRestart</A></H2></CENTER>
  +<P><LI>
   <P>
  -To reload <CODE>PerlRequire</CODE>, <CODE>PerlModule</CODE>, other <CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache on server restart, add:
  +Follow the libapreq directions as usual:
   
   <P>
  -<PRE>  PerlFreshRestart On
  -Make sure you read L&lt;Evil things might happen when using
  -PerlFreshRestart|warnings/Evil_things_might_happen_when_us&gt;.
  +<PRE>  % perl Makefile.PL
  +  % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
  +</OL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="_perl_status_location">/perl-status location</A></H2></CENTER>
  +<CENTER><H2><A NAME="Compiling_libapreq_with_mod_perl">Compiling libapreq with mod_perl installed from RPM (general)</A></H2></CENTER>
   <P>
  -A very useful feature. You can watch what happens to the perl guts of the
  -server. Below you will find the instructions of configuration and usage of
  -this feature
  +There have been many reports of libapreq - which provides the
  +<CODE>Apache::Request</CODE> module - not working properly with various RPM packages. It is definitely
  +possible to integrate libapreq with mod_perl RPMs, it just requires a few
  +additional steps.
   
  +<OL>
  +<P><LI>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Configuration">Configuration</A></H3></CENTER>
  +Make certain you have the <CODE>apache-devel-x.x.x-x.i386.rpm</CODE> package installed.
  +
  +<P><LI>
   <P>
  -Add this to <CODE>httpd.conf</CODE>:
  +Install <CODE>mod_perl-x.xx-x.src.rpm</CODE> source code package using the following syntax:
   
   <P>
  -<PRE>  &lt;Location /perl-status&gt;
  -    SetHandler perl-script
  -    PerlHandler Apache::Status
  -    order deny,allow
  -    #deny from all
  -    #allow from 
  -  &lt;/Location&gt;
  +<PRE>  % rpm -ih mod_perl-x.xx-x.src.rpm
   </PRE>
  +<P><LI>
   <P>
  -If you are going to use <CODE>Apache::Status</CODE>, it's important to put it as a first module in the start-up file, or in
  -the <CODE>httpd.conf</CODE> (after
  -<CODE>Apache::Registry</CODE>):
  +Prepare the source package using the following syntax:
   
   <P>
  -<PRE>  # startup.pl
  -  use Apache::Registry ();
  -  use Apache::Status ();
  -  use Apache::DBI ();
  +<PRE>  % rpm -bp /usr/src/redhat/SPECS/mod_perl-x.xx-x.spec
   </PRE>
  +<P><LI>
   <P>
  -If you don't put <CODE>Apache::Status</CODE> before <CODE>Apache::DBI</CODE> then you don't get <CODE>Apache::DBI</CODE>'s menu entry in status.
  +Copy the necessary source files to the proper destination by issuing the
  +following commands:
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Usage">Usage</A></H3></CENTER>
   <P>
  -Assuming that your mod_perl server listens to port 81, fetch <A
  -HREF="http://www.nowhere.com:81/perl-status">http://www.nowhere.com:81/perl-status</A>
  -
  -
  +<PRE>  % mkdir /usr/include/apache 
  +</PRE>
   <P>
  -<PRE>  Embedded Perl version 5.00502 for Apache/1.3.2 (Unix) mod_perl/1.16 
  -  process 187138, running since Thu Nov 19 09:50:33 1998
  +<PRE>  % cp `find /usr/src/redhat/BUILD/mod_perl-1.19 -name '*.h'` \
  +    /usr/include/apache
   </PRE>
  +<P><LI>
   <P>
  -This is the linked menu that you should see:
  +Download the current libapreq module from
  +<CODE>CPAN/modules/by-module/Apache/DOUGM/libapreq-x.xx.tar.gz</CODE>, and unwrap it.
   
  -<P>
  -<PRE>  Signal Handlers
  -  Enabled mod_perl Hooks
  -  PerlRequire'd Files
  -  Environment
  -  Perl Section Configuration
  -  Loaded Modules
  -  Perl Configuration
  -  ISA Tree
  -  Inheritance Tree
  -  Compiled Registry Scripts
  -  Symbol Table Dump
  -</PRE>
  +<P><LI>
   <P>
  -Let's follow for example : <STRONG>PerlRequire'd Files</STRONG> -- we see:
  +Make the following changes to the <CODE>Makefile.PL</CODE> in the <CODE>Cookie</CODE>,
  +<CODE>Request</CODE>, and <CODE>c</CODE> directories of <CODE>libapreq-x.xx</CODE>. Change: 
   
   <P>
  -<PRE>  PerlRequire                          Location
  -  /usr/myproject/lib/apache-startup.pl /usr/myproject/lib/apache-startup.pl
  +<PRE>  'INC' = &quot;-I../c &quot;. $src-&gt;inc,
   </PRE>
   <P>
  -From some menus you can continue deeper to peek at the perl internals of
  -the server, to watch the values of the global variables in the packages, to
  -the list of cached scripts and modules and much more. Just click around...
  +To:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A></H3></CENTER>
  +<PRE>  'INC' = &quot;-I../c -I/usr/include/apache&quot;,
  +</PRE>
  +<P><LI>
   <P>
  -Sometimes when you fetch <CODE>/perl-status</CODE> you and follow the <STRONG>Compiled
  -Registry Scripts</STRONG> link from the status menu -- you see no listing of scripts at all. This is
  -absolutely correct -- <CODE>Apache::Status</CODE> shows the registry scripts compiled in the httpd child which is serving
  -your request for <CODE>/perl-status</CODE>. If a child has not compiled yet the script you are asking for, <CODE>/perl-status</CODE> will just show you the main menu. This usually happens when the child was
  -just spawned.
  +Add the following line to the <CODE>Makefile.PL</CODE> in the <CODE>libapreq-x.xx</CODE>
  +directory. Add:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A></H2></CENTER>
  -<P>
  -<PRE>  PerlSetEnv key val
  -  PerlPassEnv key
  +<PRE>  'INC' = &quot;-I../c -I/usr/include/apache&quot;,
   </PRE>
   <P>
  -<CODE>PerlPassEnv</CODE> passes, <CODE>PerlSetEnv</CODE> sets and passes the
  -<EM>ENVironment</EM> variables to your scripts. you can access them in your scripts through <CODE>%ENV</CODE> (e.g. <CODE>$ENV{&quot;key&quot;}</CODE>).
  +Under:
   
   <P>
  -Regarding the setting of <CODE>PerlPassEnv PERL5LIB</CODE> in httpd.conf If you turn on taint checks (<CODE>PerlTaintMode On</CODE>), <CODE>$ENV{PERL5LIB}</CODE> will be ignored (unset).
  -
  +<PRE>  'DIR' = [qw(c Request Cookie)],
  +</PRE>
  +<P><LI>
   <P>
  -<CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In &lt;Perl&gt; sections:
  +Run:
   
   <P>
  -<PRE>  push @{ $Location{&quot;/&quot;}-&gt;{PerlSetVar} }, [ 'FOO' =&gt; BAR ];
  +<PRE>  % perl Makefile.PL
  +  % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -and in the code you read it with:
  +and you should be off and running.
   
  -<P>
  -<PRE>  my $r = Apache-&gt;request;
  -  print $r-&gt;dir_config('FOO');
  -</PRE>
  +</OL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="perl_startup_file">perl-startup file</A></H2></CENTER>
  +<CENTER><H2><A NAME="Installing_separate_Apache_and_m">Installing separate Apache and mod_perl RPMs</A></H2></CENTER>
   <P>
  -Since many times you have to add many perl directives to the configuration
  -file, it can be a good idea to put all of these into a one file, so the
  -configuration file will be cleaner. Add the following line to <CODE>httpd.conf</CODE>:
  +If you are trying to install separate Apache and mod_perl RPMs, like those
  +provided by RedHat distributions, you may be in for a bit of a surprise.
  +Installing the Apache RPM will go just fine, and <A
  +HREF="http://localhost">http://localhost</A> will bring up some type of web
  +page for your viewing pleasure. However, installation of the mod_perl RPM,
  +followed by the
  +<A HREF="././install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is  running</A>
  +tests, will show that Apache is not mod_perl enabled. This is because
  +mod_perl needs to be added as a separate module using Apache's Dynamic
  +Shared Objects.
   
   <P>
  -<PRE>    # startup.perl loads all functions that we want to use within
  -    # mod_perl
  -  Perlrequire /path/to/startup.pl
  +To use mod_perl as a DSO, make the following modifications to your Apache
  +configuration files:
  +
  +<P>
  +<PRE>  httpd.conf:
  +  ----------
  +  LoadModule perl_module modules/libperl.so
  +  AddModule mod_perl.c
   </PRE>
   <P>
  -before the rest of the mod_perl configuration directives.
  -
  +<PRE>  srm.conf (or httpd.conf in later versions of Apache):
  +  ----------
  +  PerlModule Apache::Registry 
  +  Alias /perl/ /home/httpd/perl/ 
  +  &lt;Location /perl 
  +    SetHandler perl-script 
  +    PerlHandler Apache::Registry 
  +    PerlSendHeader On 
  +    Options +ExecCGI
  +  &lt;/Location
  +</PRE>
   <P>
  -Also you can call <CODE>perl -c perl-startup</CODE> to test the file's syntax. What does this take?
  +After a complete shutdown and startup of the server, mod_perl should be up
  +and running.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Sample_perl_startup_file">Sample perl-startup file</A></H3></CENTER>
  +<CENTER><H2><A NAME="Testing_the_mod_perl_API">Testing the mod_perl API</A></H2></CENTER>
   <P>
  -An example of perl-startup file:
  +Some people have reported that even when the server responds positively to
  +the <A HREF="././install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is  running</A>
  +tests, the mod_perl API will not function properly. You may want to run the
  +below script to verify the availability of the mod_perl API.
   
   <P>
  -<PRE>  use strict;
  -  
  -  # extend @INC if needed
  -  use lib qw(/dir/foo /dir/bar);
  -  
  -  # make sure we are in a sane environment.
  -  $ENV{GATEWAY_INTERFACE} =~ /^CGI-Perl/
  -     or die &quot;GATEWAY_INTERFACE not Perl!&quot;;
  -   
  -  # for things in the &quot;/perl&quot; URL
  -  use Apache::Registry;          
  -   
  -  #load perl modules of your choice here
  -  #this code is interpreted *once* when the server starts
  -  use LWP::UserAgent ();
  -  use DBI ();
  -  
  -  # tell me more about warnings
  -  use Carp ();
  -  $SIG{__WARN__} = \&amp;Carp::cluck;
  -  
  -  # Load CGI.pm and call its compile() method to precompile 
  -  # (but not to import) its autoloaded methods. 
  -  use CGI ();
  -  CGI-&gt;compile(':all');
  +<PRE>        use strict;
  +        my $r = shift;
  +        $r-&gt;send_http_header('text/html');
  +        $r-&gt;print(&quot;It worked!!!\n&quot;);
   </PRE>
  -<P>
  -Note that starting with <CODE>$CGI::VERSION</CODE> 2.46, the recommended method to precompile the code in <CODE>CGI.pm</CODE> is:
  -
   <P>
  -<PRE>  use CGI qw(-compile :all);
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Automating_installation">Automating installation</A></H1></CENTER>
   <P>
  -But the old method is still available for backward compatibility.
  +James G Smith wrote an Apache Builder 
   
   <P>
  -See also <A HREF="././status.html#Configuration">Apache::Status</A>
  +<A
  +HREF="http://hex.tamu.edu/projects/1999/build-apache/">http://hex.tamu.edu/projects/1999/build-apache/</A>
   
   
  +<P>
  +(META: provide more info)
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A></H3></CENTER>
  +<CENTER><H1><A NAME="How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A></H1></CENTER>
   <P>
  -Modules that are being loaded at the server startup will be shared among
  -server children, so only one copy of each module will be loaded, thus
  -saving a lot of RAM for you. Usually I put most of the code I develop into
  -modules and preload them from here. You can even preload your CGI script
  -with <CODE>Apache::RegistryLoader</CODE> and preopen the DB connections with <CODE>Apache::DBI</CODE>. (See <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>).
  +There are a few ways. In older versions of apache ( &lt; 1.3.6 ?) you could check that by running <CODE>httpd -v</CODE>, it no longer works. Now you should use <CODE>httpd -l</CODE>. Please notice that it is not enough to have it installed - you should of
  +course configure it for mod_perl and restart the server.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A></H3></CENTER>
  +<CENTER><H2><A NAME="Testing_by_checking_the_error_lo">Testing by checking the error_log file</A></H2></CENTER>
   <P>
  -Many people wonder, why there is a need for duplication of <CODE>use()</CODE>
  -clause both in startup file and in the script itself. The question rises
  -from misunderstanding of the <CODE>use()</CODE> operand. <CODE>use()</CODE> consists of two other operands, namely <CODE>require()</CODE> and <CODE>import()</CODE>. So when you write:
  +When starting the server, just check the <CODE>error_log</CODE> file for the following message:
   
   <P>
  -<PRE>  use Foo qw(bar);
  +<PRE>  [Thu Dec  3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured 
  +                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  +    -- resuming normal operations
   </PRE>
  -<P>
  -perl actually does:
  -
   <P>
  -<PRE>  require Foo.pm;
  -  import qw(bar);
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Testing_by_viewing_perl_status">Testing by viewing /perl-status</A></H2></CENTER>
   <P>
  -When you write:
  +Assuming that you have configured the <CODE>&lt;Location /perl-status</CODE>&gt; section in the server configuration file fetch: <A
  +HREF="http://www.nowhere.com/perl-status">http://www.nowhere.com/perl-status</A>
  +using your favorite Netscape browser :-)
   
  -<P>
  -<PRE>  use Foo qw();
  -</PRE>
   <P>
  -perl actually does:
  +You should see something like this:
   
   <P>
  -<PRE>  require Foo.pm;
  -  import qw();
  +<PRE>  Embedded Perl version 5.00502 for Apache/1.3.1 (Unix) mod_perl/1.19 
  +  process 50880, running since Tue Oct 6 14:31:45 1998
   </PRE>
   <P>
  -which means that the caller does not want any symbols to be imported. Why
  -is this important? Since some modules has <CODE>@EXPORT</CODE> set to a list of tags to be exported by default and when you write:
  -
  -<P>
  -<PRE>  use Foo;
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Testing_via_telnet">Testing via telnet</A></H2></CENTER>
   <P>
  -and think nothing is being imported, the <CODE>import()</CODE> call is being executed and probably some symbols do being imported. See the
  -docs/source of the module in question to make sure you <CODE>use()</CODE> it correctly. When you write your own modules, always remember that it's
  -better to use <CODE>@EXPORT_OK</CODE> instead of <CODE>@EXPORT</CODE>, since the former doesn't export tags unless it was asked to.
  +Knowing the port you have configured apache to listen on, you can use
  +<CODE>telnet</CODE> to talk directly to it.
   
   <P>
  -Since the symbols that you might import into a startup's script namespace
  -will be visible by none of the children, scripts that need a
  -<CODE>Foo</CODE>'s module exported tags have to pull it in like if you did not preload <CODE>Foo</CODE> at the startup file. For example, just because you have
  -<CODE>use()d</CODE>  <CODE>Apache::Constants</CODE> in the startup script, does not mean you can have the following handler:
  +Assuming that your mod_perl enabled server listens to port 8080, telnet to
  +your server at port 8080, and type <CODE>HEAD / HTTP/1.0</CODE> then press the &lt;ENTER&gt; key TWICE:
   
  -<P>
  -<PRE>  package MyModule;
  -  
  -  sub {
  -    my $r = shift;
  -  
  -    ## Cool stuff goes here
  -  
  -    return OK;
  -  }
  -</PRE>
   <P>
  -<PRE>  1;
  +<PRE>  % telnet localhost 8080&lt;ENTER&gt;
  +  HEAD / HTTP/1.0&lt;ENTER&gt;&lt;ENTER&gt;
   </PRE>
   <P>
  -You would either need to add:
  +You should see a response like this:
   
   <P>
  -<PRE>  use Apache::Constants qw( OK );
  +<PRE>  HTTP/1.1 200 OK
  +  Date: Tue, 01 Dec 1998 12:27:52 GMT
  +  Server: Apache/1.3.6 (Unix) mod_perl/1.19
  +  Connection: close
  +  Content-Type: text/html
  +  
  +  Connection closed.
   </PRE>
   <P>
  -Or instead of <CODE>return OK;</CODE> say:
  +The line: <CODE>Server: Apache/1.3.6 (Unix) mod_perl/1.19</CODE> --confirms that you <STRONG>do</STRONG> have mod_perl installed and its version is <CODE>1.19</CODE>. Of course in your case it would be the version you have installed.
   
  -<P>
  -<PRE>  return Apache::Constants::OK;
  -</PRE>
   <P>
  -See the manpage/perldoc on <CODE>Exporter</CODE> and <CODE>perlmod</CODE> for more on
  -<CODE>import()</CODE>.
  +However, just because you have got mod_perl linked in there, that does not
  +mean that you have configured your server to handle Perl scripts with
  +mod_perl. You will find the configuration assistance at
  +<A HREF="././config.html#">ModPerlConfiguration</A>
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="The_confusion_with_defining_glob">The confusion with defining globals in startup</A></H3></CENTER>
  -<P>
  -<CODE>PerlRequire</CODE> allows you to execute code that preloads modules and does more things.
  -Imported or defined variables are visible in the scope of the startup file.
  -It is a wrong assumption that global variables that were defined in the
  -startup file, will be accessible by child processes.
   
  -<P>
  -You do have to define/import variables in your scripts and they will be
  -visible inside a child process who run this script. They will be not shared
  -between siblings. Remember that every script is running in a specially
  -(uniquely) named package - so it cannot access variables from other
  -packages unless it inherits from them or <CODE>use()</CODE>'s them.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Running_apachectl_configtest_o">Running 'apachectl configtest' or 'httpd -t'</A></H1></CENTER>
  -<P>
  -<CODE>apachectl configtest</CODE> tests the configuration file without starting the server. You can safely
  -modify the configuration file on your production server, if you run this
  -test before you restart the server. Of course it is not 100% error prone,
  -but it will reveal any syntax errors you might do while editing the file.
  -
  +<CENTER><H2><A NAME="Testing_via_a_CGI_script">Testing via a CGI script</A></H2></CENTER>
   <P>
  -'<CODE>apachectl configtest</CODE>' is the same as '<CODE>httpd -t</CODE>' and it actually executes the code in startup.pl, not just parses it. <CODE>&lt;Perl</CODE>&gt; configuration has always started Perl during the configuration read,
  -<CODE>Perl{Require,Module}</CODE> do so as well.
  +Another method is to invoke a CGI script which dumps the server's
  +environment.
   
   <P>
  -If you want your startup code to get a control over the <CODE>-t</CODE>
  -(<CODE>configtest</CODE>) server launch, start the server configuration test with:
  +Copy and paste the script below (no need for the first perl calling
  +(shebang) line!). Let's say you named it <CODE>test.pl</CODE>, saved it at the root of the CGI scripts and CGI root is mapped directly
  +to the
  +<CODE>/perl</CODE> location of your server.
   
   <P>
  -<PRE>  httpd -t -Dsyntax_check
  +<PRE>  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;Server's environment&lt;P&gt;\n&quot;;
  +  print &quot;&lt;TABLE&gt;&quot;;
  +  foreach ( keys %ENV ) {
  +      print &quot;&lt;TR&gt;&lt;TD&gt;$_ &lt;/TD&gt;&lt;TD&gt;$ENV{$_}&lt;/TR&gt;&lt;/TD&gt;&quot;;
  +  }
  +  print &quot;&lt;/TABLE&gt;&quot;;
   </PRE>
   <P>
  -and in your startup file, add (at the top):
  +Make it readable and executable by server:
   
   <P>
  -<PRE>  return if Apache-&gt;define('syntax_check');
  +<PRE>  % chmod a+rx test.pl
   </PRE>
   <P>
  -if you want to prevent the code in the file from being executed.
  +(you will want to tune permissions on the public host).
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Perl_behavior_controls">Perl behavior controls</A></H1></CENTER>
  -<P>
  -For <STRONG>PerlWarn</STRONG> and <STRONG>PerlTaintCheck</STRONG> see <A HREF="././porting.html#Switches_w_T">Switches -w, -T</A>
  -
  -
  +Now fetch the URL <CODE>http://www.nowhere.com:8080/perl/test.pl</CODE> (replace 8080 with the port your mod_perl enabled server is listening to.
  +You should see something like this (the generated output was trimmed):
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Tuning_MinSpareServers_MaxSpareS">Tuning MinSpareServers MaxSpareServers StartServers MaxClients
  -MaxRequestsPerChild</A></H1></CENTER>
  +<PRE>  SERVER_SOFTWARE    Apache/1.3.6 (Unix) mod_perl/1.19
  +  GATEWAY_INTERFACE  CGI-Perl/1.1
  +  REQUEST_METHOD     GET
  +  HTTP_ACCEPT        image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
  +  MOD_PERL           1.19
  +  REQUEST_URI        /perl/test.pl
  +  SCRIPT_NAME        /perl/test.pl
  +  [...snipped]
  +</PRE>
   <P>
  -See <A HREF="././performance.html#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  -
  -
  +Now if I run the same script in mod_cgi mode (configured with
  +<CODE>/cgi-bin</CODE> Alias) (you will need to add the perl invocation line
  +<CODE>#!/bin/perl</CODE> for the above script) and fetch
  +<CODE>http://www.nowhere.com/cgi-bin/test.pl</CODE>.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Publishing_port_numbers_differen">Publishing port numbers different from 80</A></H1></CENTER>
  +<PRE>  SERVER_SOFTWARE   Apache/1.3.6 (Unix)
  +  GATEWAY_INTERFACE CGI/1.1
  +  [...snipped]
  +</PRE>
   <P>
  -It is advised not to publish the 8080 (or alike) port number in URLs, but
  -rather using a proxying rewrite rule in the thin (httpd_docs) server:
  +You will see that two variables, <CODE>SERVER_SOFTWARE</CODE> and
  +<CODE>GATEWAY_INTERFACE</CODE>, are different from the case above. This gives you a hint of how to tell
  +in what mode you are running in your cgi scripts. I start all my cgi
  +scripts that are mod_perl aware with:
   
   <P>
  -<PRE>  RewriteRule .*/perl/(.*) <A HREF="http://my.url:8080/perl/">http://my.url:8080/perl/</A>$1 [P]
  +<PRE>  BEGIN {
  +      # Auto-detect if we are running under mod_perl or CGI.
  +    $USE_MOD_PERL = ((exists $ENV{'GATEWAY_INTERFACE'}
  +                  and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/)
  +                   or exists $ENV{'MOD_PERL'} );
  +      # perl5.004 is a must under mod_perl
  +    require 5.004 if $USE_MOD_PERL;
  +  }
   </PRE>
   <P>
  -One problem with publishing 8080 port numbers is that I was told that IE
  -4.x has a bug when re-posting data to a non-port-80 url. It drops the port
  -designator, and uses port 80 anyway.
  +You might wonder why in the world you would need to know in what mode you
  +are running. For example you will want to use <CODE>Apache::exit()</CODE>
  +and not <CODE>CORE::exit()</CODE> in your modules, but if you think that your script might be used in both
  +environments (mod_cgi vs. mod_perl), you will have to override the <CODE>exit()</CODE> subroutine and to make the runtime decision of what method you will use.
  +Not that if you run scripts under <CODE>Apache::Registry</CODE> handler, it takes care of overriding the
  +<CODE>exit()</CODE> call for you, so it's not an issue if this is your case. For reasons and
  +implementations see: <A HREF="././porting.html#Using_exit_">Using exit()</A> and the whole <A HREF="././porting.html#">Writing Mod Perl scripts and Porting plain CGIs to it</A> page.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Perl_Sections">Perl Sections</A></H1></CENTER>
  +<CENTER><H2><A NAME="Testing_via_lwp_request">Testing via lwp-request</A></H2></CENTER>
   <P>
  -With <CODE>&amp;lt;Perl&amp;gt;&amp;lt;/Perl&amp;gt;</CODE> sections, it is possible to configure your server entirely in Perl.
  +Yet another one. Why do I show all these approaches? While here they are
  +serving a very simple purpose, they can be helpful in other situations.
   
   <P>
  -<STRONG>&lt;Perl&gt;</STRONG> sections can contain *any* and as much Perl code as you wish. These
  -sections are compiled into a special package whose symbol table mod_perl
  -can then walk and grind the names and values of Perl variables/structures
  -through the apache core configuration gears. Most of the configurations
  -directives can be represented as scalars (<STRONG>$scalar</STRONG>) or lists (<STRONG>@list</STRONG>). An <CODE>@List</CODE> inside these sections is simply converted into a space delimited string for
  -you inside. Here is an example:
  +Assuming you have the <CODE>libwww-perl</CODE> (<CODE>LWP</CODE>) package installed (you will need it installed in order to pass mod_perl's <CODE>make test</CODE> anyway):
   
   <P>
  -<PRE>  #httpd.conf
  -  &lt;Perl&gt;
  -  @PerlModule = qw(Mail::Send Devel::Peek);
  - 
  -  #run the server as whoever starts it
  -  $User  = getpwuid($&gt;) || $&gt;;
  -  $Group = getgrgid($)) || $); 
  - 
  -  $ServerAdmin = $User;
  - 
  -  &lt;/Perl&gt;
  +<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A>
   </PRE>
   <P>
  -Block sections such as <CODE>&lt;Location</CODE>..&lt;/Location&gt;&gt; are represented in a
  -<CODE>%Location</CODE> hash, e.g.:
  +Will show you all the headers. (The <CODE>-d</CODE> option disables printing the response content.)
   
   <P>
  -<PRE>  $Location{&quot;/~dougm/&quot;} = {
  -    AuthUserFile =&gt; '/tmp/htpasswd',
  -    AuthType =&gt; 'Basic',
  -    AuthName =&gt; 'test',
  -    DirectoryIndex =&gt; [qw(index.html index.htm)],  
  -    Limit =&gt; {
  -    METHODS =&gt; 'GET POST',
  -    require =&gt; 'user dougm',
  -    },
  -  };
  +<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A> | egrep '^Server:'
   </PRE>
   <P>
  -If a Directive can take two *or* three arguments you may push strings and
  -the lowest number of arguments will be shifted off the <CODE>@List</CODE> or use array reference to handle any number greater than the minimum for
  -that directive:
  +To see the server's version only.
   
   <P>
  -<PRE>  push @Redirect, &quot;/foo&quot;, &quot;<A HREF="http://www.foo.com/&quot">http://www.foo.com/&quot</A>;;
  -  
  -  push @Redirect, &quot;/imdb&quot;, &quot;<A HREF="http://www.imdb.com/&quot">http://www.imdb.com/&quot</A>;;
  -  
  -  push @Redirect, [qw(temp &quot;/here&quot; &quot;<A HREF="http://www.there.com&quot">http://www.there.com&quot</A>;)];
  -</PRE>
  -<P>
  -Other section counterparts include <CODE>%VirtualHost</CODE>, <CODE>%Directory</CODE> and
  -<CODE>%Files</CODE>.
  +Use <CODE>http://www.nowhere.com:port_number</CODE> if your server is listening to a non-default 80 port.
   
   <P>
  -To pass all environment variables to the children with a single
  -configuration directive, rather than listing each one via PassEnv or
  -PerlPassEnv, a <STRONG>&lt;Perl&gt;</STRONG> section could read in a file and:
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Is_it_possible_to_install_and_us">Is it possible to install and use apache/mod_perl without having a root access?</A></H1></CENTER>
   <P>
  -<PRE>  push @PerlPassEnv, [$key =&gt; $val];
  -</PRE>
  +Yes, no problem with that. Follow the installation instructions and when
  +you encounter <CODE>APACI_ARGS</CODE> use your home directory (or some other directory which you have write
  +access to) as a prefix, (e.g. <CODE>/home/stas/www</CODE>), and everything will be installed there. There is a chance that some perl
  +libs will be not installed on your server by root and you will have to
  +install these locally too. See the <A
  +HREF="http://www.singlesheaven.com/stas/TULARC/webmaster/myfaq.html#7">http://www.singlesheaven.com/stas/TULARC/webmaster/myfaq.html#7</A>
  +for more information on local perl installations.
  +
   <P>
  -or
  +So you end up with something like:
   
   <P>
  -<PRE>  Apache-&gt;httpd_conf(&quot;PerlPassEnv $key $val&quot;);
  +<PRE>  $ gunzip &lt;apache_x.x.xx.tar.gz | tar xvf -
  +  $ gunzip &lt;mod_perl-x.xx.tar.gz | tar xvf -
  +  $ cd mod_perl-x.xx
  +  $ perl Makefile.PL \
  +      APACHE_SRC=../apache-1.3.X/src \
  +      DO_HTTPD=1 \
  +      USE_APACI=1 \
  +      EVERYTHING=1 \
  +      APACI_ARGS=--sbindir=/home/stas/sbin/httpd_perl, \
  +           --sysconfdir=/home/stas/etc/httpd_perl, \
  +           --localstatedir=/home/stas/var/httpd_perl, \
  +           --runtimedir=/home/stas/var/httpd_perl/run, \
  +           --logfiledir=/home/stas/var/httpd_perl/logs, \
  +           --proxycachedir=/home/stas/var/httpd_perl/proxy
   </PRE>
   <P>
  -These are somewhat simple examples, but they should give you the basic
  -idea. You can mix in any Perl code your heart desires. See
  -<CODE>eg/httpd.conf.pl</CODE> and <CODE>eg/perl_sections.txt</CODE> in mod_perl distribution for some examples.
  +You will not be able to have the server listen to a port lower then 1024 if
  +you are not starting it as <CODE>root</CODE>, so choose a port number above 1024. (I use 8080 in most cases). Note that
  +you will have to use a URL like <CODE>http://www.nowhere.com:8080</CODE> in that case, but that is not a problem since usually users do not directly
  +access URLs to CGI scripts, but rather are directed to them from a link on
  +a web page or as the '<CODE>ACTION</CODE>' of a HTML form, so they should not know at all that the port is different
  +from the default port 80.
   
   <P>
  -A tip for syntax checking outside of httpd:
  +If you want your apache server to start automatically on system reboot, you
  +will need to invoke the server startup script from somewhere within the
  +init scripts on your host. This is often somewhere under <CODE>/etc/rc.d</CODE>, but this path can vary depending upon the flavor of Unix you are using.
   
   <P>
  -<PRE>  &lt;Perl&gt;
  -  # !perl
  -  
  -  #... code here ...
  -  
  -  __END__
  -  &lt;/Perl&gt;
  -</PRE>
  +One more important thing to keep in mind is system resources. mod_perl is
  +memory hungry -- if you run a lot of mod_perl processes on a public,
  +multiuser (not dedicated) machine -- most likely the system administrator
  +of the host will ask you to use less resources and even to shut down your
  +mod_perl server and to find another home for it. You have a few solutions:
  +
  +<UL>
  +<P><LI>
   <P>
  -Now you may run:
  +Reduce resources usage (see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>).
   
  +<P><LI>
   <P>
  -<PRE>  perl -cx httpd.conf
  +Ask your ISP if you can put a dedicated machine into their computer room
  +and be root there.
  +
  +<P><LI>
  +<P>
  +Look for another ISP with lots of resources or one that supports mod_perl.
  +You can find a list of these ISP at <A
  +HREF="http://perl.apache.org">http://perl.apache.org</A> .
  +
  +</UL>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Is_it_possible_to_tell_whether_s">Is it possible to tell whether some option was included</A></H1></CENTER>
  +<P>
  +Sure, you can take a look at the symbols inside the httpd executable. e.g.
  +if you want to see whether you have enabled PERL_AUTH=1 while building the
  +mod_perl, you do:
  +
  +<P>
  +<PRE>  nm httpd | grep perl_authenticate
   </PRE>
   <P>
  -To enable <CODE>&lt;Perl</CODE>&gt; sections you should build mod_perl with <STRONG>perl
  -Makefile.PL PERL_SECTIONS=1</STRONG>.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Is_it_possible_to_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A></H1></CENTER>
  +<P>
  +It is possible to determine which options were given to modperl's
  +<CODE>Makefile.PL</CODE> during the configuration stage, so to be used later in recreating the same
  +build tree when rebuilding the server. This is relevant only if you did not
  +use the default config parameters and altered some of them during the
  +configuration stage.
   
   <P>
  -You can watch how have you configured the <CODE>&lt;Perl</CODE>&gt; sections through the <A HREF="././config.html#_perl_status_location">/perl-status</A> location, by choosing the <STRONG>Perl Sections</STRONG> from the menu.
  +I was into this problem many times. I am going to build something by
  +passing some non-default parameters to the config script and then later
  +when I need to rebuild the tool either to upgrade it or to make an
  +identical copy at another machine, I would find that I do not remember what
  +parameters I altered.
   
   <P>
  -You can dump the configuration by <CODE>&lt;Perl</CODE>&gt; sections configuration this way:
  +The best solution for this problem is to prepare the run file with all the
  +parameters that are about to be used and then run it instead of typing it
  +all by hand. So later I will have the script handy to be reused.
   
   <P>
  -<PRE>  &lt;Perl&gt;
  -  use Apache::PerlSections();
  -  ...
  -  print STDERR Apache-&gt;PerlSections-&gt;dump();
  -  &lt;/Perl&gt;
  -</PRE>
  +mod_perl suggests using the <CODE>makepl_args.mod_perl</CODE> file which comes with mod_perl distribution. This is the file where you
  +should specify all the parameters you are going to use.
  +
   <P>
  -Alternatively you can store it in a file:
  +But if you have found yourself with a compiled tool and no traces of the
  +specified parameters left, usually you can still find them out, if the
  +sources were not <CODE>make clean</CODE>'d. You will find the apache specific parameters in <CODE>apache_x.x.x/config.status</CODE> and modperl's at in <CODE>mod_perl_x.xx/apaci/mod_perl.config</CODE>.
   
   <P>
  -<PRE>  Apache::PerlSections-&gt;store(&quot;httpd_config.pl&quot;);
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Installation_problems">Installation problems</A></H1></CENTER>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="make_problems">make problems</A></H2></CENTER>
  +<P>
  +<PRE>  undefined reference to 'Perl_newAV'
   </PRE>
   <P>
  -You can then <CODE>require()</CODE> that file in some other <CODE>&lt;Perl</CODE>&gt; section.
  +This and similar error messages show up during <CODE>make</CODE> process. Generally happens when you have a broken Perl installation. Make
  +sure it's not installed from a broken RPM or another binary package, if it
  +is -- build Perl from source or use another properly built binary package.
  +Run <CODE>perl -V</CODE> to learn what version of Perl you are using and other important details.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A></H1></CENTER>
  +<CENTER><H2><A NAME="make_test_skipping_test_on_">make test......skipping test on this platform</A></H2></CENTER>
   <P>
  -mod_macro is an Apache module written by Fabien Coelho that lets you define
  -and use macros in the Apache configuration file.
  +While doing <CODE>make test</CODE> you would notice that some of the tests are being reported as skipped. The
  +real reason is that you are missing some optional modules for these test to
  +be passed. For a hint you might want to peek at the content of each test
  +(you will find them all in the <CODE>./t</CODE> directory (mnemonic - t, tests). I'll list a few examples, but of course
  +the requirements might be changed in the future.
   
   <P>
  -mod_macro proved really useful when you have many virtual hosts, each
  -virtual host has a number of scripts/modules, most of them with a
  -moderately complex configuration setup.
  +&gt; modules/cookie......skipping test on this platform
   
   <P>
  -First download the latest version of mod_macro from <A
  -HREF="http://www.cri.ensmp.fr/~coelho/mod_macro/">http://www.cri.ensmp.fr/~coelho/mod_macro/</A>
  -, and configure your Apache server to use this module.
  +install libapreq
   
   <P>
  -Here are some useful macros for mod_perl users:
  +&gt; modules/psections...skipping test on this platform
   
   <P>
  -<PRE>        # set up a registry script
  -        &lt;Macro registry&gt;
  -        SetHandler &quot;perl-script&quot;
  -        PerlHandler Apache::Registry
  -        Options +ExecCGI
  -        &lt;/Macro&gt;
  -</PRE>
  +install Devel::Symdump / Data::Dumper
  +
   <P>
  -<PRE>        # example
  -        Alias /stuff /usr/www/scripts/stuff
  -        &lt;Location /stuff&gt;
  -        Use registry
  -        &lt;/Location&gt;
  -</PRE>
  +&gt; modules/request.....skipping test on this platform
  +
   <P>
  -If your registry scripts are all located in the same directory, and your
  -aliasing rules consistent, you can use this macro:
  +libapreq
   
   <P>
  -<PRE>        # set up a registry script for a specific location
  -        &lt;Macro registry $location $script&gt;
  -        Alias /script /usr/www/scripts/$script
  -        &lt;Location $location&gt;
  -        SetHandler &quot;perl-script&quot;
  -        PerlHandler Apache::Registry
  -        Options +ExecCGI
  -        &lt;/Location&gt;
  -        &lt;/Macro&gt;
  -</PRE>
  +&gt; modules/sandwich....skipping test on this platform
  +
   <P>
  -<PRE>        # example
  -        Use registry stuff stuff.pl
  -</PRE>
  +Apache::Sandwich
  +
   <P>
  -If you're using content handlers packaged as modules, you can use the
  -following macro:
  +&gt; modules/stage.......skipping test on this platform
   
   <P>
  -<PRE>        # set up a mod_perl content handler module
  -        &lt;Macro modperl $module&gt;
  -        SetHandler &quot;perl-script&quot;
  -        Options +ExecCGI
  -        PerlHandler $module
  -        &lt;/Macro&gt;
  -</PRE>
  +Apache::Stage
  +
   <P>
  -<PRE>        #examples
  -        &lt;Location /perl-status&gt;
  -        PerlSetVar StatusPeek On
  -        PerlSetVar StatusGraph On
  -        PerlSetVar StatusDumper On
  -        Use modperl Apache::Status
  -        &lt;/Location&gt;
  -</PRE>
  +&gt; modules/symbol......skipping test on this platform
  +
   <P>
  -The following macro sets up a Location for use with HTML::Embperl. Here we
  -define all ``.html'' files to be processed by Embperl.
  +Devel::Symdump
   
   <P>
  -<PRE>        &lt;Macro embperl&gt;
  -        SetHandler &quot;perl-script&quot;
  -        Options +ExecCGI
  -        PerlHandler HTML::Embperl
  -        PerlSetEnv EMBPERL_FILESMATCH \.html$
  -        &lt;/Macro&gt;
  -</PRE>
  +Chances are that all of these are installed if you use <CODE>CPAN.pm</CODE> to
  +<CODE>install Bundle::Apache</CODE>.
  +
   <P>
  -<PRE>        # examples
  -        &lt;Location /mrtg&gt;
  -        Use embperl
  -        &lt;/Location&gt;
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="make_test_fails">make test fails</A></H2></CENTER>
   <P>
  -Macros are also very useful for things that tend to be verbose, such as
  -setting up Basic Authentication:
  +There are two configuration parameters: <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>, that you can use in:
   
  -<P>
  -<PRE>        # Sets up Basic Authentication
  -        &lt;Macro BasicAuth $realm $group&gt;
  -        Order deny,allow
  -        Satisfy any
  -        AuthType Basic
  -        AuthName $realm
  -        AuthGroupFile /usr/www/auth/groups
  -        AuthUserFile /usr/www/auth/users
  -        Require group $group
  -        Deny from all
  -        &lt;/Macro&gt;
  -</PRE>
   <P>
  -<PRE>        # example of use
  -        &lt;Location /stats&gt;
  -        Use BasicAuth WebStats Admin
  -        &lt;/Location&gt;
  +<PRE>  perl Makefile.PL [options]
   </PRE>
   <P>
  -Finally, here is a complete example that uses macros to set up simple
  -virtual hosts. It uses the BasicAuth macro defined previously (yes, macros
  -can be nested!).
  +<CODE>DO_HTTPD=1</CODE> means default to '<CODE>y</CODE>' for the two apache's
  +<CODE>configure</CODE> utility prompts: (a) 'which source tree to configure against' and (b)
  +'whether to build the httpd in that tree'. <CODE>PREP_HTTPD=1</CODE> just means default '<CODE>n</CODE>' to the second prompt -- meaning, <EM>do not build httpd (make) in the
  +apache source tree</EM>. In other words if you use <CODE>PREP_HTTPD=1</CODE> the httpd will be not build. It will be build only if you use
  +<CODE>DO_HTTPD=1</CODE> option and not use <CODE>PREP_HTTPD=1</CODE>.
   
   <P>
  -<PRE>        &lt;Macro vhost $ip $domain $docroot $admingroup&gt;
  -        &lt;VirtualHost $ip&gt;
  -        ServerAdmin webmaster@$domain
  -        DocumentRoot /usr/www/htdocs/$docroot
  -        ServerName www.$domain
  -        &lt;Location /stats&gt;
  -        Use BasicAuth Stats-$domain $admingroup
  -        &lt;/Location&gt;
  -        &lt;/VirtualHost&gt;
  -        &lt;/Macro&gt;
  -</PRE>
  +If you did not build the httpd, chdir to the apache source, and execute:
  +
   <P>
  -<PRE>        # define some virtual hosts
  -        Use vhost 10.1.1.1 example.com example example-admin
  -        Use vhost 10.1.1.2 example.net examplenet examplenet-admin
  +<PRE>  make
   </PRE>
   <P>
  -mod_macro also useful in a non vhost setting. Some sites for example have
  -lots of scripts where people use to view various statistics, email settings
  -and etc. It is much easier to read things like:
  +Then return to the mod_perl source and run:
   
   <P>
  -<PRE>  use /forwards email/showforwards
  -  use /webstats web/showstats
  +<PRE>  make test
  +  make install
   </PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="General_pitfalls">General pitfalls</A></H1></CENTER>
  +Note that you would have to do the same if you do not pass
  +<CODE>APACHE_PREFIX=/path_to_installation_prefix</CODE> during the <CODE>perl
  +Makefile.PL [options]</CODE> stage.
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="My_cgi_perl_code_is_being_return">My cgi/perl code is being returned as a plain text instead of being executed by the webserver?</A></H2></CENTER>
  +<CENTER><H2><A NAME="mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A></H2></CENTER>
   <P>
  -Check your configuration files and make sure that the ``ExecCGI'' is turned
  -on in your configurations. 
  +You will see this message when you try to run a httpd, if you have had a
  +stale old apache header layout in one of the <CODE>include</CODE> paths during the build process. Do run <CODE>find</CODE> (or <CODE>locate</CODE>) utility in order to locate <CODE>ap_mmn.h</CODE> file. In my case I have had a
  +<CODE>/usr/local/include/ap_mmn.h</CODE> which was installed by RedHat install process. If this is the case get rid
  +of it, and rebuild it again.
   
   <P>
  -<PRE>  &lt;Location /perl&gt;
  -    SetHandler perl-script
  -    PerlHandler Apache::Registry
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  +For all RedHat fans, before you are going to build the apache by yourself,
  +do:
  +
  +<P>
  +<PRE>  rpm -e apache
   </PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A></H2></CENTER>
  +to remove the pre-installed RPM package first!
  +
   <P>
  -Did you put <STRONG>PerlSendHeader On</STRONG> in the configuration part of the &lt;Location foo&gt;&lt;/Location&gt;?
  -
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A></H2></CENTER>
  +<CENTER><H2><A NAME="Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A></H2></CENTER>
   <P>
  -No. Any virtual host will be able to see the routines from a startup.pl
  -loaded for any other virtual host.  
  +Yes, you should. You have to rebuild mod_perl enabled server since it has a
  +hard coded <CODE>@INC</CODE> which points to the old perl and it is is probably linked to the an old <CODE>libperl</CODE> library. You can try to modify the <CODE>@INC</CODE> in the startup script (if you keep the old perl version around), but it is
  +better to build a fresh one to save you a mess.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A></H2></CENTER>
  -<P>
  -You can use 'PerlSetEnv PERL5LIB ...' or a PerlFixupHandler w/ the lib
  -pragma.
  -
  +<CENTER><H1><A NAME="mod_auth_dbm_nuances">mod_auth_dbm nuances</A></H1></CENTER>
   <P>
  -Even a better way is to use <A HREF="././modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC</A>
  -
  -
  +If you are a user of <STRONG>mod_auth_dbm</STRONG> or <STRONG>mod_auth_db</STRONG>, you may need to edit Perl's <CODE>Config</CODE> module. When Perl is configured it attempts to find libraries for ndbm,
  +gdbm, db, etc., for the *DBM*_File modules. By default, these libraries are
  +linked with Perl and remembered by the <STRONG>Config</STRONG> module. When mod_perl is configured with apache, the <STRONG>ExtUtils::Embed</STRONG> module returns these libraries to be linked with httpd so Perl extensions
  +will work under mod_perl. However, the order in which these libraries are
  +stored in
  +<STRONG>Config.pm</STRONG>, may confuse <CODE>mod_auth_db*</CODE>. If <CODE>mod_auth_db*</CODE> does not work with mod_perl, take a look at this order with the following
  +command:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A></H2></CENTER>
  +<PRE> % perl -V:libs
  +</PRE>
   <P>
  -This has been a bug before, last fixed in 1.15_01, i.e. if you are running
  -1.15, that could be the problem. You should set this variable in a startup
  -file (PerlRequire):
  +If <CODE>-lgdbm</CODE> or <CODE>-ldb</CODE> is before <CODE>-lndbm</CODE>, example:
   
   <P>
  -<PRE>  $Apache::Registry::NameWithVirtualHost = 1;
  +<PRE> libs='-lnet -lnsl_s -lgdbm -lndbm -ldb -ldld -lm -lc -lndir -lcrypt';
   </PRE>
   <P>
  -But, as we know sometimes bug turns into a feature. If there is the same
  -script running for more than one Virtual host on the same machine, this can
  -be a waste, right? Set it to 0 in a startup script if you want to turn it
  -off and have this bug as a feature. (Only makes sense if you are sure that
  -there will be no <STRONG>other</STRONG>scripts named by the same path/name). It also saves you some memory on the
  -way.
  +Edit <STRONG>Config.pm</STRONG> and move <CODE>-lgdbm</CODE> and <CODE>-ldb</CODE> to the end of the list. Here's how to find <STRONG>Config.pm</STRONG>:
   
   <P>
  -<PRE>  $Apache::Registry::NameWithVirtualHost = 0;
  +<PRE> % perl -MConfig -e 'print &quot;$Config{archlibexp}/Config.pm\n&quot;'
   </PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A></H2></CENTER>
   <P>
  -The problem was reported by users who declared mod_perl configuration
  -inside a &lt;Directory&gt; section for all files matching to *.pl. The
  -problem has gone away after placing the usage of mod_perl in a
  -&lt;File&gt;- section.
  +Another solution for building Apache/mod_perl+mod_auth_dbm under Solaris is
  +to remove the DBM and NDBM ``emulation'' from libgdbm.a. Seems Solaris
  +already provides its own DBM and NDBM, and there's no reason to build GDBM
  +with them (for us anyway).
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Configuration_Security_Concerns">Configuration Security Concerns</A></H1></CENTER>
  -<P>
  -It is better not to advertise the port mod_perl server running at to the
  -outside world for it creates a potential security risk by revealing which
  -<CODE>module(s)</CODE> and/or OS you are running your web server on.
  +In our Makefile for GDBM, we changed
   
   <P>
  -The more modules you have in your web server, the more complex the code in
  -your webserver.
  -
  +<PRE>  OBJS = $(DBM_OF) $(NDBM_OF) $(GDBM_OF)
  +</PRE>
   <P>
  -The more complex the code in your web server, the more chances for bugs.
  +to
   
   <P>
  -The more chance for bugs, the more chance that some of those bugs may
  -involve security.
  -
  +<PRE>  OBJS = $(GDBM_OF)
  +</PRE>
   <P>
  -Never was completely sure why the default of the ServerToken directive in
  -Apache is Full rather than Minimal. Seems like you would only make it full
  -if you are debugging.
  +Rebuild libgdbm, then Apache/mod_perl.  
   
   <P>
  -For more information see <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
  -
  -
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A></H1></CENTER>
   <P>
  -Another approach is to modify httpd sources to reveal no unwanted
  -information, so if you know the port the <CODE>HEAD</CODE> request will return an empty or phony <CODE>Server:</CODE> field.
  +Since most of the functionality that various apache mod_* modules provide
  +is being implemented in <CODE>Apache::{*}</CODE> perl modules, it was reported that one can build an apache server with
  +mod_perl only. If you can reduce the problems down to whatever mod_perl can
  +handle, you can eliminate nearly every other module. Then basically you
  +will have a perl-server, with C code to handle the tricky HTTP bits. The
  +only module you will need to leave in is a <CODE>mod_actions</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A></H1></CENTER>
  +<CENTER><H1><A NAME="mod_perl_server_as_DSO">mod_perl server as DSO</A></H1></CENTER>
   <P>
  -Let's say that you want all the file in a specific directory and below to
  -be handled the same way, but a few of them to be handled somewhat
  -different. For example:
  +To build the mod_perl as DSO add <CODE>USE_DSO=1</CODE> to the rest of configuration parameters (to build <CODE>libperl.so</CODE> instead of
  +<CODE>libperl.a</CODE>), like:
   
   <P>
  -<PRE>  &lt;Directory /home/foo&gt;
  -    &lt;FilesMatch &quot;\.(html|txt)$&quot;&gt;
  -      SetHandler perl-script
  -      PerlHandler Apache::AddrMunge
  -    &lt;/FilesMatch&gt;
  -  &lt;/Directory&gt;
  +<PRE>  perl Makefile.PL USE_DSO=1 ...
   </PRE>
   <P>
  -Alternatively you can use &lt;Files&gt; inside an <CODE>.htaccess</CODE> file.
  +If you run <CODE>./configure</CODE> from apache source do not forget to add:
  +<CODE>--enable-shared=perl</CODE>
  +
  +
   
   <P>
  -Note that you cannot have <CODE>Files</CODE> derective inside <CODE>Location</CODE>, but you can have <CODE>Files</CODE> inside <CODE>Directory</CODE>.
  +Then just add the <CODE>LoadModule</CODE> directive into your <CODE>httpd.conf</CODE>.
  +
  +<P>
  +You will find a complete explanation in the <CODE>INSTALL.apaci</CODE> pod which can be found in the mod_perl distribution.
  +
  +<P>
  +Some people reported that DSO compiled mod_perl would not run on specific
  +OS/perl version. Also threads enabled perl reported sometimes to break the
  +mod_perl/DSO. But it still can work for you.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_restarts_twice_on_start">Apache restarts twice on start</A></H1></CENTER>
  +<CENTER><H1><A NAME="Caveats_of_adding_mod_perl_php_">Caveats of adding mod_perl, php, ssl and other into Apache</A></H1></CENTER>
   <P>
  -When the server is restarted. the configuration and module initialization
  -phases are called again (twice in total). To ensure that the future restart
  -will workout correctly, Apache actually runs these two phases twice during
  -server startup, to check that all modules can survive a restart.
  +Typically, when building the bloated apache that sits behind squid or
  +whatever, you need mod_perl, php, mod_ssl and the rest. As you install each
  +they typically overwrite each other's <CODE>config.status</CODE> files. An advise is to save them after each step, so you would be able to
  +reproduce and reuse them later.
   
   <P>
  -(META: And add an example that writes to the log file - I was restarted 1,
  -2 times)
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Should_I_Build_mod_perl_with_gcc">Should I Build mod_perl with gcc or cc?</A></H1></CENTER>
  +<P>
  +Since mod_perl includes C code, to make it binary compatible with Perl, the
  +same compiler should be used as the one Perl was built with. So if your
  +Perl was built with gcc, it will pick the same compiler when you do <CODE>perl Makefile.PL ...</CODE>. To find out which compiler it was built with, run <CODE>perl -V</CODE> at the command prompt.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -11479,7 +11757,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="install.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="frequent.html">Next</A>      ]
  +	     [    <A HREF="scenario.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="config.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -11492,7 +11770,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/26/1999
  +	     <BR>Last Modified at 10/15/1999
         </FONT>
       </B>
     </TD>
  @@ -11519,7 +11797,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Frequent mod_perl problems</TITLE>
  +   <TITLE>mod_perl guide: Server Configuration</TITLE>
      <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
      <META NAME="Author" CONTENT="Stas Bekman">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  @@ -11538,15 +11816,62 @@
   <H1 ALIGN=CENTER>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Frequent mod_perl problems</H1>
  +Server Configuration</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="install.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="frequent.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Coverage">Coverage</A>
  -	<LI><A HREF="#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
  -	<LI><A HREF="#Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A>
  +	<LI><A HREF="#mod_perl_Specific_Configuration">mod_perl Specific Configuration</A>
  +	<UL>
  +
  +		<LI><A HREF="#Alias_Configurations">Alias Configurations</A>
  +		<LI><A HREF="#Location_Configuration">Location Configuration</A>
  +		<LI><A HREF="#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
  +		<LI><A HREF="#Perl_Handlers">Perl*Handlers</A>
  +		<LI><A HREF="#Stacked_Handlers">Stacked Handlers</A>
  +		<LI><A HREF="#Perl_Method_Handlers">Perl Method Handlers</A>
  +		<LI><A HREF="#PerlFreshRestart">PerlFreshRestart</A>
  +		<LI><A HREF="#_perl_status_location">/perl-status location</A>
  +		<UL>
  +
  +			<LI><A HREF="#Configuration">Configuration</A>
  +			<LI><A HREF="#Usage">Usage</A>
  +			<LI><A HREF="#Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A>
  +		</UL>
  +
  +		<LI><A HREF="#PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A>
  +		<LI><A HREF="#perl_startup_file">perl-startup file</A>
  +		<UL>
  +
  +			<LI><A HREF="#Sample_perl_startup_file">Sample perl-startup file</A>
  +			<LI><A HREF="#What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A>
  +			<LI><A HREF="#The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A>
  +			<LI><A HREF="#The_confusion_with_defining_glob">The confusion with defining globals in startup</A>
  +		</UL>
  +
  +	</UL>
  +
  +	<LI><A HREF="#Running_apachectl_configtest_o">Running 'apachectl configtest' or 'httpd -t'</A>
  +	<LI><A HREF="#Perl_behavior_controls">Perl behavior controls</A>
  +	<LI><A HREF="#Tuning_MinSpareServers_MaxSpareS">Tuning MinSpareServers MaxSpareServers StartServers MaxClients</A>
  +	<LI><A HREF="#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
  +	<LI><A HREF="#Perl_Sections">Perl Sections</A>
  +	<LI><A HREF="#Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A>
  +	<LI><A HREF="#General_pitfalls">General pitfalls</A>
  +	<UL>
  +
  +		<LI><A HREF="#My_cgi_perl_code_is_being_return">My cgi/perl code is being returned as a plain text instead of being executed by the webserver?</A>
  +		<LI><A HREF="#My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A>
  +		<LI><A HREF="#Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A>
  +		<LI><A HREF="#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A>
  +		<LI><A HREF="#A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A>
  +		<LI><A HREF="#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
  +	</UL>
  +
  +	<LI><A HREF="#Configuration_Security_Concerns">Configuration Security Concerns</A>
  +	<LI><A HREF="#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
  +	<LI><A HREF="#Apache_restarts_twice_on_start">Apache restarts twice on start</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -11570,32 +11895,2598 @@
   	       directly to me</A>.
   
   	       <HR>
  +
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<P>
  +<CENTER><H1><A NAME="mod_perl_Specific_Configuration">mod_perl Specific Configuration</A></H1></CENTER>
  +<P>
  +The next step after building and installing your new mod_perl enabled
  +apache server, is to configure the server. To learn how to modify apache's
  +configuration files, please refer to the documentation included with the
  +apache distribution, or just view the files in
  +<CODE>conf</CODE> directory and follow the instructions in these files - the embedded
  +comments within the file do a good job of explaining the options.
  +
  +<P>
  +Before you start with mod_perl specific configuration, first configure
  +apache, and see that it works. When done, return here to continue...
  +
  +<P>
  +[ Note that prior to version 1.3.4, the default apache install used three
  +configuration files -- <STRONG>httpd.conf</STRONG>, <STRONG>srm.conf</STRONG>, and
  +<STRONG>access.conf</STRONG>. The 1.3.4 version began distributing the configuration directives in a
  +single file -- <STRONG>httpd.conf</STRONG>. The remainder of this chapter refers to the location of the configuration
  +directives using their historical location. ]
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Alias_Configurations">Alias Configurations</A></H2></CENTER>
  +<P>
  +First, you need to specify the locations on a file-system for the scripts
  +to be found.
  +
  +<P>
  +Add the following configuration directives:
  +
  +<P>
  +<PRE>    # for plain cgi-bin:
  +  ScriptAlias /cgi-bin/ /usr/local/myproject/cgi/
  +    
  +    # for Apache::Registry mode
  +  Alias /perl/ /usr/local/myproject/cgi/
  +    
  +    # Apache::PerlRun mode
  +  Alias /cgi-perl/ /usr/local/myproject/cgi/
  +</PRE>
  +<P>
  +<CODE>Alias</CODE> provides a mapping of URL to file system object under
  +<CODE>mod_perl</CODE>. <CODE>ScriptAlias</CODE> is being used for <CODE>mod_cgi</CODE>.
  +
  +<P>
  +Alias defines the start of the URL path to the script you are referencing.
  +For example, using the above configuration, fetching
  +<CODE>http://www.nowhere.com/perl/test.pl</CODE>, will cause the server to look for the file <CODE>test.pl</CODE> at <CODE>/usr/local/myproject/cgi</CODE>, and execute it as an <CODE>Apache::Registry</CODE> script if we define <CODE>Apache::Registry</CODE> to be the handler of <CODE>/perl</CODE> location (see below). The URL
  +<CODE>http://www.nowhere.com/perl/test.pl</CODE> will be mapped to
  +<CODE>/usr/local/myproject/cgi/test.pl</CODE>. This means that you can have all your CGIs located at the same place in
  +the file-system, and call the script in any of three modes simply by
  +changing the directory name component of the URL (<CODE>cgi-bin|perl|cgi-perl</CODE>) - is not this neat? (That is the configuration you see above - all three
  +Aliases point to the same directory within your file system, but of course
  +they can be different). If your script does not seem to be working while
  +running under mod_perl, you can easily call the script in straight mod_cgi
  +mode without making any script changes (in most cases), but rather by
  +changing the URL you invoke it by.
  +
  +<P>
  +FYI: for modperl <CODE>ScriptAlias</CODE> is the same thing as:
  +
  +<P>
  +<PRE>  Alias /foo/ /path/to/foo/
  +  SetHandler cgi-handler
  +</PRE>
  +<P>
  +where <CODE>SetHandler cgi-handler</CODE> invokes mod_cgi. The latter will be overwritten if you enable <CODE>Apache::Registry</CODE>. In other words,
  +<CODE>ScriptAlias</CODE> does not work for mod_perl, it only appears to work when the additional
  +configuration is in there. If the
  +<CODE>Apache::Registry</CODE> configuration came before the <CODE>ScriptAlias</CODE>, scripts would be run under mod_cgi. While handy, <CODE>ScriptAlias</CODE> is a known kludge, always better to use <CODE>Alias</CODE> and <CODE>SetHandler</CODE>.
  +
  +<P>
  +Of course you can choose any other Alias (you will use it later in
  +<CODE>httpd.conf</CODE>), you can choose to use all three modes or only one of these. It is
  +undesirable to run scripts in plain mod_cgi from a mod_perl-enabled server
  +- the price is too high, it is better to run these on plain apache server.
  +(See <A HREF="././strategy.html#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>)
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Location_Configuration">Location Configuration</A></H2></CENTER>
  +<P>
  +Now we will work with the <CODE>httpd.conf</CODE> file. I add all the mod_perl stuff at the end of the file, after the native
  +apache configurations.
  +
  +<P>
  +First we add:
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    #AllowOverride None
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    Options ExecCGI
  +    allow from all
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +This configuration causes all scripts that are called with a <CODE>/perl</CODE>
  +path prefix to be executed under the <CODE>Apache::Registry</CODE> module and as a CGI (so the <STRONG>ExecCGI</STRONG>, if you omit this option the script will be printed to the caller's
  +browser as a plain text or possibly will trigger a 'Save-As' window).
  +
  +<P>
  +<CODE>PerlSendHeader On</CODE> tells the server to send an HTTP header to the browser on every script
  +invocation. You will want to turn this off for nph (non-parsed-headers)
  +scripts. <CODE>PerlSendHeader On</CODE> means to call
  +<CODE>ap_send_http_header()</CODE> after parsing your script headers. It is only meant for CGI emulation, its
  +always better to use <CODE>CGI-&amp;gt;header</CODE>
  +from <CODE>CGI.pm</CODE> module or <CODE>$r-&amp;gt;send_http_header</CODE> directly.
  +
  +<P>
  +Remember the <STRONG>Alias</STRONG> from the section above? We must use the same
  +<CODE>Alias</CODE> here, if you use <CODE>Location</CODE> that does not have the same
  +<CODE>Alias</CODE> defined in <CODE>srm.conf</CODE>, the server will fail to locate the script in the file system. (We are
  +talking about script execution here -- there are cases where <CODE>Location</CODE> is something that is being executed by the server itself, without having
  +the corresponding file, like <CODE>/perl-status</CODE> location.)
  +
  +<P>
  +Note that sometimes you will have to add :
  +
  +<P>
  +<PRE>  PerlModule Apache::Registry
  +</PRE>
  +<P>
  +before you specify the location that uses <CODE>Apache::Registry</CODE> as a
  +<CODE>PerlHandler</CODE>. Basically you can start running the scripts in the
  +<CODE>Apache::Registry</CODE> mode...
  +
  +<P>
  +You have nothing to do about <CODE>/cgi-bin</CODE> location (mod_cgi), since it has nothing to do with mod_perl.
  +
  +<P>
  +Here is a similar location configuration for <CODE>Apache::PerlRun</CODE> (More about <A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun</A>):
  +
  +<P>
  +<PRE>  &lt;Location /cgi-perl&gt;
  +    #AllowOverride None
  +    SetHandler perl-script
  +    PerlHandler Apache::PerlRun
  +    Options ExecCGI
  +    allow from all
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A></H2></CENTER>
  +<P>
  +You may load modules from the config file at server startup via:
  +
  +<P>
  +<PRE>    PerlModule Apache::DBI CGI DBD::Mysql
  +</PRE>
  +<P>
  +There is a limit of 10 <CODE>PerlModule</CODE>'s, if you need more to be loaded when the server starts, use one <CODE>PerlModule</CODE> to pull in many or write them all in a regular perl syntax and put them
  +into a startup file which can be loaded with use of the <CODE>PerlRequire</CODE> directive. 
  +
  +<P>
  +<PRE>    PerlRequire  /home/httpd/perl/lib/startup.pl
  +</PRE>
  +<P>
  +Both <CODE>PerlModule</CODE> and <CODE>PerlRequire</CODE> are implemented by <CODE>require(),</CODE> but there is a subtle change. <CODE>PerlModule</CODE> works like <CODE>use(),</CODE> expecting a module name without <CODE>.pm</CODE> extension and slashes.
  +<CODE>Apache::DBI</CODE> is OK, while <CODE>Apache/DBI.pm</CODE> is not. <CODE>PerlRequire</CODE> is the opposite to <CODE>PerlModule</CODE> -- it expects a relative or full path to the module or a filename, like in
  +the example above.
  +
  +<P>
  +As with any file that's being <CODE>required()</CODE> -- it must return a <STRONG>true</STRONG>
  +value, to ensure that this happens don't forget to add <CODE>1;</CODE> at the end of such files.
  +
  +<P>
  +We must stress that all the code that is run at the server initialization
  +time is run with root priveleges if you are executing it as a root user
  +(you have to unless you choose an unpriveledged port, above 1024.
  +somethings that you might have to if you don't have a root access. Just
  +remember that you better pick a well known port like 8000 or 8080 since
  +other non-standard ports might be blocked by firewalls that protect many
  +organizations and individuals). This means that anyone who has write access
  +to a script or module that is loaded by <CODE>PerlModule</CODE> or <CODE>PerlRequire</CODE>, effectively has root access to the system. You might want to take a look
  +at the new and experimental <CODE>PerlOpmask</CODE> directive and <CODE>PERL_OPMASK_DEFAULT</CODE>
  +compile time option to try to disable some dangerous operators.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Perl_Handlers">Perl*Handlers</A></H2></CENTER>
  +<P>
  +As you know Apache specifies about 11 phases of the request loop, namely in
  +that order: Post-Read-Request, URI Translation, Header Parsing, Access
  +Control, Authentication, Authorization, MIME type checking, FixUp, Response
  +(Content phase). Logging and finally Cleanup. These are the stages of a
  +request where the Apache API allows a module to step in and do something.
  +There is a dedicated PerlHandler for each of these stages. Namely:
  +
  +<P>
  +<PRE>    PerlChildInitHandler
  +    PerlPostReadRequestHandler
  +    PerlInitHandler
  +    PerlTransHandler
  +    PerlHeaderParserHandler
  +    PerlAccessHandler
  +    PerlAuthenHandler
  +    PerlAuthzHandler
  +    PerlTypeHandler
  +    PerlFixupHandler
  +    PerlHandler
  +    PerlLogHandler
  +    PerlCleanupHandler
  +    PerlChildExitHandler
  +</PRE>
  +<P>
  +The first 4 handlers cannot be used in the <CODE>&lt;Location</CODE>&gt;,
  +<CODE>&lt;Directory</CODE>&gt;, <CODE>&lt;Files</CODE>&gt; and <CODE>.htaccess</CODE> file, the main reason is all the above require a known path to the file in
  +order to bind a requested path with one or more of the identifiers above.
  +Starting from <CODE>PerlHeaderParserHandler</CODE> (5th) URI is allready being mapped to a physical pathname, thus can be used
  +to match the <CODE>&lt;Location</CODE>&gt;,
  +<CODE>&lt;Directory</CODE>&gt; or <CODE>&lt;Files</CODE>&gt; configuration section, or to look at
  +<CODE>.htaccess</CODE> file if exists at the specified directory in the translated path.
  +
  +<P>
  +The Apache documentation (or even better -- the ``Writing Apache Modules
  +with Perl and C'' book by Doug MacEachern and Lincoln Stein) will tell you
  +all about those stages and what your modules can do. By default, these
  +hooks are disabled at compile time, see the INSTALL document for
  +information on enabling these hooks.
  +
  +<P>
  +Note that by default Perl API expects a subrotine called <CODE>handler</CODE> to handle the request in the registered PerlHandler module. Thus if your
  +module implements this subrotine, you can register the handler as simple as
  +writing:
  +
  +<P>
  +<PRE>  Perl*Handler Apache::SomeModule
  +</PRE>
  +<P>
  +replace <EM>Perl*Handler</EM> with a wanted name of the handler. mod_perl will preload the specified
  +module for you. But if you decide to give the handler code a different
  +name, like <CODE>my_handler</CODE>, you must preload the module and to write explicitly the chosen name.
  +
  +<P>
  +<PRE>  PerlModule Apache::SomeModule
  +  Perl*Handler Apache::SomeModule::my_handler
  +</PRE>
  +<P>
  +Please note that the former approach will not preload the module at the
  +startup, so either explicitly preload it with <CODE>PerlModule</CODE>
  +directive, add it to the startup file or use a nice shortcut the
  +<CODE>Perl*Handler</CODE> syntax suggests:
  +
  +<P>
  +<PRE>  Perl*Handler +Apache::SomeModule
  +</PRE>
  +<P>
  +Notice the leading <CODE>+</CODE> character. It's equal to:
  +
  +<P>
  +<PRE>  PerlModule Apache::SomeModule
  +  Perl*Handler Apache::SomeModule
  +</PRE>
  +<P>
  +If a module wishes to know what handler is currently being run, it can find
  +out with the <EM>current_callback</EM> method. This method is most useful to <EM>PerlDispatchHandlers</EM> who wish to only take action for certain phases.
  +
  +<P>
  +<PRE> if($r-&gt;current_callback eq &quot;PerlLogHandler&quot;) {
  +     $r-&gt;warn(&quot;Logging request&quot;);
  + }
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Stacked_Handlers">Stacked Handlers</A></H2></CENTER>
  +<P>
  +With the mod_perl stacked handlers mechanism, it is possible for more than
  +one <CODE>Perl*Handler</CODE> to be defined and run during each stage of a request.
  +
  +<P>
  +Perl*Handler directives can define any number of subroutines, e.g. (in
  +config files)
  +
  +<P>
  +<PRE> PerlTransHandler OneTrans TwoTrans RedTrans BlueTrans
  +</PRE>
  +<P>
  +With the method, <CODE>Apache-&amp;gt;push_handlers()</CODE>, callbacks can be added to the stack by scripts at runtime by mod_perl
  +scripts.
  +
  +<P>
  +<CODE>Apache-&amp;gt;push_handlers()</CODE> takes the callback hook name as its first argument and a subroutine name or
  +reference as its second. e.g.:
  +
  +<P>
  +<PRE> Apache-&gt;push_handlers(&quot;PerlLogHandler&quot;, \&amp;first_one);
  + 
  + $r-&gt;push_handlers(&quot;PerlLogHandler&quot;, sub {
  +     print STDERR &quot;__ANON__ called\n&quot;;
  +     return 0;
  + });
  +</PRE>
  +<P>
  +After each request, this stack is cleared out.
  +
  +<P>
  +All handlers will be called unless a handler returns a status other than <CODE>OK</CODE> or <CODE>DECLINED</CODE>.
  +
  +<P>
  +example uses:
  +
  +<P>
  +<CODE>CGI.pm</CODE> maintains a global object for its plain function interface. Since the
  +object is global, it does not go out of scope, DESTROY is never called.  <CODE>CGI-&amp;gt;new</CODE> can call:
  +
  +<P>
  +<PRE> Apache-&gt;push_handlers(&quot;PerlCleanupHandler&quot;, \&amp;CGI::_reset_globals);
  +</PRE>
  +<P>
  +This function will be called during the final stage of a request,
  +refreshing <CODE>CGI.pm</CODE>'s globals before the next request comes in.
  +
  +<P>
  +<CODE>Apache::DCELogin</CODE> establishes a DCE login context which must exist for the lifetime of a
  +request, so the <CODE>DCE::Login</CODE> object is stored in a global variable. Without stacked handlers, users must
  +set
  +
  +<P>
  +<PRE> PerlCleanupHandler Apache::DCELogin::purge
  +</PRE>
  +<P>
  +in the configuration files to destroy the context. This is not
  +``user-friendly''. Now, <CODE>Apache::DCELogin::handler</CODE> can call:
  +
  +<P>
  +<PRE> Apache-&gt;push_handlers(&quot;PerlCleanupHandler&quot;, \&amp;purge);
  +</PRE>
  +<P>
  +Persistent database connection modules such as <CODE>Apache::DBI</CODE> could push a <CODE>PerlCleanupHandler</CODE> handler that iterates over <CODE>%Connected</CODE>, refreshing connections or just checking that ones have not gone stale.
  +Remember, by the time we get to <CODE>PerlCleanupHandler</CODE>, the client has what it wants and has gone away, we can spend as much time
  +as we want here without slowing down response time to the client (but the
  +process is unavailable for serving new request befor the operation is
  +completed).
  +
  +<P>
  +<CODE>PerlTransHandlers</CODE> may decide, based on URI or other condition, whether or not to handle a
  +request, e.g. <CODE>Apache::MsqlProxy</CODE>. Without stacked handlers, users must configure:
  +
  +<P>
  +<PRE> PerlTransHandler Apache::MsqlProxy::translate
  + PerlHandler      Apache::MsqlProxy
  +</PRE>
  +<P>
  +<CODE>PerlHandler</CODE> is never actually invoked unless <CODE>translate()</CODE> sees the request is a proxy request (<CODE>$r-&amp;gt;proxyreq</CODE>), if it is a proxy request, <CODE>translate()</CODE> sets <CODE>$r-&amp;gt;handler(&quot;perl-script&quot;)</CODE>, only then will <CODE>PerlHandler</CODE> handle the request. Now, users do not have to specify <CODE>PerlHandler Apache::MsqlProxy</CODE>, the <CODE>translate()</CODE>
  +function can set it with <CODE>push_handlers()</CODE>.
  +
  +<P>
  +Includes, footers, headers, etc., piecing together a document, imagine (no
  +need for SSI parsing!):
  +
  +<P>
  +<PRE> PerlHandler My::Header Some::Body A::Footer
  +</PRE>
  +<P>
  +A little test:
  +
  +<P>
  +<PRE> #My.pm
  + package My;
  +</PRE>
  +<P>
  +<PRE> sub header {
  +     my $r = shift;
  +     $r-&gt;content_type(&quot;text/plain&quot;);
  +     $r-&gt;send_http_header;
  +     $r-&gt;print(&quot;header text\n&quot;);
  + }
  + sub body   { shift-&gt;print(&quot;body text\n&quot;)   }
  + sub footer { shift-&gt;print(&quot;footer text\n&quot;) }
  + 1;
  + __END__
  +</PRE>
  +<P>
  +<PRE> #in config
  + &lt;Location /foo&gt;
  + SetHandler &quot;perl-script&quot;
  + PerlHandler My::header My::body My::footer   
  + &lt;/Location&gt;
  +</PRE>
  +<P>
  +Parsing the output of another PerlHandler? this is a little more tricky,
  +but consider:
  +
  +<P>
  +<PRE> &lt;Location /foo&gt;
  +   SetHandler &quot;perl-script&quot;
  +   PerlHandler OutputParser SomeApp
  + &lt;/Location&gt;
  + 
  + &lt;Location /bar&gt;
  +   SetHandler &quot;perl-script&quot;
  +   PerlHandler OutputParser AnotherApp
  + &lt;/Location&gt;
  +</PRE>
  +<P>
  +Now, OutputParser goes first, but it <CODE>untie()'s</CODE> <CODE>*STDOUT</CODE> and re-tie()'s to its own package like so:
  +
  +<P>
  +<PRE> package OutputParser;
  +</PRE>
  +<P>
  +<PRE> sub handler {
  +     my $r = shift;
  +     untie *STDOUT;
  +     tie *STDOUT =&gt; 'OutputParser', $r;
  + }
  +  
  + sub TIEHANDLE {
  +     my($class, $r) = @_;
  +     bless { r =&gt; $r}, $class;
  + }
  + 
  + sub PRINT {
  +     my $self = shift;   
  +     for (@_) {
  +         #do whatever you want to $_
  +         $self-&gt;{r}-&gt;print($_ . &quot;[insert stuff]&quot;);
  +     }
  + }
  +</PRE>
  +<P>
  +<PRE> 1;
  + __END__
  +</PRE>
  +<P>
  +To build in this feature, configure with:
  +
  +<P>
  +<PRE> % perl Makefile.PL PERL_STACKED_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
  +</PRE>
  +<P>
  +Another method <CODE>Apache-&amp;gt;can_stack_handlers</CODE> will return TRUE if mod_perl was configured with <CODE>PERL_STACKED_HANDLERS=1</CODE>, FALSE otherwise.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Perl_Method_Handlers">Perl Method Handlers</A></H2></CENTER>
  +<P>
  +If a Perl*Handler is prototyped with <CODE>$$</CODE>, this handler will be invoked as method. e.g.
  +
  +<P>
  +<PRE> package My;
  + @ISA = qw(BaseClass);
  +  
  + sub handler ($$) {
  +     my($class, $r) = @_;
  +     ...;
  + }
  +  
  + package BaseClass;
  +  
  + sub method ($$) {
  +     my($class, $r) = @_;
  +     ...;
  + }
  + __END__
  +</PRE>
  +<P>
  +Configuration:
  +
  +<P>
  +<PRE> PerlHandler My
  +</PRE>
  +<P>
  +or
  +
  +<P>
  +<PRE> PerlHandler My-&gt;handler
  +</PRE>
  +<P>
  +Since the handler is invoked as a method, it may inherit from other
  +classes:
  +
  +<P>
  +<PRE> PerlHandler My-&gt;method
  +</PRE>
  +<P>
  +In this case, the <CODE>My</CODE> class inherits this method from <CODE>BaseClass</CODE>.
  +
  +<P>
  +To build in this feature, configure with:
  +
  +<P>
  +<PRE> % perl Makefile.PL PERL_METHOD_HANDLERS=1 [PERL_FOO_HOOK=1,etc]
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="PerlFreshRestart">PerlFreshRestart</A></H2></CENTER>
  +<P>
  +To reload <CODE>PerlRequire</CODE>, <CODE>PerlModule</CODE>, other <CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache on server restart, add:
  +
  +<P>
  +<PRE>  PerlFreshRestart On
  +Make sure you read L&lt;Evil things might happen when using
  +PerlFreshRestart|warnings/Evil_things_might_happen_when_us&gt;.
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="_perl_status_location">/perl-status location</A></H2></CENTER>
  +<P>
  +A very useful feature. You can watch what happens to the perl guts of the
  +server. Below you will find the instructions of configuration and usage of
  +this feature
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Configuration">Configuration</A></H3></CENTER>
  +<P>
  +Add this to <CODE>httpd.conf</CODE>:
  +
  +<P>
  +<PRE>  &lt;Location /perl-status&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Status
  +    order deny,allow
  +    #deny from all
  +    #allow from 
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +If you are going to use <CODE>Apache::Status</CODE>, it's important to put it as a first module in the start-up file, or in
  +the <CODE>httpd.conf</CODE> (after
  +<CODE>Apache::Registry</CODE>):
  +
  +<P>
  +<PRE>  # startup.pl
  +  use Apache::Registry ();
  +  use Apache::Status ();
  +  use Apache::DBI ();
  +</PRE>
  +<P>
  +If you don't put <CODE>Apache::Status</CODE> before <CODE>Apache::DBI</CODE> then you don't get <CODE>Apache::DBI</CODE>'s menu entry in status.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Usage">Usage</A></H3></CENTER>
  +<P>
  +Assuming that your mod_perl server listens to port 81, fetch <A
  +HREF="http://www.nowhere.com:81/perl-status">http://www.nowhere.com:81/perl-status</A>
  +
  +
  +<P>
  +<PRE>  Embedded Perl version 5.00502 for Apache/1.3.2 (Unix) mod_perl/1.16 
  +  process 187138, running since Thu Nov 19 09:50:33 1998
  +</PRE>
  +<P>
  +This is the linked menu that you should see:
  +
  +<P>
  +<PRE>  Signal Handlers
  +  Enabled mod_perl Hooks
  +  PerlRequire'd Files
  +  Environment
  +  Perl Section Configuration
  +  Loaded Modules
  +  Perl Configuration
  +  ISA Tree
  +  Inheritance Tree
  +  Compiled Registry Scripts
  +  Symbol Table Dump
  +</PRE>
  +<P>
  +Let's follow for example : <STRONG>PerlRequire'd Files</STRONG> -- we see:
  +
  +<P>
  +<PRE>  PerlRequire                          Location
  +  /usr/myproject/lib/apache-startup.pl /usr/myproject/lib/apache-startup.pl
  +</PRE>
  +<P>
  +From some menus you can continue deeper to peek at the perl internals of
  +the server, to watch the values of the global variables in the packages, to
  +the list of cached scripts and modules and much more. Just click around...
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A></H3></CENTER>
  +<P>
  +Sometimes when you fetch <CODE>/perl-status</CODE> you and follow the <STRONG>Compiled
  +Registry Scripts</STRONG> link from the status menu -- you see no listing of scripts at all. This is
  +absolutely correct -- <CODE>Apache::Status</CODE> shows the registry scripts compiled in the httpd child which is serving
  +your request for <CODE>/perl-status</CODE>. If a child has not compiled yet the script you are asking for, <CODE>/perl-status</CODE> will just show you the main menu. This usually happens when the child was
  +just spawned.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A></H2></CENTER>
  +<P>
  +<PRE>  PerlSetEnv key val
  +  PerlPassEnv key
  +</PRE>
  +<P>
  +<CODE>PerlPassEnv</CODE> passes, <CODE>PerlSetEnv</CODE> sets and passes the
  +<EM>ENVironment</EM> variables to your scripts. you can access them in your scripts through <CODE>%ENV</CODE> (e.g. <CODE>$ENV{&quot;key&quot;}</CODE>).
  +
  +<P>
  +Regarding the setting of <CODE>PerlPassEnv PERL5LIB</CODE> in httpd.conf If you turn on taint checks (<CODE>PerlTaintMode On</CODE>), <CODE>$ENV{PERL5LIB}</CODE> will be ignored (unset).
  +
  +<P>
  +<CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In &lt;Perl&gt; sections:
  +
  +<P>
  +<PRE>  push @{ $Location{&quot;/&quot;}-&gt;{PerlSetVar} }, [ 'FOO' =&gt; BAR ];
  +</PRE>
  +<P>
  +and in the code you read it with:
  +
  +<P>
  +<PRE>  my $r = Apache-&gt;request;
  +  print $r-&gt;dir_config('FOO');
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="perl_startup_file">perl-startup file</A></H2></CENTER>
  +<P>
  +Since many times you have to add many perl directives to the configuration
  +file, it can be a good idea to put all of these into a one file, so the
  +configuration file will be cleaner. Add the following line to <CODE>httpd.conf</CODE>:
  +
  +<P>
  +<PRE>    # startup.perl loads all functions that we want to use within
  +    # mod_perl
  +  Perlrequire /path/to/startup.pl
  +</PRE>
  +<P>
  +before the rest of the mod_perl configuration directives.
  +
  +<P>
  +Also you can call <CODE>perl -c perl-startup</CODE> to test the file's syntax. What does this take?
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Sample_perl_startup_file">Sample perl-startup file</A></H3></CENTER>
  +<P>
  +An example of perl-startup file:
  +
  +<P>
  +<PRE>  use strict;
  +  
  +  # extend @INC if needed
  +  use lib qw(/dir/foo /dir/bar);
  +  
  +  # make sure we are in a sane environment.
  +  $ENV{GATEWAY_INTERFACE} =~ /^CGI-Perl/
  +     or die &quot;GATEWAY_INTERFACE not Perl!&quot;;
  +   
  +  # for things in the &quot;/perl&quot; URL
  +  use Apache::Registry;          
  +   
  +  #load perl modules of your choice here
  +  #this code is interpreted *once* when the server starts
  +  use LWP::UserAgent ();
  +  use DBI ();
  +  
  +  # tell me more about warnings
  +  use Carp ();
  +  $SIG{__WARN__} = \&amp;Carp::cluck;
  +  
  +  # Load CGI.pm and call its compile() method to precompile 
  +  # (but not to import) its autoloaded methods. 
  +  use CGI ();
  +  CGI-&gt;compile(':all');
  +</PRE>
  +<P>
  +Note that starting with <CODE>$CGI::VERSION</CODE> 2.46, the recommended method to precompile the code in <CODE>CGI.pm</CODE> is:
  +
  +<P>
  +<PRE>  use CGI qw(-compile :all);
  +</PRE>
  +<P>
  +But the old method is still available for backward compatibility.
  +
  +<P>
  +See also <A HREF="././status.html#Configuration">Apache::Status</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A></H3></CENTER>
  +<P>
  +Modules that are being loaded at the server startup will be shared among
  +server children, so only one copy of each module will be loaded, thus
  +saving a lot of RAM for you. Usually I put most of the code I develop into
  +modules and preload them from here. You can even preload your CGI script
  +with <CODE>Apache::RegistryLoader</CODE> and preopen the DB connections with <CODE>Apache::DBI</CODE>. (See <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>).
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A></H3></CENTER>
  +<P>
  +Many people wonder, why there is a need for duplication of <CODE>use()</CODE>
  +clause both in startup file and in the script itself. The question rises
  +from misunderstanding of the <CODE>use()</CODE> operand. <CODE>use()</CODE> consists of two other operands, namely <CODE>require()</CODE> and <CODE>import()</CODE>. So when you write:
  +
  +<P>
  +<PRE>  use Foo qw(bar);
  +</PRE>
  +<P>
  +perl actually does:
  +
  +<P>
  +<PRE>  require Foo.pm;
  +  import qw(bar);
  +</PRE>
  +<P>
  +When you write:
  +
  +<P>
  +<PRE>  use Foo qw();
  +</PRE>
  +<P>
  +perl actually does:
  +
  +<P>
  +<PRE>  require Foo.pm;
  +  import qw();
  +</PRE>
  +<P>
  +which means that the caller does not want any symbols to be imported. Why
  +is this important? Since some modules has <CODE>@EXPORT</CODE> set to a list of tags to be exported by default and when you write:
  +
  +<P>
  +<PRE>  use Foo;
  +</PRE>
  +<P>
  +and think nothing is being imported, the <CODE>import()</CODE> call is being executed and probably some symbols do being imported. See the
  +docs/source of the module in question to make sure you <CODE>use()</CODE> it correctly. When you write your own modules, always remember that it's
  +better to use <CODE>@EXPORT_OK</CODE> instead of <CODE>@EXPORT</CODE>, since the former doesn't export tags unless it was asked to.
  +
  +<P>
  +Since the symbols that you might import into a startup's script namespace
  +will be visible by none of the children, scripts that need a
  +<CODE>Foo</CODE>'s module exported tags have to pull it in like if you did not preload <CODE>Foo</CODE> at the startup file. For example, just because you have
  +<CODE>use()d</CODE>  <CODE>Apache::Constants</CODE> in the startup script, does not mean you can have the following handler:
  +
  +<P>
  +<PRE>  package MyModule;
  +  
  +  sub {
  +    my $r = shift;
  +  
  +    ## Cool stuff goes here
  +  
  +    return OK;
  +  }
  +</PRE>
  +<P>
  +<PRE>  1;
  +</PRE>
  +<P>
  +You would either need to add:
  +
  +<P>
  +<PRE>  use Apache::Constants qw( OK );
  +</PRE>
  +<P>
  +Or instead of <CODE>return OK;</CODE> say:
  +
  +<P>
  +<PRE>  return Apache::Constants::OK;
  +</PRE>
  +<P>
  +See the manpage/perldoc on <CODE>Exporter</CODE> and <CODE>perlmod</CODE> for more on
  +<CODE>import()</CODE>.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="The_confusion_with_defining_glob">The confusion with defining globals in startup</A></H3></CENTER>
  +<P>
  +<CODE>PerlRequire</CODE> allows you to execute code that preloads modules and does more things.
  +Imported or defined variables are visible in the scope of the startup file.
  +It is a wrong assumption that global variables that were defined in the
  +startup file, will be accessible by child processes.
  +
  +<P>
  +You do have to define/import variables in your scripts and they will be
  +visible inside a child process who run this script. They will be not shared
  +between siblings. Remember that every script is running in a specially
  +(uniquely) named package - so it cannot access variables from other
  +packages unless it inherits from them or <CODE>use()</CODE>'s them.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Running_apachectl_configtest_o">Running 'apachectl configtest' or 'httpd -t'</A></H1></CENTER>
  +<P>
  +<CODE>apachectl configtest</CODE> tests the configuration file without starting the server. You can safely
  +modify the configuration file on your production server, if you run this
  +test before you restart the server. Of course it is not 100% error prone,
  +but it will reveal any syntax errors you might do while editing the file.
  +
  +<P>
  +'<CODE>apachectl configtest</CODE>' is the same as '<CODE>httpd -t</CODE>' and it actually executes the code in startup.pl, not just parses it. <CODE>&lt;Perl</CODE>&gt; configuration has always started Perl during the configuration read,
  +<CODE>Perl{Require,Module}</CODE> do so as well.
  +
  +<P>
  +If you want your startup code to get a control over the <CODE>-t</CODE>
  +(<CODE>configtest</CODE>) server launch, start the server configuration test with:
  +
  +<P>
  +<PRE>  httpd -t -Dsyntax_check
  +</PRE>
  +<P>
  +and in your startup file, add (at the top):
  +
  +<P>
  +<PRE>  return if Apache-&gt;define('syntax_check');
  +</PRE>
  +<P>
  +if you want to prevent the code in the file from being executed.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Perl_behavior_controls">Perl behavior controls</A></H1></CENTER>
  +<P>
  +For <STRONG>PerlWarn</STRONG> and <STRONG>PerlTaintCheck</STRONG> see <A HREF="././porting.html#Switches_w_T">Switches -w, -T</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Tuning_MinSpareServers_MaxSpareS">Tuning MinSpareServers MaxSpareServers StartServers MaxClients
  +MaxRequestsPerChild</A></H1></CENTER>
  +<P>
  +See <A HREF="././performance.html#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Publishing_port_numbers_differen">Publishing port numbers different from 80</A></H1></CENTER>
  +<P>
  +It is advised not to publish the 8080 (or alike) port number in URLs, but
  +rather using a proxying rewrite rule in the thin (httpd_docs) server:
  +
  +<P>
  +<PRE>  RewriteRule .*/perl/(.*) <A HREF="http://my.url:8080/perl/">http://my.url:8080/perl/</A>$1 [P]
  +</PRE>
  +<P>
  +One problem with publishing 8080 port numbers is that I was told that IE
  +4.x has a bug when re-posting data to a non-port-80 url. It drops the port
  +designator, and uses port 80 anyway.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Perl_Sections">Perl Sections</A></H1></CENTER>
  +<P>
  +With <CODE>&amp;lt;Perl&amp;gt;&amp;lt;/Perl&amp;gt;</CODE> sections, it is possible to configure your server entirely in Perl.
  +
  +<P>
  +<STRONG>&lt;Perl&gt;</STRONG> sections can contain *any* and as much Perl code as you wish. These
  +sections are compiled into a special package whose symbol table mod_perl
  +can then walk and grind the names and values of Perl variables/structures
  +through the apache core configuration gears. Most of the configurations
  +directives can be represented as scalars (<STRONG>$scalar</STRONG>) or lists (<STRONG>@list</STRONG>). An <CODE>@List</CODE> inside these sections is simply converted into a space delimited string for
  +you inside. Here is an example:
  +
  +<P>
  +<PRE>  #httpd.conf
  +  &lt;Perl&gt;
  +  @PerlModule = qw(Mail::Send Devel::Peek);
  + 
  +  #run the server as whoever starts it
  +  $User  = getpwuid($&gt;) || $&gt;;
  +  $Group = getgrgid($)) || $); 
  + 
  +  $ServerAdmin = $User;
  + 
  +  &lt;/Perl&gt;
  +</PRE>
  +<P>
  +Block sections such as <CODE>&lt;Location</CODE>..&lt;/Location&gt;&gt; are represented in a
  +<CODE>%Location</CODE> hash, e.g.:
  +
  +<P>
  +<PRE>  $Location{&quot;/~dougm/&quot;} = {
  +    AuthUserFile =&gt; '/tmp/htpasswd',
  +    AuthType =&gt; 'Basic',
  +    AuthName =&gt; 'test',
  +    DirectoryIndex =&gt; [qw(index.html index.htm)],  
  +    Limit =&gt; {
  +    METHODS =&gt; 'GET POST',
  +    require =&gt; 'user dougm',
  +    },
  +  };
  +</PRE>
  +<P>
  +If a Directive can take two *or* three arguments you may push strings and
  +the lowest number of arguments will be shifted off the <CODE>@List</CODE> or use array reference to handle any number greater than the minimum for
  +that directive:
  +
  +<P>
  +<PRE>  push @Redirect, &quot;/foo&quot;, &quot;<A HREF="http://www.foo.com/&quot">http://www.foo.com/&quot</A>;;
  +  
  +  push @Redirect, &quot;/imdb&quot;, &quot;<A HREF="http://www.imdb.com/&quot">http://www.imdb.com/&quot</A>;;
  +  
  +  push @Redirect, [qw(temp &quot;/here&quot; &quot;<A HREF="http://www.there.com&quot">http://www.there.com&quot</A>;)];
  +</PRE>
  +<P>
  +Other section counterparts include <CODE>%VirtualHost</CODE>, <CODE>%Directory</CODE> and
  +<CODE>%Files</CODE>.
  +
  +<P>
  +To pass all environment variables to the children with a single
  +configuration directive, rather than listing each one via PassEnv or
  +PerlPassEnv, a <STRONG>&lt;Perl&gt;</STRONG> section could read in a file and:
  +
  +<P>
  +<PRE>  push @PerlPassEnv, [$key =&gt; $val];
  +</PRE>
  +<P>
  +or
  +
  +<P>
  +<PRE>  Apache-&gt;httpd_conf(&quot;PerlPassEnv $key $val&quot;);
  +</PRE>
  +<P>
  +These are somewhat simple examples, but they should give you the basic
  +idea. You can mix in any Perl code your heart desires. See
  +<CODE>eg/httpd.conf.pl</CODE> and <CODE>eg/perl_sections.txt</CODE> in mod_perl distribution for some examples.
  +
  +<P>
  +A tip for syntax checking outside of httpd:
  +
  +<P>
  +<PRE>  &lt;Perl&gt;
  +  # !perl
  +  
  +  #... code here ...
  +  
  +  __END__
  +  &lt;/Perl&gt;
  +</PRE>
  +<P>
  +Now you may run:
  +
  +<P>
  +<PRE>  perl -cx httpd.conf
  +</PRE>
  +<P>
  +To enable <CODE>&lt;Perl</CODE>&gt; sections you should build mod_perl with <STRONG>perl
  +Makefile.PL PERL_SECTIONS=1</STRONG>.
  +
  +<P>
  +You can watch how have you configured the <CODE>&lt;Perl</CODE>&gt; sections through the <A HREF="././config.html#_perl_status_location">/perl-status</A> location, by choosing the <STRONG>Perl Sections</STRONG> from the menu.
  +
  +<P>
  +You can dump the configuration by <CODE>&lt;Perl</CODE>&gt; sections configuration this way:
  +
  +<P>
  +<PRE>  &lt;Perl&gt;
  +  use Apache::PerlSections();
  +  ...
  +  print STDERR Apache::PerlSections-&gt;dump();
  +  &lt;/Perl&gt;
  +</PRE>
  +<P>
  +Alternatively you can store it in a file:
  +
  +<P>
  +<PRE>  Apache::PerlSections-&gt;store(&quot;httpd_config.pl&quot;);
  +</PRE>
  +<P>
  +You can then <CODE>require()</CODE> that file in some other <CODE>&lt;Perl</CODE>&gt; section.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A></H1></CENTER>
  +<P>
  +mod_macro is an Apache module written by Fabien Coelho that lets you define
  +and use macros in the Apache configuration file.
  +
  +<P>
  +mod_macro proved really useful when you have many virtual hosts, each
  +virtual host has a number of scripts/modules, most of them with a
  +moderately complex configuration setup.
  +
  +<P>
  +First download the latest version of mod_macro from <A
  +HREF="http://www.cri.ensmp.fr/~coelho/mod_macro/">http://www.cri.ensmp.fr/~coelho/mod_macro/</A>
  +, and configure your Apache server to use this module.
  +
  +<P>
  +Here are some useful macros for mod_perl users:
  +
  +<P>
  +<PRE>        # set up a registry script
  +        &lt;Macro registry&gt;
  +        SetHandler &quot;perl-script&quot;
  +        PerlHandler Apache::Registry
  +        Options +ExecCGI
  +        &lt;/Macro&gt;
  +</PRE>
  +<P>
  +<PRE>        # example
  +        Alias /stuff /usr/www/scripts/stuff
  +        &lt;Location /stuff&gt;
  +        Use registry
  +        &lt;/Location&gt;
  +</PRE>
  +<P>
  +If your registry scripts are all located in the same directory, and your
  +aliasing rules consistent, you can use this macro:
  +
  +<P>
  +<PRE>        # set up a registry script for a specific location
  +        &lt;Macro registry $location $script&gt;
  +        Alias /script /usr/www/scripts/$script
  +        &lt;Location $location&gt;
  +        SetHandler &quot;perl-script&quot;
  +        PerlHandler Apache::Registry
  +        Options +ExecCGI
  +        &lt;/Location&gt;
  +        &lt;/Macro&gt;
  +</PRE>
  +<P>
  +<PRE>        # example
  +        Use registry stuff stuff.pl
  +</PRE>
  +<P>
  +If you're using content handlers packaged as modules, you can use the
  +following macro:
  +
  +<P>
  +<PRE>        # set up a mod_perl content handler module
  +        &lt;Macro modperl $module&gt;
  +        SetHandler &quot;perl-script&quot;
  +        Options +ExecCGI
  +        PerlHandler $module
  +        &lt;/Macro&gt;
  +</PRE>
  +<P>
  +<PRE>        #examples
  +        &lt;Location /perl-status&gt;
  +        PerlSetVar StatusPeek On
  +        PerlSetVar StatusGraph On
  +        PerlSetVar StatusDumper On
  +        Use modperl Apache::Status
  +        &lt;/Location&gt;
  +</PRE>
  +<P>
  +The following macro sets up a Location for use with HTML::Embperl. Here we
  +define all ``.html'' files to be processed by Embperl.
  +
  +<P>
  +<PRE>        &lt;Macro embperl&gt;
  +        SetHandler &quot;perl-script&quot;
  +        Options +ExecCGI
  +        PerlHandler HTML::Embperl
  +        PerlSetEnv EMBPERL_FILESMATCH \.html$
  +        &lt;/Macro&gt;
  +</PRE>
  +<P>
  +<PRE>        # examples
  +        &lt;Location /mrtg&gt;
  +        Use embperl
  +        &lt;/Location&gt;
  +</PRE>
  +<P>
  +Macros are also very useful for things that tend to be verbose, such as
  +setting up Basic Authentication:
  +
  +<P>
  +<PRE>        # Sets up Basic Authentication
  +        &lt;Macro BasicAuth $realm $group&gt;
  +        Order deny,allow
  +        Satisfy any
  +        AuthType Basic
  +        AuthName $realm
  +        AuthGroupFile /usr/www/auth/groups
  +        AuthUserFile /usr/www/auth/users
  +        Require group $group
  +        Deny from all
  +        &lt;/Macro&gt;
  +</PRE>
  +<P>
  +<PRE>        # example of use
  +        &lt;Location /stats&gt;
  +        Use BasicAuth WebStats Admin
  +        &lt;/Location&gt;
  +</PRE>
  +<P>
  +Finally, here is a complete example that uses macros to set up simple
  +virtual hosts. It uses the BasicAuth macro defined previously (yes, macros
  +can be nested!).
  +
  +<P>
  +<PRE>        &lt;Macro vhost $ip $domain $docroot $admingroup&gt;
  +        &lt;VirtualHost $ip&gt;
  +        ServerAdmin webmaster@$domain
  +        DocumentRoot /usr/www/htdocs/$docroot
  +        ServerName www.$domain
  +        &lt;Location /stats&gt;
  +        Use BasicAuth Stats-$domain $admingroup
  +        &lt;/Location&gt;
  +        &lt;/VirtualHost&gt;
  +        &lt;/Macro&gt;
  +</PRE>
  +<P>
  +<PRE>        # define some virtual hosts
  +        Use vhost 10.1.1.1 example.com example example-admin
  +        Use vhost 10.1.1.2 example.net examplenet examplenet-admin
  +</PRE>
  +<P>
  +mod_macro also useful in a non vhost setting. Some sites for example have
  +lots of scripts where people use to view various statistics, email settings
  +and etc. It is much easier to read things like:
  +
  +<P>
  +<PRE>  use /forwards email/showforwards
  +  use /webstats web/showstats
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="General_pitfalls">General pitfalls</A></H1></CENTER>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="My_cgi_perl_code_is_being_return">My cgi/perl code is being returned as a plain text instead of being executed by the webserver?</A></H2></CENTER>
  +<P>
  +Check your configuration files and make sure that the ``ExecCGI'' is turned
  +on in your configurations. 
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    Options ExecCGI
  +    allow from all
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="My_script_works_under_cgi_bin_b">My script works under cgi-bin, but when called via mod_perl I see A 'Save-As' prompt</A></H2></CENTER>
  +<P>
  +Did you put <STRONG>PerlSendHeader On</STRONG> in the configuration part of the &lt;Location foo&gt;&lt;/Location&gt;?
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Is_there_a_way_to_provide_a_diff">Is there a way to provide a different startup.pl file for each individual virtual host</A></H2></CENTER>
  +<P>
  +No. Any virtual host will be able to see the routines from a startup.pl
  +loaded for any other virtual host.  
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A></H2></CENTER>
  +<P>
  +You can use 'PerlSetEnv PERL5LIB ...' or a PerlFixupHandler w/ the lib
  +pragma.
  +
  +<P>
  +Even a better way is to use <A HREF="././modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="A_Script_from_one_virtual_host_c">A Script from one virtual host calls a script with the same path from the other virtual host</A></H2></CENTER>
  +<P>
  +This has been a bug before, last fixed in 1.15_01, i.e. if you are running
  +1.15, that could be the problem. You should set this variable in a startup
  +file (PerlRequire):
  +
  +<P>
  +<PRE>  $Apache::Registry::NameWithVirtualHost = 1;
  +</PRE>
  +<P>
  +But, as we know sometimes bug turns into a feature. If there is the same
  +script running for more than one Virtual host on the same machine, this can
  +be a waste, right? Set it to 0 in a startup script if you want to turn it
  +off and have this bug as a feature. (Only makes sense if you are sure that
  +there will be no <STRONG>other</STRONG>scripts named by the same path/name). It also saves you some memory on the
  +way.
  +
  +<P>
  +<PRE>  $Apache::Registry::NameWithVirtualHost = 0;
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A></H2></CENTER>
  +<P>
  +The problem was reported by users who declared mod_perl configuration
  +inside a &lt;Directory&gt; section for all files matching to *.pl. The
  +problem has gone away after placing the usage of mod_perl in a
  +&lt;File&gt;- section.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Configuration_Security_Concerns">Configuration Security Concerns</A></H1></CENTER>
  +<P>
  +It is better not to advertise the port mod_perl server running at to the
  +outside world for it creates a potential security risk by revealing which
  +<CODE>module(s)</CODE> and/or OS you are running your web server on.
  +
  +<P>
  +The more modules you have in your web server, the more complex the code in
  +your webserver.
  +
  +<P>
  +The more complex the code in your web server, the more chances for bugs.
  +
  +<P>
  +The more chance for bugs, the more chance that some of those bugs may
  +involve security.
  +
  +<P>
  +Never was completely sure why the default of the ServerToken directive in
  +Apache is Full rather than Minimal. Seems like you would only make it full
  +if you are debugging.
  +
  +<P>
  +For more information see <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
  +
  +
  +
  +<P>
  +Another approach is to modify httpd sources to reveal no unwanted
  +information, so if you know the port the <CODE>HEAD</CODE> request will return an empty or phony <CODE>Server:</CODE> field.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A></H1></CENTER>
  +<P>
  +Let's say that you want all the file in a specific directory and below to
  +be handled the same way, but a few of them to be handled somewhat
  +different. For example:
  +
  +<P>
  +<PRE>  &lt;Directory /home/foo&gt;
  +    &lt;FilesMatch &quot;\.(html|txt)$&quot;&gt;
  +      SetHandler perl-script
  +      PerlHandler Apache::AddrMunge
  +    &lt;/FilesMatch&gt;
  +  &lt;/Directory&gt;
  +</PRE>
  +<P>
  +Alternatively you can use &lt;Files&gt; inside an <CODE>.htaccess</CODE> file.
  +
  +<P>
  +Note that you cannot have <CODE>Files</CODE> derective inside <CODE>Location</CODE>, but you can have <CODE>Files</CODE> inside <CODE>Directory</CODE>.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_restarts_twice_on_start">Apache restarts twice on start</A></H1></CENTER>
  +<P>
  +When the server is restarted. the configuration and module initialization
  +phases are called again (twice in total). To ensure that the future restart
  +will workout correctly, Apache actually runs these two phases twice during
  +server startup, to check that all modules can survive a restart.
  +
  +<P>
  +(META: And add an example that writes to the log file - I was restarted 1,
  +2 times)
  +
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     book can be purchased online from <a
  +	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  +	     and <a
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
  +
  +	     <HR>
  +
  +	     Your corrections of either technical or grammatical
  +	     errors are very welcome. You are encouraged to help me
  +	     to improve this guide.  If you have something to
  +	     contribute please <A
  +	     HREF="help.html#This_document_s_Author"> send it
  +	     directly to me</A>.
  +
  +	     <HR>
  +
  +	     [    <A HREF="install.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="frequent.html">Next</A>      ]
  +
  +<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  +	     <HR>
  +  </TD>
  +</TR>
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <TD ALIGN=CENTER VALIGN=CENTER>
  +    <B>
  +      <FONT SIZE=-1>
  +	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  +	     <BR>Last Modified at 10/12/1999
  +      </FONT>
  +    </B>
  +  </TD>
  +
  +  <TD>
  +	     <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
  +  </TD>
  +
  +  <TD>
  +    <FONT SIZE=-2>
  +	     Use of the Camel for Perl is <BR>
  +	     a trademark of <A HREF="http://www.ora.com">O'Reilly &amp; Associates</A>,<BR>
  +             and is used by permission. 
  +    </FONT> 
  +  </TD>
  +</TR>
  +</TABLE></CENTER>
  +
  +</BODY>
  +</HTML>
  +	    
  +
  +<HR SIZE=6>
  +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  +<HTML>
  +<HEAD>
  +   <TITLE>mod_perl guide: Frequent mod_perl problems</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
  +   <META NAME="Author" CONTENT="Stas Bekman">
  +   <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  +   <META NAME="keywords" CONTENT="mod_perl modperl perl apache cgi webserver speed  fast guide mod_perl apache guide help info faq mod_perl installation cgi troubleshooting help no sex speedup free open source OSS mod_perl apache guide">
  +</HEAD>
  +     <LINK REL=STYLESHEET TYPE="text/css"
  +        HREF="style.css" TITLE="refstyle">
  +     <style type="text/css">
  +     <!-- 
  +        @import url(style.css);
  +     -->
  +     
  +     </style>
  +<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
  +<A NAME="toc"></A>
  +<H1 ALIGN=CENTER>
  +<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
  +<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  +Frequent mod_perl problems</H1>
  +<HR WIDTH="100%">
  +	    [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#Coverage">Coverage</A>
  +	<LI><A HREF="#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
  +	<LI><A HREF="#Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A>
  +</UL>
  +<!-- INDEX END -->
  +
  +<HR>
  +
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     book can be purchased online from <a
  +	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  +	     and <a
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
  +
  +	     <HR>
  +
  +	       Your corrections of either technical or grammatical
  +	       errors are very welcome. You are encouraged to help me
  +	       to improve this guide.  If you have something to
  +	       contribute please <A
  +	       HREF="help.html#This_document_s_Author"> send it
  +	       directly to me</A>.
  +
  +	       <HR>
  +
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<P>
  +<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
  +<P>
  +This new document was born because some problems come up so often on the
  +mailing list that should be stressed in the guide as one of the most
  +important things to read/beware of. So I have tried to enlist them in this
  +document. If you think some important problem that is being reported
  +frequently on the list and covered in the guide but not included below,
  +please tell.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A></H1></CENTER>
  +<P>
  +See <A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A></H1></CENTER>
  +<P>
  +See <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
  +
  +
  +
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     book can be purchased online from <a
  +	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  +	     and <a
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
  +
  +	     <HR>
  +
  +	     Your corrections of either technical or grammatical
  +	     errors are very welcome. You are encouraged to help me
  +	     to improve this guide.  If you have something to
  +	     contribute please <A
  +	     HREF="help.html#This_document_s_Author"> send it
  +	     directly to me</A>.
  +
  +	     <HR>
  +
  +	     [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]
  +
  +<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  +	     <HR>
  +  </TD>
  +</TR>
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <TD ALIGN=CENTER VALIGN=CENTER>
  +    <B>
  +      <FONT SIZE=-1>
  +	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  +	     <BR>Last Modified at 07/09/1999
  +      </FONT>
  +    </B>
  +  </TD>
  +
  +  <TD>
  +	     <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl2.jpg" ALT="Mod Perl Icon" BORDER=0 HEIGHT=59 WIDTH=150></A>
  +  </TD>
  +
  +  <TD>
  +    <FONT SIZE=-2>
  +	     Use of the Camel for Perl is <BR>
  +	     a trademark of <A HREF="http://www.ora.com">O'Reilly &amp; Associates</A>,<BR>
  +             and is used by permission. 
  +    </FONT> 
  +  </TD>
  +</TR>
  +</TABLE></CENTER>
  +
  +</BODY>
  +</HTML>
  +	    
  +
  +<HR SIZE=6>
  +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  +<HTML>
  +<HEAD>
  +   <TITLE>mod_perl guide: Controlling and Monitoring the Server</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
  +   <META NAME="Author" CONTENT="Stas Bekman">
  +   <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  +   <META NAME="keywords" CONTENT="mod_perl modperl perl apache cgi webserver speed  fast guide mod_perl apache guide help info faq mod_perl installation cgi troubleshooting help no sex speedup free open source OSS mod_perl apache guide">
  +</HEAD>
  +     <LINK REL=STYLESHEET TYPE="text/css"
  +        HREF="style.css" TITLE="refstyle">
  +     <style type="text/css">
  +     <!-- 
  +        @import url(style.css);
  +     -->
  +     
  +     </style>
  +<BODY TEXT="#000000" BGCOLOR="#E0FFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
  +<A NAME="toc"></A>
  +<H1 ALIGN=CENTER>
  +<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
  +<A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  +Controlling and Monitoring the Server</H1>
  +<HR WIDTH="100%">
  +	    [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#Restarting_techniques">Restarting techniques</A>
  +	<LI><A HREF="#Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A>
  +	<LI><A HREF="#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
  +	<LI><A HREF="#Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A>
  +	<LI><A HREF="#An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A>
  +	<LI><A HREF="#SUID_start_up_scripts">SUID start-up scripts</A>
  +	<LI><A HREF="#Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A>
  +	<LI><A HREF="#Running_server_in_a_single_mode">Running server in a single mode</A>
  +	<LI><A HREF="#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
  +	<LI><A HREF="#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
  +	<LI><A HREF="#Log_Rotation">Log Rotation</A>
  +	<LI><A HREF="#Preventing_from_modperl_process_">Preventing from modperl process from going wild</A>
  +</UL>
  +<!-- INDEX END -->
  +
  +<HR>
  +
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     book can be purchased online from <a
  +	     href="http://www.ora.com/catalog/wrapmod/">O'Reilly </a>
  +	     and <a
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
  +
  +	     <HR>
  +
  +	       Your corrections of either technical or grammatical
  +	       errors are very welcome. You are encouraged to help me
  +	       to improve this guide.  If you have something to
  +	       contribute please <A
  +	       HREF="help.html#This_document_s_Author"> send it
  +	       directly to me</A>.
  +
  +	       <HR>
  +
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<P>
  +<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
  +<P>
  +All of these techniques require that you know the server PID (Process ID).
  +The easiest way to find the PID is to look it up in the <CODE>httpd.pid</CODE> file. With my configuration it exists as
  +<CODE>/usr/local/var/httpd_perl/run/httpd.pid</CODE>. It's easy to discover where to look at, by checking out the httpd.conf
  +file. Open the file and locate the entry <CODE>PidFile</CODE>:
  +
  +<P>
  +<PRE>  PidFile /usr/local/var/httpd_perl/run/httpd.pid
  +</PRE>
  +<P>
  +Another way is to use the <CODE>ps</CODE> and <CODE>grep</CODE> utilities:
  +
  +<P>
  +<PRE>  % ps auxc | grep httpd_perl
  +</PRE>
  +<P>
  +or maybe:
  +
  +<P>
  +<PRE>  % ps -ef | grep httpd_perl
  +</PRE>
  +<P>
  +This will produce a list of all <CODE>httpd_perl</CODE> (the parent and the children) processes. You are looking for the parent
  +process. If you run your server as root - you will easily locate it, since
  +it belongs to root. If you run the server as user (when you <A HREF="././install.html#Is_it_possible_to_install_and_us">don't have a root access</A>, most likely all the processes will belong to that user (unless defined
  +differently in the
  +<CODE>httpd.conf</CODE>), but it's still easy to know 'who is the parent' -- the one of the
  +smallest size...
  +
  +<P>
  +You will notice many <CODE>httpd_perl</CODE> executables running on your system, but you should not send signals to any
  +of them except the parent, whose pid is in the <CODE>PidFile</CODE>. That is to say you shouldn't ever need to send signals to any process
  +except the parent. There are three signals that you can send the parent: <STRONG>TERM</STRONG>, <STRONG>HUP</STRONG>, and <STRONG>USR1</STRONG>.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A></H1></CENTER>
  +<P>
  +We will concentrate here on the implications of sending these signals to a
  +mod_perl enabled server. For documentation on the implications of sending
  +these signals to a plain Apache server see <A
  +HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
  +.
  +
  +<DL>
  +<P><DT><STRONG><A NAME="item_TERM">TERM Signal: stop now</A></STRONG><DD>
  +<P>
  +Sending the <STRONG>TERM</STRONG> signal to the parent causes it to immediately attempt to kill off all of
  +its children. This process may take several seconds to complete, following
  +which the parent itself exits. Any requests in progress are terminated, and
  +no further requests are served.
  +
  +<P>
  +That's the moment that the accumulated <CODE>END</CODE> blocks will be executed! Note that if you use <CODE>Apache::Registry</CODE> or <CODE>Apache::PerlRun</CODE>, then
  +<CODE>END</CODE> blocks are being executed upon each request (at the end).
  +
  +<P><DT><STRONG><A NAME="item_HUP">HUP Signal: restart now</A></STRONG><DD>
  +<P>
  +Sending the <STRONG>HUP</STRONG> signal to the parent causes it to kill off its children like in <STRONG>TERM</STRONG> (Any requests in progress are terminated) but the parent doesn't exit. It
  +re-reads its configuration files, and re-opens any log files. Then it
  +spawns a new set of children and continues serving hits.
  +
  +<P>
  +The server will reread its configuration files, flush all the compiled and
  +preloaded modules, and rerun any startup files. It's equivalent to
  +stopping, then restarting a server.
  +
  +<P>
  +Note: If your configuration file has errors in it when you issue a restart
  +then your parent will not restart but exit with an error. See below for a
  +method of avoiding this.
  +
  +<P><DT><STRONG><A NAME="item_USR1">USR1 Signal: graceful restart</A></STRONG><DD>
  +<P>
  +The <STRONG>USR1</STRONG> signal causes the parent process to advise the children to exit after their
  +current request (or to exit immediately if they're not serving anything).
  +The parent re-reads its configuration files and re-opens its log files. As
  +each child dies off the parent replaces it with a child from the new
  +generation of the configuration, which begins serving new requests
  +immediately. 
  +
  +<P>
  +The only difference between <STRONG>USR1</STRONG> and <STRONG>HUP</STRONG> is that <STRONG>USR1</STRONG> allows children to complete any in-progress request prior to killing them
  +off.
  +
  +<P>
  +By default, if a server is restarted (ala <CODE>kill -USR1 `cat
  +logs/httpd.pid`</CODE> or with <STRONG>HUP</STRONG> signal), Perl scripts and modules are not reloaded. To reload <STRONG>PerlRequire</STRONG>'s, <STRONG>PerlModule</STRONG>'s, other
  +<CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache, enable with this command:
  +
  +<P>
  +<PRE> PerlFreshRestart On              (in httpd.conf) 
  +</PRE>
  +<P>
  +Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
  +
  +</DL>
  +<P>
  +It's worth mentioning that restart or termination can sometimes take quite
  +a lot of time. Check out the <CODE>PERL_DESTRUCT_LEVEL=-1</CODE> option during the mod_perl <CODE>perl Makefile.PL</CODE> stage, which speeds this up and leads to more robust operation in the face
  +of problems, like running out of memory. It is only usable if no
  +significant cleanup has to be done by perl <CODE>END</CODE>
  +blocks and <CODE>DESTROY</CODE> methods when the child terminates, of course. What constitutes significant
  +cleanup? Any change of state outside of the current process that would not
  +be handled by the operating system itself. So committing database
  +transactions is significant but closing an ordinary file isn't.
  +
  +<P>
  +Some folks prefer to specify signals using numerical values, rather than
  +symbolics. If you are looking for these, check out your
  +<CODE>kill(3)</CODE> man page. My page points to <CODE>/usr/include/sys/signal.h</CODE>, the relevant entries are:
  +
  +<P>
  +<PRE>  #define SIGHUP     1    /* hangup, generated when terminal disconnects */ 
  +  #define SIGTERM   15    /* software termination signal */
  +  #define SIGUSR1   30    /* user defined signal 1 */
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Using_apachectl_to_control_the_s">Using apachectl to control the server</A></H1></CENTER>
  +<P>
  +Apache's distribution provides a nice script to control the server. It's
  +called <STRONG>apachectl</STRONG> and it's installed into the same location with httpd. In our scenario -
  +it's
  +<CODE>/usr/local/sbin/httpd_perl/apachectl</CODE>.
  +
  +<P>
  +Start httpd:
  +
  +<P>
  +<PRE>  % /usr/local/sbin/httpd_perl/apachectl start 
  +</PRE>
  +<P>
  +Stop httpd:
  +
  +<P>
  +<PRE>  % /usr/local/sbin/httpd_perl/apachectl stop
  +</PRE>
  +<P>
  +Restart httpd if running by sending a <STRONG>SIGHUP</STRONG> or start if not running:
  +
  +<P>
  +<PRE>  % /usr/local/sbin/httpd_perl/apachectl restart
  +</PRE>
  +<P>
  +Do a graceful restart by sending a <STRONG>SIGUSR1</STRONG> or start if not running:
  +
  +<P>
  +<PRE>  % /usr/local/sbin/httpd_perl/apachectl graceful    
  +</PRE>
  +<P>
  +Do a configuration syntax test:
  +
  +<P>
  +<PRE>  % /usr/local/sbin/httpd_perl/apachectl configtest 
  +</PRE>
  +<P>
  +Replace <CODE>httpd_perl</CODE> with <CODE>httpd_docs</CODE> in the above calls to control the <STRONG>httpd_docs</STRONG> server.
  +
  +<P>
  +There are other options for <STRONG>apachectl</STRONG>, use <CODE>help</CODE> option to see them all.
  +
  +<P>
  +It's important to understand that this script is based on the PID file
  +which is <CODE>PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid</CODE>. If you delete the file by hand - <STRONG>apachectl</STRONG> will fail to run.
  +
  +<P>
  +Also, notice that <STRONG>apachectl</STRONG> is suitable to use from within your Unix system's startup files so that
  +your web server is automatically restarted upon system reboot. Either copy
  +the <STRONG>apachectl</STRONG> file to the appropriate location (<CODE>/etc/rc.d/rc3.d/S99apache</CODE> works on my RedHat Linux system) or create a symlink with that name
  +pointing to the the canonical location. (If you do this, make certain that
  +the script is writable only by root -- the startup scripts have root
  +privileges during init processing, and you don't want to be opening any
  +security holes.)
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A></H1></CENTER>
  +<P>
  +You have prepared a new version of code, uploaded it into a production
  +server, restarted it and it doesn't work. What could be worse than that?
  +You also cannot go back, because you have overwritten the good working
  +code.
  +
  +<P>
  +It's quite easy to prevent it! Just don't overwrite the previous good
  +files!!! 
  +
  +<P>
  +Personally I do all updates on the live server with a following sequence.
  +Assume that the root directory lies in
  +<CODE>/home/httpd/perl/rel</CODE>. When I'm about to update the files I create a new directory <CODE>/home/httpd/perl/beta</CODE>, copy the old files from
  +<CODE>/home/httpd/perl/rel</CODE> and update it with new files I'm about to replace. The I do last sanity
  +checks (file permissions (read+executable), run <CODE>perl -c</CODE> on the new modules to make sure there no errors in them). When I think I'm
  +ready I do:
  +
  +<P>
  +<PRE>  % cd /home/httpd/perl
  +  % mv rel old; mv beta rel; stop; sleep 3; restart; err
  +</PRE>
  +<P>
  +Let's explain what I'm doing. First I use alises to make things faster:
  +
  +<P>
  +<PRE>  % alias | grep apachectl
  +  graceful        /usr/local/apache/bin/apachectl graceful
  +  rehup   /usr/local/apache/sbin/apachectl restart
  +  restart /usr/local/apache/bin/apachectl restart
  +  start   /usr/local/apache/bin/apachectl start
  +  stop    /usr/local/apache/bin/apachectl stop
  +  
  +  % alias err
  +  tail -f /usr/local/apache/logs/error_log
  +</PRE>
  +<P>
  +So I write all the commands in one line, separated with semicolon and only
  +then press <CODE>Enter</CODE> key. That ensures that if I suddenly get a connection lost (sadly but that
  +happens sometimes) I wouldn't leave the server down if only the <CODE>stop</CODE> command squeezed in. 
  +
  +<P>
  +I backup the old working directory in <CODE>old</CODE>, and move the new one instead. I stop the server, give it a few seconds to
  +shutdown (it might take even longer) and then do <CODE>restart</CODE> followed by immediate view of the tail of the <CODE>error_log</CODE> file in order to see that everything is OK. <CODE>apachectl</CODE> generates the status messages too early (e.g. on <CODE>stop</CODE> it says server has been stopped, while it's not yet, so don't rely on it,
  +rely on <CODE>error_log</CODE> file instead). Also you have noticed that I use <CODE>restart</CODE> and not just <CODE>start</CODE>. I do this for the same reason of Apache's long stopping times (it depends
  +on what you do with it of course!), so if you use <CODE>start</CODE> and Apache didn't release the port it listens to, the start would fail and <CODE>error_log</CODE> would tell that port is in use, e.g.:
  +
  +<P>
  +<PRE>  Address already in use: make_sock: could not bind to port 8080
  +</PRE>
  +<P>
  +But if you use <CODE>restart</CODE>, it will patiently wait for the server to quit and then will cleanly start
  +it.
  +
  +<P>
  +Now what happens if the new modules are broken? First of all, I see
  +immediately the indication of the problems reported at <CODE>error_log</CODE>
  +file, which I <CODE>tail -f</CODE> immediately after a restart command. That's easy, we just put everything as
  +it was before:
  +
  +<P>
  +<PRE>  % mv rel bad; mv old rel; stop; sleep 3; restart; err
  +</PRE>
  +<P>
  +And 99.9% that everything would be alright, and you have had only about 10
  +secs of downtime, which is pretty good!
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A></H1></CENTER>
  +<P>
  +What happens if you really must took down the server or disable the
  +scripts? This situation might happen when you need to do some maintanance
  +works on your database server, which you have to put down and which cause
  +all the scripts using this database server non-working. If you do nothing,
  +user will see either grey <CODE>The Error
  +has happened</CODE> or a better customized error message if you have added a code to trap and
  +customize the errors (See <A HREF="././porting.html#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
  +for the latter case)
  +
  +<P>
  +A much more user friendly approach is to confess to your users that you are
  +doing some maintainance works and plead for a paitience, promising that the
  +services will become fully functional in X minutes (it worth to keep the
  +promize!). There are a few ways to do that:
  +
  +<P>
  +First doesn't require messing with server and works when you have to
  +disable a script and not a module! Just prepare a little script like:
  +
  +<P>
  +<PRE>  /home/http/perl/construction.pl
  +  ----------------------------
  +  #!/usr/bin/perl -wT
  +  
  +  use strict;
  +  use CGI;
  +  my $q = new CGI;
  +  print $q-&gt;header,
  +  &quot;Sorry, the service is down for maintainance. 
  +   It will be back in a about 5-15 minutes.
  +   Please, bear with us.
  +   Thank you!&quot;;
  +</PRE>
  +<P>
  +And if now you have to disable a script at <CODE>/home/http/perl/chat.pl</CODE>, just do:
  +
  +<P>
  +<PRE>  % mv /home/http/perl/chat.pl /home/http/perl/chat.pl.orig
  +  % ln -s /home/http/perl/construction.pl /home/http/perl/chat.pl
  +</PRE>
  +<P>
  +Of course you server configuration should allow symbolic links for this
  +trick to work. Just make sure you have
  +
  +<P>
  +<PRE>  Options FollowSymLinks
  +</PRE>
  +<P>
  +directive in your <CODE>&lt;Location</CODE>&gt;/<CODE>&lt;Directory</CODE>&gt; section configuration.
  +
  +<P>
  +When done, it's easy to restore the previous setup. Just do:
  +
  +<P>
  +<PRE>  % mv /home/http/perl/chat.pl.orig /home/http/perl/chat.pl
  +</PRE>
  +<P>
  +and overwrite the symbolic link. Apache will automatically detect the
  +change and will use the moved script instead.
  +
  +<P>
  +Second approach, is changing the server configuration and configure a whole
  +directories to be handled by Contruction handler that you would write, e.g.
  +if you write something like:
  +
  +<P>
  +<PRE>  Construction.pm
  +  ---------------
  +  use strict;
  +  use CGI;
  +  use Apache::Constants;
  +  sub handler{
  +    my $q = new CGI;
  +    print $q-&gt;header,
  +    &quot;Sorry, the service is down for maintainance. 
  +     It will be back in a about 5-15 minutes.
  +     Please, bear with us.
  +     Thank you!&quot;;
  +    return OK;
  +  }
  +</PRE>
  +<P>
  +and put it in directory that in the server's <CODE>@INC</CODE>, to put down all your scripts at <CODE>/perl</CODE> you would replace:
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    [snip]
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +with
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Construction
  +    [snip]
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +Now restart the server and your user will be happy to know that you are
  +working on a much better version of the service and it worth for them to go
  +read slashdot.org and come back in 10 minutes.
  +
  +<P>
  +If you need to disable a location handled by some module, the second
  +approach would work just as well.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="SUID_start_up_scripts">SUID start-up scripts</A></H1></CENTER>
  +<P>
  +For those who wants to use <STRONG>SUID</STRONG> startup script, here is an example for you. This script is <STRONG>SUID</STRONG> to <STRONG>root</STRONG>, and should be executable only by members of some special group at your
  +site. Note the 10th line, which ``fixes an obscure error when starting
  +apache/mod_perl'' by setting the real to the effective UID. As others have
  +pointed out, it is the mismatch between the real and the effective UIDs
  +that causes Perl to croak on the -e switch.
  +
  +<P>
  +Note that you must be using a version of Perl that recognizes and emulates
  +the suid bits in order for this to work. The script will do different
  +things depending on whether it is named <CODE>start_http</CODE>,
  +<CODE>stop_http</CODE> or <CODE>restart_http</CODE>. You can use symbolic links for this purpose.
  +
  +<P>
  +<PRE> #!/usr/bin/perl
  + 
  + # These constants will need to be adjusted.
  + $PID_FILE = '/home/www/logs/httpd.pid';
  + $HTTPD = '/home/www/httpd -d /home/www';
  + 
  + # These prevent taint warnings while running suid
  + $ENV{PATH}='/bin:/usr/bin';
  + $ENV{IFS}='';
  + 
  + # This sets the real to the effective ID, and prevents
  + # an obscure error when starting apache/mod_perl
  + $&lt; = $&gt;;
  + $( = $) = 0; # set the group to root too
  + 
  + # Do different things depending on our name
  + ($name) = $0 =~ m|([^/]+)$|;
  + 
  + if ($name eq 'start_http') {
  +     system $HTTPD and die &quot;Unable to start HTTP&quot;;
  +     print &quot;HTTP started.\n&quot;;
  +     exit 0;
  + }
  + 
  + # extract the process id and confirm that it is numeric
  + $pid = `cat $PID_FILE`;
  + $pid =~ /(\d+)/ or die &quot;PID $pid not numeric&quot;;
  + $pid = $1;
  + 
  + if ($name eq 'stop_http') {
  +     kill 'TERM',$pid or die &quot;Unable to signal HTTP&quot;;
  +     print &quot;HTTP stopped.\n&quot;;
  +     exit 0;
  + }
  + 
  + if ($name eq 'restart_http') {
  +     kill 'HUP',$pid or die &quot;Unable to signal HTTP&quot;;
  +     print &quot;HTTP restarted.\n&quot;;
  +     exit 0;
  + }
  + 
  + die &quot;Script must be named start_http, stop_http, or restart_http.\n&quot;;
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A></H1></CENTER>
  +<P>
  +With mod_perl many things can happen to your server. The worst one is the
  +possibility that the server will die when you will be not around. As with
  +any other critical service you need to run some kind of watchdog.
  +
  +<P>
  +One simple solution is to use a slightly modified <STRONG>apachectl</STRONG> script which I called apache.watchdog and to put it into the crontab to be
  +called every 30 minutes or even every minute - if it's so critical to make
  +sure the server will be up all the time.
  +
  +<P>
  +The crontab entry:
  +
  +<P>
  +<PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
  +</PRE>
  +<P>
  +The script:
  +
  +<P>
  +<PRE>  #!/bin/sh
  +    
  +  # this script is a watchdog to see whether the server is online
  +  # It tries to restart the server if it's
  +  # down and sends an email alert to admin 
  +  
  +  # admin's email
  +  EMAIL=webmaster@somewhere.far
  +  #EMAIL=root@localhost
  +    
  +  # the path to your PID file
  +  PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid
  +    
  +  # the path to your httpd binary, including options if necessary
  +  HTTPD=/usr/local/sbin/httpd_perl/httpd_perl
  +        
  +  # check for pidfile
  +  if [ -f $PIDFILE ] ; then
  +    PID=`cat $PIDFILE`
  +    
  +    if kill -0 $PID; then
  +      STATUS=&quot;httpd (pid $PID) running&quot;
  +      RUNNING=1
  +    else
  +      STATUS=&quot;httpd (pid $PID?) not running&quot;
  +      RUNNING=0
  +    fi
  +  else
  +    STATUS=&quot;httpd (no pid file) not running&quot;
  +    RUNNING=0
  +  fi
  +      
  +  if [ $RUNNING -eq 0 ]; then
  +    echo &quot;$0 $ARG: httpd not running, trying to start&quot;
  +    if $HTTPD ; then
  +      echo &quot;$0 $ARG: httpd started&quot;
  +      mail $EMAIL -s &quot;$0 $ARG: httpd started&quot; &lt;/dev/null &gt;&amp; /dev/null
  +    else
  +      echo &quot;$0 $ARG: httpd could not be started&quot;
  +      mail $EMAIL -s &quot;$0 $ARG: httpd could not be started&quot; &lt;/dev/null &gt;&amp; /dev/null
  +    fi
  +  fi
  +</PRE>
  +<P>
  +Another approach, probably even more practical, is to use the cool <CODE>LWP</CODE>
  +perl package , to test the server by trying to fetch some document (script)
  +served by the server. Why is it more practical? Because, while server can
  +be up as a process, it can be stuck and not working, So failing to get the
  +document will trigger restart, and ``probably'' the problem will go away.
  +(Just replace <CODE>start</CODE> with <CODE>restart</CODE> in the <CODE>$restart_command</CODE>
  +below.
  +
  +<P>
  +Again we put this script into a crontab to call it every 30 minutes.
  +Personally I call it every minute, to fetch some very light script. Why so
  +often? If your server starts to spin and trash your disk's space with
  +multiply error messages, in a 5 minutes you might run out of free space,
  +which might bring your system to its knees. And most chances that no other
  +child will be able to serve requests, since the system will be too busy,
  +writing to an <CODE>error_log</CODE> file. Think big -- if you are running a heavy service, which is very fast,
  +since you are running under mod_perl, adding one more request every minute,
  +will be not felt by the server at all.
  +
  +<P>
  +So we end up with crontab entry:
  +
  +<P>
  +<PRE>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
  +</PRE>
  +<P>
  +And the watchdog itself:
  +
  +<P>
  +<PRE>  #!/usr/local/bin/perl -w
  +  
  +  use strict;
  +  use diagnostics;
  +  use URI::URL;
  +  use LWP::MediaTypes qw(media_suffix);
  +  
  +  my $VERSION = '0.01';
  +  use vars qw($ua $proxy);
  +  $proxy = '';    
  +</PRE>
  +<P>
  +<PRE>  require LWP::UserAgent;
  +  use HTTP::Status;
  +  
  +  ###### Config ########
  +  my $test_script_url = '<A HREF="http://www.stas.com:81/perl/test.pl">http://www.stas.com:81/perl/test.pl</A>';
  +  my $monitor_email   = 'root@localhost';
  +  my $restart_command = '/usr/local/sbin/httpd_perl/apachectl restart';
  +  my $mail_program    = '/usr/lib/sendmail -t -n';
  +  ######################
  +  
  +  $ua  = new LWP::UserAgent;
  +  $ua-&gt;agent(&quot;$0/Stas &quot; . $ua-&gt;agent);
  +  # Uncomment the proxy if you don't use it!
  +  #  $proxy=&quot;<A HREF="http://www-proxy.com&quot">http://www-proxy.com&quot</A>;;
  +  $ua-&gt;proxy('http', $proxy) if $proxy;
  +  
  +  # If returns '1' it's we are alive
  +  exit 1 if checkurl($test_script_url);
  +  
  +  # We have got the problem - the server seems to be down. Try to
  +  # restart it. 
  +  my $status = system $restart_command;
  +  #  print &quot;Status $status\n&quot;;
  +  
  +  my $message = ($status == 0) 
  +              ? &quot;Server was down and successfully restarted!&quot; 
  +              : &quot;Server is down. Can't restart.&quot;;
  +    
  +  my $subject = ($status == 0) 
  +              ? &quot;Attention! Webserver restarted&quot;
  +              : &quot;Attention! Webserver is down. can't restart&quot;;
  +  
  +  # email the monitoring person
  +  my $to = $monitor_email;
  +  my $from = $monitor_email;
  +  send_mail($from,$to,$subject,$message);
  +  
  +  # input:  URL to check 
  +  # output: 1 if success, o for fail  
  +  #######################  
  +  sub checkurl{
  +    my ($url) = @_;
  +  
  +    # Fetch document 
  +    my $res = $ua-&gt;request(HTTP::Request-&gt;new(GET =&gt; $url));
  +  
  +    # Check the result status
  +    return 1 if is_success($res-&gt;code);
  +  
  +    # failed
  +    return 0;
  +  } #  end of sub checkurl
  +  
  +  # sends email about the problem 
  +  #######################  
  +  sub send_mail{
  +    my($from,$to,$subject,$messagebody) = @_;
  +  
  +    open MAIL, &quot;|$mail_program&quot;
  +        or die &quot;Can't open a pipe to a $mail_program :$!\n&quot;;
  +   
  +    print MAIL &lt;&lt;__END_OF_MAIL__;
  +  To: $to
  +  From: $from
  +  Subject: $subject
  +  
  +  $messagebody
  +  
  +  __END_OF_MAIL__
  +  
  +    close MAIL;
  +  } 
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
  +<P>
  +Often while developing new code, you will want to run the server in single
  +process mode. See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it works Sometimes it does Not</A> and <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>
  +Running in single process mode inhibits the server from ``daemonizing'',
  +allowing you to run it more easily under debugger control.
  +
  +<P>
  +<PRE>  % /usr/local/sbin/httpd_perl/httpd_perl -X
  +</PRE>
  +<P>
  +When you execute the above the server will run in the fg (foreground) of
  +the shell you have called it from. So to kill you just kill it with
  +<STRONG>Ctrl-C</STRONG>.
  +
  +<P>
  +Note that in <CODE>-X</CODE> mode the server will run very slowly while fetching images. If you use
  +Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
  +keep them open. Because there is only one server process listening, each
  +connection has to time-out before the next succeeds. Turn off
  +<CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect while developing or you can press <STRONG>STOP</STRONG> after a few seconds (assuming you use the image size params, so the
  +Netscape will be able to render the rest of the page).
  +
  +<P>
  +In addition you should know that when running with <CODE>-X</CODE> you will not see any control messages that the parent server normally
  +writes to the error_log. (Like ``server started, server stopped and etc''.)
  +Since
  +<CODE>httpd -X</CODE> causes the server to handle all requests itself, without forking any
  +children, there is no controlling parent to write status messages.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</A></H1></CENTER>
  +<P>
  +If you are the only developer working on the specific server:port - you
  +have no problems, since you have a complete control over the server.
  +However, many times you have a group of developers who need to concurrently
  +develop their own mod_perl scripts. This means that each one will want to
  +have control over the server - to kill it, to run it in single server mode,
  +to restart it again, etc., as well to have control over the location of the
  +log files and other configuration settings like <STRONG>MaxClients</STRONG>, etc. You can work around this problem by preparing a few httpd.conf file
  +and forcing each developer to use:
  +
  +<P>
  +<PRE>  httpd_perl -f /path/to/httpd.conf  
  +</PRE>
  +<P>
  +I have approached it in other way. I have used the <CODE>-Dparameter</CODE>
  +startup option of the server. I call my version of the server
  +
  +<P>
  +<PRE>  % http_perl -Dsbekman
  +</PRE>
  +<P>
  +In <CODE>httpd.conf</CODE> I wrote:
  +
  +<P>
  +<PRE>  # Personal development Server for sbekman
  +  # sbekman use the server running on port 8000
  +  &lt;IfDefine sbekman&gt;
  +  Port 8000
  +  PidFile /usr/local/var/httpd_perl/run/httpd.pid.sbekman
  +  ErrorLog /usr/local/var/httpd_perl/logs/error_log.sbekman
  +  Timeout 300
  +  KeepAlive On
  +  MinSpareServers 2
  +  MaxSpareServers 2
  +  StartServers 1
  +  MaxClients 3
  +  MaxRequestsPerChild 15
  +  &lt;/IfDefine&gt;
  +  
  +  # Personal development Server for userfoo
  +  # userfoo use the server running on port 8001
  +  &lt;IfDefine userfoo&gt;
  +  Port 8001
  +  PidFile /usr/local/var/httpd_perl/run/httpd.pid.userfoo
  +  ErrorLog /usr/local/var/httpd_perl/logs/error_log.userfoo
  +  Timeout 300
  +  KeepAlive Off
  +  MinSpareServers 1
  +  MaxSpareServers 2
  +  StartServers 1
  +  MaxClients 5
  +  MaxRequestsPerChild 0
  +  &lt;/IfDefine&gt;
  +</PRE>
  +<P>
  +What we have achieved with this technique: Full control over start/stop,
  +number of children, separate error log file, and port selection. This saves
  +me from getting called every few minutes - ``Stas, I'm going to restart the
  +server''.
  +
  +<P>
  +To make things even easier. (In the above technique, you have to discover
  +the PID of your parent <CODE>httpd_perl</CODE> process - written in
  +<CODE>/usr/local/var/httpd_perl/run/httpd.pid.userfoo</CODE>) . We change the
  +<STRONG>apachectl</STRONG> script to do the work for us. We make a copy for each developer called <STRONG>apachectl.username</STRONG> and we change 2 lines in script:
  +
  +<P>
  +<PRE>  PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid.sbekman
  +  HTTPD='/usr/local/sbin/httpd_perl/httpd_perl -Dsbekman'
  +</PRE>
  +<P>
  +Of course you think you can use only one control file and know who is
  +calling by using uid, but since you have to be root to start the server -
  +it is not so simple.
  +
  +<P>
  +The last thing was to let developers an option to run in single process
  +mode by:
  +
  +<P>
  +<PRE>  /usr/local/sbin/httpd_perl/httpd_perl -Dsbekman -X
  +</PRE>
  +<P>
  +In addition to making life easier, we decided to use relative links
  +everywhere in the static docs (including the calls to CGIs). You may ask
  +how using the relative link you will get to the right server? Very simple -
  +we have utilized the mod_rewrite to solve our problems:
  +
  +<P>
  +In <CODE>access.conf</CODE> of the <CODE>httpd_docs</CODE> server we have the following code: (you have to configure your <CODE>httpd_docs</CODE> server with
  +<CODE>--enable-module=rewrite</CODE> )
  +
  +<P>
  +<PRE>  # sbekman' server
  +  # port = 8000
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteCond  %{REMOTE_ADDR} 123.34.45.56
  +  RewriteRule ^(.*)           <A HREF="http://nowhere.com:8000/">http://nowhere.com:8000/</A>$1 [R,L]
  +  
  +  # userfoo's server
  +  # port = 8001
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteCond  %{REMOTE_ADDR} 123.34.45.57
  +  RewriteRule ^(.*)           <A HREF="http://nowhere.com:8001/">http://nowhere.com:8001/</A>$1 [R,L]
  +  
  +  # all the rest
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteRule ^(.*)           <A HREF="http://nowhere.com:81/">http://nowhere.com:81/</A>$1 [R]
  +  
  +</PRE>
  +<P>
  +where IP numbers are the IPs of the developer client machines (where they
  +are running their web browser.) (I have tried to use
  +<CODE>REMOTE_USER</CODE> since we have all the users authenticated but it did not work for me)
  +
  +<P>
  +So if I have a relative URL like <CODE>/perl/test.pl</CODE> written in some html or even <CODE>http://www.nowhere.com/perl/test.pl</CODE> in my case (user at machine of <CODE>sbekman</CODE>) it will be redirected by <CODE>httpd_docs</CODE> to
  +<CODE>http://www.nowhere.com:8000/perl/test.pl</CODE>.
  +
  +<P>
  +Of course you have another problem: The CGI generates some html, which
  +should be called again. If it generates a URL with hard coded PORT the
  +above scheme will not work. There 2 solutions:
  +
  +<P>
  +First, generate relative URL so it will reuse the technique above, with
  +redirect (which is transparent for user) but it will not work if you have
  +something to <CODE>POST</CODE> (redirect looses all the data!).
  +
  +<P>
  +Second, use a general configuration module which generates a correct full
  +URL according to <CODE>REMOTE_USER</CODE>, so if <CODE>$ENV{REMOTE_USER} eq
  +'sbekman'</CODE>, I return <CODE>http://www.nowhere.com:8000/perl/</CODE> as
  +<CODE>cgi_base_url</CODE>. Again this will work if the user is authenticated.
  +
  +<P>
  +All this is good for development. It is better to use the full URLs in
  +production, since if you have a static form and the <CODE>Action</CODE> is relative but the static document located on another server, pressing the
  +form's submit will cause a redirect to mod_perl server, but all the form's
  +data will be lost during the redirect.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A></H1></CENTER>
  +<P>
  +Many times you start off debugging your script by running it from your
  +favorite shell. Sometimes you encounter a very weird situation when script
  +runs from the shell but dies when called as a CGI. The real problem lies in
  +the difference between the environment that is being used by your server
  +and your shell. An example can be a different perl path or having <CODE>PERL5LIB</CODE> env variable which includes paths that are not in the <CODE>@INC</CODE> of the perl compiled with mod_perl server and configured during the
  +startup.
  +
  +<P>
  +The best debugging approach is to write a wrapper that emulates the exact
  +environment of the server, by first deleting the environment variables like <CODE>PERL5LIB</CODE> and calling the same perl binary that it is being used by the server. Next,
  +set the environment identical to the server's by copying the perl run
  +directives from server startup and configuration files. It will also allow
  +you to remove completely the first line of the script - since mod_perl
  +skips it and the wrapper knows how to call the script.
  +
  +<P>
  +Below is the example of such a script. Note that we force the <CODE>-Tw</CODE>
  +when we call the real script. (I have also added the ability to pass
  +params, which will not happen when you call the cgi from the web)
  +
  +<P>
  +<PRE>  #!/usr/local/bin/perl -w    
  +   
  +  # This is a wrapper example 
  +   
  +  # It simulates the web server environment by setting the @INC and other
  +  # stuff, so what will run under this wrapper will run under web and
  +  # vice versa. 
  +  
  +  #
  +  # Usage: wrap.pl some_cgi.pl
  +  #
  +  
  +  BEGIN{
  +    use vars qw($basedir);
  +    $basedir = &quot;/usr/local&quot;;
  +  
  +    # we want to make a complete emulation, 
  +    # so we must remove the user's environment
  +    @INC = ();
  +  
  +    # local perl libs
  +    push @INC,
  +      qw($basedir/lib/perl5/5.00502/aix
  +         $basedir/lib/perl5/5.00502
  +         $basedir/lib/perl5/site_perl/5.005/aix
  +         $basedir/lib/perl5/site_perl/5.005
  +        );
  +  }
  +  
  +  use strict;
  +  use File::Basename;
  +  
  +    # process the passed params
  +  my $cgi = shift || '';
  +  my $params = (@ARGV) ? join(&quot; &quot;, @ARGV) : '';
  +  
  +  die &quot;Usage:\n\t$0 some_cgi.pl\n&quot; unless $cgi;
  +  
  +    # Set the environment
  +  my $PERL5LIB = join &quot;:&quot;, @INC;
  +  
  +    # if the path includes the directory 
  +    # we extract it and chdir there
  +  if ($cgi =~ m|/|) {
  +    my $dirname = dirname($cgi);
  +    chdir $dirname or die &quot;Can't chdir to $dirname: $! \n&quot;;
  +    $cgi =~ m|$dirname/(.*)|;
  +    $cgi = $1;
  +  }
  +  
  +    # run the cgi from the script's directory
  +    # Note that we invoke warnings and Taint mode ON!!!
  +  system qq{$basedir/bin/perl -I$PERL5LIB -Tw $cgi $params};
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Log_Rotation">Log Rotation</A></H1></CENTER>
  +<P>
  +A little bit off topic but good to know and use with mod_perl where your
  +error_log can grow at a 10-100Mb per day rate if your scripts spit out lots
  +of warnings...
  +
  +<P>
  +To rotate the logs do:
  +
  +<P>
  +<PRE>  mv access_log access_log.renamed
  +  kill -HUP `cat httpd.pid`
  +  sleep 10; # allow some children to complete requests and logging
  +  # now it's safe to use access_log.renamed
  +  .....
  +</PRE>
  +<P>
  +The effect of <STRONG>SIGUSR1</STRONG> and <STRONG>SIGHUP</STRONG> is detailed in: <A
  +HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
  +.
  +
  +<P>
  +I use this script:
  +
  +<P>
  +<PRE>  #!/usr/local/bin/perl -Tw
  +  
  +  # this script does a log rotation. Called from crontab.
  +  
  +  use strict;
  +  $ENV{PATH}='/bin:/usr/bin';
  +  
  +  ### configuration
  +  my @logfiles = qw(access_log error_log);
  +  umask 0;
  +  my $server = &quot;httpd_perl&quot;;
  +  my $logs_dir = &quot;/usr/local/var/$server/logs&quot;;
  +  my $restart_command = &quot;/usr/local/sbin/$server/apachectl restart&quot;;
  +  my $gzip_exec = &quot;/usr/bin/gzip&quot;;
  +  
  +  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  +  my $time = sprintf &quot;%0.2d.%0.2d.%0.2d-%0.2d.%0.2d.%0.2d&quot;, $year,++$mon,$mday,$hour,$min,$sec;
  +  $^I = &quot;.&quot;.$time;
  +  
  +  # rename log files
  +  chdir $logs_dir;
  +  @ARGV = @logfiles;
  +  while (&lt;&gt;) {
  +    close ARGV;
  +  }
  +  
  +  # now restart the server so the logs will be restarted
  +  system $restart_command;
  +  
  +  # compress log files
  +  foreach (@logfiles) {
  +      system &quot;$gzip_exec $_.$time&quot;;
  +  }
  +</PRE>
  +<P>
  +Randal L. Schwartz contributed this:
  +
  +<BLOCKQUOTE>
  +
  +<P>
  +Cron fires off setuid script called log-roller that looks like this:
  +
  +<P>
  +<PRE>    #!/usr/bin/perl -Tw
  +    use strict;
  +    use File::Basename;
  +    
  +    $ENV{PATH} = &quot;/usr/ucb:/bin:/usr/bin&quot;;
  +    
  +    my $ROOT = &quot;/WWW/apache&quot;; # names are relative to this
  +    my $CONF = &quot;$ROOT/conf/httpd.conf&quot;; # master conf
  +    my $MIDNIGHT = &quot;MIDNIGHT&quot;;  # name of program in each logdir
  +    
  +    my ($user_id, $group_id, $pidfile); # will be set during parse of conf
  +    die &quot;not running as root&quot; if $&gt;;
  +    
  +    chdir $ROOT or die &quot;Cannot chdir $ROOT: $!&quot;;
  +    
  +    my %midnights;
  +    open CONF, &quot;&lt;$CONF&quot; or die &quot;Cannot open $CONF: $!&quot;;
  +    while (&lt;CONF&gt;) {
  +      if (/^User (\w+)/i) {
  +        $user_id = getpwnam($1);
  +        next;
  +      }
  +      if (/^Group (\w+)/i) {
  +        $group_id = getgrnam($1);
  +        next;
  +      }
  +      if (/^PidFile (.*)/i) {
  +        $pidfile = $1;
  +        next;
  +      }
  +     next unless /^ErrorLog (.*)/i;
  +      my $midnight = (dirname $1).&quot;/$MIDNIGHT&quot;;
  +      next unless -x $midnight;
  +      $midnights{$midnight}++;
  +    }
  +    close CONF;
  +    
  +    die &quot;missing User definition&quot; unless defined $user_id;
  +    die &quot;missing Group definition&quot; unless defined $group_id;
  +    die &quot;missing PidFile definition&quot; unless defined $pidfile;
  +    
  +    open PID, $pidfile or die &quot;Cannot open $pidfile: $!&quot;;
  +    &lt;PID&gt; =~ /(\d+)/;
  +    my $httpd_pid = $1;
  +    close PID;
  +    die &quot;missing pid definition&quot; unless defined $httpd_pid and $httpd_pid;
  +    kill 0, $httpd_pid or die &quot;cannot find pid $httpd_pid: $!&quot;;
  +    
  +    
  +    for (sort keys %midnights) {
  +      defined(my $pid = fork) or die &quot;cannot fork: $!&quot;;
  +      if ($pid) {
  +        ## parent:
  +        waitpid $pid, 0;
  +      } else {
  +        my $dir = dirname $_;
  +        ($(,$)) = ($group_id,$group_id);
  +        ($&lt;,$&gt;) = ($user_id,$user_id);
  +        chdir $dir or die &quot;cannot chdir $dir: $!&quot;;
  +        exec &quot;./$MIDNIGHT&quot;;
  +        die &quot;cannot exec $MIDNIGHT: $!&quot;;
  +      }
  +    }
  +    
  +    kill 1, $httpd_pid or die &quot;Cannot sighup $httpd_pid: $!&quot;;
  +</PRE>
  +<P>
  +And then individual MIDNIGHT scripts can look like this:
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
  +<PRE>    #!/usr/bin/perl -Tw
  +    use strict;
  +    
  +    die &quot;bad guy&quot; unless getpwuid($&lt;) =~ /^(root|nobody)$/;
  +    my @LOGFILES = qw(access_log error_log);
  +    umask 0;
  +    $^I = &quot;.&quot;.time;
  +    @ARGV = @LOGFILES;
  +    while (&lt;&gt;) {
  +      close ARGV;
  +    }
  +</PRE>
   <P>
  -This new document was born because some problems come up so often on the
  -mailing list that should be stressed in the guide as one of the most
  -important things to read/beware of. So I have tried to enlist them in this
  -document. If you think some important problem that is being reported
  -frequently on the list and covered in the guide but not included below,
  -please tell.
  +Can you spot the security holes? Our trusted user base can't or won't. :)
  +But these shouldn't be used in hostile situations.
  +
  +</BLOCKQUOTE>
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A></H1></CENTER>
  +<CENTER><H1><A NAME="Preventing_from_modperl_process_">Preventing from modperl process from going wild</A></H1></CENTER>
   <P>
  -See <A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +Sometimes calling an undefined subroutine in a module can cause a tight
  +loop that consumes all memory. Here is a way to catch such errors. Define
  +an autoload subroutine:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A></H1></CENTER>
  +<PRE>  sub UNIVERSAL::AUTOLOAD {
  +    my $class = shift;
  +    warn &quot;$class can't \$UNIVERSAL::AUTOLOAD!\n&quot;;
  +  }
  +</PRE>
   <P>
  -See <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
  +It will produce a nice error in error_log, giving the line number of the
  +call and the name of the undefined subroutine.
  +
  +<P>
  +Sometimes an error happens and causes the server to write millions of lines
  +into your <CODE>error_log</CODE> file and in a few minutes to put your server down on its knees. For example
  +I get an error <CODE>Callback called
  +exit</CODE> show up in my error_log file many times. The <CODE>error_log</CODE> file grows to 300 Mbytes in size in a few minutes. You should run a cron
  +job to make sure this does not happen and if it does to take care of it.
  +Andreas J. Koenig is running this shell script every minute:
   
  +<P>
  +<PRE>  S=`ls -s /usr/local/apache/logs/error_log | awk '{print $1}'`
  +  if [ &quot;$S&quot; -gt 100000 ] ; then
  +    mv  /usr/local/apache/logs/error_log /usr/local/apache/logs/error_log.old
  +    /etc/rc.d/init.d/httpd restart
  +    date | /bin/mail -s &quot;error_log $S kB on inx&quot; myemail@domain.com
  +  fi
  +</PRE>
  +<P>
  +It seems that his script will trigger restart every minute, since once the
  +logfile grows to be of 100000 lines, it will stay of this size, unless you
  +remove or rename it, before you do restart. On my server I run a watchdog
  +every five minutes which restarts the server if it is getting stuck (it
  +always works since when some modperl child process goes wild, the I/O it
  +causes is so heavy that other brother processes cannot normally to serve
  +the requests.) See <A HREF="././control.html#Monitoring_the_Server_A_watchdo">Monitoring the Server</A> for more hints.
   
  +<P>
  +Also check out the daemontools from <A
  +HREF="ftp://koobera.math.uic.edu/www/daemontools.html">ftp://koobera.math.uic.edu/www/daemontools.html</A>
  +:
   
  +<P>
  +<PRE>  ,-----
  +  | cyclog writes a log to disk. It automatically synchronizes the log
  +  | every 100KB (by default) to guarantee data integrity after a crash. It
  +  | automatically rotates the log to keep it below 1MB (by default). If
  +  | the disk fills up, cyclog pauses and then tries again, without losing
  +  | any data.
  +  `-----
  +</PRE>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -11616,7 +14507,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]
  +	     [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -11629,7 +14520,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 07/09/1999
  +	     <BR>Last Modified at 10/15/1999
         </FONT>
       </B>
     </TD>
  @@ -11656,7 +14547,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Controlling and Monitoring the Server</TITLE>
  +   <TITLE>mod_perl guide: Things obvious to others, but not to you</TITLE>
      <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
      <META NAME="Author" CONTENT="Stas Bekman">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  @@ -11675,22 +14566,29 @@
   <H1 ALIGN=CENTER>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Controlling and Monitoring the Server</H1>
  +Things obvious to others, but not to you</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Restarting_techniques">Restarting techniques</A>
  -	<LI><A HREF="#Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A>
  -	<LI><A HREF="#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
  -	<LI><A HREF="#SUID_start_up_scripts">SUID start-up scripts</A>
  -	<LI><A HREF="#Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A>
  -	<LI><A HREF="#Running_server_in_a_single_mode">Running server in a single mode</A>
  -	<LI><A HREF="#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
  -	<LI><A HREF="#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
  -	<LI><A HREF="#Log_Rotation">Log Rotation</A>
  -	<LI><A HREF="#Preventing_from_modperl_process_">Preventing from modperl process from going wild</A>
  +	<LI><A HREF="#Coverage">Coverage</A>
  +	<LI><A HREF="#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
  +	<UL>
  +
  +		<LI><A HREF="#The_poison">The poison</A>
  +		<LI><A HREF="#The_diagnosis">The diagnosis</A>
  +		<LI><A HREF="#The_remedy">The remedy</A>
  +		<LI><A HREF="#Additional_reading_references">Additional reading references</A>
  +	</UL>
  +
  +	<LI><A HREF="#Compiled_Regular_Expressions">Compiled Regular Expressions </A>
  +	<LI><A HREF="#Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A>
  +	<LI><A HREF="#_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A>
  +	<LI><A HREF="#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>
  +	<LI><A HREF="#Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A>
  +	<LI><A HREF="#Where_do_the_warnings_errors_go_">Where do the warnings/errors go?</A>
  +	<LI><A HREF="#Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -11716,894 +14614,640 @@
   	       <HR>
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<P>
  -<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
  -<P>
  -All of these techniques require that you know the server PID (Process ID).
  -The easiest way to find the PID is to look it up in the <CODE>httpd.pid</CODE> file. With my configuration it exists as
  -<CODE>/usr/local/var/httpd_perl/run/httpd.pid</CODE>. It's easy to discover where to look at, by checking out the httpd.conf
  -file. Open the file and locate the entry <CODE>PidFile</CODE>:
  -
  -<P>
  -<PRE>  PidFile /usr/local/var/httpd_perl/run/httpd.pid
  -</PRE>
  -<P>
  -Another way is to use the <CODE>ps</CODE> and <CODE>grep</CODE> utilities:
  -
  -<P>
  -<PRE>  % ps auxc | grep httpd_perl
  -</PRE>
  -<P>
  -or maybe:
  -
  -<P>
  -<PRE>  % ps -ef | grep httpd_perl
  -</PRE>
  -<P>
  -This will produce a list of all <CODE>httpd_perl</CODE> (the parent and the children) processes. You are looking for the parent
  -process. If you run your server as root - you will easily locate it, since
  -it belongs to root. If you run the server as user (when you <A HREF="././install.html#Is_it_possible_to_install_and_us">don't have a root access</A>, most likely all the processes will belong to that user (unless defined
  -differently in the
  -<CODE>httpd.conf</CODE>), but it's still easy to know 'who is the parent' -- the one of the
  -smallest size...
  -
  -<P>
  -You will notice many <CODE>httpd_perl</CODE> executables running on your system, but you should not send signals to any
  -of them except the parent, whose pid is in the <CODE>PidFile</CODE>. That is to say you shouldn't ever need to send signals to any process
  -except the parent. There are three signals that you can send the parent: <STRONG>TERM</STRONG>, <STRONG>HUP</STRONG>, and <STRONG>USR1</STRONG>.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A></H1></CENTER>
  -<P>
  -We will concentrate here on the implications of sending these signals to a
  -mod_perl enabled server. For documentation on the implications of sending
  -these signals to a plain Apache server see <A
  -HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
  -.
  -
  -<DL>
  -<P><DT><STRONG><A NAME="item_TERM">TERM Signal: stop now</A></STRONG><DD>
  -<P>
  -Sending the <STRONG>TERM</STRONG> signal to the parent causes it to immediately attempt to kill off all of
  -its children. This process may take several seconds to complete, following
  -which the parent itself exits. Any requests in progress are terminated, and
  -no further requests are served.
  -
  -<P>
  -That's the moment that the accumulated <CODE>END</CODE> blocks will be executed! Note that if you use <CODE>Apache::Registry</CODE> or <CODE>Apache::PerlRun</CODE>, then
  -<CODE>END</CODE> blocks are being executed upon each request (at the end).
  -
  -<P><DT><STRONG><A NAME="item_HUP">HUP Signal: restart now</A></STRONG><DD>
  -<P>
  -Sending the <STRONG>HUP</STRONG> signal to the parent causes it to kill off its children like in <STRONG>TERM</STRONG> (Any requests in progress are terminated) but the parent doesn't exit. It
  -re-reads its configuration files, and re-opens any log files. Then it
  -spawns a new set of children and continues serving hits.
  -
  -<P>
  -The server will reread its configuration files, flush all the compiled and
  -preloaded modules, and rerun any startup files. It's equivalent to
  -stopping, then restarting a server.
  -
  -<P>
  -Note: If your configuration file has errors in it when you issue a restart
  -then your parent will not restart but exit with an error. See below for a
  -method of avoiding this.
  -
  -<P><DT><STRONG><A NAME="item_USR1">USR1 Signal: graceful restart</A></STRONG><DD>
  -<P>
  -The <STRONG>USR1</STRONG> signal causes the parent process to advise the children to exit after their
  -current request (or to exit immediately if they're not serving anything).
  -The parent re-reads its configuration files and re-opens its log files. As
  -each child dies off the parent replaces it with a child from the new
  -generation of the configuration, which begins serving new requests
  -immediately. 
  -
  -<P>
  -The only difference between <STRONG>USR1</STRONG> and <STRONG>HUP</STRONG> is that <STRONG>USR1</STRONG> allows children to complete any in-progress request prior to killing them
  -off.
  -
  -<P>
  -By default, if a server is restarted (ala <CODE>kill -USR1 `cat
  -logs/httpd.pid`</CODE> or with <STRONG>HUP</STRONG> signal), Perl scripts and modules are not reloaded. To reload <STRONG>PerlRequire</STRONG>'s, <STRONG>PerlModule</STRONG>'s, other
  -<CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache, enable with this command:
  -
  -<P>
  -<PRE> PerlFreshRestart On              (in httpd.conf) 
  -</PRE>
  -<P>
  -Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
  -
  -</DL>
   <P>
  -It's worth mentioning that restart or termination can sometimes take quite
  -a lot of time. Check out the <CODE>PERL_DESTRUCT_LEVEL=-1</CODE> option during the mod_perl <CODE>perl Makefile.PL</CODE> stage, which speeds this up and leads to more robust operation in the face
  -of problems, like running out of memory. It is only usable if no
  -significant cleanup has to be done by perl <CODE>END</CODE>
  -blocks and <CODE>DESTROY</CODE> methods when the child terminates, of course. What constitutes significant
  -cleanup? Any change of state outside of the current process that would not
  -be handled by the operating system itself. So committing database
  -transactions is significant but closing an ordinary file isn't.
  -
  +<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
   <P>
  -Some folks prefer to specify signals using numerical values, rather than
  -symbolics. If you are looking for these, check out your
  -<CODE>kill(3)</CODE> man page. My page points to <CODE>/usr/include/sys/signal.h</CODE>, the relevant entries are:
  +This document describes ``special'' traps you may encounter when running
  +your plain CGIs under <CODE>Apache::Registry</CODE> and <CODE>Apache::PerlRun</CODE>.
   
   <P>
  -<PRE>  #define SIGHUP     1    /* hangup, generated when terminal disconnects */ 
  -  #define SIGTERM   15    /* software termination signal */
  -  #define SIGUSR1   30    /* user defined signal 1 */
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Using_apachectl_to_control_the_s">Using apachectl to control the server</A></H1></CENTER>
  -<P>
  -Apache's distribution provides a nice script to control the server. It's
  -called <STRONG>apachectl</STRONG> and it's installed into the same location with httpd. In our scenario -
  -it's
  -<CODE>/usr/local/sbin/httpd_perl/apachectl</CODE>.
  -
  +<CENTER><H1><A NAME="my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A></H1></CENTER>
   <P>
  -Start httpd:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_poison">The poison</A></H2></CENTER>
  +<P>
  +In a non modperl script (stand alone or CGI), there is no problem writing
  +code like this:
   
   <P>
  -<PRE>  % /usr/local/sbin/httpd_perl/apachectl start 
  +<PRE>    use CGI qw/param/;
  +    my $x = param('x');
  +    sub printit {
  +       print &quot;$x\n&quot;;
  +    }
   </PRE>
   <P>
  -Stop httpd:
  +However, the script is run under <CODE>Apache::Registry</CODE>, it will in fact be repackaged into something like this:
   
   <P>
  -<PRE>  % /usr/local/sbin/httpd_perl/apachectl stop
  +<PRE>  package $mangled_package_name;
  +  sub handler {
  +    #line1 $original_filename
  +    use CGI qw/param/;
  +    my $x = param('x');
  +    sub printit {
  +       print &quot;$x\n&quot;;
  +    }
  +  }
   </PRE>
   <P>
  -Restart httpd if running by sending a <STRONG>SIGHUP</STRONG> or start if not running:
  +Now <CODE>printit()</CODE> is an inner named subroutine. Because it is referencing a lexical variable
  +from an enclosing scope, a closure is created.
   
   <P>
  -<PRE>  % /usr/local/sbin/httpd_perl/apachectl restart
  -</PRE>
  +The first time the script is run, the correct value of <CODE>$x</CODE> will
  +be printed. However on subsequent runs, <CODE>printit()</CODE> will retain the initial value of <CODE>$x</CODE> -- not what you want.
  +
   <P>
  -Do a graceful restart by sending a <STRONG>SIGUSR1</STRONG> or start if not running:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_diagnosis">The diagnosis</A></H2></CENTER>
  +<P>
  +Always use <CODE>-w</CODE> (or/and <CODE>PerlWarn ON</CODE>)! Perl will then emit a warning like:
   
   <P>
  -<PRE>  % /usr/local/sbin/httpd_perl/apachectl graceful    
  +<PRE>  Value of $x will not stay shared at - line 5.
   </PRE>
   <P>
  -Do a configuration syntax test:
  +NOTE: Subroutines defined inside <CODE>BEGIN{}</CODE> and <CODE>END{}</CODE> cannot trigger this message, since each <CODE>BEGIN{}</CODE> and <CODE>END{}</CODE> is defined to be called exactly once. (To understand why, read about the
  +closures at
  +<CODE>perlref</CODE> or <CODE>perlfaq</CODE> 13.12)
   
   <P>
  -<PRE>  % /usr/local/sbin/httpd_perl/apachectl configtest 
  +PERLDIAG manpage says:
  +
  +<P>
  +<PRE>  An inner (nested) named subroutine is referencing a lexical variable
  +  defined in an outer subroutine.
   </PRE>
   <P>
  -Replace <CODE>httpd_perl</CODE> with <CODE>httpd_docs</CODE> in the above calls to control the <STRONG>httpd_docs</STRONG> server.
  +When the inner subroutine is called, it will probably see the value of the
  +outer subroutine's variable as it was before and during the *first* call to
  +the outer subroutine; in this case, after the first call to the outer
  +subroutine is complete, the inner and outer subroutines will no longer
  +share a common value for the variable. In other words, the variable will no
  +longer be shared.
   
   <P>
  -There are other options for <STRONG>apachectl</STRONG>, use <CODE>help</CODE> option to see them all.
  +Check your code by running Apache in single-child mode (<CODE>httpd
  +-X</CODE>). Since the value of a my variable retain its initial value <CODE>per
  +child process</CODE>, the closure problem can be difficult to track down in multi-user mode. It
  +will appear to work fine until you have cycled through all the httpd
  +children.
   
   <P>
  -It's important to understand that this script is based on the PID file
  -which is <CODE>PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid</CODE>. If you delete the file by hand - <STRONG>apachectl</STRONG> will fail to run.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_remedy">The remedy</A></H2></CENTER>
  +<P>
  +If a variable needs file scope, use a global variable:
   
   <P>
  -Also, notice that <STRONG>apachectl</STRONG> is suitable to use from within your Unix system's startup files so that
  -your web server is automatically restarted upon system reboot. Either copy
  -the <STRONG>apachectl</STRONG> file to the appropriate location (<CODE>/etc/rc.d/rc3.d/S99apache</CODE> works on my RedHat Linux system) or create a symlink with that name
  -pointing to the the canonical location. (If you do this, make certain that
  -the script is writable only by root -- the startup scripts have root
  -privileges during init processing, and you don't want to be opening any
  -security holes.)
  +<PRE>    use vars qw/$x/;
  +    use CGI qw/param/;
  +    $x = param('x');
  +    sub printit {
  +       print &quot;$x\n&quot;;
  +    }
  +</PRE>
  +<P>
  +You can safely use a <CODE>my()</CODE> scoped variable if its value is constant:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="SUID_start_up_scripts">SUID start-up scripts</A></H1></CENTER>
  +<PRE>    use vars qw/$x/;
  +    use CGI qw/param/;
  +    $x = param('x');
  +    my $y = 5;
  +    sub printit {
  +       print &quot;$x, $y\n&quot;;
  +    }
  +</PRE>
   <P>
  -For those who wants to use <STRONG>SUID</STRONG> startup script, here is an example for you. This script is <STRONG>SUID</STRONG> to <STRONG>root</STRONG>, and should be executable only by members of some special group at your
  -site. Note the 10th line, which ``fixes an obscure error when starting
  -apache/mod_perl'' by setting the real to the effective UID. As others have
  -pointed out, it is the mismatch between the real and the effective UIDs
  -that causes Perl to croak on the -e switch.
  +Also see the clarification of <CODE>my()</CODE> vs. <CODE>use vars</CODE> - Ken Williams writes:
   
   <P>
  -Note that you must be using a version of Perl that recognizes and emulates
  -the suid bits in order for this to work. The script will do different
  -things depending on whether it is named <CODE>start_http</CODE>,
  -<CODE>stop_http</CODE> or <CODE>restart_http</CODE>. You can use symbolic links for this purpose.
  +<PRE>  Yes, there is quite a bit of difference!  With use vars(), you are
  +  making an entry in the symbol table, and you are telling the
  +  compiler that you are going to be referencing that entry without an
  +  explicit package name.
  +  
  +  With my(), NO ENTRY IS PUT IN THE SYMBOL TABLE.  The compiler
  +  figures out _at_ _compile_time_ which my() variables (i.e. lexical
  +  variables) are the same as each other, and once you hit execute time
  +  you can not go looking those variables up in the symbol table.
  +</PRE>
  +<P>
  +And <CODE>my()</CODE> vs. <CODE>local()</CODE> - Randal Schwartz writes:
   
   <P>
  -<PRE> #!/usr/bin/perl
  - 
  - # These constants will need to be adjusted.
  - $PID_FILE = '/home/www/logs/httpd.pid';
  - $HTTPD = '/home/www/httpd -d /home/www';
  - 
  - # These prevent taint warnings while running suid
  - $ENV{PATH}='/bin:/usr/bin';
  - $ENV{IFS}='';
  - 
  - # This sets the real to the effective ID, and prevents
  - # an obscure error when starting apache/mod_perl
  - $&lt; = $&gt;;
  - $( = $) = 0; # set the group to root too
  - 
  - # Do different things depending on our name
  - ($name) = $0 =~ m|([^/]+)$|;
  - 
  - if ($name eq 'start_http') {
  -     system $HTTPD and die &quot;Unable to start HTTP&quot;;
  -     print &quot;HTTP started.\n&quot;;
  -     exit 0;
  - }
  - 
  - # extract the process id and confirm that it is numeric
  - $pid = `cat $PID_FILE`;
  - $pid =~ /(\d+)/ or die &quot;PID $pid not numeric&quot;;
  - $pid = $1;
  - 
  - if ($name eq 'stop_http') {
  -     kill 'TERM',$pid or die &quot;Unable to signal HTTP&quot;;
  -     print &quot;HTTP stopped.\n&quot;;
  -     exit 0;
  - }
  - 
  - if ($name eq 'restart_http') {
  -     kill 'HUP',$pid or die &quot;Unable to signal HTTP&quot;;
  -     print &quot;HTTP restarted.\n&quot;;
  -     exit 0;
  - }
  - 
  - die &quot;Script must be named start_http, stop_http, or restart_http.\n&quot;;
  +<PRE>  local() creates a temporal-limited package-based scalar, array,
  +  hash, or glob -- when the scope of definition is exited at runtime,
  +  the previous value (if any) is restored.  References to such a
  +  variable are *also* global... only the value changes.  (Aside: that
  +  is what causes variable suicide. :)
  +  
  +  my() creates a lexically-limited non-package-based scalar, array, or
  +  hash -- when the scope of definition is exited at compile-time, the
  +  variable ceases to be accessible.  Any references to such a variable
  +  at runtime turn into unique anonymous variables on each scope exit.
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A></H1></CENTER>
  +<CENTER><H2><A NAME="Additional_reading_references">Additional reading references</A></H2></CENTER>
   <P>
  -With mod_perl many things can happen to your server. The worst one is the
  -possibility that the server will die when you will be not around. As with
  -any other critical service you need to run some kind of watchdog.
  +For more information see: <A HREF="././perl.html#Using_global_variables_and_shari">Using global variables and sharing them between modules/packages</A> and an article by Mark-Jason Dominus about how Perl handles variables and
  +namespaces, and the difference between <CODE>use vars()</CODE> and <CODE>my()</CODE> - <A
  +HREF="http://www.plover.com/~mjd/perl/FAQs/Namespaces.html">http://www.plover.com/~mjd/perl/FAQs/Namespaces.html</A>
  +.
   
   <P>
  -One simple solution is to use a slightly modified <STRONG>apachectl</STRONG> script which I called apache.watchdog and to put it into the crontab to be
  -called every 30 minutes or even every minute - if it's so critical to make
  -sure the server will be up all the time.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Compiled_Regular_Expressions">Compiled Regular Expressions</A></H1></CENTER>
   <P>
  -The crontab entry:
  +When using a regular expression that contains an interpolated Perl
  +variable, if it is known that the variable (or variables) will not vary
  +during the execution of the program, a standard optimization technique
  +consists of adding the <CODE>/o</CODE> modifier to the regexp pattern. This directs the compiler to build the
  +internal table once, for the entire lifetime of the script, rather than
  +every time the pattern is executed. Consider:
   
   <P>
  -<PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
  +<PRE>  my $pat = '^foo$'; # likely to be input from an HTML form field
  +  foreach( @list ) {
  +    print if /$pat/o;
  +  }
   </PRE>
   <P>
  -The script:
  +This is usually a big win in loops over lists, or when using <CODE>grep()</CODE>
  +or <CODE>map()</CODE> operators.
   
   <P>
  -<PRE>  #!/bin/sh
  -    
  -  # this script is a watchdog to see whether the server is online
  -  # It tries to restart the server if it's
  -  # down and sends an email alert to admin 
  -  
  -  # admin's email
  -  EMAIL=webmaster@somewhere.far
  -  #EMAIL=root@localhost
  -    
  -  # the path to your PID file
  -  PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid
  -    
  -  # the path to your httpd binary, including options if necessary
  -  HTTPD=/usr/local/sbin/httpd_perl/httpd_perl
  -        
  -  # check for pidfile
  -  if [ -f $PIDFILE ] ; then
  -    PID=`cat $PIDFILE`
  -    
  -    if kill -0 $PID; then
  -      STATUS=&quot;httpd (pid $PID) running&quot;
  -      RUNNING=1
  -    else
  -      STATUS=&quot;httpd (pid $PID?) not running&quot;
  -      RUNNING=0
  -    fi
  -  else
  -    STATUS=&quot;httpd (no pid file) not running&quot;
  -    RUNNING=0
  -  fi
  -      
  -  if [ $RUNNING -eq 0 ]; then
  -    echo &quot;$0 $ARG: httpd not running, trying to start&quot;
  -    if $HTTPD ; then
  -      echo &quot;$0 $ARG: httpd started&quot;
  -      mail $EMAIL -s &quot;$0 $ARG: httpd started&quot; &lt;/dev/null &gt;&amp; /dev/null
  -    else
  -      echo &quot;$0 $ARG: httpd could not be started&quot;
  -      mail $EMAIL -s &quot;$0 $ARG: httpd could not be started&quot; &lt;/dev/null &gt;&amp; /dev/null
  -    fi
  -  fi
  -</PRE>
  +In long-lived mod_perl scripts, however, this can pose a problem if the
  +variable changes according to the invocation. The first invocation of a
  +fresh httpd child will compile the regex and perform the search correctly.
  +However, all subsequent uses by the httpd child will continue to match the
  +original pattern, regardless of the current contents of the Perl variables
  +the pattern is dependent on. Your script will appear broken.
  +
   <P>
  -Another approach, probably even more practical, is to use the cool <CODE>LWP</CODE>
  -perl package , to test the server by trying to fetch some document (script)
  -served by the server. Why is it more practical? Because, while server can
  -be up as a process, it can be stuck and not working, So failing to get the
  -document will trigger restart, and ``probably'' the problem will go away.
  -(Just replace <CODE>start</CODE> with <CODE>restart</CODE> in the <CODE>$restart_command</CODE>
  -below.
  +There are two solutions to this problem:
   
   <P>
  -Again we put this script into a crontab to call it every 30 minutes.
  -Personally I call it every minute, to fetch some very light script. Why so
  -often? If your server starts to spin and trash your disk's space with
  -multiply error messages, in a 5 minutes you might run out of free space,
  -which might bring your system to its knees. And most chances that no other
  -child will be able to serve requests, since the system will be too busy,
  -writing to an <CODE>error_log</CODE> file. Think big -- if you are running a heavy service, which is very fast,
  -since you are running under mod_perl, adding one more request every minute,
  -will be not felt by the server at all.
  +The first -- is to use <CODE>eval q//</CODE>, to force the code to be evaluated each time. Just make sure that the eval
  +block covers the entire loop of processing, and not just the pattern match
  +itself.
   
   <P>
  -So we end up with crontab entry:
  +The above code fragment would be rewritten as: 
   
   <P>
  -<PRE>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
  +<PRE>  my $pat = '^foo$';
  +  eval q{
  +    foreach( @list ) {
  +      print if /$pat/o;
  +    }
  +  }
   </PRE>
   <P>
  -And the watchdog itself:
  +Just saying:
   
   <P>
  -<PRE>  #!/usr/local/bin/perl -w
  -  
  -  use strict;
  -  use diagnostics;
  -  use URI::URL;
  -  use LWP::MediaTypes qw(media_suffix);
  -  
  -  my $VERSION = '0.01';
  -  use vars qw($ua $proxy);
  -  $proxy = '';    
  +<PRE>  foreach( @list ) {
  +    eval q{ print if /$pat/o; };
  +  }
   </PRE>
   <P>
  -<PRE>  require LWP::UserAgent;
  -  use HTTP::Status;
  -  
  -  ###### Config ########
  -  my $test_script_url = '<A HREF="http://www.stas.com:81/perl/test.pl">http://www.stas.com:81/perl/test.pl</A>';
  -  my $monitor_email   = 'root@localhost';
  -  my $restart_command = '/usr/local/sbin/httpd_perl/apachectl restart';
  -  my $mail_program    = '/usr/lib/sendmail -t -n';
  -  ######################
  -  
  -  $ua  = new LWP::UserAgent;
  -  $ua-&gt;agent(&quot;$0/Stas &quot; . $ua-&gt;agent);
  -  # Uncomment the proxy if you don't use it!
  -  #  $proxy=&quot;<A HREF="http://www-proxy.com&quot">http://www-proxy.com&quot</A>;;
  -  $ua-&gt;proxy('http', $proxy) if $proxy;
  -  
  -  # If returns '1' it's we are alive
  -  exit 1 if checkurl($test_script_url);
  -  
  -  # We have got the problem - the server seems to be down. Try to
  -  # restart it. 
  -  my $status = system $restart_command;
  -  #  print &quot;Status $status\n&quot;;
  -  
  -  my $message = ($status == 0) 
  -              ? &quot;Server was down and successfully restarted!&quot; 
  -              : &quot;Server is down. Can't restart.&quot;;
  -    
  -  my $subject = ($status == 0) 
  -              ? &quot;Attention! Webserver restarted&quot;
  -              : &quot;Attention! Webserver is down. can't restart&quot;;
  -  
  -  # email the monitoring person
  -  my $to = $monitor_email;
  -  my $from = $monitor_email;
  -  send_mail($from,$to,$subject,$message);
  -  
  -  # input:  URL to check 
  -  # output: 1 if success, o for fail  
  -  #######################  
  -  sub checkurl{
  -    my ($url) = @_;
  -  
  -    # Fetch document 
  -    my $res = $ua-&gt;request(HTTP::Request-&gt;new(GET =&gt; $url));
  -  
  -    # Check the result status
  -    return 1 if is_success($res-&gt;code);
  -  
  -    # failed
  -    return 0;
  -  } #  end of sub checkurl
  -  
  -  # sends email about the problem 
  -  #######################  
  -  sub send_mail{
  -    my($from,$to,$subject,$messagebody) = @_;
  -  
  -    open MAIL, &quot;|$mail_program&quot;
  -        or die &quot;Can't open a pipe to a $mail_program :$!\n&quot;;
  -   
  -    print MAIL &lt;&lt;__END_OF_MAIL__;
  -  To: $to
  -  From: $from
  -  Subject: $subject
  -  
  -  $messagebody
  -  
  -  __END_OF_MAIL__
  -  
  -    close MAIL;
  -  } 
  -</PRE>
  +is going to be a horribly expensive proposition. 
  +
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
  +You can use this approach if you require more than one pattern match
  +operator in a given section of code. If the section contains only one
  +operator (be it an <CODE>m//</CODE> or <CODE>s///</CODE>), you can rely on the property of the null pattern, that reuses the last
  +pattern seen. This leads to the second solution, which also eliminates the
  +use of eval.
  +
   <P>
  -Often while developing new code, you will want to run the server in single
  -process mode. See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it works Sometimes it does Not</A> and <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>
  -Running in single process mode inhibits the server from ``daemonizing'',
  -allowing you to run it more easily under debugger control.
  +The above code fragment becomes: 
   
   <P>
  -<PRE>  % /usr/local/sbin/httpd_perl/httpd_perl -X
  +<PRE>  my $pat = '^foo$';
  +  &quot;something&quot; =~ /$pat/; # dummy match (MUST NOT FAIL!)
  +  foreach( @list ) {
  +    print if //;
  +  }
   </PRE>
   <P>
  -When you execute the above the server will run in the fg (foreground) of
  -the shell you have called it from. So to kill you just kill it with
  -<STRONG>Ctrl-C</STRONG>.
  +The only gotcha is that the dummy match that boots the regular expression
  +engine must absolutely, positively succeed, otherwise the pattern will not
  +be cached, and the <CODE>//</CODE> will match everything. If you can't count on fixed text to ensure the match
  +succeeds, you have two possibilities.
   
   <P>
  -Note that in <CODE>-X</CODE> mode the server will run very slowly while fetching images. If you use
  -Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
  -keep them open. Because there is only one server process listening, each
  -connection has to time-out before the next succeeds. Turn off
  -<CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect while developing or you can press <STRONG>STOP</STRONG> after a few seconds (assuming you use the image size params, so the
  -Netscape will be able to render the rest of the page).
  +If you can guarantee that the pattern variable contains no meta-characters
  +(things like *, +, ^, $...), you can use the dummy match:
   
   <P>
  -In addition you should know that when running with <CODE>-X</CODE> you will not see any control messages that the parent server normally
  -writes to the error_log. (Like ``server started, server stopped and etc''.)
  -Since
  -<CODE>httpd -X</CODE> causes the server to handle all requests itself, without forking any
  -children, there is no controlling parent to write status messages.
  +<PRE>  &quot;$pat&quot; =~ /\Q$pat\E/; # guaranteed if no meta-characters present
  +</PRE>
  +<P>
  +If there is a possibility that the pattern can contain meta-characters, you
  +should search for the pattern or the unsearchable \377 character as
  +follows:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</A></H1></CENTER>
  +<PRE>  &quot;\377&quot; =~ /$pat|^[\377]$/; # guaranteed if meta-characters present
  +</PRE>
   <P>
  -If you are the only developer working on the specific server:port - you
  -have no problems, since you have a complete control over the server.
  -However, many times you have a group of developers who need to concurrently
  -develop their own mod_perl scripts. This means that each one will want to
  -have control over the server - to kill it, to run it in single server mode,
  -to restart it again, etc., as well to have control over the location of the
  -log files and other configuration settings like <STRONG>MaxClients</STRONG>, etc. You can work around this problem by preparing a few httpd.conf file
  -and forcing each developer to use:
  +Another approach:
   
   <P>
  -<PRE>  httpd_perl -f /path/to/httpd.conf  
  +It depends on the complexity of the regexp you apply this technique to. One
  +common usage where compiled regexp is usually more efficient is to ``match
  +any one of a group of patterns'' over and over again.
  +
  +<P>
  +Maybe with some helper routine, it's easier to remember. Here is one
  +slightly modified from Jeffery Friedl's example in his book ``Mastering
  +Regex''.
  +
  +<P>
  +<PRE>  #####################################################
  +  # Build_MatchMany_Function
  +  # -- Input:  list of patterns
  +  # -- Output: A code ref which matches its $_[0]
  +  #            against ANY of the patterns given in the
  +  #            &quot;Input&quot;, efficiently.
  +  #
  +  sub Build_MatchMany_Function {
  +    my @R = @_;
  +    my $expr = join '||', map { &quot;\$_[0] =~ m/\$R[$_]/o&quot; } ( 0..$#R );
  +    my $matchsub = eval &quot;sub { $expr }&quot;;
  +    die &quot;Failed in building regex @R: $@&quot; if $@;
  +    $matchsub;
  +  }
   </PRE>
   <P>
  -I have approached it in other way. I have used the <CODE>-Dparameter</CODE>
  -startup option of the server. I call my version of the server
  +Example usage:
   
   <P>
  -<PRE>  % http_perl -Dsbekman
  +<PRE>  @some_browsers = qw(Mozilla Lynx MSIE AmigaVoyager lwp libwww);
  +  $Known_Browser=Build_MatchMany_Function(@some_browsers);
   </PRE>
   <P>
  -In <CODE>httpd.conf</CODE> I wrote:
  +<PRE>  while (&lt;ACCESS_LOG&gt;) {
  +    # ...
  +    $browser = get_browser_field($_);
  +    if ( ! &amp;$Known_Browser($browser) ) {
  +      print STDERR &quot;Unknown Browser: $browser\n&quot;;
  +    }
  +    # ...
  +  }
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A></H1></CENTER>
  +<P>
  +Running in httpd -X mode. (good only for testing during development phase).
   
   <P>
  -<PRE>  # Personal development Server for sbekman
  -  # sbekman use the server running on port 8000
  -  &lt;IfDefine sbekman&gt;
  -  Port 8000
  -  PidFile /usr/local/var/httpd_perl/run/httpd.pid.sbekman
  -  ErrorLog /usr/local/var/httpd_perl/logs/error_log.sbekman
  -  Timeout 300
  -  KeepAlive On
  -  MinSpareServers 2
  -  MaxSpareServers 2
  -  StartServers 1
  -  MaxClients 3
  -  MaxRequestsPerChild 15
  -  &lt;/IfDefine&gt;
  -  
  -  # Personal development Server for userfoo
  -  # userfoo use the server running on port 8001
  -  &lt;IfDefine userfoo&gt;
  -  Port 8001
  -  PidFile /usr/local/var/httpd_perl/run/httpd.pid.userfoo
  -  ErrorLog /usr/local/var/httpd_perl/logs/error_log.userfoo
  -  Timeout 300
  -  KeepAlive Off
  -  MinSpareServers 1
  -  MaxSpareServers 2
  -  StartServers 1
  -  MaxClients 5
  -  MaxRequestsPerChild 0
  -  &lt;/IfDefine&gt;
  +You want to test that your application correctly handles global variables
  +(if you have any - the less you have of them the better, but sometimes you
  +just can't without them). It's hard to test with multiple servers serving
  +your cgi since each child has a different value for its global variables.
  +Imagine that you have a <CODE>random()</CODE>
  +sub that returns a random number and you have the following script.
  +
  +<P>
  +<PRE>  use vars qw($num);
  +  $num ||= random();
  +  print ++$num;
   </PRE>
   <P>
  -What we have achieved with this technique: Full control over start/stop,
  -number of children, separate error log file, and port selection. This saves
  -me from getting called every few minutes - ``Stas, I'm going to restart the
  -server''.
  +This script initializes the variable <CODE>$num</CODE> with a random value, then increments it on each request and prints it out.
  +Running this script in multiple server environments will result in
  +something like <CODE>1</CODE>,
  +<CODE>9</CODE>, <CODE>4</CODE>, <CODE>19</CODE> (number per reload), since each time your script will be served by a
  +different child. (On some OSes, the parent httpd process will assign all of
  +the requests to the same child process if all of the children are idle...
  +AIX...). But if you run in <CODE>httpd -X</CODE>
  +single server mode you will get <CODE>2</CODE>, <CODE>3</CODE>, <CODE>4</CODE>, <CODE>5</CODE>... (assuming that the <CODE>random()</CODE> returned <CODE>1</CODE> at the first call)
   
   <P>
  -To make things even easier. (In the above technique, you have to discover
  -the PID of your parent <CODE>httpd_perl</CODE> process - written in
  -<CODE>/usr/local/var/httpd_perl/run/httpd.pid.userfoo</CODE>) . We change the
  -<STRONG>apachectl</STRONG> script to do the work for us. We make a copy for each developer called <STRONG>apachectl.username</STRONG> and we change 2 lines in script:
  +But do not get too obsessive with this mode, since working only in single
  +server mode sometimes hides problems that show up when you switch to a
  +normal (multi) server mode. Consider an application that allows you to
  +change the configuration at run time.
   
   <P>
  -<PRE>  PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid.sbekman
  -  HTTPD='/usr/local/sbin/httpd_perl/httpd_perl -Dsbekman'
  +Let's say the script produces a form to change the background color of the
  +page. It's not a good design, but for the sake of demonstrating the
  +potential problem, we will assume that our script doesn't write the changed
  +background color to the disk, but simply changes it in memory, like:
  +
  +<P>
  +<PRE>  use vars qw($bgcolor);
  +    # assign default value at first invocation
  +  $bgcolor ||= &quot;white&quot;;
  +    # modify the color if requested to
  +  $bgcolor = $q-&gt;param('bgcolor') || $bgcolor;
   </PRE>
   <P>
  -Of course you think you can use only one control file and know who is
  -calling by using uid, but since you have to be root to start the server -
  -it is not so simple.
  +So you have typed in a new color, and in response, your script prints back
  +the html with a new color - you think that's it! It was so simple. And if
  +you keep running in single server mode you will never notice that you have
  +a problem...
   
   <P>
  -The last thing was to let developers an option to run in single process
  -mode by:
  +If you run the same code in the normal server mode, after you submit the
  +color change you will get the result as expected, but when you will call
  +the same URL again (not reload!) chances are that you will get back the
  +original default color (white in our case), since except the child who
  +processed the color change request no one knows about their global variable
  +change. Just remember that children can't share information, other than
  +that which they inherited from their parent on their load. Of course you
  +should use a hidden variable for the color to be remembered or store it on
  +the server side (database, shared memory, etc).
   
  -<P>
  -<PRE>  /usr/local/sbin/httpd_perl/httpd_perl -Dsbekman -X
  -</PRE>
   <P>
  -In addition to making life easier, we decided to use relative links
  -everywhere in the static docs (including the calls to CGIs). You may ask
  -how using the relative link you will get to the right server? Very simple -
  -we have utilized the mod_rewrite to solve our problems:
  +Also note that since the server is running in single mode, if the output
  +returns HTML with <CODE>&lt;IMG</CODE>&gt; tags, then the load of these will take a lot of time. 
   
   <P>
  -In <CODE>access.conf</CODE> of the <CODE>httpd_docs</CODE> server we have the following code: (you have to configure your <CODE>httpd_docs</CODE> server with
  -<CODE>--enable-module=rewrite</CODE> )
  +When you use Netscape client while your server is running in single-process
  +mode, if the output returns a HTML with <CODE>&lt;IMG</CODE>&gt; tags, then the load of these will take a lot of time, since the <CODE>KeepAlive</CODE>
  +feature gets in the way. Netscape tries to open multiple connections and
  +keep them open. Because there is only one server process listening, each
  +connection has to time-out before the next succeeds. Turn off <CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect.
   
   <P>
  -<PRE>  # sbekman' server
  -  # port = 8000
  -  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  -  RewriteCond  %{REMOTE_ADDR} 123.34.45.56
  -  RewriteRule ^(.*)           <A HREF="http://nowhere.com:8000/">http://nowhere.com:8000/</A>$1 [R,L]
  -  
  -  # userfoo's server
  -  # port = 8001
  -  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  -  RewriteCond  %{REMOTE_ADDR} 123.34.45.57
  -  RewriteRule ^(.*)           <A HREF="http://nowhere.com:8001/">http://nowhere.com:8001/</A>$1 [R,L]
  -  
  -  # all the rest
  -  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  -  RewriteRule ^(.*)           <A HREF="http://nowhere.com:81/">http://nowhere.com:81/</A>$1 [R]
  -  
  -</PRE>
  +Also note that since the server is running in single mode, if the output
  +returns HTML with <CODE>&lt;IMG</CODE>&gt; tags, then the load of these will take a lot of time. If you use
  +Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
  +keep them open. Because there is only one server process listening, each
  +connection has to time-out before the next succeeds. Turn off
  +<CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect while developing or you can press <STRONG>STOP</STRONG> after a few seconds (assuming you use the image size params, so the
  +Netscape will be able to render the rest of the page).
  +
   <P>
  -where IP numbers are the IPs of the developer client machines (where they
  -are running their web browser.) (I have tried to use
  -<CODE>REMOTE_USER</CODE> since we have all the users authenticated but it did not work for me)
  +In addition you should know that when running with <CODE>-X</CODE> you will not see any control messages that the parent server normally
  +writes to the error_log. (Like ``server started, server stopped and etc''.)
  +Since
  +<CODE>httpd -X</CODE> causes the server to handle all requests itself, without forking any
  +children, there is no controlling parent to write status messages.
   
   <P>
  -So if I have a relative URL like <CODE>/perl/test.pl</CODE> written in some html or even <CODE>http://www.nowhere.com/perl/test.pl</CODE> in my case (user at machine of <CODE>sbekman</CODE>) it will be redirected by <CODE>httpd_docs</CODE> to
  -<CODE>http://www.nowhere.com:8000/perl/test.pl</CODE>.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A></H1></CENTER>
  +<P>
  +Under mod_perl, files that have been created after the server's (child?)
  +startup are being reported with negative age with <CODE>-M</CODE>
  +(<CODE>-C</CODE>  <CODE>-A</CODE>) test. This is obvious if you remember that you will get the negative
  +result if the server was started before the file was created and it's a
  +normal behavior with any perl.
   
   <P>
  -Of course you have another problem: The CGI generates some html, which
  -should be called again. If it generates a URL with hard coded PORT the
  -above scheme will not work. There 2 solutions:
  +If you want to have <CODE>-M</CODE> test to count the time relative to the current request, you should reset
  +the <CODE>$^T</CODE> variable as with any other perl script. Just add <CODE>$^T=time;</CODE> at the beginning of the scripts.
   
   <P>
  -First, generate relative URL so it will reuse the technique above, with
  -redirect (which is transparent for user) but it will not work if you have
  -something to <CODE>POST</CODE> (redirect looses all the data!).
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A></H1></CENTER>
  +<P>
  +When a user presses the <STRONG>STOP</STRONG> button, Apache will detect that via
  +<CODE>$SIG{PIPE}</CODE> and will cease the script execution. When we are talking about mod_cgi,
  +there is generally no problem, since all opened files will be closed and
  +all the resources will be freed (almost all -- if you happened to use
  +external lock files, most likely the resources that are being locked by
  +these will be left blocked and non-usable by any others who use the same
  +advisory locking scheme.)
   
   <P>
  -Second, use a general configuration module which generates a correct full
  -URL according to <CODE>REMOTE_USER</CODE>, so if <CODE>$ENV{REMOTE_USER} eq
  -'sbekman'</CODE>, I return <CODE>http://www.nowhere.com:8000/perl/</CODE> as
  -<CODE>cgi_base_url</CODE>. Again this will work if the user is authenticated.
  +It's important to notice that when the user hits the browser's <STRONG>STOP</STRONG>
  +button, the mod_perl script is blissfully unaware until it tries to send
  +some data to the browser. At that point, Apache realizes that the browser
  +is gone, and all the good cleanup stuff happens.
   
   <P>
  -All this is good for development. It is better to use the full URLs in
  -production, since if you have a static form and the <CODE>Action</CODE> is relative but the static document located on another server, pressing the
  -form's submit will cause a redirect to mod_perl server, but all the form's
  -data will be lost during the redirect.
  +Starting from apache 1.3.6 apache will not catch SIGPIPE anymore and
  +modperl will do it much better. Here is something from CHANGES from Apache
  +1.3.6.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A></H1></CENTER>
  +<PRE>  *) SIGPIPE is now ignored by the server core.  The request write
  +  routines (ap_rputc, ap_rputs, ap_rvputs, ap_rwrite, ap_rprintf,
  +  ap_rflush) now correctly check for output errors and mark the
  +  connection as aborted.  Replaced many direct (unchecked) calls to
  +  ap_b* routines with the analogous ap_r* calls.  [Roy Fielding]
  +</PRE>
   <P>
  -Many times you start off debugging your script by running it from your
  -favorite shell. Sometimes you encounter a very weird situation when script
  -runs from the shell but dies when called as a CGI. The real problem lies in
  -the difference between the environment that is being used by your server
  -and your shell. An example can be a different perl path or having <CODE>PERL5LIB</CODE> env variable which includes paths that are not in the <CODE>@INC</CODE> of the perl compiled with mod_perl server and configured during the
  -startup.
  +What happens if your mod_perl script has some global variables, that are
  +being used for resource locking?
   
   <P>
  -The best debugging approach is to write a wrapper that emulates the exact
  -environment of the server, by first deleting the environment variables like <CODE>PERL5LIB</CODE> and calling the same perl binary that it is being used by the server. Next,
  -set the environment identical to the server's by copying the perl run
  -directives from server startup and configuration files. It will also allow
  -you to remove completely the first line of the script - since mod_perl
  -skips it and the wrapper knows how to call the script.
  +It's possible not to notice the pitfall if the critical code section
  +between lock and unlock is very short and finishes fast, so you never see
  +this happens (you aren't fast enough to stop the code in the middle). But
  +look at the following scenario:
   
   <P>
  -Below is the example of such a script. Note that we force the <CODE>-Tw</CODE>
  -when we call the real script. (I have also added the ability to pass
  -params, which will not happen when you call the cgi from the web)
  +<PRE>  1. lock resource
  +     &lt;critical section starts&gt;
  +  2. sleep 20 (== do some time consuming processing)
  +     &lt;critical section ends&gt;
  +  3. unlock resource
  +</PRE>
  +<P>
  +If user presses <STRONG>STOP</STRONG> and Apache sends <CODE>SIGPIPE</CODE> before step 3, since we are in the mod_perl mode and we want the lock
  +variable to be cached, it will be not unlocked. A kind of <STRONG>deadlock</STRONG> exists.
   
   <P>
  -<PRE>  #!/usr/local/bin/perl -w    
  -   
  -  # This is a wrapper example 
  -   
  -  # It simulates the web server environment by setting the @INC and other
  -  # stuff, so what will run under this wrapper will run under web and
  -  # vice versa. 
  -  
  -  #
  -  # Usage: wrap.pl some_cgi.pl
  -  #
  -  
  -  BEGIN{
  -    use vars qw($basedir);
  -    $basedir = &quot;/usr/local&quot;;
  +Here is the working example. Run the server with <CODE>-X</CODE>, Press <STRONG>STOP</STRONG>
  +before the count-up to 10 has been finished. Then rerun the script, it'll
  +hang in <CODE>while(1)</CODE>! The resource is not available anymore to this child.
  +
  +<P>
  +<PRE>  use vars qw(%CACHE);
  +  use CGI;
  +  $|=1;
  +  my $q = new CGI;
  +  print $q-&gt;header,$q-&gt;start_html;
     
  -    # we want to make a complete emulation, 
  -    # so we must remove the user's environment
  -    @INC = ();
  +  print $q-&gt;p(&quot;$$ Going to lock!\n&quot;);
     
  -    # local perl libs
  -    push @INC,
  -      qw($basedir/lib/perl5/5.00502/aix
  -         $basedir/lib/perl5/5.00502
  -         $basedir/lib/perl5/site_perl/5.005/aix
  -         $basedir/lib/perl5/site_perl/5.005
  -        );
  +   # actually the while loop below is not needed 
  +   # (since it's an internal lock and accessible only 
  +   # by the same process and it if it's locked... it's locked for the
  +   # whole child's life
  +  while (1) {
  +    unless (defined $CACHE{LOCK} and $CACHE{LOCK} == 1) {
  +      $CACHE{LOCK} = 1;
  +      print $q-&gt;p(&quot;Got the lock!\n&quot;);
  +      last;
  +    }
     }
  -  
  -  use strict;
  -  use File::Basename;
  -  
  -    # process the passed params
  -  my $cgi = shift || '';
  -  my $params = (@ARGV) ? join(&quot; &quot;, @ARGV) : '';
  -  
  -  die &quot;Usage:\n\t$0 some_cgi.pl\n&quot; unless $cgi;
  -  
  -    # Set the environment
  -  my $PERL5LIB = join &quot;:&quot;, @INC;
  -  
  -    # if the path includes the directory 
  -    # we extract it and chdir there
  -  if ($cgi =~ m|/|) {
  -    my $dirname = dirname($cgi);
  -    chdir $dirname or die &quot;Can't chdir to $dirname: $! \n&quot;;
  -    $cgi =~ m|$dirname/(.*)|;
  -    $cgi = $1;
  +  print $q-&gt;p(&quot;Going to sleep (I mean working)!&quot;);
  +  my $c=0;
  +  foreach (1..10) {
  +    sleep 1;
  +    print $c++,&quot;\n&lt;BR&gt;&quot;;
     }
  -  
  -    # run the cgi from the script's directory
  -    # Note that we invoke warnings and Taint mode ON!!!
  -  system qq{$basedir/bin/perl -I$PERL5LIB -Tw $cgi $params};
  +  
  +  print $q-&gt;p(&quot;Going to unlock!&quot;);
  +  $CACHE{LOCK} = 0;
  +  print $q-&gt;p(&quot;Unlock!\n&quot;);
   </PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Log_Rotation">Log Rotation</A></H1></CENTER>
  +You may ask, what is the solution for this problem? As noted in the
  +<A HREF="././porting.html#END_blocks">END blocks</A> any <CODE>END</CODE> blocks that are encountered during compilation of <CODE>Apache::Registry</CODE> scripts are called after the script done is running, including subsequent
  +invocations when the script is cached in memory. So if you are running in <CODE>Apache::Registry</CODE>
  +mode, the following is your remedy:
  +
   <P>
  -A little bit off topic but good to know and use with mod_perl where your
  -error_log can grow at a 10-100Mb per day rate if your scripts spit out lots
  -of warnings...
  +<PRE>  END {
  +    $CACHE{LOCK} = 0;
  +  }
  +</PRE>
  +<P>
  +Notice that the <CODE>END</CODE> block will be run after the
  +<CODE>Apache::Registry::handler</CODE> is finished (not during the cleanup phase though).
   
   <P>
  -To rotate the logs do:
  +If you are into a perl API, use the <CODE>register_cleanup()</CODE> method of Apache.
   
   <P>
  -<PRE>  mv access_log access_log.renamed
  -  kill -HUP `cat httpd.pid`
  -  sleep 10; # allow some children to complete requests and logging
  -  # now it's safe to use access_log.renamed
  -  .....
  +<PRE>  $r-&gt;register_cleanup(sub {$CACHE{LOCK} = 0;});
   </PRE>
   <P>
  -The effect of <STRONG>SIGUSR1</STRONG> and <STRONG>SIGHUP</STRONG> is detailed in: <A
  -HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
  -.
  +If you are into Apache API
  +<CODE>Apache-&amp;gt;request-&amp;gt;connection-&amp;gt;aborted()</CODE> construct can be used to test for the aborted connection.
   
   <P>
  -I use this script:
  +I hope you noticed, that this example is very misleading, since there is a
  +different instance of <CODE>%CACHE</CODE> in every child, so if you modify it -- it is known only inside the same
  +child, none of global <CODE>%CACHE</CODE>
  +variables in other children is getting affected. But if you are going to
  +work with code that allows you to control variables that are being visible
  +to every child (some external shared memory or other approach) -- the
  +hazard this example still applies. Make sure you unlock the resources
  +either when you stop using them or when the script is being aborted in the
  +middle, before the actual unlocking is being happening.
   
   <P>
  -<PRE>  #!/usr/local/bin/perl -Tw
  -  
  -  # this script does a log rotation. Called from crontab.
  -  
  -  use strict;
  -  $ENV{PATH}='/bin:/usr/bin';
  -  
  -  ### configuration
  -  my @logfiles = qw(access_log error_log);
  -  umask 0;
  -  my $server = &quot;httpd_perl&quot;;
  -  my $logs_dir = &quot;/usr/local/var/$server/logs&quot;;
  -  my $restart_command = &quot;/usr/local/sbin/$server/apachectl restart&quot;;
  -  my $gzip_exec = &quot;/usr/bin/gzip&quot;;
  -  
  -  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  -  my $time = sprintf &quot;%0.2d.%0.2d.%0.2d-%0.2d.%0.2d.%0.2d&quot;, $year,++$mon,$mday,$hour,$min,$sec;
  -  $^I = &quot;.&quot;.$time;
  -  
  -  # rename log files
  -  chdir $logs_dir;
  -  @ARGV = @logfiles;
  -  while (&lt;&gt;) {
  -    close ARGV;
  -  }
  -  
  -  # now restart the server so the logs will be restarted
  -  system $restart_command;
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A></H1></CENTER>
  +<P>
  +A similar situation to <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Pressed Stop button disease</A> happens when client (browser) timeouts the connection (is it about 2
  +minutes?) . There are cases when your script is about to perform a very
  +long operation and there is a chance that its duration will be longer than
  +the client's timeout. One case I can think about is the DataBase
  +interaction, where the DB engine hangs or needs a lot of time to return
  +results. If this is the case, use <CODE>$SIG{ALRM}</CODE> to prevent the timeouts:
  +
  +<P>
  +<PRE>    $timeout = 10; # seconds
  +  eval {
  +    local $SIG{ALRM} =
  +        sub { die &quot;Sorry timed out. Please try again\n&quot; };
  +    alarm $timeout;
  +    ... db stuff ...
  +    alarm 0;
  +  };
     
  -  # compress log files
  -  foreach (@logfiles) {
  -      system &quot;$gzip_exec $_.$time&quot;;
  -  }
  +  die $@ if $@;
   </PRE>
   <P>
  -Randal L. Schwartz contributed this:
  +But, as lately it was discovered <CODE>local $SIG{'ALRM'}</CODE> does not restore the original underlying C handler. It was fixed in the
  +mod_perl 1.19_01 (CVS version). As a matter of fact none of the
  +<CODE>local $SIG{FOO}</CODE> restore the original C handler - read <A HREF="././debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A> for a debug technique and a possible workaround.
   
  -<BLOCKQUOTE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Where_do_the_warnings_errors_go_">Where do the warnings/errors go?</A></H1></CENTER>
  +<P>
  +Your CGI does not work and you want to see what the problem is. The best
  +idea is to check out any errors that the server may be reporting. Where I
  +can find these errors?
   
   <P>
  -Cron fires off setuid script called log-roller that looks like this:
  +Generally all errors are logged into an error_log file. The exact file
  +location and name are defined in the http.conf file. Look for the
  +<CODE>ErrorLog</CODE> parameter. My httpd.conf says:
   
   <P>
  -<PRE>    #!/usr/bin/perl -Tw
  -    use strict;
  -    use File::Basename;
  -    
  -    $ENV{PATH} = &quot;/usr/ucb:/bin:/usr/bin&quot;;
  -    
  -    my $ROOT = &quot;/WWW/apache&quot;; # names are relative to this
  -    my $CONF = &quot;$ROOT/conf/httpd.conf&quot;; # master conf
  -    my $MIDNIGHT = &quot;MIDNIGHT&quot;;  # name of program in each logdir
  -    
  -    my ($user_id, $group_id, $pidfile); # will be set during parse of conf
  -    die &quot;not running as root&quot; if $&gt;;
  -    
  -    chdir $ROOT or die &quot;Cannot chdir $ROOT: $!&quot;;
  -    
  -    my %midnights;
  -    open CONF, &quot;&lt;$CONF&quot; or die &quot;Cannot open $CONF: $!&quot;;
  -    while (&lt;CONF&gt;) {
  -      if (/^User (\w+)/i) {
  -        $user_id = getpwnam($1);
  -        next;
  -      }
  -      if (/^Group (\w+)/i) {
  -        $group_id = getgrnam($1);
  -        next;
  -      }
  -      if (/^PidFile (.*)/i) {
  -        $pidfile = $1;
  -        next;
  -      }
  -     next unless /^ErrorLog (.*)/i;
  -      my $midnight = (dirname $1).&quot;/$MIDNIGHT&quot;;
  -      next unless -x $midnight;
  -      $midnights{$midnight}++;
  -    }
  -    close CONF;
  -    
  -    die &quot;missing User definition&quot; unless defined $user_id;
  -    die &quot;missing Group definition&quot; unless defined $group_id;
  -    die &quot;missing PidFile definition&quot; unless defined $pidfile;
  -    
  -    open PID, $pidfile or die &quot;Cannot open $pidfile: $!&quot;;
  -    &lt;PID&gt; =~ /(\d+)/;
  -    my $httpd_pid = $1;
  -    close PID;
  -    die &quot;missing pid definition&quot; unless defined $httpd_pid and $httpd_pid;
  -    kill 0, $httpd_pid or die &quot;cannot find pid $httpd_pid: $!&quot;;
  -    
  -    
  -    for (sort keys %midnights) {
  -      defined(my $pid = fork) or die &quot;cannot fork: $!&quot;;
  -      if ($pid) {
  -        ## parent:
  -        waitpid $pid, 0;
  -      } else {
  -        my $dir = dirname $_;
  -        ($(,$)) = ($group_id,$group_id);
  -        ($&lt;,$&gt;) = ($user_id,$user_id);
  -        chdir $dir or die &quot;cannot chdir $dir: $!&quot;;
  -        exec &quot;./$MIDNIGHT&quot;;
  -        die &quot;cannot exec $MIDNIGHT: $!&quot;;
  -      }
  -    }
  -    
  -    kill 1, $httpd_pid or die &quot;Cannot sighup $httpd_pid: $!&quot;;
  +<PRE>  ErrorLog var/logs/error_log
   </PRE>
   <P>
  -And then individual MIDNIGHT scripts can look like this:
  +Hey, where is the beginning of the path? There is another Apache parameter
  +called <CODE>ServerRoot</CODE>. Every time apache sees a value of the parameter with no absolute path
  +(e.g <CODE>/tmp/my.txt</CODE>) but with relative path (e.g <CODE>my.txt</CODE>) it prepends the value of the <CODE>ServerRoot</CODE> to this value. I have:
   
   <P>
  -<PRE>    #!/usr/bin/perl -Tw
  -    use strict;
  -    
  -    die &quot;bad guy&quot; unless getpwuid($&lt;) =~ /^(root|nobody)$/;
  -    my @LOGFILES = qw(access_log error_log);
  -    umask 0;
  -    $^I = &quot;.&quot;.time;
  -    @ARGV = @LOGFILES;
  -    while (&lt;&gt;) {
  -      close ARGV;
  -    }
  +<PRE>  ServerRoot /usr/local/apache
   </PRE>
   <P>
  -Can you spot the security holes? Our trusted user base can't or won't. :)
  -But these shouldn't be used in hostile situations.
  +So I will look for error_log file at
  +<CODE>/usr/local/apache/var/logs/error_log</CODE>. Of course you can also use an absolute path to define the file's location
  +at the file system.
   
  -</BLOCKQUOTE>
  +<P>
  +&lt;META&gt;: is this 100% correct?
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Preventing_from_modperl_process_">Preventing from modperl process from going wild</A></H1></CENTER>
  +But there are cases when errors don't go to the error_log file. For example
  +some errors are being printed to the console (tty) you have executed the
  +httpd from (unless you redirected the httpd's stderr flow). This happens
  +when the server didn't open the error_log file for writing yet.
  +
   <P>
  -Sometimes calling an undefined subroutine in a module can cause a tight
  -loop that consumes all memory. Here is a way to catch such errors. Define
  -an autoload subroutine:
  +For example, if you have mistakenly entered a non-existent directory path
  +in your <CODE>ErrorLog</CODE> directive, the error message will be printed on the controlling tty. Or, if
  +the error happens when server executes
  +<CODE>PerlRequire</CODE> or <CODE>PerlModule</CODE> directive you might see the errors here also.
   
   <P>
  -<PRE>  sub UNIVERSAL::AUTOLOAD {
  -    my $class = shift;
  -    warn &quot;$class can't \$UNIVERSAL::AUTOLOAD!\n&quot;;
  -  }
  -</PRE>
  +You are probably wonder where all the errors go when you are running the
  +server in single mode (<CODE>httpd -X</CODE>). They go to the console. That is because when running in the single mode
  +there is no parent httpd process to perform all the logging. It includes
  +all the status messages that generally show up in the error_log file.
  +
   <P>
  -It will produce a nice error in error_log, giving the line number of the
  -call and the name of the undefined subroutine.
  +&lt;/META&gt;
   
   <P>
  -Sometimes an error happens and causes the server to write millions of lines
  -into your <CODE>error_log</CODE> file and in a few minutes to put your server down on its knees. For example
  -I get an error <CODE>Callback called
  -exit</CODE> show up in my error_log file many times. The <CODE>error_log</CODE> file grows to 300 Mbytes in size in a few minutes. You should run a cron
  -job to make sure this does not happen and if it does to take care of it.
  -Andreas J. Koenig is running this shell script every minute:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A></H1></CENTER>
  +<P>
  +Perl uses <CODE>sh()</CODE> for its iteractions for <CODE>system()</CODE> and <CODE>open()</CODE>
  +calls. So when you want to set a temporary variable when you call a script
  +from your CGI you do:
   
   <P>
  -<PRE>  S=`ls -s /usr/local/apache/logs/error_log | awk '{print $1}'`
  -  if [ &quot;$S&quot; -gt 100000 ] ; then
  -    mv  /usr/local/apache/logs/error_log /usr/local/apache/logs/error_log.old
  -    /etc/rc.d/init.d/httpd restart
  -    date | /bin/mail -s &quot;error_log $S kB on inx&quot; myemail@domain.com
  -  fi
  +<PRE> open UTIL, &quot;USER=stas ; script.pl | &quot; or die &quot;...: $!\n&quot;;
   </PRE>
  -<P>
  -It seems that his script will trigger restart every minute, since once the
  -logfile grows to be of 100000 lines, it will stay of this size, unless you
  -remove or rename it, before you do restart. On my server I run a watchdog
  -every five minutes which restarts the server if it is getting stuck (it
  -always works since when some modperl child process goes wild, the I/O it
  -causes is so heavy that other brother processes cannot normally to serve
  -the requests.) See <A HREF="././control.html#Monitoring_the_Server_A_watchdo">Monitoring the Server</A> for more hints.
  +<P>
  +or
   
   <P>
  -Also check out the daemontools from <A
  -HREF="ftp://koobera.math.uic.edu/www/daemontools.html">ftp://koobera.math.uic.edu/www/daemontools.html</A>
  -:
  +<PRE>  system &quot;USER=stas ; script.pl&quot;;
  +</PRE>
  +<P>
  +This is useful for example if you need to invoke a script that uses CGI.pm
  +from within a mod_perl script. We are tricking the perl script to think
  +it's a simple CGI, which is not running under mod_perl.
   
   <P>
  -<PRE>  ,-----
  -  | cyclog writes a log to disk. It automatically synchronizes the log
  -  | every 100KB (by default) to guarantee data integrity after a crash. It
  -  | automatically rotates the log to keep it below 1MB (by default). If
  -  | the disk fills up, cyclog pauses and then tries again, without losing
  -  | any data.
  -  `-----
  +<PRE>  open(PUBLISH, &quot;GATEWAY_INTERFACE=CGI/1.1 ; script.cgi
  +       \&quot;param1=value1&amp;param2=value2\&quot; |&quot;) or die &quot;...: $!\n&quot;;
   </PRE>
  +<P>
  +Make sure, that the parameters you pass are shell safe (All ``unsafe''
  +characters like single-tick should be properly escaped).
  +
  +<P>
  +However you are fork-ing to run a Perl script, so you have thrown the so
  +hardly gained performance out the window. Whatever script.cgi is now, it
  +should be moved to a module with a subroutine you can call directly from
  +your script, to avoid the fork.
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -12624,7 +15268,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]
  +	     [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -12637,7 +15281,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 08/05/1999
  +	     <BR>Last Modified at 09/26/1999
         </FONT>
       </B>
     </TD>
  @@ -12664,7 +15308,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Things obvious to others, but not to you</TITLE>
  +   <TITLE>mod_perl guide: Runtime Warnings and Errors: Where and Why.</TITLE>
      <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
      <META NAME="Author" CONTENT="Stas Bekman">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  @@ -12683,29 +15327,36 @@
   <H1 ALIGN=CENTER>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Things obvious to others, but not to you</H1>
  +Runtime Warnings and Errors: Where and Why.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="correct_headers.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
  -
  -	<LI><A HREF="#Coverage">Coverage</A>
  -	<LI><A HREF="#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
  -	<UL>
  -
  -		<LI><A HREF="#The_poison">The poison</A>
  -		<LI><A HREF="#The_diagnosis">The diagnosis</A>
  -		<LI><A HREF="#The_remedy">The remedy</A>
  -		<LI><A HREF="#Additional_reading_references">Additional reading references</A>
  -	</UL>
   
  -	<LI><A HREF="#Compiled_Regular_Expressions">Compiled Regular Expressions </A>
  -	<LI><A HREF="#Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A>
  -	<LI><A HREF="#_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A>
  -	<LI><A HREF="#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>
  -	<LI><A HREF="#Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A>
  -	<LI><A HREF="#Where_do_the_warnings_errors_go_">Where do the warnings/errors go?</A>
  -	<LI><A HREF="#Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A>
  +	<LI><A HREF="#General_Advice">General Advice </A>
  +	<LI><A HREF="#Installation_problems">Installation problems</A>
  +	<LI><A HREF="#Incorrect_line_number_reporting_">Incorrect line number reporting in error/warn log messages</A>
  +	<LI><A HREF="#Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A>
  +	<LI><A HREF="#Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A>
  +	<LI><A HREF="#rwrite_returned_1">rwrite returned -1</A>
  +	<LI><A HREF="#Can_t_locate_loadable_object_for">Can't locate loadable object for module XXX</A>
  +	<LI><A HREF="#Missing_right_bracket_at_line_">Missing right bracket at line ...</A>
  +	<LI><A HREF="#caught_SIGPIPE_in_process">caught SIGPIPE in process</A>
  +	<LI><A HREF="#Client_hit_STOP_or_Netscape_bit_">Client hit STOP or Netscape bit it!</A>
  +	<LI><A HREF="#Constant_subroutine_XXX_redefine">Constant subroutine XXX redefined</A>
  +	<LI><A HREF="#Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</A>
  +	<LI><A HREF="#Can_t_undef_active_subroutine">Can't undef active subroutine</A>
  +	<LI><A HREF="#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
  +	<LI><A HREF="#Undefined_subroutine_Apache_RO">Undefined subroutine &amp;Apache::ROOT::perl::test_2epl::some_function called at</A>
  +	<LI><A HREF="#Can_t_load_auto_DBI_DBI_so_">Can't load '.../auto/DBI/DBI.so' for module DBI</A>
  +	<LI><A HREF="#Callback_called_exit">Callback called exit</A>
  +	<LI><A HREF="#Out_of_memory_">Out of memory!</A>
  +	<LI><A HREF="#Invalid_command_PerlHandler_">Invalid command 'PerlHandler'...</A>
  +	<LI><A HREF="#_warn_child_process_30388_did_n">[warn] child process 30388 did not exit, sending another SIGHUP</A>
  +	<LI><A HREF="#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
  +	<LI><A HREF="#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
  +	<LI><A HREF="#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
  +	<LI><A HREF="#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near &quot;line arguments:&quot;</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -12732,639 +15383,431 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
  +<CENTER><H1><A NAME="General_Advice">General Advice</A></H1></CENTER>
   <P>
  -This document describes ``special'' traps you may encounter when running
  -your plain CGIs under <CODE>Apache::Registry</CODE> and <CODE>Apache::PerlRun</CODE>.
  +Enabling <CODE>use diagnostics;</CODE> generally helps you to determine the source of the problem and how to solve
  +it. See <A HREF="././porting.html#diagnostics_pragma">diagnostics pragma</A> for more info.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A></H1></CENTER>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="The_poison">The poison</A></H2></CENTER>
  -<P>
  -In a non modperl script (stand alone or CGI), there is no problem writing
  -code like this:
  -
  -<P>
  -<PRE>    use CGI qw/param/;
  -    my $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  -</PRE>
  +<CENTER><H1><A NAME="Installation_problems">Installation problems</A></H1></CENTER>
   <P>
  -However, the script is run under <CODE>Apache::Registry</CODE>, it will in fact be repackaged into something like this:
  +See <A HREF="././install.html#Installation_problems">Installation problems</A>
   
  -<P>
  -<PRE>  package $mangled_package_name;
  -  sub handler {
  -    #line1 $original_filename
  -    use CGI qw/param/;
  -    my $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  -  }
  -</PRE>
  -<P>
  -Now <CODE>printit()</CODE> is an inner named subroutine. Because it is referencing a lexical variable
  -from an enclosing scope, a closure is created.
   
  -<P>
  -The first time the script is run, the correct value of <CODE>$x</CODE> will
  -be printed. However on subsequent runs, <CODE>printit()</CODE> will retain the initial value of <CODE>$x</CODE> -- not what you want.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="The_diagnosis">The diagnosis</A></H2></CENTER>
  -<P>
  -Always use <CODE>-w</CODE> (or/and <CODE>PerlWarn ON</CODE>)! Perl will then emit a warning like:
  -
  -<P>
  -<PRE>  Value of $x will not stay shared at - line 5.
  -</PRE>
  -<P>
  -NOTE: Subroutines defined inside <CODE>BEGIN{}</CODE> and <CODE>END{}</CODE> cannot trigger this message, since each <CODE>BEGIN{}</CODE> and <CODE>END{}</CODE> is defined to be called exactly once. (To understand why, read about the
  -closures at
  -<CODE>perlref</CODE> or <CODE>perlfaq</CODE> 13.12)
  -
  +<CENTER><H1><A NAME="Incorrect_line_number_reporting_">Incorrect line number reporting in error/warn log messages</A></H1></CENTER>
   <P>
  -PERLDIAG manpage says:
  +See <A HREF="././warnings.html#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
   
  -<P>
  -<PRE>  An inner (nested) named subroutine is referencing a lexical variable
  -  defined in an outer subroutine.
  -</PRE>
  -<P>
  -When the inner subroutine is called, it will probably see the value of the
  -outer subroutine's variable as it was before and during the *first* call to
  -the outer subroutine; in this case, after the first call to the outer
  -subroutine is complete, the inner and outer subroutines will no longer
  -share a common value for the variable. In other words, the variable will no
  -longer be shared.
   
  -<P>
  -Check your code by running Apache in single-child mode (<CODE>httpd
  --X</CODE>). Since the value of a my variable retain its initial value <CODE>per
  -child process</CODE>, the closure problem can be difficult to track down in multi-user mode. It
  -will appear to work fine until you have cycled through all the httpd
  -children.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="The_remedy">The remedy</A></H2></CENTER>
  -<P>
  -If a variable needs file scope, use a global variable:
  -
  -<P>
  -<PRE>    use vars qw/$x/;
  -    use CGI qw/param/;
  -    $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  -</PRE>
  -<P>
  -You can safely use a <CODE>my()</CODE> scoped variable if its value is constant:
  -
  -<P>
  -<PRE>    use vars qw/$x/;
  -    use CGI qw/param/;
  -    $x = param('x');
  -    my $y = 5;
  -    sub printit {
  -       print &quot;$x, $y\n&quot;;
  -    }
  -</PRE>
  -<P>
  -Also see the clarification of <CODE>my()</CODE> vs. <CODE>use vars</CODE> - Ken Williams writes:
  -
  -<P>
  -<PRE>  Yes, there is quite a bit of difference!  With use vars(), you are
  -  making an entry in the symbol table, and you are telling the
  -  compiler that you are going to be referencing that entry without an
  -  explicit package name.
  -  
  -  With my(), NO ENTRY IS PUT IN THE SYMBOL TABLE.  The compiler
  -  figures out _at_ _compile_time_ which my() variables (i.e. lexical
  -  variables) are the same as each other, and once you hit execute time
  -  you can not go looking those variables up in the symbol table.
  -</PRE>
  +<CENTER><H1><A NAME="Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A></H1></CENTER>
   <P>
  -And <CODE>my()</CODE> vs. <CODE>local()</CODE> - Randal Schwartz writes:
  +<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
   
   <P>
  -<PRE>  local() creates a temporal-limited package-based scalar, array,
  -  hash, or glob -- when the scope of definition is exited at runtime,
  -  the previous value (if any) is restored.  References to such a
  -  variable are *also* global... only the value changes.  (Aside: that
  -  is what causes variable suicide. :)
  -  
  -  my() creates a lexically-limited non-package-based scalar, array, or
  -  hash -- when the scope of definition is exited at compile-time, the
  -  variable ceases to be accessible.  Any references to such a variable
  -  at runtime turn into unique anonymous variables on each scope exit.
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Additional_reading_references">Additional reading references</A></H2></CENTER>
  +<CENTER><H1><A NAME="Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A></H1></CENTER>
   <P>
  -For more information see: <A HREF="././perl.html#Using_global_variables_and_shari">Using global variables and sharing them between modules/packages</A> and an article by Mark-Jason Dominus about how Perl handles variables and
  -namespaces, and the difference between <CODE>use vars()</CODE> and <CODE>my()</CODE> - <A
  -HREF="http://www.plover.com/~mjd/perl/FAQs/Namespaces.html">http://www.plover.com/~mjd/perl/FAQs/Namespaces.html</A>
  -.
  +<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Compiled_Regular_Expressions">Compiled Regular Expressions</A></H1></CENTER>
  -<P>
  -When using a regular expression that contains an interpolated Perl
  -variable, if it is known that the variable (or variables) will not vary
  -during the execution of the program, a standard optimization technique
  -consists of adding the <CODE>/o</CODE> modifier to the regexp pattern. This directs the compiler to build the
  -internal table once, for the entire lifetime of the script, rather than
  -every time the pattern is executed. Consider:
  -
  -<P>
  -<PRE>  my $pat = '^foo$'; # likely to be input from an HTML form field
  -  foreach( @list ) {
  -    print if /$pat/o;
  -  }
  -</PRE>
  +<CENTER><H1><A NAME="rwrite_returned_1">rwrite returned -1</A></H1></CENTER>
   <P>
  -This is usually a big win in loops over lists, or when using <CODE>grep()</CODE>
  -or <CODE>map()</CODE> operators.
  +That message happens when the client breaks the connection while your
  +script is trying to write to the client. With Apache 1.3.x, you should only
  +see the rwrite messages if <CODE>LogLevel</CODE> is set to <CODE>debug</CODE>.
   
   <P>
  -In long-lived mod_perl scripts, however, this can pose a problem if the
  -variable changes according to the invocation. The first invocation of a
  -fresh httpd child will compile the regex and perform the search correctly.
  -However, all subsequent uses by the httpd child will continue to match the
  -original pattern, regardless of the current contents of the Perl variables
  -the pattern is dependent on. Your script will appear broken.
  +There was a bug that reported this debug message regardless the value of <CODE>LogLevel</CODE> directive. It has been fixed in mod_perl 1.19_01 (CVS version).
   
   <P>
  -There are two solutions to this problem:
  +Generally a <CODE>LogLevel</CODE> is either <CODE>debug</CODE> or <CODE>info</CODE>. <CODE>debug</CODE> logs everything, <CODE>info</CODE> is the next level, which doesn't include debug messages. You shouldn't use
  +a ``debug'' mode on your production server. And as of this moment there is
  +no way to stop users from aborting connections.
   
   <P>
  -The first -- is to use <CODE>eval q//</CODE>, to force the code to be evaluated each time. Just make sure that the eval
  -block covers the entire loop of processing, and not just the pattern match
  -itself.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Can_t_locate_loadable_object_for">Can't locate loadable object for module XXX</A></H1></CENTER>
   <P>
  -The above code fragment would be rewritten as: 
  +There is no object built for this module. e.g. when you see:
   
   <P>
  -<PRE>  my $pat = '^foo$';
  -  eval q{
  -    foreach( @list ) {
  -      print if /$pat/o;
  -    }
  -  }
  +<PRE>  Can't locate loadable object for module Apache::Util in @INC...
   </PRE>
   <P>
  -Just saying:
  +make sure to give mod_perl's <CODE>Makefile.PL</CODE>  <CODE>PERL_UTIL_API=1</CODE>,
  +<CODE>EVERYTHING=1</CODE> or <CODE>DYNAMIC=1</CODE> parameters to enable and build all the components of <CODE>Apache::Util</CODE>.
   
   <P>
  -<PRE>  foreach( @list ) {
  -    eval q{ print if /$pat/o; };
  -  }
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Missing_right_bracket_at_line_">Missing right bracket at line ...</A></H1></CENTER>
   <P>
  -is going to be a horribly expensive proposition. 
  +Most chances you really have a syntax error. However the other reason might
  +be a script running under <CODE>Apache::Registry</CODE> and using &lt;__DATA__&gt; or &lt;__END__&gt; tokens. <A HREF="././porting.html#_END_and_DATA_tokens">Learn why</A>
   
  -<P>
  -You can use this approach if you require more than one pattern match
  -operator in a given section of code. If the section contains only one
  -operator (be it an <CODE>m//</CODE> or <CODE>s///</CODE>), you can rely on the property of the null pattern, that reuses the last
  -pattern seen. This leads to the second solution, which also eliminates the
  -use of eval.
  +
   
   <P>
  -The above code fragment becomes: 
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="caught_SIGPIPE_in_process">caught SIGPIPE in process</A></H1></CENTER>
   <P>
  -<PRE>  my $pat = '^foo$';
  -  &quot;something&quot; =~ /$pat/; # dummy match (MUST NOT FAIL!)
  -  foreach( @list ) {
  -    print if //;
  -  }
  +<PRE>  [modperl] caught SIGPIPE in process 1234
  +  [modperl] process 1234 going to Apache::exit with status...
   </PRE>
   <P>
  -The only gotcha is that the dummy match that boots the regular expression
  -engine must absolutely, positively succeed, otherwise the pattern will not
  -be cached, and the <CODE>//</CODE> will match everything. If you can't count on fixed text to ensure the match
  -succeeds, you have two possibilities.
  +That's the <STRONG>$SIG{PIPE}</STRONG> handler installed by mod_perl/Apache::SIG, called if a connection timesout
  +or Client presses the 'Stop' button. It gives you an opportunity to do
  +cleanups if the script was aborted in the middle of its execution. See <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A> for more info.
   
   <P>
  -If you can guarantee that the pattern variable contains no meta-characters
  -(things like *, +, ^, $...), you can use the dummy match:
  +If your mod_perl version &lt; 1.17 you might get the message in the
  +following section...
   
   <P>
  -<PRE>  &quot;$pat&quot; =~ /\Q$pat\E/; # guaranteed if no meta-characters present
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Client_hit_STOP_or_Netscape_bit_">Client hit STOP or Netscape bit it!</A></H1></CENTER>
  +<P>
  +<PRE>  Client hit STOP or Netscape bit it!
  +  Process 2493 going to Apache::exit with status=-2
   </PRE>
   <P>
  -If there is a possibility that the pattern can contain meta-characters, you
  -should search for the pattern or the unsearchable \377 character as
  -follows:
  +You will see this message in mod_perl &lt; 1.17. See <A HREF="././warnings.html#caught_SIGPIPE_in_process">caught SIGPIPE in process</A>.
   
   <P>
  -<PRE>  &quot;\377&quot; =~ /$pat|^[\377]$/; # guaranteed if meta-characters present
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Constant_subroutine_XXX_redefine">Constant subroutine XXX redefined</A></H1></CENTER>
   <P>
  -Another approach:
  +That's a mandatory warning inside Perl. It happens only if you modify your
  +script and Apache::Registry reloads it. Perl is warning you that the
  +<CODE>subroutine(s)</CODE> were redefined. It is mostly harmless. If you
  +don't like seeing those, just <CODE>kill -USR2</CODE> (graceful restart) apache when you modify your scripts.
   
   <P>
  -It depends on the complexity of the regexp you apply this technique to. One
  -common usage where compiled regexp is usually more efficient is to ``match
  -any one of a group of patterns'' over and over again.
  +You aren't supposed to see these warnings when you don't modify the code
  +with perl 5.004_05 or 5.005+.and higher. If you still experince a problem
  +with code within a CGI script, moving all the code into a module (or a
  +library) and requiring it should solve the problem.
   
   <P>
  -Maybe with some helper routine, it's easier to remember. Here is one
  -slightly modified from Jeffery Friedl's example in his book ``Mastering
  -Regex''.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</A></H1></CENTER>
  +<P>
  +The script below will print a warning like above, moreover it will print
  +the whole script as a part of the warning message:
   
   <P>
  -<PRE>  #####################################################
  -  # Build_MatchMany_Function
  -  # -- Input:  list of patterns
  -  # -- Output: A code ref which matches its $_[0]
  -  #            against ANY of the patterns given in the
  -  #            &quot;Input&quot;, efficiently.
  -  #
  -  sub Build_MatchMany_Function {
  -    my @R = @_;
  -    my $expr = join '||', map { &quot;\$_[0] =~ m/\$R[$_]/o&quot; } ( 0..$#R );
  -    my $matchsub = eval &quot;sub { $expr }&quot;;
  -    die &quot;Failed in building regex @R: $@&quot; if $@;
  -    $matchsub;
  -  }
  +<PRE>  #!/usr/bin/perl -w
  +  use strict;
  +  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;Hello $undefined&quot;;
   </PRE>
   <P>
  -Example usage:
  +The warning:
   
  -<P>
  -<PRE>  @some_browsers = qw(Mozilla Lynx MSIE AmigaVoyager lwp libwww);
  -  $Known_Browser=Build_MatchMany_Function(@some_browsers);
  -</PRE>
   <P>
  -<PRE>  while (&lt;ACCESS_LOG&gt;) {
  -    # ...
  -    $browser = get_browser_field($_);
  -    if ( ! &amp;$Known_Browser($browser) ) {
  -      print STDERR &quot;Unknown Browser: $browser\n&quot;;
  -    }
  -    # ...
  +<PRE>  Global symbol &quot;$undefined&quot; requires explicit package name at /usr/apps/foo/cgi/tmp.pl line 4.
  +          eval 'package Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub handler {
  +  #line 1 /usr/apps/foo/cgi/tmp.pl
  +  BEGIN {$^W = 1;}#!/usr/bin/perl -w
  +  use strict;
  +  print &quot;Content-type: text/html\\n\\n&quot;;
  +  print &quot;Hello $undefined&quot;;
  +  
  +  
     }
  +  ;' called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 168
  +          Apache::Registry::compile('package
  +        Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub han...') 
  +        called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 121
  +          Apache::Registry::handler('Apache=SCALAR(0x205026c0)') called at /usr/apps/foo/cgi/tmp.pl line 4
  +          eval {...} called at /usr/apps/foo/cgi/tmp.pl line 4
  +  [Sun Nov 15 15:15:30 1998] [error] Undefined subroutine &amp;Apache::ROOT::perl::tmp_2epl::handler called at /
  +  usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 135.
  +  
  +  [Sun Nov 15 15:15:30 1998] [error] Goto undefined subroutine &amp;Apache::Constants::SERVER_ERROR at /usr/apps
  +  /lib/perl5/site_perl/5.005/aix/Apache/Constants.pm line 23.
   </PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A></H1></CENTER>
  +The error is simple to fix. When you use the <CODE>use strict;</CODE> pragma (and you should...), all variables should be defined before being
  +used.
  +
   <P>
  -Running in httpd -X mode. (good only for testing during development phase).
  +The bad thing is that sometimes the whole script (possibly, thousands of
  +lines) is printed to error_log file as a code that the server has tried to <STRONG>eval()</STRONG>uate.
   
   <P>
  -You want to test that your application correctly handles global variables
  -(if you have any - the less you have of them the better, but sometimes you
  -just can't without them). It's hard to test with multiple servers serving
  -your cgi since each child has a different value for its global variables.
  -Imagine that you have a <CODE>random()</CODE>
  -sub that returns a random number and you have the following script.
  +As Doug answered to this question:
   
   <P>
  -<PRE>  use vars qw($num);
  -  $num ||= random();
  -  print ++$num;
  +<PRE> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
  + That's what's expected if so.
   </PRE>
   <P>
  -This script initializes the variable <CODE>$num</CODE> with a random value, then increments it on each request and prints it out.
  -Running this script in multiple server environments will result in
  -something like <CODE>1</CODE>,
  -<CODE>9</CODE>, <CODE>4</CODE>, <CODE>19</CODE> (number per reload), since each time your script will be served by a
  -different child. (On some OSes, the parent httpd process will assign all of
  -the requests to the same child process if all of the children are idle...
  -AIX...). But if you run in <CODE>httpd -X</CODE>
  -single server mode you will get <CODE>2</CODE>, <CODE>3</CODE>, <CODE>4</CODE>, <CODE>5</CODE>... (assuming that the <CODE>random()</CODE> returned <CODE>1</CODE> at the first call)
  +It wasn't in my case, but may be yours. 
   
   <P>
  -But do not get too obsessive with this mode, since working only in single
  -server mode sometimes hides problems that show up when you switch to a
  -normal (multi) server mode. Consider an application that allows you to
  -change the configuration at run time.
  +Bryan Miller said:
   
   <P>
  -Let's say the script produces a form to change the background color of the
  -page. It's not a good design, but for the sake of demonstrating the
  -potential problem, we will assume that our script doesn't write the changed
  -background color to the disk, but simply changes it in memory, like:
  -
  +<PRE> You might wish to try something more terse such as 
  + &quot;local $SIG{__WARN__} = \&amp;Carp::cluck;&quot;  The confess method is _very_
  + verbose and will tell you more than you might wish to know including
  + full source.
  +</PRE>
   <P>
  -<PRE>  use vars qw($bgcolor);
  -    # assign default value at first invocation
  -  $bgcolor ||= &quot;white&quot;;
  -    # modify the color if requested to
  -  $bgcolor = $q-&gt;param('bgcolor') || $bgcolor;
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Can_t_undef_active_subroutine">Can't undef active subroutine</A></H1></CENTER>
  +<P>
  +<PRE>  Can't undef active subroutine at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 102. 
  +  Called from package Apache::Registry, filename /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm, line 102 
   </PRE>
   <P>
  -So you have typed in a new color, and in response, your script prints back
  -the html with a new color - you think that's it! It was so simple. And if
  -you keep running in single server mode you will never notice that you have
  -a problem...
  +This problem is caused when, a client drops the connection while httpd is
  +in the middle of a write, httpd timeout happens, sending a SIGPIPE, and
  +Perl in that child is stuck in the middle of its eval context. This is
  +fixed by the Apache::SIG module which is called by default. This should not
  +happen unless you have code that is messing with <STRONG>$SIG{PIPE}</STRONG>. It's also triggered only when you've changed your script on disk and
  +mod_perl is trying to reload it.
   
   <P>
  -If you run the same code in the normal server mode, after you submit the
  -color change you will get the result as expected, but when you will call
  -the same URL again (not reload!) chances are that you will get back the
  -original default color (white in our case), since except the child who
  -processed the color change request no one knows about their global variable
  -change. Just remember that children can't share information, other than
  -that which they inherited from their parent on their load. Of course you
  -should use a hidden variable for the color to be remembered or store it on
  -the server side (database, shared memory, etc).
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A></H1></CENTER>
   <P>
  -Also note that since the server is running in single mode, if the output
  -returns HTML with <CODE>&lt;IMG</CODE>&gt; tags, then the load of these will take a lot of time. 
  +Your code includes some undefined variable that you have used as if it was
  +already defined and initialized. For example:
   
   <P>
  -When you use Netscape client while your server is running in single-process
  -mode, if the output returns a HTML with <CODE>&lt;IMG</CODE>&gt; tags, then the load of these will take a lot of time, since the <CODE>KeepAlive</CODE>
  -feature gets in the way. Netscape tries to open multiple connections and
  -keep them open. Because there is only one server process listening, each
  -connection has to time-out before the next succeeds. Turn off <CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect.
  -
  +<PRE>  $param = $q-&gt;param('test');
  +  print $param;
  +</PRE>
   <P>
  -Also note that since the server is running in single mode, if the output
  -returns HTML with <CODE>&lt;IMG</CODE>&gt; tags, then the load of these will take a lot of time. If you use
  -Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
  -keep them open. Because there is only one server process listening, each
  -connection has to time-out before the next succeeds. Turn off
  -<CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect while developing or you can press <STRONG>STOP</STRONG> after a few seconds (assuming you use the image size params, so the
  -Netscape will be able to render the rest of the page).
  +<PRE>  vs.
  +</PRE>
  +<P>
  +<PRE>  $param = $q-&gt;param('test') || '';
  +  print $param;
  +</PRE>
  +<P>
  +In the second case, <CODE>$param</CODE> will always be <CODE>defined</CODE>, either
  +<CODE>$q-&amp;gt;param('test')</CODE> returns some value or <CODE>undef</CODE>.
   
   <P>
  -In addition you should know that when running with <CODE>-X</CODE> you will not see any control messages that the parent server normally
  -writes to the error_log. (Like ``server started, server stopped and etc''.)
  -Since
  -<CODE>httpd -X</CODE> causes the server to handle all requests itself, without forking any
  -children, there is no controlling parent to write status messages.
  +Also read about <A HREF="././porting.html#Finding_the_line_number_the_erro">finding the line number the error/warning has been triggered at</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A></H1></CENTER>
  -<P>
  -Under mod_perl, files that have been created after the server's (child?)
  -startup are being reported with negative age with <CODE>-M</CODE>
  -(<CODE>-C</CODE>  <CODE>-A</CODE>) test. This is obvious if you remember that you will get the negative
  -result if the server was started before the file was created and it's a
  -normal behavior with any perl.
  -
  +<CENTER><H1><A NAME="Undefined_subroutine_Apache_RO">Undefined subroutine &amp;Apache::ROOT::perl::test_2epl::some_function called at</A></H1></CENTER>
   <P>
  -If you want to have <CODE>-M</CODE> test to count the time relative to the current request, you should reset
  -the <CODE>$^T</CODE> variable as with any other perl script. Just add <CODE>$^T=time;</CODE> at the beginning of the scripts.
  +See <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A></H1></CENTER>
  +<CENTER><H1><A NAME="Can_t_load_auto_DBI_DBI_so_">Can't load '.../auto/DBI/DBI.so' for module DBI</A></H1></CENTER>
   <P>
  -When a user presses the <STRONG>STOP</STRONG> button, Apache will detect that via
  -<CODE>$SIG{PIPE}</CODE> and will cease the script execution. When we are talking about mod_cgi,
  -there is generally no problem, since all opened files will be closed and
  -all the resources will be freed (almost all -- if you happened to use
  -external lock files, most likely the resources that are being locked by
  -these will be left blocked and non-usable by any others who use the same
  -advisory locking scheme.)
  +Check that all your modules are compiled with the same perl that is being
  +compiled into mod_perl. perl 5.005 and 5.004 are not binary compatible by
  +default.
   
   <P>
  -It's important to notice that when the user hits the browser's <STRONG>STOP</STRONG>
  -button, the mod_perl script is blissfully unaware until it tries to send
  -some data to the browser. At that point, Apache realizes that the browser
  -is gone, and all the good cleanup stuff happens.
  +Other known causes of this problem: OS distributions that ship with a
  +(broken) binary Perl installation. The `perl' program and `libperl.a'
  +library are somehow built with different binary compatibility flags.
   
   <P>
  -Starting from apache 1.3.6 apache will not catch SIGPIPE anymore and
  -modperl will do it much better. Here is something from CHANGES from Apache
  -1.3.6.
  +The solution to these problems is to rebuild Perl and any extension modules
  +from a fresh source tree. Tip for running Perl's Configure script: use the
  +`-des' flags to accepts defaults and `-D' flag to override certain
  +attributes:
   
   <P>
  -<PRE>  *) SIGPIPE is now ignored by the server core.  The request write
  -  routines (ap_rputc, ap_rputs, ap_rvputs, ap_rwrite, ap_rprintf,
  -  ap_rflush) now correctly check for output errors and mark the
  -  connection as aborted.  Replaced many direct (unchecked) calls to
  -  ap_b* routines with the analogous ap_r* calls.  [Roy Fielding]
  +<PRE>  % ./Configure -des -Dcc=gcc ... &amp;&amp; make test &amp;&amp; make install
  + 
  +Read Perl's INSTALL doc for more details.
   </PRE>
   <P>
  -What happens if your mod_perl script has some global variables, that are
  -being used for resource locking?
  +Solaris OS specific: 
   
   <P>
  -It's possible not to notice the pitfall if the critical code section
  -between lock and unlock is very short and finishes fast, so you never see
  -this happens (you aren't fast enough to stop the code in the middle). But
  -look at the following scenario:
  +Can't load DBI or similar Error for the IO module or whatever dynamic
  +module mod_perl tries to pull in first. The solution is to re-configure,
  +re-build and re-install Perl and dynamic modules with the following flags
  +when Configure asks for ``additional LD flags'': -Xlinker --export-dynamic
  +or
   
   <P>
  -<PRE>  1. lock resource
  -     &lt;critical section starts&gt;
  -  2. sleep 20 (== do some time consuming processing)
  -     &lt;critical section ends&gt;
  -  3. unlock resource
  +<PRE>  -Xlinker -E
   </PRE>
   <P>
  -If user presses <STRONG>STOP</STRONG> and Apache sends <CODE>SIGPIPE</CODE> before step 3, since we are in the mod_perl mode and we want the lock
  -variable to be cached, it will be not unlocked. A kind of <STRONG>deadlock</STRONG> exists.
  +This problem is only known to be caused by installing gnu ld under Solaris.
   
   <P>
  -Here is the working example. Run the server with <CODE>-X</CODE>, Press <STRONG>STOP</STRONG>
  -before the count-up to 10 has been finished. Then rerun the script, it'll
  -hang in <CODE>while(1)</CODE>! The resource is not available anymore to this child.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Callback_called_exit">Callback called exit</A></H1></CENTER>
   <P>
  -<PRE>  use vars qw(%CACHE);
  -  use CGI;
  -  $|=1;
  -  my $q = new CGI;
  -  print $q-&gt;header,$q-&gt;start_html;
  -  
  -  print $q-&gt;p(&quot;$$ Going to lock!\n&quot;);
  -  
  -   # actually the while loop below is not needed 
  -   # (since it's an internal lock and accessible only 
  -   # by the same process and it if it's locked... it's locked for the
  -   # whole child's life
  -  while (1) {
  -    unless (defined $CACHE{LOCK} and $CACHE{LOCK} == 1) {
  -      $CACHE{LOCK} = 1;
  -      print $q-&gt;p(&quot;Got the lock!\n&quot;);
  -      last;
  -    }
  -  }
  -  print $q-&gt;p(&quot;Going to sleep (I mean working)!&quot;);
  -  my $c=0;
  -  foreach (1..10) {
  -    sleep 1;
  -    print $c++,&quot;\n&lt;BR&gt;&quot;;
  -  }
  -  
  -  print $q-&gt;p(&quot;Going to unlock!&quot;);
  -  $CACHE{LOCK} = 0;
  -  print $q-&gt;p(&quot;Unlock!\n&quot;);
  -</PRE>
  +<EM>Callback called exit</EM> is just a generic message when some unrecoverable error occurs inside Perl
  +during <CODE>perl_call_sv()</CODE> (which mod_perl uses to invoke all handler subroutines. Such problems seem
  +far less with 5.005_03 than 5.004.
  +
   <P>
  -You may ask, what is the solution for this problem? As noted in the
  -<A HREF="././porting.html#END_blocks">END blocks</A> any <CODE>END</CODE> blocks that are encountered during compilation of <CODE>Apache::Registry</CODE> scripts are called after the script done is running, including subsequent
  -invocations when the script is cached in memory. So if you are running in <CODE>Apache::Registry</CODE>
  -mode, the following is your remedy:
  +Sometimes you discover that your server is not responding and its error_log
  +has filled up the remaining space on the file system. When you get to see
  +the contents of the error_log -- it includes millions of lines, like:
   
   <P>
  -<PRE>  END {
  -    $CACHE{LOCK} = 0;
  -  }
  +<PRE>  Callback called exit at -e line 33, &lt;HTML&gt; chunk 1.
   </PRE>
   <P>
  -Notice that the <CODE>END</CODE> block will be run after the
  -<CODE>Apache::Registry::handler</CODE> is finished (not during the cleanup phase though).
  +Why the looping?
   
   <P>
  -If you are into a perl API, use the <CODE>register_cleanup()</CODE> method of Apache.
  +Perl can get *very* confused inside an endless loop in your code, it
  +doesn't mean your code called <CODE>exit()</CODE>, but Perl's malloc went haywire and called <CODE>croak()</CODE>, but no memory is left to properly report the error, so Perl is stuck in a
  +loop writing that same message to stderr.
   
  -<P>
  -<PRE>  $r-&gt;register_cleanup(sub {$CACHE{LOCK} = 0;});
  -</PRE>
   <P>
  -If you are into Apache API
  -<CODE>Apache-&amp;gt;request-&amp;gt;connection-&amp;gt;aborted()</CODE> construct can be used to test for the aborted connection.
  +Perl 5.005+ plus is recommended for its improved malloc.c and other
  +features that improve mod_perl and come turned on by default.
   
   <P>
  -I hope you noticed, that this example is very misleading, since there is a
  -different instance of <CODE>%CACHE</CODE> in every child, so if you modify it -- it is known only inside the same
  -child, none of global <CODE>%CACHE</CODE>
  -variables in other children is getting affected. But if you are going to
  -work with code that allows you to control variables that are being visible
  -to every child (some external shared memory or other approach) -- the
  -hazard this example still applies. Make sure you unlock the resources
  -either when you stop using them or when the script is being aborted in the
  -middle, before the actual unlocking is being happening.
  +See also <A HREF="#Out_of_memory_">Out_of_memory!</A>
   
  +
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A></H1></CENTER>
  +<CENTER><H1><A NAME="Out_of_memory_">Out of memory!</A></H1></CENTER>
   <P>
  -A similar situation to <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Pressed Stop button disease</A> happens when client (browser) timeouts the connection (is it about 2
  -minutes?) . There are cases when your script is about to perform a very
  -long operation and there is a chance that its duration will be longer than
  -the client's timeout. One case I can think about is the DataBase
  -interaction, where the DB engine hangs or needs a lot of time to return
  -results. If this is the case, use <CODE>$SIG{ALRM}</CODE> to prevent the timeouts:
  +If something goes really wrong with your code, Perl may die with an ``Out
  +of memory!'' message and/or ``Callback called exit''. Common causes of this
  +are never-ending loops, deep recursion, or calling an undefined subroutine.
  +Here's one way to catch the problem: See Perl's INSTALL document for this
  +item: 
   
   <P>
  -<PRE>    $timeout = 10; # seconds
  -  eval {
  -    local $SIG{ALRM} =
  -        sub { die &quot;Sorry timed out. Please try again\n&quot; };
  -    alarm $timeout;
  -    ... db stuff ...
  -    alarm 0;
  -  };
  -  
  -  die $@ if $@;
  +<PRE>  =item -DPERL_EMERGENCY_SBRK
   </PRE>
   <P>
  -But, as lately it was discovered <CODE>local $SIG{'ALRM'}</CODE> does not restore the original underlying C handler. It was fixed in the
  -mod_perl 1.19_01 (CVS version). As a matter of fact none of the
  -<CODE>local $SIG{FOO}</CODE> restore the original C handler - read <A HREF="././debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A> for a debug technique and a possible workaround.
  -
  +<PRE>  If PERL_EMERGENCY_SBRK is defined, running out of memory need not be a
  +  fatal error: a memory pool can allocated by assigning to the special
  +  variable $^M.  See perlvar(1) for more details.
  +</PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Where_do_the_warnings_errors_go_">Where do the warnings/errors go?</A></H1></CENTER>
  +If you compile with that option and add '<CODE>use Apache::Debug level =&amp;gt;
  +4;</CODE>' to your PerlScript, it will allocate the <CODE>$^M</CODE> emergency pool and the <CODE>$SIG{__DIE__}</CODE> handler will call <CODE>Carp::confess</CODE>, giving you a stack trace which should reveal where the problem is. See
  +the
  +<CODE>Apache::Resource</CODE> module for prevention of spinning httpds.
  +
   <P>
  -Your CGI does not work and you want to see what the problem is. The best
  -idea is to check out any errors that the server may be reporting. Where I
  -can find these errors?
  +Note that perl-5.005+ has <CODE>PERL_EMERGENCY_SBRK</CODE> turned on by default.
   
   <P>
  -Generally all errors are logged into an error_log file. The exact file
  -location and name are defined in the http.conf file. Look for the
  -<CODE>ErrorLog</CODE> parameter. My httpd.conf says:
  +The other trick is to have a startup script initialize
  +<CODE>Carp::confess</CODE>, like so:
   
   <P>
  -<PRE>  ErrorLog var/logs/error_log
  +<PRE>  use Carp ();
  +  eval { Carp::confess(&quot;init&quot;) };
   </PRE>
   <P>
  -Hey, where is the beginning of the path? There is another Apache parameter
  -called <CODE>ServerRoot</CODE>. Every time apache sees a value of the parameter with no absolute path
  -(e.g <CODE>/tmp/my.txt</CODE>) but with relative path (e.g <CODE>my.txt</CODE>) it prepends the value of the <CODE>ServerRoot</CODE> to this value. I have:
  +this way, when the real problem happens, <CODE>Carp::confess</CODE> doesn't eat memory in the emergency pool (<CODE>$^M</CODE>).
   
   <P>
  -<PRE>  ServerRoot /usr/local/apache
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Invalid_command_PerlHandler_">Invalid command 'PerlHandler'...</A></H1></CENTER>
  +<P>
  +<PRE>  Syntax error on line 393 of /etc/httpd/conf/httpd.conf: Invalid
  +  command 'PerlHandler', perhaps mis-spelled or defined by a module
  +  not included in the server configuration [FAILED]
   </PRE>
   <P>
  -So I will look for error_log file at
  -<CODE>/usr/local/apache/var/logs/error_log</CODE>. Of course you can also use an absolute path to define the file's location
  -at the file system.
  +Happens when you have a mod_perl enabled Apache compiled with DSO
  +(Generally it's an installed RPM or other binary package). You have to tell
  +apache to load mod_perl by adding:
   
   <P>
  -&lt;META&gt;: is this 100% correct?
  -
  +<PRE>  AddModule mod_perl.c
  +</PRE>
   <P>
  -But there are cases when errors don't go to the error_log file. For example
  -some errors are being printed to the console (tty) you have executed the
  -httpd from (unless you redirected the httpd's stderr flow). This happens
  -when the server didn't open the error_log file for writing yet.
  +in your config file.
   
   <P>
  -For example, if you have mistakenly entered a non-existent directory path
  -in your <CODE>ErrorLog</CODE> directive, the error message will be printed on the controlling tty. Or, if
  -the error happens when server executes
  -<CODE>PerlRequire</CODE> or <CODE>PerlModule</CODE> directive you might see the errors here also.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="_warn_child_process_30388_did_n">[warn] child process 30388 did not exit, sending another SIGHUP</A></H1></CENTER>
   <P>
  -You are probably wonder where all the errors go when you are running the
  -server in single mode (<CODE>httpd -X</CODE>). They go to the console. That is because when running in the single mode
  -there is no parent httpd process to perform all the logging. It includes
  -all the status messages that generally show up in the error_log file.
  +From mod_perl.pod: With Apache versions 1.3.0 and higher, mod_perl will
  +call the <CODE>perl_destruct()</CODE> Perl API function during the child
  +exit phase. This will cause proper execution of <STRONG>END</STRONG> blocks found during server startup along with invoking the <STRONG>DESTROY</STRONG> method on global objects who are still alive. It is possible that this
  +operation may take a long time to finish, causing problems during a
  +restart. If your code does not contain and <STRONG>END</STRONG> blocks or <STRONG>DESTROY</STRONG> methods which need to be run during child server shutdown, this destruction
  +can be avoided by setting the <EM>PERL_DESTRUCT_LEVEL</EM> environment variable to <CODE>-1</CODE>.
   
   <P>
  -&lt;/META&gt;
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A></H1></CENTER>
  +<P>
  +<PRE>  RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl
  +              into a real path to the filename. Please refer to the
  +              manpage for more information
  +              or use the complete method's call like:
  +              $r-&gt;handler(uri,filename);\n&quot;;
  +</PRE>
  +<P>
  +This warning shows up when RegistryLoader fails to translate the URI into
  +the corresponding filesystem path. Most of failures happen when one passes
  +a file path instead of URI. (A reminder: /home/httpd/perl/test.pl is a file
  +path, while /perl/test.pl is an URI). In most cases all you have to do is
  +to pass something that RegistryLoader expects to get - the URI, but there
  +are more complex cases. RegistryLoader's man page shows how to handle these
  +cases as well (watch for the <CODE>trans()</CODE> sub).
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A></H1></CENTER>
  +<CENTER><H1><A NAME="Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A></H1></CENTER>
   <P>
  -Perl uses <CODE>sh()</CODE> for its iteractions for <CODE>system()</CODE> and <CODE>open()</CODE>
  -calls. So when you want to set a temporary variable when you call a script
  -from your CGI you do:
  +Unfortunately, not all perl modules are robust enough to survive reload,
  +for them, unusual situation. PerlFreshRestart does not much more than:
   
   <P>
  -<PRE> open UTIL, &quot;USER=stas ; script.pl | &quot; or die &quot;...: $!\n&quot;;
  +<PRE>  while (my($k,$v) = each %INC) {
  +    delete $INC{$k};
  +    require $k;
  +  }
   </PRE>
   <P>
  -or
  +Besides that, it flushes the Apache::Registry cache, and empties any
  +dynamic stacked handlers (e.g. PerlChildInitHandler).
   
   <P>
  -<PRE>  system &quot;USER=stas ; script.pl&quot;;
  -</PRE>
  +Lots of SegFaults and other problems were reported by users who have turned <CODE>PerlFreshRestart</CODE>  <STRONG>On</STRONG>. Most of them have gone away when it was turned off. It doesn't mean that
  +you shouldn't use it, if it works for you. Just be aware of the dragons...
  +
   <P>
  -This is useful for example if you need to invoke a script that uses CGI.pm
  -from within a mod_perl script. We are tricking the perl script to think
  -it's a simple CGI, which is not running under mod_perl.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A></H1></CENTER>
  +<P>
  +See <A HREF="././performance.html#Choosing_MaxClients">Choosing MaxClients</A>.
   
   <P>
  -<PRE>  open(PUBLISH, &quot;GATEWAY_INTERFACE=CGI/1.1 ; script.cgi
  -       \&quot;param1=value1&amp;param2=value2\&quot; |&quot;) or die &quot;...: $!\n&quot;;
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near &quot;line arguments:&quot;</A></H1></CENTER>
  +<P>
  +<PRE>  syntax error at /dev/null line 1, near &quot;line arguments:&quot;
  +  Execution of /dev/null aborted due to compilation errors.
  +  parse: Undefined error: 0
   </PRE>
   <P>
  -Make sure, that the parameters you pass are shell safe (All ``unsafe''
  -characters like single-tick should be properly escaped).
  +There is a chance that your <CODE>/dev/null</CODE> device is broken. Try:
   
   <P>
  -However you are fork-ing to run a Perl script, so you have thrown the so
  -hardly gained performance out the window. Whatever script.cgi is now, it
  -should be moved to a module with a subroutine you can call directly from
  -your script, to avoid the fork.
  -
  +<PRE>  % sudo echo &gt; /dev/null
  +</PRE>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -13385,7 +15828,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]
  +	     [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="correct_headers.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -13398,7 +15841,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/26/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  @@ -13425,7 +15868,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Runtime Warnings and Errors: Where and Why.</TITLE>
  +   <TITLE>mod_perl guide: Correct Headers - A quick guide for mod_perl users</TITLE>
      <META NAME="GENERATOR" CONTENT="Pod2HTML [Perl/Linux]">
      <META NAME="Author" CONTENT="Stas Bekman">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, Guidelines, Scenarios and Troubleshottings">
  @@ -13444,32 +15887,53 @@
   <H1 ALIGN=CENTER>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=LEFT></A>
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
  -Runtime Warnings and Errors: Where and Why.</H1>
  +Correct Headers - A quick guide for mod_perl users</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  -<UL>
  -
  -	<LI><A HREF="#General_Advice">General Advice </A>
  -	<LI><A HREF="#Incorrect_line_number_reporting_">Incorrect line number reporting in error/warn log messages</A>
  -	<LI><A HREF="#Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A>
  -	<LI><A HREF="#Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A>
  -	<LI><A HREF="#mod_perl_rwrite_returned_1">mod_perl: rwrite returned -1</A>
  -	<LI><A HREF="#caught_SIGPIPE_in_process">caught SIGPIPE in process</A>
  -	<LI><A HREF="#Client_hit_STOP_or_Netscape_bit_">Client hit STOP or Netscape bit it!</A>
  -	<LI><A HREF="#Constant_subroutine_redefine">Constant subroutine ... redefined</A>
  -	<LI><A HREF="#Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</A>
  -	<LI><A HREF="#Can_t_undef_active_subroutine">Can't undef active subroutine</A>
  -	<LI><A HREF="#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
  -	<LI><A HREF="#Undefined_subroutine_Apache_RO">Undefined subroutine &amp;Apache::ROOT::perl::test_2epl::some_function called at</A>
  -	<LI><A HREF="#Can_t_load_auto_DBI_DBI_so_">Can't load '.../auto/DBI/DBI.so' for module DBI</A>
  -	<LI><A HREF="#Callback_called_exit">Callback called exit</A>
  -	<LI><A HREF="#Out_of_memory_">Out of memory!</A>
  -	<LI><A HREF="#_warn_child_process_30388_did_n">[warn] child process 30388 did not exit, sending another SIGHUP</A>
  -	<LI><A HREF="#RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A>
  -	<LI><A HREF="#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
  -	<LI><A HREF="#server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A>
  -	<LI><A HREF="#syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near &quot;line arguments:&quot;</A>
  +	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
  +	<LI><A HREF="#The_origin_of_this_chapter">The origin of this chapter</A>
  +	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
  +	<LI><A HREF="#1_Why_headers">1) Why headers</A>
  +	<LI><A HREF="#2_Which_Headers">2) Which Headers</A>
  +	<UL>
  +
  +		<LI><A HREF="#2_1_Date_related_headers">2.1) Date related headers</A>
  +		<LI><A HREF="#2_1_1_Date">2.1.1) Date</A>
  +		<LI><A HREF="#2_1_2_Last_Modified">2.1.2) Last-Modified</A>
  +		<LI><A HREF="#2_1_3_Expires_and_Cache_Control">2.1.3) Expires and Cache-Control</A>
  +		<LI><A HREF="#2_2_Content_related_headers">2.2) Content related headers</A>
  +		<LI><A HREF="#2_2_1_Content_Type">2.2.1) Content-Type</A>
  +		<LI><A HREF="#2_2_2_Content_Length">2.2.2) Content-Length</A>
  +		<LI><A HREF="#2_2_3_Entity_Tags">2.2.3) Entity Tags</A>
  +		<LI><A HREF="#2_3_Content_Negotiation">2.3) Content Negotiation</A>
  +		<LI><A HREF="#2_3_1_Vary">2.3.1) Vary</A>
  +	</UL>
  +
  +	<LI><A HREF="#3_Requests">3) Requests</A>
  +	<UL>
  +
  +		<LI><A HREF="#3_1_HEAD">3.1) HEAD</A>
  +		<LI><A HREF="#3_2_POST">3.2) POST</A>
  +		<LI><A HREF="#3_3_C_GET_">3.3) &lt;CODE&gt;GET&lt;/CODE&gt;</A>
  +		<LI><A HREF="#3_4_Conditional_GET">3.4) Conditional GET</A>
  +		<LI><A HREF="#3_Avoiding_to_deal_with_them">3.) Avoiding to deal with them</A>
  +	</UL>
  +
  +	<LI><A HREF="#References_and_other_literature">References and other literature</A>
  +	<UL>
  +
  +		<LI><A HREF="#_1_">[1]</A>
  +		<LI><A HREF="#_2_">[2]</A>
  +		<LI><A HREF="#_3_">[3]</A>
  +		<LI><A HREF="#_4_">[4]</A>
  +		<LI><A HREF="#_5_">[5]</A>
  +	</UL>
  +
  +	<LI><A HREF="#VERSION">VERSION</A>
  +	<LI><A HREF="#AUTHOR">AUTHOR</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -13496,366 +15960,710 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="General_Advice">General Advice</A></H1></CENTER>
  +<CENTER><H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1></CENTER>
   <P>
  -Enabling <CODE>use diagnostics;</CODE> generally helps you to determine the source of the problem and how to solve
  -it. See <A HREF="././porting.html#diagnostics_pragma">diagnostics pragma</A> for more info.
  +As there is always more than one way to do it, I'm tempted to believe one
  +must be the best. Hardly ever am I right.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Incorrect_line_number_reporting_">Incorrect line number reporting in error/warn log messages</A></H1></CENTER>
  +<CENTER><H1><A NAME="The_origin_of_this_chapter">The origin of this chapter</A></H1></CENTER>
   <P>
  -See <A HREF="././warnings.html#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
  +This chapter has been contributed to the Guide by Andreas Koenig. You will
  +find the references and other related info at the bottom of this page. I'll
  +try to keep it concurrent with the Master version which resides on CPAN. If
  +in doubt -- always check the CPAN for
  +<CODE>Apache::correct_headers</CODE>.
  +
  +<P>
  +If you have any questions regarding this specific document only, please
  +refer to Andreas, since he is the guru on this subject. On any other matter
  +please contact the mod_perl mailing list.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1></CENTER>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="1_Why_headers">1) Why headers</A></H1></CENTER>
  +<P>
  +Dynamic Content is dynamic, after all, so why would anybody care about HTTP
  +headers? Header composition is an often neglected task in the CGI world.
  +Because pages are generated dynamically, you might believe that pages
  +without a <CODE>Last-Modified</CODE> header are fine, and that an
  +<CODE>If-Modified-Since</CODE> header in the browser's request can go by unnoticed. This laissez-faire
  +principle gets in the way when you try to establish a server that is
  +entirely driven by dynamic components and the number of hits is
  +significant.
   
  +<P>
  +If the number of hits is not significant, don't bother to read this
  +document.
   
  +<P>
  +If the number of hits is significant, you might want to consider what
  +cache-friendliness means (you may also want to read
  +<A HREF="././correct_headers.html#_4_">[4]</A>) and how you can cooperate with caches to increase the performace of your
  +site. Especially if you use a squid in accelerator mode (helpful hints for
  +squid, see
  +<A HREF="././correct_headers.html#_1_">[1]</A>), you will have a strong motivation to cooperate with it. This document
  +may help you to do it correctly.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A></H1></CENTER>
  +<CENTER><H1><A NAME="2_Which_Headers">2) Which Headers</A></H1></CENTER>
   <P>
  -<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +The HTTP standard (v 1.1 is specified in <A HREF="././correct_headers.html#_3_">[3]</A>, v 1.0 in <A HREF="././correct_headers.html#_2_">[2]</A>) describes lots of headers. In this document, we only discuss those
  +headers which are most relevant to caching.
   
   <P>
  +I have grouped the headers in three groups: date headers, content headers,
  +and the special Vary header.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_1_Date_related_headers">2.1) Date related headers</A></H2></CENTER>
   <P>
  -<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="2_1_1_Date">2.1.1) Date</A></H2></CENTER>
  +<P>
  +Section 14.18 of the HTTP standard deals with the circumstances, under
  +which you must or must not send a <CODE>Date</CODE> header. For almost everything a normal mod_perl user is doing, a <CODE>Date</CODE> header needs to be generated. But the mod_perl programmer doesn't have to
  +care for this header, the apache server guarantees that this header is
  +being sent.
  +
  +<P>
  +In http_protocol.c the <CODE>Date</CODE> header is set according to
  +<CODE>$r-&amp;gt;request_time</CODE>. A modperl script can read, but not change,
  +<CODE>$r-&amp;gt;request_time</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_rwrite_returned_1">mod_perl: rwrite returned -1</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_1_2_Last_Modified">2.1.2) Last-Modified</A></H2></CENTER>
   <P>
  -That message happens when the client breaks the connection while your
  -script is trying to write to the client. With Apache 1.3.x, you should only
  -see the rwrite messages if LogLevel is set to debug.
  +Section 14.29 of the HTTP standard deals with this. The
  +<CODE>Last-Modified</CODE> header is mostly used as a so-called weak validator. I'm citing two
  +sentences from the HTTP specs:
  +
  +<P>
  +<PRE>  A validator that does not always change when the resource
  +  changes is a &quot;weak validator.&quot;
  +</PRE>
  +<P>
  +<PRE>  One can think of a strong validator as one that changes
  +  whenever the bits of an entity changes, while a weak value
  +  changes whenever the meaning of an entity changes.
  +</PRE>
  +<P>
  +This tells us that we should consider the semantics of the page we are
  +generating and not the date when we are running. The question is, when did
  +the <STRONG>meaning</STRONG> of this page change last time? Let's imagine, the document in question is a
  +text-to-gif renderer that takes as input a font to use, background and
  +foreground color, and a string to render. Although the actual image is
  +created on-the-fly, the semantics of the page are determined when the
  +script has changed the last time, right?
   
   <P>
  -This bug has been fixed in mod_perl 1.19_01 (CVS version).
  +Actually, there are a few more things relevant: the semantics also change a
  +little when you update one of the fonts that may be used or when you update
  +your <CODE>ImageMagick</CODE> or whatever program. It's something you should consider, if you want to get
  +it right.
   
   <P>
  +If you have several components that compose a page, you should ask the
  +question for all components, when they changed their semantic behaviour
  +last time. And then pick the maximum of those times.
  +
  +<P>
  +mod_perl offers you two convenient methods to deal with this header:
  +update_mtime and set_last_modified. Both these two and several more methods
  +are not available in the normal mod_perl environment but get added silently
  +when you require <CODE>Apache::File</CODE>. As of this writing,
  +<CODE>Apache::File</CODE> comes without a manpage, so you have to read about it in Chapter 9 of <A HREF="././correct_headers.html#_5_">[5]</A>.
  +
  +<P>
  +<CODE>update_mtime()</CODE> takes a UNIX time as argument and sets Apache's
  +request structure finfo.st_mtime to this value. It does so only when the
  +argument is greater than an already stored <CODE>finfo.st_mtime</CODE>.
  +
  +<P>
  +<CODE>set_last_modified()</CODE> sets the outgoing header <CODE>Last-Modified</CODE> to the string that corresponds to the stored finfo.st_mtime. By passing a
  +UNIX time to <CODE>set_last_modified(),</CODE> mod_perl calls
  +<CODE>update_mtime()</CODE> with this argument first.
  +
  +<P>
  +<PRE>  use Apache::File;
  +  use Date::Parse;
  +  # Date::Parse parses RCS format, Apache::Util::parsedate doesn't
  +  $Mtime ||=
  +    Date::Parse::str2time(substr q$Date: 1999/10/15 22:52:35 $, 6);
  +  $r-&gt;set_last_modified($Mtime);
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="caught_SIGPIPE_in_process">caught SIGPIPE in process</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_1_3_Expires_and_Cache_Control">2.1.3) Expires and Cache-Control</A></H2></CENTER>
   <P>
  -<PRE>  [modperl] caught SIGPIPE in process 1234
  -  [modperl] process 1234 going to Apache::exit with status...
  +Section 14.21 of the HTTP standard deals with the <CODE>Expires</CODE>
  +header. The meaning of the <CODE>Expires</CODE> header is to determine a point in time after which this document should be
  +considered out of date (stale). Don't confuse this with the very different
  +meaning of the
  +<CODE>Last-Modified</CODE>. The <CODE>Expires</CODE> header is useful to avoid unnecessary validation from now on until the
  +document expires and it helps the recipient to clean up his stored
  +documents. A sentence from the HTTP standard:
  +
  +<P>
  +<PRE>  The presence of an Expires field does not imply that the
  +  original resource will change or cease to exist at, before, or
  +  after that time.
   </PRE>
   <P>
  -That's the <STRONG>$SIG{PIPE}</STRONG> handler installed by mod_perl/Apache::SIG, called if a connection timesout
  -or Client presses the 'Stop' button. It gives you an opportunity to do
  -cleanups if the script was aborted in the middle of its execution. See <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A> for more info.
  +So think before you set up a time when you believe, a resource should be
  +regarded as stale. Most of the time I can determine an expected lifetime
  +from ``now'', that is the time of the request. I would not recommend to
  +hardcode the date of Expiry, because when you forget that you did that, and
  +the date arrives, you will serve ``already expired'' documents that cannot
  +be cached at all by anybody. If you believe, a resource will never expire,
  +read this quote from the HTTP specs:
   
   <P>
  -If your mod_perl version &lt; 1.17 you might get the message in the
  -following section...
  +<PRE>  To mark a response as &quot;never expires,&quot; an origin server sends an
  +  Expires date approximately one year from the time the response is
  +  sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one
  +  year in the future.
  +</PRE>
  +<P>
  +Now the code for the mod_perl programmer that wants to expire a document
  +half a year from now:
  +
  +<P>
  +<PRE>  $r-&gt;header_out('Expires',
  +                 HTTP::Date::time2str(time + 180*24*60*60));
  +</PRE>
  +<P>
  +A very handy alternative to this computation is available in HTTP 1.1, the
  +cache control mechanism. Instead of setting the <CODE>Expires</CODE> header you can specify a delta value in a <CODE>Cache-Control</CODE> header. You can do that by running just
  +
  +<P>
  +<PRE>  $r-&gt;header_out('Cache-Control', &quot;max-age=&quot; . 180*24*60*60);
  +</PRE>
  +<P>
  +which is, of course much cheaper than the above because perl computes the
  +value only once at compile time and optimizes it away as a constant.
  +
  +<P>
  +As this alternative is only available in HTTP 1.1 and old cache servers may
  +not understand this header, it is advisable to send both headers. In this
  +case the <CODE>Cache-Control</CODE> header takes precedence, so that the <CODE>Expires</CODE> header is ignored on HTTP 1.1 complient servers. Or you could go with an
  +if/else clause:
   
   <P>
  +<PRE>  if ($r-&gt;protocol =~ /(\d\.\d)/ &amp;&amp; $1 &gt;= 1.1){
  +    $r-&gt;header_out('Cache-Control', &quot;max-age=&quot; . 180*24*60*60);
  +  } else {
  +    $r-&gt;header_out('Expires',
  +                   HTTP::Date::time2str(time + 180*24*60*60));
  +  }
  +</PRE>
  +<P>
  +If you restart your apache regularly, I'd save the <CODE>Expires</CODE>
  +header in a global variable. Oh, well, this is probably over-engineered
  +now.
  +
  +<P>
  +If people are determined that their document shouldn't be cached, here is
  +the easy way to set a suitable <CODE>Expires</CODE> header...
  +
  +<P>
  +The call <CODE>$r-&amp;gt;no_cache(1)</CODE> will cause apache to generate an
  +<CODE>Expires</CODE> header with the same content as the Date-header in the response, so that
  +the document ``expires immediately''. Don't set
  +<CODE>Expires</CODE> with <CODE>$r-&amp;gt;header_out</CODE> if you use <CODE>$r-&amp;gt;no_cache</CODE>, because header_out takes precedence. the problem that remains are broken
  +browsers that ignore <CODE>Expires</CODE> headers.
  +
  +<P>
  +Currently to avoid caching alltogether
  +
  +<P>
  +<PRE>  my $headers = $r-&gt;headers_out;
  +  $headers-&gt;{'Pragma'} = $headers-&gt;{'Cache-control'} = 'no-cache';
  +  $r-&gt;no_cache(1);
  +</PRE>
  +<P>
  +works with the major browsers.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Client_hit_STOP_or_Netscape_bit_">Client hit STOP or Netscape bit it!</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_2_Content_related_headers">2.2) Content related headers</A></H2></CENTER>
   <P>
  -<PRE>  Client hit STOP or Netscape bit it!
  -  Process 2493 going to Apache::exit with status=-2
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="2_2_1_Content_Type">2.2.1) Content-Type</A></H2></CENTER>
  +<P>
  +You are most probably familiar with <CODE>Content-Type</CODE>. Sections 3.7, 7.2.1 and 14.17 of the HTTP specs deal with the details.
  +Mod_perl has the <CODE>content_type()</CODE> method to deal with this
  +header, as in
  +
  +<P>
  +<PRE>  $r-&gt;content_type(&quot;image/png&quot;);
   </PRE>
   <P>
  -You will see this message in mod_perl &lt; 1.17. See <A HREF="././warnings.html#caught_SIGPIPE_in_process">caught SIGPIPE in process</A>.
  +<CODE>Content-Type</CODE> SHOULD be included in all messages according to the specs, and apache will
  +generate one if you don't. It will be whatever is specified in the relevant <CODE>DefaultType</CODE> configuration directive or
  +<CODE>text/plain</CODE> if none is active.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Constant_subroutine_redefine">Constant subroutine ... redefined</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_2_2_Content_Length">2.2.2) Content-Length</A></H2></CENTER>
   <P>
  -That's a mandatory warning inside Perl. It happens only if you modify your
  -script and Apache::Registry reloads it. Perl is warning you that the
  -<CODE>subroutine(s)</CODE> were redefined. It is mostly harmless. If you
  -don't like seeing those, just <CODE>kill -USR2</CODE> (graceful restart) apache when you modify your scripts.
  +The <CODE>Content-Length</CODE> header according to the HTTP specs section 14.13, is the number of octets
  +in the body of a message. If it can be determined prior to sending, it can
  +be very useful for several reasons to include it. The most important reason
  +why it is good to include it, is that keepalive requests only work with
  +responses that contain a
  +<CODE>Content-Length</CODE> header. In mod_perl you can say
   
   <P>
  -<PRE>  &lt;META&gt;
  -  Someone said: 
  -  You won't see that warning in this case with 5.004_05 or 5.005+. 
  +<PRE>  $r-&gt;header_out('Content-Length', $length);
   </PRE>
  +<P>
  +If you use <CODE>Apache::File</CODE>, you get the additional set_content_length method for the Apache class
  +which is a bit more efficient than the above. You can then say:
  +
   <P>
  -<PRE>  I'm running perl5.00502 and I still get these warnings???
  +<PRE>  $r-&gt;set_content_length($length);
   </PRE>
  +<P>
  +The <CODE>Content-Length</CODE> header can have an important impact on caches by invalidating cache entries
  +as the following citation of the specs explains:
  +
   <P>
  -<PRE>  Who is right?
  -  &lt;/META&gt;
  +<PRE>  The response to a HEAD request MAY be cacheable in the sense that
  +  the information contained in the response MAY be used to update a
  +  previously cached entity from that resource. If the new field values
  +  indicate that the cached entity differs from the current entity (as
  +  would be indicated by a change in Content-Length, Content-MD5, ETag
  +  or Last-Modified), then the cache MUST treat the cache entry as
  +  stale.
   </PRE>
   <P>
  +So be careful to never send a wrong <CODE>Content-Length</CODE>, be it in a GET or in a HEAD request.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_2_3_Entity_Tags">2.2.3) Entity Tags</A></H2></CENTER>
   <P>
  -The script below will print a warning like above, moreover it will print
  -the whole script as a part of the warning message:
  +An <CODE>Entity Tag</CODE> is a validator that can be used instead of or in addition to the <CODE>Last-Modified</CODE> header. An entity tag is a quoted string that has the property to identify
  +different versions of a particular resource. An entity tag can be added to
  +the response headers like so:
   
   <P>
  -<PRE>  #!/usr/bin/perl -w
  -  use strict;
  -  print &quot;Content-type: text/html\n\n&quot;;
  -  print &quot;Hello $undefined&quot;;
  +<PRE>  $r-&gt;header_out(&quot;ETag&quot;,&quot;\&quot;$VERSION\&quot;&quot;);
   </PRE>
   <P>
  -The warning:
  +Note: mod_perl offers the <CODE>Apache::set_etag()</CODE> method if you have loaded <CODE>Apache::File</CODE>. It is strongly recommended to not use this method unless you know what
  +you are doing. <CODE>set_etag()</CODE> is expecting that it is used in
  +conjunction with a static request for a file on disk that has been
  +<CODE>stat()ed</CODE> in the course of the current request. It is
  +inappropriate and dangerous to use it for dynamic content.
   
   <P>
  -<PRE>  Global symbol &quot;$undefined&quot; requires explicit package name at /usr/apps/foo/cgi/tmp.pl line 4.
  -          eval 'package Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub handler {
  -  #line 1 /usr/apps/foo/cgi/tmp.pl
  -  BEGIN {$^W = 1;}#!/usr/bin/perl -w
  -  use strict;
  -  print &quot;Content-type: text/html\\n\\n&quot;;
  -  print &quot;Hello $undefined&quot;;
  -  
  -  
  -  }
  -  ;' called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 168
  -          Apache::Registry::compile('package
  -        Apache::ROOT::perl::tmp_2epl;use Apache qw(exit);sub han...') 
  -        called at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 121
  -          Apache::Registry::handler('Apache=SCALAR(0x205026c0)') called at /usr/apps/foo/cgi/tmp.pl line 4
  -          eval {...} called at /usr/apps/foo/cgi/tmp.pl line 4
  -  [Sun Nov 15 15:15:30 1998] [error] Undefined subroutine &amp;Apache::ROOT::perl::tmp_2epl::handler called at /
  -  usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 135.
  -  
  -  [Sun Nov 15 15:15:30 1998] [error] Goto undefined subroutine &amp;Apache::Constants::SERVER_ERROR at /usr/apps
  -  /lib/perl5/site_perl/5.005/aix/Apache/Constants.pm line 23.
  -</PRE>
  +By sending an entity tag you promise to the recipient, that you will not
  +send the same <CODE>ETag</CODE> for the same resource again unless the content is equal to the one you are
  +sending now (see below for what equality means).
  +
   <P>
  -The error is simple to fix. When you use the <CODE>use strict;</CODE> pragma (and you should...), all variables should be defined before being
  -used.
  +The pros and cons of using entity tags are discussed in section 13.3 of the
  +HTTP specs. For us mod_perl programmers that discussion can be summed up as
  +follows:
   
   <P>
  -The bad thing is that sometimes the whole script (possibly, thousands of
  -lines) is printed to error_log file as a code that the server has tried to <STRONG>eval()</STRONG>uate.
  +There are strong and weak validators. Strong validators change whenever a
  +single bit changes in the response. Weak validators change when the meaning
  +of the response changes. Strong validators are needed for caches to allow
  +for sub-range requests. Weak validators allow a more efficient caching of
  +equivalent objects. Algorithms like MD5 or SHA are good strong validators,
  +but what we usually want, when we want to take advantage of caching, is a
  +good weak validator.
   
   <P>
  -As Doug answered to this question:
  +A <CODE>Last-Modified</CODE> time, when used as a validator in a request, can be strong or weak,
  +depending on a couple of rules. Please refer to section 13.3.3 of the HTTP
  +standard to understand these rules. This is mostly relevant for range
  +requests as this citation of section 14.27 explains:
   
   <P>
  -<PRE> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
  - That's what's expected if so.
  +<PRE>  If the client has no entity tag for an entity, but does have a
  +  Last-Modified date, it MAY use that date in a If-Range header.
   </PRE>
   <P>
  -It wasn't in my case, but may be yours. 
  +But it is not limited to range requests. Section 13.3.1 succintly states
  +that
   
   <P>
  -Bryan Miller said:
  +<PRE>  The Last-Modified entity-header field value is often used as a
  +  cache validator.
  +</PRE>
  +<P>
  +The fact that a <CODE>Last-Modified</CODE> date may be used as a strong validator can be pretty disturbing if we are
  +in fact changing our output slightly without changing the semantics of the
  +output. To prevent such kind of misunderstanding between us and the cache
  +servers in the response chain, we can send a weak validator in an <CODE>ETag</CODE>
  +header. This is possible because the specs say:
   
   <P>
  -<PRE> You might wish to try something more terse such as 
  - &quot;local $SIG{__WARN__} = \&amp;Carp::cluck;&quot;  The confess method is _very_
  - verbose and will tell you more than you might wish to know including
  - full source.
  +<PRE>  If a client wishes to perform a sub-range retrieval on a value for
  +  which it has only a Last-Modified time and no opaque validator, it
  +  MAY do this only if the Last-Modified time is strong in the sense
  +  described here.
   </PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Can_t_undef_active_subroutine">Can't undef active subroutine</A></H1></CENTER>
  +In other words: by sending them an <CODE>ETag</CODE> that is marked as weak we prevent them to use the Last-Modified header as a
  +strong validator.
  +
   <P>
  -<PRE>  Can't undef active subroutine at /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm line 102. 
  -  Called from package Apache::Registry, filename /usr/apps/lib/perl5/site_perl/5.005/aix/Apache/Registry.pm, line 102 
  +An <CODE>ETag</CODE> value is marked as a weak validator by prepending the string <CODE>W/</CODE> to the quoted string, otherwise it is strong. In perl this would mean
  +something like this:
  +
  +<P>
  +<PRE>  $r-&gt;header_out('ETag',&quot;W/\&quot;$VERSION\&quot;&quot;);
   </PRE>
   <P>
  -This problem is caused when, a client drops the connection while httpd is
  -in the middle of a write, httpd timeout happens, sending a SIGPIPE, and
  -Perl in that child is stuck in the middle of its eval context. This is
  -fixed by the Apache::SIG module which is called by default. This should not
  -happen unless you have code that is messing with <STRONG>$SIG{PIPE}</STRONG>. It's also triggered only when you've changed your script on disk and
  -mod_perl is trying to reload it.
  +Consider carefully, which string you choose to act as a validator. You are
  +left alone with this decision because...
  +
  +<P>
  +<PRE>  ... only the service author knows the semantics of a resource
  +  well enough to select an appropriate cache validation
  +  mechanism, and the specification of any validator comparison
  +  function more complex than byte-equality would open up a can
  +  of worms. Thus, comparisons of any other headers (except
  +  Last-Modified, for compatibility with HTTP/1.0) are never used
  +  for purposes of validating a cache entry.
  +</PRE>
  +<P>
  +If you are composing a message from multiple components, it may be
  +necessary to combine some kind of version information for all components
  +into a single string.
  +
  +<P>
  +If you are producing relative big documents or contents that do not change
  +frequently, you most likely will prefer a strong entity tag, thus giving
  +caches a chance to transfer the document in chunks. (Anybody in the mood to
  +add a chapter about ranges to this document?)
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A></H1></CENTER>
  +<CENTER><H2><A NAME="2_3_Content_Negotiation">2.3) Content Negotiation</A></H2></CENTER>
   <P>
  -Your code includes some undefined variable that you have used as if it was
  -already defined and initialized. For example:
  +A particularly wonderful but unfortunately not yet widely supported feature
  +that was introduced with HTTP 1.1 is content negotiation. The probably most
  +popular usage scenario of content negotiation is language negotiation. A
  +user specifies in his browser preferences the languages he understands and
  +how well he understands them. The browser includes these settings in an <CODE>Accept-Language</CODE> header when it sends the request to the server and the server then chooses
  +among several available representations of the document the one that fits
  +the user's preferences best. Content negotiation is not limited to
  +language. Citing the specs:
   
   <P>
  -<PRE>  $param = $q-&gt;param('test');
  -  print $param;
  +<PRE>  HTTP/1.1 includes the following request-header fields for enabling
  +  server-driven negotiation through description of user agent
  +  capabilities and user preferences: Accept (section 14.1), Accept-
  +  Charset (section 14.2), Accept-Encoding (section 14.3), Accept-
  +  Language (section 14.4), and User-Agent (section 14.43). However, an
  +  origin server is not limited to these dimensions and MAY vary the
  +  response based on any aspect of the request, including information
  +  outside the request-header fields or within extension header fields
  +  not defined by this specification.
   </PRE>
   <P>
  -<PRE>  vs.
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="2_3_1_Vary">2.3.1) Vary</A></H2></CENTER>
   <P>
  -<PRE>  $param = $q-&gt;param('test') || '';
  -  print $param;
  +In order to signal to the recipient that content negotiation has been used
  +to determine the best available representation for a given request, the
  +server must include a <CODE>Vary</CODE> header that tells the recipient, which of the request headers have been
  +used to determine it. So an answer may be generated like so:
  +
  +<P>
  +<PRE>  $r-&gt;header_out('Vary', join &quot;, &quot;, 'accept', 'accept-language',
  +                 'accept-encoding', 'user-agent');
   </PRE>
   <P>
  -In the second case, <CODE>$param</CODE> will always be <CODE>defined</CODE>, either
  -<CODE>$q-&amp;gt;param('test')</CODE> returns some value or <CODE>undef</CODE>.
  +While this may be in the header of a very cool page that greets the user
  +with something like
   
   <P>
  -Also read about <A HREF="././porting.html#Finding_the_line_number_the_erro">finding the line number the error/warning has been triggered at</A>.
  +<PRE>  Hallo Kraut, Dein NutScrape versteht zwar PNG aber leider
  +  kein GZIP.
  +</PRE>
  +<P>
  +it has the side effect of being expensive for a caching proxy. As of this
  +writing, squid (version 2.1PATCH2) does not cache resources at all that
  +come with a Vary header. So unless you find a clever workaround, you won't
  +enjoy your squid accelerator for these documents :-(
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Undefined_subroutine_Apache_RO">Undefined subroutine &amp;Apache::ROOT::perl::test_2epl::some_function called at</A></H1></CENTER>
  +<CENTER><H1><A NAME="3_Requests">3) Requests</A></H1></CENTER>
   <P>
  -See <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>.
  +Section 13.11 of the specs states that the only two cachable methods are <CODE>GET</CODE> and <CODE>HEAD</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Can_t_load_auto_DBI_DBI_so_">Can't load '.../auto/DBI/DBI.so' for module DBI</A></H1></CENTER>
  +<CENTER><H2><A NAME="3_1_HEAD">3.1) HEAD</A></H2></CENTER>
   <P>
  -Check that all your modules are compiled with the same perl that is being
  -compiled into mod_perl. perl 5.005 and 5.004 are not binary compatible by
  -default.
  +Among the above recommended headers, the date-related ones (<CODE>Date</CODE>,
  +<CODE>Last-Modified</CODE>, and <CODE>Expires</CODE>/<CODE>Cache-Control</CODE>) are usually easy to produce and thus should be computed for <CODE>HEAD</CODE> requests just the same as for <CODE>GET</CODE> requests.
   
   <P>
  -Other known causes of this problem: OS distributions that ship with a
  -(broken) binary Perl installation. The `perl' program and `libperl.a'
  -library are somehow built with different binary compatibility flags.
  +The <CODE>Content-Type</CODE> and <CODE>Content-Length</CODE> headers should be exactly the same as would be supplied to the
  +corresponding <CODE>GET</CODE> request. But as it can be expensive to compute them, they can just as well
  +be omitted, there is nothing in the specs that forces you to compute them.
   
   <P>
  -The solution to these problems is to rebuild Perl and any extension modules
  -from a fresh source tree. Tip for running Perl's Configure script: use the
  -`-des' flags to accepts defaults and `-D' flag to override certain
  -attributes:
  +What is important for the mod_perl programmer is that the response to a <CODE>HEAD</CODE> request MUST NOT contain a message-body. The code in your mod_perl handler
  +might look like this:
   
   <P>
  -<PRE>  % ./Configure -des -Dcc=gcc ... &amp;&amp; make test &amp;&amp; make install
  - 
  -Read Perl's INSTALL doc for more details.
  +<PRE>  # compute all headers that are easy to compute
  +  if ( $r-&gt;header_only ){ # currently equivalent for $r-&gt;method eq &quot;HEAD&quot;
  +    $r-&gt;send_http_header;
  +    return OK;
  +  }
   </PRE>
   <P>
  -Solaris OS specific: 
  +If you are running a squid accelerator, it will be able to handle the whole <CODE>HEAD</CODE> request for you, but under some circumstances it may not be allowed to do
  +so.
   
   <P>
  -Can't load DBI or similar Error for the IO module or whatever dynamic
  -module mod_perl tries to pull in first. The solution is to re-configure,
  -re-build and re-install Perl and dynamic modules with the following flags
  -when Configure asks for ``additional LD flags'': -Xlinker --export-dynamic
  -or
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="3_2_POST">3.2) POST</A></H2></CENTER>
  +<P>
  +The response to a <CODE>POST</CODE> request is not cachable due to an underspecification in the HTTP standards.
  +Section 13.4 does not forbid caching of responses to <CODE>POST</CODE> request but no other part of the HTTP standard explains how caching of <CODE>POST</CODE> requests could be implemented, so we are in a vacuum here and all existing
  +caching servers therefore refuse to implement caching of <CODE>POST</CODE> requests. This may change if somebody does the footwork of defining the
  +semantics for cache operations on <CODE>POST</CODE>. Note that some browsers with their more aggressive caching do implement
  +caching of <CODE>POST</CODE> requests.
   
   <P>
  -<PRE>  -Xlinker -E
  +Note: If you are running a squid accelerator, you should be aware that it
  +accelerates outgoing traffic, but does not bundle incoming traffic, so if
  +you have long post requests, the squid doesn't buy you anything. So always
  +consider to use a <CODE>GET</CODE> instead of a <CODE>POST</CODE> if possible.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="3_3_C_GET_">3.3) &lt;CODE&gt;GET&lt;/CODE&gt;</A></H2></CENTER>
  +<P>
  +A normal <CODE>GET</CODE> is what we usually write our mod_perl programs for. Nothing special about
  +it. We send our headers followed by the body.
  +
  +<P>
  +But there is a certain case that needs a workaround to achieve better
  +cacheability. We need to deal with the ``?'' in the rel_path part of the
  +requested URI. Section 13.9 specifies, that
  +
  +<P>
  +<PRE>  ... caches MUST NOT treat responses to such URIs as fresh unless
  +  the server provides an explicit expiration time. This specifically
  +  means that responses from HTTP/1.0 servers for such URIs SHOULD NOT
  +  be taken from a cache.
   </PRE>
   <P>
  -This problem is only known to be caused by installing gnu ld under Solaris.
  +You're tempted to believe, that we are using HTTP 1.1 and sending an
  +explicit expiration time, so we're on the safe side? Unfortunately reality
  +is a little bit different. It has been a bad habit for quite a long time to
  +misconfigure cache servers such that they treat all
  +<CODE>GET</CODE> requests containing a question mark as uncacheable. People even used to
  +mark everything as uncacheable that contained the string
  +<CODE>cgi-bin</CODE>.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Callback_called_exit">Callback called exit</A></H1></CENTER>
  +To work around this bug in the heads, I have dropped the habit to call my
  +CGI directories <CODE>cgi-bin</CODE> and I have written the following handler that lets me work with CGI-like
  +query strings without rewriting the software that deals with them, namely <CODE>Apache::Request</CODE> or <CODE>CGI.pm</CODE>.
  +
  +<P>
  +<PRE>  sub handler {
  +    my($r) = @_;
  +    my $uri = $r-&gt;uri;
  +    if ( my($u1,$u2) = $uri =~ / ^ ([^?]+?) ; ([^?]*) $ /x ) {
  +      $r-&gt;uri($u1);
  +      $r-&gt;args($u2);
  +    } elsif ( my($u1,$u2) = $uri =~ m/^(.*?)%3[Bb](.*)$/ ) {
  +      # protect against old proxies that escape volens nolens
  +      # (see HTTP standard section 5.1.2)
  +      $r-&gt;uri($u1);
  +      $u2 =~ s/%3B/;/gi;
  +      $u2 =~ s/%26/;/gi; # &amp;
  +      $u2 =~ s/%3D/=/gi;
  +      $r-&gt;args($u2);
  +    }
  +    DECLINED;
  +  }
  +</PRE>
  +<P>
  +This handler must be installed as a <CODE>PerlPostReadRequestHandler</CODE>.
  +
   <P>
  -See <A HREF="#Out_of_memory_">Out_of_memory!</A>
  +The handler takes any request that contains <STRONG>no</STRONG> questionmark but one or more semicolons such that the first semicolon is
  +interpreted as a questionmark and everything after that as the querystring.
  +You can now exchange the request
   
  +<P>
  +<PRE>  <A HREF="http://foo.com/query?BGCOLOR=blue;FGCOLOR=red">http://foo.com/query?BGCOLOR=blue;FGCOLOR=red</A>
  +</PRE>
  +<P>
  +with
   
  +<P>
  +<PRE>  <A HREF="http://foo.com/query;BGCOLOR=blue;FGCOLOR=red">http://foo.com/query;BGCOLOR=blue;FGCOLOR=red</A>
  +</PRE>
  +<P>
  +Thus it allows the co-existence of queries from ordinary forms that are
  +being processed by a browser and predefined requests for the same resource.
  +It has one minor bug: Apache doesn't allow percent-escaped slashes in such
  +a querystring. So you must write
   
  +<P>
  +<PRE>  <A HREF="http://foo.com/query;BGCOLOR=blue;FGCOLOR=red;FONT=/font/bla">http://foo.com/query;BGCOLOR=blue;FGCOLOR=red;FONT=/font/bla</A>
  +</PRE>
   <P>
  -I've just discovered that my server is not responding and its error log has
  -filled up the remaining space on the file system (about a gig's worth). The
  -error_log includes millions of lines:
  +and must not say
   
   <P>
  -<PRE>  Callback called exit at -e line 33, &lt;HTML&gt; chunk 1.
  +<PRE>  <A HREF="http://foo.com/query;BGCOLOR=blue;FGCOLOR=red;FONT=%2Ffont%2Fbla">http://foo.com/query;BGCOLOR=blue;FGCOLOR=red;FONT=%2Ffont%2Fbla</A>
   </PRE>
   <P>
  -Why the looping?
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="3_4_Conditional_GET">3.4) Conditional GET</A></H2></CENTER>
  +<P>
  +A rather challenging request we mod_perl programmers can get is the
  +conditional <CODE>GET</CODE>, which typically means a request with an If-Modified-Since header. The
  +HTTP specs have this to say:
   
   <P>
  -Perl can get *very* confused inside an endless loop in your code, it
  -doesn't mean your code called 'exit', but Perl's malloc went haywire and
  -called <CODE>croak(),</CODE> but no memory is left to properly report the
  -error, so Perl is stuck in a loop writing that same message to stderr.
  +<PRE>  The semantics of the GET method change to a &quot;conditional GET&quot;
  +  if the request message includes an If-Modified-Since,
  +  If-Unmodified-Since, If-Match, If-None-Match, or If-Range
  +  header field. A conditional GET method requests that the
  +  entity be transferred only under the circumstances described
  +  by the conditional header field(s). The conditional GET method
  +  is intended to reduce unnecessary network usage by allowing
  +  cached entities to be refreshed without requiring multiple
  +  requests or transferring data already held by the client.
  +</PRE>
  +<P>
  +So how can we reduce the unnecessary network usage in such a case? mod_perl
  +makes it easy for you by offering apache's <CODE>meets_conditions().</CODE>
  +You have to set up your <CODE>Last-Modified</CODE> (and possibly <CODE>ETag</CODE>) header before running this method. If the return value of this method is
  +anything but <CODE>OK</CODE>, you should return from your handler with that return value and you're
  +done. Apache handles the rest for you. The following example is taken from
  +<A HREF="././correct_headers.html#_5_">[5]</A>:
   
   <P>
  -Perl 5.005+ plus is recommended for its improved malloc.c and features
  -mentioned in mod_perl_traps.pod on by default.
  +<PRE>  if((my $rc = $r-&gt;meets_conditions) != OK) {
  +     return $rc;
  +  }
  +  #else ... go and send the response body ...
  +</PRE>
  +<P>
  +If you have a squid accellerator running, it will often handle the
  +conditionals for you and you can enjoy its extreme fast responses for such
  +requests by reading the access.log. Just grep for
  +<CODE>TCP_IMS_HIT/304</CODE>. But as with a <CODE>HEAD</CODE> request there are circumstances under which it may not be allowed to do so.
  +That is why the origin server (which is the server you're programming)
  +needs to handle conditional <CODE>GET</CODE>s as well even if a squid accelerator is running.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Out_of_memory_">Out of memory!</A></H1></CENTER>
  +<CENTER><H2><A NAME="3_Avoiding_to_deal_with_them">3.) Avoiding to deal with them</A></H2></CENTER>
   <P>
  -If something goes really wrong with your code, Perl may die with an ``Out
  -of memory!'' message and/or ``Callback called exit''. Common causes of this
  -are never-ending loops, deep recursion, or calling an undefined subroutine.
  -Here's one way to catch the problem: See Perl's INSTALL document for this
  -item: 
  +There is another approach to dynamic content that is possible with
  +mod_perl. This approach is appropriate if the content changes relatively
  +infrequently, if you expect lots of requests to retrieve the same content
  +before it changes again and if it is much cheaper to test whether the
  +content needs refreshing than it is to refresh it.
   
   <P>
  -<PRE>  =item -DPERL_EMERGENCY_SBRK
  -</PRE>
  +In this case a <CODE>PerlFixupHandler</CODE> can be installed for the relevant location. It tests whether the content is
  +up to date. If so it returns <CODE>DECLINED</CODE> and lets the apache core serve the content from a file. Otherwise, it
  +regenerates the content into the file, updates the <CODE>$r-&amp;gt;finfo</CODE> status and again returns <CODE>DECLINED</CODE> so that apache serves the updated file. Updating <CODE>$r-&amp;gt;finfo</CODE> can be achieved by calling
  +
   <P>
  -<PRE>  If PERL_EMERGENCY_SBRK is defined, running out of memory need not be a
  -  fatal error: a memory pool can allocated by assigning to the special
  -  variable $^M.  See perlvar(1) for more details.
  +<PRE>  $r-&gt;filename($file); # force update of finfo
   </PRE>
   <P>
  -If you compile with that option and add '<CODE>use Apache::Debug level =&amp;gt;
  -4;</CODE>' to your PerlScript, it will allocate the $^M emergency pool and the
  -$SIG{__DIE__} handler will call Carp::confess, giving you a stack trace
  -which should reveal where the problem is. See the Apache::Resource module
  -for prevention of spinning httpds.
  +even if this seems redundant because the filename is already equal to
  +<CODE>$file</CODE>. Setting the filename has the side effect of doing a <CODE>stat()</CODE>
  +on the file. This is important because otherwise apache would use the out
  +of date finfo when generating the response header.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="_warn_child_process_30388_did_n">[warn] child process 30388 did not exit, sending another SIGHUP</A></H1></CENTER>
  +<CENTER><H1><A NAME="References_and_other_literature">References and other literature</A></H1></CENTER>
   <P>
  -From mod_perl.pod: With Apache versions 1.3.0 and higher, mod_perl will
  -call the <CODE>perl_destruct()</CODE> Perl API function during the child
  -exit phase. This will cause proper execution of <STRONG>END</STRONG> blocks found during server startup along with invoking the <STRONG>DESTROY</STRONG> method on global objects who are still alive. It is possible that this
  -operation may take a long time to finish, causing problems during a
  -restart. If your code does not contain and <STRONG>END</STRONG> blocks or <STRONG>DESTROY</STRONG> methods which need to be run during child server shutdown, this destruction
  -can be avoided by setting the <EM>PERL_DESTRUCT_LEVEL</EM> environment variable to <CODE>-1</CODE>.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="_1_">[1]</A></H2></CENTER>
  +<P>
  +Stas Bekman: Mod_perl Guide. <A
  +HREF="http://perl.apache.org/guide/">http://perl.apache.org/guide/</A>
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="RegistryLoader_Cannot_translate">RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl</A></H1></CENTER>
  -<P>
  -<PRE>  RegistryLoader: Cannot translate the URI /home/httpd/perl/test.pl
  -              into a real path to the filename. Please refer to the
  -              manpage for more information
  -              or use the complete method's call like:
  -              $r-&gt;handler(uri,filename);\n&quot;;
  -</PRE>
  +<CENTER><H2><A NAME="_2_">[2]</A></H2></CENTER>
   <P>
  -This warning shows up when RegistryLoader fails to translate the URI into
  -the corresponding filesystem path. Most of failures happen when one passes
  -a file path instead of URI. (A reminder: /home/httpd/perl/test.pl is a file
  -path, while /perl/test.pl is an URI). In most cases all you have to do is
  -to pass something that RegistryLoader expects to get - the URI, but there
  -are more complex cases. RegistryLoader's man page shows how to handle these
  -cases as well (watch for the <CODE>trans()</CODE> sub).
  +T. Berners-Lee et al.: Hypertext Transfer Protocol -- HTTP/1.0, RFC 1945.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A></H1></CENTER>
  +<CENTER><H2><A NAME="_3_">[3]</A></H2></CENTER>
   <P>
  -Unfortunately, not all perl modules are robust enough to survive reload,
  -for them, unusual situation. PerlFreshRestart does not much more than:
  +R. Fielding et al.: Hypertext Transfer Protocol -- HTTP/1.1, RFC 2616.
   
   <P>
  -<PRE>  while (my($k,$v) = each %INC) {
  -    delete $INC{$k};
  -    require $k;
  -  }
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="_4_">[4]</A></H2></CENTER>
   <P>
  -Besides that, it flushes the Apache::Registry cache, and empties any
  -dynamic stacked handlers (e.g. PerlChildInitHandler).
  +Martin Hamilton: Cachebusting - cause and prevention,
  +draft-hamilton-cachebusting-01. Also available online at <A
  +HREF="http://vancouver-webpages.com/CacheNow/">http://vancouver-webpages.com/CacheNow/</A>
   
  -<P>
  -Lots of SegFaults and other problems were reported by users who have turned <CODE>PerlFreshRestart</CODE>  <STRONG>On</STRONG>. Most of them have gone away when it was turned off. It doesn't mean that
  -you shouldn't use it, if it works for you. Just be aware of the dragons...
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="server_reached_MaxClients_settin">server reached MaxClients setting, consider raising the MaxClients setting</A></H1></CENTER>
  +<CENTER><H2><A NAME="_5_">[5]</A></H2></CENTER>
   <P>
  -See <A HREF="././performance.html#Choosing_MaxClients">Choosing MaxClients</A>.
  +Lincoln Stein, Doug MacEachern: Writing Apache Modules with Perl and C,
  +O'Reilly, 1-56592-567-X. Selected chapters available online at <A
  +HREF="http://www.modperl.com">http://www.modperl.com</A> . Amazon page at
  +<A
  +HREF="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu/">http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu/</A>
  +
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="syntax_error_at_dev_null_line_1">syntax error at /dev/null line 1, near &quot;line arguments:&quot;</A></H1></CENTER>
  -<P>
  -<PRE>  syntax error at /dev/null line 1, near &quot;line arguments:&quot;
  -  Execution of /dev/null aborted due to compilation errors.
  -  parse: Undefined error: 0
  -</PRE>
  +<CENTER><H1><A NAME="VERSION">VERSION</A></H1></CENTER>
   <P>
  -There is a chance that your <CODE>/dev/null</CODE> device is broken. Try:
  +You're reading revision $Revision: 1.18 $ of this document, written on
  +$Date: 1999/10/15 22:52:35 $
   
   <P>
  -<PRE>  % sudo echo &gt; /dev/null
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="AUTHOR">AUTHOR</A></H1></CENTER>
  +<P>
  +Andreas Koenig with helpful corrections, addition, comments from Ask Bjoern
  +Hansen &lt;<A HREF="mailto:ask@netcetera.dk">ask@netcetera.dk</A>&gt;,
  +Frank D. Cringle &lt;<A
  +HREF="mailto:fdc@cliwe.ping.de">fdc@cliwe.ping.de</A>&gt;, Eric Cholet
  +&lt;<A HREF="mailto:cholet@logilune.com">cholet@logilune.com</A>&gt;, Mark
  +Kennedy &lt;<A
  +HREF="mailto:mark.kennedy@gs.com">mark.kennedy@gs.com</A>&gt;, Doug
  +MacEachern &lt;<A HREF="mailto:dougm@pobox.com">dougm@pobox.com</A>&gt;,
  +Tom Hukins &lt;<A HREF="mailto:tom@eborcom.com">tom@eborcom.com</A>&gt;,
  +Wham Bang &lt;<A
  +HREF="mailto:wham_bang@yahoo.com">wham_bang@yahoo.com</A>&gt; and many
  +others.
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -13876,7 +16684,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]
  +	     [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -13889,7 +16697,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/26/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  @@ -13937,7 +16745,7 @@
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
   Protecting Your Site</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="correct_headers.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -14244,7 +17052,7 @@
   
   	     <HR>
   
  -	     [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]
  +	     [    <A HREF="correct_headers.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -14488,6 +17296,10 @@
   <PRE>  $Apache::DBI::DEBUG = 1;
   </PRE>
   <P>
  +Starting with <CODE>ApacheDBI-0.84</CODE> setting <CODE>$Apache::DBI::DEBUG = 1</CODE>
  +will produce only a minimal output. For getting full traces you have to set <CODE>$Apache::DBI::DEBUG = 2</CODE>.
  +
  +<P>
   Since now on you will see in the <CODE>error.log</CODE> file when Apache::DBI initializes a connection and when it just returns it
   from its cache. Use the following command to see it in the real time (your
   <CODE>error.log</CODE> file might be locate at a different path):
  @@ -15496,7 +18308,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 08/16/1999
  +	     <BR>Last Modified at 10/10/1999
         </FONT>
       </B>
     </TD>
  @@ -15552,7 +18364,7 @@
   	<LI><A HREF="#mod_perl_and_dbm">mod_perl and dbm</A>
   	<LI><A HREF="#Locking_dbm_handlers">Locking dbm handlers</A>
   	<LI><A HREF="#Tie_DB_Lock">Tie::DB_Lock</A>
  -	<LI><A HREF="#Code_snippets">Code snippets</A>
  +	<LI><A HREF="#Locking_techniques_that_works_wi">Locking techniques that works with dbm files</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -15756,161 +18568,159 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Code_snippets">Code snippets</A></H1></CENTER>
  +<CENTER><H1><A NAME="Locking_techniques_that_works_wi">Locking techniques that works with dbm files</A></H1></CENTER>
   <P>
   I have discussed what can be achieved with mod_perl and dbm files, the cons
   and pros. Now it is a time to show some code. I wrote a simple wrapper for
  -a <CODE>DB_File</CODE> module, and extended it to handle locking, and proper exits. Note that this
  -code still demands some testing, so be careful if you use it on your
  -production machine as is.
  +a <CODE>DB_File</CODE> module to handle locking, and proper cleanup when program terminates.
  +
  +<P>
  +<STRONG>Caution</STRONG>: The suggested locking methods in the Camel book and DB_File man page (at
  +least before the version 1.72) are flawed and if you use them in the
  +environment where more than one process modify the dbm file, it can get
  +corrupted!!! The following is an explanation of why does this happen.
  +
  +<P>
  +You may not use a tied file's filehandle for locking, since you get the
  +filehandle after the file has been already tied. It's too late to lock. The
  +problem is that the database file is opened and then later locked -- and
  +when the database is opened the first 4k (in my dbm library) are read and
  +then cached in memory. Therefore, a process can open the database file and
  +cache the first 4k, then block in the flock while another process modifies
  +the first 4k of the file. When the original process gets the lock is now
  +has a inconsistent view of the database, and if it writes using this
  +inconstant view, it may corrupt the database on disk.
  +
  +<P>
  +This does not cause corruption every time a process has to block in the
  +flock call, because one can do quite a bit of writing to the database file
  +without actually changing the first 4k of the file. You can easily
  +reproduce the corruption if you make your program to modify the records in
  +the first 4k of the DB.
   
   <P>
  -So the <CODE>DB_File::Wrap</CODE> (note that you will not find it on CPAN):
  +On some Operating Systems like FreeBSD, it's possible to lock on tie:
   
   <P>
  -<PRE>  package DB_File::Wrap;
  +<PRE>  tie my %t, 'DB_File', $TOK_FILE, O_RDWR | O_EXLOCK, 0664;
  +</PRE>
  +<P>
  +And only release the lock by untieing the file. Notice the <CODE>O_EXLOCK</CODE>
  +flag, which is not available on all OSes.
  +
  +<P>
  +So here is <CODE>DB_File::Lock</CODE> which does the locking by using an external lockfile, which allows to gain
  +the lock before the file is tied. (note that it's not yet on CPAN and since
  +all listed here). Note that this code still demands some testing, so be
  +careful if you use it on your production machine as is.
  +
  +<P>
  +<PRE>  package DB_File::Lock;
     require 5.004;
     
     use strict;
     
     BEGIN {
         # RCS/CVS complient:  must be all one line, for MakeMaker
  -    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.17 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +    $DB_File::Lock::VERSION = do { my @r = (q$Revision: 1.18 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
     
     }
     
  -  use DB_File;
  +  use DB_File ();
     use Fcntl qw(:flock O_RDWR O_CREAT);
     use Carp qw(croak carp verbose);
  -  use IO::File;
  +  use Symbol ();
  +  
  +  @DB_File::Lock::ISA    = qw( DB_File );
  +  %DB_File::Lock::lockfhs = ();
     
  -  use vars qw($debug);
  +  use constant DEBUG =&gt; 0;
     
  -  #$debug = 1;
  -  $debug = 0;
  +    # file creation permissions mode
  +  use constant PERM_MODE =&gt; 0660;
     
  -  # my $db = DB_File::Wrap \%hash, $filename, [lockmode];
  -  # from now one we can work with both %hash (tie API) and $db (direct API)
  +    # file locking modes
  +  %DB_File::Lock::locks =
  +    (
  +     read  =&gt; LOCK_SH,
  +     write =&gt; LOCK_EX,
  +    );
  +  
  +  # SYNOPSIS:
  +  # tie my %mydb, 'DB_File::Lock', $filepath, 
  +  #     ['read' || 'write', 'HASH' || 'BTREE']
  +  # while (my($k,$v) = each %mydb) {
  +  #   print &quot;$k =&gt; $v\n&quot;;
  +  # }
  +  # untie %mydb;
     #########
  -  sub new{
  +  sub TIEHASH {
       my $class     = shift;
  -    my $hr_hash   = shift;
       my $file      = shift;
  -    my $lock_mode = shift || '';
  +    my $lock_mode = lc shift || 'read';
       my $db_type   = shift || 'HASH';
  -  
  -    my $self;
  -    $self = bless {
  -                 db_type =&gt; 'DB_File',
  -                 flags   =&gt; O_RDWR|O_CREAT,
  -                 mode    =&gt; 0660,
  -                 hash    =&gt; $hr_hash,
  -                 how     =&gt; $DB_HASH,
  -                }, $class ;
  -  
  -      # by default we tie with HASH alg and if requested with BTREE
  -    $self-&gt;{'how'} = ($db_type eq 'BTREE') ? $DB_BTREE : $DB_HASH;
  -  
  -      # tie the object
  -    $self-&gt;{'db_obj'} = tie %{$hr_hash},
  -      $self-&gt;{'db_type'},$file, $self-&gt;{'flags'},$self-&gt;{'mode'}, $self-&gt;{'how'}
  -        or croak &quot;Can't tie $file:$!\n&quot;; ;
  -  
  -    my $fd = $self-&gt;{'db_obj'}-&gt;fd;
  -    croak &quot;Can't get fd :$!&quot; unless defined $fd and $fd;
  -    $self-&gt;{'fh'}= new IO::File &quot;+&lt;&amp;=$fd&quot; or croak &quot;[&quot;.__PACKAGE__.&quot;] Can't dup: $!&quot;;
  -  
  -      # set the lock status to unlocked
  -    $self-&gt;{'lock'} = 0;
  -  
  -      # do the lock here if requested
  -    $self-&gt;lock($lock_mode) if $lock_mode;
  -  
  -    return $self;
     
  -  } # end of sub new
  -  
  -  
  -  # lock the fd either exclusive or shared lock (write/read)
  -  # default is read (shared)
  -  ###########
  -  sub lock{
  -    my $self      = shift;
  -    my $lock_mode = shift || 'read';
  -  
  -  # lock codes:
  -  # 0 == not   locked
  -  # 1 == read  locked
  -  # 2 == write locked
  -  
  -    if ($lock_mode eq 'write') {
  -        # Get the exclusive write lock
  -      unless (flock ($self-&gt;{'fh'}, LOCK_EX | LOCK_NB)) {
  -        unless (flock ($self-&gt;{'fh'}, LOCK_EX)) { croak &quot;exclusive flock: $!&quot; }
  +    die &quot;Dunno about lock mode: [$lock_mode].\n
  +         Valid modes are 'read' or 'write'.\n&quot;
  +      unless $lock_mode eq 'read' or $lock_mode eq 'write';
  +  
  +    # Critical section starts here if in write mode!
  +  
  +      # create an external lock
  +    my $lockfh = Symbol::gensym();
  +    open $lockfh, &quot;&gt;$file.lock&quot; or die &quot;Cannot open $file.lock for writing: $!\n&quot;;
  +    unless (flock $lockfh,  $DB_File::Lock::locks{$lock_mode}|LOCK_NB) {
  +      unless (flock $lockfh, $DB_File::Lock::locks{$lock_mode}) {
  +        croak &quot;cannot flock: $lock_mode =&gt; $DB_File::Lock::locks{$lock_mode}: $!\n&quot;;
         }
  -        # save the status of lock
  -      $self-&gt;{'lock'} = 2;
  -  
  -    } elsif ($lock_mode eq 'read'){
  -        # Get the shared read lock
  -      unless (flock ($self-&gt;{'fh'}, LOCK_SH | LOCK_NB)) {
  -        unless (flock ($self-&gt;{'fh'}, LOCK_SH)) { croak &quot;shared flock: $!&quot; }
  -      }
  -        # save the status of lock
  -      $self-&gt;{'lock'} = 1;
  -    } else {
  -        # incorrect mode
  -      carp &quot;Can't lock. Unknown mode: $lock_mode\n&quot;;
       }
  -  
  -  } # end of sub lock
     
  -  # unlock 
  -  ###########
  -  sub unlock{
  -    my $self = shift;
  -  
  -    $self-&gt;{'db_obj'}-&gt;sync() if defined $self-&gt;{'db_obj'};   # flush
  -    flock($self-&gt;{'fh'}, LOCK_UN);
  -    $self-&gt;{'lock'} = 0;
  -  }
  +    my $self = $class-&gt;SUPER::TIEHASH
  +      ($file,
  +       O_RDWR|O_CREAT,
  +       PERM_MODE,
  +       ($db_type eq 'BTREE' ? $DB_File::DB_BTREE : $DB_File::DB_HASH )
  +      );
     
  -  # untie the hash
  -  # and close all the handlers
  -  # if wasn't unlocked, end() will unlock as well
  -  ###########
  -  sub end{
  -    my $self = shift;
  +      # remove the package name in case re-blessing occurs
  +    (my $id = &quot;$self&quot;) =~ s/^[^=]+=//;
     
  -      # unlock if stilllocked
  -    $self-&gt;unlock() if $self-&gt;{'lock'};
  +      # cache the lock fh
  +    $DB_File::Lock::lockfhs{$id} = $lockfh;
     
  -    delete $self-&gt;{'db_obj'}    if $self-&gt;{'db_obj'};
  -    untie %{$self-&gt;{'hr_hash'}} if $self-&gt;{'hr_hash'};
  -    $self-&gt;{'fh'}-&gt;close        if $self-&gt;{'fh'};
  +    return $self;
     
  -  }
  +  } # end of sub new
     
     
  -  # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  -  # before their completion and haven't had a chance to make a clean up.
  +  # DESTROY is automatically being called, when either a tied variable
  +  # goes out of scope, on explicit untie() call or when the program is
  +  # being interrupted in the middle, e.g. with die() call.
  +  # 
  +  # It unties the db, by forwarding it to the parent class,
  +  # unlocks the file and remove it from the cache of locks.
     ###########
     sub DESTROY{
       my $self = shift;
     
  -      # just to be sure that we properly closed everything
  -    $self-&gt;end();
  +    $self-&gt;SUPER::DESTROY(@_);
     
  -    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  -    undef $self if $self;
  +      # now it safe to unlock the file, (close() unlocks as well). Since
  +      # the object has gone we remove its entry of the lock filehandler
  +      # from the cache.
  +    (my $id = &quot;$self&quot;) =~ s/^[^=]+=//; # see 'sub TIEHASH'
  +    close delete $DB_File::Lock::lockfhs{$id};
     
  +      # Critical section ends here if in write mode!
  +  
  +    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if DEBUG;
  +  
     }
     
     ####
     END {
  +    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if DEBUG;
     
  -    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  -  
     }
     
     1;
  @@ -15919,60 +18729,72 @@
   And you use it :
   
   <P>
  -<PRE>  use DB_File::Wrap ();
  +<PRE>  use DB_File::Lock ();
   </PRE>
   <P>
   A simple tie, READ lock and untie
   
   <P>
  -<PRE>  my $dbfile = &quot;/tmp/test&quot;;
  -  my %mydb = ();
  -  my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  -  print $mydb{'stas'} if exists $mydb{'stas'};
  -    # sync and untie
  -  $db-&gt;end();
  +<PRE>  use DB_File::Lock ();
  +  my $dbfile = &quot;/tmp/test&quot;;
  +  tie my %mydb, 'DB_File::Lock', $dbfile, 'read';
  +  print $mydb{foo} if exists $mydb{foo};
  +  untie %mydb;
   </PRE>
  +<P>
  +You can even skip the <CODE>untie()</CODE> call. When the scope of <CODE>$mydb</CODE> is finished (inside the block), everything will be done automatically. You
  +still better use the explicit call, to make sure the critical sections
  +between lock and unlock will be as short as possible. This is especially
  +important when requesting an exclusive (write) lock.
  +
   <P>
  -You can even skip the <CODE>end()</CODE> call, if leave the scope <CODE>$db</CODE> defined in:
  +The following example shows where it might be convenient to skip the
  +explicit <CODE>untie()</CODE>. In the following example, we don't need to save the intermidiate result,
  +we just return and the cleanup is being done automatically.
   
   <P>
  -<PRE>  sub user_exists{
  -    my $user = shift;
  -    my $result = 0;
  +<PRE>  use DB_File::Lock ();
  +  my $dbfile = &quot;/tmp/test&quot;;
  +  print user_exists(&quot;stas&quot;) ? &quot;Yes&quot; : &quot;No&quot;;
  +  sub user_exists{
  +    my $username = shift || '';
  +  
  +    warn(&quot;No username passed\n&quot;), return 0 unless $username;
     
  -    my %mydb = ();
  -    my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  +    tie my %mydb, 'DB_File::Lock', $dbfile, 'read';
     
  -    # if we match the username return 1
  -    $result = 1 if $mydb{$user};
  +    # if we match the username return 1, else 0
  +    return $mydb{$username} ? 1 : 0;
     
  -    $result;
     } # end of sub user_exists
   </PRE>
   <P>
  -Perform both, read and write operations:
  +Now let's write all Upper case characters and their respective ASCII
  +values. Then read the dbm file and print them the contents of the DB
  +(unsorted).
   
   <P>
  -<PRE>  my $dbfile = &quot;/tmp/test&quot;;
  -  my %mydb = ();
  -  my $db = new DB_File::Wrap \%mydb, $dbfile;
  -  print $mydb{'stas'} if exists $mydb{'stas'};
  +<PRE>  use DB_File::Lock ();
  +  my $dbfile = &quot;/tmp/test&quot;;
     
  -    # lock the db, we gonna change it!
  -  $db-&gt;lock('write');
  -  $mydb{'stas'} = 1;
  -    # unlock the db for write
  +    # write 
  +  tie my %mydb, 'DB_File::Lock', $dbfile,'write';
  +  for (1..25) {
  +    $mydb{chr 65+$_} = $_;
  +  }
  +  untie %mydb;
     
  -    # sync and untie
  -  $db-&gt;end();
  +    # now, read them and printout (unsorted)
  +  tie %mydb, 'DB_File::Lock', $dbfile;
  +  while (my($k,$v) = each %mydb) {
  +    print &quot;$k =&gt; $v\n&quot;;
  +  }
  +  untie %mydb;
   </PRE>
   <P>
  -If your CGI was interrupted in the middle, <CODE>DESTROY</CODE> block will worry to unlock the dbm file and flush the changes. Note that I
  -have got db corruptions even with this code on huge dbm files 10000+
  -records, so be careful when you use it. I thought that I have covered all
  -the possible failures but seems that not all of them. At the end I have
  -moved everything to work with <STRONG>mysql</STRONG>. So if you figure out where the problem is you are very welcome to tell me
  -about it.
  +If your CGI was interrupted in the middle, <CODE>DESTROY</CODE> block will worry to unlock the dbm file and flush the changes. So your DB
  +will be safe against possible corruption because of unclean program
  +termination.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -16007,7 +18829,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  +	     <BR>Last Modified at 10/15/1999
         </FONT>
       </B>
     </TD>
  @@ -16553,6 +19375,7 @@
   
   	<LI><A HREF="#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
   	<LI><A HREF="#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
  +	<LI><A HREF="#Apache_Debug">Apache::Debug</A>
   	<LI><A HREF="#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
   	<LI><A HREF="#Debugging_Core_Dumps">Debugging Core Dumps</A>
   	<LI><A HREF="#Debug_Tracing">Debug Tracing</A>
  @@ -16560,9 +19383,10 @@
   	<LI><A HREF="#Monitoring_error_log_file">Monitoring error_log file</A>
   	<LI><A HREF="#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
   	<LI><A HREF="#Spinning_httpds">Spinning httpds</A>
  -	<LI><A HREF="#PROFILING">PROFILING</A>
  -	<LI><A HREF="#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="#Code_Profiling">Code Profiling</A>
  +	<LI><A HREF="#Examples_of_strace_or_truss_us">Examples of strace (or truss) usage</A>
   	<LI><A HREF="#Devel_Peek">Devel::Peek</A>
  +	<LI><A HREF="#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -16617,6 +19441,30 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_Debug">Apache::Debug</A></H1></CENTER>
  +<P>
  +(META: to be written)
  +
  +<P>
  +<PRE>  use Apache::Debug ();
  +  Apache::Debug::dump($r, SERVER_ERROR, &quot;Uh Oh!&quot;);
  +</PRE>
  +<P>
  +This module sends what may be helpful debugging info to the client rather
  +that the error log.
  +
  +<P>
  +Also, you could try using a larger emergency pool, try this instead of
  +Apache::Debug:
  +
  +<P>
  +<PRE> $^M = 'a' x (1&lt;&lt;18);  #260K buffer
  + use Carp ();
  + $SIG{__DIE__} = \&amp;Carp::confess;
  + eval { Carp::confess(&quot;init&quot;) };
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A></H1></CENTER>
   <P>
   Perl ships with a very useful interactive debugger, however, it does not
  @@ -16824,7 +19672,7 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="PROFILING">PROFILING</A></H1></CENTER>
  +<CENTER><H1><A NAME="Code_Profiling">Code Profiling</A></H1></CENTER>
   <P>
   It is possible to profile code run under mod_perl with the
   <CODE>Devel::DProf</CODE> module available on CPAN. However, you must have apache version 1.3b3 or
  @@ -16848,7 +19696,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="examples_of_strace_or_truss_us">examples of strace (or truss) usage</A></H1></CENTER>
  +<CENTER><H1><A NAME="Examples_of_strace_or_truss_us">Examples of strace (or truss) usage</A></H1></CENTER>
   <P>
   (META: below are some snippets of strace outputs from list's emails)
   
  @@ -16939,6 +19787,75 @@
   child already will already have an allocated buffer, just reset to ``'',
   when you are done.
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A></H1></CENTER>
  +<P>
  +<CODE>Apache::Leak</CODE> (derived from <CODE>Devel::Leak</CODE>) should help you with this task. Example:
  +
  +<P>
  +<PRE>  use Apache::Leak;
  +  
  +  my $global = &quot;FooAAA&quot;;
  +  
  +  leak_test {
  +    $$global = 1;
  +    ++$global;
  +  };
  +</PRE>
  +<P>
  +The argument to <CODE>leak_test()</CODE> is an anonymous sub, so you can just throw it around any code you suspect
  +might be leaking. Beware, it will run the code twice, because the first
  +time in, new <CODE>SV</CODE>s are created, but does not mean you are leaking, the second pass will give
  +better evidence. You do not need to be inside mod_perl to use it, from the
  +command line, the above script outputs:
  +
  +<P>
  +<PRE>  ENTER: 1482 SVs
  +  new c28b8 : new c2918 : 
  +  LEAVE: 1484 SVs
  +  ENTER: 1484 SVs
  +  new db690 : new db6a8 : 
  +  LEAVE: 1486 SVs
  +  !!! 2 SVs leaked !!!
  +</PRE>
  +<P>
  +Build a debuggable perl to see dumps of the <CODE>SV</CODE>s. The simple way to have both a normal perl and debuggable perl, is to
  +follow hints in the
  +<CODE>SUPPORT</CODE> doc for building <CODE>libperld.a</CODE>, when that is built copy the
  +<CODE>perl</CODE> from that directory to your perl bin directory, but name it
  +<CODE>dperl</CODE>.
  +
  +<P>
  +Leak explanation: <CODE>$$global = 1;</CODE> : new global variable created
  +<CODE>FooAAA</CODE> with value of <CODE>1</CODE>, will not be destructed until this module is destroyed.
  +
  +<P>
  +<CODE>Apache::Leak</CODE> is not very user-friendly, have a look at
  +<CODE>B::LexInfo</CODE>. You'll see that what might appear to be a leak, is actually just a Perl
  +optimization. e.g. consider this code:
  +
  +<P>
  +<PRE>  sub foo {
  +    my $string = shift;
  +  }
  +</PRE>
  +<P>
  +<PRE>  foo(&quot;a string&quot;);
  +</PRE>
  +<P>
  +<CODE>B::LexInfo</CODE> will show you that Perl does not release the value from $string, unless you
  +undef it. this is because Perl anticipates the memory will be needed for
  +another string, the next time the subroutine is entered. you'll see similar
  +for <CODE>@array</CODE> length, <CODE>%hash</CODE> keys, and scratch areas of the padlist for ops such as <CODE>join()</CODE>, `<CODE>.</CODE>', etc.
  +
  +<P>
  +<CODE>Apache::Status</CODE> now includes a new StatusLexInfo option.
  +
  +<P>
  +Apache::Leak works better if you've built a libperld.a (see SUPPORT) and
  +given PERL_DEBUG=1 to mod_perl's Makefile.PL
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -16972,7 +19889,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/22/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  @@ -17377,6 +20294,10 @@
   (See <CODE>perldoc Apache::GzipChain</CODE>).
   
   <P>
  +Notice that the rightmost PerlHandler must be a content producer. Use
  +<CODE>Apache::PassFile</CODE> or another similar module.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location</A></H1></CENTER>
   <P>
  @@ -17411,10 +20332,15 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  +It's important to stress that changed <CODE>@INC</CODE> is effective only inside the <CODE>&lt;Location</CODE>&gt; or a similar configuration directive.
  +<CODE>Apache::PerlVINC</CODE> subclasses the <CODE>PerlRequire</CODE> directive, marking the file to be reloaded by the fixup handler, using the
  +value of
  +<CODE>PerlINC</CODE> for <CODE>@INC</CODE>. That's local to the fixup handler, so you won't actually see <CODE>@INC</CODE> changed in your script.
  +
  +<P>
   To address possible issues of namespace clashes during reload, the handler
  -could call $r-&gt;child_terminate() so the next server to load the
  -different versions will have a fresh namespace. (not a good idea in a high
  -load environment, of course.)
  +could call <CODE>$r-&amp;gt;child_terminate()</CODE> so the next server to load the different versions will have a fresh
  +namespace. (not a good idea in a high load environment, of course.)
   
   <P>
   If it is still absent from CPAN get it at: <A
  @@ -17482,7 +20408,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 08/17/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  @@ -17932,10 +20858,13 @@
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  +	<LI><A HREF="#Redirect_a_POST_request_forward">Redirect a POST request, forwarding the content</A>
   	<LI><A HREF="#More_on_relative_paths">More on relative paths</A>
   	<LI><A HREF="#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server</A>
   	<LI><A HREF="#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
   	<LI><A HREF="#Handling_cookies">Handling cookies</A>
  +	<LI><A HREF="#Sending_multiply_cookies_with_Pe">Sending multiply cookies with Perl API</A>
  +	<LI><A HREF="#Passing_environment_variables_be">Passing environment variables between handlers</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -17962,6 +20891,28 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  +<CENTER><H1><A NAME="Redirect_a_POST_request_forward">Redirect a POST request, forwarding the content</A></H1></CENTER>
  +<P>
  +With mod_perl you can easily redirect a POST request to some other
  +location. All it takes is reading in the contents, setting the method to be
  +of a <CODE>GET</CODE> type and args with the content to be forwarded and finally doing the
  +redirect:
  +
  +<P>
  +<PRE>     my $r = shift;
  +     my $content = $r-&gt;content;
  +     $r-&gt;method(&quot;GET&quot;);
  +     $r-&gt;method_number(M_GET);
  +     $r-&gt;headers_in-&gt;unset(&quot;Content-length&quot;);
  +     $r-&gt;args($content);
  +     $r-&gt;internal_redirect_handler(&quot;/new/url&quot;);
  +</PRE>
  +<P>
  +Of course that last line can be any kind of redirect, not necessarily an
  +internal redirect.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="More_on_relative_paths">More on relative paths</A></H1></CENTER>
   <P>
   Many people use relative paths for <CODE>require</CODE>, <CODE>use</CODE>, etc., or open files in the current directory or relative to the current
  @@ -18026,16 +20977,23 @@
   see the <CODE>error_log</CODE>, you can ask your sysadmin to install this script.
   
   <P>
  +Note, that it was written for a plain Apache, and isn't prepared to handle
  +complex multiline error and warning messages generated by mod_perl. It also
  +uses a <CODE>system()</CODE> call to do the main work with
  +<CODE>tail()</CODE> utility, probably a more efficient perl implementation
  +is due (take a look at <CODE>File::Tail</CODE> module). You are welcome to fix it and contribute it back to mod_perl
  +community. Thank you!
  +
  +<P>
   Ok, here is the code:
   
   <P>
  -<PRE>  #!/usr/bin/perl -Tw
  +<PRE>  # !/usr/bin/perl -Tw
     
     use strict;
  -  $|=1;
     
     my $default   = 10;
  -  my $error_log = &quot;/usr/local/apache/var/logs/error_log.1&quot;;
  +  my $error_log = &quot;/usr/local/apache/logs/error_log&quot;;
     use CGI;
     
     # untaint $ENV{PATH}
  @@ -18060,20 +21018,20 @@
           $q-&gt;end_form,
           $q-&gt;hr;
     
  +  # untaint $counts
  +  $counts = ($counts =~ /(\d+)/) ? $1 : 0;
  +  
     print($q-&gt;b(&quot;$error_log doesn't exist!!!&quot;)),exit unless -e $error_log;
     
     open LOG, &quot;tail -$counts $error_log|&quot; or die &quot;Can't open tail on $error_log :$!\n&quot;;
     my @logs = &lt;LOG&gt;;
  -  print $q-&gt;b('Note: Latest logs on the top'),$q-&gt;br;
  -  
  -  print &quot;&lt;UL&gt;\n&quot;;
  -  
  +  close LOG;
       # format and colorize each line nicely
  -  foreach (reverse @logs) {
  +  foreach (@logs) {
         s{
          \[(.*?)\]\s* # date
          \[(.*?)\]\s* # type of error 
  -       \[(.*?)\]\s* # client
  +       \[(.*?)\]\s* # client part
          (.*)         # the message
         }
         {
  @@ -18083,12 +21041,10 @@
           colorize($2,$4).
           &quot;&lt;/PRE&gt;&quot;
         }ex;
  -    print &quot;&lt;BR&gt;&lt;LI&gt;$_&lt;BR&gt;&quot;; 
  +    print &quot;&lt;BR&gt;$_&lt;BR&gt;&quot;; 
     }
     
  -  print &quot;&lt;/UL&gt;\n&quot;;
     
  -  close LOG;
     
     #############
     sub colorize{
  @@ -18147,6 +21103,50 @@
       return %cookies;
     }
   </PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Sending_multiply_cookies_with_Pe">Sending multiply cookies with Perl API</A></H1></CENTER>
  +<P>
  +Taken that you have prepared your cookies in <CODE>@cookies</CODE>, the following would do:
  +
  +<P>
  +<PRE>  for(@cookies){
  +   $r-&gt;headers_out-&gt;add( 'Set-Cookie' =&gt; $_ );
  + }
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Passing_environment_variables_be">Passing environment variables between handlers</A></H1></CENTER>
  +<P>
  +A simple example of passing environment variables between handlers:
  +
  +<P>
  +Having a configuration:
  +
  +<P>
  +<PRE>  PerlAccessHandler My::Access
  +  PerlLogHandler My::Log
  +</PRE>
  +<P>
  +and startup.pl:
  +
  +<P>
  +<PRE>  sub My::Access::handler {
  +    my $r = shift;
  +    $r-&gt;subprocess_env(TICKET =&gt; $$);
  +    $r-&gt;notes(TICKET =&gt; $$);
  +  }
  +  
  +  sub My::Log::handler {
  +    my $r = shift;
  +    my $env = $r-&gt;subprocess_env('TICKET');
  +    my $note = $r-&gt;notes('TICKET');
  +    warn &quot;env=$env, note=$note\n&quot;;
  +  }
  +</PRE>
  +<P>
  +Adding <CODE>%{TICKET}e</CODE> and <CODE>%{TICKET}n</CODE> to the <CODE>LogFormat</CODE> for access_log works fine too.
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -18180,7 +21180,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  +	     <BR>Last Modified at 10/15/1999
         </FONT>
       </B>
     </TD>
  @@ -19233,10 +22233,10 @@
   HREF="http://www.saturn5.com/~jwb/dbi-examples.html">http://www.saturn5.com/~jwb/dbi-examples.html</A>
   (by Jeffrey William Baker).
   
  -<P><LI><STRONG><A NAME="item_DBI">DBI at Hermetica</A></STRONG>
  +<P><LI><STRONG><A NAME="item_DBI">DBI Homepage</A></STRONG>
   <P>
   <A
  -HREF="http://www.hermetica.com/technologia/DBI/">http://www.hermetica.com/technologia/DBI/</A>
  +HREF="http://www.symbolstone.org/technology/perl/DBI/">http://www.symbolstone.org/technology/perl/DBI/</A>
   
   
   <P><LI><STRONG><A NAME="item_DBI">DBI mailing list information</A></STRONG>
  @@ -19316,7 +22316,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.19      +6 -10     modperl-site/guide/config.html
  
  Index: config.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/config.html,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- config.html	1999/09/25 23:13:52	1.18
  +++ config.html	1999/10/15 22:52:40	1.19
  @@ -33,12 +33,8 @@
   		<LI><A HREF="#Location_Configuration">Location Configuration</A>
   		<LI><A HREF="#PerlModule_and_PerlRequire_direc">PerlModule and PerlRequire directives</A>
   		<LI><A HREF="#Perl_Handlers">Perl*Handlers</A>
  -	</UL>
  -
  -	<LI><A HREF="#STACKED_HANDLERS">STACKED HANDLERS</A>
  -	<LI><A HREF="#PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A>
  -	<UL>
  -
  +		<LI><A HREF="#Stacked_Handlers">Stacked Handlers</A>
  +		<LI><A HREF="#Perl_Method_Handlers">Perl Method Handlers</A>
   		<LI><A HREF="#PerlFreshRestart">PerlFreshRestart</A>
   		<LI><A HREF="#_perl_status_location">/perl-status location</A>
   		<UL>
  @@ -375,7 +371,7 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="STACKED_HANDLERS">STACKED HANDLERS</A></H1></CENTER>
  +<CENTER><H2><A NAME="Stacked_Handlers">Stacked Handlers</A></H2></CENTER>
   <P>
   With the mod_perl stacked handlers mechanism, it is possible for more than
   one <CODE>Perl*Handler</CODE> to be defined and run during each stage of a request.
  @@ -546,7 +542,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="PERL_METHOD_HANDLERS">PERL METHOD HANDLERS</A></H1></CENTER>
  +<CENTER><H2><A NAME="Perl_Method_Handlers">Perl Method Handlers</A></H2></CENTER>
   <P>
   If a Perl*Handler is prototyped with <CODE>$$</CODE>, this handler will be invoked as method. e.g.
   
  @@ -1062,7 +1058,7 @@
   <PRE>  &lt;Perl&gt;
     use Apache::PerlSections();
     ...
  -  print STDERR Apache-&gt;PerlSections-&gt;dump();
  +  print STDERR Apache::PerlSections-&gt;dump();
     &lt;/Perl&gt;
   </PRE>
   <P>
  @@ -1397,7 +1393,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/26/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.19      +187 -1    modperl-site/guide/control.html
  
  Index: control.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/control.html,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- control.html	1999/09/25 23:13:53	1.18
  +++ control.html	1999/10/15 22:52:41	1.19
  @@ -29,6 +29,8 @@
   	<LI><A HREF="#Restarting_techniques">Restarting techniques</A>
   	<LI><A HREF="#Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A>
   	<LI><A HREF="#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
  +	<LI><A HREF="#Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A>
  +	<LI><A HREF="#An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A>
   	<LI><A HREF="#SUID_start_up_scripts">SUID start-up scripts</A>
   	<LI><A HREF="#Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A>
   	<LI><A HREF="#Running_server_in_a_single_mode">Running server in a single mode</A>
  @@ -240,6 +242,190 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A></H1></CENTER>
  +<P>
  +You have prepared a new version of code, uploaded it into a production
  +server, restarted it and it doesn't work. What could be worse than that?
  +You also cannot go back, because you have overwritten the good working
  +code.
  +
  +<P>
  +It's quite easy to prevent it! Just don't overwrite the previous good
  +files!!! 
  +
  +<P>
  +Personally I do all updates on the live server with a following sequence.
  +Assume that the root directory lies in
  +<CODE>/home/httpd/perl/rel</CODE>. When I'm about to update the files I create a new directory <CODE>/home/httpd/perl/beta</CODE>, copy the old files from
  +<CODE>/home/httpd/perl/rel</CODE> and update it with new files I'm about to replace. The I do last sanity
  +checks (file permissions (read+executable), run <CODE>perl -c</CODE> on the new modules to make sure there no errors in them). When I think I'm
  +ready I do:
  +
  +<P>
  +<PRE>  % cd /home/httpd/perl
  +  % mv rel old; mv beta rel; stop; sleep 3; restart; err
  +</PRE>
  +<P>
  +Let's explain what I'm doing. First I use alises to make things faster:
  +
  +<P>
  +<PRE>  % alias | grep apachectl
  +  graceful        /usr/local/apache/bin/apachectl graceful
  +  rehup   /usr/local/apache/sbin/apachectl restart
  +  restart /usr/local/apache/bin/apachectl restart
  +  start   /usr/local/apache/bin/apachectl start
  +  stop    /usr/local/apache/bin/apachectl stop
  +  
  +  % alias err
  +  tail -f /usr/local/apache/logs/error_log
  +</PRE>
  +<P>
  +So I write all the commands in one line, separated with semicolon and only
  +then press <CODE>Enter</CODE> key. That ensures that if I suddenly get a connection lost (sadly but that
  +happens sometimes) I wouldn't leave the server down if only the <CODE>stop</CODE> command squeezed in. 
  +
  +<P>
  +I backup the old working directory in <CODE>old</CODE>, and move the new one instead. I stop the server, give it a few seconds to
  +shutdown (it might take even longer) and then do <CODE>restart</CODE> followed by immediate view of the tail of the <CODE>error_log</CODE> file in order to see that everything is OK. <CODE>apachectl</CODE> generates the status messages too early (e.g. on <CODE>stop</CODE> it says server has been stopped, while it's not yet, so don't rely on it,
  +rely on <CODE>error_log</CODE> file instead). Also you have noticed that I use <CODE>restart</CODE> and not just <CODE>start</CODE>. I do this for the same reason of Apache's long stopping times (it depends
  +on what you do with it of course!), so if you use <CODE>start</CODE> and Apache didn't release the port it listens to, the start would fail and <CODE>error_log</CODE> would tell that port is in use, e.g.:
  +
  +<P>
  +<PRE>  Address already in use: make_sock: could not bind to port 8080
  +</PRE>
  +<P>
  +But if you use <CODE>restart</CODE>, it will patiently wait for the server to quit and then will cleanly start
  +it.
  +
  +<P>
  +Now what happens if the new modules are broken? First of all, I see
  +immediately the indication of the problems reported at <CODE>error_log</CODE>
  +file, which I <CODE>tail -f</CODE> immediately after a restart command. That's easy, we just put everything as
  +it was before:
  +
  +<P>
  +<PRE>  % mv rel bad; mv old rel; stop; sleep 3; restart; err
  +</PRE>
  +<P>
  +And 99.9% that everything would be alright, and you have had only about 10
  +secs of downtime, which is pretty good!
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A></H1></CENTER>
  +<P>
  +What happens if you really must took down the server or disable the
  +scripts? This situation might happen when you need to do some maintanance
  +works on your database server, which you have to put down and which cause
  +all the scripts using this database server non-working. If you do nothing,
  +user will see either grey <CODE>The Error
  +has happened</CODE> or a better customized error message if you have added a code to trap and
  +customize the errors (See <A HREF="././porting.html#Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A>
  +for the latter case)
  +
  +<P>
  +A much more user friendly approach is to confess to your users that you are
  +doing some maintainance works and plead for a paitience, promising that the
  +services will become fully functional in X minutes (it worth to keep the
  +promize!). There are a few ways to do that:
  +
  +<P>
  +First doesn't require messing with server and works when you have to
  +disable a script and not a module! Just prepare a little script like:
  +
  +<P>
  +<PRE>  /home/http/perl/construction.pl
  +  ----------------------------
  +  #!/usr/bin/perl -wT
  +  
  +  use strict;
  +  use CGI;
  +  my $q = new CGI;
  +  print $q-&gt;header,
  +  &quot;Sorry, the service is down for maintainance. 
  +   It will be back in a about 5-15 minutes.
  +   Please, bear with us.
  +   Thank you!&quot;;
  +</PRE>
  +<P>
  +And if now you have to disable a script at <CODE>/home/http/perl/chat.pl</CODE>, just do:
  +
  +<P>
  +<PRE>  % mv /home/http/perl/chat.pl /home/http/perl/chat.pl.orig
  +  % ln -s /home/http/perl/construction.pl /home/http/perl/chat.pl
  +</PRE>
  +<P>
  +Of course you server configuration should allow symbolic links for this
  +trick to work. Just make sure you have
  +
  +<P>
  +<PRE>  Options FollowSymLinks
  +</PRE>
  +<P>
  +directive in your <CODE>&lt;Location</CODE>&gt;/<CODE>&lt;Directory</CODE>&gt; section configuration.
  +
  +<P>
  +When done, it's easy to restore the previous setup. Just do:
  +
  +<P>
  +<PRE>  % mv /home/http/perl/chat.pl.orig /home/http/perl/chat.pl
  +</PRE>
  +<P>
  +and overwrite the symbolic link. Apache will automatically detect the
  +change and will use the moved script instead.
  +
  +<P>
  +Second approach, is changing the server configuration and configure a whole
  +directories to be handled by Contruction handler that you would write, e.g.
  +if you write something like:
  +
  +<P>
  +<PRE>  Construction.pm
  +  ---------------
  +  use strict;
  +  use CGI;
  +  use Apache::Constants;
  +  sub handler{
  +    my $q = new CGI;
  +    print $q-&gt;header,
  +    &quot;Sorry, the service is down for maintainance. 
  +     It will be back in a about 5-15 minutes.
  +     Please, bear with us.
  +     Thank you!&quot;;
  +    return OK;
  +  }
  +</PRE>
  +<P>
  +and put it in directory that in the server's <CODE>@INC</CODE>, to put down all your scripts at <CODE>/perl</CODE> you would replace:
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    [snip]
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +with
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Construction
  +    [snip]
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +Now restart the server and your user will be happy to know that you are
  +working on a much better version of the service and it worth for them to go
  +read slashdot.org and come back in 10 minutes.
  +
  +<P>
  +If you need to disable a location handled by some module, the second
  +approach would work just as well.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="SUID_start_up_scripts">SUID start-up scripts</A></H1></CENTER>
   <P>
   For those who wants to use <STRONG>SUID</STRONG> startup script, here is an example for you. This script is <STRONG>SUID</STRONG> to <STRONG>root</STRONG>, and should be executable only by members of some special group at your
  @@ -982,7 +1168,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 08/05/1999
  +	     <BR>Last Modified at 10/15/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.8       +5 -1      modperl-site/guide/databases.html
  
  Index: databases.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/databases.html,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- databases.html	1999/09/25 23:13:53	1.7
  +++ databases.html	1999/10/15 22:52:42	1.8
  @@ -205,6 +205,10 @@
   <PRE>  $Apache::DBI::DEBUG = 1;
   </PRE>
   <P>
  +Starting with <CODE>ApacheDBI-0.84</CODE> setting <CODE>$Apache::DBI::DEBUG = 1</CODE>
  +will produce only a minimal output. For getting full traces you have to set <CODE>$Apache::DBI::DEBUG = 2</CODE>.
  +
  +<P>
   Since now on you will see in the <CODE>error.log</CODE> file when Apache::DBI initializes a connection and when it just returns it
   from its cache. Use the following command to see it in the real time (your
   <CODE>error.log</CODE> file might be locate at a different path):
  @@ -1213,7 +1217,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 08/16/1999
  +	     <BR>Last Modified at 10/10/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.8       +155 -145  modperl-site/guide/dbm.html
  
  Index: dbm.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/dbm.html,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- dbm.html	1999/09/25 23:13:54	1.7
  +++ dbm.html	1999/10/15 22:52:42	1.8
  @@ -30,7 +30,7 @@
   	<LI><A HREF="#mod_perl_and_dbm">mod_perl and dbm</A>
   	<LI><A HREF="#Locking_dbm_handlers">Locking dbm handlers</A>
   	<LI><A HREF="#Tie_DB_Lock">Tie::DB_Lock</A>
  -	<LI><A HREF="#Code_snippets">Code snippets</A>
  +	<LI><A HREF="#Locking_techniques_that_works_wi">Locking techniques that works with dbm files</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -234,161 +234,159 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Code_snippets">Code snippets</A></H1></CENTER>
  +<CENTER><H1><A NAME="Locking_techniques_that_works_wi">Locking techniques that works with dbm files</A></H1></CENTER>
   <P>
   I have discussed what can be achieved with mod_perl and dbm files, the cons
   and pros. Now it is a time to show some code. I wrote a simple wrapper for
  -a <CODE>DB_File</CODE> module, and extended it to handle locking, and proper exits. Note that this
  -code still demands some testing, so be careful if you use it on your
  -production machine as is.
  +a <CODE>DB_File</CODE> module to handle locking, and proper cleanup when program terminates.
   
   <P>
  -So the <CODE>DB_File::Wrap</CODE> (note that you will not find it on CPAN):
  +<STRONG>Caution</STRONG>: The suggested locking methods in the Camel book and DB_File man page (at
  +least before the version 1.72) are flawed and if you use them in the
  +environment where more than one process modify the dbm file, it can get
  +corrupted!!! The following is an explanation of why does this happen.
   
   <P>
  -<PRE>  package DB_File::Wrap;
  +You may not use a tied file's filehandle for locking, since you get the
  +filehandle after the file has been already tied. It's too late to lock. The
  +problem is that the database file is opened and then later locked -- and
  +when the database is opened the first 4k (in my dbm library) are read and
  +then cached in memory. Therefore, a process can open the database file and
  +cache the first 4k, then block in the flock while another process modifies
  +the first 4k of the file. When the original process gets the lock is now
  +has a inconsistent view of the database, and if it writes using this
  +inconstant view, it may corrupt the database on disk.
  +
  +<P>
  +This does not cause corruption every time a process has to block in the
  +flock call, because one can do quite a bit of writing to the database file
  +without actually changing the first 4k of the file. You can easily
  +reproduce the corruption if you make your program to modify the records in
  +the first 4k of the DB.
  +
  +<P>
  +On some Operating Systems like FreeBSD, it's possible to lock on tie:
  +
  +<P>
  +<PRE>  tie my %t, 'DB_File', $TOK_FILE, O_RDWR | O_EXLOCK, 0664;
  +</PRE>
  +<P>
  +And only release the lock by untieing the file. Notice the <CODE>O_EXLOCK</CODE>
  +flag, which is not available on all OSes.
  +
  +<P>
  +So here is <CODE>DB_File::Lock</CODE> which does the locking by using an external lockfile, which allows to gain
  +the lock before the file is tied. (note that it's not yet on CPAN and since
  +all listed here). Note that this code still demands some testing, so be
  +careful if you use it on your production machine as is.
  +
  +<P>
  +<PRE>  package DB_File::Lock;
     require 5.004;
     
     use strict;
     
     BEGIN {
         # RCS/CVS complient:  must be all one line, for MakeMaker
  -    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.7 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +    $DB_File::Lock::VERSION = do { my @r = (q$Revision: 1.8 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
     
     }
     
  -  use DB_File;
  +  use DB_File ();
     use Fcntl qw(:flock O_RDWR O_CREAT);
     use Carp qw(croak carp verbose);
  -  use IO::File;
  +  use Symbol ();
     
  -  use vars qw($debug);
  +  @DB_File::Lock::ISA    = qw( DB_File );
  +  %DB_File::Lock::lockfhs = ();
     
  -  #$debug = 1;
  -  $debug = 0;
  +  use constant DEBUG =&gt; 0;
     
  -  # my $db = DB_File::Wrap \%hash, $filename, [lockmode];
  -  # from now one we can work with both %hash (tie API) and $db (direct API)
  +    # file creation permissions mode
  +  use constant PERM_MODE =&gt; 0660;
  +  
  +    # file locking modes
  +  %DB_File::Lock::locks =
  +    (
  +     read  =&gt; LOCK_SH,
  +     write =&gt; LOCK_EX,
  +    );
  +  
  +  # SYNOPSIS:
  +  # tie my %mydb, 'DB_File::Lock', $filepath, 
  +  #     ['read' || 'write', 'HASH' || 'BTREE']
  +  # while (my($k,$v) = each %mydb) {
  +  #   print &quot;$k =&gt; $v\n&quot;;
  +  # }
  +  # untie %mydb;
     #########
  -  sub new{
  +  sub TIEHASH {
       my $class     = shift;
  -    my $hr_hash   = shift;
       my $file      = shift;
  -    my $lock_mode = shift || '';
  +    my $lock_mode = lc shift || 'read';
       my $db_type   = shift || 'HASH';
  -  
  -    my $self;
  -    $self = bless {
  -                 db_type =&gt; 'DB_File',
  -                 flags   =&gt; O_RDWR|O_CREAT,
  -                 mode    =&gt; 0660,
  -                 hash    =&gt; $hr_hash,
  -                 how     =&gt; $DB_HASH,
  -                }, $class ;
  -  
  -      # by default we tie with HASH alg and if requested with BTREE
  -    $self-&gt;{'how'} = ($db_type eq 'BTREE') ? $DB_BTREE : $DB_HASH;
  -  
  -      # tie the object
  -    $self-&gt;{'db_obj'} = tie %{$hr_hash},
  -      $self-&gt;{'db_type'},$file, $self-&gt;{'flags'},$self-&gt;{'mode'}, $self-&gt;{'how'}
  -        or croak &quot;Can't tie $file:$!\n&quot;; ;
  -  
  -    my $fd = $self-&gt;{'db_obj'}-&gt;fd;
  -    croak &quot;Can't get fd :$!&quot; unless defined $fd and $fd;
  -    $self-&gt;{'fh'}= new IO::File &quot;+&lt;&amp;=$fd&quot; or croak &quot;[&quot;.__PACKAGE__.&quot;] Can't dup: $!&quot;;
     
  -      # set the lock status to unlocked
  -    $self-&gt;{'lock'} = 0;
  -  
  -      # do the lock here if requested
  -    $self-&gt;lock($lock_mode) if $lock_mode;
  -  
  -    return $self;
  -  
  -  } # end of sub new
  -  
  -  
  -  # lock the fd either exclusive or shared lock (write/read)
  -  # default is read (shared)
  -  ###########
  -  sub lock{
  -    my $self      = shift;
  -    my $lock_mode = shift || 'read';
  -  
  -  # lock codes:
  -  # 0 == not   locked
  -  # 1 == read  locked
  -  # 2 == write locked
  -  
  -    if ($lock_mode eq 'write') {
  -        # Get the exclusive write lock
  -      unless (flock ($self-&gt;{'fh'}, LOCK_EX | LOCK_NB)) {
  -        unless (flock ($self-&gt;{'fh'}, LOCK_EX)) { croak &quot;exclusive flock: $!&quot; }
  +    die &quot;Dunno about lock mode: [$lock_mode].\n
  +         Valid modes are 'read' or 'write'.\n&quot;
  +      unless $lock_mode eq 'read' or $lock_mode eq 'write';
  +  
  +    # Critical section starts here if in write mode!
  +  
  +      # create an external lock
  +    my $lockfh = Symbol::gensym();
  +    open $lockfh, &quot;&gt;$file.lock&quot; or die &quot;Cannot open $file.lock for writing: $!\n&quot;;
  +    unless (flock $lockfh,  $DB_File::Lock::locks{$lock_mode}|LOCK_NB) {
  +      unless (flock $lockfh, $DB_File::Lock::locks{$lock_mode}) {
  +        croak &quot;cannot flock: $lock_mode =&gt; $DB_File::Lock::locks{$lock_mode}: $!\n&quot;;
         }
  -        # save the status of lock
  -      $self-&gt;{'lock'} = 2;
  -  
  -    } elsif ($lock_mode eq 'read'){
  -        # Get the shared read lock
  -      unless (flock ($self-&gt;{'fh'}, LOCK_SH | LOCK_NB)) {
  -        unless (flock ($self-&gt;{'fh'}, LOCK_SH)) { croak &quot;shared flock: $!&quot; }
  -      }
  -        # save the status of lock
  -      $self-&gt;{'lock'} = 1;
  -    } else {
  -        # incorrect mode
  -      carp &quot;Can't lock. Unknown mode: $lock_mode\n&quot;;
       }
     
  -  } # end of sub lock
  +    my $self = $class-&gt;SUPER::TIEHASH
  +      ($file,
  +       O_RDWR|O_CREAT,
  +       PERM_MODE,
  +       ($db_type eq 'BTREE' ? $DB_File::DB_BTREE : $DB_File::DB_HASH )
  +      );
     
  -  # unlock 
  -  ###########
  -  sub unlock{
  -    my $self = shift;
  +      # remove the package name in case re-blessing occurs
  +    (my $id = &quot;$self&quot;) =~ s/^[^=]+=//;
     
  -    $self-&gt;{'db_obj'}-&gt;sync() if defined $self-&gt;{'db_obj'};   # flush
  -    flock($self-&gt;{'fh'}, LOCK_UN);
  -    $self-&gt;{'lock'} = 0;
  -  }
  +      # cache the lock fh
  +    $DB_File::Lock::lockfhs{$id} = $lockfh;
     
  -  # untie the hash
  -  # and close all the handlers
  -  # if wasn't unlocked, end() will unlock as well
  -  ###########
  -  sub end{
  -    my $self = shift;
  -  
  -      # unlock if stilllocked
  -    $self-&gt;unlock() if $self-&gt;{'lock'};
  -  
  -    delete $self-&gt;{'db_obj'}    if $self-&gt;{'db_obj'};
  -    untie %{$self-&gt;{'hr_hash'}} if $self-&gt;{'hr_hash'};
  -    $self-&gt;{'fh'}-&gt;close        if $self-&gt;{'fh'};
  +    return $self;
     
  -  }
  +  } # end of sub new
     
     
  -  # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  -  # before their completion and haven't had a chance to make a clean up.
  +  # DESTROY is automatically being called, when either a tied variable
  +  # goes out of scope, on explicit untie() call or when the program is
  +  # being interrupted in the middle, e.g. with die() call.
  +  # 
  +  # It unties the db, by forwarding it to the parent class,
  +  # unlocks the file and remove it from the cache of locks.
     ###########
     sub DESTROY{
       my $self = shift;
  +  
  +    $self-&gt;SUPER::DESTROY(@_);
  +  
  +      # now it safe to unlock the file, (close() unlocks as well). Since
  +      # the object has gone we remove its entry of the lock filehandler
  +      # from the cache.
  +    (my $id = &quot;$self&quot;) =~ s/^[^=]+=//; # see 'sub TIEHASH'
  +    close delete $DB_File::Lock::lockfhs{$id};
     
  -      # just to be sure that we properly closed everything
  -    $self-&gt;end();
  +      # Critical section ends here if in write mode!
     
  -    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  -    undef $self if $self;
  +    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if DEBUG;
     
     }
     
     ####
     END {
  +    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if DEBUG;
     
  -    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  -  
     }
     
     1;
  @@ -397,60 +395,72 @@
   And you use it :
   
   <P>
  -<PRE>  use DB_File::Wrap ();
  +<PRE>  use DB_File::Lock ();
   </PRE>
   <P>
   A simple tie, READ lock and untie
   
   <P>
  -<PRE>  my $dbfile = &quot;/tmp/test&quot;;
  -  my %mydb = ();
  -  my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  -  print $mydb{'stas'} if exists $mydb{'stas'};
  -    # sync and untie
  -  $db-&gt;end();
  +<PRE>  use DB_File::Lock ();
  +  my $dbfile = &quot;/tmp/test&quot;;
  +  tie my %mydb, 'DB_File::Lock', $dbfile, 'read';
  +  print $mydb{foo} if exists $mydb{foo};
  +  untie %mydb;
   </PRE>
  +<P>
  +You can even skip the <CODE>untie()</CODE> call. When the scope of <CODE>$mydb</CODE> is finished (inside the block), everything will be done automatically. You
  +still better use the explicit call, to make sure the critical sections
  +between lock and unlock will be as short as possible. This is especially
  +important when requesting an exclusive (write) lock.
  +
   <P>
  -You can even skip the <CODE>end()</CODE> call, if leave the scope <CODE>$db</CODE> defined in:
  +The following example shows where it might be convenient to skip the
  +explicit <CODE>untie()</CODE>. In the following example, we don't need to save the intermidiate result,
  +we just return and the cleanup is being done automatically.
   
   <P>
  -<PRE>  sub user_exists{
  -    my $user = shift;
  -    my $result = 0;
  +<PRE>  use DB_File::Lock ();
  +  my $dbfile = &quot;/tmp/test&quot;;
  +  print user_exists(&quot;stas&quot;) ? &quot;Yes&quot; : &quot;No&quot;;
  +  sub user_exists{
  +    my $username = shift || '';
  +  
  +    warn(&quot;No username passed\n&quot;), return 0 unless $username;
     
  -    my %mydb = ();
  -    my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  +    tie my %mydb, 'DB_File::Lock', $dbfile, 'read';
     
  -    # if we match the username return 1
  -    $result = 1 if $mydb{$user};
  +    # if we match the username return 1, else 0
  +    return $mydb{$username} ? 1 : 0;
     
  -    $result;
     } # end of sub user_exists
   </PRE>
   <P>
  -Perform both, read and write operations:
  +Now let's write all Upper case characters and their respective ASCII
  +values. Then read the dbm file and print them the contents of the DB
  +(unsorted).
   
   <P>
  -<PRE>  my $dbfile = &quot;/tmp/test&quot;;
  -  my %mydb = ();
  -  my $db = new DB_File::Wrap \%mydb, $dbfile;
  -  print $mydb{'stas'} if exists $mydb{'stas'};
  -  
  -    # lock the db, we gonna change it!
  -  $db-&gt;lock('write');
  -  $mydb{'stas'} = 1;
  -    # unlock the db for write
  +<PRE>  use DB_File::Lock ();
  +  my $dbfile = &quot;/tmp/test&quot;;
  +  
  +    # write 
  +  tie my %mydb, 'DB_File::Lock', $dbfile,'write';
  +  for (1..25) {
  +    $mydb{chr 65+$_} = $_;
  +  }
  +  untie %mydb;
     
  -    # sync and untie
  -  $db-&gt;end();
  +    # now, read them and printout (unsorted)
  +  tie %mydb, 'DB_File::Lock', $dbfile;
  +  while (my($k,$v) = each %mydb) {
  +    print &quot;$k =&gt; $v\n&quot;;
  +  }
  +  untie %mydb;
   </PRE>
   <P>
  -If your CGI was interrupted in the middle, <CODE>DESTROY</CODE> block will worry to unlock the dbm file and flush the changes. Note that I
  -have got db corruptions even with this code on huge dbm files 10000+
  -records, so be careful when you use it. I thought that I have covered all
  -the possible failures but seems that not all of them. At the end I have
  -moved everything to work with <STRONG>mysql</STRONG>. So if you figure out where the problem is you are very welcome to tell me
  -about it.
  +If your CGI was interrupted in the middle, <CODE>DESTROY</CODE> block will worry to unlock the dbm file and flush the changes. So your DB
  +will be safe against possible corruption because of unclean program
  +termination.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -485,7 +495,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/25/1999
  +	     <BR>Last Modified at 10/15/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.17      +100 -5    modperl-site/guide/debug.html
  
  Index: debug.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/debug.html,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- debug.html	1999/09/25 23:13:54	1.16
  +++ debug.html	1999/10/15 22:52:42	1.17
  @@ -28,6 +28,7 @@
   
   	<LI><A HREF="#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
   	<LI><A HREF="#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
  +	<LI><A HREF="#Apache_Debug">Apache::Debug</A>
   	<LI><A HREF="#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
   	<LI><A HREF="#Debugging_Core_Dumps">Debugging Core Dumps</A>
   	<LI><A HREF="#Debug_Tracing">Debug Tracing</A>
  @@ -35,9 +36,10 @@
   	<LI><A HREF="#Monitoring_error_log_file">Monitoring error_log file</A>
   	<LI><A HREF="#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
   	<LI><A HREF="#Spinning_httpds">Spinning httpds</A>
  -	<LI><A HREF="#PROFILING">PROFILING</A>
  -	<LI><A HREF="#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="#Code_Profiling">Code Profiling</A>
  +	<LI><A HREF="#Examples_of_strace_or_truss_us">Examples of strace (or truss) usage</A>
   	<LI><A HREF="#Devel_Peek">Devel::Peek</A>
  +	<LI><A HREF="#How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -92,6 +94,30 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_Debug">Apache::Debug</A></H1></CENTER>
  +<P>
  +(META: to be written)
  +
  +<P>
  +<PRE>  use Apache::Debug ();
  +  Apache::Debug::dump($r, SERVER_ERROR, &quot;Uh Oh!&quot;);
  +</PRE>
  +<P>
  +This module sends what may be helpful debugging info to the client rather
  +that the error log.
  +
  +<P>
  +Also, you could try using a larger emergency pool, try this instead of
  +Apache::Debug:
  +
  +<P>
  +<PRE> $^M = 'a' x (1&lt;&lt;18);  #260K buffer
  + use Carp ();
  + $SIG{__DIE__} = \&amp;Carp::confess;
  + eval { Carp::confess(&quot;init&quot;) };
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A></H1></CENTER>
   <P>
   Perl ships with a very useful interactive debugger, however, it does not
  @@ -299,7 +325,7 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="PROFILING">PROFILING</A></H1></CENTER>
  +<CENTER><H1><A NAME="Code_Profiling">Code Profiling</A></H1></CENTER>
   <P>
   It is possible to profile code run under mod_perl with the
   <CODE>Devel::DProf</CODE> module available on CPAN. However, you must have apache version 1.3b3 or
  @@ -323,7 +349,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="examples_of_strace_or_truss_us">examples of strace (or truss) usage</A></H1></CENTER>
  +<CENTER><H1><A NAME="Examples_of_strace_or_truss_us">Examples of strace (or truss) usage</A></H1></CENTER>
   <P>
   (META: below are some snippets of strace outputs from list's emails)
   
  @@ -414,6 +440,75 @@
   child already will already have an allocated buffer, just reset to ``'',
   when you are done.
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="How_can_I_find_if_my_mod_perl_sc">How can I find if my mod_perl scripts have memory leaks</A></H1></CENTER>
  +<P>
  +<CODE>Apache::Leak</CODE> (derived from <CODE>Devel::Leak</CODE>) should help you with this task. Example:
  +
  +<P>
  +<PRE>  use Apache::Leak;
  +  
  +  my $global = &quot;FooAAA&quot;;
  +  
  +  leak_test {
  +    $$global = 1;
  +    ++$global;
  +  };
  +</PRE>
  +<P>
  +The argument to <CODE>leak_test()</CODE> is an anonymous sub, so you can just throw it around any code you suspect
  +might be leaking. Beware, it will run the code twice, because the first
  +time in, new <CODE>SV</CODE>s are created, but does not mean you are leaking, the second pass will give
  +better evidence. You do not need to be inside mod_perl to use it, from the
  +command line, the above script outputs:
  +
  +<P>
  +<PRE>  ENTER: 1482 SVs
  +  new c28b8 : new c2918 : 
  +  LEAVE: 1484 SVs
  +  ENTER: 1484 SVs
  +  new db690 : new db6a8 : 
  +  LEAVE: 1486 SVs
  +  !!! 2 SVs leaked !!!
  +</PRE>
  +<P>
  +Build a debuggable perl to see dumps of the <CODE>SV</CODE>s. The simple way to have both a normal perl and debuggable perl, is to
  +follow hints in the
  +<CODE>SUPPORT</CODE> doc for building <CODE>libperld.a</CODE>, when that is built copy the
  +<CODE>perl</CODE> from that directory to your perl bin directory, but name it
  +<CODE>dperl</CODE>.
  +
  +<P>
  +Leak explanation: <CODE>$$global = 1;</CODE> : new global variable created
  +<CODE>FooAAA</CODE> with value of <CODE>1</CODE>, will not be destructed until this module is destroyed.
  +
  +<P>
  +<CODE>Apache::Leak</CODE> is not very user-friendly, have a look at
  +<CODE>B::LexInfo</CODE>. You'll see that what might appear to be a leak, is actually just a Perl
  +optimization. e.g. consider this code:
  +
  +<P>
  +<PRE>  sub foo {
  +    my $string = shift;
  +  }
  +</PRE>
  +<P>
  +<PRE>  foo(&quot;a string&quot;);
  +</PRE>
  +<P>
  +<CODE>B::LexInfo</CODE> will show you that Perl does not release the value from $string, unless you
  +undef it. this is because Perl anticipates the memory will be needed for
  +another string, the next time the subroutine is entered. you'll see similar
  +for <CODE>@array</CODE> length, <CODE>%hash</CODE> keys, and scratch areas of the padlist for ops such as <CODE>join()</CODE>, `<CODE>.</CODE>', etc.
  +
  +<P>
  +<CODE>Apache::Status</CODE> now includes a new StatusLexInfo option.
  +
  +<P>
  +Apache::Leak works better if you've built a libperld.a (see SUPPORT) and
  +given PERL_DEBUG=1 to mod_perl's Makefile.PL
  +
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
   	     <B>Writing Apache Modules with Perl and C</B></a>
  @@ -447,7 +542,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 09/22/1999
  +	     <BR>Last Modified at 10/12/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.11      +1235 -1067modperl-site/guide/guide-src.tar.gz
  
  	<<Binary file>>
  
  
  1.12      +1901 -1617modperl-site/guide/guide.tar.gz
  
  	<<Binary file>>
  
  
  1.18      +3 -3      modperl-site/guide/help.html
  
  Index: help.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/help.html,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- help.html	1999/09/25 23:14:01	1.17
  +++ help.html	1999/10/15 22:52:52	1.18
  @@ -332,10 +332,10 @@
   HREF="http://www.saturn5.com/~jwb/dbi-examples.html">http://www.saturn5.com/~jwb/dbi-examples.html</A>
   (by Jeffrey William Baker).
   
  -<P><LI><STRONG><A NAME="item_DBI">DBI at Hermetica</A></STRONG>
  +<P><LI><STRONG><A NAME="item_DBI">DBI Homepage</A></STRONG>
   <P>
   <A
  -HREF="http://www.hermetica.com/technologia/DBI/">http://www.hermetica.com/technologia/DBI/</A>
  +HREF="http://www.symbolstone.org/technology/perl/DBI/">http://www.symbolstone.org/technology/perl/DBI/&