You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by sb...@hyperreal.org on 1999/07/02 15:42:50 UTC

cvs commit: modperl-site/guide CHANGES all.html config.html control.html databases.html dbm.html debug.html frequent.html guide-src.tar.gz guide.tar.gz hardware.html help.html index.html install.html intro.html mod_perl_guide.ps.gz modules.html multiuser.html obvious.html performance.html porting.html scenario.html security.html start.html status.html strategy.html warnings.html

sbekman     99/07/02 06:42:48

  Modified:    guide    CHANGES all.html config.html control.html
                        databases.html dbm.html debug.html frequent.html
                        guide-src.tar.gz guide.tar.gz hardware.html
                        help.html index.html install.html intro.html
                        mod_perl_guide.ps.gz modules.html multiuser.html
                        obvious.html performance.html porting.html
                        scenario.html security.html start.html status.html
                        strategy.html warnings.html
  Log:
  * porting.pod: added "Exposing Apache::Registry secrets, closures,
    multiserver mode".
  
  * A complete review, which included corrections, verifications,
    extensions and clarifications was done to the following pods during
    the preparation of the tutorial for the 3rd apache conference:
  	start.pod
  	intro.pod
  	porting.pod
  	performance.pod
  	strategy.pod
  	scenario.pod
  	config.pod
  	install.pod
  	control.pod
  	databases.pod
  	multiuser.pod
  	help.pod
  
  Revision  Changes    Path
  1.14      +43 -0     modperl-site/guide/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/CHANGES,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- CHANGES	1999/06/19 21:14:58	1.13
  +++ CHANGES	1999/07/02 13:42:09	1.14
  @@ -1,5 +1,48 @@
   This is a CHANGES file for mod_perl guide
   
  +07.3.99 ver 1.14
  +
  +* porting.pod: added "Exposing Apache::Registry secrets, closures,
  +  multiserver mode".
  +
  +* A complete review, which included corrections, verifications,
  +  extensions and clarifications was done to the following pods during
  +  the preparation of the tutorial for the 3rd apache conference:
  +	start.pod     
  +	intro.pod     
  +	porting.pod   
  +	performance.pod
  +	strategy.pod  
  +	scenario.pod  
  +	config.pod    
  +	install.pod   
  +	control.pod   
  +	databases.pod 
  +	multiuser.pod  
  +	help.pod      
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
  +* 
  +
   06.19.99 ver 1.13
   
   * While working on presentation discovered a wonderfull 'html2ps'
  
  
  
  1.15      +7185 -6613modperl-site/guide/all.html
  
  Index: all.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/all.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- all.html	1999/06/19 21:14:59	1.14
  +++ all.html	1999/07/02 13:42:11	1.15
  @@ -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.13
  - Jun, 19 1999</B></P></CENTER>
  +<CENTER><P><B>Version 1.14
  + Jul, 2 1999</B></P></CENTER>
    
   <P>
   <HR WIDTH="100%"></P>
  @@ -57,6 +57,98 @@
   
   	<LI><A HREF="start.html#What_s_inside_">What's inside?</A>
   </UL>
  +<P><LI><A HREF="porting.html"><B><FONT SIZE=+1>CGI to mod_perl Porting. mod_perl Coding guidelines.</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="porting.html#Document_Coverage">Document Coverage</A>
  +	<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>
  +	<UL>
  +
  +		<LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
  +		<LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  +		<LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  +		<LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
  +		<LI><A HREF="porting.html#Using_format_">Using format()</A>
  +		<LI><A HREF="porting.html#Using_exit_">Using exit()</A>
  +		<LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
  +		<LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
  +		<LI><A HREF="porting.html#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  +		<LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  +		<LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
  +		<LI><A HREF="porting.html#END_blocks">END blocks</A>
  +		<LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
  +		<LI><A HREF="porting.html#strict_pragma">strict pragma</A>
  +		<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#Memory_leakage">Memory leakage</A>
  +	</UL>
  +
  +	<LI><A HREF="porting.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  +	<UL>
  +
  +		<LI><A HREF="porting.html#Restarting_the_server">Restarting the server</A>
  +		<LI><A HREF="porting.html#Using_Apache_StatINC">Using Apache::StatINC</A>
  +		<LI><A HREF="porting.html#Reloading_only_specific_files">Reloading only specific files</A>
  +	</UL>
  +
  +	<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#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_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
  +	<LI><A HREF="porting.html#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</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#Sharing_Memory">Sharing Memory</A>
  +	<LI><A HREF="performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
  +	<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</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 (and where)</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>
  +	<LI><A HREF="performance.html#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Developers_Talk">Developers Talk</A>
  +		<LI><A HREF="performance.html#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
  +		<LI><A HREF="performance.html#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
  +		<LI><A HREF="performance.html#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench </A>
  +		<LI><A HREF="performance.html#Tuning_with_crashme_script">Tuning with crashme script</A>
  +		<LI><A HREF="performance.html#Choosing_MaxClients">Choosing MaxClients</A>
  +		<LI><A HREF="performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A>
  +		<LI><A HREF="performance.html#Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A>
  +		<LI><A HREF="performance.html#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
  +	<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>
  +</UL>
   <P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Choosing the Right Strategy</FONT></B></A></LI><P>
   <UL>
   
  @@ -66,13 +158,12 @@
   	<LI><A HREF="strategy.html#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl-enabled Apache Servers</A>
   	<LI><A HREF="strategy.html#One_light_non_Apache_and_One_mod">One light non-Apache and One mod_perl enabled Apache Servers</A>
   	<LI><A HREF="strategy.html#Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A>
  -	<LI><A HREF="strategy.html#squid_server">squid server</A>
  -	<LI><A HREF="strategy.html#apache_s_mod_proxy">apache's mod_proxy</A>
  +	<LI><A HREF="strategy.html#The_Squid_Server">The Squid Server</A>
  +	<LI><A HREF="strategy.html#An_Apache_s_mod_proxy">An Apache's mod_proxy</A>
   </UL>
  -<P><LI><A HREF="scenario.html"><B><FONT SIZE=+1>Real World Scenarios Implementaion</FONT></B></A></LI><P>
  +<P><LI><A HREF="scenario.html"><B><FONT SIZE=+1>Real World Scenarios Implementation</FONT></B></A></LI><P>
   <UL>
   
  -	<LI><A HREF="scenario.html#Before_you_dive_into_the_gory_de">Before you dive into the gory details</A>
   	<LI><A HREF="scenario.html#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
   	<UL>
   
  @@ -88,7 +179,7 @@
   		<UL>
   
   			<LI><A HREF="scenario.html#Building_the_httpd_docs_Server">Building the httpd_docs Server</A>
  -			<LI><A HREF="scenario.html#Building_the_httpd_perl_Server_">Building the httpd_perl Server (mod_perl):</A>
  +			<LI><A HREF="scenario.html#Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A>
   		</UL>
   
   		<LI><A HREF="scenario.html#Configuration_of_the_servers">Configuration of the servers</A>
  @@ -112,12 +203,12 @@
   	<LI><A HREF="install.html#Configuration_and_Installation">Configuration and Installation</A>
   	<UL>
   
  -		<LI><A HREF="install.html#Perl">Perl</A>
  -		<LI><A HREF="install.html#Apache">Apache</A>
  -		<LI><A HREF="install.html#Mod_Perl">Mod_Perl</A>
  +		<LI><A HREF="install.html#perl">perl</A>
  +		<LI><A HREF="install.html#apache">apache</A>
  +		<LI><A HREF="install.html#mod_perl">mod_perl</A>
   	</UL>
   
  -	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is really installed</A>
  +	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
   	<UL>
   
   		<LI><A HREF="install.html#Testing_by_checking_the_error_lo">Testing by checking the error_log file</A>
  @@ -149,13 +240,19 @@
   		<LI><A HREF="config.html#Location_Configuration">Location Configuration</A>
   		<LI><A HREF="config.html#PerlFreshRestart">PerlFreshRestart</A>
   		<LI><A HREF="config.html#_perl_status_location">/perl-status location</A>
  +		<UL>
  +
  +			<LI><A HREF="config.html#Configuration">Configuration</A>
  +			<LI><A HREF="config.html#Usage">Usage</A>
  +			<LI><A HREF="config.html#Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A>
  +		</UL>
  +
   		<LI><A HREF="config.html#PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A>
   		<LI><A HREF="config.html#perl_startup_file">perl-startup file</A>
   		<UL>
   
   			<LI><A HREF="config.html#Sample_perl_startup_file">Sample perl-startup file</A>
   			<LI><A HREF="config.html#What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A>
  -			<LI><A HREF="config.html#Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</A>
   			<LI><A HREF="config.html#The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A>
   			<LI><A HREF="config.html#The_confusion_with_defining_glob">The confusion with defining globals in startup</A>
   		</UL>
  @@ -188,94 +285,20 @@
   	<LI><A HREF="frequent.html#Coverage">Coverage</A>
   	<LI><A HREF="frequent.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
   	<LI><A HREF="frequent.html#Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A>
  -</UL>
  -<P><LI><A HREF="porting.html"><B><FONT SIZE=+1>CGI to mod_perl Porting. mod_perl Coding guidelines.</FONT></B></A></LI><P>
  -<UL>
  -
  -	<LI><A HREF="porting.html#Document_Coverage">Document Coverage</A>
  -	<LI><A HREF="porting.html#Before_you_start_to_code">Before you start to code</A>
  -	<LI><A HREF="porting.html#Coding_with_mod_perl">Coding with mod_perl</A>
  -	<UL>
  -
  -		<LI><A HREF="porting.html#What_s_different_about_modperl">What's different about modperl</A>
  -		<UL>
  -
  -			<LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
  -			<LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  -			<LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  -			<LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
  -			<LI><A HREF="porting.html#Using_format_">Using format()</A>
  -			<LI><A HREF="porting.html#Using_exit_">Using exit()</A>
  -			<LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
  -			<LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
  -			<LI><A HREF="porting.html#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  -			<LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  -			<LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
  -			<LI><A HREF="porting.html#END_blocks">END blocks </A>
  -			<LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
  -		</UL>
  -
  -		<LI><A HREF="porting.html#strict_pragma">strict pragma</A>
  -		<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#Global_Variables">Global Variables</A>
  -		<LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</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#Memory_leakage">Memory leakage</A>
  -	</UL>
  -
  -	<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
  -	<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</A>
  -	<LI><A HREF="porting.html#The_Script_is_too_dirty_It_does">The Script is too dirty, 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#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_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
  -	<LI><A HREF="porting.html#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
   </UL>
  -<P><LI><A HREF="performance.html"><B><FONT SIZE=+1>Performance. Benchmarks.</FONT></B></A></LI><P>
  +<P><LI><A HREF="control.html"><B><FONT SIZE=+1>Controlling and Monitoring the Server</FONT></B></A></LI><P>
   <UL>
  -
  -	<LI><A HREF="performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
  -	<UL>
  -
  -		<LI><A HREF="performance.html#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A>
  -	</UL>
  -
  -	<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
  -	<LI><A HREF="performance.html#Sharing_Memory">Sharing Memory</A>
  -	<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</A>
  -	<LI><A HREF="performance.html#How_can_I_find_if_my_modperl_scr">How can I find if my modperl scripts have memory leaks (and where)</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>
  -	<LI><A HREF="performance.html#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
  -	<UL>
  -
  -		<LI><A HREF="performance.html#Developers_Talk">Developers Talk</A>
  -		<LI><A HREF="performance.html#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
  -		<LI><A HREF="performance.html#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
  -		<LI><A HREF="performance.html#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
  -	</UL>
  -
  -	<LI><A HREF="performance.html#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  -	<UL>
  -
  -		<LI><A HREF="performance.html#Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench </A>
  -		<LI><A HREF="performance.html#Tuning_with_crashme_script">Tuning with crashme script</A>
  -		<LI><A HREF="performance.html#Choosing_MaxClients">Choosing MaxClients</A>
  -		<LI><A HREF="performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A>
  -		<LI><A HREF="performance.html#Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A>
  -		<LI><A HREF="performance.html#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
  -	</UL>
   
  -	<LI><A HREF="performance.html#Preopen_DB_connection_at_server_">Preopen DB connection at server startup:</A>
  -	<LI><A HREF="performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
  -	<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="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#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>
  +	<LI><A HREF="control.html#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
  +	<LI><A HREF="control.html#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
  +	<LI><A HREF="control.html#Log_Rotation">Log Rotation</A>
  +	<LI><A HREF="control.html#Preventing_from_modperl_process_">Preventing from modperl process from going wild</A>
   </UL>
   <P><LI><A HREF="obvious.html"><B><FONT SIZE=+1>Things obvious to others, but not to you</FONT></B></A></LI><P>
   <UL>
  @@ -290,14 +313,6 @@
   		<LI><A HREF="obvious.html#Additional_reading_references">Additional reading references</A>
   	</UL>
   
  -	<LI><A HREF="obvious.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  -	<UL>
  -
  -		<LI><A HREF="obvious.html#Restarting_the_server">Restarting the server</A>
  -		<LI><A HREF="obvious.html#Using_Apache_StatINC">Using Apache::StatINC</A>
  -		<LI><A HREF="obvious.html#Reloading_only_specific_files">Reloading only specific files</A>
  -	</UL>
  -
   	<LI><A HREF="obvious.html#Compiled_Regular_Expressions">Compiled Regular Expressions </A>
   	<LI><A HREF="obvious.html#Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A>
   	<LI><A HREF="obvious.html#_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A>
  @@ -329,20 +344,6 @@
   	<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>
   </UL>
  -<P><LI><A HREF="control.html"><B><FONT SIZE=+1>Controlling and Monitoring the Server</FONT></B></A></LI><P>
  -<UL>
  -
  -	<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#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>
  -	<LI><A HREF="control.html#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
  -	<LI><A HREF="control.html#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
  -	<LI><A HREF="control.html#Log_Rotation">Log Rotation</A>
  -	<LI><A HREF="control.html#Preventing_from_modperl_process_">Preventing from modperl process from going wild</A>
  -</UL>
   <P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
   <UL>
   
  @@ -534,7 +535,10 @@
   
   <UL>
   
  -<LI><A HREF="all.html"><B>Guide All in One. Ready for Printing</B></A></LI>
  +<LI><A HREF="all.html"><B>Guide All in One. Ready for Printing</B></A>
  +(You better use the Postscript Book -- <A
  +HREF="mod_perl_guide.ps.gz">mod_perl_guide.ps.gz</A>)
  + </LI>
   
   <LI><A HREF="CHANGES"><B>CHANGES</B></A></LI>
   
  @@ -583,11 +587,20 @@
   <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
   <HR></TD>
   </TR>
  -
   <TR ALIGN=CENTER VALIGN=TOP>
  +<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  +URL: <B>http://perl.apache.org/guide</B><BR>
  +Copyright &copy; 1998, 1999 Stas Bekman. All rights reserved.
  +</TD>
  +</TR>
  +<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 06/19/1999
  +HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 07/02/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>
  @@ -898,7 +911,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -946,7 +959,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>
   Guide's Overview</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -1100,7 +1113,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]
  +	     [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -1113,7 +1126,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/14/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -1140,7 +1153,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Choosing the Right Strategy</TITLE>
  +   <TITLE>mod_perl guide: CGI to mod_perl Porting. mod_perl Coding guidelines.</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">
  @@ -1159,20 +1172,56 @@
   <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>
  +CGI to mod_perl Porting. mod_perl Coding guidelines.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.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="#squid_server">squid server</A>
  -	<LI><A HREF="#apache_s_mod_proxy">apache's mod_proxy</A>
  +	<LI><A HREF="#Document_Coverage">Document Coverage</A>
  +	<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>
  +	<UL>
  +
  +		<LI><A HREF="#Script_s_name_space">Script's name space</A>
  +		<LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  +		<LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  +		<LI><A HREF="#Output_from_system_calls">Output from system calls</A>
  +		<LI><A HREF="#Using_format_">Using format()</A>
  +		<LI><A HREF="#Using_exit_">Using exit()</A>
  +		<LI><A HREF="#Running_from_shell">Running from shell</A>
  +		<LI><A HREF="#I_O_is_different">I/O is different</A>
  +		<LI><A HREF="#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  +		<LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  +		<LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
  +		<LI><A HREF="#END_blocks">END blocks</A>
  +		<LI><A HREF="#Switches_w_T">Switches -w, -T</A>
  +		<LI><A HREF="#strict_pragma">strict pragma</A>
  +		<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="#Memory_leakage">Memory leakage</A>
  +	</UL>
  +
  +	<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  +	<UL>
  +
  +		<LI><A HREF="#Restarting_the_server">Restarting the server</A>
  +		<LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
  +		<LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</A>
  +	</UL>
  +
  +	<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="#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_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
  +	<LI><A HREF="#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -1190,1973 +1239,1988 @@
   
   	      <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>
  +<CENTER><H1><A NAME="Document_Coverage">Document Coverage</A></H1></CENTER>
   <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, and
  -some hints on approaches that should be used and things to avoid.
  +This document is relevant to both writing a new CGI from scratch and
  +migrating an application from plain CGI to mod_perl.
   
   <P>
  -To be clear, I will not address all technologies and tools, but limit this
  -discussion to those complementing mod_perl.
  +If you are in the porting stage, use it as a reference for possible
  +problems you might encounter when running the existent CGI in the new mode.
   
   <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 out what this is.
  +If you are about to write a new CGI from scratch, it would be a good idea
  +to learn most of the possible pitfalls and to avoid them in first place.
   
   <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>
  +It covers also the case where the CGI script being ported does the job, but
  +is too dirty to be easily altered to run as a mod_perl program. (<CODE>Apache::PerlRun</CODE>)
  +
   <P>
  -There are several different ways to build, configure and deploy your
  -mod_perl enabled server. Some of them are:
  +If your project schedule is tight, I would suggest converting to mod_perl
  +in the following steps: Initially, run all the scripts in the
  +<CODE>Apache::PerlRun</CODE> mode. Then as time allows, move them into
  +<CODE>Apache::Registry</CODE> mode.
   
  -<OL>
  -<P><LI>
   <P>
  -Having one binary and one config file (one big binary for mod_perl).
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Before_you_start_to_code">Before you start to code</A></H1></CENTER>
  +<P>
  +It can be a good idea to tighten up some of your Perl programming
  +practices, since <CODE>Apache::Registry</CODE> doesn't allow sloppy programming.
   
  -<P><LI>
   <P>
  -Having two binaries and two config files (one big binary for mod_perl and
  -one small for static objects like images.)
  +You might want to read:
   
  -<P><LI>
  +<UL>
  +<P><LI><STRONG><A NAME="item_Perl">Perl Module Mechanics</A></STRONG>
   <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.)
  +This page describes the mechanics of creating, compiling, releasing, and
  +maintaining Perl modules. <A
  +HREF="http://world.std.com/~swmcd/steven/perl/module_mechanics.html">http://world.std.com/~swmcd/steven/perl/module_mechanics.html</A>
   
  -<P><LI>
  -<P>
  -Any of the above plus a reverse proxy server in http accelerator mode.
   
  -</OL>
  +<P><LI><STRONG><A NAME="item_Mod">Mod Perl Book</A></STRONG>
   <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 forth
  -option which gives you even more power.
  +A must have book! See the details at <A
  +HREF="http://www.modperl.com">http://www.modperl.com</A> .
   
  -<OL>
  -<P><LI>
  +</UL>
   <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.
  -
  -<P><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A></H1></CENTER>
   <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 sync. 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.
  +Let's start with some simple code and see what can go wrong with it ,detect
  +bugs and debug them, discuss possible caveats and how to avoid them.
   
  -<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 milegue may vary. See <A HREF="././scenario.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>.
  +I will use a simple CGI script, that initializes a <CODE>$counter</CODE> to 0, and prints its value to the screen while incrementing it.
   
  -<P><LI>
   <P>
  -The fourth option (proxy in http accelerator mode), once correctly
  -configured and tuned, improves performance by caching and buffering page
  -results.
  -
  -</OL>
  +<PRE>  counter.pl:
  +  ----------
  +  #!/usr/bin/perl -w
  +  use strict;
  +  
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  
  +  my $counter = 0;
  +  
  +  for (1..5) {
  +    increment_counter();
  +  }
  +  
  +  sub increment_counter{
  +    $counter++;
  +    print &quot;Counter is equal to $counter !&lt;BR&gt;\n&quot;;
  +  }
  +  ----------
  +</PRE>
   <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.
  +You would expect to see an output:
   
  -<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>
   <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.
  -
  +<PRE>  Counter is equal to 1 !
  +  Counter is equal to 2 !
  +  Counter is equal to 3 !
  +  Counter is equal to 4 !
  +  Counter is equal to 5 !
  +</PRE>
   <P>
  -The Advantages:
  +And that's what you see when you execute this script at first time. But
  +let's reload it a few times... See, suddenly after a few reloads the
  +counter doesn't start its count from 5 anymore. We continue to reload and
  +see that it keeps on growing, but not steadily 10, 10, 10, 15, 20...
  +Weird...
   
  -<UL>
  -<P><LI>
   <P>
  -Simplicity. You just follow the installation instructions, configure it,
  -restart the server and you are done.
  -
  -<P><LI>
  +<PRE>  Counter is equal to 6 !
  +  Counter is equal to 7 !
  +  Counter is equal to 8 !
  +  Counter is equal to 9 !
  +  Counter is equal to 10 !
  +</PRE>
   <P>
  -No network changes. You do not have to worry about using additional ports
  -as we will see later.
  +We saw two anomalies in this very simple script: Unexpected growth of
  +counter over 5 and inconsistent growth over reloads. Let's investigate this
  +script.
   
  -<P><LI>
   <P>
  -Speed. You get a very fast server, you see an enormous speedup from the
  -first moment you start to use it.
  +First let's peek into an <CODE>error_log</CODE> file... what we see is:
   
  -</UL>
   <P>
  -The Disadvantages:
  -
  -<UL>
  -<P><LI>
  +<PRE>  Variable &quot;$counter&quot; will not stay shared 
  +  at /home/httpd/perl/conference/counter.pl line 13.
  +</PRE>
   <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
  +What kind of error is this? We should ask perl to help us. I'm going to
  +enable a special diagnostics mode, by adding at the top of the script:
   
   <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.
  -
  +<PRE>  use diagnostics;
  +</PRE>
   <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.
  +Reloading again, <CODE>error_log</CODE> shows:
   
  -<P><LI>
   <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.
  +<PRE>    Variable &quot;$counter&quot; will not stay shared at
  +        /home/httpd/perl/conference/counter.pl line 15 (#1)
  +    
  +    (W) An inner (nested) named subroutine is referencing a lexical
  +    variable defined in an outer subroutine.
  +    
  +    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.
  +    
  +    Furthermore, if the outer subroutine is anonymous and references a
  +    lexical variable outside itself, then the outer and inner subroutines
  +    will never share the given variable.
  +    
  +    This problem can usually be solved by making the inner subroutine
  +    anonymous, using the sub {} syntax.  When inner anonymous subs that
  +    reference variables in outer subroutines are called or referenced,
  +    they are automatically rebound to the current values of such
  +    variables.
  +</PRE>
  +<P>
  +Actually perl detected a <STRONG>closure</STRONG>, which is sometimes a wanted effect, but not in our case (see <CODE>perldoc perlsub</CODE> for more information about closures). While <CODE>diagnostics.pm</CODE> sometimes is handy for debugging purpose - it drastically slows down your
  +CGI script. Make sure you remove it in your production server.
  +
  +<P>
  +Do you see a <STRONG>nested named subroutine</STRONG> in my script? I do not!!! What is going on? I suggest to report a bug. But
  +wait, may be a perl interpreter sees the script in a different way, may be
  +the code goes through some changes before it actually gets executed? The
  +easiest way to check what's actually happening is to run the script with
  +debugger, but since we must debug it when it's being executed by the
  +server, normal debugging process wouldn't help, for we have to invoke the
  +debugger from within the webserver. Luckily Doug wrote an
  +<CODE>Apache::DB</CODE> module and we will use it to debug my script. I'll do it non-interactively
  +(while you can debug interactively with
  +<CODE>Apache::DB</CODE>). I change my <CODE>http.conf</CODE> with:
   
   <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.
  -
  -</UL>
  +<PRE>  PerlSetEnv PERLDB_OPTS &quot;NonStop=1 LineInfo=/tmp/db.out AutoTrace=1 frame=2&quot;
  +  PerlModule Apache::DB
  +  &lt;Location /perl&gt;
  +    PerlFixupHandler Apache::DB
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry::handler
  +    Options ExecCGI
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
   <P>
  -If you are new to mod_perl, this is probably the best way to get yourself
  -started.
  +Comment out '<CODE>use diagnostics;</CODE>', restart the server and call the
  +<CODE>counter.pl</CODE> from your browser. On the surface nothing changed - we still see the
  +correct output as before, but two things happened at the background: first
  +-- the <CODE>/tmp/db.out</CODE> was written, with a complete trace of the code that was executed, second -- <CODE>error_log</CODE> file showed us the whole code that was executed as a side effect of
  +reporting the warning we saw before: <CODE>Variable &quot;$counter&quot; will not
  +stay shared at (eval 52) line 15...</CODE>. In any case that's the code that actually is being executed:
   
   <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!
  -
  +<PRE>  package Apache::ROOT::perl::conference::counter_2epl;
  +  use Apache qw(exit);
  +  sub handler {
  +    BEGIN {
  +      $^W = 1;
  +    };
  +    $^W = 1;
  +    
  +    use strict;
  +    
  +    print &quot;Content-type: text/html\\r\\n\\r\\n&quot;;
  +    
  +    my $counter = 0;
  +    
  +    for (1..5) {
  +      increment_counter();
  +    }
  +    
  +    sub increment_counter{
  +      $counter++;
  +      print &quot;Counter is equal to $counter !&lt;BR&gt;\\n&quot;;
  +    }
  +    
  +  }
  +</PRE>
   <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>
  -
  +What do we learn from this discovering? First that every cgi script is
  +being cached under a package whose name is compounded from
  +<CODE>Apache::ROOT::</CODE> prefix and the relative part of the script's URL (<CODE>perl::conference::counter_2epl</CODE>) by replacing all occurrences of
  +<CODE>/</CODE> with <CODE>::</CODE>. That's how mod_perl knows what script should be fetched from cache - each
  +script is just a package with a single subroutine named <CODE>handler</CODE>. Now you understand why <CODE>diagnostics</CODE>
  +pragma talked about inner (nested) subroutine - <CODE>increment_counter</CODE>
  +is actually a nested sub. In every script each subroutine is nested inside
  +the <CODE>handler</CODE> subroutine.
   
  -
  -<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>
   <P>
  -As I have mentioned before, when running scripts under mod_perl, you will
  -notice that the httpd processes consume a huge amount of memory, from 5M to
  -25M, or even more. That is the price you pay for the enormous speed
  -improvements under mod_perl.
  +The workaround is to use global declared variables, with <CODE>vars</CODE>
  +pragma.
   
   <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>  # !/usr/bin/perl -w
  +  use strict;
  +  use vars qw($counter);
  +  
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  
  +  $counter = 0;
  +  
  +  for (1..5) {
  +    increment_counter();
  +  }
  +  
  +  sub increment_counter{
  +    $counter++;
  +    print &quot;Counter is equal to $counter !&lt;BR&gt;\n&quot;;
  +  }
  +</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).
  +There is no more <CODE>closure</CODE> effect, since there is no <CODE>my()</CODE>
  +(lexically) defined variable being used in the nested subroutine.
   
   <P>
  -The Advantages:
  +Another approach is to use fully qualified variables, which is even better,
  +since less memory will be used, but it adds an overhead of extra typing:
   
  -<UL>
  -<P><LI>
   <P>
  -The heavy mod_perl processes serve only dynamic requests, which allows the
  -deployment of fewer of these large servers. When user browses static pages,
  -all relative URLs (e.g. <CODE>/main/download.html</CODE>) are being served by the light plain apache server. But this is not the
  -case with dynamically generated pages, all relative URLs in the dynamically
  -generated HTML will be served by the mod_perl process. 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). When you generate a HTML page which has relative
  -references to images or other static objects - the user's browser sets its
  -base url to point to that of the
  -<CODE>httpd_perl</CODE> server. Because of this, all static requests will be sent to the heavy <CODE>httpd_perl</CODE>. Beware! You can solve this by either generating full URLs to the <CODE>httpd_docs</CODE> server (the fastest) or by rewriting the requests back to <CODE>httpd_docs</CODE> inside the <CODE>httpd_perl</CODE>
  -<CODE>server(much</CODE> slower). This is not a problem if you hide the
  -internal implementations, so client sees only one server running on port
  -<CODE>80</CODE>. (<A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>)
  -
  -<P><LI>
  +<PRE>  #!/usr/bin/perl -w
  +  use strict;
  +  
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  
  +  $main::counter = 0;
  +  
  +  for (1..5) {
  +    increment_counter();
  +  }
  +  
  +  sub increment_counter{
  +    $main::counter++;
  +    print &quot;Counter is equal to $main::counter !&lt;BR&gt;\n&quot;;
  +  }
  +</PRE>
   <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 better server performance.
  +Now let's proceed to the second mystery. Why did we see inconsistent
  +results over numerous reloads. That's very simple. Every time a server gets
  +a request to process, it handles it over one of the children, generally in
  +a round robin fashion. So if you have 10 httpd children alive, first 10
  +reloads might seem to be correct. Since the closure starts to effect from
  +the second re-invocation, consequent reloads return unexpected results.
  +Moreover children don't serve the same request always consequently, at any
  +given moment one of the children could serve more times the same script
  +than any other. That's why we saw that strange behavior.
   
   <P>
  -Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
  +A workaround is to run the server in a single server mode. You achieve this
  +by invoking the server with <CODE>-X</CODE> parameter (<CODE>httpd -X</CODE>). Since there is no other servers (children) running - you will detect the
  +problem on the second reload. But before that let the <CODE>error_log</CODE> to help you detect most of the possible errors - most of the warnings can
  +become errors, so you better make sure to check every warning that is being
  +detected by perl, and probably to write the code in a way, that none of the
  +warnings will show up in the <CODE>error_log</CODE>. If your
  +<CODE>error_log</CODE> file is being filled up with hundreds of lines on every script invocation -
  +you will have a problem to locate and notice real problems.
   
  -</UL>
   <P>
  -The Disadvantages:
  +Of course none of the warnings will be reported if the warning mechanism
  +will not be turned ON. With mod_perl it is also possible to turn on
  +warnings globally via the PerlWarn directive, just add into a
  +<CODE>httpd.conf</CODE>:
   
  -<UL>
  -<P><LI>
   <P>
  -An administration overhead.
  -
  -<UL>
  -<P><LI>
  +<PRE>    PerlWarn On
  +</PRE>
   <P>
  -A need for two different configuration files, two log files sets, etc. 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, storing the apache include files), most of them should be
  -separated and the configuration files updated to reflect the changes. (Of
  -course, this assumes that both are built from the same source
  -distribution.)
  +You can turn it off within your code with <CODE>local $^W=0</CODE>. on the local basis (or inside the block). If you write <CODE>$^W=0</CODE> you disable the warning mode everywhere inside the child, <CODE>$^W=1</CODE> enables it back. So if perl warns you somewhere you sure it's not a
  +problem, you can locally disable the warning, e.g.:
   
  -<P><LI>
   <P>
  -A need for two sets of controlling scripts (startup/shutdown)
  -
  -<P><LI>
  +<PRE>  [snip]
  +    # we want perl to be quiet here - 
  +    # we don't care whether $a was initialized
  +  local $^W = 0;
  +    print $a;
  +  local $^W = 1;
  +  [snip]
  +</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.
  +Of course this is not a way to fix initialization and other problems, but
  +sometimes it helps.
   
  -</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.
  +While having a warning mode turned <STRONG>On</STRONG> is a must in a development server, you better turn it globally <STRONG>Off</STRONG> in a production server, since if every CGI script generates only one
  +warning per request, and your server serves millions of requests per day -
  +your log file will eat up all of your disk space and machine will die. My
  +production serves has the following directive in the <CODE>httpd.conf</CODE>:
   
   <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.
  -
  -</UL>
  +<PRE>    PerlWarn Off
  +</PRE>
   <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.
  +While we are talking about control flags, another even more important flag
  +is <CODE>-T</CODE> which turns <STRONG>On</STRONG> the <STRONG>Taint</STRONG> mode <STRONG>On</STRONG>. Since this is very broad topic I'll not discuss it here, but if you
  +aren't forcing all of your scripts to run under <STRONG>Taint</STRONG> mode you are looking for a trouble (always remember about malicious users).
  +To turn it on, add to
  +<CODE>httpd.conf</CODE>:
   
   <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>
  -
  -
  -
  +<PRE>  PerlTaintCheck On
  +</PRE>
   <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>
  -<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>
  -Meta: Hey No personal experience. Please let me know if I have missed some
  -pros/cons here. Thanks!
  -
  +<CENTER><H1><A NAME="Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A></H1></CENTER>
   <P>
  -The Advantages:
  +When you start running your scripts under mod_perl, you might find yourself
  +in situation where a script seems to work, but sometimes it screws up. And
  +the more it runs without a restart, the more it screws up. Many times you
  +can resolve this problem very easily. You have to test your script under a
  +server running in a single process mode (<CODE>httpd -X</CODE>).
   
  -<UL>
  -<P><LI>
   <P>
  -All the advantages of the 2 servers scenario.
  +Generally the problem you have is of using global variables. Since global
  +variables don't change from one script invocation to another unless you
  +change them, you can find your scripts do ``fancy'' things.
   
  -<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.
  +The first example is amazing -- Web Services. Imagine that you enter some
  +site you have your account on (Free Email Account?). Now you want to see
  +what other users read.
   
   <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. Than the save-ups with <STRONG>thttpd</STRONG> are much smaller.
  +You type in your name and passwd, and you expect to enter to your account,
  +but instead you enter the account of someone else. This is cool isn't it?
  +Is it a bug or feature. (For some of us it's a feature, while for others
  +it's a bug.) You say, why in the world does this happen? The answer is
  +simple: Global Variables. You have entered the account of someone who
  +happened to be served by the same server child as you. Because of sloppy
  +programming, a global variable was not reset at the beginning of the
  +program and voila, you can easily peek into other people's emails! You
  +would think that it can't happen, since you have entered the login and
  +passwd. I tell you, it happens! See for yourself:
   
  -<P><LI>
   <P>
  -Reported to be about 5 times faster then plain apache serving static
  -objects.
  -
  -</UL>
  +<PRE>  use vars ($authenticated);
  +  my $q = new CGI;
  +  my $username = $q-&gt;param('username');
  +  my $passwd   = $q-&gt;param('passwd');
  +  authenticate($username,$passwd);
  +    # failed, break out
  +  die &quot;Wrong passwd&quot; unless $authenticated == 1;
  +    # user is OK, fetch user's data
  +  show_user($username);
  +  
  +  sub authenticate{
  +    my ($username,$passwd) = @_;
  +        # some checking
  +    $authenticated = 1 if (SOMETHING);
  +  }
  +</PRE>
   <P>
  -The Disadvantages:
  +Do you see the catch? With the code above, I can type in any valid username
  +and any dummy passwd and enter that user's account, if someone has
  +successfully entered his account before me using the same child process!
  +Since <STRONG>$authenticated</STRONG> is global - if it becomes 1 once it'll be 1 for the remainder of the
  +child's life!!! The solution is trivial -- reset <STRONG>$authenticated</STRONG> to 0 at the beginning of the program. (Or many other different solutions).
  +Of course this example is trivial -- but believe me it happens!
   
  -<UL>
  -<P><LI>
   <P>
  -Lacks some of apache's features, like access control, error redirection,
  -customizable logfile formats, and so on.
  +Just another little one liner that can spoil your day, assuming you forgot
  +to reset the <STRONG>$allowed</STRONG> variable. It works perfectly OK in plain mod_cgi:
   
  -</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>
  +<PRE>  $allowed = 1 if $username eq 'admin';
  +</PRE>
   <P>
  -At the beginning there were 2 servers: one - plain apache server, which was
  -_very_ light, and configured to serve static objects, the other - mod_perl
  -enabled, which was _very_ heavy 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 httpd_docs (e.g. <A
  -HREF="http://www.nowhere.com/images/test.gif">http://www.nowhere.com/images/test.gif</A>
  -) and 8080 for httpd_perl (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. (Note that later on, I
  -will be moving the httpd_docs server to port 81.)
  +But you will let any user to admin your system with the line above (again
  +assuming you have used the same child prior to some user request).
   
   <P>
  -Now I am going to convince you that you _want_ to use a proxy server (in
  -the http accelerator mode). The advantages are:
  +Another good example is usage of the <STRONG>/o</STRONG> regular expression qualifier, which compiles a regular expression once, on
  +its first execution and never recompile it again. This problem can be
  +difficult to detect, as after restarting the server each request you make
  +will be served by a different child process, and thus the regex pattern for
  +that child will be compiled fresh. Only when you make a request that
  +happens to be served by a child which has already cached the regexp will
  +you see the problem. Generally you miss that and when you press reload, you
  +see that it works (with a new, fresh child) and then it doesn't (with a
  +child that already cached the regexp and wouldn't recompile because of <STRONG>/o</STRONG>.) The example of such a case would be:
   
  -<UL>
  -<P><LI>
   <P>
  -Allow serving of static objects from the proxy's cache (objects that
  -previously were entirely served by the httpd_docs server).
  +<PRE>  my $pat = '^foo$'; # likely to be input from an HTML form field
  +  foreach( @list ) {
  +    print if /$pat/o;
  +  }
  +</PRE>
  +<P>
  +To make sure you don't miss these bugs always test your CGI in
  +<A HREF="././control.html#Running_server_in_a_single_mode">single process</A>. To solve this particular <STRONG>/o</STRONG> problem refer to <A HREF="././obvious.html#Compiled_Regular_Expressions">Compiled Regular Expressions</A>.
   
  -<P><LI>
  +<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>
  -You get less I/O activity reading 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 serve the static objects faster.
  +There are a few things that behave differently under mod_perl. It's good to
  +know what they are.
   
  -<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.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Script_s_name_space">Script's name space</A></H2></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,
  +if your URI is <STRONG>/perl/test.pl</STRONG> the package will be called
  +<STRONG>Apache::ROOT::perl::test_2epl</STRONG>.
   
   <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 was left
  -to the reader as an exercise :)
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H2></CENTER>
  +<P>
  +To make things clear before we go into details: each child process has its
  +own <CODE>%INC</CODE> hash which is used to store information about its compiled modules. The
  +keys of the hash are the names of the modules or parameters passed to <CODE>require()</CODE>. The values are the real paths to these modules. So if you do:
   
   <P>
  -To make your 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 visit _heavy_ sites). So the speed of 3.6kb/sec we were
  -assuming before, may many times be 5-10 times slower.
  +<PRE>  use lib qw(.);
  +  require &quot;./my/lib.pl&quot;;
  +</PRE>
  +<P>
  +where <CODE>./my/lib.pl</CODE> is actually a <CODE>/home/httpd/perl/my/lib.pl</CODE>. The following entry will show up in the <CODE>%INC</CODE>:
   
  -<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 pretty big topic, and it would not be
  -included in the scope of this document)
  +<PRE>  print $INC{&quot;./my/lib.pl&quot;};
  +   
  +  printed result:
  +  ---------------
  +  /home/httpd/perl/my/lib.pl
  +</PRE>
  +<P>
  +I'm talking about single server child below!
   
  -<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.
  +Let's look at 3 faulty scenarios:
   
  -<P><LI>
  +<DL>
  +<P><DT><STRONG><A NAME="item_Scenario">Scenario 1</A></STRONG><DD>
   <P>
  -You can have the <CODE>mod_proxy</CODE> process serve your static documents from disk to ``kill two birds with one
  -stone''.
  +First, You can't have 2 identical module names running under the same
  +server! Only the first one <CODE>use()'d</CODE> or <CODE>require()'d</CODE>
  +will be compiled into the package, the request to the other identical
  +module will be skipped since server will think that it's already compiled.
  +It's already in the child's <CODE>%INC</CODE>. (See <A HREF="././status.html#Watching_the_server">Watching the server</A> section to find out how you can know what is loaded and where)
   
  -</UL>
   <P>
  -The disadvantages are:
  +So if you have two different <CODE>Foo</CODE> modules in two different directories and two scripts <CODE>script1.pl</CODE> and <CODE>script2.pl</CODE>, locate like:
   
  -<UL>
  -<P><LI>
   <P>
  -Of course there are drawbacks. Luckily, these are not functionality
  -drawbacks, but more of administration hassle. You add another program 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.
  +<PRE>  ./cgi/tool1/Foo.pm
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/Foo.pm
  +  ./cgi/tool2/tool2.pl
  +</PRE>
  +<P>
  +Where a sample code could be:
   
  -<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.
  +<PRE>  ./cgi/tool1/tool1.pl
  +  --------------------
  +  use Foo;
  +  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;I'm Script number One&lt;BR&gt;\n&quot;;
  +  foo();
  +  --------------------
  +</PRE>
  +<P>
  +<PRE>  ./cgi/tool1/Foo.pm
  +  --------------------
  +  sub foo{
  +    print &quot;&lt;B&gt;I'm Tool Number One!&lt;/B&gt;&lt;BR&gt;\n&quot;;
  +  }
  +  1;
  +  --------------------
  +</PRE>
  +<P>
  +<PRE>  ./cgi/tool2/tool2.pl
  +  --------------------
  +  use Foo;
  +  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;I'm Script number Two&lt;BR&gt;\n&quot;;
  +  foo();
  +  --------------------
  +</PRE>
  +<P>
  +<PRE>  ./cgi/tool2/Foo.pm
  +  --------------------
  +  sub foo{
  +    print &quot;&lt;B&gt;I'm Tool Number Two!&lt;/B&gt;&lt;BR&gt;\n&quot;;
  +  }
  +  1;
  +  --------------------
  +</PRE>
  +<P>
  +And both scripts call: <CODE>use Foo</CODE> only the first one called will know about Foo, when you will call the
  +second script it will not know about Foo at all - it's like you've
  +forgotten to write <CODE>use Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to detect that kind of bug immediately.
   
  -</UL>
   <P>
  -Have I succeeded in convincing you that you want the proxy server?
  +You will see the following in the error_log file:
   
   <P>
  -If you are on a local area network, 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>  Undefined subroutine
  +  &amp;Apache::ROOT::perl::tool2_2epl::some_function called at
  +  /home/httpd/perl/tool2.pl line 4.
  +</PRE>
  +<P><DT><STRONG>Scenario 2</STRONG><DD>
  +<P>
  +The above is true for the files you <CODE>require()</CODE> as well (assuming that the required files do not declare a package). If you
  +have:
   
   <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>  ./cgi/tool1/config.pl
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/config.pl
  +  ./cgi/tool2/tool2.pl
  +</PRE>
  +<P>
  +And both scripts do:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="squid_server">squid server</A></H1></CENTER>
  +<PRE>  use lib qw(.);
  +  require &quot;config.pl&quot;;
  +</PRE>
   <P>
  -The Advantages:
  +While the content of the scripts and <CODE>config.pl</CODE> files is exactly like in the example above. Only the first one will
  +actually do the
  +<CODE>require()</CODE>, all for the same reason that <CODE>%INC</CODE> already includes the key <STRONG>"config.pl"</STRONG>! The second scenario is not different from the first one, since there is
  +no difference between <CODE>use()</CODE> and
  +<CODE>require()</CODE> if you don't have to import some symbols into a calling script.
   
  -<UL>
  -<P><LI>
  +<P><DT><STRONG>Scenario 3</STRONG><DD>
   <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.
  +What's interesting that the following scenario wouldn't work too!
   
  -<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.
  +<PRE>  ./cgi/tool/config.pl
  +  ./cgi/tool/tool1.pl
  +  ./cgi/tool/tool2.pl
  +</PRE>
  +<P>
  +where <CODE>tool1.pl</CODE> and <CODE>tool2.pl</CODE> both <CODE>require()</CODE> the <STRONG>same</STRONG>
   
  -<P><LI>
  +<CODE>config.pl</CODE>.
  +
  +</DL>
   <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.
  +There are 3 solutions for that: (make sure you read the whole item 3)
   
  -</UL>
  +<DL>
  +<P><DT><STRONG><A NAME="item_Solution">Solution 1</A></STRONG><DD>
   <P>
  -The Disadvantages:
  +The first two faulty scenarios can be solved by placing your library
  +modules in a subdirectory structure so that they have different path
  +prefixes. The file system layout will be something like:
   
  -<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>  ./cgi/tool1/Tool1/Foo.pm
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/Tool2/Foo.pm
  +  ./cgi/tool2/tool2.pl
  +</PRE>
  +<P>
  +And change the scripts:
   
  -<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>  use Tool1::Foo;
  +  use Tool2::Foo;
  +</PRE>
  +<P>
  +For <CODE>require()</CODE> (scenario number 2) use the following:
   
  -<P><LI>
   <P>
  -Memory usage. Squid uses quite a bit of memory.
  +<PRE>  ./cgi/tool1/tool1-lib/config.pl
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/tool2-lib/config.pl
  +  ./cgi/tool2/tool2.pl
  +</PRE>
  +<P>
  +And each script does respectively:
   
  -<P><LI>
   <P>
  -HTTP protocol level. Squid is pretty much a HTTP/1.0 server, which
  -seriously limits the deployment of HTTP/1.1 features.
  +<PRE>  use lib qw(.);
  +  require &quot;tool1-lib/config.pl&quot;;
  +</PRE>
  +<P>
  +<PRE>  use lib qw(.);
  +  require &quot;tool2-lib/config.pl&quot;;
  + 
  +But this solution is very bad, since while it might work for you now,
  +if you add another script that wants to use the same module or
  +C&lt;config.pl&gt; file, it still wouldn't work as we saw in the third
  +scenario. So let see better solutions.
  +</PRE>
  +<P><DT><STRONG>Solution 2</STRONG><DD>
  +<P>
  +Another option is to use a full path to the script, so it'll be compiled
  +into the name of the key in the <CODE>%INC</CODE>;
   
  -<P><LI>
  +<P>
  +<PRE>  require &quot;/full/path/to/the/config.pl&quot;;
  +</PRE>
   <P>
  -HTTP headers / dates, freshness. Your server will be giving out ``old''
  -pages, which might confuse downstream/client caches. Also chances are that
  -you will be giving out stale pages.
  +This solution solves the first two scenarios. I was surprised but it worked
  +for the third scenario as well!
   
  -<P><LI>
   <P>
  -Stability. Compared to plain web servers Squid is not the most stable.
  +But with this solution you loose portability! (If you move the tool around
  +in the file system you will have to change the base dir)
   
  -</UL>
  +<P><DT><STRONG>Solution 3</STRONG><DD>
   <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.
  +Declare a package in the required files! (Of course it should be unique to
  +the rest of the package names you use!) The <CODE>%INC</CODE> will use the package name for the key! It's a good idea to build at least 2
  +level package names for your private modules. (e.g. <CODE>MyProject::Carp</CODE>
  +and not <CODE>Carp</CODE> for it will collide with existent standard package - even if as of the time
  +of your coding it doesn't exist yet - it might enter the next perl
  +distribution as a standard module and your code will become broken. Foresee
  +problems like this and save you a future trouble.)
   
   <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>
  +When you <CODE>use()d</CODE> or <CODE>require()d</CODE> files without package declarations, it was very convenient since all the
  +variables and subroutines were part of the <CODE>main::</CODE> package, so any of them could be used as if they were part of the main
  +script. With package declarations things get more complicated. To be
  +correct -- not complicated, but awkward, since you will have to use
  +<CODE>Package::function()</CODE> method to call a subroutine from a package
  +<CODE>Package</CODE> and to access a global variable inside the same package you will have to
  +write <CODE>$Package::some_variable</CODE>, you get a kind of typing overhead. You will be unable to access lexically
  +defined variables inside <CODE>Package</CODE> (declared with <CODE>my()</CODE>).
   
  +<P>
  +You can make things simpler by exporting the symbols from the
  +<CODE>use()'d</CODE> package, like:
   
  +<P>
  +<PRE>  use Package qw(:mysubs sub_b $var1 :myvars);
  +</PRE>
  +<P>
  +You can export both -- subroutines and global variables. This is a bad
  +approach since it'll consume more memory for the current process. (See
  +<CODE>perldoc Exporter</CODE> for information about exporting variables)
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="apache_s_mod_proxy">apache's mod_proxy</A></H1></CENTER>
  +This solution completely covers the third scenario. By using different
  +module names in package declarations, as explained above you solve the
  +first two as well.
  +
  +</DL>
   <P>
  -I do not think the difference in speed between apache's <CODE>ProxyPass</CODE>
  -and squid 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 'location' window.
  +Read also perlmodlib and perlmod manpages.
   
   <P>
  -The Advantages:
  +From the above discussion it should be clear that you cannot run a
  +development and a production versions of the tools on the same server! You
  +have to run a separate server for each (it still can be the same machine,
  +but the server will use a different port).
   
  -<UL>
  -<P><LI>
   <P>
  -No additional server is needed. We keep the 1 plain plus 1 mod_perl enabled
  -apache servers. All you need is to enable the <CODE>mod_proxy</CODE> in
  -<CODE>httpd_docs</CODE> and add a few lines to <CODE>httpd.conf</CODE> file.
  -
  -<P><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H2></CENTER>
   <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:
  +<CODE>Apache::Registry</CODE> scripts cannot contain __END__ or __DATA__ tokens.
   
   <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><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Output_from_system_calls">Output from system calls</A></H2></CENTER>
   <P>
  -It does mod_perl output buffering like squid does. See the <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</A> notes for more details.
  +Output of <CODE>system()</CODE>, <CODE>exec()</CODE>, and <CODE>open(PIPE,&quot;|program&quot;)</CODE> calls will not be sent to the browser unless your Perl was configured with
  +<CODE>sfio</CODE>.
   
  -<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
  -ProxyPass.
  -
  -<P><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Using_format_">Using format()</A></H2></CENTER>
   <P>
  -<CODE>ProxyPass</CODE> happens before the authentication phase, so you do not have to worry about
  -authenticating twice.
  +Currently possible only if you have perl compiled with <CODE>sfio</CODE>.
   
  -<P><LI>
   <P>
  -Apache is able to accel https requests completely, while also doing http
  -accel. (with squid you have to use an external redirection program for
  -that).
  -
  -<P><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Using_exit_">Using exit()</A></H2></CENTER>
   <P>
  -The latest (from apache 1.3.6) Apache proxy accel mode reported to be very
  -stable.
  +Perl's <STRONG>exit()</STRONG> built-in function cannot be used in mod_perl scripts. Calling it causes the
  +server child to exit (which makes the whole idea of using mod_perl
  +irrelevant.) The <STRONG>Apache::exit()</STRONG> function should be used instead. 
   
  -</UL>
   <P>
  -The Disadvantages:
  +You might start your scripts by overriding the exit sub (if you use
  +<STRONG>Apache::exit()</STRONG> directly, you will have a problem testing the script from the shell, unless
  +you stuff <CODE>use Apache ();</CODE> into your code.) I use the following code:
   
  -<UL>
  -<P><LI>
  -</UL>
   <P>
  -For implementation see <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</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>
  -	     [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.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 06/19/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 Implementaion</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 Implementaion</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="#Before_you_dive_into_the_gory_de">Before you dive into the gory details</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_Server_">Building the httpd_perl Server (mod_perl):</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="#Using_mod_proxy">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>
  -</UL>
  -<!-- INDEX END -->
  +<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'} ) ? 1 : 0;
  +  }
  +  use subs (exit);
  +  
  +  # Select the correct exit way
  +  ########
  +  sub exit{
  +      # Apache::exit(-2) will cause the server to exit gracefully,
  +      # once logging happens and protocol, etc  (-2 == Apache::Constants::DONE)
  +    $USE_MOD_PERL ? Apache::exit(0) : CORE::exit(0);
  +  }
  +</PRE>
  +<P>
  +Now each time the select code is called, the correct <CODE>exit()</CODE> will be chosen, whether you run the script as a CGI or from the shell.
   
  -<HR>
  +<P>
  +<STRONG>Note</STRONG> that if you run the script under <CODE>Apache::Registry</CODE>, <STRONG>The
  +Apache function <CODE>exit()</CODE> overrides the Perl core built-in
  +function</STRONG>. While you see the <CODE>exit()</CODE> listed in <CODE>@EXPORT_OK</CODE> of Apache package, <CODE>Apache::Registry</CODE> makes something you don't see and imports this function for you. This means
  +that if your script is running under <CODE>Apache::Registry</CODE> handler (<CODE>Apache::PerlRun</CODE> as well), you don't have to worry about <CODE>exit().</CODE>
   
  -	     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>
  +<STRONG>Note</STRONG> that if you still use <CODE>CORE::exit()</CODE> in your scripts running under modperl, the child will exit, but neither
  +proper exit nor logging will happen on the way. <CODE>CORE::exit()</CODE> cuts off the server's legs... If you need to properly shutdown the child ,
  +use
  +<CODE>$r-&amp;gt;child_terminate</CODE> (which sets the internal
  +<CODE>MaxRequestsPerChild</CODE> so the child will exit).
   
  -	     <HR>
  +<P>
  +You can accomplish this in two ways - in the <CODE>Apache::Registry</CODE> script:
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Before_you_dive_into_the_gory_de">Before you dive into the gory details</A></H1></CENTER>
  +<PRE>  Apache-&gt;request-&gt;child_terminate;
  +</PRE>
   <P>
  -There are many implementation schemes, each one has its benefits and
  -drawbacks. Please take your time to read the <A HREF="././strategy.html#">Picking the Right Strategy</A> chapter before you proceed. This section
  -<EM>merely</EM> details the implementation, installation and configuration. It hardly
  -mentions the pros and cons of each scheme detailed here.
  +in httpd.conf:
   
   <P>
  -This section describes a real world scenarios ready for almost blindly copy
  -and paste, you may think of it as a kick start. You will probably will want
  -to change the directories and some parameters like your hostname, but
  -basically you can use it as it is.
  -
  +<PRE>  PerlFixupHandler &quot;sub { shift-&gt;child_terminate }&quot;
  +</PRE>
   <P>
  -<STRONG>Important:</STRONG> Since both apache and mod_perl tend to release new versions so often (which
  -is good :), I will be not able to update the version numbers I present
  -here. So make sure to work with the latest version, even if you see me
  -using some older one. I prefer to use the real version number instead of <CODE>x.xx.xx</CODE>.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Running_from_shell">Running from shell</A></H2></CENTER>
  +<P>
  +Your scripts <STRONG>will not</STRONG> run from the command line (yet) unless you use CGI::Switch or CGI.pm and
  +5.004+ and do not make any direct calls to Apache-&gt;methods.
   
   <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="I_O_is_different">I/O is different</A></H2></CENTER>
  +<P>
  +If you are using Perl 5.004 or better, most CGI scripts can run under
  +mod_perl untouched. If you're using 5.003, Perl's built-in
  +<CODE>read()</CODE> and <CODE>print()</CODE> functions do not work as they
  +do under CGI. If you're using CGI.pm, use $query-&gt;print instead of plain 'ol <CODE>print().</CODE>
  +
   <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><H2><A NAME="HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A></H2></CENTER>
   <P>
  -The Installation is very very simple (example from Linux OS):
  +By default, mod_perl does not send any headers by itself, however, you may
  +wish to change this (in httpd.conf):
   
   <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 \
  -    USE_APACI=1 DO_HTTPD=1 PERL_MARK_WHERE=1 ALL_HOOKS=1 
  -  % make &amp;&amp; make test &amp;&amp; make install
  -  % cd ../apache_x.x.x/src
  -  % make install
  +<PRE>  PerlSendHeader On
   </PRE>
   <P>
  -That's all!
  +Now the response line and common headers will be sent as they are by
  +mod_cgi. And, just as with mod_cgi, <CODE>PerlSendHeader</CODE> will not send a terminating newline, your script must send that itself,
  +e.g.:
   
   <P>
  -Notes: Replace x.x.x with the real version numbers of mod_perl and apache.
  -gnu tar uncompresses as well (with z flag).
  +<PRE>  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +</PRE>
  +<P>
  +If you are using CGI.pm or CGI::Switch and <STRONG>print $q-&gt;header</STRONG> you do _not_ need <CODE>PerlSendHeader</CODE> On.
   
   <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><H2><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</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 libwww) 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.
  +To run a Non Parsed Header CGI script under mod_perl, simply add to your
  +code:
   
   <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>  local $| = 1;
   </PRE>
   <P>
  -Extract both sources. Generally I open all the sources in
  -<CODE>/usr/src/</CODE>, your mileage may vary. So move the sources and cd to the directory you
  -want to put the sources in. Gnu <CODE>tar</CODE> utility knows to uncompress too with z flag, if you have a non-gnu <CODE>tar</CODE> utility, it will be incapable to decompress, so you would do it in 2 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>. And untarring them with <CODE>tar xvf
  -apache_x.xx.tar</CODE> and <CODE>tar xvf mod_perl-x.xx.tar</CODE>.
  +And if you normally set <CODE>PerlSendHeader On</CODE>, add this to your
  +<CODE>httpd.conf</CODE>:
   
   <P>
  -<PRE>  % cd /usr/src
  -  % tar zvxf apache_x.xx.tar.gz
  -  % tar zvxf mod_perl-x.xx.tar.gz
  +<PRE>  &lt;Files */nph-*&gt;
  +    PerlSendHeader Off
  +  &lt;/Files&gt;
   </PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="BEGIN_blocks">BEGIN blocks</A></H2></CENTER>
   <P>
  -Change to the mod_perl source directory.
  +Perl executes <CODE>BEGIN</CODE> blocks during the compile time of code as soon as possible. The same is
  +true under mod_perl. However, since mod_perl normally only compiles scripts
  +and modules once -- either in the parent server or once per-child -- <CODE>BEGIN</CODE> blocks in that code will only be run once. As <CODE>perlmod manpage</CODE> explains, once a <CODE>BEGIN</CODE> has run, it is immediately undefined. In the mod_perl environment, this
  +means <CODE>BEGIN</CODE> blocks will not be run during each incoming request unless that request
  +happens to be one that is compiling the code.
   
   <P>
  -<PRE>  % cd mod_perl-x.xx
  -</PRE>
  +<CODE>BEGIN</CODE> blocks in modules and files pulled in via <CODE>require()</CODE> and/or
  +<CODE>use()</CODE> will be executed:
  +
  +<UL>
  +<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 &lt;src&gt; directory is. If you have followed my
  -advice and extracted the sources under the same directory (e.g.
  -&lt;/usr/src&gt;), the following is correct.
  +Only once, if pulled in by the parent process.
   
  +<P><LI>
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    USE_APACI=1 DO_HTTPD=1 PERL_MARK_WHERE=1 ALL_HOOKS=1 
  -</PRE>
  +Once per-child process if not pulled in by the parent process.
  +
  +<P><LI>
   <P>
  -There are many additional parameters. You can find some of them in the
  -configuration dedicated chapter and other sections where any of them
  -becomes relevant. 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.
  +An additional time, once per-child process if the module is pulled in off a
  +disk again via <CODE>Apache::StatINC</CODE>.
   
  +<P><LI>
   <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>make test</STRONG> it (by running various tests) and install the mod_perl modules.
  +An additional time, in the parent process on each restart if
  +<CODE>PerlFreshRestart</CODE> is <CODE>On</CODE>.
   
  +<P><LI>
   <P>
  -<PRE>  % make &amp;&amp; make test &amp;&amp; make install
  -</PRE>
  -<P>
  -Note that if <CODE>make</CODE> fails, non of the <CODE>make test</CODE> and <CODE>make
  -install</CODE> will be not executed. If <CODE>make test</CODE> fails, <CODE>make install</CODE>
  -will be not executed.
  +Unpredictable if you fiddle with <CODE>%INC</CODE> yourself.
   
  +</UL>
   <P>
  -Now change to apache source directory and run <CODE>make install</CODE> to install apache's headers, default configuration files, build apache
  -directory tree and put the <CODE>httpd</CODE> there.
  +<CODE>BEGIN</CODE> blocks in <CODE>Apache::Registry</CODE> scripts will be executed:
   
  +<UL>
  +<P><LI>
   <P>
  -<PRE>  % cd ../apache_x.x.x/src
  -  % make install
  -</PRE>
  +Only once, if pulled in by the parent process via
  +<CODE>Apache::RegistryLoader</CODE> - once per-child process if not pulled in by the parent process.
  +
  +<P><LI>
   <P>
  -When you execute the above command, apache installation process will tell
  -you how can you start the webserver (the path of the &lt;apachectl&gt;,
  -more about it later) and where the configuration files are. Remember (or
  -even better write down) both for you will need this information very soon.
  -On my machine they 2 important paths are:
  +An additional time, once per-child process if the script file has changed
  +on disk.
   
  +<P><LI>
   <P>
  -<PRE>  /usr/local/apache/bin/apachectl
  -  /usr/local/apache/conf/httpd.conf
  -</PRE>
  +An additional time, in the parent process on each restart if pulled in by
  +the parent process via <CODE>Apache::RegistryLoader</CODE> and
  +<CODE>PerlFreshRestart</CODE> is <CODE>On</CODE>.
  +
  +</UL>
   <P>
  -Now the build and the installation processes are completed. Just configure <CODE>httpd.conf</CODE> and start the webserver.
  +Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
   
   <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><H2><A NAME="END_blocks">END blocks</A></H2></CENTER>
   <P>
  -A basic configuration is a simple one. First configure the apache as you
  -always do (like setting a correct <CODE>Port</CODE>, <CODE>User</CODE>, <CODE>Group</CODE>, log-file 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:
  +As perlmod explains, an <CODE>END</CODE> subroutine is executed as late as possible, that is, when the interpreter
  +exits. In the mod_perl environment, the interpreter does not exit until the
  +server is shutdown. However, mod_perl does make a special case for
  +<CODE>Apache::Registry</CODE> scripts.
   
   <P>
  -<PRE>  /usr/local/apache/bin/apachectl start
  -  /usr/local/apache/bin/apachectl stop
  -</PRE>
  +Normally, <CODE>END</CODE> blocks are executed by Perl during its <STRONG>perl_run()</STRONG>
  +function, which is called once each time the Perl program is executed, e.g.
  +once per (mod_cgi) CGI scripts. However, mod_perl only calls
  +<STRONG>perl_run()</STRONG> once, during server startup. Any <CODE>END</CODE> blocks encountered during main server startup, i.e. those pulled in by the
  +<CODE>PerlRequire</CODE> or by any <CODE>PerlModule</CODE>, are suspended and run at server shutdown, aka child_exit (requires apache
  +1.3b3+).
  +
   <P>
  -Put 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).
  +Any <CODE>END</CODE> blocks that are encountered during compilation of
  +<CODE>Apache::Registry</CODE> scripts <STRONG>are called after the script has
  +completed</STRONG> (not during the cleanup phase though) including subsequent invocations when
  +the script is cached in memory. All other <CODE>END</CODE>
  +blocks encountered during other <CODE>Perl*Handler</CODE> call-backs, e.g.
  +<CODE>PerlChildInitHandler</CODE>, will be suspended while the process is running and called during <CODE>child_exit()</CODE> when the process is shutting down. Module authors might wish to use $r-&gt;register_cleanup as an alternative to <CODE>END</CODE> blocks if this behavior is not desirable.
   
   <P>
  -Add the following configuration directives:
  +The last paragraph is very important for the <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>.
   
   <P>
  -<PRE>  Alias /perl/ /home/httpd/perl/
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Switches_w_T">Switches -w, -T</A></H2></CENTER>
   <P>
  -Assuming that you put all your scripts that should be executed under
  -mod_perl into <CODE>/home/httpd/perl/</CODE> directory.
  +Normally when you run perl from the command line or have the shell invoke
  +it with `#!', you may choose to pass perl switch arguments such as <STRONG>-w</STRONG> or <STRONG>-T</STRONG>. Most command line arguments have a equivalent special variable. For
  +example, the <STRONG>$^W</STRONG> variable corresponds to the
  +<STRONG>-w</STRONG> switch. Consult <CODE>perlvar</CODE> manpage for more details. With mod_perl it is also possible to turn on
  +warnings globally via the PerlWarn directive:
   
   <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>  PerlWarn On
   </PRE>
   <P>
  -Now put a test script into <CODE>/home/httpd/perl/</CODE> directory:
  +You can turn it off with <CODE>local $^W = 0;</CODE> in your scripts on the local basis (or inside the block). If you write <CODE>$^W = 0;</CODE> you disable the warning mode everywhere, the same with <CODE>$^W = 1;</CODE>.
   
   <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>
  -<P>
  -Make it executable and readable by server, if your server is running as
  -user <CODE>nobody</CODE> (hint see <CODE>User</CODE> directive in <CODE>httpd.conf</CODE> file), do the following:
  +The switch which enables taint checks does not have a special variable, so
  +mod_perl provides the PerlTaintCheck directive to turn on taint checks. In
  +httpd.conf, enable with:
   
   <P>
  -<PRE>  chown nobody /home/httpd/perl/test.pl
  -  chmod u+rx   /home/httpd/perl/test.pl
  +<PRE>  PerlTaintCheck On
   </PRE>
   <P>
  -Test that the script is running from the command line, by executing it:
  +Now, any and all code compiled inside httpd will be taint checked.
   
   <P>
  -<PRE>  /home/httpd/perl/test.pl
  -</PRE>
  +The environment variable PERL5OPT can be used to set additional perl
  +startup flags such as -d and -D. See
  +<A HREF="././modules.html#Apache_PerlRun_Run_unaltered_">Apache::PerlRun</A> .
  +
   <P>
  -You should see:
  +If you have the shebang line (<CODE>#!/bin/perl -Tw</CODE>) in your script, <STRONG>-w</STRONG>
  +will be honored (which means that you have turned the warn mode on for the
  +scope of this script, <STRONG>-T</STRONG> will produce a warning if
  +<CODE>PerlTaintCheck</CODE> is not <CODE>On</CODE>.
   
   <P>
  -<PRE>  Content-type: text/html
  -  
  -  It worked!!!
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="strict_pragma">strict pragma</A></H2></CENTER>
   <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:
  +It's _absolutely_ mandatory (at least for development) to start all your
  +scripts with:
   
   <P>
  -<PRE>  <A HREF="http://localhost/perl/test.pl">http://localhost/perl/test.pl</A>
  +<PRE>  use strict;
   </PRE>
   <P>
  -(Assuming that you have a loop-back device configured, if not use the real
  -server name for this test (e.g. <CODE>http://www.nowhere.com/perl/test.pl</CODE>)
  -
  -<P>
  -You should see:
  +If needed, you can always turn off the 'strict' pragma or a part of it
  +inside the block, e.g:
   
   <P>
  -<PRE>  It worked!!!
  +<PRE>  {
  +    no strict 'refs';
  +    ... some code
  +  }
   </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.
  +It's more important to have <CODE>strict</CODE> pragma enabled under mod_perl than anywhere else. While it's not required,
  +it is strongly recommended, it will save you more time in the long run.
  +And, of course, clean scripts will still run under mod_cgi (plain CGI)!
   
   <P>
  -Now migrate your 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>). Not all of your scripts will work unchanges, but many will.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Turning_warnings_ON">Turning warnings ON</A></H2></CENTER>
   <P>
  -The above setup is very basic, it will help you to have a mod_perl enabled
  -server running.
  +Have a <CODE>local $^W=1</CODE> in the script or <CODE>PerlWarn ON</CODE> at the server configuration file. Turning the warning on will save you a
  +lot of troubles with debugging your code. Note that all perl switches, but
  +<CODE>-w</CODE> in the first magic (shebang) line of the script <CODE>#!/perl
  +-switches</CODE> are being ignored by mod_perl. If you write <CODE>-T</CODE> you will be warned to set <CODE>PerlTaintCheck ON</CODE> in the config file.
   
   <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.
  +If you need -- you can always turn off the warnings with <CODE>local
  +$^W=0</CODE> in your code if you have some section you don't want the perl compiler to
  +warn in. The correct way to do this is:
   
   <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>
  +<PRE>  {
  +   local $^W=0;
  +    # some code
  +  }
  +</PRE>
   <P>
  -Since we run two apache servers we will need two different configuration
  -files, log files and etc. 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. We
  -will refer to these two servers as <STRONG>httpd_docs</STRONG> (vanilla Apache) and <STRONG>httpd_perl</STRONG>
  -(Apache/mod_perl).
  +It preserves the previous value of <CODE>$^W</CODE> when you quit the block (so if it was set before, it will return to be set
  +at the leaving of the block.
   
   <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...)
  +In production code, it can be a good idea to turn warnings off. Otherwise
  +if your code isn't very clean and spits a few lines of warnings here and
  +there, you will end up with a huge <CODE>error_log</CODE> file in a short time on the heavily loaded server. Also, enabling runtime
  +warning checking has a small performance impact -- in any script, not just
  +under mod_perl -- so your approach should be to enable warnings during
  +development, and then disable them when your code is production-ready.
  +Controlling the warnings mode through the
  +<CODE>httpd.conf</CODE> is much better, since you can control the behavior of all of the scripts
  +from a central place. I have <CODE>PerlWarn On</CODE> on my development server and <CODE>PerlWarn Off</CODE> on the production machine.
   
   <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 in this section.
  +<CODE>diagnostics</CODE> pragma can shed more light on the errors and warnings you see, but again,
  +it's better not to use it in production, since otherwise you incur a huge
  +overhead of the diagnostics pragma examining your every bit of code
  +mod_perl executes. (You can run your script with <CODE>-dDprof</CODE> to check the overhead. See <CODE>Devel::Dprof</CODE> for more info).
   
   <P>
  -Make two subdirectories:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="diagnostics_pragma">diagnostics pragma</A></H2></CENTER>
  +<P>
  +This is a Perl compiler pragma which forces verbose warning diagnostics.
  +Put at the start of your scripts:
   
   <P>
  -<PRE>  % mkdir /usr/src/httpd_docs
  -  % mkdir /usr/src/httpd_perl
  +<PRE>  use diagnostics;
   </PRE>
   <P>
  -Now we will put the Apache source into <CODE>/usr/src/httpd_docs</CODE>:
  +This pragma turns on the <CODE>-w</CODE> mode, but gives you much better diagnostics of the errors and warnings
  +encountered. Generally it explains the reason for warnings/errors you get,
  +shows you an example of code where the same kind of warning is being
  +triggered, and tells you the remedy.
   
  -<P>
  -<PRE>  % cd /usr/src/httpd_docs
  -  % gzip -dc /path/to/tarfile/apache.tar.gz | tar xvf -
  -</PRE>
   <P>
  -If you have a gnu tar:
  +Again, it's a bad idea to keep it in your production code, as it will spit
  +10 and more lines of diagnostics messages into your error_log file for
  +every warning perl will report for the first time (per invocation). Also,
  +it will add a significant overhead to the code's runtime. (I discovered
  +this by using <CODE>Devel::DProf</CODE>!)
   
   <P>
  -<PRE>  % tar xvzf /path/to/apache.tar.gz
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H2></CENTER>
   <P>
  -Replace everywhere <CODE>/path/to/tarfile</CODE> with a path to a downloaded file.
  +To pass an environment variable from a configuration file, add to it:
   
   <P>
  -<PRE>  % cd /usr/src/httpd_docs
  -  % ls -l
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_1.3.6/
  +<PRE>  PerlSetEnv key val
  +  PerlPassEnv key
   </PRE>
   <P>
  -Now we will prepare the <CODE>httpd_perl</CODE> server sources:
  +e.g.:
   
   <P>
  -<PRE>  % cd /usr/src/httpd_perl
  -  % gzip -dc /path/to/apache.tar.gz | tar xvf -
  -  % gzip -dc /path/to/modperl.tar.gz | tar xvf -
  -  % ls -l
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_1.3.6/
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 modperl-1.19/
  +<PRE>  PerlSetEnv PERLDB_OPTS &quot;NonStop=1 LineInfo=/tmp/db.out AutoTrace=1&quot;
   </PRE>
   <P>
  -Time to decide on the desired directory structure layout (where the apache
  -files go):
  +will set <CODE>$ENV{PERLDB_OPTS}</CODE>, and it'll be accessible in every child.
   
   <P>
  -<PRE>  ROOT = /usr/local
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Global_Variables">Global Variables</A></H2></CENTER>
   <P>
  -The two servers can share the following directories (so we will not
  -duplicate data):
  +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. 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 space. When possible, try to use fully qualified
  +names instead of use vars. Example:
   
   <P>
  -<PRE>  /usr/local/bin/
  -  /usr/local/lib
  -  /usr/local/include/
  -  /usr/local/man/
  -  /usr/local/share/
  +<PRE>  package MyPackage;
  +  use strict;
  +  @MyPackage::ISA = qw(...);
  +  $MyPackage::VERSION = &quot;1.00&quot;;
   </PRE>
  -<P>
  -<STRONG>Important:</STRONG> we assume that both servers are built from the same Apache source version.
  -
   <P>
  -Servers store their specific files either in <CODE>httpd_docs</CODE> or
  -<CODE>httpd_perl</CODE> sub-directories:
  +vs.
   
   <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>  package MyPackage;
  +  use strict;
  +  use vars qw(@ISA $VERSION);
  +  @ISA = qw(...);
  +  $VERSION = &quot;1.00&quot;;
   </PRE>
   <P>
  -After you will complete the compilation and installation of the both
  -servers, you will have 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 then the one
  -<CODE>httpd_docs</CODE> server listens to (e.g. 8080). The port numbers issue will be discussed
  -later.
  +Also see <A HREF="././perl.html#Using_global_variables_and_shari">Using global variables and sharing them</A>
   
  -<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
  -we have just decided to use.
  +
   
   <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><H2><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H2></CENTER>
   <P>
  -Important note: In the installation scenario I have used apache and
  -mod_perl release numbers. As you understand I would not change these
  -numbers every time a new version of either apache or mod_perl will be
  -released. So please if you see <CODE>apache_1.3.6</CODE> it does not mean
  -<CODE>1.3.6</CODE> is the latest apache version.
  +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.
   
   <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>
  +<CENTER><H2><A NAME="Memory_leakage">Memory leakage</A></H2></CENTER>
   <P>
  -<PRE>  % cd /usr/src/httpd_docs/apache_1.3.6
  -  % 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>
  +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>
  -If you need some other modules, like mod_rewrite and mod_include (SSI), add
  -them here as well:
  +Perl doesn't return the memory it acquired from the kernel. It does reuse
  +it though!
   
   <P>
  -<PRE>    --enable-module=include --enable-module=rewrite
  +<STRONG>First example</STRONG> demonstrates reading a file:
  +
  +<P>
  +<PRE>  open IN, $file or die $!;
  +  $/ = undef; # will read the whole file in
  +  $content = &lt;IN&gt;;
  +  close IN;
   </PRE>
   <P>
  -Note: gcc - compiles httpd by 100K+ smaller then cc on AIX, remove the
  -<CODE>env CC=gcc</CODE> if you want to use the default compiler.
  +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>
  -Note: add <CODE>--layout</CODE> to see the resulting directories' layout without actually making the
  -configuration.
  +<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. 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>
  +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><DT><STRONG>Sources Compilation:</STRONG><DD>
   <P>
  -<PRE>  % make
  -  % make install
  +<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>
  -Rename <CODE>httpd</CODE> to <CODE>http_docs</CODE>
  -
  +For more info see <CODE>perldoc perlref</CODE>.
   
  +<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!
   
   <P>
  -<PRE>  % mv /usr/local/sbin/httpd_docs/httpd \
  -  /usr/local/sbin/httpd_docs/httpd_docs
  +<PRE>  process($content);
  +  sub process{
  +    $_[0] =~ s/foo/bar/gs;
  +      # nothing returned - the variable $content outside has been
  +      # already modified
  +  }
   </PRE>
   <P>
  -Now update an <STRONG>apachectl</STRONG> utility to point to the renamed httpd via your favorite text editor or by
  -using perl:
  +From <CODE>perldoc perlsub</CODE>:
   
   <P>
  -<PRE>  % perl -p -i -e 's|httpd_docs/httpd|httpd_docs/httpd_docs|' \
  -  /usr/local/sbin/httpd_docs/apachectl
  +<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>
  -</DL>
  -<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_Server_">Building the httpd_perl Server (mod_perl):</A></H3></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>.
  +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>
  -Make sure the sources are clean:
  -
  -<P>
  -<PRE>  % cd /usr/src/httpd_perl/apache_1.3.6
  -  % make clean
  -  % cd /usr/src/httpd_perl/mod_perl-1.19
  -  % make clean
  -</PRE>
  -<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
  -1.3.4 header files.
  +<STRONG>Third example</STRONG> demonstrates 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>
  -Here I did not find a way to compile with gcc (my perl was compiled with cc
  -so we have to compile with the same compiler!!!
  +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>  % cd /usr/src/httpd_perl/mod_perl-1.19
  -</PRE>
   <P>
  -<PRE>  % /usr/local/bin/perl Makefile.PL \
  -  APACHE_PREFIX=/usr/local/ \
  -  APACHE_SRC=../apache_1.3.6/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>  $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>
  -Notice that <STRONG>ALL</STRONG>  <CODE>APACI_ARGS</CODE> (below) must be passed as one long line if you work with <CODE>t?csh</CODE>!!! It works correctly the way it shown above with <CODE>(ba)?sh</CODE>. If you work with <CODE>t?csh</CODE> it does not work for
  -<CODE>csh</CODE> passes to <CODE>./configure</CODE>  <CODE>APACI_ARGS</CODE> params with new lines without '' - tcsh strips the original '' - and the
  -build goes broken.
  +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>
  -As with <CODE>httpd_docs</CODE> you might need other modules like
  -<CODE>mod_rewrite</CODE>, so add them here:
  +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>         --enable-module=rewrite
  +<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: <CODE>PERL_STACKED_HANDLERS=1</CODE> is needed for <CODE>Apache::DBI</CODE>
  -
  -
  +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.
   
   <P>
  -Now, build, test and install the <CODE>httpd_perl</CODE>.
  +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>  % make &amp;&amp; make test &amp;&amp; make install
  +<PRE>  rows();
   </PRE>
  -<P>
  -Note: Apache puts a stripped version of <CODE>httpd</CODE> at
  -<CODE>/usr/local/sbin/httpd_perl/httpd</CODE>. The original version including debugging symbols (if you need to run a
  -debugger on this executable) is located at <CODE>/usr/src/httpd_perl/apache_1.3.6/src/httpd</CODE>.
  -
   <P>
  -Note: You may have noted that we did not go to the apache's source dir and
  -run <CODE>make install</CODE>. When <CODE>USE_APACI</CODE> is enabled,
  -<CODE>APACHE_PREFIX</CODE> will specify the --prefix option for Apache's configure script, 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.
  -
  +<PRE>  $rv = $sth-&gt;rows;
  +</PRE>
   <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>.
  -
  +<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>
  -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.
  -
  +<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>
  -Now rename the <CODE>httpd</CODE> to <CODE>httpd_perl</CODE>:
  +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>  % mv /usr/local/sbin/httpd_perl/httpd \
  -  /usr/local/sbin/httpd_perl/httpd_perl
  +<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>
  -Update the apachectl utility to point to renamed httpd name:
  +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>  % perl -p -i -e 's|httpd_perl/httpd|httpd_perl/httpd_perl|' \
  -  /usr/local/sbin/httpd_perl/apachectl
  +<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>
  -<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.
  +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><H3><A NAME="Basic_httpd_docs_Server_s_Config">Basic httpd_docs Server's Configuration</A></H3></CENTER>
  +<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></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 pathes according to the directory layout
  -we decided to use.
  +When you develop plain CGI scripts, you can just change the code, and rerun
  +the CGI from your browser. Since the script isn't cached in memory, the
  +next time you call it the server starts up a new perl process, which
  +recompiles it from scratch. The effects of any modifications you've applied
  +are immediately present.
   
   <P>
  -Start the server with:
  +The situation is different with <CODE>Apache::Registry</CODE>, since the whole idea is to get maximum performance from the server. By
  +default, the server won't spend the time to check whether any included
  +library modules have been changed. It assumes that they weren't, thus
  +saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are <CODE>use()</CODE>-ing and/or <CODE>require()</CODE>-ing in your script.) The only check that is being done is whether your
  +main script has been changed. So if you have only one script that doesn't
  +<CODE>use()</CODE> (or <CODE>require()</CODE>) other perl modules (or packages), there is nothing new about it. If
  +however, you are developing a script that includes other modules, the files
  +you <CODE>use()</CODE> or <CODE>require()</CODE> aren't being checked whether they have been modified.
   
   <P>
  -<PRE>  /usr/local/sbin/httpd_docs/apachectl start
  -</PRE>
  +Acknowledging this, how do we get our modperl-enabled server to recognize
  +changes in any library modules? Well, there are a couple of techniques:
  +
   <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 log and other files directives are set
  -to point to the right places, according to the chosen directory layout.
  -
  +<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
   <P>
  -One 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 &lt;8080&gt;. 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, for 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 users, by either using the mod_proxy's
  -<CODE>ProxyPass</CODE> or proxy server like squid.
  +The simplest approach is to restart the server each time you apply some
  +change to your code. See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</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#Using_mod_proxy">Using mod_proxy</A>.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
   <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 of them.
  +After restarting the server about 100 times, you will be tired and will
  +look for another solutions. Help comes from the
  +<CODE>Apache::StatINC</CODE> module.
   
   <P>
  -First, you need to specify the location where all mod_perl scripts will be
  -located.
  +<CODE>Apache::StatINC</CODE> - Reload <CODE>%INC</CODE> files when updated on disk. When Perl pulls a file via require, it stores
  +the filename in the global hash <CODE>%INC</CODE>. The next time Perl tries to require the same file, it sees the file in <CODE>%INC</CODE> and does not reload from disk. This module's handler iterates over <CODE>%INC</CODE> and reloads the file if it has changed on disk.
   
   <P>
  -Add the following configuration directive:
  +To enable this module just add two lines to <CODE>httpd.conf</CODE> file.
   
   <P>
  -<PRE>    # mod_perl scripts will be called from
  -  Alias /perl/ /usr/local/myproject/perl/
  +<PRE>  PerlModule Apache::StatINC
  +  PerlInitHandler Apache::StatINC
   </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>.
  -
   <P>
  -Now we should configure the <CODE>/perl</CODE> location.
  +To be sure it really works, turn on the debug mode on your development box
  +with <CODE>PerlSetVar StatINCDebug On</CODE>. You end up with something like:
   
   <P>
  -<PRE>  PerlModule Apache::Registry
  -</PRE>
  -<P>
  -<PRE>  &lt;Location /perl&gt;
  -    #AllowOverride None
  +<PRE>  PerlModule Apache::StatINC
  +  &lt;Location /perl&gt;
       SetHandler perl-script
  -    PerlHandler Apache::Registry
  +    PerlHandler Apache::Registry::handler
       Options ExecCGI
  -    allow from all
       PerlSendHeader On
  +    PerlInitHandler Apache::StatINC
  +    PerlSetVar StatINCDebug On
     &lt;/Location&gt;
   </PRE>
   <P>
  -This configuration causes all scripts that are called with a <STRONG>/perl</STRONG>
  -path prefix to be executed under the <STRONG>Apache::Registry</STRONG> 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 will possibly will trigger a 'Save-As' window). <STRONG>Apache::Registry</STRONG> 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
  -<STRONG>Apache::Registry</STRONG> module before we use it in the <CODE>PerlHandler</CODE> in the <CODE>Location</CODE> configuration.
  +Beware that only the modules located in <CODE>@INC</CODE> are being reloaded on change, and you can change the <CODE>@INC</CODE> only before the server has been started. Whatever you do in your
  +scripts/modules which are being
  +<CODE>required()</CODE> after the server startup will not have any effect on
  +<CODE>@INC</CODE>. When you do <STRONG>use lib qw(foo/bar);</STRONG>, the <CODE>@INC</CODE> is being changed only for the time the code is being parsed and compiled.
  +When it's over the <CODE>@INC</CODE> is being reset to its original value. To make sure that you have set a
  +correct <CODE>@INC</CODE> fetch <A
  +HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
  +and watch the bottom of the page. (I assume you have configured the &lt;Location /perl-status&gt; section in <CODE>httpd.conf</CODE> as the mod_perl docs show.)
   
   <P>
  -<STRONG>PerlSendHeader On</STRONG> 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.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
   <P>
  -This is only a very basic configuration. <A HREF="././config.html#">Server Configuration</A> section covers the rest of the details.
  +Checking all the Modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
  +certainly would not want
  +<CODE>Apache::StatINC</CODE> module to be enabled in your production site's configuration. But sometimes
  +you want to have some Configuration module to be reloaded without
  +restarting the whole server. To accomplish this, one of the solutions is to
  +use a code that I describe below.
   
   <P>
  -Start the server with:
  +Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
   
   <P>
  -<PRE>  /usr/local/sbin/httpd_perl/apachectl start
  +<PRE>  use lib &quot;/some/private/path&quot;;
  +  use Foo::Bar qw(:tags_group tag1 tag2);
   </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 have got 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 the server.
  -
  -<P>
  -First, lets 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 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>
  -You should understand that squid can be used as a straight forward proxy
  -server, generally used in companies and ISPs to save up the traffic by
  -caching the most popular requests. 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 proxy mode, you can extend its
  -functionality by running both modes concurrently. To accomplish this, you
  -just configure the <CODE>httpd
  -accelerator mode</CODE>'s related directives as you were configuring it from scratch.
  -
  -<P>
  -As stated before, proxy server listens now to the port 80, we have to move
  -the httpd_docs server to port 81 for example (your mileage may vary :). So
  -you have to modify the httpd.conf in the httpd_docs config 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>
  -Let's go thru the changes we should apply to the default configuration
  -file. Since this file (<CODE>/etc/squid/squid.conf</CODE>)is huge (60k+) and we would not use 99% of it, my suggestion is to write a
  -new including only the modified directives.
  -
  -<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.
  +Now to make a modification testing and reload at runtime you have to use
  +something like this:
   
   <P>
  -<PRE>  httpd_accel_host virtual
  +<PRE>  # child's private global variable to keep the timestamps
  +  use vars qw(%MODIFIED);
  +    
  +  my $module = &quot;Foo::Bar&quot;;
  +  
  +  (my $inc_key = $module) =~ s|::|/|g;
  +  $inc_key .= &quot;.pm&quot;;
  +  # the $module's path should be registered in %INC if it was already loaded
  +  my $path = $INC{$inc_key} or warn &quot;Can't find $inc_key in %INC\n&quot;;
  +  
  +  # Note: consider to not continue if $path wasn't set!
  +  
  +  # set modification time if it wasn't set before (first time)
  +  # Note: Use (stat $path)[9] instead of -M test, if you reset
  +  # time with $^M=time
  +  $MODIFIED{$module} ||= -M $path;
  +    
  +  # now check whether it was changed (assuming the above wasn't
  +  # performed in this session
  +  if ($MODIFIED{$module} != -M $path){
  +    # only if deleted from %INC the require will be called below
  +    delete $INC{$inc_key};
  +    
  +    require $path;
  +    
  +    # now reimport the symbols (if you need them back :)
  +    import $module qw(:tags_group tag1 tag2);
  +    
  +    # Update the MODIFICATION times
  +    $MODIFIED{$module} = -M $path;
  +  }
   </PRE>
   <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.
  +You may want to add debug print statements to debug this code in your
  +application.
   
   <P>
  -<PRE>  httpd_accel_port 81
  -</PRE>
  -<P>
  -And as described before, squid listens to port 80.
  +Read the ``use versus require'' article for more info. ( <A
  +HREF="http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require">http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require</A>
  +)
   
   <P>
  -<PRE>  http_port 80
  -</PRE>
  +<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>
  -We do not use icp (icp used for cache sharing between neighbor machines),
  -which is more relevant in the proxy mode.
  +When you wrote a script running under mod_cgi, you could get away with
  +sloppy programming, by opening a file and letting the interpreter to close
  +it for you when the script had finished his run, like:
   
   <P>
  -<PRE>  icp_port 0
  +<PRE>  open IN, &quot;in.txt&quot; or die &quot;Cannot open in.txt for reading : $!\n&quot;;
   </PRE>
   <P>
  -<CODE>hierarchy_stoplist</CODE> defined a list of words which, if found in a URL, cause 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.
  +For mod_perl you <STRONG>must</STRONG>  <CODE>close()</CODE> the files you opened!
   
   <P>
  -<PRE>  hierarchy_stoplist /cgi-bin /perl
  +<PRE>  close IN;
   </PRE>
   <P>
  -Now we tell squid not to cache dynamic pages.
  +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>  acl QUERY urlpath_regex /cgi-bin /perl
  -  no_cache deny QUERY
  +<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>
  -Please note that the last 2 directives are controversial. 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. If you set the headers correctly there is no need to
  -tell squid accelerator to NOT try to cache something. The headers I am
  -talking about are <CODE>Last-Modified</CODE> and <CODE>Expires</CODE>. What are they good for?
  -
   <P>
  -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, which means that mod_perl servers have as twice as less work
  -than before. This is only possible by setting the headers correctly.
  +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>
  -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.
  -
  +<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>
  -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 from your servers without investing money for more memory
  -and better hardware.
  +What the first technique (using <CODE>{ BLOCK }</CODE>) makes sure is that the file will be closed the moment, the block is
  +finished.
   
   <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).
  +But even faster and lighter technique is to use <CODE>Symbol.pm</CODE>:
   
   <P>
  -<PRE>  # debug_options ALL,1 28,9
  +<PRE>  my $fh = Symbol::gensym();
  +  open $fh, &quot;filename&quot; or die $!
   </PRE>
   <P>
  -We need to provide a way for a 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, the path to the redirect daemon and disable rewriting any <CODE>Host:</CODE> header in redirected requests (as suggested by squid's documentation). The
  -redirection daemon script is enlisted below.
  +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>  redirect_program /usr/lib/squid/redirect.pl
  -  redirect_children 10
  -  redirect_rewrites_host_header off
  -</PRE>
  +<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>
  -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.
  +You still can win from using mod_perl. 
   
   <P>
  -<PRE>  request_size 1000 KB
  -</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.
  +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>  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
  +<PRE>  # srm.conf
  +  Alias /cgi-perl/ /home/httpd/cgi/
     
  -  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
  +  # 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>
  -Since squid should be run as non root, you need these if you are starting
  -the squid as root.
  +See <A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
   
  -<P>
  -<PRE>  cache_effective_user squid
  -  cache_effective_group squid
  -</PRE>
  -<P>
  -Memory used for caching parameter. The squid documentation warns that the
  -actual size of the squid can become 3 times higher than this value.
   
  -<P>
  -<PRE>  cache_mem 20 MB
  -</PRE>
  +
   <P>
  -Keep pools of allocated (but unused) memory available for future use. Read
  -more about it in the squid docs.
  +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
  +though, as the parent server will need to fork a new child each time one is
  +killed, but you can fiddle with <CODE>MaxStartServers</CODE>,
  +<CODE>MinSpareServers</CODE>, to make the parent spawn more servers ahead so the killed one will be
  +immediately replaced with the fresh one. Again, probably that's not what
  +you want.
   
   <P>
  -<PRE>  memory_pools on
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A></H1></CENTER>
   <P>
  -Cache manager cgi script (cachemgr.cgi - comes bundled with squid) - you
  -will want to tight the permissions for a production server.
  +<CODE>Apache::PerlRun</CODE> gives you a benefit of preloaded perl and its modules. This module's
  +handler emulates the CGI environment, allowing programmers to write scripts
  +that run under CGI or mod_perl without any change. Unlike <CODE>Apache::Registry</CODE>, the <CODE>Apache::PerlRun</CODE>
  +handler does not cache the script inside of a subroutine. Scripts will be
  +``compiled'' on each request. After the script has run, its name space is
  +flushed of all variables and subroutines. Still, you don't have the
  +overhead of loading the perl and compilation time of the standard modules
  +(If your script is very light, but uses lots of standard modules - you will
  +see no difference between
  +<CODE>Apache::PerlRun</CODE> and <CODE>Apache::Registry</CODE> !).
   
  -<P>
  -<PRE>  cachemgr_passwd disable shutdown
  -  #cachemgr_passwd none all
  -</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):
  +Be aware though, that if you use packages that use internal variables that
  +have circular references, they will be not flushed!!!
  +<CODE>Apache::PerlRun</CODE> only flushes your script's name space, which does not include any other
  +required packages' name spaces. If there's a reference to a <CODE>my()</CODE> scoped variable that's keeping it from being destroyed after leaving the
  +eval scope (of <CODE>Apache::PerlRun</CODE>), that cleanup might not be taken care of until the server is shutdown and
  +<CODE>perl_destruct()</CODE> is run, which always happens after running command line scripts. Consider
  +this example:
   
   <P>
  -<PRE>  #!/usr/local/bin/perl
  -  
  -  $|=1;
  +<PRE>  package Foo;
  +  sub new { bless {} }
  +  sub DESTROY {
  +    warn &quot;Foo-&gt;DESTROY\n&quot;;
  +  }
     
  -  while (&lt;&gt;) {
  -  # redirect to mod_perl server
  -    print($_), next if 
  -   s|<A HREF="http://127">http://127</A>\.0\.0\.1:81/perl|<A HREF="http://www.nowhere.com:8080/perl">http://www.nowhere.com:8080/perl</A>|o;
  +  eval &lt;&lt;'EOF';
  +  package my_script;
  +  my $self = Foo-&gt;new;
  +  #$self-&gt;{circle} = $self;
  +  EOF
     
  -  # default - static server
  -    print;
  -  }
  +  print $@ if $@;
  +  print &quot;Done with script\n&quot;;
   </PRE>
  -<P>
  -Note: you see the 127.0.0.1 (which is a 'localhost'), because in my
  -scenario the proxy and the apache servers are running on the same machine.
  -So the requests that went through squid being converted to point to the
  -localhost in our configuration.
  -
  -<P>
  -A few notes regarding this redirector script:
  -
  -<P>
  -You must disable buffering. <CODE>$|=1;</CODE> does the job. If you do not disable buffering, the stdout will be flushed
  -only when the buffer will be full and it's about 4 or 8k if I remember
  -correctly. So your users will just wait till it will be filled up.
  -
  -<P>
  -For those who thinks that it is a very ineffective way to redirect, the
  -redirector runs as a daemon, you fire up N redirect daemons, so there is no
  -problem with perl interpreter loading, exactly like modperl - it is already
  -loaded and the code compiled, so redirect is very fast (not slower if
  -redirector was written in C or alike). I think that squid keeps a pipe
  -opened to all redirect daemons so there is no overhead of system calls as
  -well.
  -
   <P>
  -Now it is time to restart the server, at linux I do it with:
  +First you'll see:
   
   <P>
  -<PRE>  /etc/rc.d/init.d/squid restart
  +<PRE>  Foo-&gt;DESTROY
  +  Done with script
   </PRE>
  -<P>
  -Now you are done...
  -
   <P>
  -Almost... When you will try the new setup, you will be surprised and upset
  -to discover the 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 since
  -it will bypass the squid server and the hard work we went through was just
  -a waste of time? The solution is to run both the squid and the httpd_docs
  -on 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:
  +Then, uncomment the line where <CODE>$self</CODE> makes a circular
  +reference, and you'll see:
   
   <P>
  -<PRE>  Port 80
  -  BindAddress 127.0.0.1
  -  Listen 127.0.0.1:80
  +<PRE>  Done with script
  +  Foo-&gt;DESTROY
   </PRE>
   <P>
  -Modify the <CODE>squid.conf</CODE>
  +In this case, under mod_perl you wouldn't see <CODE>Foo-&amp;gt;DESTROY</CODE>
  +until the server shutdown, or your module properly took care of things.
   
  -
  -
  -<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>
   <P>
  -Where <CODE>123.123.123.3</CODE> should be replaced with IP of your main server. Now restart the squid and
  -httpd_docs in either order you want, and voila the port number has gone.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A></H1></CENTER>
   <P>
  -I think that you must also have in the /etc/hosts an entry:
  +To trap all/most Perl run-time errors and send the output to the client
  +instead of Apache's error log add this line to your script.
   
   <P>
  -<PRE>  127.0.0.1  localhost.localdomain   localhost
  +<PRE>  use CGI::Carp qw(fatalsToBrowser);
   </PRE>
   <P>
  -But generally it is always there in first place.
  +Refer to <CODE>CGI::Carp</CODE> man page for more related info.
   
   <P>
  -Now if you scripts were generating full self references using the port 8080
  -or other you should remove it and generate links to point to port 80 (which
  -means not using the port at all). If you do not, users will bypass the
  -squid, like if it was not setup at all. The only question left is what to
  -do with users who bookmarked your services and they still have the port
  -8080 inside. Do not worry about it. The most important thing is for your
  -scripts to return a full URLs, so if user comes from the link with 8080
  -port inside, let it be. Just make sure that all the consecutive calls to
  -you server will be pointed correctly. During some period your users will
  -change their bookmarks, nothing you can do about by 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. See
  -<A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>.
  +Also you can write your custom DIE/WARN signal handler. I don't want users
  +to see the error message, but I want it to be emailed to me if it's severe
  +enough. The handler traps various errors and performs accordingly to the
  +defined logic. My handler was written for the modperl environment, but
  +works correctly when is being called from the shell. A stripped version of
  +the code is shown here:
   
   <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>  # assign the DIE sighandler to call mydie(error_message) whenever a
  +  # die() sub is being called. Can be added anywhere in the code.
  +  local $SIG{'__DIE__'} = \&amp;mydie;
  +  
  +Do not forget the C&lt;local()&gt;, unless you want this signal handler to
  +be invoked every time any scripts dies (Even those where this
  +treatment is undesirable)
  +</PRE>
   <P>
  -See <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</A> for information about
  -<CODE>X-Forwarded-For</CODE>.
  -
  -<P>
  -To save you keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
  -
  -<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>  # and the handler itself
  +  sub mydie{
  +    my $why = shift;
     
  -  icp_port 0
  +    my $UNDER_MOD_PERL = ( (exists $ENV{'GATEWAY_INTERFACE'} 
  +                           and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/)
  +                         or exists $ENV{'MOD_PERL'} ) ? 1 : 0;
     
  -  hierarchy_stoplist /cgi-bin /perl
  -  acl QUERY urlpath_regex /cgi-bin /perl
  -  no_cache deny QUERY
  +    chomp $why;
  +    my $orig_why = $why;                # an ASCII copy for email report
     
  -  # debug_options ALL,1 28,9
  +    # handle the shell execution case (so we will not get all the HTML)
  +    print(&quot;Error: $why\n&quot;), exit unless $UNDER_MOD_PERL;
     
  -  redirect_program /usr/lib/squid/redirect.pl
  -  redirect_children 10
  -  redirect_rewrites_host_header off
  +    my $should_email = 0;
  +    my $message = '';
     
  -  request_size 1000 KB
  +    $why =~ s/[&lt;&amp;&gt;]/&quot;&amp;#&quot;.ord($&amp;).&quot;;&quot;/ge;    # entity escape
     
  -  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
  +    # Now we need to trap various kinds of errors, that come from CGI.pm
  +    # And we don't want these errors to be emailed to us, since
  +    # these aren't programmatical errors
  +    if ($orig_why =~ /Client attempted to POST (\d+) bytes/o) {
     
  -  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
  +      $message = qq{
  +                  You can not POST messages bigger than 
  +                  @{[1024*$c{max_image_size}]} bytes.&lt;BR&gt;
  +                  You have tried to post $1 bytes&lt;BR&gt;
  +                  If you are trying to upload an image, make sure its size is not 
  +                  bigger than @{[1024*$c{max_image_size}]} bytes.&lt;P&gt;
  +                  Thank you!
  +                 };
     
  -  cache_effective_user squid
  -  cache_effective_group squid
  +    } elsif ($orig_why =~ /Malformed multipart POST/o) {
     
  -  cache_mem 20 MB
  +      $message = qq{
  +                  Have you tried to upload an image in the wrong way?&lt;P&gt;
  +                  To sucessfully upload an image you must use a browser that supports
  +                  image upload and use the 'Browse' button to select that image.
  +                  DO NOT type the path to the image into the upload field.&lt;P&gt;
  +                  Thank you!
  +                 };
     
  -  memory_pools on
  +    } elsif ($orig_why =~ /closed socket during multipart read/o) {
     
  -  cachemgr_passwd disable shutdown
  -</PRE>
  -<P>
  -Note that parameters' names 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><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 the squid, I thought: ``Hey I can drop now 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 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 documents. 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 fetches per second at a peak period
  -and thus the number of servers you need for static pages. This number you
  -have to multiply with the difference of memory requirements to get the
  -memory overhead. I can imagine, this amount could be significant in some
  -installations.
  -
  -<P>
  -So I have decided to have even more administration overhead and to stick to
  -the 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 last 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>
  -So if you are still with me. Install the apache with mod_perl and the
  -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>. We also do not need to bind two servers on the same port anymore because
  -we do not redirect anymore (There is no more need for <CODE>Bind</CODE> and <CODE>Listen</CODE> directives in the httpd.conf).
  -
  -<P>
  -The modified configuration (see the explanations in the previous section):
  -
  -<P>
  -<PRE>  httpd_accel_host put.your.hostname.here
  -  httpd_accel_port 8080
  -  http_port 80
  -  icp_port 0
  +      $message = qq{
  +                  Have you pressed a 'STOP' button?&lt;BR&gt;
  +                  Please try again!&lt;P&gt;
  +                  Thank you!
  +                 };
     
  -  hierarchy_stoplist /cgi-bin /perl
  -  acl QUERY urlpath_regex /cgi-bin /perl
  -  no_cache deny QUERY
  +    } else {
     
  -  # debug_options ALL,1 28,9
  +      $message = qq{
  +                    &lt;B&gt;There is no action to be performed on your side, since
  +                  the error report has been already sent to webmaster. &lt;BR&gt;&lt;P&gt;
  +                  &lt;B&gt;Thank you for your patience!&lt;/B&gt;
  +                 };
     
  -  # redirect_program /usr/lib/squid/redirect.pl
  -  # redirect_children 10
  -  # redirect_rewrites_host_header off
  +      $should_email = 1;
  +    }
     
  -  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
  +    print qq|Content-type: text/html
     
  -  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
  +  &lt;HTML&gt;&lt;BODY BGCOLOR=&quot;white&quot;&gt;
  +  &lt;B&gt;Oops, An error has happened.&lt;/B&gt;&lt;P&gt;
  +    |;  
     
  -  cache_effective_user squid
  -  cache_effective_group squid
  +    print $message;
     
  -  cache_mem 20 MB
  +      # send email report if appropriate
  +    if ($should_email){
     
  -  memory_pools on
  +        # import sendmail subs
  +      use Mail ();
  +        # prepare the email error report:
  +      my $subject =&quot;Error Report&quot;;
  +      my $body = qq|
  +    An error has happened:
     
  -  cachemgr_passwd disable shutdown
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Using_mod_proxy">Using mod_proxy</A></H1></CENTER>
  -<P>
  -The server on port 80 answers html requests directly and proxies the
  -modperl enabled directory like this:
  -
  -<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>
  +    $orig_why
  +  
  +      |;
  +  
  +        # send error reports to admin and author
  +      send_mail($c{email}{'admin'},$c{email}{'admin'},$subject,$body);
  +      send_mail($c{email}{'admin'},$c{email}{'author'},$subject,$body);
  +      print STDERR &quot;[&quot;.scalar localtime().&quot;] [SIGDIE] Sending Error Email\n&quot;;
  +    }
  +  
  +       # print to error_log so we will know we've sent
  +    print STDERR &quot;[&quot;.scalar localtime().&quot;] [SIGDIE] $orig_why \n&quot;;
  +  
  +    exit 1;
  +  }                             # end of sub mydie
  +  
   </PRE>
   <P>
  -<CODE>PPR</CODE> is the saving grace here, that makes Apache a win over Squid. That cleans
  -up redirects and stuff to remove the :81 from the URIs. Very nice. If you
  -want to use mod_proxy to proxy pass more than one port, you probably want
  -to take a look at mod_rewrite.
  +You may have noticed that I trap the CGI.pm's <CODE>die()</CODE> calls
  +here, I don't see any reason why my users should see an ugly error
  +messages, but that's the way CGI.pm written. The workaround is to trap them
  +myself.
   
   <P>
  -You can control the buffering feature with <CODE>ProxyReceiveBufferSize</CODE>
  -directive:
  +Please note that as of ver 2.49, CGI.pm provides a <CODE>cgi_error()</CODE>
  +method to print the errors and wouldn't <CODE>die()</CODE> unless you want
  +it.
   
   <P>
  -<PRE>  ProxyReceiveBufferSize 1048576
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A></H1></CENTER>
   <P>
  -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 basicaly to get an immediate release of the
  -mod_perl server, <CODE>ProxyReceiveBufferSize</CODE> should be set to a value greater than the biggest generated respond
  -produced by any mod_perl script.
  +<CODE>Apache::Registry</CODE>, <CODE>Apache::PerlRun</CODE> and modules that compile-via-eval confuse the line numbering. Other files
  +that are read normally by Perl from disk have no problem with file
  +name/line number.
   
   <P>
  -The <CODE>ProxyReceiveBufferSize</CODE> directive specifies an explicit network buffer size for <STRONG>outgoing</STRONG> HTTP and FTP connections, for increased throughput. It has to be greater
  -than 512 or set to 0 to indicate that the system's default buffer size
  -should be used.
  +If you compile with the experimental <STRONG>PERL_MARK_WHERE=1</STRONG>, it shows you almost the exact line number, where this is happening.
  +Generally a compiler makes a shift in its line counter. You can always
  +stuff your code with special compiler directives, to reset its counter to
  +the value you will tell. At the beginning of the line you should write (the
  +'#' in column 1):
   
   <P>
  -As the name states its buffering 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)
  -
  +<PRE>  #line 298 myscript.pl
  +  or 
  +  #line 890 some_label_to_be_used_in_the_error_message
  +</PRE>
   <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.
  +The label is optional - the filename of the script will be used by default.
  +This specifies the line number of the <STRONG>following</STRONG> line, not the line the directive is on. You can use a little script to
  +stuff every N lines of your code with these directives, but then you will
  +have to rerun this script every time you add or remove code lines. The
  +script:
   
   <P>
  -Ask Bjoern Hansen has written a <CODE>mod_proxy_add_forward.c</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. His patch is at: <A
  -HREF="http://modules.apache.org/search?id=124">http://modules.apache.org/search?id=124</A>
  -or at <A
  -HREF="ftp://ftp.netcetera.dk/pub/apache/">ftp://ftp.netcetera.dk/pub/apache/</A>
  -. 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>:
  -
  +<PRE>    &lt;META&gt;
  +        This example was double incrementing $counter.
  +        I took the second increment out -- sgr.
  +    &lt;/META&gt;
  +</PRE>
   <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>  #!/usr/bin/perl
  +  # Puts Perl line markers in a Perl program for debugging purposes.  
  +  # Also takes out old line markers.
  +  die &quot;No filename to process.\n&quot; unless @ARGV;
  +  my $filename = $ARGV[0];
  +  my $lines = 100;
  +  open IN, $filename or die &quot;Cannot open file: $filename: $!\n&quot;;
  +  open OUT, &quot;&gt;$filename.marked&quot;
  +      or die &quot;Cannot open file: $filename.marked: $!\n&quot;;
  +  my $counter = 1;
  +  while (&lt;IN&gt;) {
  +    print OUT &quot;#line $counter\n&quot; unless $counter++ % $lines;
  +    next if $_ =~ /^#line /;
  +    print OUT $_;
     }
  +  close OUT;
  +  close IN;
  +  chmod 0755, &quot;$filename.marked&quot;;
   </PRE>
   <P>
  -And in <CODE>httpd.conf</CODE>:
  +To have a complete trace of calls add:
   
   <P>
  -<PRE>  PerlPostReadRequestHandler My::ProxyRemoteAddr
  +<PRE>  use Carp ();
  +  local $SIG{__WARN__} = \&amp;Carp::cluck;
   </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.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A></H1></CENTER>
   <P>
  -That's why the above ``recommanded code'' includes a check for where the
  -request really is coming from before we change remote_ip.
  +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. 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 function or methods to call from CGI script. 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>
  -From that point on, the remote IP address is correct. You should be able to
  -access <CODE>REMOTE_ADDR</CODE> as usual.
  +Basically, you would do:
   
   <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="mod_perl_server_as_DSO">mod_perl server as DSO</A></H1></CENTER>
  +<PRE>  $params=FreezeThaw::freeze(
  +        [all data to pass to the other process]
  +        );
  +  system(&quot;program.pl $params&quot;);
  +</PRE>
   <P>
  -To build the mod_perl as DSO add <CODE>USE_DSO=1</CODE> to the rest of configuration parameters (so it will build libperl.so and
  -not libperl.a), like:
  +and in <CODE>program.pl</CODE> :
   
   <P>
  -<PRE>  perl Makefile.PL USE_DSO=1 ...
  +<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>
  -If you run <CODE>./configure</CODE> from apache source do not forget to add:
  -<CODE>--enable-shared=perl</CODE>
  -
  +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>
  -Then just add the <CODE>LoadModule</CODE> into your <CODE>httpd.conf</CODE>.
  +Also, the communication is only one way.
   
   <P>
  -You will find a complete explanation in the <CODE>INSTALL.apaci</CODE> pod which can be found in the mod_perl distribution.
  +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>
  -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 correctly for you.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A></H1></CENTER>
  +<P>
  +The <CODE>Apache::print()</CODE> routine has to gather up the headers that your script outputs, in order to
  +pass them to <CODE>$r-&amp;gt;send_http_header</CODE>. This happens in <CODE>src/modules/perl/Apache.xs</CODE> (<CODE>print</CODE>) and
  +<CODE>Apache/Apache.pm</CODE> (<CODE>send_cgi_header</CODE>). There is a shortcut in there, namely the assumption that each print
  +statement contains one or more complete headers. If for example you used to
  +generate a
  +<CODE>Set-Cookie</CODE> header by multiply <CODE>print()</CODE> statements, like:
   
  +<P>
  +<PRE>   print &quot;Content-type: text/html\n&quot;;
  +   print &quot;Set-Cookie: iscookietext\; &quot;;
  +   print &quot;expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; &quot;;
  +   print &quot;path=\/\; &quot;;
  +   print &quot;domain=\.mmyserver.com\; &quot;;
  +   print &quot;\n\n&quot;;
  +   print &quot;hello&quot;;
  +</PRE>
   <P>
  -&lt;META&gt; Incomplete &lt;/META&gt;
  +your generated <CODE>Set-Cookie</CODE> header is split over a number of print statements and gets lost. Try this:
   
   <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>
  +<PRE>   print &quot;Content-type: text/html\n&quot;;
  +   my $cookie = &quot;Set-Cookie: iscookietext\; &quot;;
  +   $cookie .= &quot;expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; &quot;;
  +   $cookie .= &quot;path=\/\; &quot;;
  +   $cookie .= &quot;domain=\.mmyserver.com\; &quot;;
  +   print $cookie;
  +   print &quot;\n\n&quot;;
  +   print &quot;hello&quot;;
  +</PRE>
  +<P>
  +&lt;META&gt; some leftovers... # =head1 Coding with mod_perl
  +
   <P>
  -Assuming that you have a setup of one ``front-end'' server, which provides
  -proxies the ``back-end'' (mod_perl) server, if you need to perform the
  -athentication in the ``back-end'' server, it should handle all
  -authentication. 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 pass through information.
  +Before you start coding for <CODE>Apache::Registry</CODE>, you have to change your programming state of mind. Scripts running under
  +mod_perl are like subroutines are being called from a continually running
  +daemon. Imagine a daemon process that when requested to process some
  +script, reads it in, compiles it as a subroutine, and finally executes it.
  +On any subsequent request, it'll just recall the already compiled
  +subroutine. Hope that you get the idea.
   
   <P>
  -The only possible caveat in config file is that your Auth stuff needs to be
  -in &lt;Directory ...&gt; ... &lt;/Directory&gt; tags because if you use a
  -&lt;Location /&gt; ... &lt;/Location&gt; the proxypass server takes the
  -auth info for its authentication and would not pass it on.
  +The best thing you do when coding from scratch is to make it clean and use
  +packages. By ``make it clean'' we mean make certain that you <STRONG>use
  +strict;</STRONG> and that your script produces no warnings when tested via
  +<STRONG>perl -cw myscript.pl</STRONG>. As you go thru the notes you will understand why. &lt;/META&gt;
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -3168,7 +3232,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="strategy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A>      ]
  +	     [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -3181,7 +3245,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -3208,7 +3272,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Installation Notes</TITLE>
  +   <TITLE>mod_perl guide: Performance. Benchmarks.</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">
  @@ -3227,41 +3291,52 @@
   <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>
  +Performance. Benchmarks.</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 -->
  +	    [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Configuration_and_Installation">Configuration and Installation</A>
  +	<LI><A HREF="#Performance_The_Overall_picture">Performance: The Overall picture</A>
  +	<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
  +	<LI><A HREF="#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
   	<UL>
   
  -		<LI><A HREF="#Perl">Perl</A>
  -		<LI><A HREF="#Apache">Apache</A>
  -		<LI><A HREF="#Mod_Perl">Mod_Perl</A>
  +		<LI><A HREF="#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A>
   	</UL>
   
  -	<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is really installed</A>
  +	<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
  +	<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</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 (and where)</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>
  +	<LI><A HREF="#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</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>
  +		<LI><A HREF="#Developers_Talk">Developers Talk</A>
  +		<LI><A HREF="#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
  +		<LI><A HREF="#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
  +		<LI><A HREF="#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
   	</UL>
   
  -	<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_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>
  +	<LI><A HREF="#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
   	<UL>
   
  -		<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>
  +		<LI><A HREF="#Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench </A>
  +		<LI><A HREF="#Tuning_with_crashme_script">Tuning with crashme script</A>
  +		<LI><A HREF="#Choosing_MaxClients">Choosing MaxClients</A>
  +		<LI><A HREF="#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A>
  +		<LI><A HREF="#Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A>
  +		<LI><A HREF="#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
   	</UL>
   
  -	<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  +	<LI><A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>
  +	<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>
   </UL>
   <!-- INDEX END -->
   
  @@ -3279,1336 +3354,1798 @@
   
   	      <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>
  -<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>
  -<P>
  -First install perl. Follow the instructions in the distribution's INSTALL
  -file. During the configuration stage (while running
  -<CODE>./Configure</CODE>), make sure you answer <CODE>YES</CODE> to:
  -
  -<P>
  -<PRE>  Do you wish to use dynamic loading? [y]
  -</PRE>
  +<CENTER><H1><A NAME="Performance_The_Overall_picture">Performance: The Overall picture</A></H1></CENTER>
   <P>
  -Answer <CODE>y</CODE> to be able to load dynamically Perl Modules extensions.
  +Before we dive into performance issues, there is something very important
  +to understand. It applies to any webserver, not only apache. All the
  +efforts are made to make user's web browsing experience a swift. Among
  +other web site usability factors, speed is one of the most crucial ones.
  +What is a correct speed measurement? Since user is the one that interacts
  +with web site, speed measurement is a time passed from the moment user
  +follows a link or presses a submit button till the resulting page is being
  +rendered by her browser. So if we trace the data packet's movement as it
  +leaves user's machine (request sent) till the reply arrives, the packet
  +travels through many entities on its way. It has to make its way through
  +the network, passing many interconnection nodes, before it enters the
  +target machine it might go through proxy (accelerator) servers, then it's
  +being served by your server, and finally it has to make the whole way back.
  +A webserver is only one of the elements the packet sees on its way. You
  +could work hard to fine tune your webserver for the best performance, but a
  +slow NIC (Network Interface Card) or slow network connection from your
  +server might defeat it all. That's why it's important to think big and to
  +be aware of possible bottlenecks between the server and the web. Of course
  +there is nothing you can do if user has a slow connection on its behalf.
  +
  +<P>
  +From the other side, you might tune your scripts and webserver to process
  +incoming requests ultra fast, so you will need a little number of working
  +servers, but you might find out that server processes are busy waiting for
  +slow clients to complete the download. You will see more examples in this
  +chapter. My point is that a web service is like car, if one of the details
  +or mechanisms is broken the car will not drive smoothly and it can even
  +stop dead if pushed further without first fixing it.
   
   <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>
  +<CENTER><H1><A NAME="Sharing_Memory">Sharing Memory</A></H1></CENTER>
   <P>
  -It is a good idea to try to install the Apache webserver without mod_perl
  -first. This way, if something going 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.
  +A very important point is the sharing of memory. If your OS supports this
  +(and most sane systems do), you might save more memory by sharing it
  +between child processes. This is only possible when you preload code at
  +server startup. However during a child process' life, its memory pages
  +becomes unshared and there is no way we can control perl to make it
  +allocate memory so (dynamic) variables land on different memory pages than
  +constants, that's why the <STRONG>copy-on-write</STRONG> effect (will explain in a moment) will hit almost at random. If you are
  +pre-loading many modules you might be able to balance the memory that stays
  +shared against the time for an occasional fork by tuning the
  +<CODE>MaxRequestsPerChild</CODE> to a point where you restart before too much becomes unshared. In this case
  +the <CODE>MaxRequestsPerChild</CODE> is very specific to your scenario. You should do some measurements and you
  +might see if this really makes a difference and what a reasonable number
  +might be. Each time a child reaches this upper limit and restarts it should
  +release the unshared copies and the new child will inherit pages that are
  +shared until it scribbles on them.
   
  -<P>
  -<PRE>  % ls -l /usr/src
  -  drwxr-xr-x   8 stas  bar         2048 Oct  6 09:46 apache_1.3.6/
  -  drwxr-xr-x  19 stas  bar         4096 Oct  2 14:33 mod_perl-1.19/
  -</PRE>
   <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>
  -<P>
  -Now we come to the main point of this document.
  +It is very important to understand that your goal is not to have
  +<CODE>MaxRequestsPerChild</CODE> to be 10000. Having a child serving 300 requests on precompiled code is
  +already a huge speedup, so if it is 100 or 10000 it does not really matter
  +if it saves you the RAM by sharing. Do not forget that if you preload most
  +of your code at the server startup, the fork to spawn a new child will be
  +very very fast, because it inherits most of the preloaded code and the perl
  +interpreter from the parent process. But then during the work of the child,
  +its memory pages (which aren't really its yet, it uses the parent's pages)
  +are getting dirty (originally inherited and shared variables are getting
  +updated/modified) and the <STRONG>copy-on-write</STRONG>
  +happens, which reduces the number of shared memory pages - thus enlarging
  +the memory demands. Killing the child and respawning a new one, allows to
  +get the pristine shared memory from the parent process again.
   
   <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.
  +The conclusion is that <CODE>MaxRequestsPerChild</CODE> should not be too big, otherwise you loose the benefits of the memory
  +sharing.
   
   <P>
  -As with any perl package, the installation of mod_perl is very easy and
  -standard. <CODE>perldoc INSTALL</CODE> will guide you thru the configuration and installation process.
  +See <A HREF="././performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A> for more about tuning the <CODE>MaxRequestsPerChild</CODE> parameter.
   
   <P>
  -The fastest way to install would be:
  +<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
  +be able to share the code space used by these modules. Just add the
  +following directives into <CODE>httpd.conf</CODE>:
   
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_1.3.6/src \
  -    DO_HTTPD=1  USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
  -  % make &amp;&amp; make test &amp;&amp; make install
  +<PRE>  PerlModule CGI;
  +  PerlModule DBI;
   </PRE>
   <P>
  -(Note: if you use an apache version different then apache_1.3.6, change the
  -version number in the example above and in all later examples
  -appropriately)
  +But even a better approach is to create a separate startup file (where you
  +code in plain perl) and put there things like:
   
   <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 /foo/server as a base directory root, you have to run this:
  +<PRE>  use DBI;
  +  use Carp;
  +</PRE>
  +<P>
  +Then you <CODE>require()</CODE> this startup file with help of <CODE>PerlRequire</CODE>
  +directive from <CODE>httpd.conf</CODE>, by placing it before the rest of the mod_perl configuration directives:
   
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_1.3.6/src \
  -    DO_HTTPD=1 PERL_MARK_WHERE=1 EVERYTHING=1 \
  -    APACHE_PREFIX=/foo/server PREFIX=/foo/server
  +<PRE>  PerlRequire /path/to/start-up.pl
   </PRE>
   <P>
  -Where <CODE>PREFIX</CODE> specifies where to install the perl modules,
  -<CODE>APACHE_PREFIX</CODE> - the same for the apache files.
  +<CODE>CGI.pm</CODE> is a special case. Ordinarily <CODE>CGI.pm</CODE> autoloads most of its functions on an as-needed basis. This speeds up the
  +loading time by deferring the compilation phase. However, if you are using
  +mod_perl, FastCGI or another system that uses a persistent Perl
  +interpreter, you will want to precompile the methods at initialization
  +time. To accomplish this, call the package function <CODE>compile()</CODE>
  +like this:
   
   <P>
  -The next step is to configure the mod_perl sections of the apache conf
  -files. See <A HREF="././config.html#">ModPerlConfiguration</A>
  -
  -
  +<PRE>    use CGI ();
  +    CGI-&gt;compile(':all');
  +</PRE>
  +<P>
  +The arguments to <CODE>compile()</CODE> are a list of method names or sets, and are identical to those accepted by
  +the <CODE>use()</CODE> and <CODE>import()</CODE>
  +operators. Note that in most cases you will want to replace <CODE>':all'</CODE>
  +with tag names you really use in your code, since generally only a subset
  +of subs is actually being used.
   
   <P>
  -Fire up the server with <CODE>/foo/server/sbin/apachectl start</CODE>, Watch the error log file if server does not start up (No error message
  -will be printed to the console!)
  +You can also preload the Registry scripts. See <A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>.
   
   <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 really installed</A></H1></CENTER>
  +<CENTER><H2><A NAME="Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A></H2></CENTER>
   <P>
  -There 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 and restart the server.
  +I have conducted a few tests to benchmark the memory usage when some
  +modules are preloaded. The first set of tests checks the memory use with
  +Library Perl Module preload (only <CODE>CGI.pm</CODE>). The second set checks the compile method of <CODE>CGI.pm</CODE>. The third test checks the benefit of Library Perl Module preload but a
  +few of them (to see more memory saved) and also the effect of precompiling
  +the Registry modules with <CODE>Apache::RegistryLoader</CODE>.
   
  -<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>
   <P>
  -When starting the server, just check the <CODE>error_log</CODE> file for this:
  +1. In the first test, the following script was used:
   
   <P>
  -<PRE>  [Thu Dec  3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured
  -                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  -   -- resuming normal operations
  +<PRE>  use strict;
  +  use CGI ();
  +  my $q = new CGI;
  +  print $q-&gt;header;
  +  print $q-&gt;start_html,$q-&gt;p(&quot;Hello&quot;);
   </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>
  +<STRONG>Server restarted</STRONG>
  +
  +
  +
   <P>
  -Assuming that you have configured the &lt;<CODE>Location /perl-status</CODE>&gt;
  -Section in the server configuration file (refer to
  -<A HREF="././config.html#">ModPerlConfiguration</A>), fetch: <A
  -HREF="http://www.yourserver.com/perl-status">http://www.yourserver.com/perl-status</A>
  -using your favorite Netscape browser :-)
  +Before the <CODE>CGI.pm</CODE> preload: (No other modules preloaded)
   
   <P>
  -You should see something like this:
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      87004  0.0  0.0 1060 1524      - A    16:51:14  0:00 httpd
  +  httpd    240864  0.0  0.0 1304 1784      - A    16:51:13  0:00 httpd
  +</PRE>
  +<P>
  +After running a script which uses CGI's methods (no imports):
   
   <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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root     188068  0.0  0.0 1052 1524      - A    17:04:16  0:00 httpd
  +  httpd     86952  0.0  1.0 2520 3052      - A    17:04:16  0:00 httpd
   </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>
  +Observation: child httpd has grown up by 1268K
  +
   <P>
  -Knowing the port you have configured Apache to listen on, you can use
  -<CODE>telnet</CODE> to talk directly to the web server.
  +<STRONG>Server restarted</STRONG>
   
  +
  +
   <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!
  +After the <CODE>CGI.pm</CODE> preload:
   
   <P>
  -<PRE>  % telnet yourserver.com 8080&lt;ENTER&gt;
  -  HEAD / HTTP/1.0&lt;ENTER&gt;&lt;ENTER&gt;
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root     240796  0.0  0.0 1456 1552      - A    16:55:30  0:00 httpd
  +  httpd     86944  0.0  0.0 1688 1800      - A    16:55:30  0:00 httpd
   </PRE>
   <P>
  -You should see a response like this:
  +after running a script which uses CGI's methods (no imports):
   
   <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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      86872  0.0  0.0 1448 1552      - A    17:02:56  0:00 httpd
  +  httpd    187996  0.0  1.0 2808 2968      - A    17:02:56  0:00 httpd
   </PRE>
   <P>
  -So you see <CODE>Server: Apache/1.3.6 (Unix) mod_perl/1.19</CODE> - which says that you <STRONG>do</STRONG> have mod_perl installed and it is version 1.19. Of course in your case it
  -would be the version you have installed.
  +Observation: child httpd has grown up by 1168K, 100K less then without
  +preload - good!
   
   <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>
  +<STRONG>Server restarted</STRONG>
   
   
   
  -<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.
  +After <CODE>CGI.pm</CODE> preloaded and compiled with CGI-&gt;compile(':all');
   
   <P>
  -Copy and paste the script below (no need for perl line!). Let's say you
  -called it test.pl, you saved it into the root of the cgi scripts, and cgi
  -root is mapped directly to /perl 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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      86980  0.0  0.0 2836 1524      - A    17:05:27  0:00 httpd
  +  httpd    188104  0.0  0.0 3064 1768      - A    17:05:27  0:00 httpd
   </PRE>
   <P>
  -Make it executable:
  +After running a script which uses CGI's methods (no imports):
   
   <P>
  -<PRE>  % chmod a+x test.pl
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      86980  0.0  0.0 2828 1524      - A    17:05:27  0:00 httpd
  +  httpd    188104  0.0  1.0 4188 2940      - A    17:05:27  0:00 httpd
   </PRE>
   <P>
  -Now fetch the URL <CODE>http://www.you.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 (part of the output was snipped).
  +Observation: child httpd has grown up by 1172K No change! So what does
  +CGI-&gt;compile(':all') help? I think it's because we never use all of the
  +methods CGI provides - so in real use it's faster. So you might want to
  +compile only the tags you are about to use - then you will benefit for
  +sure.
   
   <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]
  +2. I have tried the second test to find it. I run the script:
  +
  +<P>
  +<PRE>  use strict;
  +  use CGI qw(:all);
  +  print header,start_html,p(&quot;Hello&quot;);
   </PRE>
   <P>
  -Now if I run the same script in mod_cgi mode (configured with /cgi-bin)
  -(you will need to add the perl line <CODE>#!/bin/perl</CODE> for the above script) and fetch <CODE>http://www.you.com/cgi-bin/test.pl</CODE>.
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
  -<PRE>  SERVER_SOFTWARE   Apache/1.3.6 (Unix)
  -  GATEWAY_INTERFACE CGI/1.1
  -  [...snipped]
  +After <CODE>CGI.pm</CODE> was preloaded and NOT compiled with CGI-&gt;compile(':all'):
  +
  +<P>
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      17268  0.0  0.0 1456 1552      - A    18:02:49  0:00 httpd
  +  httpd     86904  0.0  0.0 1688 1800      - A    18:02:49  0:00 httpd
   </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:
  +After running a script which imports symbols (all of them):
   
   <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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      17268  0.0  0.0 1448 1552      - A    18:02:49  0:00 httpd
  +  httpd     86904  0.0  1.0 2952 3112      - A    18:02:49  0:00 httpd
   </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 scripts, 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.
  -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.
  +Observation: child httpd has grown up by 1264K
   
  -<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.
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
  -Assuming you have the libwww-perl (LWP) package installed (you will need it
  -installed in order to pass mod_perl's <CODE>make test</CODE> anyway):
  +After <CODE>CGI.pm</CODE> was preloaded and compiled with CGI-&gt;compile(':all'):
   
   <P>
  -<PRE>  % lwp-request -e -d www.site.com
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      86812  0.0  0.0 2836 1524      - A    17:59:52  0:00 httpd
  +  httpd     99104  0.0  0.0 3064 1768      - A    17:59:52  0:00 httpd
   </PRE>
   <P>
  -Will show you all the headers. (The <CODE>-d</CODE> option disables printing the response content.)
  +After running a script which imports symbols (all of them):
   
   <P>
  -<PRE>  % lwp-request -e -d www.site.com | egrep '^Server:'
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      86812  0.0  0.0 2832 1436      - A    17:59:52  0:00 httpd
  +  httpd     99104  0.0  1.0 4884 3636      - A    17:59:52  0:00 httpd
   </PRE>
   <P>
  -To see the server's version only.
  +Observation: child httpd has grown by 1868K. Why? Isn't
  +<CODE>CGI::compile(':all')</CODE> supposed to make children to share the compiled code with parent? It does
  +works as advertised, but if you pay attention in the code we have called
  +only three <CODE>CGI.pm</CODE>'s methods - just saying <CODE>use CGI qw(:all)</CODE> doesn't mean we compile the all available methods - we just import their
  +names. So actually this test is misleading. Execute <CODE>compile()</CODE> only on the methods you are actually using and then you will see the
  +difference.
   
   <P>
  -Again use <CODE>www.site.com:port_number</CODE> if your server is listening to a non-default 80 port.
  +3. The third script:
   
   <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>
  +<PRE>  use strict;
  +  use CGI;
  +  use Data::Dumper;
  +  use Storable;
  +  [and many lines of code, lots of globals - so the code is huge!]
  +</PRE>
   <P>
  -Yes, no problem with that. Follow the instructions above and when you
  -encounter APACI_ARGS use your home directory (or some other directory which
  -you have write access to as a prefix, for example,
  -<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.
  +<STRONG>Server restarted</STRONG>
  +
  +
   
   <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.you.com:8080</CODE> in that case, but that is not a problem since generally 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 an HTML form, so they should not know at all that the port is
  -different from the default port 80.
  +Nothing preloaded at startup:
   
   <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.)
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      90962  0.0  0.0 1060 1524      - A    17:16:45  0:00 httpd
  +  httpd     86870  0.0  0.0 1304 1784      - A    17:16:45  0:00 httpd
  +</PRE>
  +<P>
  +Script using CGI (methods), Storable, Data::Dumper called:
   
  +<P>
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      90962  0.0  0.0 1064 1436      - A    17:16:45  0:00 httpd
  +  httpd     86870  0.0  1.0 4024 4548      - A    17:16:45  0:00 httpd
  +</PRE>
   <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 that machine
  -(and it's not your own host...), most likely the system administrator of
  -the host will ask you to shutdown your mod_perl server, or to find another
  -home for it. You have a few solutions:
  +Observation: child httpd has grown by 2764K
   
  -<UL>
  -<P><LI>
   <P>
  -Reduce resource usage - see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
  +<STRONG>Server restarted</STRONG>
   
   
   
  -<P><LI>
   <P>
  -Ask your ISP if you can put a dedicated machine into their computer room
  -and be root there.
  +Preloaded CGI (compiled), Storable, Data::Dumper at startup:
   
  -<P><LI>
   <P>
  -Look for another ISP with lots of resources or one that supports mod_perl.
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      26792  0.0  0.0 3120 1528      - A    17:19:21  0:00 httpd
  +  httpd     91052  0.0  0.0 3340 1764      - A    17:19:21  0:00 httpd
  +</PRE>
  +<P>
  +Script using CGI (methods), Storable, Data::Dumper called
   
  -</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_determine_whic">Is it possible to determine which options were given to modperl's Makefile.PL</A></H1></CENTER>
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      26792  0.0  0.0 3124 1440      - A    17:19:21  0:00 httpd
  +  httpd     91052  0.0  1.0 6568 5040      - A    17:19:21  0:00 httpd
  +</PRE>
   <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 did not use
  -the default config parameters and altered some of them during the
  -configuration stage.
  +Observation: child httpd has grown by 3276K. Great difference: 512K less!!!
   
   <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 some other machine, I have found that I do not remember
  -what parameters did I altered.
  +<STRONG>Server restarted</STRONG>
   
  -<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.
  +
   
   <P>
  -mod_perl suggests using the <CODE>makepl_args.mod_perl</CODE> file which comes with mod_perl distribution. This is the file you specify
  -all the parameters you are going to use.
  +All the above modules + the above script PreCompiled with
  +<CODE>Apache::RegistryLoader</CODE> at startup:
   
   <P>
  -But if you have found yourself with a compiled tool and no traces of the
  -specified parameters left, you can still find them out if the sources were
  -not <CODE>make clean</CODE>'d. So 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>.
  +<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      43224  0.0  0.0 3256 1528      - A    17:23:12  0:00 httpd
  +  httpd     26844  0.0  0.0 3488 1776      - A    17:23:12  0:00 httpd
  +</PRE>
  +<P>
  +Script using CGI (methods), Storable, Data::Dumper called:
   
   <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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  +  root      43224  0.0  0.0 3252 1440      - A    17:23:12  0:00 httpd
  +  httpd     26844  0.0  1.0 6748 5092      - A    17:23:12  0:00 httpd
  +</PRE>
   <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>
  +Observation: child httpd has grown even more 3316K ! Does not seem to be
  +good!
  +
   <P>
  -There are two configuration parameters <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>
  -you can use in <CODE>perl Makefile.PL [options]</CODE>.
  +<STRONG>Summary</STRONG>:
  +
  +<P>
  +1. Library Perl Modules Preloading gave good results everywhere.
   
   <P>
  -<CODE>DO_HTTPD=1</CODE> means default to 'y' for the two prompts (which source tree to configure
  -against and to build the httpd in that tree).
  -<CODE>PREP_HTTPD=1</CODE> just means default 'n' to the second prompt, meaning, do not build httpd
  -(make) in the Apache source tree.
  +2. <CODE>CGI.pm</CODE>'s <CODE>compile()</CODE> method seems to use even more memory. It's because we never use all of the
  +methods CGI provides. Do <CODE>compile()</CODE>
  +only the tags that you are going to use and you will save the overhead of
  +the first call for each has not yet been called method, and the memory -
  +since compiled code will be shared across all the children.
   
   <P>
  -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>.
  +3. <CODE>Apache::RegistryLoader</CODE> might make scripts load faster on the first request after the child has
  +just started but the memory usage is worse!!! See the numbers by yourself.
   
   <P>
  -If you did not build the httpd, chdir to the apache source, and execute:
  +HW/SW used : The server is apache 1.3.2, mod_perl 1.16 running on AIX 4.1.5
  +RS6000 1G RAM.
   
   <P>
  -<PRE>  make
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Preload_Registry_Scripts">Preload Registry Scripts</A></H1></CENTER>
   <P>
  -Then return to the mod_perl source and run:
  +<CODE>Apache::RegistryLoader</CODE> compiles <CODE>Apache::Registry</CODE> scripts at server startup. It can be a good idea to preload the scripts you
  +are going to use as well. So the code will be shared among the children.
   
   <P>
  -<PRE>  make test
  -  make install
  +Here is an example of the use of this technique. This code is included in a <CODE>PerlRequire</CODE>'d file, and walks the directory tree under which all registry scripts are
  +installed. For each <CODE>.pl</CODE> file encountered, it calls the <CODE>Apache::RegistryLoader::handler()</CODE> method to preload the script in the parent server (before pre-forking the
  +child processes):
  +
  +<P>
  +<PRE>  use File::Find 'finddepth';
  +  use Apache::RegistryLoader ();
  +  {
  +      my $perl_dir = &quot;perl/&quot;;
  +      my $rl = Apache::RegistryLoader-&gt;new;
  +      finddepth(sub {
  +          return unless /\.pl$/;
  +          my $url = &quot;/$File::Find::dir/$_&quot;;
  +          print &quot;pre-loading $url\n&quot;;
  +  
  +          my $status = $rl-&gt;handler($url);
  +          unless($status == 200) {
  +              warn &quot;pre-load of `$url' failed, status=$status\n&quot;;
  +          }
  +      }, $perl_dir);
  +  }
   </PRE>
   <P>
  -Note that you will have to do the same if you did not pass
  -<CODE>APACHE_PREFIX=/path_to_installation_prefix</CODE> during the <CODE>perl
  -Makefile.PL [options]</CODE> stage.
  +Note that we didn't use the second argument to <CODE>handler()</CODE> here, as module's manpage suggests. To make the loader smarter about the
  +uri-&gt;filename translation, you might need to provide a <CODE>trans()</CODE>
  +function to translate the uri to filename. URI to filename translation
  +normally doesn't happen until HTTP request time, so the module is forced to
  +roll its own translation. If filename is omitted and a <CODE>trans()</CODE> routine was not defined, the loader will try using the URI relative to <STRONG>ServerRoot</STRONG>.
   
  -<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>
   <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. Do
  -<CODE>find</CODE> for <CODE>ap_mmn.h</CODE>, 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.
  +You have to check whether this makes any improvement for you though, I did
  +some testing [ <A HREF="#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A> ], and it seems that it takes more memory than when the scripts are being
  +called from the child - This is only a first impression and needs better
  +investigation. If you aren't concerned about few script invocations which
  +will take some time to respond while they load the code, you might not need
  +it all!
   
   <P>
  -For all RH fans, before you are going to build the apache by yourself, do: <CODE>rpm -e apache</CODE> to remove the preinstalled one first!
  +See also <A HREF="././porting.html#BEGIN_blocks">BEGIN blocks</A>
   
  +
  +
   <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>
  +<CENTER><H1><A NAME="Avoid_Importing_Functions">Avoid Importing Functions</A></H1></CENTER>
   <P>
  -Yes, you should. You have to rebuild mod_perl since it has a hardcoded
  -<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.
  +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.
   
   <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>
  +<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 (and where)</A></H1></CENTER>
   <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>.
  -
  -<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>.
  +<CODE>Apache::Leak</CODE> (derived from <CODE>Devel::Leak</CODE>) should help you with this task. Example:
   
  -	     <HR>
  -	     [    <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>
  -  <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 06/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: 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">
  -   <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>
  -Server Configuration</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 -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  -<UL>
  -
  -	<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="#PerlFreshRestart">PerlFreshRestart</A>
  -		<LI><A HREF="#_perl_status_location">/perl-status location</A>
  -		<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="#Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</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="#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</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>
  -</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>
  -
  -	      <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>
  +<PRE>  use Apache::Leak;
  +  
  +  my $global = &quot;FooAAA&quot;;
  +  
  +  leak_test {
  +    $$global = 1;
  +    ++$global;
  +  };
  +</PRE>
   <P>
  -The next step after building and installing your new mod_perl-enabled
  -Apache server, is to configure the server's configuration files. 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 conf directory and follow the instructions in these files - the embedded
  -comments within the file do a good job of explaining the options.
  +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>
  -Before you start the mod_perl configuration, configure Apache, and see that
  -it works. When done, return here to continue...
  -
  +<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>
  -[ 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. ]
  +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>
   <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>
  +<CENTER><H1><A NAME="Limiting_the_size_of_the_process">Limiting the size of the processes</A></H1></CENTER>
   <P>
  -First, you need to specify the location where all mod_perl scripts will be
  -located.
  +<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>
  -Add the following configuration directives:
  +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>
  -<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><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>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>.
  +<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>
  -Alias defines the start of the URL path to the script you are referencing.
  -For example, using the above configuration, fetching
  -<STRONG>http://www.you.com/perl/test.pl</STRONG>, will cause the server to look for the file <STRONG>test.pl</STRONG> at <STRONG>/usr/local/myproject/cgi</STRONG>, and execute it as an <STRONG>Apache::Registry</STRONG> script if we define Apache::Register to be the handler of <CODE>/perl</CODE> location (see below). The URL
  -<STRONG>http://www.you.com/perl/test.pl</STRONG> will be mapped to
  -<STRONG>/usr/local/myproject/cgi/test.pl</STRONG>. This means you can have all your CGIs located at the same place at file
  -system, and call the script in any of three modes simply by changing the
  -directory name component of the URL (cgi-bin|perl|cgi-perl) - is not this
  -cool? (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 an <CODE>Alias</CODE>
  -directive + <CODE>sethandler cgi-handler</CODE>. 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
  -http.conf), you can choose to use all three modes or only one of these (It
  -is undesirable to run plain cgi-bin scripts from a mod_perl-enabled server
  -- the price is too high, it is better to run these on plain Apache server.
  -(META: add link to strategies)
  +To configure use:
   
   <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>  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>
  -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.
  +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>
  -First we add:
  +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>
  -<PRE>  &lt;Location /perl&gt;
  -    #AllowOverride None
  -    SetHandler perl-script
  -    PerlHandler Apache::Registry
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  +To debug add:
  +
  +<P>
  +<PRE>  &lt;Perl&gt;
  +    $Apache::Resource::Debug = 1;
  +    require Apache::Resource;
  +  &lt;/Perl&gt;
  +  PerlChildInitHandler Apache::Resource
   </PRE>
   <P>
  -This configuration causes all scripts that are called with a <STRONG>/perl</STRONG>
  -path prefix to be executed under the <STRONG>Apache::Registry</STRONG> 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 will possibly will trigger a 'Save-As' window).
  +and look in the error_log to see what it's doing.
   
   <P>
  -<STRONG>PerlSendHeader On</STRONG> 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
  -CGI-&gt;header or $r-&gt;send_http_header directly.
  +Refer to <CODE>perldoc Apache::Resource</CODE> and <CODE>man 2 setrlimit</CODE> for more info.
   
   <P>
  -Remember the <STRONG>Alias</STRONG> from the section above? We must use the same Alias here, if you use
  -Location that does not have the same Alias defined in srm.conf, the server
  -will fail to locate the script in the file system. (We are talking about
  -script execution here -- there are cases where Location is something that
  -is being executed by the server itself, without having the corresponding
  -file, like <A HREF="#_perl_status_location">perl-status location</A>.)
  -
  +<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>
  -Note that sometimes you will have to add : PerlModule Apache::Registry
  +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>
  -before you specify the location that uses Apache::Registry as a
  -PerlHandler. Basically you can start running the scripts in the
  -Apache::Registry mode...
  +<CODE>Apache::SpeedLimit</CODE> comes for you to help, see:
   
   <P>
  -You have to do nothing about /cgi-bin (mod_cgi), since it has nothing to do
  -with mod_perl
  +<A
  +HREF="http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients">http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients</A>
   
  -<P>
  -Here is a similar location configuration for Apache::PerlRun. (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="PerlFreshRestart">PerlFreshRestart</A></H2></CENTER>
  +<CENTER><H1><A NAME="Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A></H1></CENTER>
   <P>
  -To reload <STRONG>PerlRequire</STRONG>, <STRONG>PerlModule</STRONG>, other <CODE>use()'d</CODE> modules and flush the Apache::Registry cache
  -on server restart, add:
  +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>
  -<PRE>  PerlFreshRestart On
  -</PRE>
   <P>
  -Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
  +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>
  -<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>
  +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>
  -Adding a directive to enable a <STRONG>/perl-status</STRONG> location allows you to see many things about your server. See
  -<A HREF="././status.html#Configuration">perl-status</A>
  +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>
   <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>
  +<CENTER><H2><A NAME="Developers_Talk">Developers Talk</A></H2></CENTER>
   <P>
  -Set and Pass the ENV variables to your scripts. So you can read them in
  -your scripts from <CODE>%ENV</CODE> (e.g. <CODE>$ENV{&quot;key&quot;}</CODE>)
  +Perrin Harkins writes on benchmarks or comparisons, official or unofficial:
  +
  +<BLOCKQUOTE>
   
   <P>
  -<CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In &lt;Perl&gt; sections:
  +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>  push @{ $Location{&quot;/&quot;}-&gt;{PerlSetVar} }, [ 'FOO' =&gt; BAR ];
  -</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>
  -and in the code you read it with:
  +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>  my $r = Apache-&gt;request;
  -  print $r-&gt;dir_config('FOO');
  -</PRE>
  +But I'm not bitter or anything...
  +
  +</BLOCKQUOTE>
  +
   <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>
  +Jonathan Peterson adds:
  +
  +<BLOCKQUOTE>
  +
   <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 one file, so the
  -configuration file will be cleaner, also you can call
  -<STRONG>perl -c perl-startup</STRONG> to test the file's syntax. What does this take? Add this line to
  -httpd.conf:
  +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>
  -<PRE>    # startup.perl loads all functions that we want to use within
  -    # mod_perl
  -  Perlrequire /path/to/startup.pl
  -</PRE>
  +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>
  -<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>
  +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>
  -An example of perl-startup file:
  +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>
  -<PRE>  use strict;
  -  
  -  #modify @INC if needed
  -  use lib qw(/some/other/dir /some/bar/dir);
  -  
  -  # 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>
  +For very large jobs, it may be worth finding the best technical solution,
  +and then recruiting the team with the necessary skills.
  +
  +</BLOCKQUOTE>
  +
   <P>
  -Note that starting with CGI::VERSION 2.46, the recommended method to
  -precompile the code in CGI.pm is:
  +<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>
  +<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:
   
   <P>
  -<PRE>  use CGI qw(-compile :all);
  +<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>
  -But the old method is still available for backward compatibility.
  +We don't know what server configurations was used for these tests, but I
  +guess the numbers speak for themselves.
   
   <P>
  -See also <A HREF="././status.html#Configuration">Apache::Status</A>
  +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>
  +<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.
   
  +<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>
  +<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><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><H2><A NAME="PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A></H2></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. 
  +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>
  -See <A HREF="././performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A> 
  +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>
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</A></H3></CENTER>
  +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>
  +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>
  -Yes! See <A HREF="././performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
  +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>
   <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="Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench</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:
  +<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>  use Foo qw(bar);
  +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>  % ./ab -n 100 -c 10 www.nowhere.com:81/test/test.pl
   </PRE>
   <P>
  -perl actually does:
  +The results are:
   
   <P>
  -<PRE>  require Foo.pm;
  -  import qw(bar);
  +<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>
  -When you write:
  +The only numbers we really care about are:
   
   <P>
  -<PRE>  use Foo qw();
  +<PRE>  Complete requests:      100
  +  Failed requests:        0
  +  Requests per second:    139.86
   </PRE>
   <P>
  -perl actually does:
  +Let's raise the load of requests to 100 x 10 (10 users, each makes 100
  +requests)
   
   <P>
  -<PRE>  require Foo.pm;
  -  import qw();
  +<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>
  -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 some tags to be exported by default and when write:
  +As expected nothing changes -- we have the same 10 concurrent users. Now
  +let's raise the number of concurrent users to 50:
   
   <P>
  -<PRE>  use Foo;
  +<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>
  -And you 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 correctly.
  +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>
  -Since the symbols that you might import into a startup's script namespace
  -will be visible by none of the children, scripts that needs a <CODE>Foo</CODE>'s module functionality 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 a startup script does not mean you can have the following handler:
  +The above tests were performed with the following configuration:
   
   <P>
  -<PRE>  package MyModule;
  -  
  -  sub {
  -    my $r = shift;
  -  
  -    ## Cool stuff goes here
  -  
  -    return OK;
  -  }
  -</PRE>
  -<P>
  -<PRE>  1;
  +<PRE>  MinSpareServers 8
  +  MaxSpareServers 6
  +  StartServers 10
  +  MaxClients 50
  +  MaxRequestsPerChild 1500
   </PRE>
   <P>
  -You would either need to add:
  +Now let's kill a child after a single request, we will use the following
  +configuration:
   
   <P>
  -<PRE>  use Apache::Constants qw( OK );
  +<PRE>  MinSpareServers 8
  +  MaxSpareServers 6
  +  StartServers 10
  +  MaxClients 100
  +  MaxRequestsPerChild 1
   </PRE>
   <P>
  -Or instead of <CODE>return OK;</CODE> say:
  +Simulate 50 users each generating a total of 20 requests:
   
   <P>
  -<PRE>  return Apache::Constants::OK;
  +<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
   </PRE>
   <P>
  -See the manpage/perldoc on <CODE>Exporter</CODE> and <CODE>perlmod</CODE> for more on import.
  +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).
   
   <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 preload modules and do a few 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 accessable by child processes.
  +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>
  -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 is a specially
  -(uniquely) named package - so it cannot access variables from other
  -packages unless it inherits from them or <CODE>use()</CODE>s them.
  -
  +<PRE>  MinSpareServers 8
  +  MaxSpareServers 6
  +  StartServers 10
  +  MaxClients 10
  +  MaxRequestsPerChild 1500
  +</PRE>
   <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>
  +I've got 27.12 req/sec, which is better but still 4-5 times slower (133
  +with <CODE>MaxClients</CODE> of 50)
  +
   <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% errorprone,
  -but it will reveal any syntaxical errors you might do while editing the
  -file.
  +<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:
   
   <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. &lt;Perl&gt; configuration has always started Perl during the configuration
  -read,
  -<CODE>Perl{Require,Module}</CODE> do so as well.
  +<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>
  -If you want your startup code to get a control over the <CODE>-t</CODE>
  -(configtest) server launch, start the server configuration test with 
  +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>
  -<PRE>  httpd -t -Dsyntax_check
  -</PRE>
  +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>
  -and in your startup file, add:
  +The benchmarks were run with:
   
   <P>
  -<PRE>  return if Apache-&gt;define('syntax_check');
  +<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>
  -<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>
  -
  -
  +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>
  -<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>
  +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>
  +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:
   
   <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>  NR    = Total Number of Request
  +  NC    = Concurrency
  +  MC    = MaxClients
  +  MRPC  = MaxRequestsPerChild
  +  RPS   = Requests per second
  +</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:
  +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>  RewriteRule .*/perl/(.*) <A HREF="http://my.url:8080/perl/">http://my.url:8080/perl/</A>$1 [P]
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
  +  MaxRequestsPerChild 5000
   </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.
  +gives us:
   
   <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>
  +<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>
  -With <STRONG>&lt;Perl&gt;&lt;/Perl&gt;</STRONG> sections, it is possible to configure your server entirely in Perl.
  +Conclusions: 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>
  -<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:
  +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>
  -<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>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
  +  MaxRequestsPerChild 5000
   </PRE>
  -<P>
  -Block sections such as &lt;Location&gt;&lt;/Location&gt; are represented in
  -a %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>     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 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:
  +Conclusions: 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>
  -<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>;;
  +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>  MinSpareServers       50
  +  MaxSpareServers       50
  +  StartServers          50
  +  MaxClients            50
  +  MaxRequestsPerChild 5000
     
  -  push @Redirect, [qw(temp &quot;/here&quot; &quot;<A HREF="http://www.there.com&quot">http://www.there.com&quot</A>;)];
  +     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>
  -Other section counterparts include <STRONG>%VirtualHost</STRONG>, <STRONG>%Directory</STRONG> and
  -<STRONG>%Files</STRONG>.
  -
   <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:
  +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>  push @PerlPassEnv, [$key =&gt; $val];
  -</PRE>
   <P>
  -or
  +Now we will try to change the <CODE>MaxClients</CODE> and to watch the results: Let's reduce MC to 10.
   
   <P>
  -<PRE>  Apache-&gt;httpd_conf(&quot;PerlPassEnv $key $val&quot;);
  +<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>
  -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.
  +Conclusions: 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>
  -A tip for syntax checking outside of httpd:
  +Now we will start to drastically reduce the <CODE>MaxRequestsPerChild</CODE>:
   
   <P>
  -<PRE>  &lt;Perl&gt;
  -  # !perl
  -  
  -  #... code here ...
  +<PRE>  MinSpareServers        8
  +  MaxSpareServers       16
  +  StartServers          10
  +  MaxClients            50
     
  -  __END__
  -  &lt;/Perl&gt;
  +     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>
  -Now you may run <STRONG>perl -cx httpd.conf</STRONG>.
  +Conclusions: 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>
  -To configure this feature build with <STRONG>perl Makefile.PL 
  -PERL_SECTIONS=1</STRONG>
  -
  -
  +<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>
  +Conclusion: 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="Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A></H1></CENTER>
  +<CENTER><H2><A NAME="Tuning_with_crashme_script">Tuning with crashme script</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.
  +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>
  -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.
  +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 Latency
  +(secs/Request) and Throughput (Requests/sec) numbers. It can give you a
  +better picture and make a complete simulation of your favorite Netscape
  +browser :).
   
   <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.
  +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>
  -Here are some useful macros for mod_perl users:
  +Sample output:
   
   <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>  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>
  -<PRE>        # example
  -        Alias /stuff /usr/www/scripts/stuff
  -        &lt;Location /stuff&gt;
  -        Use registry
  -        &lt;/Location&gt;
  +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() / 
  +                                   $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>
  +<P>
  +The <CODE>MaxClients</CODE> directive sets the limit on the number of simultaneous requests that can be
  +supported; not 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>  MaxClients = Total RAM Dedicated to the Webserver / MAX child's process size
  +</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>).
  +
  +<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:
  +
  +<P>
  +<PRE>  [Sun Jan 24 12:05:32 1999] [error] server reached MaxClients setting,
  +  consider raising the MaxClients setting
  +</PRE>
  +<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.
  +
  +<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 reached you should start to worry about it.
  +
  +<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>
  +<PRE>  MaxClients=(Total_RAM+Shared_RAM_per_Child*MaxClients)/Max_Process_Size-1
  +</PRE>
  +<P>
  +which is:
  +
  +<P>
  +<PRE>  MaxClients=(Total_RAM-Max_Process_Size)/(Max_Process_Size-Shared_RAM_per_Child)
  +</PRE>
  +<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>
  +<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>
  +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>
  +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 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!)
  +
  +<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.
  +
  +<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><H2><A NAME="Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A></H2></CENTER>
  +<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 then
  +<CODE>MaxClients</CODE>.)
  +
  +<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):
  +
  +<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>
  +<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:
  +
  +<P>
  +<PRE>  Available to webserver RAM:   400Mb
  +  Child's memory size bounded:  10Mb
  +  MaxClients:                   400/10 = 40
  +  StartServers:                 5
  +  MinSpareServers:              5
  +  MaxSpareServers:              10
  +</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!)
  +
  +<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>
  +<P>
  +OK, we've run various benchmarks -- let's summarize the conclusions:
  +
  +<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.
  +
  +<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.)
  +
  +<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.
  +
  +<P><LI><STRONG><A NAME="item_MaxSpareServers">MaxSpareServers</A></STRONG>
  +<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.
  +
  +<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. 
  +
  +<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.
  +
  +</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:
  +
  +<P>
  +<PRE>  # Apache::Registry script
  +  -------------------------
  +  use strict;
  +  use vars qw($dbh);
  +  
  +  $dbh ||= SomeDbPackage-&gt;connect(...);
   </PRE>
   <P>
  -If your registry scripts are all located in the same directory, and your
  -aliasing rules consistent, you can use this macro:
  +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>
  -<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>
  +Be careful to use different names for handlers if you open connection to
  +different databases!
  +
   <P>
  -<PRE>        # example
  -        Use registry stuff stuff.pl
  -</PRE>
  +<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>
  -If you're using content handlers packaged as modules, you can use the
  -following macro:
  +The usage is simple -- add to <CODE>httpd.conf</CODE>:
   
   <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>  PerlModule Apache::DBI
   </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;
  +It is important, to load this module before any other <CODE>ApacheDBI*</CODE> module!
  +
  +<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>
   <P>
  -The following macro sets up a Location for use with HTML::Embperl. Here we
  -define all ``.html'' files to be processed by Embperl.
  +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>
  -<PRE>        &lt;Macro embperl&gt;
  -        SetHandler &quot;perl-script&quot;
  -        Options +ExecCGI
  -        PerlHandler HTML::Embperl
  -        PerlSetEnv EMBPERL_FILESMATCH \.html$
  -        &lt;/Macro&gt;
  +<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>
  -<PRE>        # examples
  -        &lt;Location /mrtg&gt;
  -        Use embperl
  -        &lt;/Location&gt;
  -</PRE>
  +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>
  -Macros are also very useful for things that tend to be verbose, such as
  -setting up Basic Authentication:
  +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>
  -<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>
  +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>
  -<PRE>        # example of use
  -        &lt;Location /stats&gt;
  -        Use BasicAuth WebStats Admin
  -        &lt;/Location&gt;
  -</PRE>
  +<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>
  -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!).
  +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>
  -<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 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.
  +
   <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
  +Many old CGIs were written in the style of:
  +
  +<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>
   <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:
  +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>
  -<PRE>  use /forwards email/showforwards
  -  use /webstats web/showstats
  +<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>
  -<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>
  +I guess you see the difference. Be careful though, when printing a
  +<CODE>&lt;HTML</CODE>&gt; tag. The correct way is:
  +
   <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>
  +<PRE>  print qq{&lt;HTML&gt;
  +    &lt;HEAD&gt;&lt;/HEAD&gt;
  +    &lt;BODY&gt;
  +  }
  +</PRE>
   <P>
  -Check your configuration files and make sure that the ``ExecCGI'' is turned
  -on in your configurations. 
  +If you try the following:
   
   <P>
  -<PRE>  &lt;Location /perl&gt;
  -    SetHandler perl-script
  -    PerlHandler Apache::Registry
  -    Options ExecCGI
  -    allow from all
  -    PerlSendHeader On
  -  &lt;/Location&gt;
  +<PRE>  print qq{
  +    &lt;HTML&gt;
  +    &lt;HEAD&gt;&lt;/HEAD&gt;
  +    &lt;BODY&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;?
  +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>
  -<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>
  +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 Submit
  +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>
  -No. Any virtual host will be able to see the routines from a startup.pl
  -loaded for any other virtual host.  
  +Conclusion: 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><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>
  +<CENTER><H1><A NAME="More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A></H1></CENTER>
   <P>
  -You can use 'PerlSetEnv PERL5LIB ...' or a PerlFixupHandler w/ the lib
  -pragma.
  +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>
  -Even a better way is to use <A HREF="././modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC</A>
  +See <A HREF="././porting.html#Global_Variables">Global Variables</A>
  +
  +
  +
  +<P>
  +See <A HREF="././porting.html#Memory_leakage">Memory "leakages"</A>
   
   
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with
  -the same path from the second virtual host</A></H2></CENTER>
  +<CENTER><H1><A NAME="Profiling">Profiling</A></H1></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):
  +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>
  -<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 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:
   
   <P>
  -<PRE>  $Apache::Registry::NameWithVirtualHost = 0;
  +<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>
  -<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>
  +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>
  -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 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>
  -<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>
  +<PRE>  PerlModule Apache::DProf
  +</PRE>
   <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.
  +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>
  -The more modules you have in your web server, the more complex the code in
  -your webserver.
  -
  +<PRE>  % dprofpp
  +</PRE>
   <P>
  -The more complex the code in your web server, the more chances for bugs.
  +<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>
  +<PRE>  use CGI;
  +  my $q = new CGI;
  +  print $q-&gt;param('x');
  +</PRE>
   <P>
  -The more chance for bugs, the more chance that some of those bugs may
  -involve security.
  +versus
   
   <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.
  -
  +<PRE>  use CGI (:standard);
  +  print param('x');
  +</PRE>
   <P>
  -For more information see <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
  -
  -
  +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.
   
   <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.
  +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.
   
   <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="Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</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:
  +See <A HREF="././modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
   
  -<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><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -4620,7 +5157,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="install.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="frequent.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>
  @@ -4633,7 +5170,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/05/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -4660,7 +5197,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: 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">
  @@ -4679,15 +5216,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>
  -Frequent mod_perl problems</H1>
  +Choosing the Right Strategy</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.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="#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="#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 -->
   
  @@ -4705,3459 +5247,3487 @@
   
   	      <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="Do_it_like_me_">Do it like me?!</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.
  +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>
  -<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>
  +To be clear, I will not address all technologies and tools, but limit this
  +discussion to those complementing mod_perl.
  +
   <P>
  -See <A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +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><H1><A NAME="Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A></H1></CENTER>
  +<CENTER><H1><A NAME="mod_perl_Deployment_Overview">mod_perl Deployment Overview</A></H1></CENTER>
   <P>
  -See <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>
  +There are several different ways to build, configure and deploy your
  +mod_perl enabled server. Some of them are:
  +
  +<OL>
  +<P><LI>
  +<P>
  +Having one binary and one config file (one big binary for mod_perl).
  +
  +<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>
  +<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.)
  +
  +<P><LI>
  +<P>
  +Any of the above plus a reverse proxy server in http accelerator mode.
  +
  +</OL>
  +<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 forth
  +option which gives you even more power.
  +
  +<OL>
  +<P><LI>
  +<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.
  +
  +<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><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>.
   
  +<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.
   
  +</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.
   
  +<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>.
  +<CENTER><H1><A NAME="Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A></H1></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.
   
  -	     <HR>
  -	     [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]
  +<P>
  +The advantages:
   
  -<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 05/08/1999
  -      </FONT>
  -    </B>
  -  </TD>
  +<UL>
  +<P><LI>
  +<P>
  +Simplicity. You just follow the installation instructions, configure it,
  +restart the server and you are done.
   
  -  <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><LI>
  +<P>
  +No network changes. You do not have to worry about using additional ports
  +as we will see later.
   
  -  <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><LI>
  +<P>
  +Speed. You get a very fast server, you see an enormous speedup from the
  +first moment you start to use it.
   
  -</BODY>
  -</HTML>
  -	    
  +</UL>
  +<P>
  +The disadvantages:
   
  -<HR SIZE=6>
  -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  -<HTML>
  -<HEAD>
  -   <TITLE>mod_perl guide: CGI to mod_perl Porting. mod_perl Coding guidelines.</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>
  -CGI to mod_perl Porting. mod_perl Coding guidelines.</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <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.
   
  -	<LI><A HREF="#Document_Coverage">Document Coverage</A>
  -	<LI><A HREF="#Before_you_start_to_code">Before you start to code</A>
  -	<LI><A HREF="#Coding_with_mod_perl">Coding with mod_perl</A>
  -	<UL>
  +<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.
   
  -		<LI><A HREF="#What_s_different_about_modperl">What's different about modperl</A>
  -		<UL>
  +<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.
   
  -			<LI><A HREF="#Script_s_name_space">Script's name space</A>
  -			<LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  -			<LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  -			<LI><A HREF="#Output_from_system_calls">Output from system calls</A>
  -			<LI><A HREF="#Using_format_">Using format()</A>
  -			<LI><A HREF="#Using_exit_">Using exit()</A>
  -			<LI><A HREF="#Running_from_shell">Running from shell</A>
  -			<LI><A HREF="#I_O_is_different">I/O is different</A>
  -			<LI><A HREF="#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  -			<LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  -			<LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
  -			<LI><A HREF="#END_blocks">END blocks </A>
  -			<LI><A HREF="#Switches_w_T">Switches -w, -T</A>
  -		</UL>
  +<P><LI>
  +<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.
   
  -		<LI><A HREF="#strict_pragma">strict pragma</A>
  -		<LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
  -		<LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
  -		<LI><A HREF="#Global_Variables">Global Variables</A>
  -		<LI><A HREF="#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</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="#Memory_leakage">Memory leakage</A>
  -	</UL>
  +<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.
   
  -	<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
  -	<LI><A HREF="#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</A>
  -	<LI><A HREF="#The_Script_is_too_dirty_It_does">The Script is too dirty, 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="#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_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
  -	<LI><A HREF="#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
   </UL>
  -<!-- INDEX END -->
  +<P>
  +If you are new to mod_perl, this is probably the best way to get yourself
  +started.
   
  -<HR>
  +<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!
   
  -	     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>
  +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>
   
  -	     <HR>
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +
   <P>
  -<CENTER><H1><A NAME="Document_Coverage">Document Coverage</A></H1></CENTER>
  +<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>
  -This document is relevant to both writing a new CGI from scratch and
  -migrating an application from plain CGI to mod_perl.
  +As I have mentioned before, when running scripts under mod_perl, you will
  +notice that the httpd processes consume a huge amount of memory, from 5M to
  +25M, or even more. That is the price you pay for the enormous speed
  +improvements under mod_perl. (Again -- shared memory keeps them smaller :)
   
   <P>
  -If you are in the porting stage, use it as a reference for possible
  -problems you might encounter when running the existent CGI in the new mode.
  +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 you are about to write a new CGI from scratch, it would be a good idea
  -to learn most of the possible pitfalls and to avoid them in first place.
  +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>
  -It covers also the case where the CGI script being ported does the job, but
  -is too dirty to be easily altered to run as a mod_perl program.
  -(Apache::PerlRun)
  +The advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -If your project schedule is tight, I would suggest converting to mod_perl
  -in the following steps: Initially, run all the scripts in the
  -Apache::PerlRun mode. Then as time allows, move them into Apache::Registry
  -mode.
  +The heavy mod_perl processes serve only dynamic requests, which allows the
  +deployment of fewer of these large servers.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Before_you_start_to_code">Before you start to code</A></H1></CENTER>
  +<P><LI>
   <P>
  -It can be a good idea to tighten up some of your Perl programming
  -practices, since Apache::Registry doesn't allow sloppy programming.
  +<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>
  -You might want to read:
  +Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
   
  -<UL>
  -<P><LI><STRONG><A NAME="item_Perl">Perl Module Mechanics</A></STRONG>
  +</UL>
   <P>
  -This page describes the mechanics of creating, compiling, releasing, and
  -maintaining Perl modules. <A
  -HREF="http://world.std.com/~swmcd/steven/perl/module_mechanics.html">http://world.std.com/~swmcd/steven/perl/module_mechanics.html</A>
  +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>
  +The disadvantages:
   
  -<P><LI><STRONG><A NAME="item_Mod">Mod Perl Book</A></STRONG>
  +<UL>
  +<P><LI>
   <P>
  -A must have book! See the details at <A
  -HREF="http://www.modperl.com">http://www.modperl.com</A> .
  +An administration overhead.
   
  -</UL>
  +<UL>
  +<P><LI>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Coding_with_mod_perl">Coding with mod_perl</A></H1></CENTER>
  +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>
  -Before you start coding for Apache::Registry, you have to change your
  -programming state of mind. Scripts running under mod_perl are like
  -subroutines are being called from a continually running daemon. Imagine a
  -daemon process that when requested to process some script, reads it in,
  -compiles it as a subroutine, and finally executes it. On any subsequent
  -request, it'll just recall the already compiled subroutine. Hope that you
  -get the idea.
  +A need for two sets of controlling scripts (startup/shutdown) and
  +watchdogs.
   
  +<P><LI>
   <P>
  -The best thing you do when coding from scratch is to make it clean and use
  -packages. By ``make it clean'' we mean make certain that you <STRONG>use strict;</STRONG>
  -and that your script produces no warnings when tested via
  -<STRONG>perl -cw myscript.pl</STRONG>. As you go thru the notes you will understand why.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="What_s_different_about_modperl">What's different about modperl</A></H2></CENTER>
  +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>
  -There are a few things that behave differently under mod_perl. It's good to
  -know what they are.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Script_s_name_space">Script's name space</A></H3></CENTER>
  +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>
  -Scripts under Apache::Registry do not run in package <STRONG>main</STRONG>, they run in a unique name space based on the requested URI. For example,
  -if your URI is <STRONG>/perl/test.pl</STRONG> the package will be called 
  -<STRONG>Apache::ROOT::perl::test_2epl;</STRONG>
  +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>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H3></CENTER>
  +<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>
  -Just to make things clear before we go into detail: each server process has
  -its own <CODE>%INC</CODE> hash which is used to store information about its
  -compiled modules. The keys of the hash are the names of the modules or
  -parameters passed to <CODE>require().</CODE> The values are the real paths
  -to these modules. So if you do (assume it's in the <CODE>@INC</CODE> path)
  +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>  require &quot;./my/lib.pl&quot;;
  -</PRE>
   <P>
  -where <CODE>./my/lib.pl</CODE> is actually a <CODE>/home/httpd/perl/my/lib.pl</CODE>. The following entry will show up in the <CODE>%INC</CODE>
  +Meta: Hey, No personal experience here, only rumours. Please let me know if
  +I have missed some pros/cons here. Thanks!
   
  -<P>
  -<PRE>  $INC{&quot;./my/lib.pl&quot;} = &quot;/home/httpd/perl/my/lib.pl&quot;;
  -</PRE>
   <P>
  -I'm talking about single server child below!
  +The Advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -You can't have 2 identical module names running under the same server! Only
  -the first one <CODE>use()'d</CODE> or <CODE>require()'d</CODE> will be
  -compiled into the package, the request to the other identical module will
  -be skipped since server will think that it's already compiled. It'll be
  -already in child's %INC. (See <A HREF="././status.html#Watching_the_server">Watching the server</A> 
  -section to find out how you can know what is loaded and where)
  +All the advantages of the 2 servers scenario.
   
  +<P><LI>
   <P>
  -So if you have 
  +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>
  -<PRE>  cgi/tool1/Foo.pm 
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/Foo.pm 
  -  cgi/tool2/tool2.pl
  -</PRE>
   <P>
  -And both scripts do: <CODE>use Foo;</CODE> only the first one called will know about Foo, when you will call the
  -second script it will not know about Foo at all - it's like you've
  -forgotten to write <CODE>use Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to solve that kind of bug immediately.
  +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>
  -You will see the following in the error_log file:
  +Reported to be about 5 times faster then plain apache serving static
  +objects.
   
  -<P>
  -<PRE>  Undefined subroutine
  -  &amp;Apache::ROOT::perl::test_2epl::some_function called at
  -  /home/httpd/perl/test.pl line 10. 
  -</PRE>
  +</UL>
   <P>
  -The above is true for the files you require as well (assuming that the
  -required files do not declare a package). If you have:
  +The Disadvantages:
   
  -<P>
  -<PRE>  cgi/tool1/config.pl
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/config.pl
  -  cgi/tool2/tool2.pl
  -</PRE>
  +<UL>
  +<P><LI>
   <P>
  -And both scripts do:
  +Lacks some of apache's features, like access control, error redirection,
  +customizable log file formats, and so on.
   
  +</UL>
   <P>
  -<PRE>  use lib qw(.);
  -  require &quot;config.pl&quot;;
  -</PRE>
  +<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>
   <P>
  -Only the first one will do the require, all for the same reason that
  -<CODE>%INC</CODE> already includes the key ``config.pl''!
  +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 httpd_docs (e.g. <A
  +HREF="http://www.nowhere.com/images/test.gif">http://www.nowhere.com/images/test.gif</A>
  +) and 8080 -- for httpd_perl (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 httpd_docs server to port 81.)
   
   <P>
  -There are 3 workarounds for that: (make sure you read the whole item 3)
  +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:
   
  -<OL>
  +<UL>
   <P><LI>
   <P>
  -Place your library modules in a subdirectory structure so that they have
  -different path prefixes. The file system layout will be something like
  +Allow serving of static objects from the proxy's cache (objects that
  +previously were entirely served by the httpd_docs server).
   
  -<P>
  -<PRE>  cgi/tool1/Tool1/Foo.pm 
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/Tool2/Foo.pm 
  -  cgi/tool2/tool2.pl
  -</PRE>
  +<P><LI>
   <P>
  -And change the scripts:
  +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>
  -<PRE>  use Tool1::Foo;
  -  use Tool2::Foo;
  -</PRE>
  +<P><LI>
   <P>
  -and respectively, the package declaration in the modules: 
  +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>
  -<PRE>  package Tool1::Foo;
  -  package Tool2::Foo;
  -</PRE>
   <P>
  -For require:
  +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>
  -<PRE>  cgi/tool1/tool1-lib/config.pl
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/tool2-lib/config.pl
  -  cgi/tool2/tool2.pl
  -</PRE>
  +To make your 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><LI>
   <P>
  -And each script does respectively:
  +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>
  -<PRE>  use lib qw(.);
  -  require &quot;tool1-lib/config.pl&quot;;
  -</PRE>
  +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>
  -<PRE>  use lib qw(.);
  -  require &quot;tool2-lib/config.pl&quot;;
  - 
  -</PRE>
  +The disadvantages are:
  +
  +<UL>
   <P><LI>
   <P>
  -Another option is to use a full path to the script, so it'll be compiled
  -into the name of the key in the %INC;
  +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>  require &quot;/full/path/to/the/config.pl&quot;;
  -</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>
  -But then you lose portability! (I mean if you move the tool around in the
  -file system you will have to change the base dir)
  +Have I succeeded in convincing you that you want the proxy server?
   
  -<P><LI>
   <P>
  -Declare a package in the required files! (Of course it should be unique to
  -the rest of the package names you use!) The <CODE>%INC</CODE> will use the
  -package name for the key!
  +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>
  -But then you will have to use <STRONG>Package::function()</STRONG> method unless you will export the symbols from the <CODE>use()'d</CODE>
  -package like:
  +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>
  -<PRE>  use Package qw(:all_subs);
  -</PRE>
  +<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>
   <P>
  -This is a bad approach since it'll consume more memory for the current
  -process.
  +The Advantages:
   
  +<UL>
  +<P><LI>
   <P>
  -<STRONG>Important:</STRONG> This solution will only work if you have two scripts that
  -<CODE>require()</CODE> the same file! 
  +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>
  -<PRE>  cgi/tool1/config.pl
  -  cgi/tool1/tool_1.pl
  -  cgi/tool1/tool_2.pl
  -</PRE>
  +<P><LI>
   <P>
  -and both tool_1.pl and tool_2.pl do:   
  +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>
  -<PRE>  use lib qw(.);
  -  require &quot;config.pl&quot;;
  -</PRE>
  +<P><LI>
   <P>
  -Here playing with dir name or using the full path will not help! You must
  -declare a package inside the files that are being <CODE>require()d!</CODE>
  +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.
   
  -</OL>
  +</UL>
   <P>
  -Read also perlmodlib and perlmod manpages.
  +The Disadvantages:
   
  +<UL>
  +<P><LI>
   <P>
  -From the above discussion it should be clear that you can't run a
  -development and a production versions of the tools on the same server! You
  -have to run a separate server for each.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H3></CENTER>
  +<P><LI>
   <P>
  -Apache::Registry scripts cannot contain __END__ or __DATA__ tokens 
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Output_from_system_calls">Output from system calls</A></H3></CENTER>
  +<P><LI>
   <P>
  -Output of <STRONG>system</STRONG>, <STRONG>exec</STRONG>, and <STRONG>open PIPE "|program"</STRONG> calls will not be sent to the browser unless your Perl was configured with
  -sfio.
  +Memory usage. Squid uses quite a bit of memory.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Using_format_">Using format()</A></H3></CENTER>
  +<P><LI>
   <P>
  -Currently possible only if you have perl compiled with sfio
  +HTTP protocol level. Squid is pretty much a HTTP/1.0 server, which
  +seriously limits the deployment of HTTP/1.1 features.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Using_exit_">Using exit()</A></H3></CENTER>
  +<P><LI>
   <P>
  -Perl's <STRONG>exit()</STRONG> built-in function cannot be used in mod_perl scripts. Calling it causes the
  -server child to exit (which makes the whole idea of using mod_perl
  -irrelevant.) The <STRONG>Apache::exit()</STRONG> function should be used instead. 
  +HTTP headers / dates, freshness. The squid server might give out ``old''
  +pages, confusing downstream/client caches. Also chances are that you will
  +be giving out stale pages.
   
  +<P><LI>
   <P>
  -You might start your scripts by overriding the exit sub (if you use
  -<STRONG>Apache::exit()</STRONG> directly, you will have a problem testing the script from the shell, unless
  -you stuff <CODE>use Apache ();</CODE> into your code.) I use the following code:
  +Stability. Compared to plain web servers Squid is not the most stable.
   
  -<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'} ) ? 1 : 0;
  -  }
  -  use subs (exit);
  -  
  -  # Select the correct exit way
  -  ########
  -  sub exit{
  -      # Apache::exit(-2) will cause the server to exit gracefully,
  -      # once logging happens and protocol, etc  (-2 == Apache::Constants::DONE)
  -    $USE_MOD_PERL ? Apache::exit(0) : CORE::exit(0);
  -  }
  -</PRE>
  +</UL>
   <P>
  -Now each time the select code is called, the correct <STRONG>exit</STRONG>
  -will be chosen, whether you run the script as a CGI or from the shell.
  +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>
  -<STRONG>Note</STRONG> that if you run the script under <CODE>Apache::Registry</CODE>, <STRONG>The
  -Apache function `exit' overrides the Perl core built-in
  -function</STRONG>. While you see the <CODE>exit()</CODE> listed in <CODE>@EXPORT_OK</CODE>
  -of Apache package, Apache::Registry makes something you don't see and
  -imports this function for you. This means that if your script is running
  -under Apache::Registry handler (Apache::PerlRun as well), you don't have to
  -worry about <CODE>exit().</CODE>
  -
  -<P>
  -<STRONG>Note</STRONG> that if you still use CORE::exit() in your scripts running under modperl,
  -the child will exit, but neither proper exit nor logging will happen on the
  -way. CORE::exit() cuts off the server's legs... If you need to properly
  -shutdown the child , use $r-&gt;child_terminate (which sets the internal MaxRequestsPerChild so the child
  -will exit).
  +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>
  -You can accomplish this in 2 ways - in the Apache::Registry script:
   
  -<P>
  -<PRE>  Apache-&gt;request-&gt;child_terminate;
  -</PRE>
  -<P>
  -in httpd.conf:
   
   <P>
  -<PRE>  PerlFixupHandler &quot;sub { shift-&gt;child_terminate }&quot;
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Running_from_shell">Running from shell</A></H3></CENTER>
  +<CENTER><H1><A NAME="An_Apache_s_mod_proxy">An Apache's mod_proxy</A></H1></CENTER>
   <P>
  -Your scripts <CODE>*will</CODE> not* run from the command line (yet) unless
  -you use CGI::Switch or CGI.pm and 5.004+ and do not make any direct calls
  -to Apache-&gt;methods. 
  +I do not think the difference in speed between apache's <CODE>ProxyPass</CODE>
  +and squid 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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="I_O_is_different">I/O is different</A></H3></CENTER>
  -<P>
  -If you are using Perl 5.004 or better, most CGI scripts can run under
  -mod_perl untouched. If you're using 5.003, Perl's built-in
  -<CODE>read()</CODE> and <CODE>print()</CODE> functions do not work as they
  -do under CGI. If you're using CGI.pm, use $query-&gt;print instead of plain 'ol <CODE>print().</CODE>
  +The Advantages:
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A></H3></CENTER>
  +<UL>
  +<P><LI>
   <P>
  -By default, mod_perl does not send any headers by itself, however, you may
  -wish to change this (in httpd.conf):
  +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>
  -<PRE>  PerlSendHeader On
  -</PRE>
  +<P><LI>
   <P>
  -Now the response line and common headers will be sent as they are by
  -mod_cgi. And, just as with mod_cgi, PerlSendHeader will not send a
  -terminating newline, your script must send that itself, e.g.:
  +<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>
  -<PRE>  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +<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>
  -If you are using CGI.pm or CGI::Switch and <STRONG>print $q-&gt;header</STRONG> you do _not_ need PerlSendHeader On.
  +It does mod_perl output buffering like squid does. See the <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</A> notes for more details.
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H3></CENTER>
  +<P><LI>
   <P>
  -To run a Non Parsed Header CGI script under mod_perl, simply add to your
  -code:
  +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>  local $| = 1;
  -</PRE>
  +<P><LI>
   <P>
  -And if you normally set PerlSendHeader On, add this to your httpd.conf:
  +<CODE>ProxyPass</CODE> happens before the authentication phase, so you do not have to worry about
  +authenticating twice.
   
  -<P>
  -<PRE>  &lt;Files */nph-*&gt;
  -    PerlSendHeader Off
  -  &lt;/Files&gt;
  -</PRE>
  +<P><LI>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="BEGIN_blocks">BEGIN blocks</A></H3></CENTER>
  +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><LI>
   <P>
  -Perl executes BEGIN blocks during the compile time of code as soon as
  -possible. The same is true under mod_perl. However, since mod_perl normally
  -only compiles scripts and modules once -- either in the parent server or
  -once per-child -- BEGIN blocks in that code will only be run once. As
  -perlmod explains, once a BEGIN has run, it is immediately undefined. In the
  -mod_perl environment, this means BEGIN blocks will not be run during each
  -incoming request unless that request happens to be one that is compiling
  -the code.
  +The latest (from apache 1.3.6) Apache proxy accel mode reported to be very
  +stable.
   
  +</UL>
   <P>
  -Modules and files pulled in via require/use which contain BEGIN blocks will
  -be executed:
  +The Disadvantages:
   
   <UL>
   <P><LI>
   <P>
  -only once, if pulled in by the parent process.
  +Users reported that it might be a bit slow, but the latest version is fast
  +enough. (How fast is enough? :)
   
  -<P><LI>
  +</UL>
   <P>
  -once per-child process if not pulled in by the parent process.
  +For implementation see <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</A>.
   
  -<P><LI>
  -<P>
  -an additional time, once per-child process if the module is pulled in off
  -of disk again via Apache::StatINC.
  +<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>.
   
  -<P><LI>
  -<P>
  -an additional time, in the parent process on each restart if
  -PerlFreshRestart is On.
  +	     <HR>
  +	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.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/02/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>
   
  -<P><LI>
  -<P>
  -unpredictable if you fiddle with <CODE>%INC</CODE> yourself.
  +		<LI><A HREF="#Configuration_and_Compilation_of">Configuration and Compilation of the Sources.</A>
  +		<UL>
   
  -</UL>
  -<P>
  -Apache::Registry scripts which contain BEGIN blocks will be executed:
  +			<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>
   
  -<UL>
  -<P><LI>
  -<P>
  -only once, if pulled in by the parent process via Apache::RegistryLoader -
  -once per-child process if not pulled in by the parent process.
  +		<LI><A HREF="#Configuration_of_the_servers">Configuration of the servers</A>
  +		<UL>
   
  -<P><LI>
  -<P>
  -an additional time, once per-child process if the script file has changed
  -on disk.
  +			<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>
   
  -<P><LI>
  -<P>
  -an additional time, in the parent process on each restart if pulled in by
  -the parent process via Apache::RegistryLoader and PerlFreshRestart is On.
  +	</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="#Using_mod_proxy">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>
   </UL>
  -<P>
  -Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
  +<!-- INDEX END -->
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="END_blocks">END blocks</A></H3></CENTER>
  -<P>
  -As perlmod explains, an END subroutine is executed as late as possible,
  -that is, when the interpreter is being exited. In the mod_perl environment,
  -the interpreter does not exit until the server is shutdown. However,
  -mod_perl does make a special case for Apache::Registry scripts.
  +<HR>
   
  -<P>
  -Normally, END blocks are executed by Perl during its <STRONG>perl_run()</STRONG>
  -function, which is called once each time the Perl program is executed, e.g.
  -once per (mod_cgi) CGI scripts. However, mod_perl only calls
  -<STRONG>perl_run()</STRONG> once, during server startup. Any END blocks encountered during main server
  -startup, i.e. those pulled in by the PerlRequire or by any PerlModule, are
  -suspended and run at server shutdown, aka child_exit (requires apache
  -1.3b3+). 
  +	     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>
  -Any END blocks that are encountered during compilation of Apache::Registry
  -scripts <STRONG>are called after the script has completed</STRONG>
  -(not during the cleanup phase though) including subsequent invocations when
  -the script is cached in memory. All other END blocks encountered during
  -other Perl*Handler callbacks, e.g. PerlChildInitHandler, will be suspended
  -while the process is running and called during child_exit when the process
  -is shutting down. Module authors may be wish to use $r-&gt;register_cleanup as an alternative to END blocks if this behavior is not
  -desirable.
  +	     <HR>
   
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -The last paragraph is very important for the <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>.
  -
  +<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><H3><A NAME="Switches_w_T">Switches -w, -T</A></H3></CENTER>
  +<CENTER><H2><A NAME="Installation_in_10_lines">Installation in 10 lines</A></H2></CENTER>
   <P>
  -Normally when you run perl from the command line or have the shell invoke
  -it with `#!', you may choose to pass perl switch arguments such as <STRONG>-w</STRONG> or <STRONG>-T</STRONG>. Most command line arguments have a equivalent special variable. For
  -example, the <STRONG>$^W</STRONG> variable corresponds to the <STRONG>-w</STRONG>
  -switch. Consult perlvar for more details. With mod_perl it is also possible
  -to turn on warnings globally via the PerlWarn directive:
  +The Installation is very very simple (example of installation on Linux OS):
   
   <P>
  -<PRE>  PerlWarn On
  +<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/src
  +  % make install
   </PRE>
   <P>
  -You can turn it off with <CODE>local $^W = 0;</CODE> in your scripts on the local basis (or inside the block). If you write <CODE>$^W = 0;</CODE> you disable the warning mode everywhere, the same with <CODE>$^W = 1;</CODE>.
  +That's all!
   
   <P>
  -The switch which enables taint checks does not have a special variable, so
  -mod_perl provides the PerlTaintCheck directive to turn on taint checks. In
  -httpd.conf, enable with:
  +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>
  -<PRE>  PerlTaintCheck On
  -</PRE>
  +<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>
  -Now, any and all code compiled inside httpd will be taint checked.
  +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>
  -The environment variable PERL5OPT can be used to set additional perl
  -startup flags such as -d and -D. See
  -<A HREF="././modules.html#Apache_PerlRun_Run_unaltered_">Apache::PerlRun</A> .
  -
  +<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>
  -If you have the shebang line (#!/bin/perl -Tw) in your script, <STRONG>-w</STRONG>
  -will be honored (which means that you have turned the warn mode on for the
  -scope of this script, <STRONG>-T</STRONG> will produce a warning if
  -<CODE>PerlTaintCheck</CODE> is not <CODE>On</CODE>.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="strict_pragma">strict pragma</A></H2></CENTER>
  +<PRE>  % cd /usr/src
  +  % tar zvxf apache_x.xx.tar.gz
  +  % tar zvxf mod_perl-x.xx.tar.gz
  +</PRE>
   <P>
  -It's _absolutely_ mandatory (at least for development) to start all your
  -scripts with:
  +<CODE>chdir</CODE> to the mod_perl source directory:
   
   <P>
  -<PRE>  use strict;
  +<PRE>  % cd mod_perl-x.xx
   </PRE>
   <P>
  -If needed, you can always turn off the 'strict' pragma or a part of it
  -inside the block, e.g:
  +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>
  -<PRE>  {
  -    no strict 'refs';
  -    ... some code
  -  }
  +<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>
  -It's more important to have <STRONG>use strict;</STRONG> enabled under mod_perl than anywhere else. While it's not required, it is
  -strongly recommended, it will save you more time in the long run. And, of
  -course, clean scripts will still run under mod_cgi (plain CGI)!
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Turning_warnings_ON">Turning warnings ON</A></H2></CENTER>
   <P>
  -Have a <CODE>$^W=1</CODE> in the script or PerlWarn ON at the server configuration file. Turning the
  -warning on will save you a lot of troubles with debugging your code. Note
  -that first magic line <CODE>#!/perl -switches</CODE>
  -is ignored by mod_perl, so too are the switches you used to write there.
  +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>
  -If you need you can always turn off the warning with <CODE>$^W = 0</CODE> in your code if you have some section you don't want the perl compiler to
  -warn in.
  -
  +<PRE>  % make &amp;&amp; make test &amp;&amp; make install
  +</PRE>
   <P>
  -In production code, it can be a good idea to turn warnings off. Otherwise
  -if your code isn't very clean and spits a few lines of warnings here and
  -there, you will end up with a huge error_log file in a short time on the
  -loaded server. Also, enabling runtime warning checking has a small
  -performance impact -- in any script, not just under mod_perl -- so your
  -approach should be to enable warnings during development, and then disable
  -them when your code is production-ready.
  +Note that if <CODE>make</CODE> fails, neither <CODE>make test</CODE> nor <CODE>make
  +install</CODE> will be executed. If <CODE>make test</CODE> fails, <CODE>make install</CODE>
  +will be not executed.
   
   <P>
  -<CODE>use diagnostics;</CODE> can shed more light on the errors and warnings you see, but again, it's
  -better to not use <CODE>use diagnostics;</CODE>
  -in production, since otherwise you incur the overhead of the diagnostics
  -pragma. (You can run your script with -dDprof to check the overhead. See
  -Devel::Dprof for more info)
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="diagnostics_pragma">diagnostics pragma</A></H2></CENTER>
  +<PRE>  % cd ../apache_x.x.x/src
  +  % make install
  +</PRE>
   <P>
  -This is a Perl compiler pragma which forces verbose warning diagnostics.
  -Put at the start of your scripts:
  +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 they two important paths are:
   
   <P>
  -<PRE>  use diagnostics;
  +<PRE>  /usr/local/apache/bin/apachectl
  +  /usr/local/apache/conf/httpd.conf
   </PRE>
   <P>
  -This pragma turns on the -w mode, but gives you much better diagnostics of
  -the errors and warnings encountered. Generally it explains the reason for
  -warnings/errors you get, shows you an example of code where the same kind
  -of warning is being triggered, and tells you the remedy.
  -
  -<P>
  -Again, it's a bad idea to keep this in your production code, as it will
  -spit zillions of diagnostics lines into your error_log file. Also, it will
  -add significant overhead to the CGI's runtime. (I discovered this by using
  -Devel::DProf!)
  +Now the build and the installation processes are completed. Just configure <CODE>httpd.conf</CODE> and start the webserver.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Global_Variables">Global Variables</A></H2></CENTER>
  +<CENTER><H2><A NAME="Configuration_Process">Configuration Process</A></H2></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 <STRONG>@ISA</STRONG> or
  -<STRONG>$VERSION</STRONG> variables. In common practice, a combination of <STRONG>use strict</STRONG> and <STRONG>use vars</STRONG> keeps modules clean and reduces a bit of noise. However, <STRONG>use vars</STRONG> also creates aliases as the Exporter does, which eat up more space. When
  -possible, try to use fully qualified names instead of use vars. Example:
  +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>  package MyPackage;
  -  use strict;
  -  @MyPackage::ISA = qw(...);
  -  $MyPackage::VERSION = &quot;1.00&quot;;
  +<PRE>  % /usr/local/apache/bin/apachectl start
  +  % /usr/local/apache/bin/apachectl stop
   </PRE>
   <P>
  -vs.
  +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>  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>
  -
  -
  +Add the following configuration directives:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H2></CENTER>
  +<PRE>  Alias /perl/ /home/httpd/perl/
  +</PRE>
   <P>
  -To pass an environment variable from a configuration file, add to it:
  +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>  PerlSetEnv key val
  -  PerlPassEnv key
  +<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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H2></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="././obvious.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A> for more info.
  +Now put a test script into <CODE>/home/httpd/perl/</CODE> directory:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Memory_leakage">Memory leakage</A></H2></CENTER>
  +<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>
  -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. 
  +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>
  -Perl doesn't return the memory it acquired from the kernel. It does reuse
  -it though!
  -
  +<PRE>  % chown nobody /home/httpd/perl/test.pl
  +  % chmod u+rx   /home/httpd/perl/test.pl
  +</PRE>
   <P>
  -<STRONG>First example</STRONG> demonstrates reading a file:
  +Test that the script is running from the command line, by executing it:
   
   <P>
  -<PRE>  open IN, $file or die $!;
  -  $/ = undef; # will read the whole file in
  -  $content = &lt;IN&gt;;
  -  close IN;
  +<PRE>  % /home/httpd/perl/test.pl
   </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, making sure to provide a locking mechanism!)
  +You should see:
   
   <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. Now you have a very nice sub
  -<CODE>process()</CODE> 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>
  -Once I wrote the script that passed a content of the little DB to the
  -function and it was OK, but then the DB become huge - I had to make a
  -decision, whether to buy more memory or to rewrite the code. So it's better
  -to plan ahead and pass the variables by reference. There are few approaches
  -for that:
  -
  -<P>
  -<PRE>  sub process{
  -    my $content_r = shift; 
  -    ... some processing on $$content here
  -        ($$var_r - dereference the scalar)
  -        [nothing returned - the variable $content
  -         outside is already changed]
  -  }
  -  process(\$content);
  +<PRE>  Content-type: text/html
     
  -  @{$var_lr} - dereference an array
  -  %{$var_hr} = dereference a hash
  +  It worked!!!
   </PRE>
  -<P>
  -For more see <CODE>perldoc perlref</CODE>
  -
  -
  -
   <P>
  -Another approach would be to directly use the <CODE>@_</CODE> variable.
  -Using directly the <CODE>@_</CODE> array serves the job of passing by
  -reference!
  +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>  sub process{
  -    $_[0] =~ s/A/a/gs;
  -    ... some processing on $_[0] here
  -    [nothing returned - the variable $content
  -     outside is already changed]
  -  }
  -  process($content);
  +<PRE>  <A HREF="http://localhost/perl/test.pl">http://localhost/perl/test.pl</A>
   </PRE>
   <P>
  -From <CODE>perldoc perlsub</CODE>: The array <CODE>@_</CODE> 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)... 
  +Make sure that you have a loop-back device configured, if not -- use the
  +real server name for this test, for example:
   
   <P>
  -<STRONG>Third example</STRONG> demonstrates 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!!!).
  -
  +<PRE>  <A HREF="http://www.nowhere.com/perl/test.pl">http://www.nowhere.com/perl/test.pl</A>
  +</PRE>
   <P>
  -We will use DBI for this (assume we are already connected to the DB) (read
  -perldoc DBI for complete info):
  +You should see:
   
   <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>  It worked!!!
   </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!).
  -
   <P>
  -A better approach is to not accumulate the records, but rather print them
  -as they are fetched from the DB. Moreover, we use the <STRONG>bind_col</STRONG>
  -and <STRONG>$sth-&gt;fetchrow_arrayref</STRONG> (aliased to <STRONG>$sth-&gt;fetch</STRONG>) methods, to fetch the data in the fastest possible way. The example below
  -prints the TABLE with matched data, the only memory that is being used is a
  -@cols.
  +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>
  -<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>
  +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>
  -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 <STRONG>SELECT count(*) ...</STRONG> instead of <STRONG>'SELECT *
  -...</STRONG> to get the number of matched records.
  +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>
  -For those who think that <STRONG>$sth-&gt;rows</STRONG> will do the job, here is the quote from the DBI manpage: 
  +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.
   
  -<BLOCKQUOTE>
  +<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>
  +<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>
  -rows <CODE>$rv</CODE> = $sth-&gt;rows;
  +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>
  -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.
  +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>
  -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.
  +Make two subdirectories:
   
  -</BLOCKQUOTE>
  +<P>
  +<PRE>  % mkdir /usr/src/httpd_docs
  +  % mkdir /usr/src/httpd_perl
  +</PRE>
  +<P>
  +Put the Apache sources into a <CODE>/usr/src/httpd_docs</CODE> directory:
   
   <P>
  -As a bonus, I wanted to write a single sub that flexibly processes any
  -query, accepting: conditions, callback closure sub, select fields and
  -restrictions. 
  +<PRE>  % cd /usr/src/httpd_docs
  +  % gzip -dc /tmp/apache_x.x.x.tar.gz | tar xvf -
  +</PRE>
  +<P>
  +If you have a gnu tar:
   
   <P>
  -<PRE>  # $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>  % tar xvzf /tmp/apache_x.x.x.tar.gz
   </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: 
  +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>  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;)));
  -        }
  +<PRE>  % cd /usr/src/httpd_docs
     
  -      }  #  end of sub {}
  -  };  #  end of my $rsub = eval {
  +  % ls -l
  +  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_x.x.x/
   </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>.
  +Now we will prepare the <CODE>httpd_perl</CODE> server sources:
   
   <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>
  +<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>
  -At the beginning there was:
  +Time to decide on the desired directory structure layout (where the apache
  +files go):
   
   <P>
  -<PRE>  open IN, &quot;in.txt&quot; or die &quot;Cannot open in.txt for reading : $!\n&quot;;
  +<PRE>  ROOT = /usr/local
   </PRE>
   <P>
  -But it was not perfect for mod_perl, since you have had to make sure you
  -do:
  +The two servers can share the following directories (so we will not
  +duplicate data):
   
   <P>
  -<PRE>  close IN;
  +<PRE>  /usr/local/bin/
  +  /usr/local/lib
  +  /usr/local/include/
  +  /usr/local/man/
  +  /usr/local/share/
   </PRE>
   <P>
  -somewhere before the end of the script, since if you do not, you will get a
  -file descriptor leakage and unlock problem. Even if you do have it, but for
  -some reason the interpreter did not make it to it, because of various
  -reasons, such as user aborted script (<A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>) the leakage is still there.
  +<STRONG>Important:</STRONG> we assume that both servers are built from the same Apache source version.
   
   <P>
  -What do we do? We use <CODE>IO::File</CODE> (and other <CODE>IO::*</CODE>), which allows us to assign the file handler to variable, which can be <CODE>my()</CODE>
  -scoped. And when this variable goes out of scope the file or other file
  -system entity will be properly closed and unlocked (if was locked).
  +Servers store their specific files either in <CODE>httpd_docs</CODE> or
  +<CODE>httpd_perl</CODE> sub-directories:
   
   <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>  /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>
   <P>
  -But even faster and lighter technique is to use <CODE>Symbol.pm</CODE>:
  +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>
  -<PRE>  {
  -    my $fh = Symbol::gensym();
  -    open $fh, &quot;filename&quot; or die $!
  -  }
  -</PRE>
  +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>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</A></H1></CENTER>
  +<CENTER><H2><A NAME="Configuration_and_Compilation_of">Configuration and Compilation of the Sources.</A></H2></CENTER>
   <P>
  -When you start running your scripts under mod_perl, you might find yourself
  -in situation where a script seems to work, but sometimes it screws up. And
  -the more it runs without a restart, the more it screws up. Many times you
  -can resolve this problem very easily. You have to test your script under
  -with Server running as a 
  -<A HREF="././control.html#Running_server_in_a_single_mode">single process</A>.
  +Let's proceed with instalation. I will use x.x.x instead of real version
  +numbers so this document will never become obsolete :).
   
   <P>
  -Generally the problem you have is using global variables. Since global
  -variables don't change from one script invocation to another unless you
  -change them, you can find your scripts do ``fancy'' things.
  +<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>  % 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>
  +If you need some other modules, like mod_rewrite and mod_include (SSI), add
  +them here as well:
   
   <P>
  -The first example is amazing -- Web Services. Imagine that you enter some
  -site you have your account on (Free Email Account?). Now you want to see
  -what other users read.
  +<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>
  -You type in your name and passwd, and you expect to enter to your account,
  -but instead you enter the account of someone else. This is cool isn't it?
  -Is it a bug or feature. (For some of us it's a feature, while for others
  -it's a bug.) You say, why in the world does this happen? The answer is
  -simple: Global Variables. You have entered the account of someone who
  -happened to be served by the same server child as you. Because of sloppy
  -programming, a global variable was not reset at the beginning of the
  -program and voila, you can easily peek into other people's emails! You
  -would think that it can't happen, since you have entered the login and
  -passwd. I tell you, it happens! See for yourself:
  +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>  use vars ($authenticated);
  -  my $q = new CGI; 
  -  my $username = $q-&gt;param('username');
  -  my $passwd   = $q-&gt;param('passwd');
  -  authenticate($username,$passwd);
  -    # failed, break out
  -  die &quot;Wrong passwd&quot; unless $authenticated == 1;
  -    # user is OK, fetch user's data
  -  show_user($username);
  -  
  -  sub authenticate{
  -    my ($username,$passwd) = @_;
  -        # some checking
  -    $authenticated = 1 if (SOMETHING);
  -  }
  +<PRE>  % make
  +  % make install
   </PRE>
   <P>
  -Do you see the catch? With the code above, I can type in any valid username
  -and any dummy passwd and enter that user's account, if someone has
  -successfully entered his account before me using the same child process!
  -Since <STRONG>$authenticated</STRONG> is global - if it becomes 1 once it'll be 1 for the remainder of the
  -child's life!!! The solution is trivial -- reset <STRONG>$authenticated</STRONG> to 0 at the beginning of the program. (Or many other different solutions).
  -Of course this example is trivial -- but believe me it happens!
  +Rename <CODE>httpd</CODE> to <CODE>http_docs</CODE>
  +
  +
  +
  +<P>
  +<PRE>  % mv /usr/local/sbin/httpd_docs/httpd \
  +  /usr/local/sbin/httpd_docs/httpd_docs
  +</PRE>
  +<P>
  +Now update an <STRONG>apachectl</STRONG> utility to point to the renamed httpd via your favorite text editor or by
  +using perl:
  +
  +<P>
  +<PRE>  % perl -p -i -e 's|httpd_docs/httpd|httpd_docs/httpd_docs|' \
  +  /usr/local/sbin/httpd_docs/apachectl
  +</PRE>
  +</DL>
  +<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>
  +<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>.
   
   <P>
  -Just another little one liner that can spoil your day, assuming you forgot
  -to reset the <STRONG>$allowed</STRONG> variable. It works perfectly OK in plain mod_cgi:
  +Make sure the sources are clean:
   
   <P>
  -<PRE>  $allowed = 1 if $username eq 'admin';
  +<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>
  -But you will let any user to admin your system with the line above (again
  -assuming you have used the same child prior to some user request).
  +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>
  -Another good example is usage of the <STRONG>/o</STRONG> regular expression qualifier, which compiles a regular expression once, on
  -its first execution. This problem can be difficult to detect, as after
  -restarting the server each request you make will be served by a different
  -child process, and thus the regex pattern for that child will be compiled
  -fresh. Only when you make a request that happens to be served by a child
  -which has already cached the regexp will you see the problem. Generally you
  -miss that and when you press reload, you see that it works (with a new,
  -fresh child) and then it doesn't (with a child that already cached the
  -regexp and wouldn't recompile because of <STRONG>/o</STRONG>.)
  +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>
  -To make sure you don't miss these bugs always test your CGI in
  -<A HREF="././control.html#Running_server_in_a_single_mode">single process</A>. To solve this particular <STRONG>/o</STRONG> problem refer to <A HREF="././obvious.html#Compiled_Regular_Expressions">Compiled Regular Expressions</A>.
  -
  +<PRE>  % cd /usr/src/httpd_perl/mod_perl-x.xx
  +</PRE>
   <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_It_does">The Script is too dirty, It does the job and I can't afford rewriting it.</A></H1></CENTER>
  +<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>
  -You still can win from using mod_perl. 
  +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>
  -One approach is to replace the Apache::Registry handler with
  -Apache::PerlRun and define a new location (the script can reside in the
  -same directory on the disk. 
  +As with <CODE>httpd_docs</CODE> you might need other modules like
  +<CODE>mod_rewrite</CODE>, so add them here:
   
   <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>         --enable-module=rewrite
   </PRE>
   <P>
  -See <A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
  +Note: <CODE>PERL_STACKED_HANDLERS=1</CODE> is needed for <CODE>Apache::DBI</CODE>
   
   
   
   <P>
  -Another ``bad'', but working method is to set MaxRequestsPerChild 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
  -though, as the parent server will need to fork a new child each time one is
  -killed, but you can fiddle with MaxStartServers, MinSpareServers, to make
  -the parent spawn more servers ahead so the killed one will be immediately
  -replaced with the fresh one. Again, probably that's not what you want.
  +Now, build, test and install the <CODE>httpd_perl</CODE>.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A></H1></CENTER>
  +<PRE>  % make &amp;&amp; make test &amp;&amp; make install
  +</PRE>
   <P>
  -Apache::PerlRun gives you a benefit of preloaded perl and its modules. This
  -module's handler emulates the CGI environment, allowing programmers to
  -write scripts that run under CGI or mod_perl without any change. Unlike
  -Apache::Registry, the Apache::PerlRun handler does not cache the script
  -inside of a subroutine. Scripts will be ``compiled'' on each request. After
  -the script has run, its name space is flushed of all variables and
  -subroutines. Still, you don't have the overhead of loading the perl and
  -compilation time of the standard modules (If your script is very light, but
  -uses lots of standard modules - you will see no difference between
  -Apache::PerlRun and Apache::Registry !).
  +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>
  -Be aware though, that if you use packages that use internal variables that
  -have circular references, they will be not flushed!!!
  +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>
  -Apache::PerlRun only flushes your script's name space, which does not
  -include any other required packages' name spaces. If there's a reference to
  -a <STRONG>my()</STRONG> scoped variable that's keeping it from being DESTROYed after leaving the
  -eval scope (of Apache::PerlRun), that cleanup might not be taken care of
  -until the server is shutdown and <CODE>perl_destruct()</CODE> is run, which
  -always happens after running command line scripts. Consider this example:
  +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>
  -<PRE>  package Foo;
  -  sub new { bless {} }
  -  sub DESTROY {
  -    warn &quot;Foo-&gt;DESTROY\n&quot;;
  -  }
  -  
  -  eval &lt;&lt;'EOF';
  -  package my_script;
  -  my $self = Foo-&gt;new;
  -  #$self-&gt;{circle} = $self;
  -  EOF
  -  
  -  print $@ if $@;
  -  print &quot;Done with script\n&quot;;
  -</PRE>
  +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>
  -First you'll see:
  +Now rename the <CODE>httpd</CODE> to <CODE>httpd_perl</CODE>:
   
   <P>
  -<PRE>  Foo-&gt;DESTROY
  -  Done with script
  +<PRE>  % mv /usr/local/sbin/httpd_perl/httpd \
  +  /usr/local/sbin/httpd_perl/httpd_perl
   </PRE>
   <P>
  -Then, uncomment the line where <CODE>$self</CODE> makes a circular
  -reference, and you'll see:
  +Update the apachectl utility to point to renamed httpd name:
   
   <P>
  -<PRE>  Done with script
  -  Foo-&gt;DESTROY
  +<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>
  -In this case, under mod_perl you wouldn't see 'Foo-&gt;DESTROY' until the
  -server shutdown, or your module properly took care of things.
  +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><H1><A NAME="Redirecting_Errors_to_Client_ins">Redirecting Errors to Client instead of error_log</A></H1></CENTER>
  +<CENTER><H3><A NAME="Basic_httpd_docs_Server_s_Config">Basic httpd_docs Server's Configuration</A></H3></CENTER>
   <P>
  -To trap all/most Perl run-time errors and send the output to the client
  -instead of Apache's error log add this line to your script.
  +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>
  -<PRE>  use CGI::Carp qw(fatalsToBrowser);
  +Start the server with:
  +
  +<P>
  +<PRE>  /usr/local/sbin/httpd_docs/apachectl start
   </PRE>
   <P>
  -Refer to <CODE>CGI::Carp</CODE> man page for more related info.
  +<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.
   
   <P>
  -Also you can write your custom DIE/WARN signal handler. I don't want users
  -to see the error message, but I want it to be emailed to me if it's severe
  -enough. The handler traps various errors and performs accordingly to the
  -defined logic. My handler was written for the modperl environment, but
  -works correctly when is being called from the shell. A stripped version of
  -the code is shown here:
  +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 &lt;8080&gt;. 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.
   
   <P>
  -<PRE>  # assign the DIE sighandler to call mydie(error_message) whenever a
  -  # die() sub is being called. Can be added anywhere in the code.
  -  local $SIG{'__DIE__'} = \&amp;mydie;
  -  
  -Do not forget the C&lt;local()&gt;, unless you want this signal handler to
  -be invoked every time any scripts dies (Even those where this
  -treatment is undesirable)
  -</PRE>
  +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#Using_mod_proxy">Using mod_proxy</A>.
  +
   <P>
  -<PRE>  # and the handler itself
  -  sub mydie{
  -    my $why = shift;
  -  
  -    my $UNDER_MOD_PERL = ( (exists $ENV{'GATEWAY_INTERFACE'} 
  -                           and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/)
  -                         or exists $ENV{'MOD_PERL'} ) ? 1 : 0;
  -  
  -    chomp $why;
  -    my $orig_why = $why;                # an ascii copy for email report
  -  
  -    # handle the shell execution case (so we will not get all the HTML)
  -    print(&quot;Error: $why\n&quot;), exit unless $UNDER_MOD_PERL;
  -  
  -    my $should_email = 0;
  -    my $message = '';
  -  
  -    $why =~ s/[&lt;&amp;&gt;]/&quot;&amp;#&quot;.ord($&amp;).&quot;;&quot;/ge;    # entity escape
  -  
  -    # Now we need to trap various kinds of errors, that come from CGI.pm
  -    # And we don't want these errors to be emailed to us, since
  -    # these aren't programmatical errors
  -    if ($orig_why =~ /Client attempted to POST (\d+) bytes/o) {
  -  
  -      $message = qq{
  -                  You can not POST messages bigger than 
  -                  @{[1024*$c{max_image_size}]} bytes.&lt;BR&gt;
  -                  You have tried to post $1 bytes&lt;BR&gt;
  -                  If you are trying to upload an image, make sure its size is not 
  -                  bigger than @{[1024*$c{max_image_size}]} bytes.&lt;P&gt;
  -                  Thank you!
  -                 };
  -  
  -    } elsif ($orig_why =~ /Malformed multipart POST/o) {
  -  
  -      $message = qq{
  -                  Have you tried to upload an image in the wrong way?&lt;P&gt;
  -                  To sucessfully upload an image you must use a browser that supports
  -                  image upload and use the 'Browse' button to select that image.
  -                  DO NOT type the path to the image into the upload field.&lt;P&gt;
  -                  Thank you!
  -                 };
  -  
  -    } elsif ($orig_why =~ /closed socket during multipart read/o) {
  -  
  -      $message = qq{
  -                  Have you pressed a 'STOP' button?&lt;BR&gt;
  -                  Please try again!&lt;P&gt;
  -                  Thank you!
  -                 };
  -  
  -    } else {
  -  
  -      $message = qq{
  -                    &lt;B&gt;There is no action to be performed on your side, since
  -                  the error report has been already sent to webmaster. &lt;BR&gt;&lt;P&gt;
  -                  &lt;B&gt;Thank you for your patience!&lt;/B&gt;
  -                 };
  -  
  -      $should_email = 1;
  -    }
  -  
  -  
  -    print qq|Content-type: text/html
  -  
  -  &lt;HTML&gt;&lt;BODY BGCOLOR=&quot;white&quot;&gt;
  -  &lt;B&gt;Oops, An error has happened.&lt;/B&gt;&lt;P&gt;
  -    |;  
  -  
  -    print $message;
  -  
  -      # send email report if appropriate
  -    if ($should_email){
  -  
  -        # import sendmail subs
  -      use Mail ();
  -        # prepare the email error report:
  -      my $subject =&quot;Error Report&quot;;
  -      my $body = qq|
  -    An error has happened:
  -  
  -    $orig_why
  -  
  -      |;
  -  
  -        # send error reports to admin and author
  -      send_mail($c{email}{'admin'},$c{email}{'admin'},$subject,$body);
  -      send_mail($c{email}{'admin'},$c{email}{'author'},$subject,$body);
  -      print STDERR &quot;[&quot;.scalar localtime().&quot;] [SIGDIE] Sending Error Email\n&quot;;
  -    }
  -  
  -       # print to error_log so we will know we've sent
  -    print STDERR &quot;[&quot;.scalar localtime().&quot;] [SIGDIE] $orig_why \n&quot;;
  -  
  -    exit 1;
  -  }                             # end of sub mydie
  -  
  -</PRE>
  +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.
  +
   <P>
  -You may have noticed that I trap the CGI.pm's <CODE>die()</CODE> calls
  -here, I don't see any reason why my users should see an ugly error
  -messages, but that's the way CGI.pm written. The workaround is to trap them
  -myself.
  +First, you need to specify the location where all mod_perl scripts will be
  +located.
   
   <P>
  -Please note that as of ver 2.49, CGI.pm provides a <CODE>cgi_error()</CODE>
  -method to print the errors and wouldn't <CODE>die()</CODE> unless you want
  -it.
  +Add the following configuration directive:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Finding_the_line_number_the_erro">Finding the line number the error/warning has been triggered at</A></H1></CENTER>
  +<PRE>    # mod_perl scripts will be called from
  +  Alias /perl/ /usr/local/myproject/perl/
  +</PRE>
   <P>
  -<CODE>Apache::Registry</CODE>, <CODE>Apache::PerlRun</CODE> and modules that compile-via-eval confuse the line numbering. Other files
  -that are read normally by Perl from disk have no problem with file
  -name/line number.
  +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>.
   
   <P>
  -If you compile with the experimental <STRONG>PERL_MARK_WHERE=1</STRONG>, it shows you ``exactly'' where this is happening. Generally compiler
  -makes a shift in its line counter. You can always stuff your code with
  -special compiler directives, to reset its counter to the value you will
  -tell. At the beginning of the line you should write (the '#' in column 1):
  +Now we should configure the <CODE>/perl</CODE> location.
   
   <P>
  -<PRE>  #line 298 myscript.pl
  -  or 
  -  #line 890 some_label_to_be_used_in_the_error_message
  +<PRE>  PerlModule Apache::Registry
   </PRE>
   <P>
  -The label is optional - the filename of the script will be used by default.
  -This specifies the line number of the <STRONG>following</STRONG> line, not the line the directive is on. You can use a little script to
  -stuff every N lines of your code with these directives, but then you will
  -have to rerun this script every time you add or remove code lines. The
  -script:
  +<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.
   
   <P>
  -<PRE>    &lt;META&gt;
  -        This example was double incrementing $counter.
  -        I took the second increment out -- sgr.
  -    &lt;/META&gt;
  -</PRE>
  +<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.
  +
   <P>
  -<PRE>  #!/usr/bin/perl
  -  # Puts Perl line markers in a Perl program for debugging purposes.  
  -  # Also takes out old line markers.
  -  die &quot;No filename to process.\n&quot; unless @ARGV;
  -  my $filename = $ARGV[0];
  -  my $lines = 100;
  -  open IN, $filename or die &quot;Cannot open file: $filename: $!\n&quot;;
  -  open OUT, &quot;&gt;$filename.marked&quot;
  -      or die &quot;Cannot open file: $filename.marked: $!\n&quot;;
  -  my $counter = 1;
  -  while (&lt;IN&gt;) {
  -    print OUT &quot;#line $counter\n&quot; unless $counter++ % $lines;
  -    next if $_ =~ /^#line /;
  -    print OUT $_;
  -  }
  -  close OUT;
  -  close IN;
  -  chmod 0755, &quot;$filename.marked&quot;;
  -</PRE>
  +This is only a very basic configuration. <A HREF="././config.html#">Server Configuration</A> section covers the rest of the details.
  +
   <P>
  -To have a complete trace of calls add:
  +Now start the server with:
   
   <P>
  -<PRE>  use Carp ();
  -  local $SIG{__WARN__} = \&amp;Carp::cluck;
  +<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="Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Running_2_webservers_and_squid_i">Running 2 webservers and squid in httpd accelerator mode</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_speling or whatever modules you have used in your
  -server, all the core routines and so on. A much wiser approche 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
  -function or methods to call from CGI script. Just making a
  -<CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
  -should be loaded again for this extenal program to run.
  +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>
  -Basically, you would do:
  +First, lets 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>
  -<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> :
  +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>
  -<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>
  +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>
  -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.
  +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>
  -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).
  +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>
  -Also, the communication is only one way.
  +<PRE>  httpd_accel_host virtual
  +</PRE>
  +<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>
  -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>.
  +<PRE>  httpd_accel_port 81
  +</PRE>
  +<P>
  +And as described before, squid listens to port 80.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A></H1></CENTER>
  +<PRE>  http_port 80
  +</PRE>
   <P>
  -The <CODE>Apache::print()</CODE> routine has to gather up the headers that your script outputs, in order to
  -pass them to <CODE>$r-&amp;gt;send_http_header</CODE>. This happens in <CODE>src/modules/perl/Apache.xs</CODE> (<CODE>print</CODE>) and
  -<CODE>Apache/Apache.pm</CODE> (<CODE>send_cgi_header</CODE>). There is a shortcut in there, namely the assumption that each print
  -statement contains one or more complete headers. If for example you used to
  -generate a
  -<CODE>Set-Cookie</CODE> header by multiply <CODE>print()</CODE> statements, like:
  +We do not use icp (icp used for cache sharing between neighbor machines),
  +which is more relevant in the proxy mode.
   
   <P>
  -<PRE>   print &quot;Content-type: text/html\n&quot;;
  -   print &quot;Set-Cookie: iscookietext\; &quot;;
  -   print &quot;expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; &quot;;
  -   print &quot;path=\/\; &quot;;
  -   print &quot;domain=\.mmyserver.com\; &quot;;
  -   print &quot;\n\n&quot;;
  -   print &quot;hello&quot;;
  +<PRE>  icp_port 0
   </PRE>
   <P>
  -your generated <CODE>Set-Cookie</CODE> header is split over a number of print statements and gets lost. Try this:
  +<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>
  -<PRE>   print &quot;Content-type: text/html\n&quot;;
  -   my $cookie = &quot;Set-Cookie: iscookietext\; &quot;;
  -   $cookie .= &quot;expires=Wednesday, 09-Nov-1999 00:00:00 GMT\; &quot;;
  -   $cookie .= &quot;path=\/\; &quot;;
  -   $cookie .= &quot;domain=\.mmyserver.com\; &quot;;
  -   print $cookie;
  -   print &quot;\n\n&quot;;
  -   print &quot;hello&quot;;
  +<PRE>  hierarchy_stoplist /cgi-bin /perl
   </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>
  -	     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>
  +Now we tell squid not to cache dynamic pages.
   
  -	     <HR>
  -	     [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]
  +<P>
  +<PRE>  acl QUERY urlpath_regex /cgi-bin /perl
  +  no_cache deny QUERY
  +</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. 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.
   
  -<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 06/12/1999
  -      </FONT>
  -    </B>
  -  </TD>
  +<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.
   
  -  <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>
  +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.
   
  -  <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>
  +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).
   
  -</BODY>
  -</HTML>
  -	    
  +<P>
  +<PRE>  # debug_options ALL, 1, 28, 9
  +</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.
   
  -<HR SIZE=6>
  -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  -<HTML>
  -<HEAD>
  -   <TITLE>mod_perl guide: Performance. Benchmarks.</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>
  -Performance. Benchmarks.</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="porting.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>
  +<P>
  +<PRE>  redirect_program /usr/lib/squid/redirect.pl
  +  redirect_children 10
  +  redirect_rewrites_host_header off
  +</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.
   
  -	<LI><A HREF="#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
  -	<UL>
  +<P>
  +<PRE>  request_size 1000 KB
  +</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.
   
  -		<LI><A HREF="#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A>
  -	</UL>
  +<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
  +</PRE>
  +<P>
  +Since squid should be run as non-root user, you need these if you are
  +invoking the squid as root.
   
  -	<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
  -	<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
  -	<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</A>
  -	<LI><A HREF="#How_can_I_find_if_my_modperl_scr">How can I find if my modperl scripts have memory leaks (and where)</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>
  -	<LI><A HREF="#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
  -	<UL>
  +<P>
  +<PRE>  cache_effective_user squid
  +  cache_effective_group squid
  +</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.
   
  -		<LI><A HREF="#Developers_Talk">Developers Talk</A>
  -		<LI><A HREF="#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
  -		<LI><A HREF="#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
  -		<LI><A HREF="#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
  -	</UL>
  +<P>
  +<PRE>  cache_mem 20 MB
  +</PRE>
  +<P>
  +Keep pools of allocated (but unused) memory available for future use. Read
  +more about it in the squid documents.
   
  -	<LI><A HREF="#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  -	<UL>
  +<P>
  +<PRE>  memory_pools on
  +</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.
   
  -		<LI><A HREF="#Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench </A>
  -		<LI><A HREF="#Tuning_with_crashme_script">Tuning with crashme script</A>
  -		<LI><A HREF="#Choosing_MaxClients">Choosing MaxClients</A>
  -		<LI><A HREF="#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A>
  -		<LI><A HREF="#Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A>
  -		<LI><A HREF="#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
  -	</UL>
  +<P>
  +<PRE>  cachemgr_passwd disable shutdown
  +  #cachemgr_passwd none all
  +</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):
   
  -	<LI><A HREF="#Preopen_DB_connection_at_server_">Preopen DB connection at server startup:</A>
  -	<LI><A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>
  -	<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>
  -</UL>
  -<!-- INDEX END -->
  +<P>
  +<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>
  +<PRE>      # send it unchanged to plain apache server (http_docs)
  +    print;
  +  }
  +</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?
  +
  +<P>
  +A few notes regarding redirector script:
  +
  +<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.
  +
  +<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.
   
  -<HR>
  +<P>
  +Now it is time to restart the server, at linux I do it with:
   
  -	     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>
  +<PRE>  /etc/rc.d/init.d/squid restart
  +</PRE>
  +<P>
  +Now the setup is complete ...
   
  -	     <HR>
  +<P>
  +Almost... When you try the new setup, you will be surprised and upset to
  +discover the 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 than it will bypass the squid server and the hard work we went
  +through was just a waste of time? The solution is to run both squid and
  +httpd_docs on 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><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A></H1></CENTER>
  +<PRE>  Port 80
  +  BindAddress 127.0.0.1
  +  Listen 127.0.0.1:80
  +</PRE>
   <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
  -be able to share the code space used by these modules. Just add the
  -following directives into <CODE>httpd.conf</CODE>:
  +Modify the <CODE>squid.conf</CODE>:
   
   <P>
  -<PRE>  PerlModule CGI;
  -  PerlModule DBI;
  +<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>
  +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.
  +
   <P>
  -But even better to create a separate startup file (with regular perl code)
  -and put there things like:
  +You must also have in the <CODE>/etc/hosts</CODE> an entry (most chances that it's already there):
   
   <P>
  -<PRE>  use DBI;
  -  use Carp;
  +<PRE>  127.0.0.1  localhost.localdomain   localhost
   </PRE>
   <P>
  -Then you <CODE>require()</CODE> this file with help of <CODE>PerlRequire</CODE> directive from <CODE>httpd.conf</CODE>, before the rest of the mod_perl configuration directives:
  +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. 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>
  -<PRE>  PerlRequire /path/to/start-up.pl
  -</PRE>
  +&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>
  -<CODE>CGI.pm</CODE> is a special case. Ordinarily <CODE>CGI.pm</CODE> autoloads most of its functions on an as-needed basis. This speeds up the
  -loading time by deferring the compilation phase. However, if you are using
  -mod_perl, FastCGI or another system that uses a persistent Perl
  -interpreter, you will want to precompile the methods at initialization
  -time. To accomplish this, call the package function <CODE>compile()</CODE>
  -like this:
  +See <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</A> for information about
  +<CODE>X-Forwarded-For</CODE>.
   
   <P>
  -<PRE>    use CGI ();
  -    CGI-&gt;compile(':all');
  +To save you some keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
  +
  +<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
  +  
  +  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>
  -The arguments to <CODE>compile()</CODE> are a list of method names or sets, and are identical to those accepted by
  -the use operator. Note that in most cases you will want to replace <CODE>':all'</CODE> with the tags' names you really use in your code. 
  +Note that all directives should start at the beginning of the line.
   
   <P>
  -You can also preload the Registry scripts. See <A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>.
  +<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.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A></H2></CENTER>
  +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>
  -I have conducted a few tests to benchmark the memory usage when some
  -modules are preloaded. The first set of tests checks the memory use with
  -Library Perl Module preload (only <CODE>CGI.pm</CODE>). The second set checks the compile method of <CODE>CGI.pm</CODE>. The third test checks the benefit of Library Perl Module preload but a
  -few of them (to see more memory saved) and also the effect of precompiling
  -the Registry modules with <CODE>Apache::RegistryLoader</CODE>.
  +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>
  ---------------------------------------------------------------------------------
  +The modified configuration (see the explanations in the previous section):
   
  +<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>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Using_mod_proxy">Using mod_proxy</A></H1></CENTER>
  +<P>
  +Now we will talk about apache's mod_proxy and understand how it works.
   
   <P>
  -1. In the first test, the following script was used:
  +The server on port 80 answers http requests directly and proxies the
  +mod_perl enabled server in the following way:
   
   <P>
  -<PRE>  use strict;
  -  use CGI ();
  -  my $q = new CGI;
  -  print $q-&gt;header;
  -  print $q-&gt;start_html,$q-&gt;p(&quot;Hello&quot;);
  +<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>
  -&lt;Server restarted&gt;
  +<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>
  -Before the <CODE>CGI.pm</CODE> preload: (No other modules preloaded)
  +You can control the buffering feature with <CODE>ProxyReceiveBufferSize</CODE>
  +directive:
   
   <P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      87004  0.0  0.0 1060 1524      - A    16:51:14  0:00 httpd
  -  httpd    240864  0.0  0.0 1304 1784      - A    16:51:13  0:00 httpd
  +<PRE>  ProxyReceiveBufferSize 1048576
   </PRE>
   <P>
  -After running a script which uses CGI's methods (no imports):
  +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>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root     188068  0.0  0.0 1052 1524      - A    17:04:16  0:00 httpd
  -  httpd     86952  0.0  1.0 2520 3052      - A    17:04:16  0:00 httpd
  -</PRE>
  +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>
  -Observation: child httpd has grown up by 1268K
  +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>
  -&lt;Server restarted&gt;
  +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>
  -After the <CODE>CGI.pm</CODE> preload:
  +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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root     240796  0.0  0.0 1456 1552      - A    16:55:30  0:00 httpd
  -  httpd     86944  0.0  0.0 1688 1800      - A    16:55:30  0:00 httpd
  +<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>
   <P>
  -after running a script which uses CGI's methods (no imports):
  +And in <CODE>httpd.conf</CODE>:
   
   <P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      86872  0.0  0.0 1448 1552      - A    17:02:56  0:00 httpd
  -  httpd    187996  0.0  1.0 2808 2968      - A    17:02:56  0:00 httpd
  +<PRE>  PerlPostReadRequestHandler My::ProxyRemoteAddr
   </PRE>
   <P>
  -Observation: child httpd has grown up by 1168K, 100K less then without
  -preload - good!
  +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>
  -&lt;Server restarted&gt;
  +From that point on, the remote IP address is correct. You should be able to
  +access <CODE>REMOTE_ADDR</CODE> as usual.
   
   <P>
  -After <CODE>CGI.pm</CODE> preloaded and compiled with CGI-&gt;compile(':all');
  +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>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      86980  0.0  0.0 2836 1524      - A    17:05:27  0:00 httpd
  -  httpd    188104  0.0  0.0 3064 1768      - A    17:05:27  0:00 httpd
  -</PRE>
  +<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>
   <P>
  -After running a script which uses CGI's methods (no imports):
  +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>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      86980  0.0  0.0 2828 1524      - A    17:05:27  0:00 httpd
  -  httpd    188104  0.0  1.0 4188 2940      - A    17:05:27  0:00 httpd
  +<PRE>  perl Makefile.PL USE_DSO=1 ...
   </PRE>
   <P>
  -Observation: child httpd has grown up by 1172K No change! So what does
  -CGI-&gt;compile(':all') help? I think it's because we never use all of the
  -methods CGI provides - so in real use it's faster. So you might want to
  -compile only the tags you are about to use - then you will benefit for
  -sure.
  +If you run <CODE>./configure</CODE> from apache source do not forget to add:
  +<CODE>--enable-shared=perl</CODE>
   
  -<P>
  ---------------------------------------------------------------------------------
   
   
   <P>
  -2. I have tried the second test to find it. I run the script:
  +Then just add the <CODE>LoadModule</CODE> directive into your <CODE>httpd.conf</CODE>.
   
  -<P>
  -<PRE>  use strict;
  -  use CGI qw(:all);
  -  print header,start_html,p(&quot;Hello&quot;);
  -</PRE>
   <P>
  -&lt;Server restarted&gt;
  +You will find a complete explanation in the <CODE>INSTALL.apaci</CODE> pod which can be found in the mod_perl distribution.
   
   <P>
  -After <CODE>CGI.pm</CODE> was preloaded and NOT compiled with CGI-&gt;compile(':all'):
  +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>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      17268  0.0  0.0 1456 1552      - A    18:02:49  0:00 httpd
  -  httpd     86904  0.0  0.0 1688 1800      - A    18:02:49  0:00 httpd
  -</PRE>
  +<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>
  -After running a script which imports symbols (all of them):
  +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>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      17268  0.0  0.0 1448 1552      - A    18:02:49  0:00 httpd
  -  httpd     86904  0.0  1.0 2952 3112      - A    18:02:49  0:00 httpd
  -</PRE>
   <P>
  -Observation: child httpd has grown up by 1264K
  +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>
  -&lt;Server restarted&gt;
  +<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>.
   
  -<P>
  -After <CODE>CGI.pm</CODE> was preloaded and compiled with CGI-&gt;compile(':all'):
  +	     <HR>
  +	     [    <A HREF="strategy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="install.html">Next</A>      ]
   
  -<P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      86812  0.0  0.0 2836 1524      - A    17:59:52  0:00 httpd
  -  httpd     99104  0.0  0.0 3064 1768      - A    17:59:52  0:00 httpd
  -</PRE>
  -<P>
  -After running a script which imports symbols (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 07/02/1999
  +      </FONT>
  +    </B>
  +  </TD>
   
  -<P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      86812  0.0  0.0 2832 1436      - A    17:59:52  0:00 httpd
  -  httpd     99104  0.0  1.0 4884 3636      - A    17:59:52  0:00 httpd
  -</PRE>
  -<P>
  -Observation: child httpd has grown by 1868K. Why? Isn't
  -<CODE>CGI::compile(':all')</CODE> supposed to make children to share the compiled code with parent? It does
  -works as advertised, but if you pay attention in the code we have called
  -only three <CODE>CGI.pm</CODE>'s methods - just saying <CODE>use CGI qw(:all)</CODE> doesn't mean we compile the all available methods - we just import their
  -names. So actually this test is misleading. Execute <CODE>compile()</CODE> only on the methods you are actually using and then you will see the
  -difference.
  +  <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>
  ---------------------------------------------------------------------------------
  +  <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>
  +	    
   
  -<P>
  -3. The third script:
  +<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>
  -<PRE>  use strict;
  -  use CGI;
  -  use Data::Dumper;
  -  use Storable;
  -  [and many lines of code, lots of globals - so the code is huge!]
  -</PRE>
  -<P>
  -&lt;Server restarted&gt;
  +	<LI><A HREF="#Configuration_and_Installation">Configuration and Installation</A>
  +	<UL>
   
  -<P>
  -Nothing preloaded at startup:
  +		<LI><A HREF="#perl">perl</A>
  +		<LI><A HREF="#apache">apache</A>
  +		<LI><A HREF="#mod_perl">mod_perl</A>
  +	</UL>
   
  -<P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      90962  0.0  0.0 1060 1524      - A    17:16:45  0:00 httpd
  -  httpd     86870  0.0  0.0 1304 1784      - A    17:16:45  0:00 httpd
  -</PRE>
  -<P>
  -Script using CGI (methods), Storable, Data::Dumper called:
  +	<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
  +	<UL>
   
  -<P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      90962  0.0  0.0 1064 1436      - A    17:16:45  0:00 httpd
  -  httpd     86870  0.0  1.0 4024 4548      - A    17:16:45  0:00 httpd
  -</PRE>
  -<P>
  -Observation: child httpd has grown by 2764K
  +		<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>
  -&lt;Server restarted&gt;
  +	<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_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>
   
  -<P>
  -Preloaded CGI (compiled), Storable, Data::Dumper at startup:
  +		<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>
   
  -<P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      26792  0.0  0.0 3120 1528      - A    17:19:21  0:00 httpd
  -  httpd     91052  0.0  0.0 3340 1764      - A    17:19:21  0:00 httpd
  -</PRE>
  -<P>
  -Script using CGI (methods), Storable, Data::Dumper called
  +	<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  +</UL>
  +<!-- INDEX END -->
   
  -<P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      26792  0.0  0.0 3124 1440      - A    17:19:21  0:00 httpd
  -  httpd     91052  0.0  1.0 6568 5040      - A    17:19:21  0:00 httpd
  -</PRE>
  -<P>
  -Observation: child httpd has grown by 3276K. Great difference: 512K less!!!
  +<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>.
   
  -<P>
  -&lt;Server restarted&gt;
  +	     <HR>
   
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -All the above modules + the above script PreCompiled with
  -<CODE>Apache::RegistryLoader</CODE> at startup:
  -
  +<CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
   <P>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      43224  0.0  0.0 3256 1528      - A    17:23:12  0:00 httpd
  -  httpd     26844  0.0  0.0 3488 1776      - A    17:23:12  0:00 httpd
  -</PRE>
  +<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>
  -Script using CGI (methods), Storable, Data::Dumper called:
  +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>
  -<PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  -  root      43224  0.0  0.0 3252 1440      - A    17:23:12  0:00 httpd
  -  httpd     26844  0.0  1.0 6748 5092      - A    17:23:12  0:00 httpd
  +<PRE>  Do you wish to use dynamic loading? [y]
   </PRE>
   <P>
  -Observation: child httpd has grown even more 3316K ! Does not seem to be
  -good!
  +Answer <CODE>y</CODE> to be able to load dynamically Perl Modules extensions.
   
   <P>
  -<STRONG>Summary</STRONG>:
  +<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>
  +<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.
   
   <P>
  -1. Library Perl Modules Preloading gave good results everywhere.
  +<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>
  +<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>
  +Now we come to the main point of this document.
   
   <P>
  -2. <CODE>CGI.pm</CODE>'s <CODE>compile()</CODE> method seems to use even more memory. It's because we never use all of the
  -methods CGI provides. Do <CODE>compile()</CODE>
  -only the tags that you are going to use and you will save the overhead of
  -the first call for each has not yet been called method, and the memory -
  -since compiled code will be shared across all the children.
  +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>
  -3. <CODE>Apache::RegistryLoader</CODE> might make scripts load faster on the first request after the child has
  -just started but the memory usage is worse!!! See the numbers by yourself.
  +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>
  -HW/SW used : The server is apache 1.3.2, mod_perl 1.16 running on AIX 4.1.5
  -RS6000 1G RAM.
  +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><H1><A NAME="Preload_Registry_Scripts">Preload Registry Scripts</A></H1></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>
  -<CODE>Apache::RegistryLoader</CODE> compiles Apache::Registry scripts at server startup. It can be a good idea
  -to preload these as well. So the code will be shared among the child
  -servers.
  +Note: replace x.x.x with the version numbers you actually use.
   
   <P>
  -Here is an example of the use of this technique. This code is included in a <CODE>PerlRequire</CODE>'d file, and walks the directory tree under which all registry scripts are
  -installed. For each <CODE>.pl</CODE> file encountered, it calls the <CODE>Apache::RegistryLoader::handler()</CODE> method to preload the script in the parent server (before preforking the
  -child processes):
  +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>  use File::Find 'finddepth';
  -  use Apache::RegistryLoader ();
  -  {
  -      my $perl_dir = &quot;perl/&quot;;
  -      my $rl = Apache::RegistryLoader-&gt;new;
  -      finddepth(sub {
  -          return unless /\.pl$/;
  -          my $url = &quot;/$File::Find::dir/$_&quot;;
  -          print &quot;pre-loading $url\n&quot;;
  -  
  -          my $status = $rl-&gt;handler($url);
  -          unless($status == 200) {
  -              warn &quot;pre-load of `$url' failed, status=$status\n&quot;;
  -          }
  -      }, $perl_dir);
  -  }
  +<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>
  -Note that we don't use the second argument to <CODE>handler()</CODE> here. You might need to provide a <CODE>trans()</CODE> method, since it's very dependent on your server's configuration. See <CODE>perldoc Apache::RegistryLoader</CODE>
  -for the complete information.
  +Where <CODE>PREFIX</CODE> specifies where to install the perl modules,
  +<CODE>APACHE_PREFIX</CODE> -- the same for the apache files.
   
   <P>
  -You have to check whether this makes any improvement for you though, I did
  -some testing [ <A HREF="#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A> ], and it seems that it takes more memory than when the scripts are being
  -called from the child - This is only a first impression and needs better
  -investigation. If you aren't concerned about few script invocations which
  -will take some time to respond while they load the code, you might not need
  -it all!
  +The next step is to configure the mod_perl sections of the apache
  +configuration file. (See <A HREF="././config.html#">ModPerlConfiguration</A>).
   
   <P>
  -See also <A HREF="././porting.html#BEGIN_blocks">BEGIN blocks</A>
  -
  -
  +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>
   <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>
  +<CENTER><H1><A NAME="How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A></H1></CENTER>
   <P>
  -Another important point is the sharing of memory. If your OS supports this
  -(and most sane systems do), you might save more memory by sharing it
  -between child processes. This is only possible when you preload code at
  -server startup. However during a child process' life, its memory pages
  -becomes unshared and there is no way we can control perl to make it
  -allocate memory so (dynamic) variables land on different memory pages than
  -constants so the copy-on-write effect will hit almost at random. If you are
  -pre-loading many modules you might be able to balance the memory that stays
  -shared against the time for an occasional fork by tuning the <CODE>MaxRequestsperChild</CODE> to a point where you restart before too much becomes unshared. In this case
  -the
  -<CODE>MaxRequestsPerChild</CODE> is very specific to your scenario. You should do some measurements and you
  -might see if this really makes a difference and what a reasonable number
  -might be. Each time a child reaches this upper limit and restarts it should
  -release the unshared copies and the new child will inherit pages that are
  -shared until it scribbles on them.
  +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>
  -It is very important to understand that your goal is not to have
  -<CODE>MaxRequestsperChild</CODE> to be 10000. Having a child serve 300 requests on precompiled code is
  -already a huge speedup, so if it is 100 or 10000 it does not really matter
  -if it saves you the RAM by sharing. Do not forget that if you preload most
  -of your code at the server startup, the fork to spawn a new child will be
  -very very fast, because it inherits most of the preloaded code and the perl
  -interpreter from the parent process. But then during the work of the child,
  -its memory pages (which aren't really its yet, it uses the parent's pages)
  -are getting dirty (originally inherited and shared variables are getting
  -updated) and the copy-on-write happens, which reduce the sharing number of
  -memory pages - thus enlarging the memory usage. Killing the child and
  -spawning a new one allows to get the pristine shared memory from the parent
  -process again.
  -
  +<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>
   <P>
  -The conclusion is that <CODE>MaxRequestsperChild</CODE> should not be too big, otherwise you loose the benefits of the memory
  -sharing.
  +When starting the server, just check the <CODE>error_log</CODE> file for the following message:
   
   <P>
  -See <A HREF="././performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A> for more about tuning the <CODE>MaxRequestsperChild</CODE> parameter.
  -
  +<PRE>  [Thu Dec  3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured 
  +                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  +    -- resuming normal operations
  +</PRE>
   <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>
  +<CENTER><H2><A NAME="Testing_by_viewing_perl_status">Testing by viewing /perl-status</A></H2></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.
  +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>
  -<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_modperl_scr">How can I find if my modperl scripts have memory leaks (and where)</A></H1></CENTER>
   <P>
  -<CODE>Apache::Leak</CODE> (derived from <CODE>Devel::Leak</CODE>) should help you with this task. Example:
  +You should see something like this:
   
   <P>
  -<PRE>  use Apache::Leak;
  -  
  -  my $global = &quot;FooAAA&quot;;
  -  
  -  leak_test {
  -    $$global = 1;
  -    ++$global;
  -  };
  +<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>
  -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><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.
   
   <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 !!!
  +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>  % telnet localhost 8080&lt;ENTER&gt;
  +  HEAD / HTTP/1.0&lt;ENTER&gt;&lt;ENTER&gt;
   </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>.
  +You should see a response like this:
   
   <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>
  +<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>
  -<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.
  +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>
  -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.
  +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><H1><A NAME="Limiting_the_resources_used_by_h">Limiting the resources used by httpd children</A></H1></CENTER>
  +<CENTER><H2><A NAME="Testing_via_a_CGI_script">Testing via a CGI script</A></H2></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.
  +Another method is to invoke a CGI script which dumps the server's
  +environment.
   
   <P>
  -To configure use:
  +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>  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>  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>
  -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.
  +Make it readable and executable by server:
   
   <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.
  +<PRE>  % chmod a+rx test.pl
  +</PRE>
  +<P>
  +(you will want to tune permissions on the public host).
   
   <P>
  -To debug add:
  +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>
  -<PRE>  &lt;Perl&gt;
  -    $Apache::Resource::Debug = 1;
  -    require Apache::Resource;
  -  &lt;/Perl&gt;
  -  PerlChildInitHandler Apache::Resource
  +<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>
  -and look in the error_log to see what it's doing.
  +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>
  -Refer to <CODE>perldoc Apache::Resource</CODE> and <CODE>man 2 setrlimit</CODE> for more info.
  +<PRE>  SERVER_SOFTWARE   Apache/1.3.6 (Unix)
  +  GATEWAY_INTERFACE CGI/1.1
  +  [...snipped]
  +</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>
  +<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.
   
   <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>
  +<CENTER><H2><A NAME="Testing_via_lwp_request">Testing via lwp-request</A></H2></CENTER>
   <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.
  +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>
  +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>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A>
  +</PRE>
   <P>
  -<CODE>Apache::SpeedLimit</CODE> comes for you to help, see:
  +Will show you all the headers. (The <CODE>-d</CODE> option disables printing the response content.)
   
   <P>
  -<A
  -HREF="http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients">http://www.modperl.com/chapters/ch6.html#Blocking_Greedy_Clients</A>
  +<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A> | egrep '^Server:'
  +</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.
   
   <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>
  +<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.
  +
   <P>
  -How much faster is mod_perl that CGI? There are many ways to benchmark the
  -two. See a few examples and numbers below, also checkout the benchmark/
  -directory of mod_perl dist for more 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>
  -If you write a benchmark for your own, use <CODE>Benchmark</CODE> for heavy scripts or use <CODE>Time::HiRes</CODE> for very fast scripts where you need better precision.
  +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>
  -There is no need to write a special benchmark though. If you want to
  -impress your boss or colleagues, just take the heaviest cgi script you
  -have, 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 lwp-get from
  -<CODE>LWP</CODE> package to emulate the web agent (browser). (benchmark/ directory of
  -mod_perl dist includes such an example)
  +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>
  -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>
  +Reduce resources usage (see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>).
   
  +<P><LI>
  +<P>
  +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><H2><A NAME="Developers_Talk">Developers Talk</A></H2></CENTER>
  +<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>
  -Perrin Harkins writes on benchmarks or comparisons, official or unofficial:
  -
  -<BLOCKQUOTE>
  +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>
  -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.
  +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>
  -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.
  +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>
  -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.
  +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>
  -But I'm not bitter or anything...
  -
  -</BLOCKQUOTE>
  +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>
  -Jonathan Peterson adds:
  -
  -<BLOCKQUOTE>
  -
  +<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>
   <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).
  -
  +<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>
  -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.
  +There are two configuration parameters: <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>, that you can use in:
   
   <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>  perl Makefile.PL [options]
  +</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>.
   
   <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.
  +If you did not build the httpd, chdir to the apache source, and execute:
   
   <P>
  -For very large jobs, it may be worth finding the best technical solution,
  -and then recruiting the team with the necessary skills.
  +<PRE>  make
  +</PRE>
  +<P>
  +Then return to the mod_perl source and run:
   
  -</BLOCKQUOTE>
  +<P>
  +<PRE>  make test
  +  make install
  +</PRE>
  +<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.
   
   <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>
  +<CENTER><H2><A NAME="mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A></H2></CENTER>
   <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:
  +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>    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>
  -We don't know what server configurations was used for these tests, but I
  -guess the numbers speak for themselves.
  +For all RH fans, before you are going to build the apache by yourself, do:
   
   <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>
  -.
  +<PRE>  rpm -e apache
  +</PRE>
  +<P>
  +to remove the pre-installed package first!
   
   <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>
  +<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>
  -As noted before, for very fast scripts you will have to use the Time::HiRes
  -module, its usage is similar to the Benchmark's.
  +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>
  -<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><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>
  -See also <A HREF="././performance.html#Tuning_with_crashme_script">crashme test</A>.
  +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><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>
  +	     [    <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>
  +  <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/02/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: 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">
  +   <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>
  +Server Configuration</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 -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<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="#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>
   
  -<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 PerlHandler's Benchmarking.
  +			<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>
   
  -<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 not use the system for its full
  -ability, and if too ``high'' chances your server will bring the machine to
  -its knees.
  +	</UL>
   
  -<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. 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 numbers? Generally by trying different combinations and
  -testing the server.
  +	<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>
   
  -<P>
  -Before you start this task you should be armed with the proper weapon. You
  -need a crashme utility, which will load your server with mod_perl scripts
  -you possess. While there are commercial solutions, you can get away with
  -free ones who 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>). You need these to have an ability to emulate a multiuser environment and
  -to emulate multiple clients behaviour which will call the mod_perl scripts
  -at your server simultaneously.
  +		<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="#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
  +		<LI><A HREF="#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
  +	</UL>
   
  -<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 big, your testing machine much be very powerful and
  -capable to generate a big load. Of course you should not run the clients
  -and 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.
  +	<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>
  +</UL>
  +<!-- INDEX END -->
   
  -<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>
  +<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>
   
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <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>
  +<CENTER><H1><A NAME="mod_perl_Specific_Configuration">mod_perl Specific Configuration</A></H1></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 :).
  +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>
  -Lets try it. We will simulate 10 users concurrently requesting the script <CODE>www.you.com:81/test/test.pl</CODE> which is a very light one. Each one makes 10 requests.
  +Before you start with mod_perl specific configuration, first configure
  +apache, and see that it works. When done, return here to continue...
   
  -<P>
  -<PRE>  % ./ab -n 100 -c 10 www.you.com:81/test/test.pl
  -  
  -  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 only numbers we are really care about are:
  +[ 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>
  -<PRE>  Complete requests:      100
  -  Failed requests:        0
  -  Requests per second:    139.86
  -</PRE>
  +<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>
  -Let's raise the load of requests to 100 x 10 (10 users each 100 requests)
  +First, you need to specify the locations on a file-system for the scripts
  +to be found.
   
  -<P>
  -<PRE>  % ./ab -n 1000 -c 10 www-pais:81/perl/access/access.cgi
  -  Concurrency Level:      10
  -  Complete requests:      1000
  -  Failed requests:        0
  -  Requests per second:    139.76
  -</PRE>
   <P>
  -As expected nothing changes (Since the situation didn't changed, we have
  -the same 10 concurrent users). Now let's raise the number of concurrent
  -users:
  +Add the following configuration directives:
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www-pais:81/perl/access/access.cgi
  -  Complete requests:      1000
  -  Failed requests:        0
  -  Requests per second:    133.01
  +<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>
  -We see that the server is capable of serving 50 concurrent users at an
  -amazing 133 req/sec! Lets find the upper bound. 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. It went down with the high load.
  +<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>
  -This test was performed with the following configuration:
  +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 at
  +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>
  -<PRE>  MinSpareServers 8
  -  MaxSpareServers 6
  -  StartServers 10
  -  MaxClients 50
  -  MaxRequestsPerChild 1500
  -</PRE>
  -<P>
  -Now let's try this:
  +FYI: for modperl <CODE>ScriptAlias</CODE> is the same thing as:
   
  -<P>
  -<PRE>  MinSpareServers 8
  -  MaxSpareServers 6
  -  StartServers 10
  -  MaxClients 100
  -  MaxRequestsPerChild 1
  -</PRE>
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www-pais:81/perl/access/access.cgi
  +<PRE>  Alias /foo/ /path/to/foo/
  +  SetHandler cgi-handler
   </PRE>
   <P>
  -The benchmark timed out with the above configuration.... I watched the
  -output of ps 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).
  +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>
  -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:
  +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 plain cgi-bin scripts 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>
  -<PRE>  MinSpareServers 8
  -  MaxSpareServers 6
  -  StartServers 10
  -  MaxClients 10
  -  MaxRequestsPerChild 1500
  -</PRE>
  +<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>
  -I got 27.12 req/sec, which is better but still 4-5 times slower (133 with <CODE>MaxClients</CODE> of 50)
  +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>
  -<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:
  +First we add:
   
   <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).
  +<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>
  -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.
  +<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-</CODE>header&gt; from
  +<CODE>CGI.pm</CODE> module or <CODE>$r-&amp;gt;send_http_header</CODE> directly.
   
   <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. If the script
  -that was used to test was heavier, the numbers would be different but the
  -conclusions are very similar.
  +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>
  -The benchmarks were run with:
  +Note that sometimes you will have to add :
   
   <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::Registry
   </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 one time by each child.
  -
   <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 test but will not for the real world - users
  -will not wait for more than 5-10 secs for a request to complete, and the
  -browser will timeout in 30 secs or so.)
  +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>
  -Now let's take a look at some real code whose execution time is more than a
  -few msecs. We will do real testing and collect the data in tables for
  -easier viewing.
  +You have nothing to do about <CODE>/cgi-bin</CODE> location (mod_cgi), since it has nothing to do with mod_perl.
   
   <P>
  -I will use the following abbreviations
  +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>  NR    = Number of Request Total 
  -  NC    = Number of multiple requests to make
  -  MC    = MaxClients
  -  MRPC  = MaxRequestsPerChild
  -  RPS   = Requests per second
  +<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>
  -Running a mod_perl script with lots of mysql queries (script mysqld
  -bounded) (http://www:81/perl/access/access.cgi?do_sub=query_form)
  -
  +<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>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       16
  -  StartServers          10
  -  MaxClients            50
  -  MaxRequestsPerChild 5000
  -</PRE>
  +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>     NR   NC    RPS     comment
  -  ------------------------------------------------
  -     10   10    3.33    # not a reliable stat
  -    100   10    3.94    
  -   1000   10    4.62    
  -   1000   50    4.09    
  +<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>
  -Conclusions: Here I wanted to show that when the application is slow -- not
  -due to perl loading, script compiling 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 browser can time
  -out!)
  -
  +<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>
  -Now we will benchmark the same script without using the mysql (perl only
  -bounded) (http://www.you.com:81/perl/access/access.cgi)
  +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>
  -<PRE>  MinSpareServers        8
  -  MaxSpareServers       16
  -  StartServers          10
  -  MaxClients            50
  -  MaxRequestsPerChild 5000
  -</PRE>
  -<P>
  -<PRE>     NR   NC      RPS   comment
  -  ------------------------------------------------
  -     10   10    26.95   # not a reliable stat
  -    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>
  -Conclusions: 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 RequestPerSecond (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><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>
  -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.
  +<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>  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>  # startup.pl
  +  use Apache::Registry ();
  +  use Apache::Status ();
  +  use Apache::DBI ();
   </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.
  +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>
  -Now we will try to change the <CODE>MaxClients</CODE> and to watch the results: Let's reduce MC to 10.
  +<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>  MinSpareServers        8
  -  MaxSpareServers       10
  -  StartServers          10
  -  MaxClients            10
  -  MaxRequestsPerChild 5000
  -  
  -     NR   NC      RPS   comment
  -  ------------------------------------------------
  -     10   10    23.87   # not a reliable stats
  -    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>  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>
  -Conclusions: 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!
  +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>
  -Now we will start to drastically reduce the MaxRequestsPerClient:
  +Let's follow for example : <STRONG>PerlRequire'd Files</STRONG> -- we see:
   
   <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>  PerlRequire                          Location
  +  /usr/myproject/lib/apache-startup.pl /usr/myproject/lib/apache-startup.pl
   </PRE>
   <P>
  -Conclusions: When we drastically reduce the <CODE>MaxRequestsPerClient</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:
  +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>
  -<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><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>
  -Conclusion: mod_cgi is much slower :) in test NReq/NClients 100/10 the RPS
  -in mod_cgi 1.12 and in mod_perl 32 =&gt; 30 times faster !!! In the first
  -test each child waited about 100 secs to be served. In the second and third
  -1000 secs!
  +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="Tuning_with_crashme_script">Tuning with crashme script</A></H2></CENTER>
  +<CENTER><H2><A NAME="PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A></H2></CENTER>
   <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> ops :). I also
  -allowed it to accept more than one url, since sometimes you want to test an
  -overall and not just one script.
  +<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>
  -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 Latency
  -(secs/Request) and Throughput (Requests/sec) numbers. It can give you a
  -better picture and make a complete simulation of your favorite Netscape
  -browser :)
  +<CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In &lt;Perl&gt; sections:
   
   <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. Weird ha? Any ideas why? Again
  -C vs Perl question :(
  +<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>
  -Sample output: 
  +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>  URL(s):          <A HREF="http://www.you.com:81/perl/access/access.cgi">http://www.you.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>    # startup.perl loads all functions that we want to use within
  +    # mod_perl
  +  Perlrequire /path/to/startup.pl
   </PRE>
   <P>
  -And the code:
  +before the rest of the mod_perl configuration directives.
   
   <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.you.com:81/perl/faq_manager/faq_manager.pl">http://www.you.com:81/perl/faq_manager/faq_manager.pl</A>',
  -            '<A HREF="http://www.you.com:81/perl/access/access.cgi">http://www.you.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
  -  ###
  +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;
     
  -  #@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() / 
  -                                   $nof_requests_total),
  -       );
  +  # 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 ();
     
  -  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
  -  .
  +  # tell me more about warnings
  +  use Carp ();
  +  $SIG{__WARN__} = \&amp;Carp::cluck;
     
  -  while(($left, $right) = splice(@P, 0, 2)) {
  -    write;
  -  }
  +  # 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><H2><A NAME="Choosing_MaxClients">Choosing MaxClients</A></H2></CENTER>
  +<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>
  -The <CODE>MaxClients</CODE> directive sets the limit on the number of simultaneous requests that can be
  -supported; not more than this number of child server processes will be
  -created. To configure more than 256 clients, you must edit the
  -HARD_SERVER_LIMIT entry in httpd.h and recompile. In our case we want to
  -set this variable as small as possible, this way we can virtually bound the
  -resources used by the server children. If we know that we have X Mb of RAM,
  -each child consumes a maximum of Y Mb of RAM (we can restrict each child.
  -See
  -<A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>) and we have all these X Mb dedicated for the webserver. Then calculation
  -of
  -<CODE>MaxClients</CODE> is pretty straightforward :
  +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>  MaxClients = Total Available to the webserver RAM / MAX child's size
  +<PRE>  use Foo qw(bar);
   </PRE>
   <P>
  -So if I have 400Mb left for the webserver to run in, I can set the
  -<CODE>MaxClients</CODE> to be of 40 if I know that each child is bounded to the 10Mb of memory
  -(with <CODE>Apache::SizeLimit</CODE>, See the reference above.)
  +perl actually does:
   
   <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:
  +<PRE>  require Foo.pm;
  +  import qw(bar);
  +</PRE>
  +<P>
  +When you write:
   
   <P>
  -<PRE>  [Sun Jan 24 12:05:32 1999] [error] server reached MaxClients setting,
  -  consider raising the MaxClients setting
  +<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>
  -No problem - any connection attempts over the <CODE>MaxClients</CODE> limit will normally be queued, up to a number based on the ListenBacklog
  -directive. Once a child process is freed at the end of a different request,
  -the connection will then be serviced.
  -
  -<P>
  -It <STRONG>is</STRONG> an error because clients are being put in the queue rather than getting
  -serviced at once, but 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 thing is not to have this condition reached at all.
  -
  -<P>
  -It's important to understand how much memory a child occupies. If your
  -children can share some memory (when the 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 me know)
  +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><H2><A NAME="Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A></H2></CENTER>
  +<CENTER><H3><A NAME="The_confusion_with_defining_glob">The confusion with defining globals in startup</A></H3></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 never expire.
  +<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>
  -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.
  +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>
  -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 some standard modules leak memory,
  -especially on OSes where memory managements is bad (Solaris 2.5 on x86 ?)
  +<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>
  -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 lose the
  -speed bonus you receive with mod_perl, so maybe you should consider falling
  -back to plain mod_cgi, since the overhead of reloading the script and the
  -perl interpreter for each request will be too high. 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!)
  +'<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>
  -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.
  +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>
  -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>.
  +<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><H2><A NAME="Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A></H2></CENTER>
  +<CENTER><H1><A NAME="Perl_behavior_controls">Perl behavior controls</A></H1></CENTER>
   <P>
  -With mod_perl enabled, it might take as much as 3-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 then
  -<CODE>MaxClients</CODE>.)
  +For <STRONG>PerlWarn</STRONG> and <STRONG>PerlTaintCheck</STRONG> see <A HREF="././porting.html#Switches_w_T">Switches -w, -T</A>
  +
  +
   
   <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):
  +<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>
  -<PRE>  Available to webserver RAM:   400Mb
  -  Child's memory size bounded:    10Mb
  -  MaxClients:                   400/10 = 40
  -  StartServers:                 20
  -  MinSpareServers:              20
  -  MaxSpareServers:              35
  +<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>
  -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:
  +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>
  -<PRE>  Available to webserver RAM:   400Mb
  -  Child's memory size bounded:    10Mb
  -  MaxClients:                   400/10 = 40
  -  StartServers:                 5
  -  MinSpareServers:              5
  -  MaxSpareServers:              10
  +<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>
  -(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!)
  +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>
  -<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>  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>
  -OK, we've run various benchmarks let's summarize the conclusions:
  +Other section counterparts include <CODE>%VirtualHost</CODE>, <CODE>%Directory</CODE> and
  +<CODE>%Files</CODE>.
   
  -<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).
  +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><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.)
  -
  -<P><LI><STRONG><A NAME="item_MinSpareServers">MinSpareServers</A></STRONG>
  +<PRE>  push @PerlPassEnv, [$key =&gt; $val];
  +</PRE>
   <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.
  +or
   
  -<P><LI><STRONG><A NAME="item_MaxSpareServers">MaxSpareServers</A></STRONG>
   <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.
  +<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><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 too long).
  -Don't make it high, since if you get a high load and all requests will be
  -immediately granted, 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 could 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. 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 that 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 start testing like I did,
  -successively raising this parameter until you find the point on the curve
  -of the graph of the latency or 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.
  -Also don't forget that if you add more scripts, most probably that the
  -parameters need to be recalculated, since the processes will grow in size
  -as you compile in more code.
  +A tip for syntax checking outside of httpd:
   
  -</UL>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Preopen_DB_connection_at_server_">Preopen DB connection at server startup:</A></H1></CENTER>
  +<PRE>  &lt;Perl&gt;
  +  # !perl
  +  
  +  #... code here ...
  +  
  +  __END__
  +  &lt;/Perl&gt;
  +</PRE>
   <P>
  -If you use DBI for DB connections, you can preopen connections to DB for
  -each child with Apache::DBI.
  +Now you may run:
   
   <P>
  -<PRE>  use Apache::DBI ();
  -  Apache::DBI-&gt;connect_on_init(&quot;DBI:mysql:test&quot;, 'login','passwd', 
  -                               {
  -                                RaiseError =&gt; 1,
  -                                PrintError =&gt; 1,
  -                                AutoCommit =&gt; 1,
  -                               };
  +<PRE>  perl -cx httpd.conf
   </PRE>
   <P>
  -See also <A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>.
  +To enable <CODE>&lt;Perl</CODE>&gt; sections you should build mod_perl with <STRONG>perl
  +Makefile.PL PERL_SECTIONS=1</STRONG>.
   
   <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>
  +<CENTER><H1><A NAME="Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</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:
  +mod_macro is an Apache module written by Fabien Coelho that lets you define
  +and use macros in the Apache configuration file.
   
  -<P>
  -<PRE>  #Apache::Registry script
  -  use strict;
  -  use vars qw($dbh);
  -  
  -  $dbh ||= SomeDbPackage-&gt;connect(...);
  -</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>.
  +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>
  -Be careful to use different names for handlers if you open connection to
  -different databases!
  +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>
  -<CODE>Apache::DBI</CODE> allows you to make a persistent database connection. With this module
  -enabled, every connect request to the plain DBI module will be forwarded to
  -the <CODE>Apache::DBI</CODE> module. This looks to see whether a database handle from a previous connect
  -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 disconnect
  -statements from your code</STRONG>. They will not do anything, as the
  -<CODE>Apache::DBI</CODE> module overloads the disconnect method with a NOP. On child exit there is
  -no explicit disconnect, the child dies and so does the database connection.
  +Here are some useful macros for mod_perl users:
   
   <P>
  -The usage is simple -- add to <CODE>httpd.conf</CODE>:
  -
  +<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>  PerlModule Apache::DBI
  +<PRE>        # example
  +        Alias /stuff /usr/www/scripts/stuff
  +        &lt;Location /stuff&gt;
  +        Use registry
  +        &lt;/Location&gt;
   </PRE>
   <P>
  -It is important, to load this module before any other <CODE>ApacheDBI*</CODE> module!
  +If your registry scripts are all located in the same directory, and your
  +aliasing rules consistent, you can use this macro:
   
   <P>
  -<PRE>  a script.perl
  -  ------------
  -  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>        # 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>
  -The module provides the additional method:
  -
   <P>
  -<PRE>  Apache::DBI-&gt;connect_on_init($data_source, $username, $auth, \%attr)
  +<PRE>        # example
  +        Use registry stuff stuff.pl
   </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
  -(PerlModule, &lt;Perl&gt; or PerlRequire). 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.
  +If you're using content handlers packaged as modules, you can use the
  +following macro:
   
   <P>
  -Beware however, as some old DBD drivers do not support this feature (ping
  -method), so check the documentation of the driver you use.
  -
  +<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>
  -Another problem is with timeouts: some databases disconnect the client
  -after a certain time of inactivity. The ping method ensures that this will
  -not happen. Some DBD drivers don't have this method, check the Apache::DBI
  -manpage to see how to write a ping method.
  -
  +<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>
  -Another approach is to change the client's connection timeout. 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.
  +The following macro sets up a Location for use with HTML::Embperl. Here we
  +define all ``.html'' files to be processed by Embperl.
   
   <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>        &lt;Macro embperl&gt;
  +        SetHandler &quot;perl-script&quot;
  +        Options +ExecCGI
  +        PerlHandler HTML::Embperl
  +        PerlSetEnv EMBPERL_FILESMATCH \.html$
  +        &lt;/Macro&gt;
  +</PRE>
   <P>
  -As you know <CODE>$|=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>        # examples
  +        &lt;Location /mrtg&gt;
  +        Use embperl
  +        &lt;/Location&gt;
  +</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.
  +Macros are also very useful for things that tend to be verbose, such as
  +setting up Basic Authentication:
   
   <P>
  -Many old CGIs were written in the style of:
  -
  +<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>  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>        # example of use
  +        &lt;Location /stats&gt;
  +        Use BasicAuth WebStats Admin
  +        &lt;/Location&gt;
   </PRE>
   <P>
  -which reveals the following drawbacks: multiple <CODE>print()</CODE> calls - performance degradation with $|=1, 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:
  +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>  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>        &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>
  -I guess you see the difference. Be careful though, when printing a
  -<CODE>&amp;lt;HTML&amp;gt;</CODE> tag. The correct way is:
  -
   <P>
  -<PRE>  print qq{&lt;HTML&gt;
  -    &lt;HEAD&gt;&lt;/HEAD&gt;
  -    &lt;BODY&gt;
  -  }
  +<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>
  -If you try the following:
  +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>  print qq{
  -    &lt;HTML&gt;
  -    &lt;HEAD&gt;&lt;/HEAD&gt;
  -    &lt;BODY&gt;
  -  }
  +<PRE>  use /forwards email/showforwards
  +  use /webstats web/showstats
   </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>&amp;lt;HTML&amp;gt;</CODE> and not spaces and/or additional newline and then <CODE>&amp;lt;HTML&amp;gt;</CODE>. Even if it works with your browser, it might not work for others.
  +<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>
  -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 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:
  -
  +<PRE>  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry
  +    Options ExecCGI
  +    allow from all
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
   <P>
  -What do you like better: getting the output ``slowly'' but steadily or
  -having to watch the ``falling stars'' for awhile and then to receive the
  -whole output at once (if the browser did not timeout till then).
  -
  +<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>
  -Conclusion: Do not blindly follow suggestions, but think what is best for
  -you in every given case.
  +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><H1><A NAME="More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A></H1></CENTER>
  +<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>
  -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 )
  +No. Any virtual host will be able to see the routines from a startup.pl
  +loaded for any other virtual host.  
   
   <P>
  -See <A HREF="././porting.html#Global_Variables">Global Variables</A>
  -
  -
  +<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>
  -See <A HREF="././porting.html#Memory_leakage">Memory "leakages"</A>
  +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><H1><A NAME="Profiling">Profiling</A></H1></CENTER>
  -<P>
  -Profiling will help you to determine which subroutines or just snippets of
  -code take the longest execution time and which subroutines are being called
  -most often, then you will probably will want to optimize those, and to
  -improve the code toward efficiency.
  -
  +<CENTER><H2><A NAME="Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with
  +the same path from the second virtual host</A></H2></CENTER>
   <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. When the server is started, <CODE>Devel::DProf</CODE> installs an
  -<CODE>END</CODE> block to write the <CODE>tmon.out</CODE> file, which will be called at the server shutdown. Here is how to start and
  -stop a server with the profiler enabled:
  +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>  % 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>  $Apache::Registry::NameWithVirtualHost = 1;
   </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 that <CODE>print()</CODE> and <CODE>map()</CODE> are subs as well, they come together with Perl!).
  -
   <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. All it takes is to add to <CODE>httpd.conf</CODE>:
  +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)
   
   <P>
  -<PRE>  PerlModule Apache::DProf
  +<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>
  -Remember that any PerlHandler .pm that was pulled in before
  -<CODE>Apache::DProf</CODE>, would not have its code debugging info inserted.
  +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="CGI_pm_s_object_methods_calls_vs">CGI.pm's object methods calls vs. function calls</A></H1></CENTER>
  +<CENTER><H1><A NAME="Configuration_Security_Concerns">Configuration Security Concerns</A></H1></CENTER>
   <P>
  -Which approach is better?
  +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>
  -<PRE>  use CGI;
  -  my $q = new CGI;
  -  print $q-&gt;param('x');
  -</PRE>
  +The more modules you have in your web server, the more complex the code in
  +your webserver.
  +
   <P>
  -versus
  +The more complex the code in your web server, the more chances for bugs.
   
   <P>
  -<PRE>  use CGI (:standard);
  -  print param('x');
  -</PRE>
  +The more chance for bugs, the more chance that some of those bugs may
  +involve security.
  +
   <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.
  +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>
  -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.
  +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="Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A></H1></CENTER>
  +<CENTER><H1><A NAME="Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A></H1></CENTER>
   <P>
  -See <A HREF="././modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +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><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -8169,7 +8739,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]
  +	     [    <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>
  @@ -8182,7 +8752,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 07/02/1999
         </FONT>
       </B>
     </TD>
  @@ -8209,7 +8779,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: 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">
  @@ -8228,37 +8798,15 @@
   <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>
  +Frequent mod_perl problems</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
  -	<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="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  -	<UL>
  -
  -		<LI><A HREF="#Restarting_the_server">Restarting the server</A>
  -		<LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
  -		<LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</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="#Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -8278,714 +8826,1016 @@
   <P>
   <CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
   <P>
  -This document describes ``special'' traps you may encounter when running
  -your plain CGIs under Apache::Registry and Apache::PerlRun.
  +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>
  -<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:
  +See <A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
   
   <P>
  -<PRE>    use CGI qw/param/;
  -    my $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  -</PRE>
  +<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>
  -However, the script is run under Apache::Registry, it will in fact be
  -repackaged into something like this:
  +See <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</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 -w (or/and PerlWarn ON)! Perl will then emit a warning like:
  +	     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>
  +	     [    <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 05/08/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>
   
  -<P>
  -<PRE>  Value of $x will not stay shared at - line 5.
  -</PRE>
  -<P>
  -NOTE: Subroutines defined inside <STRONG>BEGIN{}</STRONG> and <STRONG>END{}</STRONG> cannot trigger this message, since each <STRONG>BEGIN{}</STRONG> and <STRONG>END{}</STRONG> is defined to be called exactly once. (To understand why, read about the
  -closures at
  -<CODE>perlref</CODE> or <CODE>perlfaq</CODE> 13.12)
  +	<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>
  +</UL>
  +<!-- INDEX END -->
   
  -<P>
  -PERLDIAG manpage says:
  +<HR>
   
  -<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.
  +	     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>
  -Check your code by running Apache in single-child mode (httpd -X). 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.
  +	     <HR>
   
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <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>
  +<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
   <P>
  -If a variable needs file scope, use a global variable:
  +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 httpd.pid file.
  +With my configuration it exists as
  +<CODE>/usr/apps/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>    use vars qw/$x/;
  -    use CGI qw/param/;
  -    $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  +<PRE>  PidFile /usr/apps/var/httpd_perl/run/httpd.pid
   </PRE>
   <P>
  -You can safely use a <CODE>my()</CODE> scoped variable if its value is constant:
  +Another way is to use the <CODE>ps</CODE> and <CODE>grep</CODE> utilities:
   
   <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>  % ps auxc | grep httpd_perl
   </PRE>
   <P>
  -Also see the clarification of <CODE>my()</CODE> vs. <CODE>use vars</CODE> - Ken Williams writes:
  +or maybe:
   
   <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>  % ps -ef | grep httpd_perl
   </PRE>
   <P>
  -And <CODE>my()</CODE> vs. <CODE>local()</CODE> - Randal Schwartz writes:
  +This will produce a list of all httpd_perl (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>
  -<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>
  +You will notice many httpd_perl 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><H2><A NAME="Additional_reading_references">Additional reading references</A></H2></CENTER>
  +<CENTER><H1><A NAME="Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</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 `use vars' and `my' - <A
  -HREF="http://www.plover.com/~mjd/perl/FAQs/Namespaces.html">http://www.plover.com/~mjd/perl/FAQs/Namespaces.html</A>
  +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>
   .
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
  +<DL>
  +<P><DT><STRONG><A NAME="item_TERM">TERM Signal: stop now</A></STRONG><DD>
   <P>
  -When you develop plain CGI scripts, you can just change the code, and rerun
  -the CGI from your browser. Since the script isn't cached in memory, the
  -next time you call it the server starts up a new perl process, which
  -recompiles it from scratch. The effects of any modifications you've applied
  -are immediately present.
  +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>
  -The situation is different with Apache::Registry, since the whole idea is
  -to get maximum performance from the server. By default, the server won't
  -spend the time to check whether any included library modules have been
  -changed. It assumes that they weren't, thus saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are
  -<STRONG>use</STRONG>/<STRONG>require</STRONG>-ing in your script.) The only check that is being done is whether your
  -main script has been changed. So if you have only one script that doesn't <STRONG>use</STRONG> (or <STRONG>require</STRONG>) other perl modules (or packages), there is nothing new about it. If
  -however, you are developing a script that includes other modules, the files
  -you <STRONG>use()</STRONG> or <STRONG>require()</STRONG> aren't being checked to see if they have been modified.
  +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>
  -Acknowledging this, how do we get our modperl-enabled server to recognize
  -changes in any library modules? Well, there are a couple of techniques:
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
  +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>
  -See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
  +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>
  -After restarting the server about 100 times, you will be tired and will
  -look for another solutions. Help comes from the Apache::StatINC module. 
  +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>
  -Read its pod pages, but beware of the following note: Only the modules
  -located in <STRONG>@INC</STRONG> are being reloaded on change, and you can change the <STRONG>@INC</STRONG> only before the server has been started. Whatever you do in your
  -scripts/modules which are being <CODE>required()</CODE> after the server
  -startup will not have any effect on <STRONG>@INC</STRONG>.
  -
  -<P>
  -When you do <STRONG>use lib qw(foo/bar);</STRONG>, the <STRONG>@INC</STRONG> is being changed only for the time the code is being parsed. When it's over
  -the <STRONG>@INC</STRONG> is being reset to its original value. To make sure that you have set a
  -correct <STRONG>@INC</STRONG> fetch <A
  -HREF="http://your.perl.server/perl-status?inc">http://your.perl.server/perl-status?inc</A>
  -and watch the bottom of the page. (I assume you have configured the
  -&lt;Location /perl-status&gt; section in httpd.conf as the mod_perl docs
  -show.)
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
  +<PRE> PerlFreshRestart On              (in httpd.conf) 
  +</PRE>
   <P>
  -Checking all the Modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
  -certainly would not want
  -<CODE>Apache::StatINC </CODE>module to be enabled in your production site's configuration. But sometimes
  -you want to have some Configuration module to be reloaded without
  -restarting the whole server. To accomplish this, one of the solutions is to
  -use a code that I describe below.
  +Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
   
  +</DL>
   <P>
  -Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
  +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>./Configure</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>
  -<PRE>  use lib &quot;/some/private/path&quot;;
  -  use Foo::Bar qw(:tags_group tag1 tag2);
  -</PRE>
   <P>
  -Now to make a modification testing and reload at runtime you have to use
  -something like this:
  +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>  # child's private global variable to keep the timestamps
  -  use vars qw(%MODIFIED);
  -    
  -  my $module = &quot;Foo::Bar&quot;;
  -  
  -  (my $inc_key = $module) =~ s|::|/|g;
  -  $inc_key .= &quot;.pm&quot;;
  -  # the $module's path should be registered in %INC if it was already loaded
  -  my $path = $INC{$inc_key} or warn &quot;Can't find $inc_key in %INC\n&quot;;
  -  
  -  # Note: consider to not continue if $path wasn't set!
  -  
  -  # set modification time if it wasn't set before (first time)
  -  # Note: Use (stat $path)[9] instead of -M test, if you reset
  -  # time with $^M=time
  -  $MODIFIED{$module} ||= -M $path;
  -    
  -  # now check whether it was changed (assuming the above wasn't
  -  # performed in this session
  -  if ($MODIFIED{$module} != -M $path){
  -    # only if deleted from %INC the require will be called below
  -    delete $INC{$inc_key};
  -    
  -    require $path;
  -    
  -    # now reimport the symbols (if you need them back :)
  -    import $module qw(:tags_group tag1 tag2);
  -    
  -    # Update the MODIFICATION times
  -    $MODIFIED{$module} = -M $path;
  -  }
  +<PRE>  #define SIGHUP     1    /* hangup, generated when terminal disconnects */ 
  +  #define SIGTERM   15    /* software termination signal */
  +  #define SIGUSR1   30    /* user defined signal 1 */
   </PRE>
   <P>
  -You may want to add debug print statements to debug this code in your
  -application.
  +<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/apps/sbin/httpd_perl/apachectl</CODE>.
   
   <P>
  -Read the ``use versus require'' article for more info. ( <A
  -HREF="http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require">http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require</A>
  -)
  +Start httpd:
   
   <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>
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl start 
  +</PRE>
   <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 <STRONG>/o</STRONG> 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:
  +Stop httpd:
   
   <P>
  -<PRE>  my $pat = '^foo$'; # likely to be input from an HTML form field
  -  foreach( @list ) {
  -    print if /$pat/o;
  -  }
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl stop
   </PRE>
   <P>
  -This is usually a big win in loops over lists, or when using
  -<STRONG>grep</STRONG> or <STRONG>map</STRONG>. 
  +Restart httpd if running by sending a <STRONG>SIGHUP</STRONG> or start if not running:
   
   <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.
  -
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl restart
  +</PRE>
   <P>
  -There are two solutions to this problem. 
  +Do a graceful restart by sending a <STRONG>SIGUSR1</STRONG> or start if not running:
   
   <P>
  -The first is to use <STRONG>eval q//</STRONG>, 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.
  -
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl graceful    
  +</PRE>
   <P>
  -The above code fragment would be rewritten as: 
  +Do a configuration syntax test:
   
   <P>
  -<PRE>  my $pat = '^foo$';
  -  eval q{
  -    foreach( @list ) {
  -      print if /$pat/o;
  -    }
  -  }
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl configtest 
   </PRE>
  +<P>
  +See the next section for the implication of the above calls.
  +
   <P>
  -Just saying:
  +Replace <CODE>httpd_perl</CODE> with <CODE>httpd_docs</CODE> in the above calls to control the <STRONG>httpd_docs</STRONG> server.
   
   <P>
  -<PRE>  eval q{ print if /$pat/o; };
  -</PRE>
  +There are other options for <STRONG>apachectl</STRONG>, use <CODE>help</CODE> option to see them all.
  +
   <P>
  -is going to be a horribly expensive proposition. 
  +It's important to understand that this script is based on the PID file
  +which is <CODE>PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid</CODE>. If you delete the file by hand - <STRONG>apachectl</STRONG> will fail to run.
   
   <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 <STRONG>m//</STRONG> or <STRONG>s///</STRONG>), 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.
  +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>
  -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="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>
  -<PRE>  my $pat = '^foo$';
  -  &quot;something&quot; =~ /$pat/; # dummy match (MUST NOT FAIL!)
  -  foreach( @list ) {
  -    print if //;
  -  }
  +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>
  -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 <STRONG>//</STRONG> will match everything. If you can't count on fixed text to ensure the match
  -succeeds, you have two possibilities.
  +<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>
  -If you can guarantee that the pattern variable contains no meta-characters
  -(things like *, +, ^, $...), you can use the dummy match:
  +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>
  -<PRE>  &quot;$pat&quot; =~ /\Q$pat\E/; # guaranteed if no meta-characters present
  +The crontab entry:
  +
  +<P>
  +<PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
   </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:
  +The script:
   
   <P>
  -<PRE>  &quot;\377&quot; =~ /$pat|^[\377]$/; # guaranteed if meta-characters present
  +<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/apps/var/httpd_perl/run/httpd.pid
  +    
  +  # the path to your httpd binary, including options if necessary
  +  HTTPD=/usr/apps/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>
  -Phil. Chu contributed this:
  +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? 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>
  -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.
  +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 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>
  -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.''. I find it quite useful:
  +So we end up with crontab entry:
   
   <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>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
   </PRE>
   <P>
  -Example usage:
  +And the watchdog itself:
   
  -<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>  #!/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);
  +  
  +  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/apps/sbin/httpd_perl/apachectl start';
  +  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="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).
  -
  +<CENTER><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
   <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.
  +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>  use vars qw($num);
  -  $num ||= random();
  -  print ++$num;
  +<PRE>  % /usr/apps/sbin/httpd_perl/httpd_perl -X
   </PRE>
  -<P>
  -This script initializes the variable <STRONG>$num</STRONG> 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 1,9,4,19 (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 httpd -X single server
  -mode you will get 2,3,4,5... (taken that the <CODE>random()</CODE> returned
  -1 at the first call)
  -
   <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 multi
  -server mode. Consider an application that allows you to change the
  -configuration at run time.
  -
  -<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.
  -
  -<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...
  +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>
  -If you run the same code in the multi server environment, 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 old color, 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.
  +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>
  -Also note that since the server is running in single mode, if the output
  -returns HTML with IMG tags, then the load of these will take a lot of time
  -(read apache docs of httpd -X to learn why).
  +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="_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</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 -M (-C -A) 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.
  +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>
  -If you want to have -M test to count the time relative to the current
  -request, you should reset the $^T variable as with any other perl script.
  -Just add <CODE>$^T = time;</CODE> at the beginning of the scripts.
  +<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>
  -<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>
  +<PRE>  % http_perl -Dsbekman
  +</PRE>
   <P>
  -When a user presses the stop button, Apache will detect that via
  -SIG{'PIPE'} 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 this
  -advisory locking scheme.)
  +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/apps/var/httpd_perl/run/httpd.pid.sbekman
  +  ErrorLog /usr/apps/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/apps/var/httpd_perl/run/httpd.pid.userfoo
  +  ErrorLog /usr/apps/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>
  -Important to notice that when the user hits ``stop'' on the browser, 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.
  +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>
  -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.
  +To make things even easier. (In the above technique, you have to discover
  +the PID of your parent httpd_perl process - written in
  +<CODE>/usr/apps/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>  *) 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>  PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid.sbekman
  +  HTTPD='/usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman'
   </PRE>
   <P>
  -What happens if your mod_perl script has some global variables, that are
  -being used for resource locking?
  +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>
  -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:
  +The last thing was to let developers an option to run in single process
  +mode by:
   
   <P>
  -<PRE>  1. lock resource
  -     &lt;b&gt;&lt;critical section starts&gt;
  -  2. sleep 20 (== do some time consuming processing)
  -     &lt;critical section ends&gt;&lt;/b&gt;
  -  3. unlock resource
  +<PRE>  /usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman -X
   </PRE>
   <P>
  -If user presses 'Stop' and Apache sends SIGPIPE 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 ``deadlock'' exists.
  +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>
  -Here is the working example. Run the server with -X, Press 'Stop' 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.
  +In access.conf of the httpd_docs server we have the following code: (you
  +have to configure your httpd_docs server with
  +<CODE>--enable-module=rewrite</CODE> )
   
   <P>
  -<PRE>  -------------------------------------------------------------
  -  use vars qw(%CACHE);
  -  use CGI;
  -  $|=1;
  -  my $q = new CGI;
  -  print $q-&gt;header,$q-&gt;start_html;
  +<PRE>  # sbekman' server
  +  # port = 8000
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteCond  %{REMOTE_ADDR} 123.34.45.56
  +  RewriteRule ^(.*)           <A HREF="http://ourserver.com:8000/">http://ourserver.com:8000/</A>$1 [R,L]
     
  -  print $q-&gt;p(&quot;$$ Going to lock!\n&quot;);
  +  # userfoo's server
  +  # port = 8001
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteCond  %{REMOTE_ADDR} 123.34.45.57
  +  RewriteRule ^(.*)           <A HREF="http://ourserver.com:8001/">http://ourserver.com:8001/</A>$1 [R,L]
     
  -   # 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;;
  -  }
  +  # all the rest
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteRule ^(.*)           <A HREF="http://ourserver.com:81/">http://ourserver.com:81/</A>$1 [R]
     
  -  print $q-&gt;p(&quot;Going to unlock!&quot;);
  -  $CACHE{LOCK} = 0;
  -  print $q-&gt;p(&quot;Unlock!\n&quot;);
  -  -------------------------------------------------------------
   </PRE>
   <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 END blocks that are encountered during compilation of Apache::Registry
  -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
  -Apache::Registry mode, the following is your remedy:
  +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>
  -<PRE>  END {
  -    $CACHE{LOCK} = 0;
  -  }
  -</PRE>
  +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 httpd_docs to
  +<CODE>http://www.nowhere.com:8000/perl/test.pl</CODE>.
  +
   <P>
  -Notice that the END block will be run after the Apache::Registry::handler
  -is finished (not during the cleanup phase though).
  +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>
  -If you are into a perl API, use the <STRONG>register_cleanup()</STRONG> method of Apache.
  +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>
  -<PRE>  $r-&gt;register_cleanup(sub {$CACHE{LOCK} = 0;});
  -</PRE>
  +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>
  -If you are into Apache API <CODE>Apache-</CODE>request-&gt;connection-&gt;aborted()&gt; construct can be used to test for
  -the aborted connection.
  +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="Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A></H1></CENTER>
  +<CENTER><H1><A NAME="Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</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:
  +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>
  -<PRE>  eval {
  -    local $SIG{ALRM} = sub { die &quot;timeout\n&quot; };
  -    alarm $timeout;
  -    ... db stuff ...
  -    alarm 0;
  -  };
  +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/apps/bin/perl -w    
      
  -  die $@ if $@;
  +  # 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/apps&quot;;
  +  
  +    # we want to make a complete emulation, so we must remove the
  +    # user's environment
  +    @INC = ();
  +  
  +    # local perl libs
  +    push @INC, (&quot;$basedir/lib/perl5/5.00502/aix&quot;,
  +                &quot;$basedir/lib/perl5/5.00502&quot;,
  +                &quot;$basedir/lib/perl5/site_perl/5.005/aix&quot;,
  +                &quot;$basedir/lib/perl5/site_perl/5.005&quot;,
  +               );
  +  }
  +  
  +  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 Taintness ON!!!
  +  system qq{$basedir/bin/perl -I$PERL5LIB -Tw $cgi $params};
   </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 'local
  -$SIG{FOO}' 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.
  -
  -<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>
  +<CENTER><H1><A NAME="Log_Rotation">Log Rotation</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?
  +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>
  -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:
  +To rotate the logs do:
   
   <P>
  -<PRE>  ErrorLog var/logs/error_log
  +<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>
  -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:
  +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>
  -<PRE>  ServerRoot /usr/local/apache
  +I use this script:
  +
  +<P>
  +<PRE>  #!/usr/apps/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/apps/var/$server/logs&quot;;
  +  my $restart_command = &quot;/usr/apps/sbin/$server/apachectl restart&quot;;
  +  my $gzip_exec = &quot;/usr/intel/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>
  -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.
  +Randal L. Schwartz contributed this:
   
  -<P>
  -&lt;META&gt;: is this 100% correct?
  +<BLOCKQUOTE>
   
   <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.
  +Cron fires off setuid script called log-roller that looks like this:
   
   <P>
  -For example, if you have mistakenly entered a non-existent directory path
  -in your <STRONG>ErrorLog</STRONG> directive, the error message will be printed on the controlling tty. Or, if
  -the error happens when server executes PerlRequire or PerlModule directive
  -you might see the errors here also.
  -
  +<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>
  -You are probably wonder where all the errors go when you are running the
  -server in single mode (httpd -X). 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.
  +And then individual MIDNIGHT scripts can look like this:
   
   <P>
  -&lt;/META&gt;
  +<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>
  +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="Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A></H1></CENTER>
  +<CENTER><H1><A NAME="Preventing_from_modperl_process_">Preventing from modperl process from going wild</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:
  +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>
  -<PRE> open UTIL, &quot;USER=stas ; script.pl | &quot; or die &quot;...: $!\n&quot;;
  +<PRE>  sub UNIVERSAL::AUTOLOAD {
  +          my $class = shift;
  +          warn &quot;$class can't \$UNIVERSAL::AUTOLOAD!\n&quot;;
  +  }
   </PRE>
   <P>
  -or
  +It will produce a nice error in error_log, giving the line number of the
  +call and the name of the undefined subroutine.
   
  -<P>
  -<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.
  +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>  open(PUBLISH, &quot;GATEWAY_INTERFACE=CGI/1.1 ; script.cgi
  -       &quot;param1=value1&amp;param2=value2&quot; |&quot;) or die &quot;...: $!\n&quot;;
  +<PRE>  S=`ls -s /usr/local/apache/logs/error_log | awk '{print $1}'`
  +  if [ &quot;$S&quot; -gt 100000 ] ; then
  +    /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>
  -Make sure, that the parameters you pass are shell safe (All ``unsafe''
  -characters like single-tick should be properly escaped).
  +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>
  -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.
  +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>
  @@ -8996,7 +9846,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.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>
  @@ -9009,7 +9859,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/05/1999
  +	     <BR>Last Modified at 06/27/1999
         </FONT>
       </B>
     </TD>
  @@ -9036,7 +9886,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: 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">
  @@ -9054,32 +9904,30 @@
   <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>
  -Runtime Warnings and Errors: Where and Why.</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="obvious.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="#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>
  +<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>
  +<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 -->
  +<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>
   </UL>
   <!-- INDEX END -->
   
  @@ -9097,351 +9945,627 @@
   
   	      <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="Coverage">Coverage</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.
  +This document describes ``special'' traps you may encounter when running
  +your plain CGIs under <CODE>Apache::Registry</CODE> and <CODE>Apache::PerlRun</CODE>.
   
   <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="my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</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>
  +<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>
  +<P>
  +However, the script is run under <CODE>Apache::Registry</CODE>, it will in fact be repackaged into something like this:
   
  +<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><H1><A NAME="Value_of_x_will_not_stay_shared">Value of $x will not stay shared at - line 5</A></H1></CENTER>
  +<CENTER><H2><A NAME="The_diagnosis">The diagnosis</A></H2></CENTER>
   <P>
  -<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +Always use <CODE>-w</CODE> (or/and <CODE>PerlWarn ON</CODE>)! Perl will then emit a warning like:
   
   <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>
  +<PRE>  Value of $x will not stay shared at - line 5.
  +</PRE>
   <P>
  -<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
  +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>
  -<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>
  +PERLDIAG manpage says:
  +
   <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.
  +<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>
  -This bug has been fixed in mod_perl 1.19_01 (CVS version).
  +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><H1><A NAME="caught_SIGPIPE_in_process">caught SIGPIPE in process</A></H1></CENTER>
  +<CENTER><H2><A NAME="The_remedy">The remedy</A></H2></CENTER>
   <P>
  -<PRE>  [modperl] caught SIGPIPE in process 1234
  -  [modperl] process 1234 going to Apache::exit with status...
  +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>
  -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.
  +You can safely use a <CODE>my()</CODE> scoped variable if its value is constant:
   
   <P>
  -If your mod_perl version &lt; 1.17 you might get the message in the
  -following section...
  +<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>
  -<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>
  +<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>
  -<PRE>  Client hit STOP or Netscape bit it!
  -  Process 2493 going to Apache::exit with status=-2
  +And <CODE>my()</CODE> vs. <CODE>local()</CODE> - Randal Schwartz writes:
  +
  +<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>
  -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><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>
  +<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>
  +.
   
   <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><H1><A NAME="Compiled_Regular_Expressions">Compiled Regular Expressions</A></H1></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.
  +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>
  +<P>
  +This is usually a big win in loops over lists, or when using <CODE>grep()</CODE>
  +or <CODE>map()</CODE> operators.
  +
  +<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.
  +
  +<P>
  +There are two solutions to this problem:
  +
  +<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>
  +The above code fragment would be rewritten as: 
  +
  +<P>
  +<PRE>  my $pat = '^foo$';
  +  eval q{
  +    foreach( @list ) {
  +      print if /$pat/o;
  +    }
  +  }
  +</PRE>
  +<P>
  +Just saying:
  +
  +<P>
  +<PRE>  foreach( @list ) {
  +    eval q{ print if /$pat/o; };
  +  }
  +</PRE>
  +<P>
  +is going to be a horribly expensive proposition. 
  +
  +<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>
  +<PRE>  my $pat = '^foo$';
  +  &quot;something&quot; =~ /$pat/; # dummy match (MUST NOT FAIL!)
  +  foreach( @list ) {
  +    print if //;
  +  }
  +</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.
  +
  +<P>
  +If you can guarantee that the pattern variable contains no meta-characters
  +(things like *, +, ^, $...), you can use the dummy match:
  +
  +<P>
  +<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>
  +<PRE>  &quot;\377&quot; =~ /$pat|^[\377]$/; # guaranteed if meta-characters present
  +</PRE>
  +<P>
  +Phil. Chu contributed this:
  +
  +<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.
  +
  +<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.''. I find it quite useful:
   
   <P>
  -<PRE>  &lt;META&gt;
  -  Someone said: 
  -  You won't see that warning in this case with 5.004_05 or 5.005+. 
  +<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>
  -<PRE>  I'm running perl5.00502 and I still get these warnings???
  +Example usage:
  +
  +<P>
  +<PRE>  @some_browsers = qw(Mozilla Lynx MSIE AmigaVoyager lwp libwww);
  +  $Known_Browser=Build_MatchMany_Function(@some_browsers);
   </PRE>
   <P>
  -<PRE>  Who is right?
  -  &lt;/META&gt;
  +<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="Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</A></H1></CENTER>
  +<CENTER><H1><A NAME="Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</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:
  +Running in httpd -X mode. (good only for testing during development phase).
   
  -<P>
  -<PRE>  #!/usr/bin/perl -w
  -  use strict;
  -  print &quot;Content-type: text/html\n\n&quot;;
  -  print &quot;Hello $undefined&quot;;
  -</PRE>
   <P>
  -The warning:
  +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>  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>  use vars qw($num);
  +  $num ||= random();
  +  print ++$num;
   </PRE>
   <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.
  +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>
  -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.
  +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>
  -As Doug answered to this question:
  +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> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
  - That's what's expected if so.
  +<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>
  -It wasn't in my case, but may be yours. 
  +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>
  -Bryan Miller said:
  +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> 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>
  +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>
  +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="Can_t_undef_active_subroutine">Can't undef active subroutine</A></H1></CENTER>
  +<CENTER><H1><A NAME="_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</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>
  +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>
  -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.
  +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>
   <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><H1><A NAME="Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A></H1></CENTER>
   <P>
  -Your code includes some undefined variable that you have used as if it was
  -already defined and initialized. For example:
  +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>
  -<PRE>  $param = $q-&gt;param('test');
  -  print $param;
  -</PRE>
  +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>
  -<PRE>  vs.
  -</PRE>
  +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>
  -<PRE>  $param = $q-&gt;param('test') || '';
  -  print $param;
  +<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>
  -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>.
  +What happens if your mod_perl script has some global variables, that are
  +being used for resource locking?
   
   <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>.
  +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>
  -<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>
  +<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>
  -See <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>.
  +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>
  -<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>
  -<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.
  +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.
   
   <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.
  -
  +<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>
   <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:
  +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>
  -<PRE>  % ./Configure -des -Dcc=gcc ... &amp;&amp; make test &amp;&amp; make install
  - 
  -Read Perl's INSTALL doc for more details.
  +<PRE>  END {
  +    $CACHE{LOCK} = 0;
  +  }
   </PRE>
   <P>
  -Solaris OS specific: 
  +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>
  -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
  +If you are into a perl API, use the <CODE>register_cleanup()</CODE> method of Apache.
   
   <P>
  -<PRE>  -Xlinker -E
  +<PRE>  $r-&gt;register_cleanup(sub {$CACHE{LOCK} = 0;});
   </PRE>
   <P>
  -This problem is only known to be caused by installing gnu ld under Solaris.
  +If you are into Apache API <CODE>Apache-</CODE>request-&gt;connection-&gt;aborted()&gt; construct can be used to test for
  +the aborted connection.
   
  -<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>
   <P>
  -See <A HREF="#Out_of_memory_">Out_of_memory!</A>
  -
  +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>
  -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:
  +<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>  Callback called exit at -e line 33, &lt;HTML&gt; chunk 1.
  +<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>
   <P>
  -Why the looping?
  +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.
   
   <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.
  -
  +<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>
  -Perl 5.005+ plus is recommended for its improved malloc.c and features
  -mentioned in mod_perl_traps.pod on by default.
  +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>
  -<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>
   <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: 
  +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>  =item -DPERL_EMERGENCY_SBRK
  +<PRE>  ErrorLog var/logs/error_log
   </PRE>
   <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.
  +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>  ServerRoot /usr/local/apache
   </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.
  +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.
   
   <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>
  +&lt;META&gt;: is this 100% correct?
  +
   <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>.
  +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>
  -<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>
  +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>  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>
  +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>
  -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).
  +&lt;/META&gt;
   
   <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><H1><A NAME="Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A></H1></CENTER>
   <P>
  -Not all Perl modules can survive a reload. PerlFreshRestart does not much
  -more than:
  +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>  while (my($k,$v) = each %INC) {
  -    delete $INC{$k};
  -    require $k;
  -  }
  +<PRE> open UTIL, &quot;USER=stas ; script.pl | &quot; or die &quot;...: $!\n&quot;;
   </PRE>
   <P>
  -Besides that, it flushes the Apache::Registry cache, and empties any
  -dynamic stacked handlers (e.g. PerlChildInitHandler).
  +or
   
   <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...
  +<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>
  -<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>
  +<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>
  -See <A HREF="././performance.html#Choosing_MaxClients">Choosing MaxClients</A>.
  +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/">
  @@ -9453,7 +10577,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.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>
  @@ -9466,7 +10590,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/27/1999
         </FONT>
       </B>
     </TD>
  @@ -9493,7 +10617,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: 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">
  @@ -9512,22 +10636,31 @@
   <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>
  +Runtime Warnings and Errors: Where and Why.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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="#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="#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>
   </UL>
   <!-- INDEX END -->
   
  @@ -9544,915 +10677,353 @@
   	     <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 httpd.pid file.
  -With my configuration it exists as
  -<CODE>/usr/apps/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/apps/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 httpd_perl (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 httpd.conf), but it's still easy to know 'who is the
  -parent' -- the one of the smallest size...
  -
  -<P>
  -You will notice many httpd_perl 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:
  -TERM, HUP, and USR1.
  -
  -<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 TERM 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 END{} blocks will be executed! Note
  -that if you use <STRONG>Apache::Registry</STRONG> or <STRONG>Apache::PerlRun</STRONG>, then END {} 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 HUP signal to the parent causes it to kill off its children
  -like in TERM (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 USR1 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 USR1 and HUP is that USR1 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 HUP signal), Perl scripts and modules are not reloaded. To reload <STRONG>PerlRequire</STRONG>'s, <STRONG>PerlModule</STRONG>'s, other <CODE>use()'d</CODE> modules and flush the Apache::Registry
  -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 PERL_DESTRUCT_LEVEL=-1 option during the
  -mod_perl ./Configure 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 END{} blocks and
  -DESTROY 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 /usr/apps/sbin/httpd_perl/apachectl
  -
  -<P>
  -Start httpd
  -
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl start 
  -</PRE>
  -<P>
  -Stop httpd
  -
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl stop
  -</PRE>
  -<P>
  -Restart httpd if running by sending a SIGHUP or start if not running
  -
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl restart
  -</PRE>
  -<P>
  -Do a graceful restart by sending a SIGUSR1 or start if not running
  -
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl graceful    
  -</PRE>
  -<P>
  -Do a configuration syntax test:
  -
   <P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl configtest 
  -</PRE>
  +<CENTER><H1><A NAME="General_Advice">General Advice</A></H1></CENTER>
   <P>
  -See the next section for the implication of the above calls.
  +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>
  -Replace 'httpd_perl' with 'httpd_docs' in the above calls to control the
  -httpd_docs server.
  -
  +<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>
   <P>
  -There are other options for <STRONG>apachectl</STRONG>, use 'help' option to see them all.
  +See <A HREF="././warnings.html#Use_of_uninitialized_value_at_e">Use of uninitialized value at (eval 80) line 12.</A>
   
  -<P>
  -It's important to understand that this script is based on the PID file
  -which is PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid. If you delete the
  -file by hand - <STRONG>apachectl</STRONG> will fail to run.
   
  -<P>
  -Also, note 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="SUID_start_up_scripts">SUID start-up scripts</A></H1></CENTER>
  -<P>
  -For those who wants to use SUID startup script, here is an example for you.
  -This script is SUID 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.
  -
  +<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>
  -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 ``start_http'', ``stop_http'' or
  -``restart_http''. You can use symbolic links for this purpose.
  +<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>.
   
   <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>
  +<CENTER><H1><A NAME="Value_of_x_may_be_unavailable_a">Value of $x may be unavailable at - line 5.</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.
  +<A HREF="././obvious.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</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="mod_perl_rwrite_returned_1">mod_perl: rwrite returned -1</A></H1></CENTER>
   <P>
  -Crontab entry:
  +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.
   
  -<P>
  -<PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
  -</PRE>
   <P>
  -The script:
  +This bug has been fixed in mod_perl 1.19_01 (CVS version).
   
   <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/apps/var/httpd_perl/run/httpd.pid
  -    
  -  # the path to your httpd binary, including options if necessary
  -  HTTPD=/usr/apps/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
  +<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>  [modperl] caught SIGPIPE in process 1234
  +  [modperl] process 1234 going to Apache::exit with status...
   </PRE>
   <P>
  -Another approach, probably even more practical, is to use the Cool LWP perl
  -package , to test the server by trying to fetch some document (script)
  -served by the server. Why is it more practical? While server can be up as a
  -process, it can be stuck and not working (SYN_RECV state - anyone??? Am I
  -getting a SYNC flood attack), 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.
  +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>
  -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 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.
  +If your mod_perl version &lt; 1.17 you might get the message in the
  +following section...
   
   <P>
  -So we end up with crontab entry:
  -
  +<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>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
  +<PRE>  Client hit STOP or Netscape bit it!
  +  Process 2493 going to Apache::exit with status=-2
   </PRE>
   <P>
  -And the watchdog itself:
  +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>  #!/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);
  -  
  -  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/apps/sbin/httpd_perl/apachectl start';
  -  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>
  +<CENTER><H1><A NAME="Constant_subroutine_redefine">Constant subroutine ... redefined</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.
  +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>
  -<PRE>  % /usr/apps/sbin/httpd_perl/httpd_perl -X
  +<PRE>  &lt;META&gt;
  +  Someone said: 
  +  You won't see that warning in this case with 5.004_05 or 5.005+. 
   </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 Ctrl-C.
  -
   <P>
  -Note that in -X 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 ``KeepAlive'' 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 KeepAlive in httpd.conf 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>  I'm running perl5.00502 and I still get these warnings???
  +</PRE>
   <P>
  -In addition you should know that when running with -X 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>  Who is right?
  +  &lt;/META&gt;
  +</PRE>
   <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>
  +<CENTER><H1><A NAME="Global_symbol_foo_requires_ex">Global symbol &quot;$foo&quot; requires explicit package name</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:
  +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>  httpd_perl -f /path/to/httpd.conf  
  +<PRE>  #!/usr/bin/perl -w
  +  use strict;
  +  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;Hello $undefined&quot;;
   </PRE>
   <P>
  -I have approached it in other way. I have used the -Dparameter startup
  -option of the server. I call my version of the server
  +The warning:
   
   <P>
  -<PRE>  % http_perl -Dsbekman
  +<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>
  -In <CODE>httpd.conf</CODE> I wrote:
  +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>
  -<PRE>  # Personal development Server for sbekman
  -  # sbekman use the server running on port 8000
  -  &lt;IfDefine sbekman&gt;
  -  Port 8000
  -  PidFile /usr/apps/var/httpd_perl/run/httpd.pid.sbekman
  -  ErrorLog /usr/apps/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/apps/var/httpd_perl/run/httpd.pid.userfoo
  -  ErrorLog /usr/apps/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''.
  +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>
  -To make things even easier. (In the above technique, you have to discover
  -the PID of your parent httpd_perl process - written in
  -/usr/apps/var/httpd_perl/run/httpd.pid.userfoo) . 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:
  +As Doug answered to this question:
   
   <P>
  -<PRE>  PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid.sbekman
  -  HTTPD='/usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman'
  +<PRE> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
  + That's what's expected if so.
   </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.
  +It wasn't in my case, but may be yours. 
   
   <P>
  -The last thing was to let developers an option to run in single process
  -mode by:
  +Bryan Miller said:
   
   <P>
  -<PRE>  /usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman -X
  +<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>
  -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><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>
  +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>
  -In access.conf of the httpd_docs server we have the following code: (you
  -have to configure your httpd_docs server with
  -<CODE>--enable-module=rewrite</CODE> )
  +<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>
  +Your code includes some undefined variable that you have used as if it was
  +already defined and initialized. For example:
   
   <P>
  -<PRE>  # sbekman' server
  -  # port = 8000
  -  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  -  RewriteCond  %{REMOTE_ADDR} 123.34.45.56
  -  RewriteRule ^(.*)           <A HREF="http://ourserver.com:8000/">http://ourserver.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://ourserver.com:8001/">http://ourserver.com:8001/</A>$1 [R,L]
  -  
  -  # all the rest
  -  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  -  RewriteRule ^(.*)           <A HREF="http://ourserver.com:81/">http://ourserver.com:81/</A>$1 [R]
  -  
  +<PRE>  $param = $q-&gt;param('test');
  +  print $param;
   </PRE>
   <P>
  -where IP numbers are the IPs of the developers' client machines (where they
  -are running their web browser.) (I have tried to use REMOTE_USER since we
  -have all the users authenticated but it did not work for me)
  -
  +<PRE>  vs.
  +</PRE>
   <P>
  -So if I have a relative URL like <CODE>/perl/test.pl</CODE> written in some html or even <A
  -HREF="http://ourserver.com/perl/test.pl">http://ourserver.com/perl/test.pl</A>
  -in my case (user at machine of sbekman) it will be redirected by httpd_docs
  -to <A
  -HREF="http://ourserver.com:8000/perl/test.pl">http://ourserver.com:8000/perl/test.pl</A>
  -
  -
  +<PRE>  $param = $q-&gt;param('test') || '';
  +  print $param;
  +</PRE>
   <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:
  +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>
  -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 POST (redirect looses all the data!).
  +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>
  -Second, use a general configuration module which generates a correct full
  -URL according to REMOTE_USER, so if <CODE>$ENV{REMOTE_USER} eq
  -'sbekman'</CODE>, I return <A
  -HREF="http://ourserver.com:8000/perl/">http://ourserver.com:8000/perl/</A>
  -as
  -<CODE>cgi_base_url</CODE>. Again this will work if the user is authenticated.
  -
  +<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>
   <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.
  +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="Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</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>
  -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 PERL5LIB
  -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.
  +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>
  -The best debugging approach is to write a wrapper that emulates the exact
  -environment of the server, by first deleting the environment variables like
  -PERL5LIB 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.
  +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>
  -Below is the example of such a script. Note that we force the -Tw 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)
  +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>  #!/usr/apps/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/apps&quot;;
  -  
  -    # we want to make a complete emulation, so we must remove the
  -    # user's environment
  -    @INC = ();
  -  
  -    # local perl libs
  -    push @INC, (&quot;$basedir/lib/perl5/5.00502/aix&quot;,
  -                &quot;$basedir/lib/perl5/5.00502&quot;,
  -                &quot;$basedir/lib/perl5/site_perl/5.005/aix&quot;,
  -                &quot;$basedir/lib/perl5/site_perl/5.005&quot;,
  -               );
  -  }
  -  
  -  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 Taintness ON!!!
  -  system qq{$basedir/bin/perl -I$PERL5LIB -Tw $cgi $params};
  +<PRE>  % ./Configure -des -Dcc=gcc ... &amp;&amp; make test &amp;&amp; make install
  + 
  +Read Perl's INSTALL doc 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="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...
  +Solaris OS specific: 
   
   <P>
  -To rotate the logs do:
  +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>  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>  -Xlinker -E
   </PRE>
   <P>
  -The effect of SIGUSR1 and SIGHUP is detailed in: <A
  -HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
  -
  +This problem is only known to be caused by installing gnu ld under Solaris.
   
  +<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>
   <P>
  -&lt;META&gt;I tried to kill -USR1 and it did not reset the logs!!! kill
  --HUP did work&lt;/META&gt;
  +See <A HREF="#Out_of_memory_">Out_of_memory!</A>
  +
   
  +
   <P>
  -I use this script:
  +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:
   
   <P>
  -<PRE>  #!/usr/apps/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/apps/var/$server/logs&quot;;
  -  my $restart_command = &quot;/usr/apps/sbin/$server/apachectl restart&quot;;
  -  my $gzip_exec = &quot;/usr/intel/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>  Callback called exit at -e line 33, &lt;HTML&gt; chunk 1.
   </PRE>
   <P>
  -Randal L. Schwartz contributed this:
  +Why the looping?
   
  -<BLOCKQUOTE>
  +<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.
   
   <P>
  -Cron fires off setuid script called log-roller that looks like this:
  +Perl 5.005+ plus is recommended for its improved malloc.c and features
  +mentioned in mod_perl_traps.pod on by default.
   
   <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><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>
   <P>
  -And then individual MIDNIGHT scripts can look like this:
  +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>    #!/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>  =item -DPERL_EMERGENCY_SBRK
   </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.
  -
  -</BLOCKQUOTE>
  +<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>
  +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.
   
   <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>
  +<CENTER><H1><A NAME="_warn_child_process_30388_did_n">[warn] child process 30388 did not exit, sending another SIGHUP</A></H1></CENTER>
   <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:
  +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>
  -<PRE>  sub UNIVERSAL::AUTOLOAD {
  -          my $class = shift;
  -          warn &quot;$class can't \$UNIVERSAL::AUTOLOAD!\n&quot;;
  -  }
  +<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>
  -It will produce a nice error in error_log, giving the line number of the
  -call and the name of the undefined subroutine.
  +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>
  -Sometimes an error happens and causes the server to write millions of lines
  -into your error_log 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 error_log files 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="Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A></H1></CENTER>
  +<P>
  +Not all Perl modules can survive a reload. PerlFreshRestart does not much
  +more than:
   
   <P>
  -<PRE>  S=`ls -s /usr/local/apache/logs/error_log | awk '{print $1}'`
  -  if [ &quot;$S&quot; -gt 100000 ] ; then
  -    /etc/rc.d/init.d/httpd restart
  -    date | /bin/mail -s &quot;error_log $S kB on inx&quot; myemail@domain.com
  -  fi
  +<PRE>  while (my($k,$v) = each %INC) {
  +    delete $INC{$k};
  +    require $k;
  +  }
   </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.
  +Besides that, it flushes the Apache::Registry cache, and empties any
  +dynamic stacked handlers (e.g. PerlChildInitHandler).
   
   <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>
  -
  +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>
  -<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>
  +<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><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>
  @@ -10463,7 +11034,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]
  +	     [    <A HREF="obvious.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>
  @@ -10476,7 +11047,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/15/1999
  +	     <BR>Last Modified at 06/19/1999
         </FONT>
       </B>
     </TD>
  @@ -10524,7 +11095,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="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="warnings.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>
   
  @@ -10729,7 +11300,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]
  +	     [    <A HREF="warnings.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>
  @@ -10742,7 +11313,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/17/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -11717,13 +12288,13 @@
     # Quote the list of parameters , alldigits parameters are unquoted (int)
     # print sql_quote(&quot;one&quot;,2,&quot;three&quot;); =&gt; 'one' 2 'three'
     #############
  -  sub sql_quote{ map{ /^(\d+|NULL)$/ ? $_ : &quot;'$_'&quot; } @_ }
  +  sub sql_quote{ map{ /^(\d+|NULL)$/ ? $_ : &quot;\'$_\'&quot; } @_ }
     
     # Escape the list of parameters (all unsafe chars like &quot;,' are escaped )
     # must make a copy of @_ since we might try to change the passed
     # (Modification of a read-only value attempted)
     ##############
  -  sub sql_escape{ my @a = @_; map { s/(['])/\\$1/g;$_} @a }
  +  sub sql_escape{ my @a = @_; map { s/([\'])/\\$1/g;$_} @a }
     
     
     # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  @@ -11929,7 +12500,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -12199,7 +12770,7 @@
     
     BEGIN {
         # RCS/CVS complient:  must be all one line, for MakeMaker
  -    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.14 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.15 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
     
     }
     
  @@ -12419,7 +12990,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/08/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -12679,7 +13250,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 04/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -12868,7 +13439,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 04/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -13254,7 +13825,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/05/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -13587,16 +14158,16 @@
   <CENTER><H1><A NAME="Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A></H1></CENTER>
   <P>
   Have you ever served a huge HTML file (e.g. a file bloated with JavaScript
  -code) and wandered how could you compress it, thus drammatically cutting
  -down the download times. After all java applets can be compressed into a
  -jar and benefit from a faster download. Why cannot we do the same with a
  -plain ASCII (HTML,JS and etc), it is a known fact that ASCII can be
  -compressed 10 times smaller than the original size.
  +code) and wandered how could you send it compressed, thus drammatically
  +cutting down the download times. After all java applets can be compressed
  +into a jar and benefit from a faster download times. Why cannot we do the
  +same with a plain ASCII (HTML,JS and etc), it is a known fact that ASCII
  +text can be compressed by a factor of 10.
   
   <P>
  -<CODE>Apache::GzipChain</CODE> comes to help you with this task. If a client (browser) understands <CODE>gzip</CODE> encoding this module compresses the output and send it downstream. A client
  -decompress the data upon receive and renders the HTML as if it was a plain
  -HTML fetch.
  +<CODE>Apache::GzipChain</CODE> comes to help you with this task. If a client (browser) understands <CODE>gzip</CODE> encoding this module compresses the output and sends it downstream. A
  +client decompresses the data upon receive and renders the HTML as if it was
  +a plain HTML fetch.
   
   <P>
   For example to compress all html files on the fly, do:
  @@ -13608,7 +14179,7 @@
     &lt;/Files&gt;
   </PRE>
   <P>
  -Remember that it will work only if the browsers claims to accept compressed
  +Remember that it will work only if the browser claims to accept compressed
   input, thru <CODE>Accept-Encoding</CODE> header. <CODE>Apache::GzipChain</CODE>
   keeps a list of user-agents, thus it also looks at <CODE>User-Agent</CODE>
   header, for known to accept compressed output browsers.
  @@ -13619,15 +14190,16 @@
   
   <P>
   <PRE>  &lt;Location /test&gt;
  -    SetHandler &quot;perl-script&quot;
  +    SetHandler perl-script
       PerlHandler Apache::OutputChain Apache::GzipChain Apache::EmbperlChain Apache::PassFile
     &lt;/Location&gt;
   </PRE>
   <P>
  -Hint: Watch an <CODE>access_log</CODE> file to see how many bytes were actually send.
  +Hint: Watch an <CODE>access_log</CODE> file to see how many bytes were actually send, compare with a regular
  +configuration send.
   
   <P>
  -See the module's documentaion for more details.
  +(See <CODE>perldoc Apache::GzipChain</CODE>).
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -13697,7 +14269,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/15/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -14835,7 +15407,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  @@ -15359,7 +15931,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.16      +204 -117  modperl-site/guide/config.html
  
  Index: config.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/config.html,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- config.html	1999/06/19 21:15:02	1.15
  +++ config.html	1999/07/02 13:42:17	1.16
  @@ -33,13 +33,19 @@
   		<LI><A HREF="#Location_Configuration">Location Configuration</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="#Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</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>
  @@ -84,19 +90,19 @@
   <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's configuration files. 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 conf directory and follow the instructions in these files - the embedded
  +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 the mod_perl configuration, configure Apache, and see that
  -it works. When done, return here to continue...
  +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
  +[ 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
  @@ -106,8 +112,8 @@
   <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 location where all mod_perl scripts will be
  -located.
  +First, you need to specify the locations on a file-system for the scripts
  +to be found.
   
   <P>
   Add the following configuration directives:
  @@ -129,37 +135,43 @@
   <P>
   Alias defines the start of the URL path to the script you are referencing.
   For example, using the above configuration, fetching
  -<STRONG>http://www.you.com/perl/test.pl</STRONG>, will cause the server to look for the file <STRONG>test.pl</STRONG> at <STRONG>/usr/local/myproject/cgi</STRONG>, and execute it as an <STRONG>Apache::Registry</STRONG> script if we define Apache::Register to be the handler of <CODE>/perl</CODE> location (see below). The URL
  -<STRONG>http://www.you.com/perl/test.pl</STRONG> will be mapped to
  -<STRONG>/usr/local/myproject/cgi/test.pl</STRONG>. This means you can have all your CGIs located at the same place at file
  -system, and call the script in any of three modes simply by changing the
  -directory name component of the URL (cgi-bin|perl|cgi-perl) - is not this
  -cool? (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 an <CODE>Alias</CODE>
  -directive + <CODE>sethandler cgi-handler</CODE>. 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
  -http.conf), you can choose to use all three modes or only one of these (It
  -is undesirable to run plain cgi-bin scripts from a mod_perl-enabled server
  -- the price is too high, it is better to run these on plain Apache server.
  -(META: add link to strategies)
  +<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 at
  +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 plain cgi-bin scripts 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.
  +apache configurations.
   
   <P>
   First we add:
  @@ -175,40 +187,41 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  -This configuration causes all scripts that are called with a <STRONG>/perl</STRONG>
  -path prefix to be executed under the <STRONG>Apache::Registry</STRONG> 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 will possibly will trigger a 'Save-As' window).
  +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>
  -<STRONG>PerlSendHeader On</STRONG> tells the server to send an HTTP header to the browser on every script
  +<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
  -CGI-&gt;header or $r-&gt;send_http_header directly.
  +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-</CODE>header&gt; 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 Alias here, if you use
  -Location that does not have the same Alias defined in srm.conf, the server
  -will fail to locate the script in the file system. (We are talking about
  -script execution here -- there are cases where Location is something that
  -is being executed by the server itself, without having the corresponding
  -file, like <A HREF="#_perl_status_location">perl-status location</A>.)
  +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 : PerlModule Apache::Registry
  +Note that sometimes you will have to add :
   
  +<P>
  +<PRE>  PerlModule Apache::Registry
  +</PRE>
   <P>
  -before you specify the location that uses Apache::Registry as a
  -PerlHandler. Basically you can start running the scripts in the
  -Apache::Registry mode...
  +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 to do nothing about /cgi-bin (mod_cgi), since it has nothing to do
  -with mod_perl
  +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 Apache::PerlRun. (More about
  -<A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun</A>)
  +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;
  @@ -224,34 +237,110 @@
   <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 <STRONG>PerlRequire</STRONG>, <STRONG>PerlModule</STRONG>, other <CODE>use()'d</CODE> modules and flush the Apache::Registry cache
  -on server restart, add:
  +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>
  -Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
  +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><H2><A NAME="_perl_status_location">/perl-status location</A></H2></CENTER>
  +<CENTER><H3><A NAME="Configuration">Configuration</A></H3></CENTER>
   <P>
  -Adding a directive to enable a <STRONG>/perl-status</STRONG> location allows you to see many things about your server. See
  -<A HREF="././status.html#Configuration">perl-status</A>
  +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>
  -Set and Pass the ENV variables to your scripts. So you can read them in
  -your scripts from <CODE>%ENV</CODE> (e.g. <CODE>$ENV{&quot;key&quot;}</CODE>)
  +<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>
   <CODE>PerlSetVar</CODE> is very similar to <CODE>PerlSetEnv</CODE>, but you extract it with another method. In &lt;Perl&gt; sections:
  @@ -271,10 +360,8 @@
   <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 one file, so the
  -configuration file will be cleaner, also you can call
  -<STRONG>perl -c perl-startup</STRONG> to test the file's syntax. What does this take? Add this line to
  -httpd.conf:
  +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
  @@ -282,6 +369,12 @@
     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>
  @@ -290,8 +383,8 @@
   <P>
   <PRE>  use strict;
     
  -  #modify @INC if needed
  -  use lib qw(/some/other/dir /some/bar/dir);
  +  # extend @INC if needed
  +  use lib qw(/dir/foo /dir/bar);
     
     # make sure we are in a sane environment.
     $ENV{GATEWAY_INTERFACE} =~ /^CGI-Perl/
  @@ -315,8 +408,7 @@
     CGI-&gt;compile(':all');
   </PRE>
   <P>
  -Note that starting with CGI::VERSION 2.46, the recommended method to
  -precompile the code in CGI.pm is:
  +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);
  @@ -335,22 +427,11 @@
   <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. 
  +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>
  -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="Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</A></H3></CENTER>
  -<P>
  -Yes! See <A HREF="././performance.html#Persistent_DB_Connections">Persistent DB Connections</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>
  @@ -383,18 +464,21 @@
   </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 some tags to be exported by default and when write:
  +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 you 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 correctly.
  +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 needs a <CODE>Foo</CODE>'s module functionality 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 a startup script does not mean you can have the following handler:
  +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;
  @@ -423,23 +507,24 @@
   <PRE>  return Apache::Constants::OK;
   </PRE>
   <P>
  -See the manpage/perldoc on <CODE>Exporter</CODE> and <CODE>perlmod</CODE> for more on import.
  +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 preload modules and do a few 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 accessable by child processes.
  +<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 is a specially
  +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.
  +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>
  @@ -447,29 +532,30 @@
   <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% errorprone,
  -but it will reveal any syntaxical errors you might do while editing the
  -file.
  +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. &lt;Perl&gt; configuration has always started Perl during the configuration
  -read,
  +'<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>
  -(configtest) server launch, start the server configuration test with 
  +(<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:
  +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>
  @@ -505,13 +591,13 @@
   <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 <STRONG>&lt;Perl&gt;&lt;/Perl&gt;</STRONG> sections, it is possible to configure your server entirely in Perl.
  +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
  +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:
   
  @@ -529,8 +615,8 @@
     &lt;/Perl&gt;
   </PRE>
   <P>
  -Block sections such as &lt;Location&gt;&lt;/Location&gt; are represented in
  -a %Hash, e.g.:
  +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;} = {
  @@ -557,8 +643,8 @@
     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 <STRONG>%VirtualHost</STRONG>, <STRONG>%Directory</STRONG> and
  -<STRONG>%Files</STRONG>.
  +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
  @@ -592,13 +678,14 @@
     &lt;/Perl&gt;
   </PRE>
   <P>
  -Now you may run <STRONG>perl -cx httpd.conf</STRONG>.
  +Now you may run:
   
   <P>
  -To configure this feature build with <STRONG>perl Makefile.PL 
  -PERL_SECTIONS=1</STRONG>
  -
  -
  +<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>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -900,7 +987,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/05/1999
  +	     <BR>Last Modified at 07/02/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.16      +92 -113   modperl-site/guide/control.html
  
  Index: control.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/control.html,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- control.html	1999/06/19 21:15:02	1.15
  +++ control.html	1999/07/02 13:42:19	1.16
  @@ -22,7 +22,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>
   Controlling and Monitoring the Server</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -81,22 +81,22 @@
   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 httpd.conf), but it's still easy to know 'who is the
  -parent' -- the one of the smallest size...
  +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 httpd_perl 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:
  -TERM, HUP, and USR1.
  +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
  +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>
   .
  @@ -104,21 +104,20 @@
   <DL>
   <P><DT><STRONG><A NAME="item_TERM">TERM Signal: stop now</A></STRONG><DD>
   <P>
  -Sending the TERM 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. 
  +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 END{} blocks will be executed! Note
  -that if you use <STRONG>Apache::Registry</STRONG> or <STRONG>Apache::PerlRun</STRONG>, then END {} blocks are being executed upon each request (at the end).
  +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 HUP signal to the parent causes it to kill off its children
  -like in TERM (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.
  +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
  @@ -132,21 +131,21 @@
   
   <P><DT><STRONG><A NAME="item_USR1">USR1 Signal: graceful restart</A></STRONG><DD>
   <P>
  -The USR1 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
  +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 USR1 and HUP is that USR1 allows children to
  -complete any in-progress request prior to killing them off.
  +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 HUP signal), Perl scripts and modules are not reloaded. To reload <STRONG>PerlRequire</STRONG>'s, <STRONG>PerlModule</STRONG>'s, other <CODE>use()'d</CODE> modules and flush the Apache::Registry
  -cache, enable with this command:
  +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) 
  @@ -157,20 +156,17 @@
   </DL>
   <P>
   It's worth mentioning that restart or termination can sometimes take quite
  -a lot of time. Check out the PERL_DESTRUCT_LEVEL=-1 option during the
  -mod_perl ./Configure 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 END{} blocks and
  -DESTROY 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.
  +a lot of time. Check out the <CODE>PERL_DESTRUCT_LEVEL=-1</CODE> option during the mod_perl <CODE>./Configure</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:
  +<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 */ 
  @@ -183,28 +179,29 @@
   <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 /usr/apps/sbin/httpd_perl/apachectl
  +it's
  +<CODE>/usr/apps/sbin/httpd_perl/apachectl</CODE>.
   
   <P>
  -Start httpd
  +Start httpd:
   
   <P>
   <PRE>        % /usr/apps/sbin/httpd_perl/apachectl start 
   </PRE>
   <P>
  -Stop httpd
  +Stop httpd:
   
   <P>
   <PRE>        % /usr/apps/sbin/httpd_perl/apachectl stop
   </PRE>
   <P>
  -Restart httpd if running by sending a SIGHUP or start if not running
  +Restart httpd if running by sending a <STRONG>SIGHUP</STRONG> or start if not running:
   
   <P>
   <PRE>        % /usr/apps/sbin/httpd_perl/apachectl restart
   </PRE>
   <P>
  -Do a graceful restart by sending a SIGUSR1 or start if not running
  +Do a graceful restart by sending a <STRONG>SIGUSR1</STRONG> or start if not running:
   
   <P>
   <PRE>        % /usr/apps/sbin/httpd_perl/apachectl graceful    
  @@ -219,19 +216,17 @@
   See the next section for the implication of the above calls.
   
   <P>
  -Replace 'httpd_perl' with 'httpd_docs' in the above calls to control the
  -httpd_docs server.
  +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 'help' option to see them all.
  +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 PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid. If you delete the
  -file by hand - <STRONG>apachectl</STRONG> will fail to run.
  +which is <CODE>PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid</CODE>. If you delete the file by hand - <STRONG>apachectl</STRONG> will fail to run.
   
   <P>
  -Also, note that <STRONG>apachectl</STRONG> is suitable to use from within your Unix system's startup files so that
  +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
  @@ -243,8 +238,7 @@
   <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 SUID startup script, here is an example for you.
  -This script is SUID to <STRONG>root</STRONG>, and should be executable only by members of some special group at your
  +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
  @@ -253,8 +247,8 @@
   <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 ``start_http'', ``stop_http'' or
  -``restart_http''. You can use symbolic links for this purpose.
  +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
  @@ -314,7 +308,7 @@
   sure the server will be up all the time.
   
   <P>
  -Crontab entry:
  +The crontab entry:
   
   <P>
   <PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
  @@ -367,13 +361,12 @@
     fi
   </PRE>
   <P>
  -Another approach, probably even more practical, is to use the Cool LWP perl
  -package , to test the server by trying to fetch some document (script)
  +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? While server can be up as a
  -process, it can be stuck and not working (SYN_RECV state - anyone??? Am I
  -getting a SYNC flood attack), 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.
  +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.
  @@ -493,22 +486,21 @@
   </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 Ctrl-C.
  +the shell you have called it from. So to kill you just kill it with
  +<STRONG>Ctrl-C</STRONG>.
   
   <P>
  -Note that in -X 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 ``KeepAlive'' 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 KeepAlive in httpd.conf 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
  +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 -X 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
  +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.
   
  @@ -529,8 +521,8 @@
   <PRE>  httpd_perl -f /path/to/httpd.conf  
   </PRE>
   <P>
  -I have approached it in other way. I have used the -Dparameter startup
  -option of the server. I call my version of the server
  +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
  @@ -578,7 +570,7 @@
   <P>
   To make things even easier. (In the above technique, you have to discover
   the PID of your parent httpd_perl process - written in
  -/usr/apps/var/httpd_perl/run/httpd.pid.userfoo) . We change the
  +<CODE>/usr/apps/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>
  @@ -627,34 +619,28 @@
     
   </PRE>
   <P>
  -where IP numbers are the IPs of the developers' client machines (where they
  -are running their web browser.) (I have tried to use REMOTE_USER since we
  -have all the users authenticated but it did not work for me)
  +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 <A
  -HREF="http://ourserver.com/perl/test.pl">http://ourserver.com/perl/test.pl</A>
  -in my case (user at machine of sbekman) it will be redirected by httpd_docs
  -to <A
  -HREF="http://ourserver.com:8000/perl/test.pl">http://ourserver.com:8000/perl/test.pl</A>
  +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 httpd_docs to
  +<CODE>http://www.nowhere.com:8000/perl/test.pl</CODE>.
   
  -
   <P>
  -Of course you have another problem: The cgi generates some html, which
  +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 POST (redirect looses all the data!).
  +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 REMOTE_USER, so if <CODE>$ENV{REMOTE_USER} eq
  -'sbekman'</CODE>, I return <A
  -HREF="http://ourserver.com:8000/perl/">http://ourserver.com:8000/perl/</A>
  -as
  +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>
  @@ -671,23 +657,21 @@
   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 PERL5LIB
  -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.
  +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
  -PERL5LIB 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.
  +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 -Tw 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)
  +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/apps/bin/perl -w    
  @@ -761,13 +745,9 @@
     .....
   </PRE>
   <P>
  -The effect of SIGUSR1 and SIGHUP is detailed in: <A
  +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>
  -&lt;META&gt;I tried to kill -USR1 and it did not reset the logs!!! kill
  --HUP did work&lt;/META&gt;
  +.
   
   <P>
   I use this script:
  @@ -924,12 +904,11 @@
   
   <P>
   Sometimes an error happens and causes the server to write millions of lines
  -into your error_log 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 error_log files 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:
  +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}'`
  @@ -950,7 +929,7 @@
   <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>  ,-----
  @@ -971,7 +950,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.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>
  @@ -984,7 +963,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/15/1999
  +	     <BR>Last Modified at 06/27/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.5       +3 -3      modperl-site/guide/databases.html
  
  Index: databases.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/databases.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- databases.html	1999/06/19 21:15:03	1.4
  +++ databases.html	1999/07/02 13:42:20	1.5
  @@ -949,13 +949,13 @@
     # Quote the list of parameters , alldigits parameters are unquoted (int)
     # print sql_quote(&quot;one&quot;,2,&quot;three&quot;); =&gt; 'one' 2 'three'
     #############
  -  sub sql_quote{ map{ /^(\d+|NULL)$/ ? $_ : &quot;'$_'&quot; } @_ }
  +  sub sql_quote{ map{ /^(\d+|NULL)$/ ? $_ : &quot;\'$_\'&quot; } @_ }
     
     # Escape the list of parameters (all unsafe chars like &quot;,' are escaped )
     # must make a copy of @_ since we might try to change the passed
     # (Modification of a read-only value attempted)
     ##############
  -  sub sql_escape{ my @a = @_; map { s/(['])/\\$1/g;$_} @a }
  +  sub sql_escape{ my @a = @_; map { s/([\'])/\\$1/g;$_} @a }
     
     
     # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  @@ -1161,7 +1161,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.5       +1 -1      modperl-site/guide/dbm.html
  
  Index: dbm.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/dbm.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- dbm.html	1999/06/19 21:15:03	1.4
  +++ dbm.html	1999/07/02 13:42:21	1.5
  @@ -244,7 +244,7 @@
     
     BEGIN {
         # RCS/CVS complient:  must be all one line, for MakeMaker
  -    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.4 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.5 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
     
     }
     
  @@ -464,7 +464,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/08/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.14      +1 -1      modperl-site/guide/debug.html
  
  Index: debug.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/debug.html,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- debug.html	1999/06/19 21:15:03	1.13
  +++ debug.html	1999/07/02 13:42:22	1.14
  @@ -360,7 +360,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/05/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.6       +2 -2      modperl-site/guide/frequent.html
  
  Index: frequent.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/frequent.html,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- frequent.html	1999/06/19 21:15:03	1.5
  +++ frequent.html	1999/07/02 13:42:22	1.6
  @@ -22,7 +22,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>
   Frequent mod_perl problems</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -79,7 +79,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="config.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]
  +	     [    <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>
  
  
  
  1.8       +820 -805  modperl-site/guide/guide-src.tar.gz
  
  	<<Binary file>>
  
  
  1.9       +1400 -1297modperl-site/guide/guide.tar.gz
  
  	<<Binary file>>
  
  
  1.4       +1 -1      modperl-site/guide/hardware.html
  
  Index: hardware.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/hardware.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- hardware.html	1999/06/19 21:15:09	1.3
  +++ hardware.html	1999/07/02 13:42:27	1.4
  @@ -469,7 +469,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.15      +1 -1      modperl-site/guide/help.html
  
  Index: help.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/help.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- help.html	1999/06/19 21:15:09	1.14
  +++ help.html	1999/07/02 13:42:27	1.15
  @@ -340,7 +340,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.18      +135 -122  modperl-site/guide/index.html
  
  Index: index.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/index.html,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- index.html	1999/06/19 21:15:09	1.17
  +++ index.html	1999/07/02 13:42:28	1.18
  @@ -27,8 +27,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.13
  - Jun, 19 1999</B></P></CENTER>
  +<CENTER><P><B>Version 1.14
  + Jul, 2 1999</B></P></CENTER>
    
   <P>
   <HR WIDTH="100%"></P>
  @@ -54,6 +54,98 @@
   
   	<LI><A HREF="start.html#What_s_inside_">What's inside?</A>
   </UL>
  +<P><LI><A HREF="porting.html"><B><FONT SIZE=+1>CGI to mod_perl Porting. mod_perl Coding guidelines.</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="porting.html#Document_Coverage">Document Coverage</A>
  +	<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>
  +	<UL>
  +
  +		<LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
  +		<LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  +		<LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  +		<LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
  +		<LI><A HREF="porting.html#Using_format_">Using format()</A>
  +		<LI><A HREF="porting.html#Using_exit_">Using exit()</A>
  +		<LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
  +		<LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
  +		<LI><A HREF="porting.html#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  +		<LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  +		<LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
  +		<LI><A HREF="porting.html#END_blocks">END blocks</A>
  +		<LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
  +		<LI><A HREF="porting.html#strict_pragma">strict pragma</A>
  +		<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#Memory_leakage">Memory leakage</A>
  +	</UL>
  +
  +	<LI><A HREF="porting.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  +	<UL>
  +
  +		<LI><A HREF="porting.html#Restarting_the_server">Restarting the server</A>
  +		<LI><A HREF="porting.html#Using_Apache_StatINC">Using Apache::StatINC</A>
  +		<LI><A HREF="porting.html#Reloading_only_specific_files">Reloading only specific files</A>
  +	</UL>
  +
  +	<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#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_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
  +	<LI><A HREF="porting.html#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</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#Sharing_Memory">Sharing Memory</A>
  +	<LI><A HREF="performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
  +	<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</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 (and where)</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>
  +	<LI><A HREF="performance.html#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Developers_Talk">Developers Talk</A>
  +		<LI><A HREF="performance.html#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
  +		<LI><A HREF="performance.html#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
  +		<LI><A HREF="performance.html#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench </A>
  +		<LI><A HREF="performance.html#Tuning_with_crashme_script">Tuning with crashme script</A>
  +		<LI><A HREF="performance.html#Choosing_MaxClients">Choosing MaxClients</A>
  +		<LI><A HREF="performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A>
  +		<LI><A HREF="performance.html#Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A>
  +		<LI><A HREF="performance.html#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
  +	<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>
  +</UL>
   <P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Choosing the Right Strategy</FONT></B></A></LI><P>
   <UL>
   
  @@ -63,13 +155,12 @@
   	<LI><A HREF="strategy.html#One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl-enabled Apache Servers</A>
   	<LI><A HREF="strategy.html#One_light_non_Apache_and_One_mod">One light non-Apache and One mod_perl enabled Apache Servers</A>
   	<LI><A HREF="strategy.html#Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A>
  -	<LI><A HREF="strategy.html#squid_server">squid server</A>
  -	<LI><A HREF="strategy.html#apache_s_mod_proxy">apache's mod_proxy</A>
  +	<LI><A HREF="strategy.html#The_Squid_Server">The Squid Server</A>
  +	<LI><A HREF="strategy.html#An_Apache_s_mod_proxy">An Apache's mod_proxy</A>
   </UL>
  -<P><LI><A HREF="scenario.html"><B><FONT SIZE=+1>Real World Scenarios Implementaion</FONT></B></A></LI><P>
  +<P><LI><A HREF="scenario.html"><B><FONT SIZE=+1>Real World Scenarios Implementation</FONT></B></A></LI><P>
   <UL>
   
  -	<LI><A HREF="scenario.html#Before_you_dive_into_the_gory_de">Before you dive into the gory details</A>
   	<LI><A HREF="scenario.html#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
   	<UL>
   
  @@ -85,7 +176,7 @@
   		<UL>
   
   			<LI><A HREF="scenario.html#Building_the_httpd_docs_Server">Building the httpd_docs Server</A>
  -			<LI><A HREF="scenario.html#Building_the_httpd_perl_Server_">Building the httpd_perl Server (mod_perl):</A>
  +			<LI><A HREF="scenario.html#Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A>
   		</UL>
   
   		<LI><A HREF="scenario.html#Configuration_of_the_servers">Configuration of the servers</A>
  @@ -109,12 +200,12 @@
   	<LI><A HREF="install.html#Configuration_and_Installation">Configuration and Installation</A>
   	<UL>
   
  -		<LI><A HREF="install.html#Perl">Perl</A>
  -		<LI><A HREF="install.html#Apache">Apache</A>
  -		<LI><A HREF="install.html#Mod_Perl">Mod_Perl</A>
  +		<LI><A HREF="install.html#perl">perl</A>
  +		<LI><A HREF="install.html#apache">apache</A>
  +		<LI><A HREF="install.html#mod_perl">mod_perl</A>
   	</UL>
   
  -	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is really installed</A>
  +	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
   	<UL>
   
   		<LI><A HREF="install.html#Testing_by_checking_the_error_lo">Testing by checking the error_log file</A>
  @@ -146,13 +237,19 @@
   		<LI><A HREF="config.html#Location_Configuration">Location Configuration</A>
   		<LI><A HREF="config.html#PerlFreshRestart">PerlFreshRestart</A>
   		<LI><A HREF="config.html#_perl_status_location">/perl-status location</A>
  +		<UL>
  +
  +			<LI><A HREF="config.html#Configuration">Configuration</A>
  +			<LI><A HREF="config.html#Usage">Usage</A>
  +			<LI><A HREF="config.html#Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A>
  +		</UL>
  +
   		<LI><A HREF="config.html#PerlSetVar_PerlSetEnv_and_PerlP">PerlSetVar, PerlSetEnv and PerlPassEnv</A>
   		<LI><A HREF="config.html#perl_startup_file">perl-startup file</A>
   		<UL>
   
   			<LI><A HREF="config.html#Sample_perl_startup_file">Sample perl-startup file</A>
   			<LI><A HREF="config.html#What_modules_should_you_add_to_t">What modules should you add to the startup file and why.</A>
  -			<LI><A HREF="config.html#Is_it_possible_to_preopen_a_DB_c">Is it possible to preopen a DB connection at the server startup?</A>
   			<LI><A HREF="config.html#The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A>
   			<LI><A HREF="config.html#The_confusion_with_defining_glob">The confusion with defining globals in startup</A>
   		</UL>
  @@ -185,94 +282,20 @@
   	<LI><A HREF="frequent.html#Coverage">Coverage</A>
   	<LI><A HREF="frequent.html#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
   	<LI><A HREF="frequent.html#Segfaults_caused_by_PerlFreshRes">Segfaults caused by PerlFreshRestart</A>
  -</UL>
  -<P><LI><A HREF="porting.html"><B><FONT SIZE=+1>CGI to mod_perl Porting. mod_perl Coding guidelines.</FONT></B></A></LI><P>
  -<UL>
  -
  -	<LI><A HREF="porting.html#Document_Coverage">Document Coverage</A>
  -	<LI><A HREF="porting.html#Before_you_start_to_code">Before you start to code</A>
  -	<LI><A HREF="porting.html#Coding_with_mod_perl">Coding with mod_perl</A>
  -	<UL>
  -
  -		<LI><A HREF="porting.html#What_s_different_about_modperl">What's different about modperl</A>
  -		<UL>
  -
  -			<LI><A HREF="porting.html#Script_s_name_space">Script's name space</A>
  -			<LI><A HREF="porting.html#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  -			<LI><A HREF="porting.html#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  -			<LI><A HREF="porting.html#Output_from_system_calls">Output from system calls</A>
  -			<LI><A HREF="porting.html#Using_format_">Using format()</A>
  -			<LI><A HREF="porting.html#Using_exit_">Using exit()</A>
  -			<LI><A HREF="porting.html#Running_from_shell">Running from shell</A>
  -			<LI><A HREF="porting.html#I_O_is_different">I/O is different</A>
  -			<LI><A HREF="porting.html#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  -			<LI><A HREF="porting.html#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  -			<LI><A HREF="porting.html#BEGIN_blocks">BEGIN blocks </A>
  -			<LI><A HREF="porting.html#END_blocks">END blocks </A>
  -			<LI><A HREF="porting.html#Switches_w_T">Switches -w, -T</A>
  -		</UL>
  -
  -		<LI><A HREF="porting.html#strict_pragma">strict pragma</A>
  -		<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#Global_Variables">Global Variables</A>
  -		<LI><A HREF="porting.html#Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</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#Memory_leakage">Memory leakage</A>
  -	</UL>
  -
  -	<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
  -	<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</A>
  -	<LI><A HREF="porting.html#The_Script_is_too_dirty_It_does">The Script is too dirty, 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#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_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</A>
  -	<LI><A HREF="porting.html#Generating_correct_HTTP_MIME_Hea">Generating correct HTTP MIME Headers</A>
   </UL>
  -<P><LI><A HREF="performance.html"><B><FONT SIZE=+1>Performance. Benchmarks.</FONT></B></A></LI><P>
  +<P><LI><A HREF="control.html"><B><FONT SIZE=+1>Controlling and Monitoring the Server</FONT></B></A></LI><P>
   <UL>
  -
  -	<LI><A HREF="performance.html#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
  -	<UL>
  -
  -		<LI><A HREF="performance.html#Preload_Perl_modules_Real_Numb">Preload Perl modules - Real Numbers</A>
  -	</UL>
  -
  -	<LI><A HREF="performance.html#Preload_Registry_Scripts">Preload Registry Scripts</A>
  -	<LI><A HREF="performance.html#Sharing_Memory">Sharing Memory</A>
  -	<LI><A HREF="performance.html#Avoid_Importing_Functions">Avoid Importing Functions</A>
  -	<LI><A HREF="performance.html#How_can_I_find_if_my_modperl_scr">How can I find if my modperl scripts have memory leaks (and where)</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>
  -	<LI><A HREF="performance.html#Benchmarks_Impressing_your_Boss">Benchmarks. Impressing your Boss and Colleagues.</A>
  -	<UL>
  -
  -		<LI><A HREF="performance.html#Developers_Talk">Developers Talk</A>
  -		<LI><A HREF="performance.html#Benchmarking_a_Graphic_hits_coun">Benchmarking a Graphic hits counter with Persistent DB Connection</A>
  -		<LI><A HREF="performance.html#Benchmarking_scripts_with_execut">Benchmarking scripts with execution times below 1 second :)</A>
  -		<LI><A HREF="performance.html#PerlHandler_s_Benchmarking">PerlHandler's Benchmarking</A>
  -	</UL>
  -
  -	<LI><A HREF="performance.html#Tuning_the_Apache_s_configuratio">Tuning the Apache's configuration variables for the best performance</A>
  -	<UL>
   
  -		<LI><A HREF="performance.html#Tuning_with_ab_ApacheBench">Tuning with ab - ApacheBench </A>
  -		<LI><A HREF="performance.html#Tuning_with_crashme_script">Tuning with crashme script</A>
  -		<LI><A HREF="performance.html#Choosing_MaxClients">Choosing MaxClients</A>
  -		<LI><A HREF="performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A>
  -		<LI><A HREF="performance.html#Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A>
  -		<LI><A HREF="performance.html#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
  -	</UL>
  -
  -	<LI><A HREF="performance.html#Preopen_DB_connection_at_server_">Preopen DB connection at server startup:</A>
  -	<LI><A HREF="performance.html#Persistent_DB_Connections">Persistent DB Connections</A>
  -	<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="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#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>
  +	<LI><A HREF="control.html#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
  +	<LI><A HREF="control.html#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
  +	<LI><A HREF="control.html#Log_Rotation">Log Rotation</A>
  +	<LI><A HREF="control.html#Preventing_from_modperl_process_">Preventing from modperl process from going wild</A>
   </UL>
   <P><LI><A HREF="obvious.html"><B><FONT SIZE=+1>Things obvious to others, but not to you</FONT></B></A></LI><P>
   <UL>
  @@ -287,14 +310,6 @@
   		<LI><A HREF="obvious.html#Additional_reading_references">Additional reading references</A>
   	</UL>
   
  -	<LI><A HREF="obvious.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  -	<UL>
  -
  -		<LI><A HREF="obvious.html#Restarting_the_server">Restarting the server</A>
  -		<LI><A HREF="obvious.html#Using_Apache_StatINC">Using Apache::StatINC</A>
  -		<LI><A HREF="obvious.html#Reloading_only_specific_files">Reloading only specific files</A>
  -	</UL>
  -
   	<LI><A HREF="obvious.html#Compiled_Regular_Expressions">Compiled Regular Expressions </A>
   	<LI><A HREF="obvious.html#Debugging_your_code_in_Single_Se">Debugging your code in Single Server Mode</A>
   	<LI><A HREF="obvious.html#_M_and_other_time_file_tests_u">-M and other time() file tests under mod_perl</A>
  @@ -326,20 +341,6 @@
   	<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>
   </UL>
  -<P><LI><A HREF="control.html"><B><FONT SIZE=+1>Controlling and Monitoring the Server</FONT></B></A></LI><P>
  -<UL>
  -
  -	<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#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>
  -	<LI><A HREF="control.html#Starting_a_personal_server_for_e">Starting a personal server for each developer</A>
  -	<LI><A HREF="control.html#Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A>
  -	<LI><A HREF="control.html#Log_Rotation">Log Rotation</A>
  -	<LI><A HREF="control.html#Preventing_from_modperl_process_">Preventing from modperl process from going wild</A>
  -</UL>
   <P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
   <UL>
   
  @@ -531,7 +532,10 @@
   
   <UL>
   
  -<LI><A HREF="all.html"><B>Guide All in One. Ready for Printing</B></A></LI>
  +<LI><A HREF="all.html"><B>Guide All in One. Ready for Printing</B></A>
  +(You better use the Postscript Book -- <A
  +HREF="mod_perl_guide.ps.gz">mod_perl_guide.ps.gz</A>)
  + </LI>
   
   <LI><A HREF="CHANGES"><B>CHANGES</B></A></LI>
   
  @@ -580,11 +584,20 @@
   <TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
   <HR></TD>
   </TR>
  -
   <TR ALIGN=CENTER VALIGN=TOP>
  +<TD ALIGN=CENTER VALIGN=CENTER COLSPAN="3">
  +URL: <B>http://perl.apache.org/guide</B><BR>
  +Copyright &copy; 1998, 1999 Stas Bekman. All rights reserved.
  +</TD>
  +</TR>
  +<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 06/19/1999
  +HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 07/02/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>
  
  
  
  1.5       +110 -106  modperl-site/guide/install.html
  
  Index: install.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/install.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- install.html	1999/06/19 21:15:10	1.4
  +++ install.html	1999/07/02 13:42:28	1.5
  @@ -29,12 +29,12 @@
   	<LI><A HREF="#Configuration_and_Installation">Configuration and Installation</A>
   	<UL>
   
  -		<LI><A HREF="#Perl">Perl</A>
  -		<LI><A HREF="#Apache">Apache</A>
  -		<LI><A HREF="#Mod_Perl">Mod_Perl</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="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is really installed</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>
  @@ -75,11 +75,12 @@
   <CENTER><H1><A NAME="Configuration_and_Installation">Configuration and Installation</A></H1></CENTER>
   <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><H2><A NAME="perl">perl</A></H2></CENTER>
   <P>
  -First install perl. Follow the instructions in the distribution's INSTALL
  -file. During the configuration stage (while running
  -<CODE>./Configure</CODE>), make sure you answer <CODE>YES</CODE> to:
  +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>
   <PRE>  Do you wish to use dynamic loading? [y]
  @@ -89,23 +90,23 @@
   
   <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>
  +<CENTER><H2><A NAME="apache">apache</A></H2></CENTER>
   <P>
  -It is a good idea to try to install the Apache webserver without mod_perl
  -first. This way, if something going 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
  +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>  % ls -l /usr/src
  -  drwxr-xr-x   8 stas  bar         2048 Oct  6 09:46 apache_1.3.6/
  -  drwxr-xr-x  19 stas  bar         4096 Oct  2 14:33 mod_perl-1.19/
  +  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>
   <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>
  +<CENTER><H2><A NAME="mod_perl">mod_perl</A></H2></CENTER>
   <P>
   Now we come to the main point of this document.
   
  @@ -115,70 +116,64 @@
   
   <P>
   As with any perl package, the installation of mod_perl is very easy and
  -standard. <CODE>perldoc INSTALL</CODE> will guide you thru the configuration and installation process.
  +standard. <CODE>perldoc INSTALL</CODE> will guide you through the configuration and the installation processes.
   
   <P>
   The fastest way to install would be:
   
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_1.3.6/src \
  +<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>
  -(Note: if you use an apache version different then apache_1.3.6, change the
  -version number in the example above and in all later examples
  -appropriately)
  +Note: replace x.x.x with the version numbers you actually use.
   
   <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 /foo/server as a base directory root, you have to run this:
  +use <CODE>/foo/server</CODE> as a base directory, you have to run this:
   
   <P>
  -<PRE>  % perl Makefile.PL APACHE_SRC=../apache_1.3.6/src \
  +<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>
   Where <CODE>PREFIX</CODE> specifies where to install the perl modules,
  -<CODE>APACHE_PREFIX</CODE> - the same for the apache files.
  +<CODE>APACHE_PREFIX</CODE> -- the same for the apache files.
   
   <P>
  -The next step is to configure the mod_perl sections of the apache conf
  -files. See <A HREF="././config.html#">ModPerlConfiguration</A>
  +The next step is to configure the mod_perl sections of the apache
  +configuration file. (See <A HREF="././config.html#">ModPerlConfiguration</A>).
   
  -
  -
   <P>
  -Fire up the server with <CODE>/foo/server/sbin/apachectl start</CODE>, Watch the error log file if server does not start up (No error message
  -will be printed to the console!)
  +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>
   <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 really installed</A></H1></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>
  -There 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 and restart the server.
  +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><H2><A NAME="Testing_by_checking_the_error_lo">Testing by checking the error_log file</A></H2></CENTER>
   <P>
  -When starting the server, just check the <CODE>error_log</CODE> file for this:
  +When starting the server, just check the <CODE>error_log</CODE> file for the following message:
   
   <P>
  -<PRE>  [Thu Dec  3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured
  +<PRE>  [Thu Dec  3 17:27:52 1998] [notice] Apache/1.3.1 (Unix) mod_perl/1.15 configured 
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  -   -- resuming normal operations
  +    -- resuming normal operations
   </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 &lt;<CODE>Location /perl-status</CODE>&gt;
  -Section in the server configuration file (refer to
  -<A HREF="././config.html#">ModPerlConfiguration</A>), fetch: <A
  -HREF="http://www.yourserver.com/perl-status">http://www.yourserver.com/perl-status</A>
  +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>
  @@ -192,15 +187,15 @@
   <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 the web server.
  +Knowing the port you have configured apache to listen on, you can use
  +<CODE>telnet</CODE> to talk directly to it.
   
   <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!
  +your server at port 8080, and type <CODE>HEAD / HTTP/1.0</CODE> then press the &lt;ENTER&gt; key TWICE:
   
   <P>
  -<PRE>  % telnet yourserver.com 8080&lt;ENTER&gt;
  +<PRE>  % telnet localhost 8080&lt;ENTER&gt;
     HEAD / HTTP/1.0&lt;ENTER&gt;&lt;ENTER&gt;
   </PRE>
   <P>
  @@ -216,8 +211,7 @@
     Connection closed.
   </PRE>
   <P>
  -So you see <CODE>Server: Apache/1.3.6 (Unix) mod_perl/1.19</CODE> - which says that you <STRONG>do</STRONG> have mod_perl installed and it is version 1.19. Of course in your case it
  -would be the version you have installed.
  +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>
   However, just because you have got mod_perl linked in there, that does not
  @@ -235,9 +229,10 @@
   environment.
   
   <P>
  -Copy and paste the script below (no need for perl line!). Let's say you
  -called it test.pl, you saved it into the root of the cgi scripts, and cgi
  -root is mapped directly to /perl of your server.
  +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;;
  @@ -249,14 +244,17 @@
     print &quot;&lt;/TABLE&gt;&quot;;
   </PRE>
   <P>
  -Make it executable:
  +Make it readable and executable by server:
   
   <P>
  -<PRE>  % chmod a+x test.pl
  +<PRE>  % chmod a+rx test.pl
   </PRE>
  +<P>
  +(you will want to tune permissions on the public host).
  +
   <P>
  -Now fetch the URL <CODE>http://www.you.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 (part of the output was snipped).
  +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>
   <PRE>  SERVER_SOFTWARE    Apache/1.3.6 (Unix) mod_perl/1.19
  @@ -269,8 +267,10 @@
     [...snipped]
   </PRE>
   <P>
  -Now if I run the same script in mod_cgi mode (configured with /cgi-bin)
  -(you will need to add the perl line <CODE>#!/bin/perl</CODE> for the above script) and fetch <CODE>http://www.you.com/cgi-bin/test.pl</CODE>.
  +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>
   <PRE>  SERVER_SOFTWARE   Apache/1.3.6 (Unix)
  @@ -296,9 +296,11 @@
   <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 scripts, but if you think that your script might be used in both
  +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.
  -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.
  +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>
  @@ -308,32 +310,30 @@
   serving a very simple purpose, they can be helpful in other situations.
   
   <P>
  -Assuming you have the libwww-perl (LWP) package installed (you will need it
  -installed in order to pass mod_perl's <CODE>make test</CODE> anyway):
  +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>  % lwp-request -e -d www.site.com
  +<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A>
   </PRE>
   <P>
   Will show you all the headers. (The <CODE>-d</CODE> option disables printing the response content.)
   
   <P>
  -<PRE>  % lwp-request -e -d www.site.com | egrep '^Server:'
  +<PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A> | egrep '^Server:'
   </PRE>
   <P>
   To see the server's version only.
   
   <P>
  -Again use <CODE>www.site.com:port_number</CODE> if your server is listening to a non-default 80 port.
  +Use <CODE>http://www.nowhere.com:port_number</CODE> if your server is listening to a non-default 80 port.
   
   <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 instructions above and when you
  -encounter APACI_ARGS use your home directory (or some other directory which
  -you have write access to as a prefix, for example,
  -<CODE>/home/stas/www</CODE>) and everything will be installed there. There is a chance that some perl
  +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>
  @@ -342,29 +342,27 @@
   <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.you.com:8080</CODE> in that case, but that is not a problem since generally 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 an HTML form, so they should not know at all that the port is
  -different from the default port 80.
  +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
  +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.)
  +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 that machine
  -(and it's not your own host...), most likely the system administrator of
  -the host will ask you to shutdown your mod_perl server, or to find another
  -home for it. You have a few solutions:
  +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 resource usage - see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>
  -
  -
  +Reduce resources usage (see <A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>).
   
   <P><LI>
   <P>
  @@ -374,6 +372,8 @@
   <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>
  @@ -382,16 +382,16 @@
   <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 did not use
  -the default config parameters and altered some of them during the
  +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>
   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
  +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 some other machine, I have found that I do not remember
  -what parameters did I altered.
  +identical copy at another machine, I would find that I do not remember what
  +parameters I altered.
   
   <P>
   The best solution for this problem is to prepare the run file with all the
  @@ -399,13 +399,13 @@
   all by hand. So later I will have the script handy to be reused.
   
   <P>
  -mod_perl suggests using the <CODE>makepl_args.mod_perl</CODE> file which comes with mod_perl distribution. This is the file you specify
  -all the parameters you are going to use.
  +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>
   But if you have found yourself with a compiled tool and no traces of the
  -specified parameters left, you can still find them out if the sources were
  -not <CODE>make clean</CODE>'d. So 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>.
  +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>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -414,18 +414,17 @@
   <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>
  -There are two configuration parameters <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>
  -you can use in <CODE>perl Makefile.PL [options]</CODE>.
  +There are two configuration parameters: <CODE>PREP_HTTPD</CODE> and <CODE>DO_HTTPD</CODE>, that you can use in:
   
   <P>
  -<CODE>DO_HTTPD=1</CODE> means default to 'y' for the two prompts (which source tree to configure
  -against and to build the httpd in that tree).
  -<CODE>PREP_HTTPD=1</CODE> just means default 'n' to the second prompt, meaning, do not build httpd
  -(make) in the Apache source tree.
  -
  +<PRE>  perl Makefile.PL [options]
  +</PRE>
   <P>
  -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>.
  +<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>
   If you did not build the httpd, chdir to the apache source, and execute:
  @@ -441,7 +440,7 @@
     make install
   </PRE>
   <P>
  -Note that you will have to do the same if you did not pass
  +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.
   
  @@ -450,20 +449,25 @@
   <CENTER><H2><A NAME="mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A></H2></CENTER>
   <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. Do
  -<CODE>find</CODE> for <CODE>ap_mmn.h</CODE>, In my case I 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>
  +For all RH fans, before you are going to build the apache by yourself, do:
  +
  +<P>
  +<PRE>  rpm -e apache
  +</PRE>
   <P>
  -For all RH fans, before you are going to build the apache by yourself, do: <CODE>rpm -e apache</CODE> to remove the preinstalled one first!
  +to remove the pre-installed package first!
   
   <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>
   <P>
  -Yes, you should. You have to rebuild mod_perl since it has a hardcoded
  -<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
  +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>
  @@ -500,7 +504,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/12/1999
  +	     <BR>Last Modified at 07/02/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.12      +1 -1      modperl-site/guide/intro.html
  
  Index: intro.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/intro.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- intro.html	1999/06/19 21:15:10	1.11
  +++ intro.html	1999/07/02 13:42:28	1.12
  @@ -291,7 +291,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.2       +771 -647  modperl-site/guide/mod_perl_guide.ps.gz
  
  	<<Binary file>>
  
  
  1.6       +14 -13    modperl-site/guide/modules.html
  
  Index: modules.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/modules.html,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- modules.html	1999/06/19 21:15:11	1.5
  +++ modules.html	1999/07/02 13:42:29	1.6
  @@ -186,16 +186,16 @@
   <CENTER><H1><A NAME="Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A></H1></CENTER>
   <P>
   Have you ever served a huge HTML file (e.g. a file bloated with JavaScript
  -code) and wandered how could you compress it, thus drammatically cutting
  -down the download times. After all java applets can be compressed into a
  -jar and benefit from a faster download. Why cannot we do the same with a
  -plain ASCII (HTML,JS and etc), it is a known fact that ASCII can be
  -compressed 10 times smaller than the original size.
  +code) and wandered how could you send it compressed, thus drammatically
  +cutting down the download times. After all java applets can be compressed
  +into a jar and benefit from a faster download times. Why cannot we do the
  +same with a plain ASCII (HTML,JS and etc), it is a known fact that ASCII
  +text can be compressed by a factor of 10.
   
   <P>
  -<CODE>Apache::GzipChain</CODE> comes to help you with this task. If a client (browser) understands <CODE>gzip</CODE> encoding this module compresses the output and send it downstream. A client
  -decompress the data upon receive and renders the HTML as if it was a plain
  -HTML fetch.
  +<CODE>Apache::GzipChain</CODE> comes to help you with this task. If a client (browser) understands <CODE>gzip</CODE> encoding this module compresses the output and sends it downstream. A
  +client decompresses the data upon receive and renders the HTML as if it was
  +a plain HTML fetch.
   
   <P>
   For example to compress all html files on the fly, do:
  @@ -207,7 +207,7 @@
     &lt;/Files&gt;
   </PRE>
   <P>
  -Remember that it will work only if the browsers claims to accept compressed
  +Remember that it will work only if the browser claims to accept compressed
   input, thru <CODE>Accept-Encoding</CODE> header. <CODE>Apache::GzipChain</CODE>
   keeps a list of user-agents, thus it also looks at <CODE>User-Agent</CODE>
   header, for known to accept compressed output browsers.
  @@ -218,15 +218,16 @@
   
   <P>
   <PRE>  &lt;Location /test&gt;
  -    SetHandler &quot;perl-script&quot;
  +    SetHandler perl-script
       PerlHandler Apache::OutputChain Apache::GzipChain Apache::EmbperlChain Apache::PassFile
     &lt;/Location&gt;
   </PRE>
   <P>
  -Hint: Watch an <CODE>access_log</CODE> file to see how many bytes were actually send.
  +Hint: Watch an <CODE>access_log</CODE> file to see how many bytes were actually send, compare with a regular
  +configuration send.
   
   <P>
  -See the module's documentaion for more details.
  +(See <CODE>perldoc Apache::GzipChain</CODE>).
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -296,7 +297,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/15/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.6       +1 -1      modperl-site/guide/multiuser.html
  
  Index: multiuser.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/multiuser.html,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- multiuser.html	1999/06/19 21:15:11	1.5
  +++ multiuser.html	1999/07/02 13:42:29	1.6
  @@ -234,7 +234,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 04/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.15      +123 -219  modperl-site/guide/obvious.html
  
  Index: obvious.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/obvious.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- obvious.html	1999/06/19 21:15:11	1.14
  +++ obvious.html	1999/07/02 13:42:29	1.15
  @@ -22,7 +22,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>
   Things obvious to others, but not to you</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.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>
   
  @@ -36,14 +36,6 @@
   		<LI><A HREF="#Additional_reading_references">Additional reading references</A>
   	</UL>
   
  -	<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  -	<UL>
  -
  -		<LI><A HREF="#Restarting_the_server">Restarting the server</A>
  -		<LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
  -		<LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</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>
  @@ -71,7 +63,7 @@
   <CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
   <P>
   This document describes ``special'' traps you may encounter when running
  -your plain CGIs under Apache::Registry and Apache::PerlRun.
  +your plain CGIs under <CODE>Apache::Registry</CODE> and <CODE>Apache::PerlRun</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -91,8 +83,7 @@
       }
   </PRE>
   <P>
  -However, the script is run under Apache::Registry, it will in fact be
  -repackaged into something like this:
  +However, the script is run under <CODE>Apache::Registry</CODE>, it will in fact be repackaged into something like this:
   
   <P>
   <PRE>  package $mangled_package_name;
  @@ -106,24 +97,24 @@
     }
   </PRE>
   <P>
  -Now <CODE>printit</CODE> is an inner named subroutine. Because it is referencing a lexical variable
  +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.
  +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 -w (or/and PerlWarn ON)! Perl will then emit a warning like:
  +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 <STRONG>BEGIN{}</STRONG> and <STRONG>END{}</STRONG> cannot trigger this message, since each <STRONG>BEGIN{}</STRONG> and <STRONG>END{}</STRONG> is defined to be called exactly once. (To understand why, read about the
  +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)
   
  @@ -143,8 +134,8 @@
   longer be shared.
   
   <P>
  -Check your code by running Apache in single-child mode (httpd -X). Since
  -the value of a my variable retain its initial value <CODE>per
  +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.
  @@ -209,134 +200,18 @@
   <CENTER><H2><A NAME="Additional_reading_references">Additional reading references</A></H2></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 `use vars' and `my' - <A
  +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>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
  -<P>
  -When you develop plain CGI scripts, you can just change the code, and rerun
  -the CGI from your browser. Since the script isn't cached in memory, the
  -next time you call it the server starts up a new perl process, which
  -recompiles it from scratch. The effects of any modifications you've applied
  -are immediately present.
  -
  -<P>
  -The situation is different with Apache::Registry, since the whole idea is
  -to get maximum performance from the server. By default, the server won't
  -spend the time to check whether any included library modules have been
  -changed. It assumes that they weren't, thus saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are
  -<STRONG>use</STRONG>/<STRONG>require</STRONG>-ing in your script.) The only check that is being done is whether your
  -main script has been changed. So if you have only one script that doesn't <STRONG>use</STRONG> (or <STRONG>require</STRONG>) other perl modules (or packages), there is nothing new about it. If
  -however, you are developing a script that includes other modules, the files
  -you <STRONG>use()</STRONG> or <STRONG>require()</STRONG> aren't being checked to see if they have been modified.
  -
  -<P>
  -Acknowledging this, how do we get our modperl-enabled server to recognize
  -changes in any library modules? Well, there are a couple of techniques:
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
  -<P>
  -See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
  -<P>
  -After restarting the server about 100 times, you will be tired and will
  -look for another solutions. Help comes from the Apache::StatINC module. 
  -
  -<P>
  -Read its pod pages, but beware of the following note: Only the modules
  -located in <STRONG>@INC</STRONG> are being reloaded on change, and you can change the <STRONG>@INC</STRONG> only before the server has been started. Whatever you do in your
  -scripts/modules which are being <CODE>required()</CODE> after the server
  -startup will not have any effect on <STRONG>@INC</STRONG>.
  -
  -<P>
  -When you do <STRONG>use lib qw(foo/bar);</STRONG>, the <STRONG>@INC</STRONG> is being changed only for the time the code is being parsed. When it's over
  -the <STRONG>@INC</STRONG> is being reset to its original value. To make sure that you have set a
  -correct <STRONG>@INC</STRONG> fetch <A
  -HREF="http://your.perl.server/perl-status?inc">http://your.perl.server/perl-status?inc</A>
  -and watch the bottom of the page. (I assume you have configured the
  -&lt;Location /perl-status&gt; section in httpd.conf as the mod_perl docs
  -show.)
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
  -<P>
  -Checking all the Modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
  -certainly would not want
  -<CODE>Apache::StatINC </CODE>module to be enabled in your production site's configuration. But sometimes
  -you want to have some Configuration module to be reloaded without
  -restarting the whole server. To accomplish this, one of the solutions is to
  -use a code that I describe below.
  -
  -<P>
  -Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
  -
  -<P>
  -<PRE>  use lib &quot;/some/private/path&quot;;
  -  use Foo::Bar qw(:tags_group tag1 tag2);
  -</PRE>
  -<P>
  -Now to make a modification testing and reload at runtime you have to use
  -something like this:
  -
  -<P>
  -<PRE>  # child's private global variable to keep the timestamps
  -  use vars qw(%MODIFIED);
  -    
  -  my $module = &quot;Foo::Bar&quot;;
  -  
  -  (my $inc_key = $module) =~ s|::|/|g;
  -  $inc_key .= &quot;.pm&quot;;
  -  # the $module's path should be registered in %INC if it was already loaded
  -  my $path = $INC{$inc_key} or warn &quot;Can't find $inc_key in %INC\n&quot;;
  -  
  -  # Note: consider to not continue if $path wasn't set!
  -  
  -  # set modification time if it wasn't set before (first time)
  -  # Note: Use (stat $path)[9] instead of -M test, if you reset
  -  # time with $^M=time
  -  $MODIFIED{$module} ||= -M $path;
  -    
  -  # now check whether it was changed (assuming the above wasn't
  -  # performed in this session
  -  if ($MODIFIED{$module} != -M $path){
  -    # only if deleted from %INC the require will be called below
  -    delete $INC{$inc_key};
  -    
  -    require $path;
  -    
  -    # now reimport the symbols (if you need them back :)
  -    import $module qw(:tags_group tag1 tag2);
  -    
  -    # Update the MODIFICATION times
  -    $MODIFIED{$module} = -M $path;
  -  }
  -</PRE>
  -<P>
  -You may want to add debug print statements to debug this code in your
  -application.
  -
  -<P>
  -Read the ``use versus require'' article for more info. ( <A
  -HREF="http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require">http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require</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 <STRONG>/o</STRONG> modifier to the regexp pattern. This directs the compiler to build the
  +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:
   
  @@ -347,8 +222,8 @@
     }
   </PRE>
   <P>
  -This is usually a big win in loops over lists, or when using
  -<STRONG>grep</STRONG> or <STRONG>map</STRONG>. 
  +This is usually a big win in loops over lists, or when using <CODE>grep()</CODE>
  +or <CODE>map()</CODE> operators.
   
   <P>
   In long-lived mod_perl scripts, however, this can pose a problem if the
  @@ -359,10 +234,10 @@
   the pattern is dependent on. Your script will appear broken.
   
   <P>
  -There are two solutions to this problem. 
  +There are two solutions to this problem:
   
   <P>
  -The first is to use <STRONG>eval q//</STRONG>, to force the code to be evaluated each time. Just make sure that the eval
  +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.
   
  @@ -381,7 +256,9 @@
   Just saying:
   
   <P>
  -<PRE>  eval q{ print if /$pat/o; };
  +<PRE>  foreach( @list ) {
  +    eval q{ print if /$pat/o; };
  +  }
   </PRE>
   <P>
   is going to be a horribly expensive proposition. 
  @@ -389,7 +266,7 @@
   <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 <STRONG>m//</STRONG> or <STRONG>s///</STRONG>), you can rely on the property of the null pattern, that reuses the last
  +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.
   
  @@ -406,7 +283,7 @@
   <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 <STRONG>//</STRONG> will match everything. If you can't count on fixed text to ensure the match
  +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>
  @@ -481,8 +358,8 @@
   (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.
  +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);
  @@ -490,79 +367,98 @@
     print ++$num;
   </PRE>
   <P>
  -This script initializes the variable <STRONG>$num</STRONG> with a random value, then increments it on each request and prints it out.
  +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 1,9,4,19 (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 httpd -X single server
  -mode you will get 2,3,4,5... (taken that the <CODE>random()</CODE> returned
  -1 at the first call)
  +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>
   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 multi
  -server mode. Consider an application that allows you to change the
  -configuration at run time.
  +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>
   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.
  +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>
   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>
  -If you run the same code in the multi server environment, 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 old color, 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.
  +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>
   Also note that since the server is running in single mode, if the output
  -returns HTML with IMG tags, then the load of these will take a lot of time
  -(read apache docs of httpd -X to learn why).
  +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>
  +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="_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 -M (-C -A) 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.
  +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>
  -If you want to have -M test to count the time relative to the current
  -request, you should reset the $^T variable as with any other perl script.
  -Just add <CODE>$^T = time;</CODE> at the beginning of the scripts.
  +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>
   <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 stop button, Apache will detect that via
  -SIG{'PIPE'} 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 this
  +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>
  -Important to notice that when the user hits ``stop'' on the browser, 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.
  +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>
   Starting from apache 1.3.6 apache will not catch SIGPIPE anymore and
  @@ -573,9 +469,8 @@
   <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]
  +  connection as aborted.  Replaced many direct (unchecked) calls to
  +  ap_b* routines with the analogous ap_r* calls.  [Roy Fielding]
   </PRE>
   <P>
   What happens if your mod_perl script has some global variables, that are
  @@ -589,24 +484,22 @@
   
   <P>
   <PRE>  1. lock resource
  -     &lt;b&gt;&lt;critical section starts&gt;
  +     &lt;critical section starts&gt;
     2. sleep 20 (== do some time consuming processing)
  -     &lt;critical section ends&gt;&lt;/b&gt;
  +     &lt;critical section ends&gt;
     3. unlock resource
   </PRE>
   <P>
  -If user presses 'Stop' and Apache sends SIGPIPE 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 ``deadlock'' exists.
  +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>
  -Here is the working example. Run the server with -X, Press 'Stop' 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.
  +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.
   
   <P>
  -<PRE>  -------------------------------------------------------------
  -  use vars qw(%CACHE);
  +<PRE>  use vars qw(%CACHE);
     use CGI;
     $|=1;
     my $q = new CGI;
  @@ -635,14 +528,12 @@
     print $q-&gt;p(&quot;Going to unlock!&quot;);
     $CACHE{LOCK} = 0;
     print $q-&gt;p(&quot;Unlock!\n&quot;);
  -  -------------------------------------------------------------
   </PRE>
   <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 END blocks that are encountered during compilation of Apache::Registry
  -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
  -Apache::Registry mode, the following is your remedy:
  +<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>
   <PRE>  END {
  @@ -650,11 +541,11 @@
     }
   </PRE>
   <P>
  -Notice that the END block will be run after the Apache::Registry::handler
  -is finished (not during the cleanup phase though).
  +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>
  -If you are into a perl API, use the <STRONG>register_cleanup()</STRONG> method of Apache.
  +If you are into a perl API, use the <CODE>register_cleanup()</CODE> method of Apache.
   
   <P>
   <PRE>  $r-&gt;register_cleanup(sub {$CACHE{LOCK} = 0;});
  @@ -664,6 +555,17 @@
   the aborted connection.
   
   <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.
  +
  +<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>
   <P>
  @@ -675,19 +577,21 @@
   results. If this is the case, use <CODE>$SIG{ALRM}</CODE> to prevent the timeouts:
   
   <P>
  -<PRE>  eval {
  -    local $SIG{ALRM} = sub { die &quot;timeout\n&quot; };
  +<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>
   <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 'local
  -$SIG{FOO}' 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.
  +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.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -699,7 +603,8 @@
   
   <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:
  +location and name are defined in the http.conf file. Look for the
  +<CODE>ErrorLog</CODE> parameter. My httpd.conf says:
   
   <P>
   <PRE>  ErrorLog var/logs/error_log
  @@ -728,16 +633,15 @@
   
   <P>
   For example, if you have mistakenly entered a non-existent directory path
  -in your <STRONG>ErrorLog</STRONG> directive, the error message will be printed on the controlling tty. Or, if
  -the error happens when server executes PerlRequire or PerlModule directive
  -you might see the errors here also.
  +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>
   You are probably wonder where all the errors go when you are running the
  -server in single mode (httpd -X). 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.
  +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>
   &lt;/META&gt;
  @@ -766,7 +670,7 @@
   
   <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;;
  +       \&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''
  @@ -788,7 +692,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.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>
  @@ -801,7 +705,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/05/1999
  +	     <BR>Last Modified at 06/27/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.17      +375 -304  modperl-site/guide/performance.html
  
  Index: performance.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/performance.html,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- performance.html	1999/06/19 21:15:12	1.16
  +++ performance.html	1999/07/02 13:42:30	1.17
  @@ -22,10 +22,12 @@
   <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>
   Performance. Benchmarks.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <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="#Sharing_Memory">Sharing Memory</A>
   	<LI><A HREF="#Preload_Perl_modules_at_server_s">Preload Perl modules at server startup</A>
   	<UL>
   
  @@ -33,9 +35,8 @@
   	</UL>
   
   	<LI><A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>
  -	<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
   	<LI><A HREF="#Avoid_Importing_Functions">Avoid Importing Functions</A>
  -	<LI><A HREF="#How_can_I_find_if_my_modperl_scr">How can I find if my modperl scripts have memory leaks (and where)</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 (and where)</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>
  @@ -59,7 +60,6 @@
   		<LI><A HREF="#Summary_of_Benchmarking_to_tune_">Summary of Benchmarking to tune all 5 parameters</A>
   	</UL>
   
  -	<LI><A HREF="#Preopen_DB_connection_at_server_">Preopen DB connection at server startup:</A>
   	<LI><A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>
   	<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>
  @@ -83,6 +83,81 @@
   
   	      <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>
  +<P>
  +Before we dive into performance issues, there is something very important
  +to understand. It applies to any webserver, not only apache. All the
  +efforts are made to make user's web browsing experience a swift. Among
  +other web site usability factors, speed is one of the most crucial ones.
  +What is a correct speed measurement? Since user is the one that interacts
  +with web site, speed measurement is a time passed from the moment user
  +follows a link or presses a submit button till the resulting page is being
  +rendered by her browser. So if we trace the data packet's movement as it
  +leaves user's machine (request sent) till the reply arrives, the packet
  +travels through many entities on its way. It has to make its way through
  +the network, passing many interconnection nodes, before it enters the
  +target machine it might go through proxy (accelerator) servers, then it's
  +being served by your server, and finally it has to make the whole way back.
  +A webserver is only one of the elements the packet sees on its way. You
  +could work hard to fine tune your webserver for the best performance, but a
  +slow NIC (Network Interface Card) or slow network connection from your
  +server might defeat it all. That's why it's important to think big and to
  +be aware of possible bottlenecks between the server and the web. Of course
  +there is nothing you can do if user has a slow connection on its behalf.
  +
  +<P>
  +From the other side, you might tune your scripts and webserver to process
  +incoming requests ultra fast, so you will need a little number of working
  +servers, but you might find out that server processes are busy waiting for
  +slow clients to complete the download. You will see more examples in this
  +chapter. My point is that a web service is like car, if one of the details
  +or mechanisms is broken the car will not drive smoothly and it can even
  +stop dead if pushed further without first fixing it.
  +
  +<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
  +(and most sane systems do), you might save more memory by sharing it
  +between child processes. This is only possible when you preload code at
  +server startup. However during a child process' life, its memory pages
  +becomes unshared and there is no way we can control perl to make it
  +allocate memory so (dynamic) variables land on different memory pages than
  +constants, that's why the <STRONG>copy-on-write</STRONG> effect (will explain in a moment) will hit almost at random. If you are
  +pre-loading many modules you might be able to balance the memory that stays
  +shared against the time for an occasional fork by tuning the
  +<CODE>MaxRequestsPerChild</CODE> to a point where you restart before too much becomes unshared. In this case
  +the <CODE>MaxRequestsPerChild</CODE> is very specific to your scenario. You should do some measurements and you
  +might see if this really makes a difference and what a reasonable number
  +might be. Each time a child reaches this upper limit and restarts it should
  +release the unshared copies and the new child will inherit pages that are
  +shared until it scribbles on them.
  +
  +<P>
  +It is very important to understand that your goal is not to have
  +<CODE>MaxRequestsPerChild</CODE> to be 10000. Having a child serving 300 requests on precompiled code is
  +already a huge speedup, so if it is 100 or 10000 it does not really matter
  +if it saves you the RAM by sharing. Do not forget that if you preload most
  +of your code at the server startup, the fork to spawn a new child will be
  +very very fast, because it inherits most of the preloaded code and the perl
  +interpreter from the parent process. But then during the work of the child,
  +its memory pages (which aren't really its yet, it uses the parent's pages)
  +are getting dirty (originally inherited and shared variables are getting
  +updated/modified) and the <STRONG>copy-on-write</STRONG>
  +happens, which reduces the number of shared memory pages - thus enlarging
  +the memory demands. Killing the child and respawning a new one, allows to
  +get the pristine shared memory from the parent process again.
  +
  +<P>
  +The conclusion is that <CODE>MaxRequestsPerChild</CODE> should not be too big, otherwise you loose the benefits of the memory
  +sharing.
  +
  +<P>
  +See <A HREF="././performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A> for more about tuning the <CODE>MaxRequestsPerChild</CODE> parameter.
  +
  +<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
  @@ -94,15 +169,16 @@
     PerlModule DBI;
   </PRE>
   <P>
  -But even better to create a separate startup file (with regular perl code)
  -and put there things like:
  +But even a better approach is to create a separate startup file (where you
  +code in plain perl) and put there things like:
   
   <P>
   <PRE>  use DBI;
     use Carp;
   </PRE>
   <P>
  -Then you <CODE>require()</CODE> this file with help of <CODE>PerlRequire</CODE> directive from <CODE>httpd.conf</CODE>, before the rest of the mod_perl configuration directives:
  +Then you <CODE>require()</CODE> this startup file with help of <CODE>PerlRequire</CODE>
  +directive from <CODE>httpd.conf</CODE>, by placing it before the rest of the mod_perl configuration directives:
   
   <P>
   <PRE>  PerlRequire /path/to/start-up.pl
  @@ -121,7 +197,10 @@
   </PRE>
   <P>
   The arguments to <CODE>compile()</CODE> are a list of method names or sets, and are identical to those accepted by
  -the use operator. Note that in most cases you will want to replace <CODE>':all'</CODE> with the tags' names you really use in your code. 
  +the <CODE>use()</CODE> and <CODE>import()</CODE>
  +operators. Note that in most cases you will want to replace <CODE>':all'</CODE>
  +with tag names you really use in your code, since generally only a subset
  +of subs is actually being used.
   
   <P>
   You can also preload the Registry scripts. See <A HREF="#Preload_Registry_Scripts">Preload Registry Scripts</A>.
  @@ -137,10 +216,6 @@
   the Registry modules with <CODE>Apache::RegistryLoader</CODE>.
   
   <P>
  ---------------------------------------------------------------------------------
  -
  -
  -<P>
   1. In the first test, the following script was used:
   
   <P>
  @@ -151,8 +226,10 @@
     print $q-&gt;start_html,$q-&gt;p(&quot;Hello&quot;);
   </PRE>
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
   
  +
  +
   <P>
   Before the <CODE>CGI.pm</CODE> preload: (No other modules preloaded)
   
  @@ -173,7 +250,9 @@
   Observation: child httpd has grown up by 1268K
   
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
  +
  +
   
   <P>
   After the <CODE>CGI.pm</CODE> preload:
  @@ -196,8 +275,10 @@
   preload - good!
   
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
   
  +
  +
   <P>
   After <CODE>CGI.pm</CODE> preloaded and compiled with CGI-&gt;compile(':all');
   
  @@ -222,10 +303,6 @@
   sure.
   
   <P>
  ---------------------------------------------------------------------------------
  -
  -
  -<P>
   2. I have tried the second test to find it. I run the script:
   
   <P>
  @@ -234,8 +311,10 @@
     print header,start_html,p(&quot;Hello&quot;);
   </PRE>
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
   After <CODE>CGI.pm</CODE> was preloaded and NOT compiled with CGI-&gt;compile(':all'):
   
  @@ -256,8 +335,10 @@
   Observation: child httpd has grown up by 1264K
   
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
   After <CODE>CGI.pm</CODE> was preloaded and compiled with CGI-&gt;compile(':all'):
   
  @@ -283,10 +364,6 @@
   difference.
   
   <P>
  ---------------------------------------------------------------------------------
  -
  -
  -<P>
   3. The third script:
   
   <P>
  @@ -297,8 +374,10 @@
     [and many lines of code, lots of globals - so the code is huge!]
   </PRE>
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
   Nothing preloaded at startup:
   
  @@ -319,8 +398,10 @@
   Observation: child httpd has grown by 2764K
   
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
   Preloaded CGI (compiled), Storable, Data::Dumper at startup:
   
  @@ -341,8 +422,10 @@
   Observation: child httpd has grown by 3276K. Great difference: 512K less!!!
   
   <P>
  -&lt;Server restarted&gt;
  +<STRONG>Server restarted</STRONG>
  +
   
  +
   <P>
   All the above modules + the above script PreCompiled with
   <CODE>Apache::RegistryLoader</CODE> at startup:
  @@ -389,13 +472,12 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Preload_Registry_Scripts">Preload Registry Scripts</A></H1></CENTER>
   <P>
  -<CODE>Apache::RegistryLoader</CODE> compiles Apache::Registry scripts at server startup. It can be a good idea
  -to preload these as well. So the code will be shared among the child
  -servers.
  +<CODE>Apache::RegistryLoader</CODE> compiles <CODE>Apache::Registry</CODE> scripts at server startup. It can be a good idea to preload the scripts you
  +are going to use as well. So the code will be shared among the children.
   
   <P>
   Here is an example of the use of this technique. This code is included in a <CODE>PerlRequire</CODE>'d file, and walks the directory tree under which all registry scripts are
  -installed. For each <CODE>.pl</CODE> file encountered, it calls the <CODE>Apache::RegistryLoader::handler()</CODE> method to preload the script in the parent server (before preforking the
  +installed. For each <CODE>.pl</CODE> file encountered, it calls the <CODE>Apache::RegistryLoader::handler()</CODE> method to preload the script in the parent server (before pre-forking the
   child processes):
   
   <P>
  @@ -417,8 +499,11 @@
     }
   </PRE>
   <P>
  -Note that we don't use the second argument to <CODE>handler()</CODE> here. You might need to provide a <CODE>trans()</CODE> method, since it's very dependent on your server's configuration. See <CODE>perldoc Apache::RegistryLoader</CODE>
  -for the complete information.
  +Note that we didn't use the second argument to <CODE>handler()</CODE> here, as module's manpage suggests. To make the loader smarter about the
  +uri-&gt;filename translation, you might need to provide a <CODE>trans()</CODE>
  +function to translate the uri to filename. URI to filename translation
  +normally doesn't happen until HTTP request time, so the module is forced to
  +roll its own translation. If filename is omitted and a <CODE>trans()</CODE> routine was not defined, the loader will try using the URI relative to <STRONG>ServerRoot</STRONG>.
   
   <P>
   You have to check whether this makes any improvement for you though, I did
  @@ -435,48 +520,6 @@
   
   <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>
  -Another important point is the sharing of memory. If your OS supports this
  -(and most sane systems do), you might save more memory by sharing it
  -between child processes. This is only possible when you preload code at
  -server startup. However during a child process' life, its memory pages
  -becomes unshared and there is no way we can control perl to make it
  -allocate memory so (dynamic) variables land on different memory pages than
  -constants so the copy-on-write effect will hit almost at random. If you are
  -pre-loading many modules you might be able to balance the memory that stays
  -shared against the time for an occasional fork by tuning the <CODE>MaxRequestsperChild</CODE> to a point where you restart before too much becomes unshared. In this case
  -the
  -<CODE>MaxRequestsPerChild</CODE> is very specific to your scenario. You should do some measurements and you
  -might see if this really makes a difference and what a reasonable number
  -might be. Each time a child reaches this upper limit and restarts it should
  -release the unshared copies and the new child will inherit pages that are
  -shared until it scribbles on them.
  -
  -<P>
  -It is very important to understand that your goal is not to have
  -<CODE>MaxRequestsperChild</CODE> to be 10000. Having a child serve 300 requests on precompiled code is
  -already a huge speedup, so if it is 100 or 10000 it does not really matter
  -if it saves you the RAM by sharing. Do not forget that if you preload most
  -of your code at the server startup, the fork to spawn a new child will be
  -very very fast, because it inherits most of the preloaded code and the perl
  -interpreter from the parent process. But then during the work of the child,
  -its memory pages (which aren't really its yet, it uses the parent's pages)
  -are getting dirty (originally inherited and shared variables are getting
  -updated) and the copy-on-write happens, which reduce the sharing number of
  -memory pages - thus enlarging the memory usage. Killing the child and
  -spawning a new one allows to get the pristine shared memory from the parent
  -process again.
  -
  -<P>
  -The conclusion is that <CODE>MaxRequestsperChild</CODE> should not be too big, otherwise you loose the benefits of the memory
  -sharing.
  -
  -<P>
  -See <A HREF="././performance.html#Choosing_MaxRequestsPerChild">Choosing MaxRequestsPerChild</A> for more about tuning the <CODE>MaxRequestsperChild</CODE> parameter.
  -
  -<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.
  @@ -486,7 +529,7 @@
   
   <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_modperl_scr">How can I find if my modperl scripts have memory leaks (and where)</A></H1></CENTER>
  +<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 (and where)</A></H1></CENTER>
   <P>
   <CODE>Apache::Leak</CODE> (derived from <CODE>Devel::Leak</CODE>) should help you with this task. Example:
   
  @@ -538,7 +581,7 @@
   <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.
  +<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>
   To configure use:
  @@ -549,7 +592,7 @@
       # (default is 64 Meg)
     PerlSetEnv PERL_RLIMIT_DATA 32:48
     
  -    # set child cpu limit in seconds
  +    # set child CPU limit in seconds
       # (default is 360 seconds)
     PerlSetEnv PERL_RLIMIT_CPU 120
     
  @@ -601,20 +644,23 @@
   <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>
  -How much faster is mod_perl that CGI? There are many ways to benchmark the
  -two. See a few examples and numbers below, also checkout the benchmark/
  -directory of mod_perl dist for more examples.
  +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>
  -If you write a benchmark for your own, use <CODE>Benchmark</CODE> for heavy scripts or use <CODE>Time::HiRes</CODE> for very fast scripts where you need better precision.
  +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>
   There is no need to write a special benchmark though. If you want to
  -impress your boss or colleagues, just take the heaviest cgi script you
  -have, 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 lwp-get from
  -<CODE>LWP</CODE> package to emulate the web agent (browser). (benchmark/ directory of
  -mod_perl dist includes such an example)
  +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>
   See also 2 tools for benchmarking:
  @@ -742,8 +788,8 @@
   <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 Time::HiRes
  -module, its usage is similar to the Benchmark's.
  +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>
   <PRE>  use Time::HiRes qw(gettimeofday tv_interval);
  @@ -763,7 +809,7 @@
   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 PerlHandler's Benchmarking.
  +<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>
  @@ -772,38 +818,40 @@
   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 not use the system for its full
  -ability, and if too ``high'' chances your server will bring the machine to
  -its knees.
  +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>
   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. The situation is different with
  +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 numbers? Generally by trying different combinations and
  -testing the server.
  +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>
  -Before you start this task you should be armed with the proper weapon. You
  -need a crashme utility, which will load your server with mod_perl scripts
  -you possess. While there are commercial solutions, you can get away with
  -free ones who do the same job. You can use an
  +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>). You need these to have an ability to emulate a multiuser environment and
  -to emulate multiple clients behaviour which will call the mod_perl scripts
  -at your server simultaneously.
  +<CODE>LWP::Parallel::UserAgent</CODE> or <CODE>httperf</CODE> (see <A HREF="././download.html#">Download page</A>).
   
   <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 big, your testing machine much be very powerful and
  -capable to generate a big load. Of course you should not run the clients
  -and 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
  +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>
  @@ -823,12 +871,17 @@
   <STRONG>ab</STRONG> tool comes bundled with apache source distribution (and it's free :).
   
   <P>
  -Lets try it. We will simulate 10 users concurrently requesting the script <CODE>www.you.com:81/test/test.pl</CODE> which is a very light one. Each one makes 10 requests.
  +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>  % ./ab -n 100 -c 10 www.you.com:81/test/test.pl
  -  
  -  Concurrency Level:      10
  +<PRE>  % ./ab -n 100 -c 10 www.nowhere.com:81/test/test.pl
  +</PRE>
  +<P>
  +The results are:
  +
  +<P>
  +<PRE>  Concurrency Level:      10
     Time taken for tests:   0.715 seconds
     Complete requests:      100
     Failed requests:        0
  @@ -845,7 +898,7 @@
     Total:         13    67    74
   </PRE>
   <P>
  -The only numbers we are really care about are:
  +The only numbers we really care about are:
   
   <P>
   <PRE>  Complete requests:      100
  @@ -853,34 +906,35 @@
     Requests per second:    139.86
   </PRE>
   <P>
  -Let's raise the load of requests to 100 x 10 (10 users each 100 requests)
  +Let's raise the load of requests to 100 x 10 (10 users, each makes 100
  +requests)
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 10 www-pais:81/perl/access/access.cgi
  +<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>
  -As expected nothing changes (Since the situation didn't changed, we have
  -the same 10 concurrent users). Now let's raise the number of concurrent
  -users:
  +As expected nothing changes -- we have the same 10 concurrent users. Now
  +let's raise the number of concurrent users to 50:
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www-pais:81/perl/access/access.cgi
  +<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>
   We see that the server is capable of serving 50 concurrent users at an
  -amazing 133 req/sec! Lets find the upper bound. 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. It went down with the high load.
  +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>
  -This test was performed with the following configuration:
  +The above tests were performed with the following configuration:
   
   <P>
   <PRE>  MinSpareServers 8
  @@ -890,7 +944,8 @@
     MaxRequestsPerChild 1500
   </PRE>
   <P>
  -Now let's try this:
  +Now let's kill a child after a single request, we will use the following
  +configuration:
   
   <P>
   <PRE>  MinSpareServers 8
  @@ -899,13 +954,16 @@
     MaxClients 100
     MaxRequestsPerChild 1
   </PRE>
  +<P>
  +Simulate 50 users each generating a total of 20 requests:
  +
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www-pais:81/perl/access/access.cgi
  +<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
   </PRE>
   <P>
   The benchmark timed out with the above configuration.... I watched the
  -output of ps as I ran it, the parent process just wasn't capable of
  -respawning the killed children at that rate...When I raised 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).
  @@ -922,7 +980,8 @@
     MaxRequestsPerChild 1500
   </PRE>
   <P>
  -I got 27.12 req/sec, which is better but still 4-5 times slower (133 with <CODE>MaxClients</CODE> of 50)
  +I've got 27.12 req/sec, which is better but still 4-5 times slower (133
  +with <CODE>MaxClients</CODE> of 50)
   
   <P>
   <STRONG>Summary:</STRONG> I have tested a few combinations of server configuration variables (<CODE>MinSpareServers</CODE>  <CODE>MaxSpareServers</CODE>  <CODE>StartServers</CODE>
  @@ -944,9 +1003,9 @@
   
   <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. If the script
  -that was used to test was heavier, the numbers would be different but the
  -conclusions are very similar.
  +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>
   The benchmarks were run with:
  @@ -960,33 +1019,35 @@
   <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 one time by each child.
  +at least once by every child.
   
   <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 test but will not for the real world - users
  -will not wait for more than 5-10 secs for a request to complete, and the
  -browser will timeout in 30 secs or so.)
  +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>
   Now let's take a look at some real code whose execution time is more than a
  -few msecs. We will do real testing and collect the data in tables for
  +few millisecs. We will do real testing and collect the data in tables for
   easier viewing.
   
   <P>
  -I will use the following abbreviations
  +I will use the following abbreviations:
   
   <P>
  -<PRE>  NR    = Number of Request Total 
  -  NC    = Number of multiple requests to make
  +<PRE>  NR    = Total Number of Request
  +  NC    = Concurrency
     MC    = MaxClients
     MRPC  = MaxRequestsPerChild
     RPS   = Requests per second
   </PRE>
   <P>
  -Running a mod_perl script with lots of mysql queries (script mysqld
  -bounded) (http://www:81/perl/access/access.cgi?do_sub=query_form)
  +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>  MinSpareServers        8
  @@ -996,26 +1057,30 @@
     MaxRequestsPerChild 5000
   </PRE>
   <P>
  +gives us:
  +
  +<P>
   <PRE>     NR   NC    RPS     comment
     ------------------------------------------------
  -     10   10    3.33    # not a reliable stat
  +     10   10    3.33    # not a reliable statistics
       100   10    3.94    
      1000   10    4.62    
      1000   50    4.09    
   </PRE>
   <P>
   Conclusions: Here I wanted to show that when the application is slow -- not
  -due to perl loading, script compiling and execution, but bounded to some
  +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 browser can time
  -out!)
  +something that goes to queue means a waiting client and a client (browser)
  +that might time out!)
   
   <P>
   Now we will benchmark the same script without using the mysql (perl only
  -bounded) (http://www.you.com:81/perl/access/access.cgi)
  +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>
   <PRE>  MinSpareServers        8
  @@ -1027,7 +1092,7 @@
   <P>
   <PRE>     NR   NC      RPS   comment
     ------------------------------------------------
  -     10   10    26.95   # not a reliable stat
  +     10   10    26.95   # not a reliable statistics
       100   10    30.88   
      1000   10    29.31
      1000   50    28.01
  @@ -1038,8 +1103,8 @@
   <P>
   Conclusions: 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 RequestPerSecond (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
  +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.
  @@ -1081,7 +1146,7 @@
     
        NR   NC      RPS   comment
     ------------------------------------------------
  -     10   10    23.87   # not a reliable stats
  +     10   10    23.87   # not a reliable statistics
       100   10    32.64 
      1000   10    32.82
      1000   50    30.43
  @@ -1100,7 +1165,7 @@
   numbers!
   
   <P>
  -Now we will start to drastically reduce the MaxRequestsPerClient:
  +Now we will start to drastically reduce the <CODE>MaxRequestsPerChild</CODE>:
   
   <P>
   <PRE>  MinSpareServers        8
  @@ -1118,7 +1183,7 @@
      1000  100      10    6.51
   </PRE>
   <P>
  -Conclusions: When we drastically reduce the <CODE>MaxRequestsPerClient</CODE>, the performance starts to become closer to the plain mod_cgi. Just for
  +Conclusions: 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>
  @@ -1135,9 +1200,9 @@
   </PRE>
   <P>
   Conclusion: mod_cgi is much slower :) in test NReq/NClients 100/10 the RPS
  -in mod_cgi 1.12 and in mod_perl 32 =&gt; 30 times faster !!! In the first
  -test each child waited about 100 secs to be served. In the second and third
  -1000 secs!
  +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>
  @@ -1146,27 +1211,27 @@
   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> ops :). I also
  -allowed it to accept more than one url, since sometimes you want to test an
  -overall and not just one script.
  +. 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>
   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 Latency
   (secs/Request) and Throughput (Requests/sec) numbers. It can give you a
   better picture and make a complete simulation of your favorite Netscape
  -browser :)
  +browser :).
   
   <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. Weird ha? Any ideas why? Again
  -C vs Perl question :(
  +with the same load with the same parameters. But the implementations are
  +different.
   
   <P>
  -Sample output: 
  +Sample output:
   
   <P>
  -<PRE>  URL(s):          <A HREF="http://www.you.com:81/perl/access/access.cgi">http://www.you.com:81/perl/access/access.cgi</A>
  +<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%)
  @@ -1193,8 +1258,8 @@
     my $nof_requests_total = 100; 
     my $timeout = 10;
     my @urls = (
  -            '<A HREF="http://www.you.com:81/perl/faq_manager/faq_manager.pl">http://www.you.com:81/perl/faq_manager/faq_manager.pl</A>',
  -            '<A HREF="http://www.you.com:81/perl/access/access.cgi">http://www.you.com:81/perl/access/access.cgi</A>',
  +            '<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>',
              );
     
     
  @@ -1326,23 +1391,20 @@
   <P>
   The <CODE>MaxClients</CODE> directive sets the limit on the number of simultaneous requests that can be
   supported; not more than this number of child server processes will be
  -created. To configure more than 256 clients, you must edit the
  -HARD_SERVER_LIMIT entry in httpd.h and recompile. In our case we want to
  -set this variable as small as possible, this way we can virtually bound the
  -resources used by the server children. If we know that we have X Mb of RAM,
  -each child consumes a maximum of Y Mb of RAM (we can restrict each child.
  -See
  -<A HREF="././performance.html#Limiting_the_size_of_the_process">Limiting the size of the processes</A>) and we have all these X Mb dedicated for the webserver. Then calculation
  -of
  -<CODE>MaxClients</CODE> is pretty straightforward :
  +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>  MaxClients = Total Available to the webserver RAM / MAX child's size
  +<PRE>  MaxClients = Total RAM Dedicated to the Webserver / MAX child's process size
   </PRE>
   <P>
  -So if I have 400Mb left for the webserver to run in, I can set the
  +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
  -(with <CODE>Apache::SizeLimit</CODE>, See the reference above.)
  +(e.g. with
  +<A HREF="././performance.html#Limiting_the_size_of_the_process"><CODE>Apache::SizeLimit</CODE></A>).
   
   <P>
   Certainly you will wonder what happens to your server if there are more
  @@ -1354,32 +1416,46 @@
   <PRE>  [Sun Jan 24 12:05:32 1999] [error] server reached MaxClients setting,
     consider raising the MaxClients setting
   </PRE>
  +<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.
  +
  +<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 reached you should start to worry about it.
  +
  +<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>
  +<PRE>  MaxClients=(Total_RAM+Shared_RAM_per_Child*MaxClients)/Max_Process_Size-1
  +</PRE>
   <P>
  -No problem - any connection attempts over the <CODE>MaxClients</CODE> limit will normally be queued, up to a number based on the ListenBacklog
  -directive. Once a child process is freed at the end of a different request,
  -the connection will then be serviced.
  -
  -<P>
  -It <STRONG>is</STRONG> an error because clients are being put in the queue rather than getting
  -serviced at once, but 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 thing is not to have this condition reached at all.
  -
  -<P>
  -It's important to understand how much memory a child occupies. If your
  -children can share some memory (when the 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 me know)
  +which is:
   
   <P>
  +<PRE>  MaxClients=(Total_RAM-Max_Process_Size)/(Max_Process_Size-Shared_RAM_per_Child)
  +</PRE>
  +<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>
   <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 never expire.
  +<CODE>MaxRequestsPerChild</CODE> is 0, then the process will live forever.
   
   <P>
   Setting <CODE>MaxRequestsPerChild</CODE> to a non-zero limit has two beneficial effects: it solves memory leakages
  @@ -1390,16 +1466,12 @@
   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 some standard modules leak memory,
  -especially on OSes where memory managements is bad (Solaris 2.5 on x86 ?)
  -
  -<P>
  -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 lose the
  -speed bonus you receive with mod_perl, so maybe you should consider falling
  -back to plain mod_cgi, since the overhead of reloading the script and the
  -perl interpreter for each request will be too high. 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
  +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 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!)
   
   <P>
  @@ -1414,7 +1486,7 @@
   <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>
   <P>
  -With mod_perl enabled, it might take as much as 3-30 seconds from the time
  +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
  @@ -1438,8 +1510,8 @@
   
   <P>
   <PRE>  Available to webserver RAM:   400Mb
  -  Child's memory size bounded:    10Mb
  -  MaxClients:                   400/10 = 40
  +  Child's memory size bounded:  10Mb
  +  MaxClients:                   400/10 = 40 (larger with mem sharing)
     StartServers:                 20
     MinSpareServers:              20
     MaxSpareServers:              35
  @@ -1450,7 +1522,7 @@
   
   <P>
   <PRE>  Available to webserver RAM:   400Mb
  -  Child's memory size bounded:    10Mb
  +  Child's memory size bounded:  10Mb
     MaxClients:                   400/10 = 40
     StartServers:                 5
     MinSpareServers:              5
  @@ -1465,14 +1537,16 @@
   <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>
  -OK, we've run various benchmarks let's summarize the conclusions:
  +OK, we've run various benchmarks -- let's summarize the conclusions:
   
   <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).
  +<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><STRONG><A NAME="item_StartServers">StartServers</A></STRONG>
   <P>
  @@ -1499,53 +1573,38 @@
   <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 too long).
  -Don't make it high, since if you get a high load and all requests will be
  -immediately granted, 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 could 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. 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 that are running, the
  -more CPU time will be required, the less CPU time slices each process will
  +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>
  +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 start testing like I did,
  -successively raising this parameter until you find the point on the curve
  -of the graph of the latency or 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.
  -Also don't forget that if you add more scripts, most probably that the
  +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="Preopen_DB_connection_at_server_">Preopen DB connection at server startup:</A></H1></CENTER>
  -<P>
  -If you use DBI for DB connections, you can preopen connections to DB for
  -each child with Apache::DBI.
  -
  -<P>
  -<PRE>  use Apache::DBI ();
  -  Apache::DBI-&gt;connect_on_init(&quot;DBI:mysql:test&quot;, 'login','passwd', 
  -                               {
  -                                RaiseError =&gt; 1,
  -                                PrintError =&gt; 1,
  -                                AutoCommit =&gt; 1,
  -                               };
  -</PRE>
  -<P>
  -See also <A HREF="#Persistent_DB_Connections">Persistent DB Connections</A>.
  -
  -<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
  @@ -1553,7 +1612,8 @@
   follows:
   
   <P>
  -<PRE>  #Apache::Registry script
  +<PRE>  # Apache::Registry script
  +  -------------------------
     use strict;
     use vars qw($dbh);
     
  @@ -1569,16 +1629,16 @@
   
   <P>
   <CODE>Apache::DBI</CODE> allows you to make a persistent database connection. With this module
  -enabled, every connect request to the plain DBI module will be forwarded to
  -the <CODE>Apache::DBI</CODE> module. This looks to see whether a database handle from a previous connect
  -request has already been opened, and if this handle is still valid using
  +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 disconnect
  -statements from your code</STRONG>. They will not do anything, as the
  -<CODE>Apache::DBI</CODE> module overloads the disconnect method with a NOP. On child exit there is
  -no explicit disconnect, the child dies and so does the database connection.
  +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>
   The usage is simple -- add to <CODE>httpd.conf</CODE>:
  @@ -1590,7 +1650,7 @@
   It is important, to load this module before any other <CODE>ApacheDBI*</CODE> module!
   
   <P>
  -<PRE>  a script.perl
  +<PRE>  db.pl
     ------------
     use DBI;
     use strict;
  @@ -1602,61 +1662,68 @@
     ...rest of the program
   </PRE>
   <P>
  -The module provides the additional method:
  +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>
  -<PRE>  Apache::DBI-&gt;connect_on_init($data_source, $username, $auth, \%attr)
  +<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>
   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
  -(PerlModule, &lt;Perl&gt; or PerlRequire). 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>
  -Beware however, as some old DBD drivers do not support this feature (ping
  -method), so check the documentation of the driver you use.
  +<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>
   Another problem is with timeouts: some databases disconnect the client
  -after a certain time of inactivity. The ping method ensures that this will
  -not happen. Some DBD drivers don't have this method, check the Apache::DBI
  -manpage to see how to write a ping method.
  +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. 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
  +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="Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</A></H1></CENTER>
   <P>
  -As you know <CODE>$|=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.
  +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>
   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.
  +in performance. The severity depends on the number of the calls you make.
   
   <P>
   Many old CGIs were written in the style of:
   
   <P>
  -<PRE>  print &quot;&lt;BODY BGCOLOR=&quot;black&quot; TEXT=&quot;white&quot;&gt;&quot;;
  +<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;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 $|=1, 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:
  +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>
   <PRE>  print qq{
  @@ -1670,7 +1737,7 @@
   </PRE>
   <P>
   I guess you see the difference. Be careful though, when printing a
  -<CODE>&amp;lt;HTML&amp;gt;</CODE> tag. The correct way is:
  +<CODE>&lt;HTML</CODE>&gt; tag. The correct way is:
   
   <P>
   <PRE>  print qq{&lt;HTML&gt;
  @@ -1691,20 +1758,19 @@
   <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>&amp;lt;HTML&amp;gt;</CODE> and not spaces and/or additional newline and then <CODE>&amp;lt;HTML&amp;gt;</CODE>. Even if it works with your browser, it might not work for others.
  +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>
  -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 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
  +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:
  +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 Submit
  +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>
  -What do you like better: getting the output ``slowly'' but steadily or
  -having to watch the ``falling stars'' for awhile and then to receive the
  -whole output at once (if the browser did not timeout till then).
  -
  -<P>
   Conclusion: Do not blindly follow suggestions, but think what is best for
   you in every given case.
   
  @@ -1731,18 +1797,18 @@
   <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>
   <P>
  -Profiling will help you to determine which subroutines or just snippets of
  -code take the longest execution time and which subroutines are being called
  -most often, then you will probably will want to optimize those, and to
  -improve the code toward efficiency.
  +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>
   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. When the server is started, <CODE>Devel::DProf</CODE> installs an
  -<CODE>END</CODE> block to write the <CODE>tmon.out</CODE> file, which will be called at the server shutdown. Here is how to start and
  -stop a server with the profiler enabled:
  +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:
   
   <P>
   <PRE>  % setenv PERL5OPT -d:DProf
  @@ -1755,22 +1821,27 @@
   <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 that <CODE>print()</CODE> and <CODE>map()</CODE> are subs as well, they come together with Perl!).
  +that <CODE>print()</CODE> and <CODE>map()</CODE> are just like any other subroutines you write, but they are come bundled
  +with Perl!)
   
   <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. All it takes is to add to <CODE>httpd.conf</CODE>:
  +<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>  PerlModule Apache::DProf
   </PRE>
   <P>
  -Remember that any PerlHandler .pm that was pulled in before
  -<CODE>Apache::DProf</CODE>, would not have its code debugging info inserted.
  +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>
  +<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>
  @@ -1815,7 +1886,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.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>
  @@ -1828,7 +1899,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.18      +1001 -459 modperl-site/guide/porting.html
  
  Index: porting.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/porting.html,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- porting.html	1999/06/19 21:15:12	1.17
  +++ porting.html	1999/07/02 13:42:30	1.18
  @@ -22,45 +22,49 @@
   <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>
   CGI to mod_perl Porting. mod_perl Coding guidelines.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
   	<LI><A HREF="#Document_Coverage">Document Coverage</A>
   	<LI><A HREF="#Before_you_start_to_code">Before you start to code</A>
  -	<LI><A HREF="#Coding_with_mod_perl">Coding with mod_perl</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>
   	<UL>
   
  -		<LI><A HREF="#What_s_different_about_modperl">What's different about modperl</A>
  -		<UL>
  -
  -			<LI><A HREF="#Script_s_name_space">Script's name space</A>
  -			<LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  -			<LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  -			<LI><A HREF="#Output_from_system_calls">Output from system calls</A>
  -			<LI><A HREF="#Using_format_">Using format()</A>
  -			<LI><A HREF="#Using_exit_">Using exit()</A>
  -			<LI><A HREF="#Running_from_shell">Running from shell</A>
  -			<LI><A HREF="#I_O_is_different">I/O is different</A>
  -			<LI><A HREF="#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  -			<LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  -			<LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
  -			<LI><A HREF="#END_blocks">END blocks </A>
  -			<LI><A HREF="#Switches_w_T">Switches -w, -T</A>
  -		</UL>
  -
  +		<LI><A HREF="#Script_s_name_space">Script's name space</A>
  +		<LI><A HREF="#Name_collisions_with_Modules_and">Name collisions with Modules and libs</A>
  +		<LI><A HREF="#_END_or_DATA_tokens">__END__ or __DATA__ tokens</A>
  +		<LI><A HREF="#Output_from_system_calls">Output from system calls</A>
  +		<LI><A HREF="#Using_format_">Using format()</A>
  +		<LI><A HREF="#Using_exit_">Using exit()</A>
  +		<LI><A HREF="#Running_from_shell">Running from shell</A>
  +		<LI><A HREF="#I_O_is_different">I/O is different</A>
  +		<LI><A HREF="#HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A>
  +		<LI><A HREF="#NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A>
  +		<LI><A HREF="#BEGIN_blocks">BEGIN blocks </A>
  +		<LI><A HREF="#END_blocks">END blocks</A>
  +		<LI><A HREF="#Switches_w_T">Switches -w, -T</A>
   		<LI><A HREF="#strict_pragma">strict pragma</A>
   		<LI><A HREF="#Turning_warnings_ON">Turning warnings ON</A>
   		<LI><A HREF="#diagnostics_pragma">diagnostics pragma</A>
  -		<LI><A HREF="#Global_Variables">Global Variables</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="#Memory_leakage">Memory leakage</A>
   	</UL>
   
  +	<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
  +	<UL>
  +
  +		<LI><A HREF="#Restarting_the_server">Restarting the server</A>
  +		<LI><A HREF="#Using_Apache_StatINC">Using Apache::StatINC</A>
  +		<LI><A HREF="#Reloading_only_specific_files">Reloading only specific files</A>
  +	</UL>
  +
   	<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
  -	<LI><A HREF="#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</A>
  -	<LI><A HREF="#The_Script_is_too_dirty_It_does">The Script is too dirty, It does the job and I can't afford rewriting it.</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="#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>
  @@ -98,21 +102,20 @@
   
   <P>
   It covers also the case where the CGI script being ported does the job, but
  -is too dirty to be easily altered to run as a mod_perl program.
  -(Apache::PerlRun)
  +is too dirty to be easily altered to run as a mod_perl program. (<CODE>Apache::PerlRun</CODE>)
   
   <P>
   If your project schedule is tight, I would suggest converting to mod_perl
   in the following steps: Initially, run all the scripts in the
  -Apache::PerlRun mode. Then as time allows, move them into Apache::Registry
  -mode.
  +<CODE>Apache::PerlRun</CODE> mode. Then as time allows, move them into
  +<CODE>Apache::Registry</CODE> mode.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Before_you_start_to_code">Before you start to code</A></H1></CENTER>
   <P>
   It can be a good idea to tighten up some of your Perl programming
  -practices, since Apache::Registry doesn't allow sloppy programming.
  +practices, since <CODE>Apache::Registry</CODE> doesn't allow sloppy programming.
   
   <P>
   You might want to read:
  @@ -133,100 +136,500 @@
   </UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Coding_with_mod_perl">Coding with mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Exposing_Apache_Registry_secret">Exposing Apache::Registry secrets</A></H1></CENTER>
   <P>
  -Before you start coding for Apache::Registry, you have to change your
  -programming state of mind. Scripts running under mod_perl are like
  -subroutines are being called from a continually running daemon. Imagine a
  -daemon process that when requested to process some script, reads it in,
  -compiles it as a subroutine, and finally executes it. On any subsequent
  -request, it'll just recall the already compiled subroutine. Hope that you
  -get the idea.
  +Let's start with some simple code and see what can go wrong with it ,detect
  +bugs and debug them, discuss possible caveats and how to avoid them.
   
   <P>
  -The best thing you do when coding from scratch is to make it clean and use
  -packages. By ``make it clean'' we mean make certain that you <STRONG>use strict;</STRONG>
  -and that your script produces no warnings when tested via
  -<STRONG>perl -cw myscript.pl</STRONG>. As you go thru the notes you will understand why.
  +I will use a simple CGI script, that initializes a <CODE>$counter</CODE> to 0, and prints its value to the screen while incrementing it.
  +
  +<P>
  +<PRE>  counter.pl:
  +  ----------
  +  #!/usr/bin/perl -w
  +  use strict;
  +  
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  
  +  my $counter = 0;
  +  
  +  for (1..5) {
  +    increment_counter();
  +  }
  +  
  +  sub increment_counter{
  +    $counter++;
  +    print &quot;Counter is equal to $counter !&lt;BR&gt;\n&quot;;
  +  }
  +  ----------
  +</PRE>
  +<P>
  +You would expect to see an output:
  +
  +<P>
  +<PRE>  Counter is equal to 1 !
  +  Counter is equal to 2 !
  +  Counter is equal to 3 !
  +  Counter is equal to 4 !
  +  Counter is equal to 5 !
  +</PRE>
  +<P>
  +And that's what you see when you execute this script at first time. But
  +let's reload it a few times... See, suddenly after a few reloads the
  +counter doesn't start its count from 5 anymore. We continue to reload and
  +see that it keeps on growing, but not steadily 10, 10, 10, 15, 20...
  +Weird...
  +
  +<P>
  +<PRE>  Counter is equal to 6 !
  +  Counter is equal to 7 !
  +  Counter is equal to 8 !
  +  Counter is equal to 9 !
  +  Counter is equal to 10 !
  +</PRE>
  +<P>
  +We saw two anomalies in this very simple script: Unexpected growth of
  +counter over 5 and inconsistent growth over reloads. Let's investigate this
  +script.
  +
  +<P>
  +First let's peek into an <CODE>error_log</CODE> file... what we see is:
  +
  +<P>
  +<PRE>  Variable &quot;$counter&quot; will not stay shared 
  +  at /home/httpd/perl/conference/counter.pl line 13.
  +</PRE>
  +<P>
  +What kind of error is this? We should ask perl to help us. I'm going to
  +enable a special diagnostics mode, by adding at the top of the script:
  +
  +<P>
  +<PRE>  use diagnostics;
  +</PRE>
  +<P>
  +Reloading again, <CODE>error_log</CODE> shows:
  +
  +<P>
  +<PRE>    Variable &quot;$counter&quot; will not stay shared at
  +        /home/httpd/perl/conference/counter.pl line 15 (#1)
  +    
  +    (W) An inner (nested) named subroutine is referencing a lexical
  +    variable defined in an outer subroutine.
  +    
  +    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.
  +    
  +    Furthermore, if the outer subroutine is anonymous and references a
  +    lexical variable outside itself, then the outer and inner subroutines
  +    will never share the given variable.
  +    
  +    This problem can usually be solved by making the inner subroutine
  +    anonymous, using the sub {} syntax.  When inner anonymous subs that
  +    reference variables in outer subroutines are called or referenced,
  +    they are automatically rebound to the current values of such
  +    variables.
  +</PRE>
  +<P>
  +Actually perl detected a <STRONG>closure</STRONG>, which is sometimes a wanted effect, but not in our case (see <CODE>perldoc perlsub</CODE> for more information about closures). While <CODE>diagnostics.pm</CODE> sometimes is handy for debugging purpose - it drastically slows down your
  +CGI script. Make sure you remove it in your production server.
  +
  +<P>
  +Do you see a <STRONG>nested named subroutine</STRONG> in my script? I do not!!! What is going on? I suggest to report a bug. But
  +wait, may be a perl interpreter sees the script in a different way, may be
  +the code goes through some changes before it actually gets executed? The
  +easiest way to check what's actually happening is to run the script with
  +debugger, but since we must debug it when it's being executed by the
  +server, normal debugging process wouldn't help, for we have to invoke the
  +debugger from within the webserver. Luckily Doug wrote an
  +<CODE>Apache::DB</CODE> module and we will use it to debug my script. I'll do it non-interactively
  +(while you can debug interactively with
  +<CODE>Apache::DB</CODE>). I change my <CODE>http.conf</CODE> with:
  +
  +<P>
  +<PRE>  PerlSetEnv PERLDB_OPTS &quot;NonStop=1 LineInfo=/tmp/db.out AutoTrace=1 frame=2&quot;
  +  PerlModule Apache::DB
  +  &lt;Location /perl&gt;
  +    PerlFixupHandler Apache::DB
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry::handler
  +    Options ExecCGI
  +    PerlSendHeader On
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +Comment out '<CODE>use diagnostics;</CODE>', restart the server and call the
  +<CODE>counter.pl</CODE> from your browser. On the surface nothing changed - we still see the
  +correct output as before, but two things happened at the background: first
  +-- the <CODE>/tmp/db.out</CODE> was written, with a complete trace of the code that was executed, second -- <CODE>error_log</CODE> file showed us the whole code that was executed as a side effect of
  +reporting the warning we saw before: <CODE>Variable &quot;$counter&quot; will not
  +stay shared at (eval 52) line 15...</CODE>. In any case that's the code that actually is being executed:
  +
  +<P>
  +<PRE>  package Apache::ROOT::perl::conference::counter_2epl;
  +  use Apache qw(exit);
  +  sub handler {
  +    BEGIN {
  +      $^W = 1;
  +    };
  +    $^W = 1;
  +    
  +    use strict;
  +    
  +    print &quot;Content-type: text/html\\r\\n\\r\\n&quot;;
  +    
  +    my $counter = 0;
  +    
  +    for (1..5) {
  +      increment_counter();
  +    }
  +    
  +    sub increment_counter{
  +      $counter++;
  +      print &quot;Counter is equal to $counter !&lt;BR&gt;\\n&quot;;
  +    }
  +    
  +  }
  +</PRE>
  +<P>
  +What do we learn from this discovering? First that every cgi script is
  +being cached under a package whose name is compounded from
  +<CODE>Apache::ROOT::</CODE> prefix and the relative part of the script's URL (<CODE>perl::conference::counter_2epl</CODE>) by replacing all occurrences of
  +<CODE>/</CODE> with <CODE>::</CODE>. That's how mod_perl knows what script should be fetched from cache - each
  +script is just a package with a single subroutine named <CODE>handler</CODE>. Now you understand why <CODE>diagnostics</CODE>
  +pragma talked about inner (nested) subroutine - <CODE>increment_counter</CODE>
  +is actually a nested sub. In every script each subroutine is nested inside
  +the <CODE>handler</CODE> subroutine.
  +
  +<P>
  +The workaround is to use global declared variables, with <CODE>vars</CODE>
  +pragma.
  +
  +<P>
  +<PRE>  # !/usr/bin/perl -w
  +  use strict;
  +  use vars qw($counter);
  +  
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  
  +  $counter = 0;
  +  
  +  for (1..5) {
  +    increment_counter();
  +  }
  +  
  +  sub increment_counter{
  +    $counter++;
  +    print &quot;Counter is equal to $counter !&lt;BR&gt;\n&quot;;
  +  }
  +</PRE>
  +<P>
  +There is no more <CODE>closure</CODE> effect, since there is no <CODE>my()</CODE>
  +(lexically) defined variable being used in the nested subroutine.
  +
  +<P>
  +Another approach is to use fully qualified variables, which is even better,
  +since less memory will be used, but it adds an overhead of extra typing:
  +
  +<P>
  +<PRE>  #!/usr/bin/perl -w
  +  use strict;
  +  
  +  print &quot;Content-type: text/html\r\n\r\n&quot;;
  +  
  +  $main::counter = 0;
  +  
  +  for (1..5) {
  +    increment_counter();
  +  }
  +  
  +  sub increment_counter{
  +    $main::counter++;
  +    print &quot;Counter is equal to $main::counter !&lt;BR&gt;\n&quot;;
  +  }
  +</PRE>
  +<P>
  +Now let's proceed to the second mystery. Why did we see inconsistent
  +results over numerous reloads. That's very simple. Every time a server gets
  +a request to process, it handles it over one of the children, generally in
  +a round robin fashion. So if you have 10 httpd children alive, first 10
  +reloads might seem to be correct. Since the closure starts to effect from
  +the second re-invocation, consequent reloads return unexpected results.
  +Moreover children don't serve the same request always consequently, at any
  +given moment one of the children could serve more times the same script
  +than any other. That's why we saw that strange behavior.
  +
  +<P>
  +A workaround is to run the server in a single server mode. You achieve this
  +by invoking the server with <CODE>-X</CODE> parameter (<CODE>httpd -X</CODE>). Since there is no other servers (children) running - you will detect the
  +problem on the second reload. But before that let the <CODE>error_log</CODE> to help you detect most of the possible errors - most of the warnings can
  +become errors, so you better make sure to check every warning that is being
  +detected by perl, and probably to write the code in a way, that none of the
  +warnings will show up in the <CODE>error_log</CODE>. If your
  +<CODE>error_log</CODE> file is being filled up with hundreds of lines on every script invocation -
  +you will have a problem to locate and notice real problems.
  +
  +<P>
  +Of course none of the warnings will be reported if the warning mechanism
  +will not be turned ON. With mod_perl it is also possible to turn on
  +warnings globally via the PerlWarn directive, just add into a
  +<CODE>httpd.conf</CODE>:
  +
  +<P>
  +<PRE>    PerlWarn On
  +</PRE>
  +<P>
  +You can turn it off within your code with <CODE>local $^W=0</CODE>. on the local basis (or inside the block). If you write <CODE>$^W=0</CODE> you disable the warning mode everywhere inside the child, <CODE>$^W=1</CODE> enables it back. So if perl warns you somewhere you sure it's not a
  +problem, you can locally disable the warning, e.g.:
  +
  +<P>
  +<PRE>  [snip]
  +    # we want perl to be quiet here - 
  +    # we don't care whether $a was initialized
  +  local $^W = 0;
  +    print $a;
  +  local $^W = 1;
  +  [snip]
  +</PRE>
  +<P>
  +Of course this is not a way to fix initialization and other problems, but
  +sometimes it helps.
   
   <P>
  +While having a warning mode turned <STRONG>On</STRONG> is a must in a development server, you better turn it globally <STRONG>Off</STRONG> in a production server, since if every CGI script generates only one
  +warning per request, and your server serves millions of requests per day -
  +your log file will eat up all of your disk space and machine will die. My
  +production serves has the following directive in the <CODE>httpd.conf</CODE>:
  +
  +<P>
  +<PRE>    PerlWarn Off
  +</PRE>
  +<P>
  +While we are talking about control flags, another even more important flag
  +is <CODE>-T</CODE> which turns <STRONG>On</STRONG> the <STRONG>Taint</STRONG> mode <STRONG>On</STRONG>. Since this is very broad topic I'll not discuss it here, but if you
  +aren't forcing all of your scripts to run under <STRONG>Taint</STRONG> mode you are looking for a trouble (always remember about malicious users).
  +To turn it on, add to
  +<CODE>httpd.conf</CODE>:
  +
  +<P>
  +<PRE>  PerlTaintCheck On
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="What_s_different_about_modperl">What's different about modperl</A></H2></CENTER>
  +<CENTER><H1><A NAME="Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it Does Not</A></H1></CENTER>
  +<P>
  +When you start running your scripts under mod_perl, you might find yourself
  +in situation where a script seems to work, but sometimes it screws up. And
  +the more it runs without a restart, the more it screws up. Many times you
  +can resolve this problem very easily. You have to test your script under a
  +server running in a single process mode (<CODE>httpd -X</CODE>).
  +
  +<P>
  +Generally the problem you have is of using global variables. Since global
  +variables don't change from one script invocation to another unless you
  +change them, you can find your scripts do ``fancy'' things.
  +
  +<P>
  +The first example is amazing -- Web Services. Imagine that you enter some
  +site you have your account on (Free Email Account?). Now you want to see
  +what other users read.
  +
   <P>
  +You type in your name and passwd, and you expect to enter to your account,
  +but instead you enter the account of someone else. This is cool isn't it?
  +Is it a bug or feature. (For some of us it's a feature, while for others
  +it's a bug.) You say, why in the world does this happen? The answer is
  +simple: Global Variables. You have entered the account of someone who
  +happened to be served by the same server child as you. Because of sloppy
  +programming, a global variable was not reset at the beginning of the
  +program and voila, you can easily peek into other people's emails! You
  +would think that it can't happen, since you have entered the login and
  +passwd. I tell you, it happens! See for yourself:
  +
  +<P>
  +<PRE>  use vars ($authenticated);
  +  my $q = new CGI;
  +  my $username = $q-&gt;param('username');
  +  my $passwd   = $q-&gt;param('passwd');
  +  authenticate($username,$passwd);
  +    # failed, break out
  +  die &quot;Wrong passwd&quot; unless $authenticated == 1;
  +    # user is OK, fetch user's data
  +  show_user($username);
  +  
  +  sub authenticate{
  +    my ($username,$passwd) = @_;
  +        # some checking
  +    $authenticated = 1 if (SOMETHING);
  +  }
  +</PRE>
  +<P>
  +Do you see the catch? With the code above, I can type in any valid username
  +and any dummy passwd and enter that user's account, if someone has
  +successfully entered his account before me using the same child process!
  +Since <STRONG>$authenticated</STRONG> is global - if it becomes 1 once it'll be 1 for the remainder of the
  +child's life!!! The solution is trivial -- reset <STRONG>$authenticated</STRONG> to 0 at the beginning of the program. (Or many other different solutions).
  +Of course this example is trivial -- but believe me it happens!
  +
  +<P>
  +Just another little one liner that can spoil your day, assuming you forgot
  +to reset the <STRONG>$allowed</STRONG> variable. It works perfectly OK in plain mod_cgi:
  +
  +<P>
  +<PRE>  $allowed = 1 if $username eq 'admin';
  +</PRE>
  +<P>
  +But you will let any user to admin your system with the line above (again
  +assuming you have used the same child prior to some user request).
  +
  +<P>
  +Another good example is usage of the <STRONG>/o</STRONG> regular expression qualifier, which compiles a regular expression once, on
  +its first execution and never recompile it again. This problem can be
  +difficult to detect, as after restarting the server each request you make
  +will be served by a different child process, and thus the regex pattern for
  +that child will be compiled fresh. Only when you make a request that
  +happens to be served by a child which has already cached the regexp will
  +you see the problem. Generally you miss that and when you press reload, you
  +see that it works (with a new, fresh child) and then it doesn't (with a
  +child that already cached the regexp and wouldn't recompile because of <STRONG>/o</STRONG>.) The example of such a case would be:
  +
  +<P>
  +<PRE>  my $pat = '^foo$'; # likely to be input from an HTML form field
  +  foreach( @list ) {
  +    print if /$pat/o;
  +  }
  +</PRE>
  +<P>
  +To make sure you don't miss these bugs always test your CGI in
  +<A HREF="././control.html#Running_server_in_a_single_mode">single process</A>. To solve this particular <STRONG>/o</STRONG> problem refer to <A HREF="././obvious.html#Compiled_Regular_Expressions">Compiled Regular Expressions</A>.
  +
  +<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><H3><A NAME="Script_s_name_space">Script's name space</A></H3></CENTER>
  +<CENTER><H2><A NAME="Script_s_name_space">Script's name space</A></H2></CENTER>
   <P>
  -Scripts under Apache::Registry do not run in package <STRONG>main</STRONG>, they run in a unique name space based on the requested URI. For example,
  -if your URI is <STRONG>/perl/test.pl</STRONG> the package will be called 
  -<STRONG>Apache::ROOT::perl::test_2epl;</STRONG>
  -
  +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,
  +if your URI is <STRONG>/perl/test.pl</STRONG> the package will be called
  +<STRONG>Apache::ROOT::perl::test_2epl</STRONG>.
   
  -
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H3></CENTER>
  +<CENTER><H2><A NAME="Name_collisions_with_Modules_and">Name collisions with Modules and libs</A></H2></CENTER>
   <P>
  -Just to make things clear before we go into detail: each server process has
  -its own <CODE>%INC</CODE> hash which is used to store information about its
  -compiled modules. The keys of the hash are the names of the modules or
  -parameters passed to <CODE>require().</CODE> The values are the real paths
  -to these modules. So if you do (assume it's in the <CODE>@INC</CODE> path)
  +To make things clear before we go into details: each child process has its
  +own <CODE>%INC</CODE> hash which is used to store information about its compiled modules. The
  +keys of the hash are the names of the modules or parameters passed to <CODE>require()</CODE>. The values are the real paths to these modules. So if you do:
   
   <P>
  -<PRE>  require &quot;./my/lib.pl&quot;;
  +<PRE>  use lib qw(.);
  +  require &quot;./my/lib.pl&quot;;
   </PRE>
   <P>
  -where <CODE>./my/lib.pl</CODE> is actually a <CODE>/home/httpd/perl/my/lib.pl</CODE>. The following entry will show up in the <CODE>%INC</CODE>
  +where <CODE>./my/lib.pl</CODE> is actually a <CODE>/home/httpd/perl/my/lib.pl</CODE>. The following entry will show up in the <CODE>%INC</CODE>:
   
   <P>
  -<PRE>  $INC{&quot;./my/lib.pl&quot;} = &quot;/home/httpd/perl/my/lib.pl&quot;;
  +<PRE>  print $INC{&quot;./my/lib.pl&quot;};
  +   
  +  printed result:
  +  ---------------
  +  /home/httpd/perl/my/lib.pl
   </PRE>
   <P>
   I'm talking about single server child below!
   
   <P>
  -You can't have 2 identical module names running under the same server! Only
  -the first one <CODE>use()'d</CODE> or <CODE>require()'d</CODE> will be
  -compiled into the package, the request to the other identical module will
  -be skipped since server will think that it's already compiled. It'll be
  -already in child's %INC. (See <A HREF="././status.html#Watching_the_server">Watching the server</A> 
  -section to find out how you can know what is loaded and where)
  +Let's look at 3 faulty scenarios:
   
  +<DL>
  +<P><DT><STRONG><A NAME="item_Scenario">Scenario 1</A></STRONG><DD>
  +<P>
  +First, You can't have 2 identical module names running under the same
  +server! Only the first one <CODE>use()'d</CODE> or <CODE>require()'d</CODE>
  +will be compiled into the package, the request to the other identical
  +module will be skipped since server will think that it's already compiled.
  +It's already in the child's <CODE>%INC</CODE>. (See <A HREF="././status.html#Watching_the_server">Watching the server</A> section to find out how you can know what is loaded and where)
  +
  +<P>
  +So if you have two different <CODE>Foo</CODE> modules in two different directories and two scripts <CODE>script1.pl</CODE> and <CODE>script2.pl</CODE>, locate like:
  +
  +<P>
  +<PRE>  ./cgi/tool1/Foo.pm
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/Foo.pm
  +  ./cgi/tool2/tool2.pl
  +</PRE>
   <P>
  -So if you have 
  +Where a sample code could be:
   
   <P>
  -<PRE>  cgi/tool1/Foo.pm 
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/Foo.pm 
  -  cgi/tool2/tool2.pl
  +<PRE>  ./cgi/tool1/tool1.pl
  +  --------------------
  +  use Foo;
  +  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;I'm Script number One&lt;BR&gt;\n&quot;;
  +  foo();
  +  --------------------
   </PRE>
   <P>
  -And both scripts do: <CODE>use Foo;</CODE> only the first one called will know about Foo, when you will call the
  +<PRE>  ./cgi/tool1/Foo.pm
  +  --------------------
  +  sub foo{
  +    print &quot;&lt;B&gt;I'm Tool Number One!&lt;/B&gt;&lt;BR&gt;\n&quot;;
  +  }
  +  1;
  +  --------------------
  +</PRE>
  +<P>
  +<PRE>  ./cgi/tool2/tool2.pl
  +  --------------------
  +  use Foo;
  +  print &quot;Content-type: text/html\n\n&quot;;
  +  print &quot;I'm Script number Two&lt;BR&gt;\n&quot;;
  +  foo();
  +  --------------------
  +</PRE>
  +<P>
  +<PRE>  ./cgi/tool2/Foo.pm
  +  --------------------
  +  sub foo{
  +    print &quot;&lt;B&gt;I'm Tool Number Two!&lt;/B&gt;&lt;BR&gt;\n&quot;;
  +  }
  +  1;
  +  --------------------
  +</PRE>
  +<P>
  +And both scripts call: <CODE>use Foo</CODE> only the first one called will know about Foo, when you will call the
   second script it will not know about Foo at all - it's like you've
  -forgotten to write <CODE>use Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to solve that kind of bug immediately.
  +forgotten to write <CODE>use Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to detect that kind of bug immediately.
   
   <P>
   You will see the following in the error_log file:
   
   <P>
   <PRE>  Undefined subroutine
  -  &amp;Apache::ROOT::perl::test_2epl::some_function called at
  -  /home/httpd/perl/test.pl line 10. 
  +  &amp;Apache::ROOT::perl::tool2_2epl::some_function called at
  +  /home/httpd/perl/tool2.pl line 4.
   </PRE>
  +<P><DT><STRONG>Scenario 2</STRONG><DD>
   <P>
  -The above is true for the files you require as well (assuming that the
  -required files do not declare a package). If you have:
  +The above is true for the files you <CODE>require()</CODE> as well (assuming that the required files do not declare a package). If you
  +have:
   
   <P>
  -<PRE>  cgi/tool1/config.pl
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/config.pl
  -  cgi/tool2/tool2.pl
  +<PRE>  ./cgi/tool1/config.pl
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/config.pl
  +  ./cgi/tool2/tool2.pl
   </PRE>
   <P>
   And both scripts do:
  @@ -236,46 +639,58 @@
     require &quot;config.pl&quot;;
   </PRE>
   <P>
  -Only the first one will do the require, all for the same reason that
  -<CODE>%INC</CODE> already includes the key ``config.pl''!
  +While the content of the scripts and <CODE>config.pl</CODE> files is exactly like in the example above. Only the first one will
  +actually do the
  +<CODE>require()</CODE>, all for the same reason that <CODE>%INC</CODE> already includes the key <STRONG>"config.pl"</STRONG>! The second scenario is not different from the first one, since there is
  +no difference between <CODE>use()</CODE> and
  +<CODE>require()</CODE> if you don't have to import some symbols into a calling script.
   
  +<P><DT><STRONG>Scenario 3</STRONG><DD>
   <P>
  -There are 3 workarounds for that: (make sure you read the whole item 3)
  +What's interesting that the following scenario wouldn't work too!
   
  -<OL>
  -<P><LI>
  +<P>
  +<PRE>  ./cgi/tool/config.pl
  +  ./cgi/tool/tool1.pl
  +  ./cgi/tool/tool2.pl
  +</PRE>
   <P>
  -Place your library modules in a subdirectory structure so that they have
  -different path prefixes. The file system layout will be something like
  +where <CODE>tool1.pl</CODE> and <CODE>tool2.pl</CODE> both <CODE>require()</CODE> the <STRONG>same</STRONG>
   
  +<CODE>config.pl</CODE>.
  +
  +</DL>
   <P>
  -<PRE>  cgi/tool1/Tool1/Foo.pm 
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/Tool2/Foo.pm 
  -  cgi/tool2/tool2.pl
  -</PRE>
  +There are 3 solutions for that: (make sure you read the whole item 3)
  +
  +<DL>
  +<P><DT><STRONG><A NAME="item_Solution">Solution 1</A></STRONG><DD>
   <P>
  -And change the scripts:
  +The first two faulty scenarios can be solved by placing your library
  +modules in a subdirectory structure so that they have different path
  +prefixes. The file system layout will be something like:
   
   <P>
  -<PRE>  use Tool1::Foo;
  -  use Tool2::Foo;
  +<PRE>  ./cgi/tool1/Tool1/Foo.pm
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/Tool2/Foo.pm
  +  ./cgi/tool2/tool2.pl
   </PRE>
   <P>
  -and respectively, the package declaration in the modules: 
  +And change the scripts:
   
   <P>
  -<PRE>  package Tool1::Foo;
  -  package Tool2::Foo;
  +<PRE>  use Tool1::Foo;
  +  use Tool2::Foo;
   </PRE>
   <P>
  -For require:
  +For <CODE>require()</CODE> (scenario number 2) use the following:
   
   <P>
  -<PRE>  cgi/tool1/tool1-lib/config.pl
  -  cgi/tool1/tool1.pl
  -  cgi/tool2/tool2-lib/config.pl
  -  cgi/tool2/tool2.pl
  +<PRE>  ./cgi/tool1/tool1-lib/config.pl
  +  ./cgi/tool1/tool1.pl
  +  ./cgi/tool2/tool2-lib/config.pl
  +  ./cgi/tool2/tool2.pl
   </PRE>
   <P>
   And each script does respectively:
  @@ -288,87 +703,96 @@
   <PRE>  use lib qw(.);
     require &quot;tool2-lib/config.pl&quot;;
    
  +But this solution is very bad, since while it might work for you now,
  +if you add another script that wants to use the same module or
  +C&lt;config.pl&gt; file, it still wouldn't work as we saw in the third
  +scenario. So let see better solutions.
   </PRE>
  -<P><LI>
  +<P><DT><STRONG>Solution 2</STRONG><DD>
   <P>
   Another option is to use a full path to the script, so it'll be compiled
  -into the name of the key in the %INC;
  +into the name of the key in the <CODE>%INC</CODE>;
   
   <P>
   <PRE>  require &quot;/full/path/to/the/config.pl&quot;;
   </PRE>
   <P>
  -But then you lose portability! (I mean if you move the tool around in the
  -file system you will have to change the base dir)
  +This solution solves the first two scenarios. I was surprised but it worked
  +for the third scenario as well!
   
  -<P><LI>
   <P>
  -Declare a package in the required files! (Of course it should be unique to
  -the rest of the package names you use!) The <CODE>%INC</CODE> will use the
  -package name for the key!
  +But with this solution you loose portability! (If you move the tool around
  +in the file system you will have to change the base dir)
   
  +<P><DT><STRONG>Solution 3</STRONG><DD>
   <P>
  -But then you will have to use <STRONG>Package::function()</STRONG> method unless you will export the symbols from the <CODE>use()'d</CODE>
  -package like:
  +Declare a package in the required files! (Of course it should be unique to
  +the rest of the package names you use!) The <CODE>%INC</CODE> will use the package name for the key! It's a good idea to build at least 2
  +level package names for your private modules. (e.g. <CODE>MyProject::Carp</CODE>
  +and not <CODE>Carp</CODE> for it will collide with existent standard package - even if as of the time
  +of your coding it doesn't exist yet - it might enter the next perl
  +distribution as a standard module and your code will become broken. Foresee
  +problems like this and save you a future trouble.)
   
  -<P>
  -<PRE>  use Package qw(:all_subs);
  -</PRE>
   <P>
  -This is a bad approach since it'll consume more memory for the current
  -process.
  +When you <CODE>use()d</CODE> or <CODE>require()d</CODE> files without package declarations, it was very convenient since all the
  +variables and subroutines were part of the <CODE>main::</CODE> package, so any of them could be used as if they were part of the main
  +script. With package declarations things get more complicated. To be
  +correct -- not complicated, but awkward, since you will have to use
  +<CODE>Package::function()</CODE> method to call a subroutine from a package
  +<CODE>Package</CODE> and to access a global variable inside the same package you will have to
  +write <CODE>$Package::some_variable</CODE>, you get a kind of typing overhead. You will be unable to access lexically
  +defined variables inside <CODE>Package</CODE> (declared with <CODE>my()</CODE>).
   
   <P>
  -<STRONG>Important:</STRONG> This solution will only work if you have two scripts that
  -<CODE>require()</CODE> the same file! 
  +You can make things simpler by exporting the symbols from the
  +<CODE>use()'d</CODE> package, like:
   
   <P>
  -<PRE>  cgi/tool1/config.pl
  -  cgi/tool1/tool_1.pl
  -  cgi/tool1/tool_2.pl
  +<PRE>  use Package qw(:mysubs sub_b $var1 :myvars);
   </PRE>
   <P>
  -and both tool_1.pl and tool_2.pl do:   
  +You can export both -- subroutines and global variables. This is a bad
  +approach since it'll consume more memory for the current process. (See
  +<CODE>perldoc Exporter</CODE> for information about exporting variables)
   
  -<P>
  -<PRE>  use lib qw(.);
  -  require &quot;config.pl&quot;;
  -</PRE>
   <P>
  -Here playing with dir name or using the full path will not help! You must
  -declare a package inside the files that are being <CODE>require()d!</CODE>
  +This solution completely covers the third scenario. By using different
  +module names in package declarations, as explained above you solve the
  +first two as well.
   
  -</OL>
  +</DL>
   <P>
   Read also perlmodlib and perlmod manpages.
   
   <P>
  -From the above discussion it should be clear that you can't run a
  +From the above discussion it should be clear that you cannot run a
   development and a production versions of the tools on the same server! You
  -have to run a separate server for each.
  +have to run a separate server for each (it still can be the same machine,
  +but the server will use a different port).
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H3></CENTER>
  +<CENTER><H2><A NAME="_END_or_DATA_tokens">__END__ or __DATA__ tokens</A></H2></CENTER>
   <P>
  -Apache::Registry scripts cannot contain __END__ or __DATA__ tokens 
  +<CODE>Apache::Registry</CODE> scripts cannot contain __END__ or __DATA__ tokens.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Output_from_system_calls">Output from system calls</A></H3></CENTER>
  +<CENTER><H2><A NAME="Output_from_system_calls">Output from system calls</A></H2></CENTER>
   <P>
  -Output of <STRONG>system</STRONG>, <STRONG>exec</STRONG>, and <STRONG>open PIPE "|program"</STRONG> calls will not be sent to the browser unless your Perl was configured with
  -sfio.
  +Output of <CODE>system()</CODE>, <CODE>exec()</CODE>, and <CODE>open(PIPE,&quot;|program&quot;)</CODE> calls will not be sent to the browser unless your Perl was configured with
  +<CODE>sfio</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Using_format_">Using format()</A></H3></CENTER>
  +<CENTER><H2><A NAME="Using_format_">Using format()</A></H2></CENTER>
   <P>
  -Currently possible only if you have perl compiled with sfio
  +Currently possible only if you have perl compiled with <CODE>sfio</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Using_exit_">Using exit()</A></H3></CENTER>
  +<CENTER><H2><A NAME="Using_exit_">Using exit()</A></H2></CENTER>
   <P>
   Perl's <STRONG>exit()</STRONG> built-in function cannot be used in mod_perl scripts. Calling it causes the
   server child to exit (which makes the whole idea of using mod_perl
  @@ -397,27 +821,23 @@
     }
   </PRE>
   <P>
  -Now each time the select code is called, the correct <STRONG>exit</STRONG>
  -will be chosen, whether you run the script as a CGI or from the shell.
  +Now each time the select code is called, the correct <CODE>exit()</CODE> will be chosen, whether you run the script as a CGI or from the shell.
   
   <P>
   <STRONG>Note</STRONG> that if you run the script under <CODE>Apache::Registry</CODE>, <STRONG>The
  -Apache function `exit' overrides the Perl core built-in
  -function</STRONG>. While you see the <CODE>exit()</CODE> listed in <CODE>@EXPORT_OK</CODE>
  -of Apache package, Apache::Registry makes something you don't see and
  -imports this function for you. This means that if your script is running
  -under Apache::Registry handler (Apache::PerlRun as well), you don't have to
  -worry about <CODE>exit().</CODE>
  -
  -<P>
  -<STRONG>Note</STRONG> that if you still use CORE::exit() in your scripts running under modperl,
  -the child will exit, but neither proper exit nor logging will happen on the
  -way. CORE::exit() cuts off the server's legs... If you need to properly
  -shutdown the child , use $r-&gt;child_terminate (which sets the internal MaxRequestsPerChild so the child
  -will exit).
  +Apache function <CODE>exit()</CODE> overrides the Perl core built-in
  +function</STRONG>. While you see the <CODE>exit()</CODE> listed in <CODE>@EXPORT_OK</CODE> of Apache package, <CODE>Apache::Registry</CODE> makes something you don't see and imports this function for you. This means
  +that if your script is running under <CODE>Apache::Registry</CODE> handler (<CODE>Apache::PerlRun</CODE> as well), you don't have to worry about <CODE>exit().</CODE>
  +
  +<P>
  +<STRONG>Note</STRONG> that if you still use <CODE>CORE::exit()</CODE> in your scripts running under modperl, the child will exit, but neither
  +proper exit nor logging will happen on the way. <CODE>CORE::exit()</CODE> cuts off the server's legs... If you need to properly shutdown the child ,
  +use
  +<CODE>$r-&amp;gt;child_terminate</CODE> (which sets the internal
  +<CODE>MaxRequestsPerChild</CODE> so the child will exit).
   
   <P>
  -You can accomplish this in 2 ways - in the Apache::Registry script:
  +You can accomplish this in two ways - in the <CODE>Apache::Registry</CODE> script:
   
   <P>
   <PRE>  Apache-&gt;request-&gt;child_terminate;
  @@ -430,15 +850,14 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Running_from_shell">Running from shell</A></H3></CENTER>
  +<CENTER><H2><A NAME="Running_from_shell">Running from shell</A></H2></CENTER>
   <P>
  -Your scripts <CODE>*will</CODE> not* run from the command line (yet) unless
  -you use CGI::Switch or CGI.pm and 5.004+ and do not make any direct calls
  -to Apache-&gt;methods. 
  +Your scripts <STRONG>will not</STRONG> run from the command line (yet) unless you use CGI::Switch or CGI.pm and
  +5.004+ and do not make any direct calls to Apache-&gt;methods.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="I_O_is_different">I/O is different</A></H3></CENTER>
  +<CENTER><H2><A NAME="I_O_is_different">I/O is different</A></H2></CENTER>
   <P>
   If you are using Perl 5.004 or better, most CGI scripts can run under
   mod_perl untouched. If you're using 5.003, Perl's built-in
  @@ -447,7 +866,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A></H3></CENTER>
  +<CENTER><H2><A NAME="HTTP_MIME_Headers_PerlSendHea">HTTP + MIME Headers (PerlSendHeader)</A></H2></CENTER>
   <P>
   By default, mod_perl does not send any headers by itself, however, you may
   wish to change this (in httpd.conf):
  @@ -457,18 +876,18 @@
   </PRE>
   <P>
   Now the response line and common headers will be sent as they are by
  -mod_cgi. And, just as with mod_cgi, PerlSendHeader will not send a
  -terminating newline, your script must send that itself, e.g.:
  +mod_cgi. And, just as with mod_cgi, <CODE>PerlSendHeader</CODE> will not send a terminating newline, your script must send that itself,
  +e.g.:
   
   <P>
   <PRE>  print &quot;Content-type: text/html\r\n\r\n&quot;;
   </PRE>
   <P>
  -If you are using CGI.pm or CGI::Switch and <STRONG>print $q-&gt;header</STRONG> you do _not_ need PerlSendHeader On.
  +If you are using CGI.pm or CGI::Switch and <STRONG>print $q-&gt;header</STRONG> you do _not_ need <CODE>PerlSendHeader</CODE> On.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H3></CENTER>
  +<CENTER><H2><A NAME="NPH_Non_Parsed_Headers_scripts">NPH (Non Parsed Headers) scripts</A></H2></CENTER>
   <P>
   To run a Non Parsed Header CGI script under mod_perl, simply add to your
   code:
  @@ -477,7 +896,8 @@
   <PRE>  local $| = 1;
   </PRE>
   <P>
  -And if you normally set PerlSendHeader On, add this to your httpd.conf:
  +And if you normally set <CODE>PerlSendHeader On</CODE>, add this to your
  +<CODE>httpd.conf</CODE>:
   
   <P>
   <PRE>  &lt;Files */nph-*&gt;
  @@ -486,63 +906,61 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="BEGIN_blocks">BEGIN blocks</A></H3></CENTER>
  +<CENTER><H2><A NAME="BEGIN_blocks">BEGIN blocks</A></H2></CENTER>
   <P>
  -Perl executes BEGIN blocks during the compile time of code as soon as
  -possible. The same is true under mod_perl. However, since mod_perl normally
  -only compiles scripts and modules once -- either in the parent server or
  -once per-child -- BEGIN blocks in that code will only be run once. As
  -perlmod explains, once a BEGIN has run, it is immediately undefined. In the
  -mod_perl environment, this means BEGIN blocks will not be run during each
  -incoming request unless that request happens to be one that is compiling
  -the code.
  +Perl executes <CODE>BEGIN</CODE> blocks during the compile time of code as soon as possible. The same is
  +true under mod_perl. However, since mod_perl normally only compiles scripts
  +and modules once -- either in the parent server or once per-child -- <CODE>BEGIN</CODE> blocks in that code will only be run once. As <CODE>perlmod manpage</CODE> explains, once a <CODE>BEGIN</CODE> has run, it is immediately undefined. In the mod_perl environment, this
  +means <CODE>BEGIN</CODE> blocks will not be run during each incoming request unless that request
  +happens to be one that is compiling the code.
   
   <P>
  -Modules and files pulled in via require/use which contain BEGIN blocks will
  -be executed:
  +<CODE>BEGIN</CODE> blocks in modules and files pulled in via <CODE>require()</CODE> and/or
  +<CODE>use()</CODE> will be executed:
   
   <UL>
   <P><LI>
   <P>
  -only once, if pulled in by the parent process.
  +Only once, if pulled in by the parent process.
   
   <P><LI>
   <P>
  -once per-child process if not pulled in by the parent process.
  +Once per-child process if not pulled in by the parent process.
   
   <P><LI>
   <P>
  -an additional time, once per-child process if the module is pulled in off
  -of disk again via Apache::StatINC.
  +An additional time, once per-child process if the module is pulled in off a
  +disk again via <CODE>Apache::StatINC</CODE>.
   
   <P><LI>
   <P>
  -an additional time, in the parent process on each restart if
  -PerlFreshRestart is On.
  +An additional time, in the parent process on each restart if
  +<CODE>PerlFreshRestart</CODE> is <CODE>On</CODE>.
   
   <P><LI>
   <P>
  -unpredictable if you fiddle with <CODE>%INC</CODE> yourself.
  +Unpredictable if you fiddle with <CODE>%INC</CODE> yourself.
   
   </UL>
   <P>
  -Apache::Registry scripts which contain BEGIN blocks will be executed:
  +<CODE>BEGIN</CODE> blocks in <CODE>Apache::Registry</CODE> scripts will be executed:
   
   <UL>
   <P><LI>
   <P>
  -only once, if pulled in by the parent process via Apache::RegistryLoader -
  -once per-child process if not pulled in by the parent process.
  +Only once, if pulled in by the parent process via
  +<CODE>Apache::RegistryLoader</CODE> - once per-child process if not pulled in by the parent process.
   
   <P><LI>
   <P>
  -an additional time, once per-child process if the script file has changed
  +An additional time, once per-child process if the script file has changed
   on disk.
   
   <P><LI>
   <P>
  -an additional time, in the parent process on each restart if pulled in by
  -the parent process via Apache::RegistryLoader and PerlFreshRestart is On.
  +An additional time, in the parent process on each restart if pulled in by
  +the parent process via <CODE>Apache::RegistryLoader</CODE> and
  +<CODE>PerlFreshRestart</CODE> is <CODE>On</CODE>.
   
   </UL>
   <P>
  @@ -550,44 +968,41 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="END_blocks">END blocks</A></H3></CENTER>
  +<CENTER><H2><A NAME="END_blocks">END blocks</A></H2></CENTER>
   <P>
  -As perlmod explains, an END subroutine is executed as late as possible,
  -that is, when the interpreter is being exited. In the mod_perl environment,
  -the interpreter does not exit until the server is shutdown. However,
  -mod_perl does make a special case for Apache::Registry scripts.
  +As perlmod explains, an <CODE>END</CODE> subroutine is executed as late as possible, that is, when the interpreter
  +exits. In the mod_perl environment, the interpreter does not exit until the
  +server is shutdown. However, mod_perl does make a special case for
  +<CODE>Apache::Registry</CODE> scripts.
   
   <P>
  -Normally, END blocks are executed by Perl during its <STRONG>perl_run()</STRONG>
  +Normally, <CODE>END</CODE> blocks are executed by Perl during its <STRONG>perl_run()</STRONG>
   function, which is called once each time the Perl program is executed, e.g.
   once per (mod_cgi) CGI scripts. However, mod_perl only calls
  -<STRONG>perl_run()</STRONG> once, during server startup. Any END blocks encountered during main server
  -startup, i.e. those pulled in by the PerlRequire or by any PerlModule, are
  -suspended and run at server shutdown, aka child_exit (requires apache
  -1.3b3+). 
  +<STRONG>perl_run()</STRONG> once, during server startup. Any <CODE>END</CODE> blocks encountered during main server startup, i.e. those pulled in by the
  +<CODE>PerlRequire</CODE> or by any <CODE>PerlModule</CODE>, are suspended and run at server shutdown, aka child_exit (requires apache
  +1.3b3+).
   
   <P>
  -Any END blocks that are encountered during compilation of Apache::Registry
  -scripts <STRONG>are called after the script has completed</STRONG>
  -(not during the cleanup phase though) including subsequent invocations when
  -the script is cached in memory. All other END blocks encountered during
  -other Perl*Handler callbacks, e.g. PerlChildInitHandler, will be suspended
  -while the process is running and called during child_exit when the process
  -is shutting down. Module authors may be wish to use $r-&gt;register_cleanup as an alternative to END blocks if this behavior is not
  -desirable.
  +Any <CODE>END</CODE> blocks that are encountered during compilation of
  +<CODE>Apache::Registry</CODE> scripts <STRONG>are called after the script has
  +completed</STRONG> (not during the cleanup phase though) including subsequent invocations when
  +the script is cached in memory. All other <CODE>END</CODE>
  +blocks encountered during other <CODE>Perl*Handler</CODE> call-backs, e.g.
  +<CODE>PerlChildInitHandler</CODE>, will be suspended while the process is running and called during <CODE>child_exit()</CODE> when the process is shutting down. Module authors might wish to use $r-&gt;register_cleanup as an alternative to <CODE>END</CODE> blocks if this behavior is not desirable.
   
   <P>
   The last paragraph is very important for the <A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Switches_w_T">Switches -w, -T</A></H3></CENTER>
  +<CENTER><H2><A NAME="Switches_w_T">Switches -w, -T</A></H2></CENTER>
   <P>
   Normally when you run perl from the command line or have the shell invoke
   it with `#!', you may choose to pass perl switch arguments such as <STRONG>-w</STRONG> or <STRONG>-T</STRONG>. Most command line arguments have a equivalent special variable. For
  -example, the <STRONG>$^W</STRONG> variable corresponds to the <STRONG>-w</STRONG>
  -switch. Consult perlvar for more details. With mod_perl it is also possible
  -to turn on warnings globally via the PerlWarn directive:
  +example, the <STRONG>$^W</STRONG> variable corresponds to the
  +<STRONG>-w</STRONG> switch. Consult <CODE>perlvar</CODE> manpage for more details. With mod_perl it is also possible to turn on
  +warnings globally via the PerlWarn directive:
   
   <P>
   <PRE>  PerlWarn On
  @@ -612,7 +1027,7 @@
   <A HREF="././modules.html#Apache_PerlRun_Run_unaltered_">Apache::PerlRun</A> .
   
   <P>
  -If you have the shebang line (#!/bin/perl -Tw) in your script, <STRONG>-w</STRONG>
  +If you have the shebang line (<CODE>#!/bin/perl -Tw</CODE>) in your script, <STRONG>-w</STRONG>
   will be honored (which means that you have turned the warn mode on for the
   scope of this script, <STRONG>-T</STRONG> will produce a warning if
   <CODE>PerlTaintCheck</CODE> is not <CODE>On</CODE>.
  @@ -638,38 +1053,50 @@
     }
   </PRE>
   <P>
  -It's more important to have <STRONG>use strict;</STRONG> enabled under mod_perl than anywhere else. While it's not required, it is
  -strongly recommended, it will save you more time in the long run. And, of
  -course, clean scripts will still run under mod_cgi (plain CGI)!
  +It's more important to have <CODE>strict</CODE> pragma enabled under mod_perl than anywhere else. While it's not required,
  +it is strongly recommended, it will save you more time in the long run.
  +And, of course, clean scripts will still run under mod_cgi (plain CGI)!
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Turning_warnings_ON">Turning warnings ON</A></H2></CENTER>
   <P>
  -Have a <CODE>$^W=1</CODE> in the script or PerlWarn ON at the server configuration file. Turning the
  -warning on will save you a lot of troubles with debugging your code. Note
  -that first magic line <CODE>#!/perl -switches</CODE>
  -is ignored by mod_perl, so too are the switches you used to write there.
  +Have a <CODE>local $^W=1</CODE> in the script or <CODE>PerlWarn ON</CODE> at the server configuration file. Turning the warning on will save you a
  +lot of troubles with debugging your code. Note that all perl switches, but
  +<CODE>-w</CODE> in the first magic (shebang) line of the script <CODE>#!/perl
  +-switches</CODE> are being ignored by mod_perl. If you write <CODE>-T</CODE> you will be warned to set <CODE>PerlTaintCheck ON</CODE> in the config file.
   
   <P>
  -If you need you can always turn off the warning with <CODE>$^W = 0</CODE> in your code if you have some section you don't want the perl compiler to
  -warn in.
  +If you need -- you can always turn off the warnings with <CODE>local
  +$^W=0</CODE> in your code if you have some section you don't want the perl compiler to
  +warn in. The correct way to do this is:
   
   <P>
  +<PRE>  {
  +   local $^W=0;
  +    # some code
  +  }
  +</PRE>
  +<P>
  +It preserves the previous value of <CODE>$^W</CODE> when you quit the block (so if it was set before, it will return to be set
  +at the leaving of the block.
  +
  +<P>
   In production code, it can be a good idea to turn warnings off. Otherwise
   if your code isn't very clean and spits a few lines of warnings here and
  -there, you will end up with a huge error_log file in a short time on the
  -loaded server. Also, enabling runtime warning checking has a small
  -performance impact -- in any script, not just under mod_perl -- so your
  -approach should be to enable warnings during development, and then disable
  -them when your code is production-ready.
  +there, you will end up with a huge <CODE>error_log</CODE> file in a short time on the heavily loaded server. Also, enabling runtime
  +warning checking has a small performance impact -- in any script, not just
  +under mod_perl -- so your approach should be to enable warnings during
  +development, and then disable them when your code is production-ready.
  +Controlling the warnings mode through the
  +<CODE>httpd.conf</CODE> is much better, since you can control the behavior of all of the scripts
  +from a central place. I have <CODE>PerlWarn On</CODE> on my development server and <CODE>PerlWarn Off</CODE> on the production machine.
   
   <P>
  -<CODE>use diagnostics;</CODE> can shed more light on the errors and warnings you see, but again, it's
  -better to not use <CODE>use diagnostics;</CODE>
  -in production, since otherwise you incur the overhead of the diagnostics
  -pragma. (You can run your script with -dDprof to check the overhead. See
  -Devel::Dprof for more info)
  +<CODE>diagnostics</CODE> pragma can shed more light on the errors and warnings you see, but again,
  +it's better not to use it in production, since otherwise you incur a huge
  +overhead of the diagnostics pragma examining your every bit of code
  +mod_perl executes. (You can run your script with <CODE>-dDprof</CODE> to check the overhead. See <CODE>Devel::Dprof</CODE> for more info).
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -682,25 +1109,44 @@
   <PRE>  use diagnostics;
   </PRE>
   <P>
  -This pragma turns on the -w mode, but gives you much better diagnostics of
  -the errors and warnings encountered. Generally it explains the reason for
  -warnings/errors you get, shows you an example of code where the same kind
  -of warning is being triggered, and tells you the remedy.
  +This pragma turns on the <CODE>-w</CODE> mode, but gives you much better diagnostics of the errors and warnings
  +encountered. Generally it explains the reason for warnings/errors you get,
  +shows you an example of code where the same kind of warning is being
  +triggered, and tells you the remedy.
   
   <P>
  -Again, it's a bad idea to keep this in your production code, as it will
  -spit zillions of diagnostics lines into your error_log file. Also, it will
  -add significant overhead to the CGI's runtime. (I discovered this by using
  -Devel::DProf!)
  +Again, it's a bad idea to keep it in your production code, as it will spit
  +10 and more lines of diagnostics messages into your error_log file for
  +every warning perl will report for the first time (per invocation). Also,
  +it will add a significant overhead to the code's runtime. (I discovered
  +this by using <CODE>Devel::DProf</CODE>!)
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H2></CENTER>
  +<P>
  +To pass an environment variable from a configuration file, add to it:
  +
  +<P>
  +<PRE>  PerlSetEnv key val
  +  PerlPassEnv key
  +</PRE>
  +<P>
  +e.g.:
  +
  +<P>
  +<PRE>  PerlSetEnv PERLDB_OPTS &quot;NonStop=1 LineInfo=/tmp/db.out AutoTrace=1&quot;
  +</PRE>
  +<P>
  +will set <CODE>$ENV{PERLDB_OPTS}</CODE>, and it'll be accessible in every child.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Global_Variables">Global Variables</A></H2></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 <STRONG>@ISA</STRONG> or
  -<STRONG>$VERSION</STRONG> variables. In common practice, a combination of <STRONG>use strict</STRONG> and <STRONG>use vars</STRONG> keeps modules clean and reduces a bit of noise. However, <STRONG>use vars</STRONG> also creates aliases as the Exporter does, which eat up more space. When
  -possible, try to use fully qualified names instead of use vars. Example:
  +Some variables must be global so Perl can see them, such as a module's <CODE>@ISA</CODE> or <CODE>$VERSION</CODE> variables. 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 space. When possible, try to use fully qualified
  +names instead of use vars. Example:
   
   <P>
   <PRE>  package MyPackage;
  @@ -725,19 +1171,9 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Passing_ENV_variables_to_CGI">Passing ENV variables to CGI</A></H2></CENTER>
  -<P>
  -To pass an environment variable from a configuration file, add to it:
  -
  -<P>
  -<PRE>  PerlSetEnv key val
  -  PerlPassEnv key
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Code_has_been_changed_but_it_se">Code has been changed, but it seems the script is running the old code</A></H2></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="././obvious.html#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A> for more info.
  +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.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -745,7 +1181,7 @@
   <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. 
  +to them from outside of that scope.
   
   <P>
   Perl doesn't return the memory it acquired from the kernel. It does reuse
  @@ -767,65 +1203,73 @@
   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, making sure to provide a locking mechanism!)
  +overwrite the source file, make sure to provide a locking mechanism!)
   
   <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. Now you have a very nice sub
  -<CODE>process()</CODE> 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>
  -Once I wrote the script that passed a content of the little DB to the
  -function and it was OK, but then the DB become huge - I had to make a
  -decision, whether to buy more memory or to rewrite the code. So it's better
  -to plan ahead and pass the variables by reference. There are few approaches
  -for that:
  -
  -<P>
  -<PRE>  sub process{
  -    my $content_r = shift; 
  -    ... some processing on $$content here
  -        ($$var_r - dereference the scalar)
  -        [nothing returned - the variable $content
  -         outside is already changed]
  -  }
  +the whole file before any data processing. 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>
  +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>
  +<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} - dereference an array
  -  %{$var_hr} = dereference a hash
  +  @{$var_lr} -- dereferences an array
  +  %{$var_hr} -- dereferences a hash
   </PRE>
   <P>
  -For more see <CODE>perldoc perlref</CODE>
  -
  +For more info see <CODE>perldoc perlref</CODE>.
   
  -
   <P>
  -Another approach would be to directly use the <CODE>@_</CODE> variable.
  -Using directly the <CODE>@_</CODE> array serves the job of passing by
  -reference!
  +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>
  -<PRE>  sub process{
  -    $_[0] =~ s/A/a/gs;
  -    ... some processing on $_[0] here
  -    [nothing returned - the variable $content
  -     outside is already changed]
  +<PRE>  process($content);
  +  sub process{
  +    $_[0] =~ s/foo/bar/gs;
  +      # nothing returned - the variable $content outside has been
  +      # already modified
     }
  -  process($content);
   </PRE>
   <P>
  -From <CODE>perldoc perlsub</CODE>: The array <CODE>@_</CODE> 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)... 
  +From <CODE>perldoc perlsub</CODE>:
   
   <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>
   <STRONG>Third example</STRONG> demonstrates 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
  @@ -834,8 +1278,8 @@
   only the records you need!!!).
   
   <P>
  -We will use DBI for this (assume we are already connected to the DB) (read
  -perldoc DBI for complete info):
  +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>  $sth-&gt;execute;
  @@ -852,10 +1296,11 @@
   
   <P>
   A better approach is to not accumulate the records, but rather print them
  -as they are fetched from the DB. Moreover, we use the <STRONG>bind_col</STRONG>
  -and <STRONG>$sth-&gt;fetchrow_arrayref</STRONG> (aliased to <STRONG>$sth-&gt;fetch</STRONG>) methods, to fetch the data in the fastest possible way. The example below
  -prints the TABLE with matched data, the only memory that is being used is a
  -@cols.
  +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);
  @@ -877,39 +1322,41 @@
   <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 <STRONG>SELECT count(*) ...</STRONG> instead of <STRONG>'SELECT *
  -...</STRONG> to get the number of matched records.
  +where you use <CODE>SELECT count(*) ...</CODE> instead of <CODE>'SELECT *
  +...</CODE> to get the number of matched records.
   
   <P>
  -For those who think that <STRONG>$sth-&gt;rows</STRONG> will do the job, here is the quote from the DBI manpage: 
  +For those who think that <STRONG>$sth-&gt;rows</STRONG> will do the job, here is the quote from the <CODE>DBI</CODE> manpage:
   
  -<BLOCKQUOTE>
  -
   <P>
  -rows <CODE>$rv</CODE> = $sth-&gt;rows;
  -
  +<PRE>  rows();
  +</PRE>
   <P>
  -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>  $rv = $sth-&gt;rows;
  +</PRE>
   <P>
  -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.
  -
  -</BLOCKQUOTE>
  -
  +<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, callback closure sub, select fields and
  +query, accepting: conditions, call-back closure sub, select fields and
   restrictions. 
   
   <P>
  -<PRE>  # $o-&gt;dump(\%conditions,\&amp;callback_closure,\@select_fields,@restrictions)
  +<PRE>  # Usage:
  +  # $o-&gt;dump(\%conditions,\&amp;callback_closure,\@select_fields,@restrictions);
  +  #
     sub dump{
       my $self = shift;
       my %param = %{+shift}; # dereference hash
  @@ -925,7 +1372,7 @@
       my @where = ();
     
         # make a @where list 
  -    map { push @where, &quot;$_='$param{$_}'&quot; if $param{$_};} keys %param;
  +    map { push @where, &quot;$_=\'$param{$_}\'&quot; if $param{$_};} keys %param;
     
         # prepare the sql statement
       $do_sql = &quot;SELECT &quot;;
  @@ -1013,140 +1460,219 @@
   
   <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>
  +<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
   <P>
  -At the beginning there was:
  +When you develop plain CGI scripts, you can just change the code, and rerun
  +the CGI from your browser. Since the script isn't cached in memory, the
  +next time you call it the server starts up a new perl process, which
  +recompiles it from scratch. The effects of any modifications you've applied
  +are immediately present.
   
   <P>
  -<PRE>  open IN, &quot;in.txt&quot; or die &quot;Cannot open in.txt for reading : $!\n&quot;;
  -</PRE>
  +The situation is different with <CODE>Apache::Registry</CODE>, since the whole idea is to get maximum performance from the server. By
  +default, the server won't spend the time to check whether any included
  +library modules have been changed. It assumes that they weren't, thus
  +saving a few milliseconds to <CODE>stat()</CODE> the source file (multiplied by however many modules/libraries you are <CODE>use()</CODE>-ing and/or <CODE>require()</CODE>-ing in your script.) The only check that is being done is whether your
  +main script has been changed. So if you have only one script that doesn't
  +<CODE>use()</CODE> (or <CODE>require()</CODE>) other perl modules (or packages), there is nothing new about it. If
  +however, you are developing a script that includes other modules, the files
  +you <CODE>use()</CODE> or <CODE>require()</CODE> aren't being checked whether they have been modified.
  +
   <P>
  -But it was not perfect for mod_perl, since you have had to make sure you
  -do:
  +Acknowledging this, how do we get our modperl-enabled server to recognize
  +changes in any library modules? Well, there are a couple of techniques:
   
   <P>
  -<PRE>  close IN;
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
  +<P>
  +The simplest approach is to restart the server each time you apply some
  +change to your code. See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
  +
   <P>
  -somewhere before the end of the script, since if you do not, you will get a
  -file descriptor leakage and unlock problem. Even if you do have it, but for
  -some reason the interpreter did not make it to it, because of various
  -reasons, such as user aborted script (<A HREF="././obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>) the leakage is still there.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Using_Apache_StatINC">Using Apache::StatINC</A></H2></CENTER>
  +<P>
  +After restarting the server about 100 times, you will be tired and will
  +look for another solutions. Help comes from the
  +<CODE>Apache::StatINC</CODE> module.
   
   <P>
  -What do we do? We use <CODE>IO::File</CODE> (and other <CODE>IO::*</CODE>), which allows us to assign the file handler to variable, which can be <CODE>my()</CODE>
  -scoped. And when this variable goes out of scope the file or other file
  -system entity will be properly closed and unlocked (if was locked).
  +<CODE>Apache::StatINC</CODE> - Reload <CODE>%INC</CODE> files when updated on disk. When Perl pulls a file via require, it stores
  +the filename in the global hash <CODE>%INC</CODE>. The next time Perl tries to require the same file, it sees the file in <CODE>%INC</CODE> and does not reload from disk. This module's handler iterates over <CODE>%INC</CODE> and reloads the file if it has changed on disk.
   
   <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.
  +To enable this module just add two lines to <CODE>httpd.conf</CODE> file.
  +
  +<P>
  +<PRE>  PerlModule Apache::StatINC
  +  PerlInitHandler Apache::StatINC
   </PRE>
   <P>
  -But even faster and lighter technique is to use <CODE>Symbol.pm</CODE>:
  +To be sure it really works, turn on the debug mode on your development box
  +with <CODE>PerlSetVar StatINCDebug On</CODE>. You end up with something like:
   
   <P>
  -<PRE>  {
  -    my $fh = Symbol::gensym();
  -    open $fh, &quot;filename&quot; or die $!
  -  }
  +<PRE>  PerlModule Apache::StatINC
  +  &lt;Location /perl&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Registry::handler
  +    Options ExecCGI
  +    PerlSendHeader On
  +    PerlInitHandler Apache::StatINC
  +    PerlSetVar StatINCDebug On
  +  &lt;/Location&gt;
   </PRE>
   <P>
  +Beware that only the modules located in <CODE>@INC</CODE> are being reloaded on change, and you can change the <CODE>@INC</CODE> only before the server has been started. Whatever you do in your
  +scripts/modules which are being
  +<CODE>required()</CODE> after the server startup will not have any effect on
  +<CODE>@INC</CODE>. When you do <STRONG>use lib qw(foo/bar);</STRONG>, the <CODE>@INC</CODE> is being changed only for the time the code is being parsed and compiled.
  +When it's over the <CODE>@INC</CODE> is being reset to its original value. To make sure that you have set a
  +correct <CODE>@INC</CODE> fetch <A
  +HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
  +and watch the bottom of the page. (I assume you have configured the &lt;Location /perl-status&gt; section in <CODE>httpd.conf</CODE> as the mod_perl docs show.)
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</A></H1></CENTER>
  +<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
  +<P>
  +Checking all the Modules in <STRONG>%INC</STRONG> every time can add a large overhead to server response times, and you
  +certainly would not want
  +<CODE>Apache::StatINC</CODE> module to be enabled in your production site's configuration. But sometimes
  +you want to have some Configuration module to be reloaded without
  +restarting the whole server. To accomplish this, one of the solutions is to
  +use a code that I describe below.
  +
  +<P>
  +Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
  +
  +<P>
  +<PRE>  use lib &quot;/some/private/path&quot;;
  +  use Foo::Bar qw(:tags_group tag1 tag2);
  +</PRE>
  +<P>
  +Now to make a modification testing and reload at runtime you have to use
  +something like this:
  +
  +<P>
  +<PRE>  # child's private global variable to keep the timestamps
  +  use vars qw(%MODIFIED);
  +    
  +  my $module = &quot;Foo::Bar&quot;;
  +  
  +  (my $inc_key = $module) =~ s|::|/|g;
  +  $inc_key .= &quot;.pm&quot;;
  +  # the $module's path should be registered in %INC if it was already loaded
  +  my $path = $INC{$inc_key} or warn &quot;Can't find $inc_key in %INC\n&quot;;
  +  
  +  # Note: consider to not continue if $path wasn't set!
  +  
  +  # set modification time if it wasn't set before (first time)
  +  # Note: Use (stat $path)[9] instead of -M test, if you reset
  +  # time with $^M=time
  +  $MODIFIED{$module} ||= -M $path;
  +    
  +  # now check whether it was changed (assuming the above wasn't
  +  # performed in this session
  +  if ($MODIFIED{$module} != -M $path){
  +    # only if deleted from %INC the require will be called below
  +    delete $INC{$inc_key};
  +    
  +    require $path;
  +    
  +    # now reimport the symbols (if you need them back :)
  +    import $module qw(:tags_group tag1 tag2);
  +    
  +    # Update the MODIFICATION times
  +    $MODIFIED{$module} = -M $path;
  +  }
  +</PRE>
   <P>
  -When you start running your scripts under mod_perl, you might find yourself
  -in situation where a script seems to work, but sometimes it screws up. And
  -the more it runs without a restart, the more it screws up. Many times you
  -can resolve this problem very easily. You have to test your script under
  -with Server running as a 
  -<A HREF="././control.html#Running_server_in_a_single_mode">single process</A>.
  +You may want to add debug print statements to debug this code in your
  +application.
   
   <P>
  -Generally the problem you have is using global variables. Since global
  -variables don't change from one script invocation to another unless you
  -change them, you can find your scripts do ``fancy'' things.
  +Read the ``use versus require'' article for more info. ( <A
  +HREF="http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require">http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require</A>
  +)
   
   <P>
  -The first example is amazing -- Web Services. Imagine that you enter some
  -site you have your account on (Free Email Account?). Now you want to see
  -what other users read.
  +<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 wrote a script running under mod_cgi, you could get away with
  +sloppy programming, by opening a file and letting the interpreter to close
  +it for you when the script had finished his run, like:
   
   <P>
  -You type in your name and passwd, and you expect to enter to your account,
  -but instead you enter the account of someone else. This is cool isn't it?
  -Is it a bug or feature. (For some of us it's a feature, while for others
  -it's a bug.) You say, why in the world does this happen? The answer is
  -simple: Global Variables. You have entered the account of someone who
  -happened to be served by the same server child as you. Because of sloppy
  -programming, a global variable was not reset at the beginning of the
  -program and voila, you can easily peek into other people's emails! You
  -would think that it can't happen, since you have entered the login and
  -passwd. I tell you, it happens! See for yourself:
  +<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>  use vars ($authenticated);
  -  my $q = new CGI; 
  -  my $username = $q-&gt;param('username');
  -  my $passwd   = $q-&gt;param('passwd');
  -  authenticate($username,$passwd);
  -    # failed, break out
  -  die &quot;Wrong passwd&quot; unless $authenticated == 1;
  -    # user is OK, fetch user's data
  -  show_user($username);
  -  
  -  sub authenticate{
  -    my ($username,$passwd) = @_;
  -        # some checking
  -    $authenticated = 1 if (SOMETHING);
  -  }
  +<PRE>  close IN;
   </PRE>
   <P>
  -Do you see the catch? With the code above, I can type in any valid username
  -and any dummy passwd and enter that user's account, if someone has
  -successfully entered his account before me using the same child process!
  -Since <STRONG>$authenticated</STRONG> is global - if it becomes 1 once it'll be 1 for the remainder of the
  -child's life!!! The solution is trivial -- reset <STRONG>$authenticated</STRONG> to 0 at the beginning of the program. (Or many other different solutions).
  -Of course this example is trivial -- but believe me it happens!
  +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>
  -Just another little one liner that can spoil your day, assuming you forgot
  -to reset the <STRONG>$allowed</STRONG> variable. It works perfectly OK in plain mod_cgi:
  +<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>  $allowed = 1 if $username eq 'admin';
  +<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>
  -But you will let any user to admin your system with the line above (again
  -assuming you have used the same child prior to some user request).
  +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 good example is usage of the <STRONG>/o</STRONG> regular expression qualifier, which compiles a regular expression once, on
  -its first execution. This problem can be difficult to detect, as after
  -restarting the server each request you make will be served by a different
  -child process, and thus the regex pattern for that child will be compiled
  -fresh. Only when you make a request that happens to be served by a child
  -which has already cached the regexp will you see the problem. Generally you
  -miss that and when you press reload, you see that it works (with a new,
  -fresh child) and then it doesn't (with a child that already cached the
  -regexp and wouldn't recompile because of <STRONG>/o</STRONG>.)
  +But even faster and lighter technique is to use <CODE>Symbol.pm</CODE>:
   
   <P>
  -To make sure you don't miss these bugs always test your CGI in
  -<A HREF="././control.html#Running_server_in_a_single_mode">single process</A>. To solve this particular <STRONG>/o</STRONG> problem refer to <A HREF="././obvious.html#Compiled_Regular_Expressions">Compiled Regular Expressions</A>.
  +<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_It_does">The Script is too dirty, It does the job and I can't afford rewriting it.</A></H1></CENTER>
  +<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 Apache::Registry handler with
  -Apache::PerlRun and define a new location (the script can reside in the
  -same directory on the disk. 
  +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
  @@ -1168,41 +1694,38 @@
   
   
   <P>
  -Another ``bad'', but working method is to set MaxRequestsPerChild 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
  +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
   though, as the parent server will need to fork a new child each time one is
  -killed, but you can fiddle with MaxStartServers, MinSpareServers, to make
  -the parent spawn more servers ahead so the killed one will be immediately
  -replaced with the fresh one. Again, probably that's not what you want.
  +killed, but you can fiddle with <CODE>MaxStartServers</CODE>,
  +<CODE>MinSpareServers</CODE>, to make the parent spawn more servers ahead so the killed one will be
  +immediately replaced with the fresh one. Again, probably that's not what
  +you want.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A></H1></CENTER>
   <P>
  -Apache::PerlRun gives you a benefit of preloaded perl and its modules. This
  -module's handler emulates the CGI environment, allowing programmers to
  -write scripts that run under CGI or mod_perl without any change. Unlike
  -Apache::Registry, the Apache::PerlRun handler does not cache the script
  -inside of a subroutine. Scripts will be ``compiled'' on each request. After
  -the script has run, its name space is flushed of all variables and
  -subroutines. Still, you don't have the overhead of loading the perl and
  -compilation time of the standard modules (If your script is very light, but
  -uses lots of standard modules - you will see no difference between
  -Apache::PerlRun and Apache::Registry !).
  +<CODE>Apache::PerlRun</CODE> gives you a benefit of preloaded perl and its modules. This module's
  +handler emulates the CGI environment, allowing programmers to write scripts
  +that run under CGI or mod_perl without any change. Unlike <CODE>Apache::Registry</CODE>, the <CODE>Apache::PerlRun</CODE>
  +handler does not cache the script inside of a subroutine. Scripts will be
  +``compiled'' on each request. After the script has run, its name space is
  +flushed of all variables and subroutines. Still, you don't have the
  +overhead of loading the perl and compilation time of the standard modules
  +(If your script is very light, but uses lots of standard modules - you will
  +see no difference between
  +<CODE>Apache::PerlRun</CODE> and <CODE>Apache::Registry</CODE> !).
   
   <P>
   Be aware though, that if you use packages that use internal variables that
   have circular references, they will be not flushed!!!
  -
  -<P>
  -Apache::PerlRun only flushes your script's name space, which does not
  -include any other required packages' name spaces. If there's a reference to
  -a <STRONG>my()</STRONG> scoped variable that's keeping it from being DESTROYed after leaving the
  -eval scope (of Apache::PerlRun), that cleanup might not be taken care of
  -until the server is shutdown and <CODE>perl_destruct()</CODE> is run, which
  -always happens after running command line scripts. Consider this example:
  +<CODE>Apache::PerlRun</CODE> only flushes your script's name space, which does not include any other
  +required packages' name spaces. If there's a reference to a <CODE>my()</CODE> scoped variable that's keeping it from being destroyed after leaving the
  +eval scope (of <CODE>Apache::PerlRun</CODE>), that cleanup might not be taken care of until the server is shutdown and
  +<CODE>perl_destruct()</CODE> is run, which always happens after running command line scripts. Consider
  +this example:
   
   <P>
   <PRE>  package Foo;
  @@ -1236,8 +1759,8 @@
     Foo-&gt;DESTROY
   </PRE>
   <P>
  -In this case, under mod_perl you wouldn't see 'Foo-&gt;DESTROY' until the
  -server shutdown, or your module properly took care of things.
  +In this case, under mod_perl you wouldn't see <CODE>Foo-&amp;gt;DESTROY</CODE>
  +until the server shutdown, or your module properly took care of things.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1279,7 +1802,7 @@
                            or exists $ENV{'MOD_PERL'} ) ? 1 : 0;
     
       chomp $why;
  -    my $orig_why = $why;                # an ascii copy for email report
  +    my $orig_why = $why;                # an ASCII copy for email report
     
       # handle the shell execution case (so we will not get all the HTML)
       print(&quot;Error: $why\n&quot;), exit unless $UNDER_MOD_PERL;
  @@ -1388,10 +1911,11 @@
   name/line number.
   
   <P>
  -If you compile with the experimental <STRONG>PERL_MARK_WHERE=1</STRONG>, it shows you ``exactly'' where this is happening. Generally compiler
  -makes a shift in its line counter. You can always stuff your code with
  -special compiler directives, to reset its counter to the value you will
  -tell. At the beginning of the line you should write (the '#' in column 1):
  +If you compile with the experimental <STRONG>PERL_MARK_WHERE=1</STRONG>, it shows you almost the exact line number, where this is happening.
  +Generally a compiler makes a shift in its line counter. You can always
  +stuff your code with special compiler directives, to reset its counter to
  +the value you will tell. At the beginning of the line you should write (the
  +'#' in column 1):
   
   <P>
   <PRE>  #line 298 myscript.pl
  @@ -1443,20 +1967,21 @@
   <CENTER><H1><A NAME="Forking_subprocesses_from_mod_pe">Forking subprocesses from mod_perl</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_speling or whatever modules you have used in your
  -server, all the core routines and so on. A much wiser approche 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
  -function or methods to call from CGI script. Just making a
  +-- 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. 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 function or methods to call from CGI script. Just
  +making a
   <CODE>system()</CODE> call defeats the whole idea behind mod_perl, perl interpreter and modules
  -should be loaded again for this extenal program to run.
  +should be loaded again for this external program to run.
   
   <P>
   Basically, you would do:
  @@ -1528,6 +2053,23 @@
      print &quot;\n\n&quot;;
      print &quot;hello&quot;;
   </PRE>
  +<P>
  +&lt;META&gt; some leftovers... # =head1 Coding with mod_perl
  +
  +<P>
  +Before you start coding for <CODE>Apache::Registry</CODE>, you have to change your programming state of mind. Scripts running under
  +mod_perl are like subroutines are being called from a continually running
  +daemon. Imagine a daemon process that when requested to process some
  +script, reads it in, compiles it as a subroutine, and finally executes it.
  +On any subsequent request, it'll just recall the already compiled
  +subroutine. Hope that you get the idea.
  +
  +<P>
  +The best thing you do when coding from scratch is to make it clean and use
  +packages. By ``make it clean'' we mean make certain that you <STRONG>use
  +strict;</STRONG> and that your script produces no warnings when tested via
  +<STRONG>perl -cw myscript.pl</STRONG>. As you go thru the notes you will understand why. &lt;/META&gt;
  +
   <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>
  @@ -1538,7 +2080,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="frequent.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]
  +	     [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="performance.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -1551,7 +2093,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/12/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.16      +291 -321  modperl-site/guide/scenario.html
  
  Index: scenario.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/scenario.html,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- scenario.html	1999/06/19 21:15:13	1.15
  +++ scenario.html	1999/07/02 13:42:30	1.16
  @@ -1,7 +1,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Real World Scenarios Implementaion</TITLE>
  +   <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">
  @@ -20,13 +20,12 @@
   <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 Implementaion</H1>
  +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="#Before_you_dive_into_the_gory_de">Before you dive into the gory details</A>
   	<LI><A HREF="#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
   	<UL>
   
  @@ -42,7 +41,7 @@
   		<UL>
   
   			<LI><A HREF="#Building_the_httpd_docs_Server">Building the httpd_docs Server</A>
  -			<LI><A HREF="#Building_the_httpd_perl_Server_">Building the httpd_perl Server (mod_perl):</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>
  @@ -76,33 +75,12 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Before_you_dive_into_the_gory_de">Before you dive into the gory details</A></H1></CENTER>
  -<P>
  -There are many implementation schemes, each one has its benefits and
  -drawbacks. Please take your time to read the <A HREF="././strategy.html#">Picking the Right Strategy</A> chapter before you proceed. This section
  -<EM>merely</EM> details the implementation, installation and configuration. It hardly
  -mentions the pros and cons of each scheme detailed here.
  -
  -<P>
  -This section describes a real world scenarios ready for almost blindly copy
  -and paste, you may think of it as a kick start. You will probably will want
  -to change the directories and some parameters like your hostname, but
  -basically you can use it as it is.
  -
  -<P>
  -<STRONG>Important:</STRONG> Since both apache and mod_perl tend to release new versions so often (which
  -is good :), I will be not able to update the version numbers I present
  -here. So make sure to work with the latest version, even if you see me
  -using some older one. I prefer to use the real version number instead of <CODE>x.xx.xx</CODE>.
  -
  -<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>
   <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>
   <P>
  -The Installation is very very simple (example from Linux OS):
  +The Installation is very very simple (example of installation on Linux OS):
   
   <P>
   <PRE>  % cd /usr/src
  @@ -112,7 +90,7 @@
     % tar zvxf mod_perl-x.xx.tar.gz
     % cd mod_perl-x.xx
     % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    USE_APACI=1 DO_HTTPD=1 PERL_MARK_WHERE=1 ALL_HOOKS=1 
  +    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/src
     % make install
  @@ -122,27 +100,24 @@
   
   <P>
   Notes: Replace x.x.x with the real version numbers of mod_perl and apache.
  -gnu tar uncompresses as well (with z flag).
  +gnu <CODE>tar</CODE> uncompresses as well (with <CODE>z</CODE> flag).
   
   <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>
   <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 libwww) 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.
  +<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>  % 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>
  -Extract both sources. Generally I open all the sources in
  -<CODE>/usr/src/</CODE>, your mileage may vary. So move the sources and cd to the directory you
  -want to put the sources in. Gnu <CODE>tar</CODE> utility knows to uncompress too with z flag, if you have a non-gnu <CODE>tar</CODE> utility, it will be incapable to decompress, so you would do it in 2 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>. And untarring them with <CODE>tar xvf
  -apache_x.xx.tar</CODE> and <CODE>tar xvf mod_perl-x.xx.tar</CODE>.
  +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>  % cd /usr/src
  @@ -150,43 +125,42 @@
     % tar zvxf mod_perl-x.xx.tar.gz
   </PRE>
   <P>
  -Change to the mod_perl source directory.
  +<CODE>chdir</CODE> to the mod_perl source directory:
   
   <P>
   <PRE>  % cd mod_perl-x.xx
   </PRE>
   <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 &lt;src&gt; directory is. If you have followed my
  -advice and extracted the sources under the same directory (e.g.
  -&lt;/usr/src&gt;), the following is correct.
  +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>
   <PRE>  % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
  -    USE_APACI=1 DO_HTTPD=1 PERL_MARK_WHERE=1 ALL_HOOKS=1 
  +    DO_HTTPD=1 USE_APACI=1 PERL_MARK_WHERE=1 EVERYTHING=1
   </PRE>
   <P>
   There are many additional parameters. You can find some of them in the
  -configuration dedicated chapter and other sections where any of them
  -becomes relevant. 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.
  +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>
   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>make test</STRONG> it (by running various tests) and install the mod_perl modules.
  +<STRONG>test</STRONG> it (by running various tests) and <STRONG>install</STRONG> the mod_perl modules.
   
   <P>
   <PRE>  % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -Note that if <CODE>make</CODE> fails, non of the <CODE>make test</CODE> and <CODE>make
  -install</CODE> will be not executed. If <CODE>make test</CODE> fails, <CODE>make install</CODE>
  +Note that if <CODE>make</CODE> fails, neither <CODE>make test</CODE> nor <CODE>make
  +install</CODE> will be executed. If <CODE>make test</CODE> fails, <CODE>make install</CODE>
   will be not executed.
   
   <P>
  -Now change to apache source directory and run <CODE>make install</CODE> to install apache's headers, default configuration files, build apache
  -directory tree and put the <CODE>httpd</CODE> there.
  +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/src
  @@ -194,10 +168,10 @@
   </PRE>
   <P>
   When you execute the above command, apache installation process will tell
  -you how can you start the webserver (the path of the &lt;apachectl&gt;,
  -more about it later) and where the configuration files are. Remember (or
  -even better write down) both for you will need this information very soon.
  -On my machine they 2 important paths are:
  +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 they two important paths are:
   
   <P>
   <PRE>  /usr/local/apache/bin/apachectl
  @@ -211,16 +185,16 @@
   <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 (like setting a correct <CODE>Port</CODE>, <CODE>User</CODE>, <CODE>Group</CODE>, log-file 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
  +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>  % /usr/local/apache/bin/apachectl start
  +  % /usr/local/apache/bin/apachectl stop
   </PRE>
   <P>
  -Put the server down, open the <CODE>httpd.conf</CODE> in your favorite editor and scroll to the end of the file, where we will
  +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).
   
  @@ -231,8 +205,8 @@
   <PRE>  Alias /perl/ /home/httpd/perl/
   </PRE>
   <P>
  -Assuming that you put all your scripts that should be executed under
  -mod_perl into <CODE>/home/httpd/perl/</CODE> directory.
  +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>  PerlModule Apache::Registry
  @@ -258,17 +232,18 @@
   </PRE>
   <P>
   Make it executable and readable by server, if your server is running as
  -user <CODE>nobody</CODE> (hint see <CODE>User</CODE> directive in <CODE>httpd.conf</CODE> file), do the following:
  +user <CODE>nobody</CODE> (hint: look for <CODE>User</CODE> directive in <CODE>httpd.conf</CODE>
  +file), do the following:
   
   <P>
  -<PRE>  chown nobody /home/httpd/perl/test.pl
  -  chmod u+rx   /home/httpd/perl/test.pl
  +<PRE>  % chown nobody /home/httpd/perl/test.pl
  +  % chmod u+rx   /home/httpd/perl/test.pl
   </PRE>
   <P>
   Test that the script is running from the command line, by executing it:
   
   <P>
  -<PRE>  /home/httpd/perl/test.pl
  +<PRE>  % /home/httpd/perl/test.pl
   </PRE>
   <P>
   You should see:
  @@ -280,16 +255,20 @@
   </PRE>
   <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:
  +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>
  -(Assuming that you have a loop-back device configured, if not use the real
  -server name for this test (e.g. <CODE>http://www.nowhere.com/perl/test.pl</CODE>)
  +Make sure that you have a loop-back device configured, if not -- use the
  +real server name for this test, for example:
   
   <P>
  +<PRE>  <A HREF="http://www.nowhere.com/perl/test.pl">http://www.nowhere.com/perl/test.pl</A>
  +</PRE>
  +<P>
   You should see:
   
   <P>
  @@ -300,12 +279,17 @@
   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>
  -Now migrate your 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>). Not all of your scripts will work unchanges, but many will.
  +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>
   The above setup is very basic, it will help you to have a mod_perl enabled
  -server running.
  +server running and to get a good feeling from watching your previously slow
  +CGIs now flying.
   
   <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
  @@ -316,12 +300,12 @@
   <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 run two apache servers we will need two different configuration
  -files, log files and etc. 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. We
  -will refer to these two servers as <STRONG>httpd_docs</STRONG> (vanilla Apache) and <STRONG>httpd_perl</STRONG>
  -(Apache/mod_perl).
  +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>
   For this illustration, we will use <CODE>/usr/local</CODE> as our <EM>root</EM>
  @@ -333,7 +317,7 @@
   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 in this section.
  +independent source trees will prove helpful, unless you use <CODE>DSO</CODE>, which is covered later in this section.
   
   <P>
   Make two subdirectories:
  @@ -343,36 +327,39 @@
     % mkdir /usr/src/httpd_perl
   </PRE>
   <P>
  -Now we will put the Apache source into <CODE>/usr/src/httpd_docs</CODE>:
  +Put the Apache sources into a <CODE>/usr/src/httpd_docs</CODE> directory:
   
   <P>
   <PRE>  % cd /usr/src/httpd_docs
  -  % gzip -dc /path/to/tarfile/apache.tar.gz | tar xvf -
  +  % gzip -dc /tmp/apache_x.x.x.tar.gz | tar xvf -
   </PRE>
   <P>
   If you have a gnu tar:
   
   <P>
  -<PRE>  % tar xvzf /path/to/apache.tar.gz
  +<PRE>  % tar xvzf /tmp/apache_x.x.x.tar.gz
   </PRE>
   <P>
  -Replace everywhere <CODE>/path/to/tarfile</CODE> with a path to a downloaded file.
  +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>  % cd /usr/src/httpd_docs
  +  
     % ls -l
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_1.3.6/
  +  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 apache_x.x.x/
   </PRE>
   <P>
   Now we will prepare the <CODE>httpd_perl</CODE> server sources:
   
   <P>
   <PRE>  % cd /usr/src/httpd_perl
  -  % gzip -dc /path/to/apache.tar.gz | tar xvf -
  -  % gzip -dc /path/to/modperl.tar.gz | tar xvf -
  +  % 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_1.3.6/
  -  drwxr-xr-x  8 stas  stas 2048 Apr 29 17:38 modperl-1.19/
  +  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
  @@ -414,37 +401,34 @@
                               run/
   </PRE>
   <P>
  -After you will complete the compilation and installation of the both
  -servers, you will have to configure them. To make things clear before we
  +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 then the one
  +<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>
   The next step is to configure and compile the sources: Below are the
   procedures to compile both servers taking into account the directory layout
  -we have just decided to use.
  +I have just suggested to use.
   
   <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>
   <P>
  -Important note: In the installation scenario I have used apache and
  -mod_perl release numbers. As you understand I would not change these
  -numbers every time a new version of either apache or mod_perl will be
  -released. So please if you see <CODE>apache_1.3.6</CODE> it does not mean
  -<CODE>1.3.6</CODE> is the latest apache version.
  +Let's proceed with instalation. I will use x.x.x instead of real version
  +numbers so this document will never become obsolete :).
   
   <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>
  +<P><DT><STRONG><A NAME="item_Sources">Sources Configuration:</A></STRONG><DD>
   <P>
  -<PRE>  % cd /usr/src/httpd_docs/apache_1.3.6
  +<PRE>  % cd /usr/src/httpd_docs/apache_x.x.x
     % make clean
     % env CC=gcc \
     ./configure --prefix=/usr/local \
  @@ -463,12 +447,13 @@
   <PRE>    --enable-module=include --enable-module=rewrite
   </PRE>
   <P>
  -Note: gcc - compiles httpd by 100K+ smaller then cc on AIX, remove the
  -<CODE>env CC=gcc</CODE> if you want to use the default compiler.
  +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>
  -Note: add <CODE>--layout</CODE> to see the resulting directories' layout without actually making the
  -configuration.
  +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>
  @@ -495,7 +480,7 @@
   </DL>
   <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_Server_">Building the httpd_perl Server (mod_perl):</A></H3></CENTER>
  +<CENTER><H3><A NAME="Building_the_httpd_perl_mod_per">Building the httpd_perl (mod_perl enabled) Server</A></H3></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
  @@ -509,27 +494,26 @@
   Make sure the sources are clean:
   
   <P>
  -<PRE>  % cd /usr/src/httpd_perl/apache_1.3.6
  +<PRE>  % cd /usr/src/httpd_perl/apache_x.x.x
     % make clean
  -  % cd /usr/src/httpd_perl/mod_perl-1.19
  +  % cd /usr/src/httpd_perl/mod_perl-x.xx
     % make clean
   </PRE>
   <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
  -1.3.4 header files.
  +latest header files.
   
   <P>
  -Here I did not find a way to compile with gcc (my perl was compiled with cc
  -so we have to compile with the same compiler!!!
  +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>
  -<PRE>  % cd /usr/src/httpd_perl/mod_perl-1.19
  +<PRE>  % cd /usr/src/httpd_perl/mod_perl-x.xx
   </PRE>
   <P>
   <PRE>  % /usr/local/bin/perl Makefile.PL \
     APACHE_PREFIX=/usr/local/ \
  -  APACHE_SRC=../apache_1.3.6/src \
  +  APACHE_SRC=../apache_x.x.x/src \
     DO_HTTPD=1 \
     USE_APACI=1 \
     PERL_MARK_WHERE=1 \
  @@ -543,9 +527,8 @@
            --proxycachedir=/usr/local/var/httpd_perl/proxy
   </PRE>
   <P>
  -Notice that <STRONG>ALL</STRONG>  <CODE>APACI_ARGS</CODE> (below) must be passed as one long line if you work with <CODE>t?csh</CODE>!!! It works correctly the way it shown above with <CODE>(ba)?sh</CODE>. If you work with <CODE>t?csh</CODE> it does not work for
  -<CODE>csh</CODE> passes to <CODE>./configure</CODE>  <CODE>APACI_ARGS</CODE> params with new lines without '' - tcsh strips the original '' - and the
  -build goes broken.
  +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
  @@ -566,16 +549,17 @@
   <PRE>  % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -Note: Apache puts a stripped version of <CODE>httpd</CODE> at
  -<CODE>/usr/local/sbin/httpd_perl/httpd</CODE>. The original version including debugging symbols (if you need to run a
  -debugger on this executable) is located at <CODE>/usr/src/httpd_perl/apache_1.3.6/src/httpd</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 noted that we did not go to the apache's source dir and
  -run <CODE>make install</CODE>. When <CODE>USE_APACI</CODE> is enabled,
  -<CODE>APACHE_PREFIX</CODE> will specify the --prefix option for Apache's configure script, 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
  +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>
  @@ -613,7 +597,7 @@
   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 pathes according to the directory layout
  +configure the log files and other paths according to the directory layout
   we decided to use.
   
   <P>
  @@ -627,21 +611,20 @@
   <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 log and other files directives are set
  -to point to the right places, according to the chosen directory layout.
  +<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.
   
   <P>
  -One 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
  +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 &lt;8080&gt;. 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, for many organizations use firewalls, which may block some of the
  +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 users, by either using the mod_proxy's
  -<CODE>ProxyPass</CODE> or proxy server like squid.
  +from firewalls and users, by either using the mod_proxy's <CODE>ProxyPass</CODE> or proxy server like squid.
   
   <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>,
  @@ -650,7 +633,7 @@
   
   <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 of them.
  +them all at the end of the <CODE>httpd.conf</CODE>, since you are going to fiddle a lot with them at the beginning.
   
   <P>
   First, you need to specify the location where all mod_perl scripts will be
  @@ -684,14 +667,13 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  -This configuration causes all scripts that are called with a <STRONG>/perl</STRONG>
  -path prefix to be executed under the <STRONG>Apache::Registry</STRONG> 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 will possibly will trigger a 'Save-As' window). <STRONG>Apache::Registry</STRONG> 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
  -<STRONG>Apache::Registry</STRONG> module before we use it in the <CODE>PerlHandler</CODE> in the <CODE>Location</CODE> configuration.
  +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.
   
   <P>
  -<STRONG>PerlSendHeader On</STRONG> tells the server to send an HTTP header to the browser on every script
  +<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.
   
  @@ -699,7 +681,7 @@
   This is only a very basic configuration. <A HREF="././config.html#">Server Configuration</A> section covers the rest of the details.
   
   <P>
  -Start the server with:
  +Now start the server with:
   
   <P>
   <PRE>  /usr/local/sbin/httpd_perl/apachectl start
  @@ -709,9 +691,9 @@
   <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 have got the rpm package, installed
  +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 the server.
  +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>
   First, lets understand what do we have in hands and what do we want from
  @@ -721,34 +703,33 @@
   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 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
  +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>
   You should understand that squid can be used as a straight forward proxy
  -server, generally used in companies and ISPs to save up the traffic by
  -caching the most popular requests. 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 proxy mode, you can extend its
  +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
  -just configure the <CODE>httpd
  -accelerator mode</CODE>'s related directives as you were configuring it from scratch.
  +extend the existent squid configuration with <CODE>httpd accelerator mode</CODE>'s related directives or you just create one from scratch.
   
   <P>
  -As stated before, proxy server listens now to the port 80, we have to move
  -the httpd_docs server to port 81 for example (your mileage may vary :). So
  -you have to modify the httpd.conf in the httpd_docs config 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.
  +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>
  -Let's go thru the changes we should apply to the default configuration
  -file. Since this file (<CODE>/etc/squid/squid.conf</CODE>)is huge (60k+) and we would not use 99% of it, my suggestion is to write a
  -new including only the modified directives.
  +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>
   We want to enable the redirect feature, to be able to serve requests, by
  @@ -781,7 +762,7 @@
   <PRE>  icp_port 0
   </PRE>
   <P>
  -<CODE>hierarchy_stoplist</CODE> defined a list of words which, if found in a URL, cause the object to be
  +<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.
  @@ -797,34 +778,31 @@
     no_cache deny QUERY
   </PRE>
   <P>
  -Please note that the last 2 directives are controversial. 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. If you set the headers correctly there is no need to
  -tell squid accelerator to NOT try to cache something. The headers I am
  -talking about are <CODE>Last-Modified</CODE> and <CODE>Expires</CODE>. What are they good for?
  +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. 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>
  -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, which means that mod_perl servers have as twice as less work
  -than before. This is only possible by setting the headers correctly.
  -
  -<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.
  +squid could serve the second request.
   
   <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 from your servers without investing money for more memory
  -and better hardware.
  +squeeze even more power from your servers without investing money for
  +additional memory and better hardware.
   
   <P>
   While testing you might want to enable the debugging options and watch the
  @@ -832,14 +810,14 @@
   == access control routes).
   
   <P>
  -<PRE>  # debug_options ALL,1 28,9
  +<PRE>  # debug_options ALL, 1, 28, 9
   </PRE>
   <P>
  -We need to provide a way for a 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, the path to the redirect daemon and disable rewriting any <CODE>Host:</CODE> header in redirected requests (as suggested by squid's documentation). The
  +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>
  @@ -876,30 +854,30 @@
     # http_access allow all
   </PRE>
   <P>
  -Since squid should be run as non root, you need these if you are starting
  -the squid as root.
  +Since squid should be run as non-root user, you need these if you are
  +invoking the squid as root.
   
   <P>
   <PRE>  cache_effective_user squid
     cache_effective_group squid
   </PRE>
   <P>
  -Memory used for caching parameter. The squid documentation warns that the
  -actual size of the squid can become 3 times higher than this value.
  +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>  cache_mem 20 MB
   </PRE>
   <P>
   Keep pools of allocated (but unused) memory available for future use. Read
  -more about it in the squid docs.
  +more about it in the squid documents.
   
   <P>
   <PRE>  memory_pools on
   </PRE>
   <P>
  -Cache manager cgi script (cachemgr.cgi - comes bundled with squid) - you
  -will want to tight the permissions for a production server.
  +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>  cachemgr_passwd disable shutdown
  @@ -916,54 +894,58 @@
     $|=1;
     
     while (&lt;&gt;) {
  -  # redirect to mod_perl server
  -    print($_), next if 
  -   s|<A HREF="http://127">http://127</A>\.0\.0\.1:81/perl|<A HREF="http://www.nowhere.com:8080/perl">http://www.nowhere.com:8080/perl</A>|o;
  -  
  -  # default - static server
  +      # redirect to mod_perl server (httpd_perl)
  +    print($_), next if s|(:81)?/perl/|:8080/perl/|o;
  +</PRE>
  +<P>
  +<PRE>      # send it unchanged to plain apache server (http_docs)
       print;
     }
   </PRE>
   <P>
  -Note: you see the 127.0.0.1 (which is a 'localhost'), because in my
  -scenario the proxy and the apache servers are running on the same machine.
  -So the requests that went through squid being converted to point to the
  -localhost in our configuration.
  +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>
  +A few notes regarding redirector script:
  +
  +<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.
  +
  +<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.
   
   <P>
  -A few notes regarding this redirector script:
  -
  -<P>
  -You must disable buffering. <CODE>$|=1;</CODE> does the job. If you do not disable buffering, the stdout will be flushed
  -only when the buffer will be full and it's about 4 or 8k if I remember
  -correctly. So your users will just wait till it will be filled up.
  -
  -<P>
  -For those who thinks that it is a very ineffective way to redirect, the
  -redirector runs as a daemon, you fire up N redirect daemons, so there is no
  -problem with perl interpreter loading, exactly like modperl - it is already
  -loaded and the code compiled, so redirect is very fast (not slower if
  -redirector was written in C or alike). I think that squid keeps a pipe
  -opened to all redirect daemons so there is no overhead of system calls as
  -well.
  -
  -<P>
   Now it is time to restart the server, at linux I do it with:
   
   <P>
   <PRE>  /etc/rc.d/init.d/squid restart
   </PRE>
   <P>
  -Now you are done...
  +Now the setup is complete ...
   
   <P>
  -Almost... When you will try the new setup, you will be surprised and upset
  -to discover the 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 since
  -it will bypass the squid server and the hard work we went through was just
  -a waste of time? The solution is to run both the squid and the httpd_docs
  -on 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:
  +Almost... When you try the new setup, you will be surprised and upset to
  +discover the 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 than it will bypass the squid server and the hard work we went
  +through was just a waste of time? The solution is to run both squid and
  +httpd_docs on 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>  Port 80
  @@ -971,10 +953,8 @@
     Listen 127.0.0.1:80
   </PRE>
   <P>
  -Modify the <CODE>squid.conf</CODE>
  -
  +Modify the <CODE>squid.conf</CODE>:
   
  -
   <P>
   <PRE>  http_port 80
     tcp_incoming_address 123.123.123.3
  @@ -983,35 +963,32 @@
     httpd_accel_port 80
   </PRE>
   <P>
  -Where <CODE>123.123.123.3</CODE> should be replaced with IP of your main server. Now restart the squid and
  +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.
   
   <P>
  -I think that you must also have in the /etc/hosts an entry:
  +You must also have in the <CODE>/etc/hosts</CODE> an entry (most chances that it's already there):
   
   <P>
   <PRE>  127.0.0.1  localhost.localdomain   localhost
   </PRE>
   <P>
  -But generally it is always there in first place.
  +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. 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>
  -Now if you scripts were generating full self references using the port 8080
  -or other you should remove it and generate links to point to port 80 (which
  -means not using the port at all). If you do not, users will bypass the
  -squid, like if it was not setup at all. The only question left is what to
  -do with users who bookmarked your services and they still have the port
  -8080 inside. Do not worry about it. The most important thing is for your
  -scripts to return a full URLs, so if user comes from the link with 8080
  -port inside, let it be. Just make sure that all the consecutive calls to
  -you server will be pointed correctly. During some period your users will
  -change their bookmarks, nothing you can do about by 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. See
  -<A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>.
  -
  -<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,
  @@ -1025,7 +1002,7 @@
   <CODE>X-Forwarded-For</CODE>.
   
   <P>
  -To save you keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
  +To save you some keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
   
   <P>
   <PRE>  http_port 80
  @@ -1073,44 +1050,45 @@
     cachemgr_passwd disable shutdown
   </PRE>
   <P>
  -Note that parameters' names should start at the beginning of the line.
  +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><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 the squid, I thought: ``Hey I can drop now the <CODE>httpd_docs</CODE> server and to have only squid and <CODE>httpd_perl</CODE>
  +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 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 documents. 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 fetches per second at a peak period
  -and thus the number of servers you need for static pages. This number you
  -have to multiply with the difference of memory requirements to get the
  -memory overhead. I can imagine, this amount could be significant in some
  -installations.
  +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>
  -So I have decided to have even more administration overhead and to stick to
  -the squid, httpd_docs and httpd_perl scenario, where I can optimize and
  +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 last 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.
  +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>
  -So if you are still with me. Install the apache with mod_perl and the
  -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>. We also do not need to bind two servers on the same port anymore because
  -we do not redirect anymore (There is no more need for <CODE>Bind</CODE> and <CODE>Listen</CODE> directives in the httpd.conf).
  +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>
   The modified configuration (see the explanations in the previous section):
  @@ -1125,7 +1103,7 @@
     acl QUERY urlpath_regex /cgi-bin /perl
     no_cache deny QUERY
     
  -  # debug_options ALL,1 28,9
  +  # debug_options ALL, 1, 28, 9
     
     # redirect_program /usr/lib/squid/redirect.pl
     # redirect_children 10
  @@ -1160,19 +1138,20 @@
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Using_mod_proxy">Using mod_proxy</A></H1></CENTER>
  +<P>
  +Now we will talk about apache's mod_proxy and understand how it works.
  +
   <P>
  -The server on port 80 answers html requests directly and proxies the
  -modperl enabled directory like this:
  +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>
  -<CODE>PPR</CODE> is the saving grace here, that makes Apache a win over Squid. That cleans
  -up redirects and stuff to remove the :81 from the URIs. Very nice. If you
  -want to use mod_proxy to proxy pass more than one port, you probably want
  -to take a look at mod_rewrite.
  +<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>
   You can control the buffering feature with <CODE>ProxyReceiveBufferSize</CODE>
  @@ -1182,39 +1161,36 @@
   <PRE>  ProxyReceiveBufferSize 1048576
   </PRE>
   <P>
  -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 basicaly to get an immediate release of the
  -mod_perl server, <CODE>ProxyReceiveBufferSize</CODE> should be set to a value greater than the biggest generated respond
  +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>
  -The <CODE>ProxyReceiveBufferSize</CODE> directive specifies an explicit network buffer size for <STRONG>outgoing</STRONG> HTTP and FTP connections, for increased throughput. It has to be greater
  -than 512 or set to 0 to indicate that the system's default buffer size
  -should be used.
  +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>
  -As the name states its buffering applies only to <STRONG>downstream data</STRONG>
  -(coming from the origin server to the proxy) and not upstream (i.e.
  +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)
  +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
  +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.c</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. His patch is at: <A
  -HREF="http://modules.apache.org/search?id=124">http://modules.apache.org/search?id=124</A>
  -or at <A
  -HREF="ftp://ftp.netcetera.dk/pub/apache/">ftp://ftp.netcetera.dk/pub/apache/</A>
  -. 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>:
  +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 ($) {
  @@ -1239,14 +1215,12 @@
   </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.
  +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>
  -That's why the above ``recommanded code'' includes a check for where the
  -request really is coming from before we change remote_ip.
  -
  -<P>
   From that point on, the remote IP address is correct. You should be able to
   access <CODE>REMOTE_ADDR</CODE> as usual.
   
  @@ -1259,8 +1233,8 @@
   <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>
   <P>
  -To build the mod_perl as DSO add <CODE>USE_DSO=1</CODE> to the rest of configuration parameters (so it will build libperl.so and
  -not libperl.a), like:
  +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>  perl Makefile.PL USE_DSO=1 ...
  @@ -1272,7 +1246,7 @@
   
   
   <P>
  -Then just add the <CODE>LoadModule</CODE> into your <CODE>httpd.conf</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.
  @@ -1280,27 +1254,23 @@
   <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 correctly for you.
  -
  -<P>
  -&lt;META&gt; Incomplete &lt;/META&gt;
  +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="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 provides
  -proxies the ``back-end'' (mod_perl) server, if you need to perform the
  -athentication in the ``back-end'' server, it should handle all
  -authentication. 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 pass through information.
  +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 config file is that your Auth stuff needs to be
  -in &lt;Directory ...&gt; ... &lt;/Directory&gt; tags because if you use a
  -&lt;Location /&gt; ... &lt;/Location&gt; the proxypass server takes the
  -auth info for its authentication and would not pass it on.
  +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>
   	     The <a href="http://www.modperl.com/">
  @@ -1325,7 +1295,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 07/02/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.4       +3 -3      modperl-site/guide/security.html
  
  Index: security.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/security.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- security.html	1999/06/19 21:15:13	1.3
  +++ security.html	1999/07/02 13:42:31	1.4
  @@ -22,7 +22,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="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="warnings.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>
   
  @@ -227,7 +227,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]
  +	     [    <A HREF="warnings.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>
  @@ -240,7 +240,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/17/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.15      +3 -3      modperl-site/guide/start.html
  
  Index: start.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/start.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- start.html	1999/06/19 21:15:13	1.14
  +++ start.html	1999/07/02 13:42:31	1.15
  @@ -22,7 +22,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>
   Guide's Overview</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -176,7 +176,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="strategy.html">Next</A>      ]
  +	     [    <A HREF="intro.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="porting.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -189,7 +189,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/14/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.15      +1 -1      modperl-site/guide/status.html
  
  Index: status.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/status.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- status.html	1999/06/19 21:15:14	1.14
  +++ status.html	1999/07/02 13:42:31	1.15
  @@ -163,7 +163,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 04/19/1999
  +	     <BR>Last Modified at 06/26/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.5       +86 -85    modperl-site/guide/strategy.html
  
  Index: strategy.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/strategy.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- strategy.html	1999/06/19 21:15:14	1.4
  +++ strategy.html	1999/07/02 13:42:31	1.5
  @@ -22,7 +22,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>
   Choosing the Right Strategy</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.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>
   
  @@ -32,8 +32,8 @@
   	<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="#squid_server">squid server</A>
  -	<LI><A HREF="#apache_s_mod_proxy">apache's mod_proxy</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 -->
   
  @@ -61,8 +61,8 @@
   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, and
  -some hints on approaches that should be used and things to avoid.
  +the relative degree of difficulty in installing and maintaining them, some
  +hints on approaches that should be used and things to avoid.
   
   <P>
   To be clear, I will not address all technologies and tools, but limit this
  @@ -70,7 +70,7 @@
   
   <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 out what this 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>
  @@ -121,9 +121,10 @@
   <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 sync. 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.
  +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><LI>
   <P>
  @@ -131,13 +132,13 @@
   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 milegue may vary. See <A HREF="././scenario.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>.
  +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>.
   
   <P><LI>
   <P>
   The fourth option (proxy in http accelerator mode), once correctly
  -configured and tuned, improves performance by caching and buffering page
  -results.
  +configured and tuned, improves the performance of any of the above three
  +options by caching and buffering page results.
   
   </OL>
   <P>
  @@ -155,7 +156,7 @@
   complex techniques.
   
   <P>
  -The Advantages:
  +The advantages:
   
   <UL>
   <P><LI>
  @@ -175,14 +176,15 @@
   
   </UL>
   <P>
  -The Disadvantages:
  +The disadvantages:
   
   <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
  +compared to the typical plain Apache. Of course if memory sharing is in
  +place -- RAM requirements will be smaller.
   
   <P>
   You probably have a few tens of children processes. The additional memory
  @@ -244,7 +246,7 @@
   As I have mentioned before, when running scripts under mod_perl, you will
   notice that the httpd processes consume a huge amount of memory, from 5M to
   25M, or even more. That is the price you pay for the enormous speed
  -improvements under mod_perl.
  +improvements under mod_perl. (Again -- shared memory keeps them smaller :)
   
   <P>
   Using these large processes to serve static objects like images and html
  @@ -258,37 +260,38 @@
   (vanilla apache) and <STRONG>httpd_perl</STRONG> (mod_perl enabled apache).
   
   <P>
  -The Advantages:
  +The advantages:
   
   <UL>
   <P><LI>
   <P>
   The heavy mod_perl processes serve only dynamic requests, which allows the
  -deployment of fewer of these large servers. When user browses static pages,
  -all relative URLs (e.g. <CODE>/main/download.html</CODE>) are being served by the light plain apache server. But this is not the
  -case with dynamically generated pages, all relative URLs in the dynamically
  -generated HTML will be served by the mod_perl process. 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). When you generate a HTML page which has relative
  -references to images or other static objects - the user's browser sets its
  -base url to point to that of the
  -<CODE>httpd_perl</CODE> server. Because of this, all static requests will be sent to the heavy <CODE>httpd_perl</CODE>. Beware! You can solve this by either generating full URLs to the <CODE>httpd_docs</CODE> server (the fastest) or by rewriting the requests back to <CODE>httpd_docs</CODE> inside the <CODE>httpd_perl</CODE>
  -<CODE>server(much</CODE> slower). This is not a problem if you hide the
  -internal implementations, so client sees only one server running on port
  -<CODE>80</CODE>. (<A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>)
  +deployment of fewer of these large servers.
   
   <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 better server performance.
  +memory usage and get a better server performance.
   
   <P>
   Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
   
   </UL>
   <P>
  -The Disadvantages:
  +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>
  +The disadvantages:
   
   <UL>
   <P><LI>
  @@ -298,17 +301,17 @@
   <UL>
   <P><LI>
   <P>
  -A need for two different configuration files, two log files sets, etc. We
  +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, storing the apache include files), most of them should be
  -separated and the configuration files updated to reflect the changes. (Of
  -course, this assumes that both are built from the same source
  -distribution.)
  +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>
  -A need for two sets of controlling scripts (startup/shutdown)
  +A need for two sets of controlling scripts (startup/shutdown) and
  +watchdogs.
   
   <P><LI>
   <P>
  @@ -349,8 +352,8 @@
   does not spawn child processes.
   
   <P>
  -Meta: Hey No personal experience. Please let me know if I have missed some
  -pros/cons here. Thanks!
  +Meta: Hey, No personal experience here, only rumours. Please let me know if
  +I have missed some pros/cons here. Thanks!
   
   <P>
   The Advantages:
  @@ -371,7 +374,8 @@
   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. Than the save-ups with <STRONG>thttpd</STRONG> are much smaller.
  +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>
  @@ -386,30 +390,27 @@
   <P><LI>
   <P>
   Lacks some of apache's features, like access control, error redirection,
  -customizable logfile formats, and so on.
  +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><H1><A NAME="Adding_a_Proxy_Server_in_http_Ac">Adding a Proxy Server in http Accelerator Mode</A></H1></CENTER>
   <P>
  -At the beginning there were 2 servers: one - plain apache server, which was
  -_very_ light, and configured to serve static objects, the other - mod_perl
  -enabled, which was _very_ heavy and aimed to serve mod_perl scripts. We
  -named them: <CODE>httpd_docs</CODE> and <CODE>httpd_perl</CODE>
  +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 httpd_docs (e.g. <A
  +by listening to different ports: 80 -- for httpd_docs (e.g. <A
   HREF="http://www.nowhere.com/images/test.gif">http://www.nowhere.com/images/test.gif</A>
  -) and 8080 for httpd_perl (e.g. <A
  +) and 8080 -- for httpd_perl (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. (Note that later on, I
  -will be moving the httpd_docs server to port 81.)
  +first example, since port 80 is a default http port. (Later on, I will be
  +moving the httpd_docs server to port 81.)
   
   <P>
  -Now I am going to convince you that you _want_ to use a proxy server (in
  -the http accelerator mode). The advantages are:
  +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>
  @@ -419,10 +420,11 @@
   
   <P><LI>
   <P>
  -You get less I/O activity reading 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 serve the static objects faster.
  +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>
  @@ -446,14 +448,14 @@
   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 was left
  -to the reader as an exercise :)
  +them of 100kb size and download time to be of... (This calculation is left
  +to you as an exercise :)
   
   <P>
   To make your 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 visit _heavy_ sites). So the speed of 3.6kb/sec we were
  -assuming before, may many times be 5-10 times slower.
  +(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><LI>
   <P>
  @@ -463,8 +465,8 @@
   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 pretty big topic, and it would not be
  -included in the scope of this document)
  +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>
  @@ -475,11 +477,6 @@
   allows for only your public ``bastion'' accelerating www server to get
   hosed in a successful attack, while leaving your internal data safe.
   
  -<P><LI>
  -<P>
  -You can have the <CODE>mod_proxy</CODE> process serve your static documents from disk to ``kill two birds with one
  -stone''.
  -
   </UL>
   <P>
   The disadvantages are:
  @@ -488,7 +485,7 @@
   <P><LI>
   <P>
   Of course there are drawbacks. Luckily, these are not functionality
  -drawbacks, but more of administration hassle. You add another program to
  +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
  @@ -507,7 +504,7 @@
   Have I succeeded in convincing you that you want the proxy server?
   
   <P>
  -If you are on a local area network, then the big benefit of the proxy
  +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.
   
  @@ -517,7 +514,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="squid_server">squid server</A></H1></CENTER>
  +<CENTER><H1><A NAME="The_Squid_Server">The Squid Server</A></H1></CENTER>
   <P>
   The Advantages:
   
  @@ -571,9 +568,9 @@
   
   <P><LI>
   <P>
  -HTTP headers / dates, freshness. Your server will be giving out ``old''
  -pages, which might confuse downstream/client caches. Also chances are that
  -you will be giving out stale pages.
  +HTTP headers / dates, freshness. The squid server might give out ``old''
  +pages, confusing downstream/client caches. Also chances are that you will
  +be giving out stale pages.
   
   <P><LI>
   <P>
  @@ -595,7 +592,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="apache_s_mod_proxy">apache's mod_proxy</A></H1></CENTER>
  +<CENTER><H1><A NAME="An_Apache_s_mod_proxy">An Apache's mod_proxy</A></H1></CENTER>
   <P>
   I do not think the difference in speed between apache's <CODE>ProxyPass</CODE>
   and squid is relevant for most sites, since the real value of what they do
  @@ -610,7 +607,7 @@
   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 'location' window.
  +not change in the client's <STRONG>Location</STRONG> window.
   
   <P>
   The Advantages:
  @@ -618,9 +615,10 @@
   <UL>
   <P><LI>
   <P>
  -No additional server is needed. We keep the 1 plain plus 1 mod_perl enabled
  -apache servers. All you need is to enable the <CODE>mod_proxy</CODE> in
  -<CODE>httpd_docs</CODE> and add a few lines to <CODE>httpd.conf</CODE> file.
  +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>
  @@ -639,8 +637,7 @@
   <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
  -ProxyPass.
  +constantly, you can dramatically increase performance by caching it with <CODE>ProxyPass</CODE>.
   
   <P><LI>
   <P>
  @@ -649,9 +646,9 @@
   
   <P><LI>
   <P>
  -Apache is able to accel https requests completely, while also doing http
  -accel. (with squid you have to use an external redirection program for
  -that).
  +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><LI>
   <P>
  @@ -664,6 +661,10 @@
   
   <UL>
   <P><LI>
  +<P>
  +Users reported that it might be a bit slow, but the latest version is fast
  +enough. (How fast is enough? :)
  +
   </UL>
   <P>
   For implementation see <A HREF="././scenario.html#Using_mod_proxy">Using mod_proxy</A>.
  @@ -678,7 +679,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="start.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]
  +	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="scenario.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -691,7 +692,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 06/19/1999
  +	     <BR>Last Modified at 07/02/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.16      +2 -2      modperl-site/guide/warnings.html
  
  Index: warnings.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/warnings.html,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- warnings.html	1999/06/19 21:15:14	1.15
  +++ warnings.html	1999/07/02 13:42:32	1.16
  @@ -22,7 +22,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>
   Runtime Warnings and Errors: Where and Why.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -418,7 +418,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="obvious.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]
  +	     [    <A HREF="obvious.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>